diff --git a/amps/share-services/src/test/java/org/alfresco/slingshot/web/scripts/SlingshotContentGetTest.java b/amps/share-services/src/test/java/org/alfresco/slingshot/web/scripts/SlingshotContentGetTest.java
index f500bf0cd2..00c646c99b 100644
--- a/amps/share-services/src/test/java/org/alfresco/slingshot/web/scripts/SlingshotContentGetTest.java
+++ b/amps/share-services/src/test/java/org/alfresco/slingshot/web/scripts/SlingshotContentGetTest.java
@@ -40,6 +40,7 @@ import org.json.JSONObject;
import org.junit.Assert;
import org.springframework.extensions.webscripts.TestWebScriptServer;
import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest;
+import org.springframework.extensions.webscripts.TestWebScriptServer.Response;
import java.io.Serializable;
import java.util.ArrayList;
@@ -194,13 +195,13 @@ public class SlingshotContentGetTest extends BaseWebScriptTest
NodeRef rootFolder = createNode(companyHome, "rootFolder", ContentModel.TYPE_FOLDER);
- NodeRef doc1 = createNodeWithTextContent(rootFolder, "doc1", ContentModel.TYPE_CONTENT, "doc1 file content");
+ NodeRef doc1 = createNodeWithTextContent(rootFolder, "doc1", ContentModel.TYPE_CONTENT, "doc1 file content", MimetypeMap.MIMETYPE_TEXT_PLAIN);
NodeRef folderX = createNode(rootFolder, "X", ContentModel.TYPE_FOLDER);
NodeRef folderY = createNode(folderX, "Y", ContentModel.TYPE_FOLDER);
NodeRef folderZ = createNode(folderY, "Z", ContentModel.TYPE_FOLDER);
- NodeRef doc2 = createNodeWithTextContent(folderZ, "doc2", ContentModel.TYPE_CONTENT, "doc2 file content");
+ NodeRef doc2 = createNodeWithTextContent(folderZ, "doc2", ContentModel.TYPE_CONTENT, "doc2 file content", MimetypeMap.MIMETYPE_TEXT_PLAIN);
// uri with relative path at the end
String uri = URL_CONTENT_DOWNLOAD + doc1.getId() + "/X/Y/Z/doc2";
@@ -212,7 +213,50 @@ public class SlingshotContentGetTest extends BaseWebScriptTest
nodeService.deleteNode(rootFolder);
}
- public NodeRef createNodeWithTextContent(NodeRef parentNode, String nodeCmName, QName nodeType, String content)
+ public void testForcedAttachment() throws Exception
+ {
+ Repository repositoryHelper = (Repository) getServer().getApplicationContext().getBean("repositoryHelper");
+ NodeRef companyHome = repositoryHelper.getCompanyHome();
+
+ NodeRef rootFolder = createNode(companyHome, "rootFolder", ContentModel.TYPE_FOLDER);
+ NodeRef testhtml = createNodeWithTextContent(rootFolder, "testhtml", ContentModel.TYPE_CONTENT, "testhtml content", MimetypeMap.MIMETYPE_HTML);
+ NodeRef testpdf = createNodeWithTextContent(rootFolder, "testpdf", ContentModel.TYPE_CONTENT, "testpdf content", MimetypeMap.MIMETYPE_PDF);
+
+ String uri = URL_CONTENT_DOWNLOAD + testhtml.getId() + "?a=false";
+ GetRequest req = new GetRequest(uri);
+ Response res = sendRequest(req, 200);
+ assertEquals("attachment", res.getHeader("Content-Disposition"));
+ assertEquals(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8", res.getContentType());
+
+ uri = URL_CONTENT_DOWNLOAD + testhtml.getId();
+ res = sendRequest(new GetRequest(uri), 200);
+ assertEquals("attachment", res.getHeader("Content-Disposition"));
+ assertEquals(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8", res.getContentType());
+
+ uri = URL_CONTENT_DOWNLOAD + testhtml.getId() + "?a=true";
+ res = sendRequest(new GetRequest(uri), 200);
+ assertEquals("attachment", res.getHeader("Content-Disposition"));
+ assertEquals(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8", res.getContentType());
+
+ uri = URL_CONTENT_DOWNLOAD + testpdf.getId() + "?a=false";
+ res = sendRequest(new GetRequest(uri), 200);
+ assertNull(res.getHeader("Content-Disposition"));
+ assertEquals(MimetypeMap.MIMETYPE_PDF + ";charset=UTF-8", res.getContentType());
+
+ uri = URL_CONTENT_DOWNLOAD + testpdf.getId();
+ res = sendRequest(new GetRequest(uri), 200);
+ assertNull(res.getHeader("Content-Disposition"));
+ assertEquals(MimetypeMap.MIMETYPE_PDF + ";charset=UTF-8", res.getContentType());
+
+ uri = URL_CONTENT_DOWNLOAD + testpdf.getId() + "?a=true";
+ res = sendRequest(new GetRequest(uri), 200);
+ assertEquals("attachment", res.getHeader("Content-Disposition"));
+ assertEquals(MimetypeMap.MIMETYPE_PDF + ";charset=UTF-8", res.getContentType());
+
+ nodeService.deleteNode(rootFolder);
+ }
+
+ public NodeRef createNodeWithTextContent(NodeRef parentNode, String nodeCmName, QName nodeType, String content, String mimetype)
{
NodeRef nodeRef = createNode(parentNode, nodeCmName, nodeType);
@@ -220,7 +264,7 @@ public class SlingshotContentGetTest extends BaseWebScriptTest
if (content != null)
{
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
- writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
+ writer.setMimetype(mimetype);
writer.setEncoding("UTF-8");
writer.putContent(content);
}
diff --git a/remote-api/src/main/java/org/alfresco/repo/web/scripts/MimeTypeUtil.java b/remote-api/src/main/java/org/alfresco/repo/web/scripts/MimeTypeUtil.java
new file mode 100644
index 0000000000..9d245ad4ea
--- /dev/null
+++ b/remote-api/src/main/java/org/alfresco/repo/web/scripts/MimeTypeUtil.java
@@ -0,0 +1,64 @@
+/*
+ * #%L
+ * Alfresco Remote API
+ * %%
+ * Copyright (C) 2005 - 2022 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.repo.web.scripts;
+
+import org.alfresco.repo.content.MimetypeMap;
+import org.alfresco.service.cmr.repository.ContentReader;
+import org.alfresco.service.cmr.repository.MimetypeService;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+
+public class MimeTypeUtil
+{
+
+ /**
+ * Get the file mimetype from the file ContentReader, and if its null then set the mimetype to binary by default
+ * and try to get the correct one from file extension
+ *
+ *
+ * @param reader reader of the file in the request
+ * @param req request relating to the file
+ * @param mimetypeService MimetypeService
+ *
+ * @return mimetype of the file as a string
+ */
+ public static String determineMimetype(ContentReader reader, WebScriptRequest req, MimetypeService mimetypeService)
+ {
+ String mimetype = reader.getMimetype();
+ if (mimetype == null || mimetype.length() == 0)
+ {
+ String extensionPath = req.getExtensionPath();
+ mimetype = MimetypeMap.MIMETYPE_BINARY;
+ int extIndex = extensionPath.lastIndexOf('.');
+ if (extIndex != -1)
+ {
+ String ext = extensionPath.substring(extIndex + 1);
+ mimetype = mimetypeService.getMimetype(ext);
+ }
+ }
+ return mimetype;
+ }
+
+}
diff --git a/remote-api/src/main/java/org/alfresco/repo/web/scripts/content/ContentGet.java b/remote-api/src/main/java/org/alfresco/repo/web/scripts/content/ContentGet.java
index 83e32679d7..1efa6b42ee 100644
--- a/remote-api/src/main/java/org/alfresco/repo/web/scripts/content/ContentGet.java
+++ b/remote-api/src/main/java/org/alfresco/repo/web/scripts/content/ContentGet.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Remote API
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -26,14 +26,18 @@
package org.alfresco.repo.web.scripts.content;
import java.io.IOException;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
+import org.alfresco.repo.web.scripts.MimeTypeUtil;
import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespaceService;
@@ -65,6 +69,19 @@ public class ContentGet extends StreamContent implements ServletContextAware
private NamespaceService namespaceService;
private ContentService contentService;
+ private List nonAttachContentTypes = Collections.emptyList();
+
+ /**
+ * @param nonAttachContentTypes List
+ */
+ public void setNonAttachContentTypes(List nonAttachContentTypes)
+ {
+ if (nonAttachContentTypes != null && !nonAttachContentTypes.isEmpty())
+ {
+ this.nonAttachContentTypes = nonAttachContentTypes;
+ }
+ }
+
/**
* @param servletContext ServletContext
*/
@@ -121,9 +138,7 @@ public class ContentGet extends StreamContent implements ServletContextAware
{
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + reference.toString());
}
-
- // determine attachment
- boolean attach = Boolean.valueOf(req.getParameter("a"));
+
// render content
QName propertyQName = ContentModel.PROP_CONTENT;
@@ -140,6 +155,19 @@ public class ContentGet extends StreamContent implements ServletContextAware
propertyQName = QName.createQName(propertyName, namespaceService);
}
}
+ // determine attachment and force download for specific mimetypes - see PRODSEC-5862
+ boolean attach = Boolean.valueOf(req.getParameter("a"));
+ ContentReader reader = contentService.getReader(nodeRef, propertyQName);
+ String mimetype = MimeTypeUtil.determineMimetype(reader, req, mimetypeService);
+
+ if (!attach)
+ {
+ if (nonAttachContentTypes == null || !nonAttachContentTypes.contains(mimetype))
+ {
+ attach = true;
+ logger.warn("Ignored a=false for " + nodeRef.getId() + " since " + mimetype + " is not in the whitelist for non-attach content types");
+ }
+ }
// Stream the content
streamContentLocal(req, res, nodeRef, attach, propertyQName, null);
diff --git a/remote-api/src/main/java/org/alfresco/repo/web/scripts/content/ContentInfo.java b/remote-api/src/main/java/org/alfresco/repo/web/scripts/content/ContentInfo.java
index 2e34694c24..9e8b8c2572 100644
--- a/remote-api/src/main/java/org/alfresco/repo/web/scripts/content/ContentInfo.java
+++ b/remote-api/src/main/java/org/alfresco/repo/web/scripts/content/ContentInfo.java
@@ -1,28 +1,28 @@
-/*
- * #%L
- * Alfresco Remote API
- * %%
- * 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%
- */
+/*
+ * #%L
+ * Alfresco Remote API
+ * %%
+ * Copyright (C) 2005 - 2022 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.repo.web.scripts.content;
import java.io.IOException;
@@ -33,7 +33,7 @@ import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
-import org.alfresco.repo.content.MimetypeMap;
+import org.alfresco.repo.web.scripts.MimeTypeUtil;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
@@ -79,18 +79,7 @@ public class ContentInfo extends StreamContent
delegate.setAttachment(req, res, attach, attachFileName);
// establish mimetype
- String mimetype = reader.getMimetype();
- String extensionPath = req.getExtensionPath();
- if (mimetype == null || mimetype.length() == 0)
- {
- mimetype = MimetypeMap.MIMETYPE_BINARY;
- int extIndex = extensionPath.lastIndexOf('.');
- if (extIndex != -1)
- {
- String ext = extensionPath.substring(extIndex + 1);
- mimetype = mimetypeService.getMimetype(ext);
- }
- }
+ String mimetype = MimeTypeUtil.determineMimetype(reader, req, mimetypeService);
// set mimetype for the content and the character encoding + length for the stream
res.setContentType(mimetype);
diff --git a/remote-api/src/main/java/org/alfresco/repo/web/scripts/content/ContentStreamer.java b/remote-api/src/main/java/org/alfresco/repo/web/scripts/content/ContentStreamer.java
index 75a4948cd5..8c418ce92d 100644
--- a/remote-api/src/main/java/org/alfresco/repo/web/scripts/content/ContentStreamer.java
+++ b/remote-api/src/main/java/org/alfresco/repo/web/scripts/content/ContentStreamer.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Remote API
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -43,6 +43,7 @@ import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.filestore.FileContentReader;
+import org.alfresco.repo.web.scripts.MimeTypeUtil;
import org.alfresco.sync.repo.events.EventPublisher;
import org.alfresco.repo.web.util.HttpRangeProcessor;
import org.alfresco.rest.framework.resource.content.CacheDirective;
@@ -361,18 +362,7 @@ public class ContentStreamer implements ResourceLoaderAware
setAttachment(req, res, attach, attachFileName);
// establish mimetype
- String mimetype = reader.getMimetype();
- String extensionPath = req.getExtensionPath();
- if (mimetype == null || mimetype.length() == 0)
- {
- mimetype = MimetypeMap.MIMETYPE_BINARY;
- int extIndex = extensionPath.lastIndexOf('.');
- if (extIndex != -1)
- {
- String ext = extensionPath.substring(extIndex + 1);
- mimetype = mimetypeService.getMimetype(ext);
- }
- }
+ String mimetype = MimeTypeUtil.determineMimetype(reader, req, mimetypeService);
res.setHeader(HEADER_ACCEPT_RANGES, "bytes");
try
diff --git a/remote-api/src/main/resources/alfresco/web-scripts-application-context.xml b/remote-api/src/main/resources/alfresco/web-scripts-application-context.xml
index 47d5358de3..4da5da51b0 100644
--- a/remote-api/src/main/resources/alfresco/web-scripts-application-context.xml
+++ b/remote-api/src/main/resources/alfresco/web-scripts-application-context.xml
@@ -249,6 +249,7 @@
+
diff --git a/remote-api/src/test/java/org/alfresco/repo/web/scripts/content/ContentGetTest.java b/remote-api/src/test/java/org/alfresco/repo/web/scripts/content/ContentGetTest.java
index 3e0e2f0f0d..8a93587f58 100644
--- a/remote-api/src/test/java/org/alfresco/repo/web/scripts/content/ContentGetTest.java
+++ b/remote-api/src/test/java/org/alfresco/repo/web/scripts/content/ContentGetTest.java
@@ -66,13 +66,17 @@ public class ContentGetTest extends BaseWebScriptTest
{
super.setUp();
- this.authenticationService = (MutableAuthenticationService) getServer().getApplicationContext()
- .getBean("AuthenticationService");
+ this.authenticationService = (MutableAuthenticationService)getServer().getApplicationContext().getBean("AuthenticationService");
this.personService = (PersonService) getServer().getApplicationContext().getBean("PersonService");
this.nodeService = (NodeService) getServer().getApplicationContext().getBean("NodeService");
this.contentService = (ContentService) getServer().getApplicationContext().getBean("ContentService");
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
createUser(USER_ONE);
+
+ Repository repositoryHelper = (Repository) getServer().getApplicationContext().getBean("repositoryHelper");
+ NodeRef companyHome = repositoryHelper.getCompanyHome();
+
+ rootFolder = createNode(companyHome, "rootFolder", ContentModel.TYPE_FOLDER);
}
private void createUser(String userName)
@@ -117,18 +121,13 @@ public class ContentGetTest extends BaseWebScriptTest
*/
public void testRelativePath() throws Exception
{
- Repository repositoryHelper = (Repository) getServer().getApplicationContext().getBean("repositoryHelper");
- NodeRef companyHome = repositoryHelper.getCompanyHome();
-
- rootFolder = createNode(companyHome, "rootFolder", ContentModel.TYPE_FOLDER);
-
- NodeRef doc1 = createNodeWithTextContent(rootFolder, "doc1", ContentModel.TYPE_CONTENT, "doc1 file content");
+ NodeRef doc1 = createNodeWithTextContent(rootFolder, "doc1", ContentModel.TYPE_CONTENT, "doc1 file content", MimetypeMap.MIMETYPE_TEXT_PLAIN);
NodeRef folderX = createNode(rootFolder, "X", ContentModel.TYPE_FOLDER);
NodeRef folderY = createNode(folderX, "Y", ContentModel.TYPE_FOLDER);
NodeRef folderZ = createNode(folderY, "Z", ContentModel.TYPE_FOLDER);
- NodeRef doc2 = createNodeWithTextContent(folderZ, "doc2", ContentModel.TYPE_CONTENT, "doc2 file content");
+ NodeRef doc2 = createNodeWithTextContent(folderZ, "doc2", ContentModel.TYPE_CONTENT, "doc2 file content", MimetypeMap.MIMETYPE_TEXT_PLAIN);
// uri with relative path at the end
String uri = URL_CONTENT_DOWNLOAD + doc1.getId() + "/X/Y/Z/doc2";
@@ -138,7 +137,46 @@ public class ContentGetTest extends BaseWebScriptTest
Assert.assertEquals("doc2 file content", resp.getContentAsString());
}
- public NodeRef createNodeWithTextContent(NodeRef parentNode, String nodeCmName, QName nodeType, String content)
+
+
+ public void testForcedAttachment() throws Exception
+ {
+ NodeRef testhtml = createNodeWithTextContent(rootFolder, "testhtml", ContentModel.TYPE_CONTENT, "testhtml content", MimetypeMap.MIMETYPE_HTML);
+ NodeRef testpdf = createNodeWithTextContent(rootFolder, "testpdf", ContentModel.TYPE_CONTENT, "testpdf content", MimetypeMap.MIMETYPE_PDF);
+
+ String uri = URL_CONTENT_DOWNLOAD + testhtml.getId() + "?a=false";
+ GetRequest req = new GetRequest(uri);
+ Response res = sendRequest(req, 200);
+ assertEquals("attachment", res.getHeader("Content-Disposition"));
+ assertEquals(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8", res.getContentType());
+
+ uri = URL_CONTENT_DOWNLOAD + testhtml.getId();
+ res = sendRequest(new GetRequest(uri), 200);
+ assertEquals("attachment", res.getHeader("Content-Disposition"));
+ assertEquals(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8", res.getContentType());
+
+ uri = URL_CONTENT_DOWNLOAD + testhtml.getId() + "?a=true";
+ res = sendRequest(new GetRequest(uri), 200);
+ assertEquals("attachment", res.getHeader("Content-Disposition"));
+ assertEquals(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8", res.getContentType());
+
+ uri = URL_CONTENT_DOWNLOAD + testpdf.getId() + "?a=false";
+ res = sendRequest(new GetRequest(uri), 200);
+ assertNull(res.getHeader("Content-Disposition"));
+ assertEquals(MimetypeMap.MIMETYPE_PDF + ";charset=UTF-8", res.getContentType());
+
+ uri = URL_CONTENT_DOWNLOAD + testpdf.getId();
+ res = sendRequest(new GetRequest(uri), 200);
+ assertNull(res.getHeader("Content-Disposition"));
+ assertEquals(MimetypeMap.MIMETYPE_PDF + ";charset=UTF-8", res.getContentType());
+
+ uri = URL_CONTENT_DOWNLOAD + testpdf.getId() + "?a=true";
+ res = sendRequest(new GetRequest(uri), 200);
+ assertEquals("attachment", res.getHeader("Content-Disposition"));
+ assertEquals(MimetypeMap.MIMETYPE_PDF + ";charset=UTF-8", res.getContentType());
+ }
+
+ public NodeRef createNodeWithTextContent(NodeRef parentNode, String nodeCmName, QName nodeType, String content, String mimetype)
{
NodeRef nodeRef = createNode(parentNode, nodeCmName, nodeType);
@@ -146,7 +184,7 @@ public class ContentGetTest extends BaseWebScriptTest
if (content != null)
{
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
- writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
+ writer.setMimetype(mimetype);
writer.setEncoding("UTF-8");
writer.putContent(content);
}