From 66664d40de1adeaf39a94ef1360dde21bf7f55ce Mon Sep 17 00:00:00 2001 From: Alexandru-Eusebiu Epure Date: Wed, 8 Jul 2020 14:31:16 +0300 Subject: [PATCH] MNT-21602 : Revive DownloadContentServlet.java (#910) * MNT-21602 : Revive DownloadContentServlet.java Remove doHEAD method from DownloadContentServlet doGET method now redirects to V1 REST - GET /nodes/{nodeId} Removed leftover org.alfresco.web.app.servlet.UploadContentServlet, org.alfresco.web.app.servlet.DownloadRawContentServlet and org.alfresco.web.app.servlet.GuestDownloadContentServlet from web.xml as those servlet implementation does not exist. Refactor javadoc. Add TAS tests to Rest-API/DownloadContentServletTests class Restrict DownloadContentServlet to allow only nodes from the workspace://SpacesStore/ * Add downloadContentServlet mapping in web.xml --- .../servlet/DownloadContentServletTests.java | 324 ++++++++++++++++++ .../resources/test-suites/part1-suite.xml | 1 + .../app/servlet/DownloadContentServlet.java | 128 +++++++ war/src/main/webapp/WEB-INF/web.xml | 14 + 4 files changed, 467 insertions(+) create mode 100644 tests/tas-restapi/src/test/java/org/alfresco/rest/servlet/DownloadContentServletTests.java create mode 100644 war/src/main/java/org/alfresco/web/app/servlet/DownloadContentServlet.java diff --git a/tests/tas-restapi/src/test/java/org/alfresco/rest/servlet/DownloadContentServletTests.java b/tests/tas-restapi/src/test/java/org/alfresco/rest/servlet/DownloadContentServletTests.java new file mode 100644 index 0000000000..d562dc2d78 --- /dev/null +++ b/tests/tas-restapi/src/test/java/org/alfresco/rest/servlet/DownloadContentServletTests.java @@ -0,0 +1,324 @@ +package org.alfresco.rest.servlet; + +import io.restassured.RestAssured; +import org.alfresco.rest.RestTest; +import org.alfresco.rest.core.RestRequest; +import org.alfresco.rest.core.RestResponse; +import org.alfresco.utility.model.FileModel; +import org.alfresco.utility.model.FileType; +import org.alfresco.utility.model.FolderModel; +import org.alfresco.utility.model.SiteModel; +import org.alfresco.utility.model.TestGroup; +import org.alfresco.utility.model.UserModel; +import org.alfresco.utility.report.Bug; +import org.alfresco.utility.testrail.ExecutionType; +import org.alfresco.utility.testrail.annotation.TestRail; +import org.apache.commons.codec.binary.Base64; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +public class DownloadContentServletTests extends RestTest +{ + private static final String CONTENT_DISPOSITION = "Content-Disposition"; + private static final String FILENAME_HEADER = "filename=\"%s\""; + private static final String ATTACHMENT = "attachment"; + private static final String FILE_CONTENT = "The content of the file."; + + private static String downloadContentServletAttach = "alfresco/d/a/workspace/SpacesStore/"; + private static String downloadContentServletDirect = "alfresco/d/d/workspace/SpacesStore/"; + + private UserModel testUser; + private FileModel testContentFile; + private String authHeaderEncoded; + + @BeforeClass(alwaysRun = true) + public void dataPreparation() throws Exception + { + testUser = dataUser.createRandomTestUser(); + SiteModel testSite = dataSite.usingUser(testUser).createPublicRandomSite(); + FolderModel testFolder = dataContent.usingUser(testUser).usingSite(testSite).createFolder(); + testContentFile = dataContent.usingUser(testUser).usingResource(testFolder) + .createContent(new FileModel("hotOuside", FileType.TEXT_PLAIN, FILE_CONTENT)); + + String authHeader = String.format("%s:%s", testUser.getUsername(), testUser.getPassword()); + authHeaderEncoded = new String(Base64.encodeBase64(authHeader.getBytes())); + + RestAssured.basePath = ""; + restClient.configureRequestSpec().setBasePath(RestAssured.basePath); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using short descriptor and attach short descriptor.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSShortAttachShort() + { + authenticateTestUser(); + RestRequest request = RestRequest.simpleRequest( + HttpMethod.GET, downloadContentServletAttach + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + RestResponse response = restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.OK); + assertEquals(FILE_CONTENT, response.getResponse().body().asString()); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName())); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using short descriptor and attach long descriptor.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSShortAttachLong() + { + authenticateTestUser(); + String downloadContentServletAttachLong = "alfresco/d/attach/workspace/SpacesStore/"; + RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, + downloadContentServletAttachLong + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + RestResponse response = restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.OK); + assertEquals(FILE_CONTENT, response.getResponse().body().asString()); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName())); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using short descriptor and direct short descriptor.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSShortDirectShort() + { + authenticateTestUser(); + RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, + downloadContentServletDirect + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + RestResponse response = restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.OK); + assertEquals(FILE_CONTENT, response.getResponse().body().asString()); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName())); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using short descriptor and direct long descriptor.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSShortDirectLong() + { + authenticateTestUser(); + String downloadContentServletDirectLong = "alfresco/d/direct/workspace/SpacesStore/"; + RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, + downloadContentServletDirectLong + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + RestResponse response = restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.OK); + assertEquals(FILE_CONTENT, response.getResponse().body().asString()); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName())); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using long descriptor and attach short descriptor.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSLongAttachShort() + { + authenticateTestUser(); + String downloadContentLongServletAttach = "alfresco/download/a/workspace/SpacesStore/"; + RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, + downloadContentLongServletAttach + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + RestResponse response = restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.OK); + assertEquals(FILE_CONTENT, response.getResponse().body().asString()); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName())); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using long descriptor and attach long descriptor.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSLongAttachLong() + { + authenticateTestUser(); + String downloadContentLongServletAttachLong = "alfresco/download/attach/workspace/SpacesStore/"; + RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, + downloadContentLongServletAttachLong + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + RestResponse response = restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.OK); + assertEquals(FILE_CONTENT, response.getResponse().body().asString()); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName())); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using long descriptor and direct short descriptor.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSLongDirectShort() + { + authenticateTestUser(); + String downloadContentLongServletDirect = "alfresco/download/d/workspace/SpacesStore/"; + RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, + downloadContentLongServletDirect + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + RestResponse response = restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.OK); + assertEquals(FILE_CONTENT, response.getResponse().body().asString()); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName())); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using long descriptor and direct long descriptor.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSLongDirectLong() + { + authenticateTestUser(); + String downloadContentLongServletDirectLong = "alfresco/download/direct/workspace/SpacesStore/"; + RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, + downloadContentLongServletDirectLong + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + RestResponse response = restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.OK); + assertEquals(FILE_CONTENT, response.getResponse().body().asString()); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName())); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using short descriptor and attach short uppercase descriptor.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSShortAttachUppercaseShort() + { + authenticateTestUser(); + String downloadContentAttachUppercase = "alfresco/d/A/workspace/SpacesStore/"; + RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, + downloadContentAttachUppercase + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + RestResponse response = restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.OK); + assertEquals(FILE_CONTENT, response.getResponse().body().asString()); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName())); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using short descriptor and direct short uppercase descriptor.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSShortDirectUppercaseShort() + { + authenticateTestUser(); + String downloadContentDirectUppercase = "alfresco/d/D/workspace/SpacesStore/"; + RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, + downloadContentDirectUppercase + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + RestResponse response = restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.OK); + assertEquals(FILE_CONTENT, response.getResponse().body().asString()); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT); + restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName())); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using attach without specifying {storeType}.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSAttachWithoutStoreType() + { + authenticateTestUser(); + String downloadContentLessPathAttach = "alfresco/d/a/SpacesStore/"; + RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, + downloadContentLessPathAttach + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.INTERNAL_SERVER_ERROR); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using direct without specifying {storeType}.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSDirectWithoutStoreType() + { + authenticateTestUser(); + String downloadContentLessPathDirect = "alfresco/d/d/SpacesStore/"; + RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, + downloadContentLessPathDirect + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.INTERNAL_SERVER_ERROR); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using direct without specifying {storeType}.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSDirectWithInvalidStoreType() + { + authenticateTestUser(); + String downloadContentLessPathDirect = "alfresco/download/d/badWorkspace/SpacesStore/"; + RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, + downloadContentLessPathDirect + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.INTERNAL_SERVER_ERROR); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using direct without specifying {storeType}.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSDirectWithInvalidStoreId() + { + authenticateTestUser(); + String downloadContentLessPathDirect = "alfresco/download/d/workspace/badSpacesStore/"; + RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, + downloadContentLessPathDirect + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.INTERNAL_SERVER_ERROR); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using attach without authentication.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSAttachWithoutAuthentication() + { + RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, + downloadContentServletAttach + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.UNAUTHORIZED); + } + + @TestRail(section = { TestGroup.REST_API }, + executionType = ExecutionType.REGRESSION, + description = "Verify DownloadContentServlet retrieve content using direct without authentication.") + @Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE}) + @Bug(id ="MNT-21602", status=Bug.Status.FIXED) + public void verifyDCSDirectWithoutAuthentication() + { + RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, + downloadContentServletDirect + testContentFile.getNodeRef() + "/" + testContentFile.getName()); + restClient.process(request); + restClient.assertStatusCodeIs(HttpStatus.UNAUTHORIZED); + } + + private void authenticateTestUser() + { + restClient.configureRequestSpec() + .addHeader("Authorization", String.format("Basic %s", authHeaderEncoded)) + .build(); + } +} diff --git a/tests/tas-restapi/src/test/resources/test-suites/part1-suite.xml b/tests/tas-restapi/src/test/resources/test-suites/part1-suite.xml index 2d1bf24ff0..ff2ffaed47 100644 --- a/tests/tas-restapi/src/test/resources/test-suites/part1-suite.xml +++ b/tests/tas-restapi/src/test/resources/test-suites/part1-suite.xml @@ -14,6 +14,7 @@ + diff --git a/war/src/main/java/org/alfresco/web/app/servlet/DownloadContentServlet.java b/war/src/main/java/org/alfresco/web/app/servlet/DownloadContentServlet.java new file mode 100644 index 0000000000..0f32483c0e --- /dev/null +++ b/war/src/main/java/org/alfresco/web/app/servlet/DownloadContentServlet.java @@ -0,0 +1,128 @@ +/* + * #%L + * Alfresco Repository WAR Community + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.web.app.servlet; + +import org.alfresco.service.cmr.repository.StoreRef; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.surf.util.URLDecoder; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.StringTokenizer; + +/** + * Servlet responsible for streaming node content from the repo directly to the response stream. + * The appropriate mimetype is calculated based on filename extension. + *

+ * The URL to the servlet should be generated thus: + *

/alfresco/download/attach/workspace/SpacesStore/0000-0000-0000-0000/myfile.pdf
+ * or + *
/alfresco/download/direct/workspace/SpacesStore/0000-0000-0000-0000/myfile.pdf

+ *

+ * The 'attach' or 'direct' element is used to indicate whether to display the stream directly + * in the browser or download it as a file attachment.

+ *

+ * Since ACS 6.X, this Servlet redirects to GET /nodes/{nodeId}/content V1 REST API. + * + * + * @author Kevin Roast + * @author gavinc + */ +public class DownloadContentServlet extends HttpServlet +{ + private static final long serialVersionUID = -576405943603122206L; + + private static Log logger = LogFactory.getLog(DownloadContentServlet.class); + + private static final String URL_ATTACH = "a"; + private static final String URL_ATTACH_LONG = "attach"; + private static final String URL_DIRECT = "d"; + private static final String URL_DIRECT_LONG = "direct"; + + /** + * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest, HttpServletResponse) + */ + protected void doGet(final HttpServletRequest req, final HttpServletResponse res) + throws IOException + { + if (logger.isDebugEnabled()) + { + String queryString = req.getQueryString(); + logger.debug("Authenticating (GET) request to URL: " + req.getRequestURI() + + ((queryString != null && queryString.length() > 0) ? ("?" + queryString) : "")); + } + + // remove request context. + String requestURI = req.getRequestURI(); + requestURI = requestURI.substring(req.getContextPath().length()); + + StringTokenizer t = new StringTokenizer(requestURI, "/"); + int tokenCount = t.countTokens(); + t.nextToken(); // skip servlet name + + // expect a minimum of 6 URL tokens. + // /d/{attach|direct}/{storeType}/{storeId}/{nodeId}/{nodeName} + if(tokenCount < 6) + { + throw new IllegalArgumentException("Download URL did not contain all required args: " + requestURI); + } + + // attachment mode (either 'attach' or 'direct') + String attachToken = t.nextToken(); + boolean isAttachment = URL_ATTACH.equalsIgnoreCase(attachToken) || URL_ATTACH_LONG.equalsIgnoreCase(attachToken); + boolean isDirect = URL_DIRECT.equalsIgnoreCase(attachToken) || URL_DIRECT_LONG.equalsIgnoreCase(attachToken); + if (!(isAttachment || isDirect)) + { + throw new IllegalArgumentException("Attachment mode is not properly specified: " + requestURI); + } + + // allow only nodes from workspace://SpaceStore/ storeRef + StoreRef storeRef = new StoreRef(URLDecoder.decode(t.nextToken()), URLDecoder.decode(t.nextToken())); + boolean isWorkspaceStoreType = storeRef.getProtocol().equalsIgnoreCase("workspace"); + boolean isSpacesStoreStoreId = storeRef.getIdentifier().equalsIgnoreCase("SpacesStore"); + + if (!isWorkspaceStoreType || !isSpacesStoreStoreId) + { + throw new IllegalArgumentException("Servlet accepts only nodes from workspace://SpaceStore/ storeRef: " + requestURI); + } + + String nodeId = URLDecoder.decode(t.nextToken()); + + // build redirect URL to V1 GET /nodes/{nodeId}/content + String redirectUrl = String + .format("%s/api/-default-/public/alfresco/versions/1/nodes/%s/content?attachment=%b", + req.getContextPath(), nodeId, isAttachment); + + if (logger.isDebugEnabled()) + { + logger.debug("Request redirected to URL: " + redirectUrl); + } + res.sendRedirect(redirectUrl); + } +} diff --git a/war/src/main/webapp/WEB-INF/web.xml b/war/src/main/webapp/WEB-INF/web.xml index 616726cea8..9c102703d9 100644 --- a/war/src/main/webapp/WEB-INF/web.xml +++ b/war/src/main/webapp/WEB-INF/web.xml @@ -243,6 +243,10 @@ + + downloadContent + org.alfresco.web.app.servlet.DownloadContentServlet + WebDAV @@ -384,6 +388,16 @@ + + downloadContent + /download/* + + + + downloadContent + /d/* + + WebDAV /webdav/*