diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/forms/pickerresults.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/forms/pickerresults.lib.ftl index c76e0755ff..26f5fa589a 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/forms/pickerresults.lib.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/forms/pickerresults.lib.ftl @@ -31,7 +31,7 @@ <#list results as row> { "type": "${row.item.typeShort}", - "parentType": "${row.item.parentTypeShort}", + "parentType": "${row.item.parentTypeShort!""}", "isContainer": ${row.item.isContainer?string}, "name": "${row.item.properties.name!""}", "title": "${row.item.properties.title!""}", diff --git a/source/java/org/alfresco/repo/web/scripts/content/ContentGet.java b/source/java/org/alfresco/repo/web/scripts/content/ContentGet.java index 6f9589d2fc..0503c75e1a 100644 --- a/source/java/org/alfresco/repo/web/scripts/content/ContentGet.java +++ b/source/java/org/alfresco/repo/web/scripts/content/ContentGet.java @@ -1,273 +1,290 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * 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 . - */ -package org.alfresco.repo.web.scripts.content; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletResponse; - -import org.alfresco.cmis.CMISFilterNotValidException; -import org.alfresco.cmis.CMISObjectReference; -import org.alfresco.cmis.CMISRendition; -import org.alfresco.cmis.CMISRenditionService; -import org.alfresco.model.ApplicationModel; -import org.alfresco.model.ContentModel; -import org.alfresco.repo.cmis.reference.ReferenceFactory; -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.web.scripts.FileTypeImageUtils; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.repository.FileTypeImageSize; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; -import org.springframework.util.FileCopyUtils; -import org.springframework.web.context.ServletContextAware; -import org.springframework.web.context.support.ServletContextResource; - - -/** - * Content Retrieval Service - * - * Stream content from the Repository. - * - * @author davidc - */ -public class ContentGet extends StreamContent implements ServletContextAware -{ - // Logger - @SuppressWarnings("unused") - private static final Log logger = LogFactory.getLog(ContentGet.class); - - // Component dependencies - private ServletContext servletContext; - private ReferenceFactory referenceFactory; - private DictionaryService dictionaryService; - private NamespaceService namespaceService; - private CMISRenditionService renditionService; - - /** - * @param - */ - public void setServletContext(ServletContext servletContext) - { - this.servletContext = servletContext; - } - - /** - * @param reference factory - */ - public void setReferenceFactory(ReferenceFactory referenceFactory) - { - this.referenceFactory = referenceFactory; - } - - /** - * @param dictionaryService - */ - public void setDictionaryService(DictionaryService dictionaryService) - { - this.dictionaryService = dictionaryService; - } - - /** - * @param namespaceService - */ - public void setNamespaceService(NamespaceService namespaceService) - { - this.namespaceService = namespaceService; - } - - /** - * @param renditionService - */ - public void setCMISRenditionService(CMISRenditionService renditionService) - { - this.renditionService = renditionService; - } - - /** - * @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) - */ - public void execute(WebScriptRequest req, WebScriptResponse res) - throws IOException - { - // create map of args - String[] names = req.getParameterNames(); - Map args = new HashMap(names.length, 1.0f); - for (String name : names) - { - args.put(name, req.getParameter(name)); - } - - // create map of template vars - Map templateVars = req.getServiceMatch().getTemplateVars(); - - // create object reference from url - CMISObjectReference reference = referenceFactory.createObjectReferenceFromUrl(args, templateVars); - NodeRef nodeRef = reference.getNodeRef(); - if (nodeRef == null) - { - throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + reference.toString()); - } - - // determine attachment - boolean attach = Boolean.valueOf(req.getParameter("a")); - - // stream content on node, or rendition of node - String streamId = req.getParameter("streamId"); - if (streamId != null && streamId.length() > 0) - { - // render content rendition - streamRendition(req, res, reference, streamId, attach); - } - else - { - // render content - QName propertyQName = ContentModel.PROP_CONTENT; - String contentPart = templateVars.get("property"); - if (contentPart.length() > 0 && contentPart.charAt(0) == ';') - { - if (contentPart.length() < 2) - { - throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Content property malformed"); - } - String propertyName = contentPart.substring(1); - if (propertyName.length() > 0) - { - propertyQName = QName.createQName(propertyName, namespaceService); - } - } - - // Stream the content - streamContent(req, res, nodeRef, propertyQName, attach); - } - } - - /** - * Stream content rendition - * - * @param req - * @param res - * @param reference - * @param streamId - * @param attach - * @throws IOException - */ - private void streamRendition(WebScriptRequest req, WebScriptResponse res, CMISObjectReference reference, String streamId, boolean attach) - throws IOException - { - try - { - // find rendition - CMISRendition rendition = null; - List renditions = renditionService.getRenditions(reference.getNodeRef(), "*"); - for (CMISRendition candidateRendition : renditions) - { - if (candidateRendition.getStreamId().equals(streamId)) - { - rendition = candidateRendition; - break; - } - } - if (rendition == null) - { - throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find rendition " + streamId + " for " + reference.toString()); - } - - // determine if special case for icons - if (streamId.startsWith("alf:icon")) - { - streamIcon(res, reference, streamId, attach); - } - else - { - streamContent(req, res, rendition.getNodeRef(), ContentModel.PROP_CONTENT, attach); - } - } - catch(CMISFilterNotValidException e) - { - throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Invalid Rendition Filter"); - } - } - - /** - * Stream Icon - * - * @param res - * @param reference - * @param streamId - * @param attach - * @throws IOException - */ - private void streamIcon(WebScriptResponse res, CMISObjectReference reference, String streamId, boolean attach) - throws IOException - { - // convert stream id to icon size - FileTypeImageSize imageSize = streamId.equals("alf:icon16") ? FileTypeImageSize.Small : FileTypeImageSize.Medium; - String iconSize = streamId.equals("alf:icon16") ? "-16" : ""; - - // calculate icon file name and path - String iconPath = null; - if (dictionaryService.isSubClass(nodeService.getType(reference.getNodeRef()), ContentModel.TYPE_CONTENT)) - { - String name = (String)nodeService.getProperty(reference.getNodeRef(), ContentModel.PROP_NAME); - iconPath = FileTypeImageUtils.getFileTypeImage(servletContext, name, imageSize); - } - else - { - String icon = (String)nodeService.getProperty(reference.getNodeRef(), ApplicationModel.PROP_ICON); - if (icon != null) - { - iconPath = "/images/icons/" + icon + iconSize + ".gif"; - } - else - { - iconPath = "/images/icons/space-icon-default" + iconSize + ".gif"; - } - } - - // set mimetype - String mimetype = MimetypeMap.MIMETYPE_BINARY; - int extIndex = iconPath.lastIndexOf('.'); - if (extIndex != -1) - { - String ext = iconPath.substring(extIndex + 1); - mimetype = mimetypeService.getMimetype(ext); - } - res.setContentType(mimetype); - - // stream icon - ServletContextResource resource = new ServletContextResource(servletContext, iconPath); - if (!resource.exists()) - { - throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find rendition " + streamId + " for " + reference.toString()); - } - FileCopyUtils.copy(resource.getInputStream(), res.getOutputStream()); - } - +/* + * Copyright (C) 2005-2012 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * 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 . + */ +package org.alfresco.repo.web.scripts.content; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.cmis.CMISFilterNotValidException; +import org.alfresco.cmis.CMISObjectReference; +import org.alfresco.cmis.CMISRendition; +import org.alfresco.cmis.CMISRenditionService; +import org.alfresco.model.ApplicationModel; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.cmis.reference.ReferenceFactory; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.web.scripts.FileTypeImageUtils; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.FileTypeImageSize; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.context.ServletContextAware; +import org.springframework.web.context.support.ServletContextResource; + + +/** + * Content Retrieval Service + * + * Stream content from the Repository. + * + * @author davidc + */ +public class ContentGet extends StreamContent implements ServletContextAware +{ + // Logger + @SuppressWarnings("unused") + private static final Log logger = LogFactory.getLog(ContentGet.class); + + // Component dependencies + private ServletContext servletContext; + private ReferenceFactory referenceFactory; + private DictionaryService dictionaryService; + private NamespaceService namespaceService; + private CMISRenditionService renditionService; + + /** + * @param + */ + public void setServletContext(ServletContext servletContext) + { + this.servletContext = servletContext; + } + + /** + * @param reference factory + */ + public void setReferenceFactory(ReferenceFactory referenceFactory) + { + this.referenceFactory = referenceFactory; + } + + /** + * @param dictionaryService + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + /** + * @param namespaceService + */ + public void setNamespaceService(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + } + + /** + * @param renditionService + */ + public void setCMISRenditionService(CMISRenditionService renditionService) + { + this.renditionService = renditionService; + } + + /** + * @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) + */ + public void execute(WebScriptRequest req, WebScriptResponse res) + throws IOException + { + // create map of args + String[] names = req.getParameterNames(); + Map args = new HashMap(names.length, 1.0f); + for (String name : names) + { + args.put(name, req.getParameter(name)); + } + + // create map of template vars + Map templateVars = req.getServiceMatch().getTemplateVars(); + + // create object reference from url + CMISObjectReference reference = referenceFactory.createObjectReferenceFromUrl(args, templateVars); + NodeRef nodeRef = reference.getNodeRef(); + if (nodeRef == null) + { + throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + reference.toString()); + } + + // determine attachment + boolean attach = Boolean.valueOf(req.getParameter("a")); + + // stream content on node, or rendition of node + String streamId = req.getParameter("streamId"); + if (streamId != null && streamId.length() > 0) + { + // render content rendition + streamRendition(req, res, reference, streamId, attach); + } + else + { + // render content + QName propertyQName = ContentModel.PROP_CONTENT; + String contentPart = templateVars.get("property"); + if (contentPart.length() > 0 && contentPart.charAt(0) == ';') + { + if (contentPart.length() < 2) + { + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Content property malformed"); + } + String propertyName = contentPart.substring(1); + if (propertyName.length() > 0) + { + propertyQName = QName.createQName(propertyName, namespaceService); + } + } + + // Stream the content + streamContentLocal(req, res, nodeRef, attach, propertyQName); + } + } + + private void streamContentLocal(WebScriptRequest req, WebScriptResponse res, NodeRef nodeRef, boolean attach, QName propertyQName) throws IOException + { + String userAgent = req.getHeader("User-Agent"); + + boolean rfc5987Supported = (null != userAgent) && (userAgent.contains("MSIE") || userAgent.contains(" Chrome/") || userAgent.contains(" FireFox/")); + + if (attach && rfc5987Supported) + { + String name = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); + streamContent(req, res, nodeRef, propertyQName, attach, name); + } + else + { + streamContent(req, res, nodeRef, propertyQName, attach); + } + } + + /** + * Stream content rendition + * + * @param req + * @param res + * @param reference + * @param streamId + * @param attach + * @throws IOException + */ + private void streamRendition(WebScriptRequest req, WebScriptResponse res, CMISObjectReference reference, String streamId, boolean attach) + throws IOException + { + try + { + // find rendition + CMISRendition rendition = null; + List renditions = renditionService.getRenditions(reference.getNodeRef(), "*"); + for (CMISRendition candidateRendition : renditions) + { + if (candidateRendition.getStreamId().equals(streamId)) + { + rendition = candidateRendition; + break; + } + } + if (rendition == null) + { + throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find rendition " + streamId + " for " + reference.toString()); + } + + // determine if special case for icons + if (streamId.startsWith("alf:icon")) + { + streamIcon(res, reference, streamId, attach); + } + else + { + streamContentLocal(req, res, reference.getNodeRef(), attach, ContentModel.PROP_CONTENT); + } + } + catch(CMISFilterNotValidException e) + { + throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Invalid Rendition Filter"); + } + } + + /** + * Stream Icon + * + * @param res + * @param reference + * @param streamId + * @param attach + * @throws IOException + */ + private void streamIcon(WebScriptResponse res, CMISObjectReference reference, String streamId, boolean attach) + throws IOException + { + // convert stream id to icon size + FileTypeImageSize imageSize = streamId.equals("alf:icon16") ? FileTypeImageSize.Small : FileTypeImageSize.Medium; + String iconSize = streamId.equals("alf:icon16") ? "-16" : ""; + + // calculate icon file name and path + String iconPath = null; + if (dictionaryService.isSubClass(nodeService.getType(reference.getNodeRef()), ContentModel.TYPE_CONTENT)) + { + String name = (String)nodeService.getProperty(reference.getNodeRef(), ContentModel.PROP_NAME); + iconPath = FileTypeImageUtils.getFileTypeImage(servletContext, name, imageSize); + } + else + { + String icon = (String)nodeService.getProperty(reference.getNodeRef(), ApplicationModel.PROP_ICON); + if (icon != null) + { + iconPath = "/images/icons/" + icon + iconSize + ".gif"; + } + else + { + iconPath = "/images/icons/space-icon-default" + iconSize + ".gif"; + } + } + + // set mimetype + String mimetype = MimetypeMap.MIMETYPE_BINARY; + int extIndex = iconPath.lastIndexOf('.'); + if (extIndex != -1) + { + String ext = iconPath.substring(extIndex + 1); + mimetype = mimetypeService.getMimetype(ext); + } + res.setContentType(mimetype); + + // stream icon + ServletContextResource resource = new ServletContextResource(servletContext, iconPath); + if (!resource.exists()) + { + throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find rendition " + streamId + " for " + reference.toString()); + } + FileCopyUtils.copy(resource.getInputStream(), res.getOutputStream()); + } + } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/content/StreamContent.java b/source/java/org/alfresco/repo/web/scripts/content/StreamContent.java index 6176da2949..87c6e649b5 100644 --- a/source/java/org/alfresco/repo/web/scripts/content/StreamContent.java +++ b/source/java/org/alfresco/repo/web/scripts/content/StreamContent.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2011 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -36,6 +36,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.webdav.WebDAVHelper; import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; @@ -804,7 +805,7 @@ public class StreamContent extends AbstractWebScript implements ResourceLoaderAw if (logger.isDebugEnabled()) logger.debug("Attaching content using filename: " + attachFileName); - headerValue += "; filename=" + attachFileName; + headerValue += "; filename*=UTF-8''" + WebDAVHelper.encodeURL(attachFileName) + "; filename=\"" + attachFileName + "\""; } // set header based on filename - will force a Save As from the browse if it doesn't recognize it