/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library 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 2.1 of the License, or (at your option) * any later version. * * This library 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. */ package com.liferay.portal.webserver; import com.liferay.document.library.kernel.document.conversion.DocumentConversionUtil; import com.liferay.document.library.kernel.exception.NoSuchFileEntryException; import com.liferay.document.library.kernel.exception.NoSuchFileException; import com.liferay.document.library.kernel.exception.NoSuchFolderException; import com.liferay.document.library.kernel.model.DLFolderConstants; import com.liferay.document.library.kernel.service.DLAppLocalServiceUtil; import com.liferay.document.library.kernel.service.DLAppServiceUtil; import com.liferay.document.library.kernel.util.AudioProcessorUtil; import com.liferay.document.library.kernel.util.DLUtil; import com.liferay.document.library.kernel.util.ImageProcessorUtil; import com.liferay.document.library.kernel.util.PDFProcessor; import com.liferay.document.library.kernel.util.PDFProcessorUtil; import com.liferay.document.library.kernel.util.VideoProcessor; import com.liferay.document.library.kernel.util.VideoProcessorUtil; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.exception.SystemException; import com.liferay.portal.kernel.flash.FlashMagicBytesUtil; import com.liferay.portal.kernel.image.ImageBag; import com.liferay.portal.kernel.image.ImageToolUtil; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.Company; import com.liferay.portal.kernel.model.CompanyConstants; import com.liferay.portal.kernel.model.Group; import com.liferay.portal.kernel.model.Image; import com.liferay.portal.kernel.model.ImageConstants; import com.liferay.portal.kernel.model.Layout; import com.liferay.portal.kernel.model.LayoutSet; import com.liferay.portal.kernel.model.User; import com.liferay.portal.kernel.portlet.PortletProvider; import com.liferay.portal.kernel.portlet.PortletProviderUtil; import com.liferay.portal.kernel.portletfilerepository.PortletFileRepositoryUtil; import com.liferay.portal.kernel.repository.Repository; import com.liferay.portal.kernel.repository.RepositoryException; import com.liferay.portal.kernel.repository.RepositoryProviderUtil; import com.liferay.portal.kernel.repository.capabilities.ThumbnailCapability; import com.liferay.portal.kernel.repository.model.FileEntry; import com.liferay.portal.kernel.repository.model.FileShortcut; import com.liferay.portal.kernel.repository.model.FileVersion; import com.liferay.portal.kernel.repository.model.Folder; import com.liferay.portal.kernel.security.auth.PrincipalException; import com.liferay.portal.kernel.security.auth.PrincipalThreadLocal; import com.liferay.portal.kernel.security.permission.ActionKeys; import com.liferay.portal.kernel.security.permission.PermissionChecker; import com.liferay.portal.kernel.security.permission.PermissionCheckerFactoryUtil; import com.liferay.portal.kernel.security.permission.PermissionThreadLocal; import com.liferay.portal.kernel.service.CompanyLocalServiceUtil; import com.liferay.portal.kernel.service.GroupLocalServiceUtil; import com.liferay.portal.kernel.service.ImageLocalServiceUtil; import com.liferay.portal.kernel.service.ImageServiceUtil; import com.liferay.portal.kernel.service.LayoutLocalServiceUtil; import com.liferay.portal.kernel.service.LayoutSetLocalServiceUtil; import com.liferay.portal.kernel.service.UserLocalServiceUtil; import com.liferay.portal.kernel.service.permission.GroupPermissionUtil; import com.liferay.portal.kernel.service.permission.LayoutPermissionUtil; import com.liferay.portal.kernel.service.permission.PortletPermissionUtil; import com.liferay.portal.kernel.servlet.HttpHeaders; import com.liferay.portal.kernel.servlet.InactiveRequestHandler; import com.liferay.portal.kernel.servlet.PortalSessionThreadLocal; import com.liferay.portal.kernel.servlet.ServletResponseUtil; import com.liferay.portal.kernel.template.Template; import com.liferay.portal.kernel.template.TemplateConstants; import com.liferay.portal.kernel.template.TemplateManagerUtil; import com.liferay.portal.kernel.template.TemplateResource; import com.liferay.portal.kernel.template.URLTemplateResource; import com.liferay.portal.kernel.theme.ThemeDisplay; import com.liferay.portal.kernel.transaction.TransactionConfig; import com.liferay.portal.kernel.transaction.TransactionInvokerUtil; import com.liferay.portal.kernel.util.CharPool; import com.liferay.portal.kernel.util.ContentTypes; import com.liferay.portal.kernel.util.DigesterUtil; import com.liferay.portal.kernel.util.FastDateFormatFactoryUtil; import com.liferay.portal.kernel.util.FileUtil; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.HtmlUtil; import com.liferay.portal.kernel.util.HttpUtil; import com.liferay.portal.kernel.util.MimeTypesUtil; import com.liferay.portal.kernel.util.ParamUtil; import com.liferay.portal.kernel.util.PortalUtil; import com.liferay.portal.kernel.util.ReleaseInfo; import com.liferay.portal.kernel.util.ServiceProxyFactory; import com.liferay.portal.kernel.util.SetUtil; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.UnicodeProperties; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.kernel.util.Validator_IW; import com.liferay.portal.kernel.util.WebKeys; import com.liferay.portal.kernel.webdav.WebDAVUtil; import com.liferay.portal.kernel.workflow.WorkflowConstants; import com.liferay.portal.model.impl.ImageImpl; import com.liferay.portal.util.PortalInstances; import com.liferay.portal.util.PropsValues; import com.liferay.trash.kernel.model.TrashEntry; import com.liferay.trash.kernel.util.TrashUtil; import com.liferay.users.admin.kernel.file.uploads.UserFileUploadsSettings; import java.awt.image.RenderedImage; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.text.Format; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Set; import java.util.concurrent.Callable; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * @author Alexander Chow * @author Brian Wing Shun Chan */ public class WebServerServlet extends HttpServlet { public static final String PATH_PORTLET_FILE_ENTRY = "portlet_file_entry"; /** * @see com.liferay.portal.servlet.filters.virtualhost.VirtualHostFilter */ public static boolean hasFiles(HttpServletRequest request) { String name = PrincipalThreadLocal.getName(); String password = PrincipalThreadLocal.getPassword(); try { // Do not use permission checking since this may be called from // other contexts that are also managing the principal User user = _getUser(request); if (!user.isDefaultUser()) { PrincipalThreadLocal.setName(user.getUserId()); PrincipalThreadLocal.setPassword( PortalUtil.getUserPassword(request)); } String path = HttpUtil.fixPath(request.getPathInfo()); String[] pathArray = StringUtil.split(path, CharPool.SLASH); if (pathArray.length == 0) { return true; } else if (Validator.isNumber(pathArray[0])) { _checkFileEntry(pathArray); } else if (PATH_PORTLET_FILE_ENTRY.equals(pathArray[0])) { FileEntry fileEntry = getPortletFileEntry(request, pathArray); if (fileEntry != null) { return true; } } else { Group group = _getGroup(user.getCompanyId(), pathArray[0]); _checkDirectoryIndexingEnabled(group); long groupId = group.getGroupId(); long folderId = DLFolderConstants.DEFAULT_PARENT_FOLDER_ID; for (int i = 1; i < pathArray.length; i++) { try { Folder folder = DLAppLocalServiceUtil.getFolder( groupId, folderId, pathArray[i]); folderId = folder.getFolderId(); } catch (NoSuchFolderException nsfe) { // LPS-52675 if (_log.isDebugEnabled()) { _log.debug(nsfe, nsfe); } if (i != (pathArray.length - 1)) { return false; } pathArray = new String[] { String.valueOf(groupId), String.valueOf(folderId), pathArray[i] }; _checkFileEntry(pathArray); } } } } catch (Exception e) { return false; } finally { PrincipalThreadLocal.setName(name); PrincipalThreadLocal.setPassword(password); } return true; } @Override public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); _lastModified = GetterUtil.getBoolean( servletConfig.getInitParameter("last_modified"), true); Class<?> clazz = getClass(); ClassLoader classLoader = clazz.getClassLoader(); String templateId = "com/liferay/portal/webserver/dependencies/template.ftl"; URL url = classLoader.getResource(templateId); _templateResource = new URLTemplateResource(templateId, url); } @Override public void service( HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { User user = null; try { user = _getUser(request); if (_processCompanyInactiveRequest( request, response, user.getCompanyId())) { return; } PrincipalThreadLocal.setName(user.getUserId()); PrincipalThreadLocal.setPassword( PortalUtil.getUserPassword(request)); PermissionChecker permissionChecker = PermissionCheckerFactoryUtil.create(user); PermissionThreadLocal.setPermissionChecker(permissionChecker); if (_lastModified) { long lastModified = getLastModified(request); if (lastModified > 0) { long ifModifiedSince = request.getDateHeader( HttpHeaders.IF_MODIFIED_SINCE); if ((ifModifiedSince > 0) && (ifModifiedSince == lastModified)) { response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); return; } } if (lastModified > 0) { response.setDateHeader( HttpHeaders.LAST_MODIFIED, lastModified); } } TransactionConfig.Builder builder = new TransactionConfig.Builder(); builder.setReadOnly(true); builder.setRollbackForClasses(Exception.class); TransactionInvokerUtil.invoke( builder.build(), _createFileServingCallable(request, response, user)); } catch (NoSuchFileEntryException nsfee) { PortalUtil.sendError( HttpServletResponse.SC_NOT_FOUND, nsfee, request, response); } catch (NoSuchFolderException nsfe) { PortalUtil.sendError( HttpServletResponse.SC_NOT_FOUND, nsfe, request, response); } catch (PrincipalException pe) { processPrincipalException(pe, user, request, response); } catch (Exception e) { PortalUtil.sendError(e, request, response); } catch (Throwable t) { PortalUtil.sendError(new Exception(t), request, response); } } protected static FileEntry getPortletFileEntry( HttpServletRequest request, String[] pathArray) throws Exception { long groupId = GetterUtil.getLong(pathArray[1]); String uuid = pathArray[3]; FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry( uuid, groupId); int status = ParamUtil.getInteger( request, "status", WorkflowConstants.STATUS_APPROVED); if ((status != WorkflowConstants.STATUS_IN_TRASH) && fileEntry.isInTrash()) { return null; } return fileEntry; } protected Image convertFileEntry(boolean smallImage, FileEntry fileEntry) throws PortalException { try { Image image = new ImageImpl(); image.setModifiedDate(fileEntry.getModifiedDate()); InputStream is = null; if (smallImage) { is = ImageProcessorUtil.getThumbnailAsStream( fileEntry.getFileVersion(), 0); } else { is = fileEntry.getContentStream(); } byte[] bytes = FileUtil.getBytes(is); image.setTextObj(bytes); image.setType(fileEntry.getExtension()); return image; } catch (PortalException pe) { throw pe; } catch (SystemException se) { throw se; } catch (Exception e) { throw new SystemException(e); } } protected Image getDefaultImage(HttpServletRequest request, long imageId) { String path = GetterUtil.getString(request.getPathInfo()); if (path.startsWith("/company_logo") || path.startsWith("/layout_set_logo") || path.startsWith("/logo")) { return ImageToolUtil.getDefaultCompanyLogo(); } else if (path.startsWith("/organization_logo")) { return ImageToolUtil.getDefaultOrganizationLogo(); } else if (path.startsWith("/user_female_portrait")) { return ImageToolUtil.getDefaultUserFemalePortrait(); } else if (path.startsWith("/user_male_portrait")) { return ImageToolUtil.getDefaultUserMalePortrait(); } else if (path.startsWith("/user_portrait")) { return ImageToolUtil.getDefaultUserMalePortrait(); } else { return null; } } protected FileEntry getFileEntry(String[] pathArray) throws Exception { if (pathArray.length == 1) { long fileShortcutId = GetterUtil.getLong(pathArray[0]); FileShortcut dlFileShortcut = DLAppServiceUtil.getFileShortcut( fileShortcutId); return DLAppServiceUtil.getFileEntry( dlFileShortcut.getToFileEntryId()); } else if (pathArray.length == 2) { long groupId = GetterUtil.getLong(pathArray[0]); return DLAppServiceUtil.getFileEntryByUuidAndGroupId( pathArray[1], groupId); } else if (pathArray.length == 3) { long groupId = GetterUtil.getLong(pathArray[0]); long folderId = GetterUtil.getLong(pathArray[1]); String fileName = HttpUtil.decodeURL(pathArray[2]); if (fileName.contains(StringPool.QUESTION)) { fileName = fileName.substring( 0, fileName.indexOf(StringPool.QUESTION)); } return DLAppServiceUtil.getFileEntry(groupId, folderId, fileName); } else { long groupId = GetterUtil.getLong(pathArray[0]); String uuid = pathArray[3]; return DLAppServiceUtil.getFileEntryByUuidAndGroupId(uuid, groupId); } } protected Image getImage(HttpServletRequest request, boolean getDefault) throws Exception { Image image = null; long imageId = getImageId(request); if (imageId > 0) { image = ImageServiceUtil.getImage(imageId); String path = GetterUtil.getString(request.getPathInfo()); if (path.startsWith("/layout_icon") || path.startsWith("/logo")) { Layout layout = LayoutLocalServiceUtil.fetchLayoutByIconImageId( true, imageId); if (layout != null) { User user = PortalUtil.getUser(request); if (user == null) { long companyId = PortalUtil.getCompanyId(request); user = UserLocalServiceUtil.getDefaultUser(companyId); } PermissionChecker permissionChecker = PermissionCheckerFactoryUtil.create(user); if (!LayoutPermissionUtil.contains( permissionChecker, layout, ActionKeys.VIEW)) { throw new PrincipalException.MustHavePermission( permissionChecker, Layout.class.getName(), layout.getPlid(), ActionKeys.VIEW); } } } else if (path.startsWith("/layout_set_logo")) { LayoutSet layoutSet = LayoutSetLocalServiceUtil.fetchLayoutSetByLogoId( true, imageId); if (layoutSet != null) { User user = PortalUtil.getUser(request); if (user == null) { long companyId = PortalUtil.getCompanyId(request); user = UserLocalServiceUtil.getDefaultUser(companyId); } PermissionChecker permissionChecker = PermissionCheckerFactoryUtil.create(user); Group group = layoutSet.getGroup(); if (!group.isShowSite( permissionChecker, layoutSet.isPrivateLayout()) && !GroupPermissionUtil.contains( permissionChecker, layoutSet.getGroupId(), ActionKeys.VIEW)) { throw new PrincipalException.MustHavePermission( permissionChecker, LayoutSet.class.getName(), layoutSet.getLayoutSetId(), ActionKeys.VIEW); } } } else if (path.startsWith("/user_female_portrait") || path.startsWith("/user_male_portrait") || path.startsWith("/user_portrait")) { image = getUserPortraitImageResized(image, imageId); } } else { String uuid = ParamUtil.getString(request, "uuid"); long groupId = ParamUtil.getLong(request, "groupId"); boolean igSmallImage = ParamUtil.getBoolean( request, "igSmallImage"); if (Validator.isNotNull(uuid) && (groupId > 0)) { try { FileEntry fileEntry = DLAppServiceUtil.getFileEntryByUuidAndGroupId( uuid, groupId); image = convertFileEntry(igSmallImage, fileEntry); } catch (Exception e) { } } } if (getDefault) { if (image == null) { if (_log.isWarnEnabled()) { _log.warn("Get a default image for " + imageId); } image = getDefaultImage(request, imageId); } } return image; } protected byte[] getImageBytes(HttpServletRequest request, Image image) throws PortalException { byte[] textObj = image.getTextObj(); if ((textObj == null) || (textObj.length == 0)) { throw new NoSuchFileException(); } try { if (!PropsValues.IMAGE_AUTO_SCALE) { return textObj; } ImageBag imageBag = null; if (image.getImageId() == 0) { imageBag = ImageToolUtil.read(textObj); RenderedImage renderedImage = imageBag.getRenderedImage(); image.setHeight(renderedImage.getHeight()); image.setWidth(renderedImage.getWidth()); } int height = ParamUtil.getInteger( request, "height", image.getHeight()); int width = ParamUtil.getInteger( request, "width", image.getWidth()); if ((height >= image.getHeight()) && (width >= image.getWidth())) { return textObj; } if (image.getImageId() != 0) { imageBag = ImageToolUtil.read(textObj); } RenderedImage renderedImage = ImageToolUtil.scale( imageBag.getRenderedImage(), height, width); return ImageToolUtil.getBytes(renderedImage, imageBag.getType()); } catch (Exception e) { if (_log.isWarnEnabled()) { _log.warn("Error scaling image " + image.getImageId(), e); } } return textObj; } protected long getImageId(HttpServletRequest request) { // The image id may be passed in as image_id, img_id, or i_id long imageId = ParamUtil.getLong(request, "image_id"); if (imageId <= 0) { imageId = ParamUtil.getLong(request, "img_id"); } if (imageId <= 0) { imageId = ParamUtil.getLong(request, "i_id"); } User user = null; if (imageId <= 0) { long companyId = ParamUtil.getLong(request, "companyId"); String screenName = ParamUtil.getString(request, "screenName"); if ((companyId > 0) && Validator.isNotNull(screenName)) { user = UserLocalServiceUtil.fetchUserByScreenName( companyId, screenName); if (user != null) { imageId = user.getPortraitId(); } } } if (_userFileUploadsSettings.isImageCheckToken() && (imageId > 0)) { String imageIdToken = ParamUtil.getString(request, "img_id_token"); if (user == null) { user = UserLocalServiceUtil.fetchUserByPortraitId(imageId); } if ((user != null) && !imageIdToken.equals(DigesterUtil.digest(user.getUserUuid()))) { return 0; } } return imageId; } @Override protected long getLastModified(HttpServletRequest request) { try { Date modifiedDate = null; Image image = getImage(request, true); if (image != null) { modifiedDate = image.getModifiedDate(); } else { String path = HttpUtil.fixPath(request.getPathInfo()); String[] pathArray = StringUtil.split(path, CharPool.SLASH); if (pathArray.length == 0) { return -1; } if (pathArray[0].equals("language")) { return -1; } FileEntry fileEntry = null; try { fileEntry = getFileEntry(pathArray); } catch (Exception e) { } if (fileEntry == null) { return -1; } String version = ParamUtil.getString(request, "version"); if (Validator.isNotNull(version)) { FileVersion fileVersion = fileEntry.getFileVersion(version); modifiedDate = fileVersion.getModifiedDate(); } else { modifiedDate = fileEntry.getModifiedDate(); } } if (modifiedDate == null) { modifiedDate = PortalUtil.getUptime(); } // Round down and remove milliseconds return (modifiedDate.getTime() / 1000) * 1000; } catch (PrincipalException pe) { if (_log.isWarnEnabled()) { _log.warn(pe, pe); } } catch (Exception e) { _log.error(e, e); } return -1; } protected Image getUserPortraitImageResized(Image image, long imageId) throws PortalException { if (image == null) { return null; } int usersImageMaxHeight = _userFileUploadsSettings.getImageMaxHeight(); int usersImageMaxWidth = _userFileUploadsSettings.getImageMaxWidth(); if (((usersImageMaxHeight > 0) && (image.getHeight() > usersImageMaxHeight)) || ((usersImageMaxWidth > 0) && (image.getWidth() > usersImageMaxWidth))) { User user = UserLocalServiceUtil.getUserByPortraitId(imageId); UserLocalServiceUtil.updatePortrait( user.getUserId(), image.getTextObj()); return ImageLocalServiceUtil.getImage(imageId); } return image; } protected boolean isLegacyImageGalleryImageId( HttpServletRequest request, HttpServletResponse response) { try { long imageId = getImageId(request); if (imageId == 0) { return false; } Repository repository = RepositoryProviderUtil.getImageRepository( imageId); if (!repository.isCapabilityProvided(ThumbnailCapability.class)) { return false; } ThumbnailCapability thumbnailCapability = repository.getCapability( ThumbnailCapability.class); FileEntry fileEntry = thumbnailCapability.fetchImageFileEntry( imageId); if (fileEntry == null) { return false; } ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute( WebKeys.THEME_DISPLAY); String queryString = StringPool.BLANK; if (imageId == thumbnailCapability.getSmallImageId(fileEntry)) { queryString = "&imageThumbnail=1"; } else if (imageId == thumbnailCapability.getCustom1ImageId(fileEntry)) { queryString = "&imageThumbnail=2"; } else if (imageId == thumbnailCapability.getCustom2ImageId(fileEntry)) { queryString = "&imageThumbnail=3"; } FileVersion fileVersion = fileEntry.getFileVersion(); if (PropsValues.DL_FILE_ENTRY_IG_THUMBNAIL_GENERATION && Validator.isNotNull(queryString)) { ImageProcessorUtil.hasImages(fileVersion); } String url = DLUtil.getPreviewURL( fileEntry, fileVersion, themeDisplay, queryString); response.setHeader(HttpHeaders.LOCATION, url); response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); return true; } catch (Exception e) { } return false; } protected boolean isSupportsRangeHeader(String contentType) { return _acceptRangesMimeTypes.contains(contentType); } protected void processPrincipalException( Throwable t, User user, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (!user.isDefaultUser()) { PortalUtil.sendError( HttpServletResponse.SC_UNAUTHORIZED, (Exception)t, request, response); return; } String redirect = PortalUtil.getPathMain() + "/portal/login"; String currentURL = PortalUtil.getCurrentURL(request); redirect = HttpUtil.addParameter(redirect, "redirect", currentURL); response.sendRedirect(redirect); } protected void sendDocumentLibrary( HttpServletRequest request, HttpServletResponse response, User user, String path, String[] pathArray) throws Exception { Group group = _getGroup(user.getCompanyId(), pathArray[0]); _checkDirectoryIndexingEnabled(group); long groupId = group.getGroupId(); long folderId = DLFolderConstants.DEFAULT_PARENT_FOLDER_ID; for (int i = 1; i < pathArray.length; i++) { String name = pathArray[i]; try { Folder folder = DLAppServiceUtil.getFolder( groupId, folderId, name); folderId = folder.getFolderId(); } catch (NoSuchFolderException nsfe) { if (i != (pathArray.length - 1)) { throw nsfe; } String title = name; sendFile(response, user, groupId, folderId, title); return; } } try { sendFile(response, user, groupId, folderId, "index.html"); return; } catch (Exception e) { if (e instanceof NoSuchFileEntryException || e instanceof PrincipalException) { try { sendFile(response, user, groupId, folderId, "index.htm"); return; } catch (NoSuchFileEntryException nsfee) { // LPS-52675 if (_log.isDebugEnabled()) { _log.debug(nsfee, nsfee); } } catch (PrincipalException pe) { // LPS-52675 if (_log.isDebugEnabled()) { _log.debug(pe, pe); } } } else { throw e; } } List<WebServerEntry> webServerEntries = new ArrayList<>(); webServerEntries.add(new WebServerEntry(path, "../")); List<Folder> folders = DLAppServiceUtil.getFolders(groupId, folderId); for (Folder folder : folders) { WebServerEntry webServerEntry = new WebServerEntry( path, folder.getName() + StringPool.SLASH, folder.getCreateDate(), folder.getModifiedDate(), folder.getDescription(), 0); webServerEntries.add(webServerEntry); } List<FileEntry> fileEntries = DLAppServiceUtil.getFileEntries( groupId, folderId); for (FileEntry fileEntry : fileEntries) { WebServerEntry webServerEntry = new WebServerEntry( path, fileEntry.getTitle(), fileEntry.getCreateDate(), fileEntry.getModifiedDate(), fileEntry.getDescription(), fileEntry.getSize()); webServerEntries.add(webServerEntry); } sendHTML(response, path, webServerEntries); } protected void sendFile( HttpServletRequest request, HttpServletResponse response, User user, String[] pathArray) throws Exception { // Retrieve file details FileEntry fileEntry = getFileEntry(pathArray); if (fileEntry == null) { throw new NoSuchFileEntryException(); } if (_processCompanyInactiveRequest( request, response, fileEntry.getCompanyId())) { return; } String version = ParamUtil.getString(request, "version"); if (Validator.isNull(version)) { if (Validator.isNotNull(fileEntry.getVersion())) { version = fileEntry.getVersion(); } } String tempFileId = DLUtil.getTempFileId( fileEntry.getFileEntryId(), version); if (fileEntry.isInTrash()) { int status = ParamUtil.getInteger( request, "status", WorkflowConstants.STATUS_APPROVED); if (status != WorkflowConstants.STATUS_IN_TRASH) { throw new NoSuchFileEntryException(); } PermissionChecker permissionChecker = PermissionThreadLocal.getPermissionChecker(); String portletId = PortletProviderUtil.getPortletId( TrashEntry.class.getName(), PortletProvider.Action.VIEW); if (!PortletPermissionUtil.hasControlPanelAccessPermission( permissionChecker, fileEntry.getGroupId(), portletId)) { throw new PrincipalException.MustHavePermission( permissionChecker, FileEntry.class.getName(), fileEntry.getFileEntryId(), ActionKeys.ACCESS_IN_CONTROL_PANEL); } } FileVersion fileVersion = fileEntry.getFileVersion(version); if ((ParamUtil.getInteger(request, "height") > 0) || (ParamUtil.getInteger(request, "width") > 0)) { InputStream inputStream = fileVersion.getContentStream(true); Image image = ImageToolUtil.getImage(inputStream); writeImage(image, request, response); return; } String fileName = fileVersion.getFileName(); // Handle requested conversion boolean converted = false; String targetExtension = ParamUtil.getString( request, "targetExtension"); int imageThumbnail = ParamUtil.getInteger(request, "imageThumbnail"); int documentThumbnail = ParamUtil.getInteger( request, "documentThumbnail"); int previewFileIndex = ParamUtil.getInteger( request, "previewFileIndex"); boolean audioPreview = ParamUtil.getBoolean(request, "audioPreview"); boolean imagePreview = ParamUtil.getBoolean(request, "imagePreview"); boolean videoPreview = ParamUtil.getBoolean(request, "videoPreview"); int videoThumbnail = ParamUtil.getInteger(request, "videoThumbnail"); InputStream inputStream = null; long contentLength = 0; if ((imageThumbnail > 0) && (imageThumbnail <= 3)) { fileName = FileUtil.stripExtension(fileName).concat( StringPool.PERIOD).concat( ImageProcessorUtil.getThumbnailType(fileVersion)); int thumbnailIndex = imageThumbnail - 1; inputStream = ImageProcessorUtil.getThumbnailAsStream( fileVersion, thumbnailIndex); contentLength = ImageProcessorUtil.getThumbnailFileSize( fileVersion, thumbnailIndex); converted = true; } else if ((documentThumbnail > 0) && (documentThumbnail <= 3)) { fileName = FileUtil.stripExtension(fileName).concat( StringPool.PERIOD).concat(PDFProcessor.THUMBNAIL_TYPE); int thumbnailIndex = documentThumbnail - 1; inputStream = PDFProcessorUtil.getThumbnailAsStream( fileVersion, thumbnailIndex); contentLength = PDFProcessorUtil.getThumbnailFileSize( fileVersion, thumbnailIndex); converted = true; } else if (previewFileIndex > 0) { fileName = FileUtil.stripExtension(fileName).concat( StringPool.PERIOD).concat(PDFProcessor.PREVIEW_TYPE); inputStream = PDFProcessorUtil.getPreviewAsStream( fileVersion, previewFileIndex); contentLength = PDFProcessorUtil.getPreviewFileSize( fileVersion, previewFileIndex); converted = true; } else if (audioPreview || videoPreview) { String type = ParamUtil.getString(request, "type"); fileName = FileUtil.stripExtension(fileName).concat( StringPool.PERIOD).concat(type); if (audioPreview) { inputStream = AudioProcessorUtil.getPreviewAsStream( fileVersion, type); contentLength = AudioProcessorUtil.getPreviewFileSize( fileVersion, type); } else { inputStream = VideoProcessorUtil.getPreviewAsStream( fileVersion, type); contentLength = VideoProcessorUtil.getPreviewFileSize( fileVersion, type); } converted = true; } else if (imagePreview) { String type = ImageProcessorUtil.getPreviewType(fileVersion); fileName = FileUtil.stripExtension(fileName).concat( StringPool.PERIOD).concat(type); inputStream = ImageProcessorUtil.getPreviewAsStream(fileVersion); contentLength = ImageProcessorUtil.getPreviewFileSize(fileVersion); converted = true; } else if ((videoThumbnail > 0) && (videoThumbnail <= 3)) { fileName = FileUtil.stripExtension(fileName).concat( StringPool.PERIOD).concat(VideoProcessor.THUMBNAIL_TYPE); int thumbnailIndex = videoThumbnail - 1; inputStream = VideoProcessorUtil.getThumbnailAsStream( fileVersion, thumbnailIndex); contentLength = VideoProcessorUtil.getThumbnailFileSize( fileVersion, thumbnailIndex); converted = true; } else { inputStream = fileVersion.getContentStream(true); contentLength = fileVersion.getSize(); if (Validator.isNotNull(targetExtension)) { File convertedFile = DocumentConversionUtil.convert( tempFileId, inputStream, fileVersion.getExtension(), targetExtension); if (convertedFile != null) { fileName = FileUtil.stripExtension(fileName).concat( StringPool.PERIOD).concat(targetExtension); inputStream = new FileInputStream(convertedFile); contentLength = convertedFile.length(); converted = true; } } } FlashMagicBytesUtil.Result flashMagicBytesUtilResult = FlashMagicBytesUtil.check(inputStream); if (flashMagicBytesUtilResult.isFlash()) { fileName = FileUtil.stripExtension(fileName) + ".swf"; } inputStream = flashMagicBytesUtilResult.getInputStream(); // Determine proper content type String contentType = null; if (converted) { contentType = MimeTypesUtil.getContentType(fileName); } else { contentType = fileVersion.getMimeType(); } if (_log.isDebugEnabled()) { _log.debug("Content type set to " + contentType); } // Send file if (isSupportsRangeHeader(contentType)) { ServletResponseUtil.sendFileWithRangeHeader( request, response, fileName, inputStream, contentLength, contentType); } else { boolean download = ParamUtil.getBoolean(request, "download"); if (download) { ServletResponseUtil.sendFile( request, response, fileName, inputStream, contentLength, contentType, HttpHeaders.CONTENT_DISPOSITION_ATTACHMENT); } else { ServletResponseUtil.sendFile( request, response, fileName, inputStream, contentLength, contentType); } } } protected void sendFile( HttpServletResponse response, User user, long groupId, long folderId, String title) throws Exception { FileEntry fileEntry = DLAppServiceUtil.getFileEntry( groupId, folderId, title); String contentType = fileEntry.getMimeType(); response.setContentType(contentType); InputStream inputStream = fileEntry.getContentStream(); ServletResponseUtil.write(response, inputStream, fileEntry.getSize()); } protected void sendGroups( HttpServletResponse response, User user, String path) throws Exception { if (!PropsValues.WEB_SERVER_SERVLET_DIRECTORY_INDEXING_ENABLED) { response.setStatus(HttpServletResponse.SC_FORBIDDEN); throw new PrincipalException(); } List<WebServerEntry> webServerEntries = new ArrayList<>(); List<Group> groups = WebDAVUtil.getGroups(user); for (Group group : groups) { if (_isDirectoryIndexingEnabled(group)) { String name = HttpUtil.fixPath(group.getFriendlyURL()); WebServerEntry webServerEntry = new WebServerEntry( path, name + StringPool.SLASH, null, null, group.getDescription(), 0); webServerEntries.add(webServerEntry); } } sendHTML(response, path, webServerEntries); } protected void sendHTML( HttpServletResponse response, String path, List<WebServerEntry> webServerEntries) throws Exception { Template template = TemplateManagerUtil.getTemplate( TemplateConstants.LANG_TYPE_FTL, _templateResource, true); template.put("dateFormat", _dateFormat); template.put("entries", webServerEntries); template.put("path", HttpUtil.encodePath(path)); if (_WEB_SERVER_SERVLET_VERSION_VERBOSITY_DEFAULT) { } else if (_WEB_SERVER_SERVLET_VERSION_VERBOSITY_PARTIAL) { template.put("releaseInfo", ReleaseInfo.getName()); } else { template.put("releaseInfo", ReleaseInfo.getReleaseInfo()); } template.put("validator", Validator_IW.getInstance()); response.setContentType(ContentTypes.TEXT_HTML_UTF8); template.processTemplate(response.getWriter()); } protected void sendPortletFileEntry( HttpServletRequest request, HttpServletResponse response, String[] pathArray) throws Exception { FileEntry fileEntry = getPortletFileEntry(request, pathArray); if (fileEntry == null) { return; } if (_processCompanyInactiveRequest( request, response, fileEntry.getCompanyId())) { return; } String fileName = HttpUtil.decodeURL(HtmlUtil.escape(pathArray[2])); if (fileEntry.isInTrash()) { fileName = TrashUtil.getOriginalTitle(fileName); } boolean download = ParamUtil.getBoolean(request, "download"); if (download) { ServletResponseUtil.sendFile( request, response, fileName, fileEntry.getContentStream(), fileEntry.getSize(), fileEntry.getMimeType(), HttpHeaders.CONTENT_DISPOSITION_ATTACHMENT); } else { InputStream is = fileEntry.getContentStream(); FlashMagicBytesUtil.Result flashMagicBytesUtilResult = FlashMagicBytesUtil.check(is); is = flashMagicBytesUtilResult.getInputStream(); if (flashMagicBytesUtilResult.isFlash()) { fileName = FileUtil.stripExtension(fileName) + ".swf"; } ServletResponseUtil.sendFile( request, response, fileName, is, fileEntry.getSize(), fileEntry.getMimeType()); } } protected void writeImage( Image image, HttpServletRequest request, HttpServletResponse response) throws PortalException { if (image == null) { return; } String contentType = null; String type = image.getType(); if (!type.equals(ImageConstants.TYPE_NOT_AVAILABLE)) { contentType = MimeTypesUtil.getExtensionContentType(type); response.setContentType(contentType); } String fileName = ParamUtil.getString(request, "fileName"); byte[] bytes = getImageBytes(request, image); try { if (Validator.isNotNull(fileName)) { ServletResponseUtil.sendFile( request, response, fileName, bytes, contentType); } else { ServletResponseUtil.write(response, bytes); } } catch (Exception e) { if (_log.isWarnEnabled()) { _log.warn(e, e); } } } private static void _checkDirectoryIndexingEnabled(Group group) throws Exception { if (!_isDirectoryIndexingEnabled(group)) { if (_log.isDebugEnabled()) { _log.debug( "Directory indexing is not enabled for group " + group.getGroupId()); } throw new NoSuchFolderException(); } } private static void _checkFileEntry(String[] pathArray) throws Exception { if (pathArray.length == 1) { long fileShortcutId = GetterUtil.getLong(pathArray[0]); FileShortcut fileShortcut = DLAppLocalServiceUtil.getFileShortcut( fileShortcutId); DLAppLocalServiceUtil.getFileEntry(fileShortcut.getToFileEntryId()); } else if (pathArray.length == 2) { // Unable to check with UUID because of multiple repositories } else if (pathArray.length == 3) { long groupId = GetterUtil.getLong(pathArray[0]); long folderId = GetterUtil.getLong(pathArray[1]); String fileName = HttpUtil.decodeURL(pathArray[2]); try { DLAppLocalServiceUtil.getFileEntry(groupId, folderId, fileName); } catch (RepositoryException re) { // LPS-52675 if (_log.isDebugEnabled()) { _log.debug(re, re); } } } else { long groupId = GetterUtil.getLong(pathArray[0]); String uuid = pathArray[3]; try { DLAppLocalServiceUtil.getFileEntryByUuidAndGroupId( uuid, groupId); } catch (RepositoryException re) { // LPS-52675 if (_log.isDebugEnabled()) { _log.debug(re, re); } } } } private static Group _getGroup(long companyId, String name) throws Exception { Group group = GroupLocalServiceUtil.fetchFriendlyURLGroup( companyId, StringPool.SLASH + name); if (group != null) { return group; } User user = UserLocalServiceUtil.getUserByScreenName(companyId, name); group = user.getGroup(); return group; } private static User _getUser(HttpServletRequest request) throws Exception { HttpSession session = request.getSession(); if (PortalSessionThreadLocal.getHttpSession() == null) { PortalSessionThreadLocal.setHttpSession(session); } User user = PortalUtil.getUser(request); if (user != null) { return user; } String userIdString = (String)session.getAttribute("j_username"); String password = (String)session.getAttribute("j_password"); if ((userIdString != null) && (password != null)) { long userId = GetterUtil.getLong(userIdString); user = UserLocalServiceUtil.getUser(userId); } else { long companyId = PortalUtil.getCompanyId(request); Company company = CompanyLocalServiceUtil.getCompany(companyId); user = company.getDefaultUser(); } return user; } private static boolean _isDirectoryIndexingEnabled(Group group) { UnicodeProperties typeSettingsProperties = group.getTypeSettingsProperties(); return GetterUtil.getBoolean( typeSettingsProperties.getProperty("directoryIndexingEnabled"), PropsValues.WEB_SERVER_SERVLET_DIRECTORY_INDEXING_ENABLED); } private Callable<Void> _createFileServingCallable( final HttpServletRequest request, final HttpServletResponse response, final User user) { return new Callable<Void>() { @Override public Void call() throws Exception { String path = HttpUtil.fixPath(request.getPathInfo()); String[] pathArray = StringUtil.split(path, CharPool.SLASH); if (pathArray.length == 0) { sendGroups( response, user, request.getServletPath() + StringPool.SLASH + path); } else { if (Validator.isNumber(pathArray[0])) { sendFile(request, response, user, pathArray); } else if (PATH_PORTLET_FILE_ENTRY.equals(pathArray[0])) { sendPortletFileEntry(request, response, pathArray); } else { if (PropsValues. WEB_SERVER_SERVLET_CHECK_IMAGE_GALLERY) { if (isLegacyImageGalleryImageId( request, response)) { return null; } } Image image = getImage(request, true); if (image != null) { if ((image.getCompanyId() != user.getCompanyId()) && _processCompanyInactiveRequest( request, response, image.getCompanyId())) { return null; } writeImage(image, request, response); } else { sendDocumentLibrary( request, response, user, request.getServletPath() + StringPool.SLASH + path, pathArray); } } } return null; } }; } private boolean _processCompanyInactiveRequest( HttpServletRequest request, HttpServletResponse response, long companyId) throws IOException { if ((companyId == CompanyConstants.SYSTEM) || PortalInstances.isCompanyActive(companyId)) { return false; } _inactiveRequesthandler.processInactiveRequest( request, response, "this-instance-is-inactive-please-contact-the-administrator"); if (_log.isDebugEnabled()) { _log.debug("Processed company inactive request"); } return true; } private static final boolean _WEB_SERVER_SERVLET_VERSION_VERBOSITY_DEFAULT = StringUtil.equalsIgnoreCase( PropsValues.WEB_SERVER_SERVLET_VERSION_VERBOSITY, ReleaseInfo.getName()); private static final boolean _WEB_SERVER_SERVLET_VERSION_VERBOSITY_PARTIAL = StringUtil.equalsIgnoreCase( PropsValues.WEB_SERVER_SERVLET_VERSION_VERBOSITY, "partial"); private static final Log _log = LogFactoryUtil.getLog( WebServerServlet.class); private static final Set<String> _acceptRangesMimeTypes = SetUtil.fromArray( PropsValues.WEB_SERVER_SERVLET_ACCEPT_RANGES_MIME_TYPES); private static volatile InactiveRequestHandler _inactiveRequesthandler = ServiceProxyFactory.newServiceTrackedInstance( InactiveRequestHandler.class, WebServerServlet.class, "_inactiveRequesthandler", false); private static volatile UserFileUploadsSettings _userFileUploadsSettings = ServiceProxyFactory.newServiceTrackedInstance( UserFileUploadsSettings.class, WebServerServlet.class, "_userFileUploadsSettings", false); private final Format _dateFormat = FastDateFormatFactoryUtil.getSimpleDateFormat("d MMM yyyy HH:mm z"); private boolean _lastModified = true; private TemplateResource _templateResource; }