1 package org.apache.archiva.web.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
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
20 import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
21 import org.apache.archiva.configuration.ArchivaConfiguration;
22 import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
23 import org.apache.archiva.test.utils.ArchivaBlockJUnit4ClassRunner;
24 import org.apache.archiva.web.AbstractRestServicesTest;
25 import org.apache.archiva.web.api.FileUploadService;
26 import org.apache.archiva.web.model.FileMetadata;
27 import org.apache.commons.lang3.StringUtils;
28 import org.apache.commons.lang3.SystemUtils;
29 import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
30 import org.apache.cxf.jaxrs.client.WebClient;
31 import org.apache.cxf.jaxrs.ext.multipart.Attachment;
32 import org.apache.cxf.jaxrs.ext.multipart.AttachmentBuilder;
33 import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition;
34 import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
35 import org.apache.cxf.message.Message;
36 import org.junit.AfterClass;
37 import org.junit.BeforeClass;
38 import org.junit.Test;
39 import org.junit.runner.RunWith;
41 import javax.ws.rs.ClientErrorException;
42 import java.io.IOException;
43 import java.net.URLEncoder;
44 import java.nio.file.Files;
45 import java.nio.file.Path;
46 import java.nio.file.Paths;
47 import java.util.Collections;
48 import java.util.concurrent.atomic.AtomicReference;
51 * @author Olivier Lamy
53 @RunWith(ArchivaBlockJUnit4ClassRunner.class)
54 public class UploadArtifactsTest
55 extends AbstractRestServicesTest
58 private static String PREVIOUS_ARCHIVA_PATH;
59 private AtomicReference<Path> projectDir = new AtomicReference<>( );
62 public static void initConfigurationPath()
65 PREVIOUS_ARCHIVA_PATH = System.getProperty(ArchivaConfiguration.USER_CONFIG_PROPERTY);
66 if (System.getProperties().containsKey( "test.resources.path" ))
68 System.setProperty( ArchivaConfiguration.USER_CONFIG_PROPERTY,
69 System.getProperty( "test.resources.path" ) + "/archiva.xml" );
71 Path path = Paths.get( "src/test/resources/archiva.xml" ).toAbsolutePath();
72 System.setProperty( ArchivaConfiguration.USER_CONFIG_PROPERTY,
76 System.err.println( "USER_CONFIG_DIR " + System.getProperty( ArchivaConfiguration.USER_CONFIG_PROPERTY ) );
81 public static void restoreConfigurationPath()
84 System.setProperty( ArchivaConfiguration.USER_CONFIG_PROPERTY, PREVIOUS_ARCHIVA_PATH );
87 protected String getSpringConfigLocation() {
88 return "classpath*:META-INF/spring-context.xml,classpath:/spring-context-test-upload.xml";
91 protected Path getProjectDirectory() {
92 if ( projectDir.get()==null) {
93 String propVal = System.getProperty("mvn.project.base.dir");
95 if (StringUtils.isEmpty(propVal)) {
96 newVal = Paths.get("").toAbsolutePath();
98 newVal = Paths.get(propVal).toAbsolutePath();
100 projectDir.compareAndSet(null, newVal);
102 System.err.println( "project dir: " + projectDir.get( ).toString( ) );
103 return projectDir.get();
107 protected String getRestServicesPath() {
108 return "restServices";
111 protected String getBaseUrl() {
112 String baseUrlSysProps = System.getProperty("archiva.baseRestUrl");
113 return StringUtils.isBlank(baseUrlSysProps) ? "http://localhost:" + getServerPort() : baseUrlSysProps;
116 private FileUploadService getUploadService() {
117 FileUploadService service =
118 JAXRSClientFactory.create(getBaseUrl() + "/" + getRestServicesPath() + "/archivaUiServices/",
119 FileUploadService.class,
120 Collections.singletonList(new JacksonJaxbJsonProvider()));
121 log.debug("Service class {}", service.getClass().getName());
122 WebClient.client(service).header("Authorization", authorizationHeader);
123 WebClient.client(service).header("Referer", "http://localhost:" + getServerPort());
125 WebClient.client(service).header("Referer", "http://localhost");
126 WebClient.getConfig(service).getRequestContext().put(Message.MAINTAIN_SESSION, true);
127 WebClient.getConfig(service).getRequestContext().put(Message.EXCEPTION_MESSAGE_CAUSE_ENABLED, true);
128 WebClient.getConfig(service).getRequestContext().put(Message.FAULT_STACKTRACE_ENABLED, true);
129 WebClient.getConfig(service).getRequestContext().put(Message.PROPOGATE_EXCEPTION, true);
130 WebClient.getConfig(service).getRequestContext().put("org.apache.cxf.transport.no_io_exceptions", true);
132 // WebClient.client( service ).
137 public void clearUploadedFiles()
139 FileUploadService service = getUploadService();
140 service.clearUploadedFiles();
144 public void uploadFile() throws IOException, ArchivaRestServiceException {
145 FileUploadService service = getUploadService();
147 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");
148 final Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"" + file.getFileName().toString() + "\"; name=\"files[]\"")).build();
149 MultipartBody body = new MultipartBody(fileAttachment);
152 service.clearUploadedFiles();
157 public void failUploadFileWithBadFileName() throws IOException, ArchivaRestServiceException {
158 FileUploadService service = getUploadService();
160 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");
161 final Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"/../TestFile.testext\"; name=\"files[]\"")).build();
162 MultipartBody body = new MultipartBody(fileAttachment);
165 fail("FileNames with path contents should not be allowed.");
166 } catch (ClientErrorException e) {
167 assertEquals(422, e.getResponse().getStatus());
170 service.clearUploadedFiles();
175 public void uploadAndDeleteFile() throws IOException, ArchivaRestServiceException {
176 FileUploadService service = getUploadService();
178 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");
179 final Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"" + file.getFileName().toString() + "\"; name=\"files[]\"")).build();
180 MultipartBody body = new MultipartBody(fileAttachment);
182 service.deleteFile(file.getFileName().toString());
184 service.clearUploadedFiles();
189 public void failUploadAndDeleteWrongFile() throws IOException, ArchivaRestServiceException {
190 FileUploadService service = getUploadService();
192 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");
193 final Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"" + file.getFileName().toString() + "\"; name=\"files[]\"")).build();
194 MultipartBody body = new MultipartBody(fileAttachment);
196 assertFalse(service.deleteFile("file123" + file.getFileName().toString()));
198 service.clearUploadedFiles();
203 public void failUploadAndDeleteFileInOtherDir() throws IOException, ArchivaRestServiceException {
204 Path testFile = null;
206 FileUploadService service = getUploadService();
207 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");
208 Path targetDir = getProjectDirectory().resolve("target/testDelete").toAbsolutePath();
209 if (!Files.exists(targetDir)) Files.createDirectories(targetDir);
210 Path tempDir = SystemUtils.getJavaIoTmpDir().toPath();
211 testFile = Files.createTempFile(targetDir, "TestFile", ".txt");
212 log.debug("Test file {}", testFile.toAbsolutePath());
213 log.debug("Tmp dir {}", tempDir.toAbsolutePath());
214 assertTrue(Files.exists(testFile));
215 Path relativePath = tempDir.relativize(testFile.toAbsolutePath());
216 final Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"" + file.getFileName().toString() + "\"; name=\"files[]\"")).build();
217 MultipartBody body = new MultipartBody(fileAttachment);
219 String relativePathEncoded = URLEncoder.encode("../target/" + relativePath.toString(), "UTF-8");
220 log.debug("Trying to delete with path traversal: {}, {}", relativePath, relativePathEncoded);
222 service.deleteFile(relativePathEncoded);
223 } catch (ArchivaRestServiceException ex) {
224 // Expected exception
226 assertTrue("File in another directory may not be deleted", Files.exists(testFile));
228 if (testFile != null) {
229 Files.deleteIfExists(testFile);
235 public void failSaveFileWithBadParams() throws IOException, ArchivaRestServiceException {
236 Path path = getProjectDirectory().resolve("target/appserver-base/repositories/internal/org/apache/archiva/archiva-model/1.2/archiva-model-1.2.jar");
237 Files.deleteIfExists(path);
238 FileUploadService service = getUploadService();
239 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");
241 Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"archiva-model.jar\"; name=\"files[]\"")).build();
242 MultipartBody body = new MultipartBody(fileAttachment);
244 assertTrue(service.save("internal", "org.apache.archiva", "archiva-model", "1.2", "jar", true));
246 fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"TestFile.FileExt\"; name=\"files[]\"")).build();
247 body = new MultipartBody(fileAttachment);
248 FileMetadata meta = service.post(body);
249 log.debug("Metadata {}", meta.toString());
251 service.save("internal", "org", URLEncoder.encode("../../../test", "UTF-8"), URLEncoder.encode("testSave", "UTF-8"), "4", true);
252 fail("Error expected, if the content contains bad characters.");
253 } catch (ClientErrorException e) {
254 assertEquals(422, e.getResponse().getStatus());
256 assertFalse(Files.exists(getProjectDirectory().resolve("target/test-testSave.4")));
260 public void saveFile() throws IOException, ArchivaRestServiceException {
261 log.debug("Starting saveFile()");
263 Path path = getProjectDirectory().resolve("target/appserver-base/repositories/internal/org/apache/archiva/archiva-model/1.2/archiva-model-1.2.jar");
264 log.debug("Jar exists: {}",Files.exists(path));
265 Files.deleteIfExists(path);
266 path = getProjectDirectory().resolve("target/appserver-base/repositories/internal/org/apache/archiva/archiva-model/1.2/archiva-model-1.2.pom");
267 Files.deleteIfExists(path);
268 FileUploadService service = getUploadService();
269 service.clearUploadedFiles();
270 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");
271 log.debug("Upload file exists: {}", Files.exists(file));
272 final Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"archiva-model.jar\"; name=\"files[]\"")).build();
273 MultipartBody body = new MultipartBody(fileAttachment);
275 service.save("internal", "org.apache.archiva", "archiva-model", "1.2", "jar", true);
279 public void saveFileWithOtherExtension() throws IOException, ArchivaRestServiceException {
280 log.debug("Starting saveFileWithOtherExtension()");
282 Path path = getProjectDirectory().resolve("target/appserver-base/repositories/internal/org/apache/archiva/archiva-model/1.2/archiva-model-1.2.bin");
283 log.debug("Jar exists: {}",Files.exists(path));
284 Files.deleteIfExists(path);
285 Path pomPath = getProjectDirectory().resolve("target/appserver-base/repositories/internal/org/apache/archiva/archiva-model/1.2/archiva-model-1.2.pom");
286 Files.deleteIfExists(pomPath);
287 FileUploadService service = getUploadService();
288 service.clearUploadedFiles();
289 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");
290 log.debug("Upload file exists: {}", Files.exists(file));
291 final Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"archiva-model.bin\"; name=\"files[]\"")).build();
292 MultipartBody body = new MultipartBody(fileAttachment);
294 assertTrue(service.save("internal", "org.apache.archiva", "archiva-model", "1.2", "bin", false));
295 assertTrue(Files.exists(path));