1 package org.apache.archiva.upload;
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
21 import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
22 import org.apache.archiva.configuration.ArchivaConfiguration;
23 import org.apache.archiva.redback.rest.services.AbstractRestServicesTest;
24 import org.apache.archiva.redback.rest.services.FakeCreateAdminService;
25 import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
26 import org.apache.archiva.test.utils.ArchivaBlockJUnit4ClassRunner;
27 import org.apache.archiva.web.api.FileUploadService;
28 import org.apache.archiva.web.model.FileMetadata;
29 import org.apache.commons.lang3.StringUtils;
30 import org.apache.commons.lang3.SystemUtils;
31 import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
32 import org.apache.cxf.jaxrs.client.WebClient;
33 import org.apache.cxf.jaxrs.ext.multipart.Attachment;
34 import org.apache.cxf.jaxrs.ext.multipart.AttachmentBuilder;
35 import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition;
36 import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
37 import org.apache.cxf.message.Message;
38 import org.junit.AfterClass;
39 import org.junit.BeforeClass;
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
43 import javax.ws.rs.ClientErrorException;
44 import java.io.IOException;
45 import java.net.URLEncoder;
46 import java.nio.file.Files;
47 import java.nio.file.Path;
48 import java.nio.file.Paths;
49 import java.util.Collections;
50 import java.util.concurrent.atomic.AtomicReference;
53 * @author Olivier Lamy
55 @RunWith(ArchivaBlockJUnit4ClassRunner.class)
56 public class UploadArtifactsTest
57 extends AbstractRestServicesTest {
59 private static String PREVIOUS_ARCHIVA_PATH;
60 private AtomicReference<Path> projectDir = new AtomicReference<>( );
63 public static void initConfigurationPath()
66 PREVIOUS_ARCHIVA_PATH = System.getProperty(ArchivaConfiguration.USER_CONFIG_PROPERTY);
67 System.setProperty( ArchivaConfiguration.USER_CONFIG_PROPERTY,
68 System.getProperty( "test.resources.path" ) + "/archiva.xml" );
73 public static void restoreConfigurationPath()
76 System.setProperty( ArchivaConfiguration.USER_CONFIG_PROPERTY, PREVIOUS_ARCHIVA_PATH );
79 protected String getSpringConfigLocation() {
80 return "classpath*:META-INF/spring-context.xml,classpath:/spring-context-test-upload.xml";
83 protected Path getProjectDirectory() {
84 if ( projectDir.get()==null) {
85 String propVal = System.getProperty("mvn.project.base.dir");
87 if (StringUtils.isEmpty(propVal)) {
88 newVal = Paths.get("").toAbsolutePath();
90 newVal = Paths.get(propVal).toAbsolutePath();
92 projectDir.compareAndSet(null, newVal);
94 return projectDir.get();
98 protected String getRestServicesPath() {
99 return "restServices";
102 protected String getBaseUrl() {
103 String baseUrlSysProps = System.getProperty("archiva.baseRestUrl");
104 return StringUtils.isBlank(baseUrlSysProps) ? "http://localhost:" + getServerPort() : baseUrlSysProps;
107 private FileUploadService getUploadService() {
108 FileUploadService service =
109 JAXRSClientFactory.create(getBaseUrl() + "/" + getRestServicesPath() + "/archivaUiServices/",
110 FileUploadService.class,
111 Collections.singletonList(new JacksonJaxbJsonProvider()));
112 log.debug("Service class {}", service.getClass().getName());
113 WebClient.client(service).header("Authorization", authorizationHeader);
114 WebClient.client(service).header("Referer", "http://localhost:" + getServerPort());
116 WebClient.client(service).header("Referer", "http://localhost");
117 WebClient.getConfig(service).getRequestContext().put(Message.MAINTAIN_SESSION, true);
118 WebClient.getConfig(service).getRequestContext().put(Message.EXCEPTION_MESSAGE_CAUSE_ENABLED, true);
119 WebClient.getConfig(service).getRequestContext().put(Message.FAULT_STACKTRACE_ENABLED, true);
120 WebClient.getConfig(service).getRequestContext().put(Message.PROPOGATE_EXCEPTION, true);
121 WebClient.getConfig(service).getRequestContext().put("org.apache.cxf.transport.no_io_exceptions", true);
123 // WebClient.client( service ).
128 public void clearUploadedFiles()
130 FileUploadService service = getUploadService();
131 service.clearUploadedFiles();
135 public void uploadFile() throws IOException, ArchivaRestServiceException {
136 FileUploadService service = getUploadService();
138 Path file = getProjectDirectory().resolve("src/test/repositories/snapshot-repo/org/apache/archiva/archiva-model/1.4-M4-SNAPSHOT/archiva-model-1.4-M4-20130425.081822-1.jar");
139 final Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"" + file.getFileName().toString() + "\"; name=\"files[]\"")).build();
140 MultipartBody body = new MultipartBody(fileAttachment);
143 service.clearUploadedFiles();
148 public void failUploadFileWithBadFileName() throws IOException, ArchivaRestServiceException {
149 FileUploadService service = getUploadService();
151 Path file = getProjectDirectory().resolve("src/test/repositories/snapshot-repo/org/apache/archiva/archiva-model/1.4-M4-SNAPSHOT/archiva-model-1.4-M4-20130425.081822-1.jar");
152 final Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"/../TestFile.testext\"; name=\"files[]\"")).build();
153 MultipartBody body = new MultipartBody(fileAttachment);
156 fail("FileNames with path contents should not be allowed.");
157 } catch (ClientErrorException e) {
158 assertEquals(422, e.getResponse().getStatus());
161 service.clearUploadedFiles();
166 public void uploadAndDeleteFile() throws IOException, ArchivaRestServiceException {
167 FileUploadService service = getUploadService();
169 Path file = getProjectDirectory().resolve("src/test/repositories/snapshot-repo/org/apache/archiva/archiva-model/1.4-M4-SNAPSHOT/archiva-model-1.4-M4-20130425.081822-1.jar");
170 final Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"" + file.getFileName().toString() + "\"; name=\"files[]\"")).build();
171 MultipartBody body = new MultipartBody(fileAttachment);
173 service.deleteFile(file.getFileName().toString());
175 service.clearUploadedFiles();
180 public void failUploadAndDeleteWrongFile() throws IOException, ArchivaRestServiceException {
181 FileUploadService service = getUploadService();
183 Path file = getProjectDirectory().resolve("src/test/repositories/snapshot-repo/org/apache/archiva/archiva-model/1.4-M4-SNAPSHOT/archiva-model-1.4-M4-20130425.081822-1.jar");
184 final Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"" + file.getFileName().toString() + "\"; name=\"files[]\"")).build();
185 MultipartBody body = new MultipartBody(fileAttachment);
187 assertFalse(service.deleteFile("file123" + file.getFileName().toString()));
189 service.clearUploadedFiles();
194 public void failUploadAndDeleteFileInOtherDir() throws IOException, ArchivaRestServiceException {
195 Path testFile = null;
197 FileUploadService service = getUploadService();
198 Path file = getProjectDirectory().resolve("src/test/repositories/snapshot-repo/org/apache/archiva/archiva-model/1.4-M4-SNAPSHOT/archiva-model-1.4-M4-20130425.081822-1.jar");
199 Path targetDir = Paths.get("target/testDelete").toAbsolutePath();
200 if (!Files.exists(targetDir)) Files.createDirectories(targetDir);
201 Path tempDir = SystemUtils.getJavaIoTmpDir().toPath();
202 testFile = Files.createTempFile(targetDir, "TestFile", ".txt");
203 log.debug("Test file {}", testFile.toAbsolutePath());
204 log.debug("Tmp dir {}", tempDir.toAbsolutePath());
205 assertTrue(Files.exists(testFile));
206 Path relativePath = tempDir.relativize(testFile.toAbsolutePath());
207 final Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"" + file.getFileName().toString() + "\"; name=\"files[]\"")).build();
208 MultipartBody body = new MultipartBody(fileAttachment);
210 String relativePathEncoded = URLEncoder.encode("../target/" + relativePath.toString(), "UTF-8");
211 log.debug("Trying to delete with path traversal: {}, {}", relativePath, relativePathEncoded);
213 service.deleteFile(relativePathEncoded);
214 } catch (ArchivaRestServiceException ex) {
215 // Expected exception
217 assertTrue("File in another directory may not be deleted", Files.exists(testFile));
219 if (testFile != null) {
220 Files.deleteIfExists(testFile);
226 public void failSaveFileWithBadParams() throws IOException, ArchivaRestServiceException {
227 Path path = Paths.get("target/appserver-base/repositories/internal/org/apache/archiva/archiva-model/1.2/archiva-model-1.2.jar");
228 Files.deleteIfExists(path);
229 FileUploadService service = getUploadService();
230 Path file = getProjectDirectory().resolve("src/test/repositories/snapshot-repo/org/apache/archiva/archiva-model/1.4-M4-SNAPSHOT/archiva-model-1.4-M4-20130425.081822-1.jar");
232 Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"archiva-model.jar\"; name=\"files[]\"")).build();
233 MultipartBody body = new MultipartBody(fileAttachment);
235 assertTrue(service.save("internal", "org.apache.archiva", "archiva-model", "1.2", "jar", true));
237 fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"TestFile.FileExt\"; name=\"files[]\"")).build();
238 body = new MultipartBody(fileAttachment);
239 FileMetadata meta = service.post(body);
240 log.debug("Metadata {}", meta.toString());
242 service.save("internal", "org", URLEncoder.encode("../../../test", "UTF-8"), URLEncoder.encode("testSave", "UTF-8"), "4", true);
243 fail("Error expected, if the content contains bad characters.");
244 } catch (ClientErrorException e) {
245 assertEquals(422, e.getResponse().getStatus());
247 assertFalse(Files.exists(Paths.get("target/test-testSave.4")));
251 public void saveFile() throws IOException, ArchivaRestServiceException {
252 log.debug("Starting saveFile()");
254 Path path = Paths.get("target/appserver-base/repositories/internal/org/apache/archiva/archiva-model/1.2/archiva-model-1.2.jar");
255 log.debug("Jar exists: {}",Files.exists(path));
256 Files.deleteIfExists(path);
257 path = Paths.get("target/appserver-base/repositories/internal/org/apache/archiva/archiva-model/1.2/archiva-model-1.2.pom");
258 Files.deleteIfExists(path);
259 FileUploadService service = getUploadService();
260 service.clearUploadedFiles();
261 Path file = getProjectDirectory().resolve("src/test/repositories/snapshot-repo/org/apache/archiva/archiva-model/1.4-M4-SNAPSHOT/archiva-model-1.4-M4-20130425.081822-1.jar");
262 log.debug("Upload file exists: {}", Files.exists(file));
263 final Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"archiva-model.jar\"; name=\"files[]\"")).build();
264 MultipartBody body = new MultipartBody(fileAttachment);
266 service.save("internal", "org.apache.archiva", "archiva-model", "1.2", "jar", true);
270 public void saveFileWithOtherExtension() throws IOException, ArchivaRestServiceException {
271 log.debug("Starting saveFileWithOtherExtension()");
273 Path path = Paths.get("target/appserver-base/repositories/internal/org/apache/archiva/archiva-model/1.2/archiva-model-1.2.bin");
274 log.debug("Jar exists: {}",Files.exists(path));
275 Files.deleteIfExists(path);
276 Path pomPath = Paths.get("target/appserver-base/repositories/internal/org/apache/archiva/archiva-model/1.2/archiva-model-1.2.pom");
277 Files.deleteIfExists(pomPath);
278 FileUploadService service = getUploadService();
279 service.clearUploadedFiles();
280 Path file = getProjectDirectory().resolve("src/test/repositories/snapshot-repo/org/apache/archiva/archiva-model/1.4-M4-SNAPSHOT/archiva-model-1.4-M4-20130425.081822-1.jar");
281 log.debug("Upload file exists: {}", Files.exists(file));
282 final Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"archiva-model.bin\"; name=\"files[]\"")).build();
283 MultipartBody body = new MultipartBody(fileAttachment);
285 assertTrue(service.save("internal", "org.apache.archiva", "archiva-model", "1.2", "bin", false));
286 assertTrue(Files.exists(path));