001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.webserver;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.image.ImageBag;
020    import com.liferay.portal.kernel.image.ImageToolUtil;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.repository.RepositoryException;
024    import com.liferay.portal.kernel.repository.model.FileEntry;
025    import com.liferay.portal.kernel.repository.model.FileVersion;
026    import com.liferay.portal.kernel.repository.model.Folder;
027    import com.liferay.portal.kernel.servlet.HttpHeaders;
028    import com.liferay.portal.kernel.servlet.PortalSessionThreadLocal;
029    import com.liferay.portal.kernel.servlet.Range;
030    import com.liferay.portal.kernel.servlet.ServletResponseUtil;
031    import com.liferay.portal.kernel.template.Template;
032    import com.liferay.portal.kernel.template.TemplateConstants;
033    import com.liferay.portal.kernel.template.TemplateManagerUtil;
034    import com.liferay.portal.kernel.template.TemplateResource;
035    import com.liferay.portal.kernel.template.URLTemplateResource;
036    import com.liferay.portal.kernel.util.CharPool;
037    import com.liferay.portal.kernel.util.ContentTypes;
038    import com.liferay.portal.kernel.util.DigesterUtil;
039    import com.liferay.portal.kernel.util.FastDateFormatFactoryUtil;
040    import com.liferay.portal.kernel.util.FileUtil;
041    import com.liferay.portal.kernel.util.GetterUtil;
042    import com.liferay.portal.kernel.util.HtmlUtil;
043    import com.liferay.portal.kernel.util.HttpUtil;
044    import com.liferay.portal.kernel.util.MimeTypesUtil;
045    import com.liferay.portal.kernel.util.ParamUtil;
046    import com.liferay.portal.kernel.util.ReleaseInfo;
047    import com.liferay.portal.kernel.util.SetUtil;
048    import com.liferay.portal.kernel.util.StringPool;
049    import com.liferay.portal.kernel.util.StringUtil;
050    import com.liferay.portal.kernel.util.UnicodeProperties;
051    import com.liferay.portal.kernel.util.Validator;
052    import com.liferay.portal.kernel.util.Validator_IW;
053    import com.liferay.portal.kernel.webdav.WebDAVUtil;
054    import com.liferay.portal.kernel.workflow.WorkflowConstants;
055    import com.liferay.portal.model.Company;
056    import com.liferay.portal.model.Group;
057    import com.liferay.portal.model.Image;
058    import com.liferay.portal.model.ImageConstants;
059    import com.liferay.portal.model.User;
060    import com.liferay.portal.model.impl.ImageImpl;
061    import com.liferay.portal.portletfilerepository.PortletFileRepositoryUtil;
062    import com.liferay.portal.repository.liferayrepository.model.LiferayFileEntry;
063    import com.liferay.portal.repository.liferayrepository.model.LiferayFileVersion;
064    import com.liferay.portal.security.auth.PrincipalException;
065    import com.liferay.portal.security.auth.PrincipalThreadLocal;
066    import com.liferay.portal.security.permission.PermissionChecker;
067    import com.liferay.portal.security.permission.PermissionCheckerFactoryUtil;
068    import com.liferay.portal.security.permission.PermissionThreadLocal;
069    import com.liferay.portal.service.CompanyLocalServiceUtil;
070    import com.liferay.portal.service.GroupLocalServiceUtil;
071    import com.liferay.portal.service.ImageLocalServiceUtil;
072    import com.liferay.portal.service.ImageServiceUtil;
073    import com.liferay.portal.service.UserLocalServiceUtil;
074    import com.liferay.portal.service.permission.PortletPermissionUtil;
075    import com.liferay.portal.theme.ThemeDisplay;
076    import com.liferay.portal.util.PortalUtil;
077    import com.liferay.portal.util.PortletKeys;
078    import com.liferay.portal.util.PropsValues;
079    import com.liferay.portal.util.WebKeys;
080    import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
081    import com.liferay.portlet.documentlibrary.NoSuchFolderException;
082    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
083    import com.liferay.portlet.documentlibrary.model.DLFileShortcut;
084    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
085    import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
086    import com.liferay.portlet.documentlibrary.service.DLAppServiceUtil;
087    import com.liferay.portlet.documentlibrary.service.DLFileEntryServiceUtil;
088    import com.liferay.portlet.documentlibrary.util.AudioProcessorUtil;
089    import com.liferay.portlet.documentlibrary.util.DLUtil;
090    import com.liferay.portlet.documentlibrary.util.DocumentConversionUtil;
091    import com.liferay.portlet.documentlibrary.util.ImageProcessorUtil;
092    import com.liferay.portlet.documentlibrary.util.PDFProcessor;
093    import com.liferay.portlet.documentlibrary.util.PDFProcessorUtil;
094    import com.liferay.portlet.documentlibrary.util.VideoProcessor;
095    import com.liferay.portlet.documentlibrary.util.VideoProcessorUtil;
096    import com.liferay.portlet.trash.util.TrashUtil;
097    
098    import java.awt.image.RenderedImage;
099    
100    import java.io.File;
101    import java.io.FileInputStream;
102    import java.io.IOException;
103    import java.io.InputStream;
104    
105    import java.net.URL;
106    
107    import java.text.Format;
108    
109    import java.util.ArrayList;
110    import java.util.Date;
111    import java.util.List;
112    import java.util.Set;
113    
114    import javax.servlet.ServletConfig;
115    import javax.servlet.ServletException;
116    import javax.servlet.http.HttpServlet;
117    import javax.servlet.http.HttpServletRequest;
118    import javax.servlet.http.HttpServletResponse;
119    import javax.servlet.http.HttpSession;
120    
121    /**
122     * @author Alexander Chow
123     * @author Brian Wing Shun Chan
124     */
125    public class WebServerServlet extends HttpServlet {
126    
127            public static final String PATH_PORTLET_FILE_ENTRY = "portlet_file_entry";
128    
129            /**
130             * @see com.liferay.portal.servlet.filters.virtualhost.VirtualHostFilter
131             */
132            public static boolean hasFiles(HttpServletRequest request) {
133                    try {
134    
135                            // Do not use permission checking since this may be called from
136                            // other contexts that are also managing the principal
137    
138                            User user = _getUser(request);
139    
140                            String path = HttpUtil.fixPath(request.getPathInfo());
141    
142                            String[] pathArray = StringUtil.split(path, CharPool.SLASH);
143    
144                            if (pathArray.length == 0) {
145                                    return true;
146                            }
147                            else if (Validator.isNumber(pathArray[0])) {
148                                    _checkFileEntry(pathArray);
149                            }
150                            else if (PATH_PORTLET_FILE_ENTRY.equals(pathArray[0])) {
151                                    FileEntry fileEntry = getPortletFileEntry(request, pathArray);
152    
153                                    if (fileEntry != null) {
154                                            return true;
155                                    }
156                            }
157                            else {
158                                    long groupId = _getGroupId(user.getCompanyId(), pathArray[0]);
159                                    long folderId = DLFolderConstants.DEFAULT_PARENT_FOLDER_ID;
160    
161                                    for (int i = 1; i < pathArray.length; i++) {
162                                            try {
163                                                    Folder folder = DLAppLocalServiceUtil.getFolder(
164                                                            groupId, folderId, pathArray[i]);
165    
166                                                    folderId = folder.getFolderId();
167                                            }
168                                            catch (NoSuchFolderException nsfe) {
169                                                    if (i != (pathArray.length - 1)) {
170                                                            return false;
171                                                    }
172    
173                                                    pathArray = new String[] {
174                                                            String.valueOf(groupId), String.valueOf(folderId),
175                                                            pathArray[i]
176                                                    };
177    
178                                                    _checkFileEntry(pathArray);
179                                            }
180                                    }
181                            }
182                    }
183                    catch (Exception e) {
184                            return false;
185                    }
186    
187                    return true;
188            }
189    
190            @Override
191            public void init(ServletConfig servletConfig) throws ServletException {
192                    super.init(servletConfig);
193    
194                    _lastModified = GetterUtil.getBoolean(
195                            servletConfig.getInitParameter("last_modified"), true);
196    
197                    Class<?> clazz = getClass();
198    
199                    ClassLoader classLoader = clazz.getClassLoader();
200    
201                    String templateId =
202                            "com/liferay/portal/webserver/dependencies/template.ftl";
203    
204                    URL url = classLoader.getResource(templateId);
205    
206                    _templateResource = new URLTemplateResource(templateId, url);
207            }
208    
209            @Override
210            public void service(
211                            HttpServletRequest request, HttpServletResponse response)
212                    throws IOException, ServletException {
213    
214                    User user = null;
215    
216                    try {
217                            user = _getUser(request);
218    
219                            PrincipalThreadLocal.setName(user.getUserId());
220                            PrincipalThreadLocal.setPassword(
221                                    PortalUtil.getUserPassword(request));
222    
223                            PermissionChecker permissionChecker =
224                                    PermissionCheckerFactoryUtil.create(user);
225    
226                            PermissionThreadLocal.setPermissionChecker(permissionChecker);
227    
228                            if (_lastModified) {
229                                    long lastModified = getLastModified(request);
230    
231                                    if (lastModified > 0) {
232                                            long ifModifiedSince = request.getDateHeader(
233                                                    HttpHeaders.IF_MODIFIED_SINCE);
234    
235                                            if ((ifModifiedSince > 0) &&
236                                                    (ifModifiedSince == lastModified)) {
237    
238                                                    response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
239    
240                                                    return;
241                                            }
242                                    }
243    
244                                    if (lastModified > 0) {
245                                            response.setDateHeader(
246                                                    HttpHeaders.LAST_MODIFIED, lastModified);
247                                    }
248                            }
249    
250                            String path = HttpUtil.fixPath(request.getPathInfo());
251                            String[] pathArray = StringUtil.split(path, CharPool.SLASH);
252    
253                            if (pathArray.length == 0) {
254                                    sendGroups(
255                                            response, user,
256                                            request.getServletPath() + StringPool.SLASH + path);
257                            }
258                            else {
259                                    if (Validator.isNumber(pathArray[0])) {
260                                            sendFile(request, response, user, pathArray);
261                                    }
262                                    else if (PATH_PORTLET_FILE_ENTRY.equals(pathArray[0])) {
263                                            sendPortletFileEntry(request, response, pathArray);
264                                    }
265                                    else {
266                                            if (PropsValues.WEB_SERVER_SERVLET_CHECK_IMAGE_GALLERY) {
267                                                    if (isLegacyImageGalleryImageId(request, response)) {
268                                                            return;
269                                                    }
270                                            }
271    
272                                            Image image = getImage(request, true);
273    
274                                            if (image != null) {
275                                                    writeImage(image, request, response);
276                                            }
277                                            else {
278                                                    sendDocumentLibrary(
279                                                            request, response, user,
280                                                            request.getServletPath() + StringPool.SLASH + path,
281                                                            pathArray);
282                                            }
283                                    }
284                            }
285                    }
286                    catch (NoSuchFileEntryException nsfee) {
287                            PortalUtil.sendError(
288                                    HttpServletResponse.SC_NOT_FOUND, nsfee, request, response);
289                    }
290                    catch (NoSuchFolderException nsfe) {
291                            PortalUtil.sendError(
292                                    HttpServletResponse.SC_NOT_FOUND, nsfe, request, response);
293                    }
294                    catch (PrincipalException pe) {
295                            processPrincipalException(pe, user, request, response);
296                    }
297                    catch (Exception e) {
298                            PortalUtil.sendError(e, request, response);
299                    }
300            }
301    
302            protected static FileEntry getPortletFileEntry(
303                            HttpServletRequest request, String[] pathArray)
304                    throws Exception {
305    
306                    long groupId = GetterUtil.getLong(pathArray[1]);
307                    String uuid = pathArray[3];
308    
309                    FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
310                            uuid, groupId);
311    
312                    DLFileEntry dlFileEntry = (DLFileEntry)fileEntry.getModel();
313    
314                    int status = ParamUtil.getInteger(
315                            request, "status", WorkflowConstants.STATUS_APPROVED);
316    
317                    if ((status != WorkflowConstants.STATUS_IN_TRASH) &&
318                            dlFileEntry.isInTrash()) {
319    
320                            return null;
321                    }
322    
323                    return fileEntry;
324            }
325    
326            protected Image convertFileEntry(boolean smallImage, FileEntry fileEntry)
327                    throws PortalException {
328    
329                    try {
330                            Image image = new ImageImpl();
331    
332                            image.setModifiedDate(fileEntry.getModifiedDate());
333    
334                            InputStream is = null;
335    
336                            if (smallImage) {
337                                    is = ImageProcessorUtil.getThumbnailAsStream(
338                                            fileEntry.getFileVersion(), 0);
339                            }
340                            else {
341                                    is = fileEntry.getContentStream();
342                            }
343    
344                            byte[] bytes = FileUtil.getBytes(is);
345    
346                            image.setTextObj(bytes);
347    
348                            image.setType(fileEntry.getExtension());
349    
350                            return image;
351                    }
352                    catch (PortalException pe) {
353                            throw pe;
354                    }
355                    catch (SystemException se) {
356                            throw se;
357                    }
358                    catch (Exception e) {
359                            throw new SystemException(e);
360                    }
361            }
362    
363            protected Image getDefaultImage(HttpServletRequest request, long imageId) {
364                    String path = GetterUtil.getString(request.getPathInfo());
365    
366                    if (path.startsWith("/company_logo") ||
367                            path.startsWith("/layout_set_logo") || path.startsWith("/logo")) {
368    
369                            return ImageToolUtil.getDefaultCompanyLogo();
370                    }
371                    else if (path.startsWith("/organization_logo")) {
372                            return ImageToolUtil.getDefaultOrganizationLogo();
373                    }
374                    else if (path.startsWith("/user_female_portrait")) {
375                            return ImageToolUtil.getDefaultUserFemalePortrait();
376                    }
377                    else if (path.startsWith("/user_male_portrait")) {
378                            return ImageToolUtil.getDefaultUserMalePortrait();
379                    }
380                    else if (path.startsWith("/user_portrait")) {
381                            return ImageToolUtil.getDefaultUserMalePortrait();
382                    }
383                    else {
384                            return null;
385                    }
386            }
387    
388            protected FileEntry getFileEntry(String[] pathArray) throws Exception {
389                    if (pathArray.length == 1) {
390                            long dlFileShortcutId = GetterUtil.getLong(pathArray[0]);
391    
392                            DLFileShortcut dlFileShortcut = DLAppServiceUtil.getFileShortcut(
393                                    dlFileShortcutId);
394    
395                            return DLAppServiceUtil.getFileEntry(
396                                    dlFileShortcut.getToFileEntryId());
397                    }
398                    else if (pathArray.length == 2) {
399                            long groupId = GetterUtil.getLong(pathArray[0]);
400    
401                            return DLAppServiceUtil.getFileEntryByUuidAndGroupId(
402                                    pathArray[1], groupId);
403                    }
404                    else if (pathArray.length == 3) {
405                            long groupId = GetterUtil.getLong(pathArray[0]);
406                            long folderId = GetterUtil.getLong(pathArray[1]);
407                            String fileName = HttpUtil.decodeURL(pathArray[2]);
408    
409                            if (fileName.contains(StringPool.QUESTION)) {
410                                    fileName = fileName.substring(
411                                            0, fileName.indexOf(StringPool.QUESTION));
412                            }
413    
414                            return DLAppServiceUtil.getFileEntry(groupId, folderId, fileName);
415                    }
416                    else {
417                            long groupId = GetterUtil.getLong(pathArray[0]);
418    
419                            String uuid = pathArray[3];
420    
421                            return DLAppServiceUtil.getFileEntryByUuidAndGroupId(uuid, groupId);
422                    }
423            }
424    
425            protected Image getImage(HttpServletRequest request, boolean getDefault)
426                    throws PortalException {
427    
428                    Image image = null;
429    
430                    long imageId = getImageId(request);
431    
432                    if (imageId > 0) {
433                            image = ImageServiceUtil.getImage(imageId);
434    
435                            String path = GetterUtil.getString(request.getPathInfo());
436    
437                            if (path.startsWith("/user_female_portrait") ||
438                                    path.startsWith("/user_male_portrait") ||
439                                    path.startsWith("/user_portrait")) {
440    
441                                    image = getUserPortraitImageResized(image, imageId);
442                            }
443                    }
444                    else {
445                            String uuid = ParamUtil.getString(request, "uuid");
446                            long groupId = ParamUtil.getLong(request, "groupId");
447                            boolean igSmallImage = ParamUtil.getBoolean(
448                                    request, "igSmallImage");
449    
450                            if (Validator.isNotNull(uuid) && (groupId > 0)) {
451                                    try {
452                                            FileEntry fileEntry =
453                                                    DLAppServiceUtil.getFileEntryByUuidAndGroupId(
454                                                            uuid, groupId);
455    
456                                            image = convertFileEntry(igSmallImage, fileEntry);
457                                    }
458                                    catch (Exception e) {
459                                    }
460                            }
461                    }
462    
463                    if (getDefault) {
464                            if (image == null) {
465                                    if (_log.isWarnEnabled()) {
466                                            _log.warn("Get a default image for " + imageId);
467                                    }
468    
469                                    image = getDefaultImage(request, imageId);
470                            }
471                    }
472    
473                    return image;
474            }
475    
476            protected byte[] getImageBytes(HttpServletRequest request, Image image) {
477                    try {
478                            if (!PropsValues.IMAGE_AUTO_SCALE) {
479                                    return image.getTextObj();
480                            }
481    
482                            ImageBag imageBag = null;
483    
484                            if (image.getImageId() == 0) {
485                                    imageBag = ImageToolUtil.read(image.getTextObj());
486    
487                                    RenderedImage renderedImage = imageBag.getRenderedImage();
488    
489                                    image.setHeight(renderedImage.getHeight());
490                                    image.setWidth(renderedImage.getWidth());
491                            }
492    
493                            int height = ParamUtil.getInteger(
494                                    request, "height", image.getHeight());
495                            int width = ParamUtil.getInteger(
496                                    request, "width", image.getWidth());
497    
498                            if ((height >= image.getHeight()) && (width >= image.getWidth())) {
499                                    return image.getTextObj();
500                            }
501    
502                            if (image.getImageId() != 0) {
503                                    imageBag = ImageToolUtil.read(image.getTextObj());
504                            }
505    
506                            RenderedImage renderedImage = ImageToolUtil.scale(
507                                    imageBag.getRenderedImage(), height, width);
508    
509                            return ImageToolUtil.getBytes(renderedImage, imageBag.getType());
510                    }
511                    catch (Exception e) {
512                            if (_log.isWarnEnabled()) {
513                                    _log.warn("Error scaling image " + image.getImageId(), e);
514                            }
515                    }
516    
517                    return image.getTextObj();
518            }
519    
520            protected long getImageId(HttpServletRequest request) {
521    
522                    // The image id may be passed in as image_id, img_id, or i_id
523    
524                    long imageId = ParamUtil.getLong(request, "image_id");
525    
526                    if (imageId <= 0) {
527                            imageId = ParamUtil.getLong(request, "img_id");
528                    }
529    
530                    if (imageId <= 0) {
531                            imageId = ParamUtil.getLong(request, "i_id");
532                    }
533    
534                    User user = null;
535    
536                    if (imageId <= 0) {
537                            long companyId = ParamUtil.getLong(request, "companyId");
538                            String screenName = ParamUtil.getString(request, "screenName");
539    
540                            if ((companyId > 0) && Validator.isNotNull(screenName)) {
541                                    user = UserLocalServiceUtil.fetchUserByScreenName(
542                                            companyId, screenName);
543    
544                                    if (user != null) {
545                                            imageId = user.getPortraitId();
546                                    }
547                            }
548                    }
549    
550                    if (PropsValues.USERS_IMAGE_CHECK_TOKEN && (imageId > 0)) {
551                            String imageIdToken = ParamUtil.getString(request, "img_id_token");
552    
553                            if (user == null) {
554                                    user = UserLocalServiceUtil.fetchUserByPortraitId(imageId);
555                            }
556    
557                            if ((user != null) &&
558                                    !imageIdToken.equals(DigesterUtil.digest(user.getUserUuid()))) {
559    
560                                    return 0;
561                            }
562                    }
563    
564                    return imageId;
565            }
566    
567            @Override
568            protected long getLastModified(HttpServletRequest request) {
569                    try {
570                            Date modifiedDate = null;
571    
572                            Image image = getImage(request, true);
573    
574                            if (image != null) {
575                                    modifiedDate = image.getModifiedDate();
576                            }
577                            else {
578                                    String path = HttpUtil.fixPath(request.getPathInfo());
579    
580                                    String[] pathArray = StringUtil.split(path, CharPool.SLASH);
581    
582                                    if (pathArray.length == 0) {
583                                            return -1;
584                                    }
585    
586                                    if (pathArray[0].equals("language")) {
587                                            return -1;
588                                    }
589    
590                                    FileEntry fileEntry = null;
591    
592                                    try {
593                                            fileEntry = getFileEntry(pathArray);
594                                    }
595                                    catch (Exception e) {
596                                    }
597    
598                                    if (fileEntry == null) {
599                                            return -1;
600                                    }
601    
602                                    String version = ParamUtil.getString(request, "version");
603    
604                                    if (Validator.isNotNull(version)) {
605                                            FileVersion fileVersion = fileEntry.getFileVersion(version);
606    
607                                            modifiedDate = fileVersion.getModifiedDate();
608                                    }
609                                    else {
610                                            modifiedDate = fileEntry.getModifiedDate();
611                                    }
612                            }
613    
614                            if (modifiedDate == null) {
615                                    modifiedDate = PortalUtil.getUptime();
616                            }
617    
618                            // Round down and remove milliseconds
619    
620                            return (modifiedDate.getTime() / 1000) * 1000;
621                    }
622                    catch (PrincipalException pe) {
623                            if (_log.isWarnEnabled()) {
624                                    _log.warn(pe, pe);
625                            }
626                    }
627                    catch (Exception e) {
628                            _log.error(e, e);
629                    }
630    
631                    return -1;
632            }
633    
634            protected Image getUserPortraitImageResized(Image image, long imageId)
635                    throws PortalException {
636    
637                    if (image == null) {
638                            return null;
639                    }
640    
641                    if (((PropsValues.USERS_IMAGE_MAX_HEIGHT > 0) &&
642                             (image.getHeight() > PropsValues.USERS_IMAGE_MAX_HEIGHT)) ||
643                            ((PropsValues.USERS_IMAGE_MAX_WIDTH > 0) &&
644                             (image.getWidth() > PropsValues.USERS_IMAGE_MAX_WIDTH))) {
645    
646                            User user = UserLocalServiceUtil.getUserByPortraitId(imageId);
647    
648                            UserLocalServiceUtil.updatePortrait(
649                                    user.getUserId(), image.getTextObj());
650    
651                            return ImageLocalServiceUtil.getImage(imageId);
652                    }
653    
654                    return image;
655            }
656    
657            protected boolean isLegacyImageGalleryImageId(
658                    HttpServletRequest request, HttpServletResponse response) {
659    
660                    try {
661                            long imageId = getImageId(request);
662    
663                            if (imageId == 0) {
664                                    return false;
665                            }
666    
667                            DLFileEntry dlFileEntry =
668                                    DLFileEntryServiceUtil.fetchFileEntryByImageId(imageId);
669    
670                            if (dlFileEntry == null) {
671                                    return false;
672                            }
673    
674                            ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
675                                    WebKeys.THEME_DISPLAY);
676    
677                            String queryString = StringPool.BLANK;
678    
679                            if (imageId == dlFileEntry.getSmallImageId()) {
680                                    queryString = "&imageThumbnail=1";
681                            }
682                            else if (imageId == dlFileEntry.getCustom1ImageId()) {
683                                    queryString = "&imageThumbnail=2";
684                            }
685                            else if (imageId == dlFileEntry.getCustom2ImageId()) {
686                                    queryString = "&imageThumbnail=3";
687                            }
688    
689                            FileEntry fileEntry = new LiferayFileEntry(dlFileEntry);
690    
691                            FileVersion fileVersion = new LiferayFileVersion(
692                                    dlFileEntry.getFileVersion());
693    
694                            if (PropsValues.DL_FILE_ENTRY_IG_THUMBNAIL_GENERATION &&
695                                    Validator.isNotNull(queryString)) {
696    
697                                    ImageProcessorUtil.hasImages(fileVersion);
698                            }
699    
700                            String url = DLUtil.getPreviewURL(
701                                    fileEntry, fileVersion, themeDisplay, queryString);
702    
703                            response.setHeader(HttpHeaders.LOCATION, url);
704                            response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
705    
706                            return true;
707                    }
708                    catch (Exception e) {
709                    }
710    
711                    return false;
712            }
713    
714            protected boolean isSupportsRangeHeader(String contentType) {
715                    return _acceptRangesMimeTypes.contains(contentType);
716            }
717    
718            protected void processPrincipalException(
719                            Throwable t, User user, HttpServletRequest request,
720                            HttpServletResponse response)
721                    throws IOException, ServletException {
722    
723                    if (!user.isDefaultUser()) {
724                            PortalUtil.sendError(
725                                    HttpServletResponse.SC_UNAUTHORIZED, (Exception)t, request,
726                                    response);
727    
728                            return;
729                    }
730    
731                    String redirect = PortalUtil.getPathMain() + "/portal/login";
732    
733                    String currentURL = PortalUtil.getCurrentURL(request);
734    
735                    redirect = HttpUtil.addParameter(redirect, "redirect", currentURL);
736    
737                    response.sendRedirect(redirect);
738            }
739    
740            protected void sendDocumentLibrary(
741                            HttpServletRequest request, HttpServletResponse response, User user,
742                            String path, String[] pathArray)
743                    throws Exception {
744    
745                    long groupId = _getGroupId(user.getCompanyId(), pathArray[0]);
746    
747                    Group group = GroupLocalServiceUtil.getGroup(groupId);
748    
749                    UnicodeProperties typeSettingsProperties =
750                            group.getTypeSettingsProperties();
751    
752                    boolean directoryIndexingEnabled = GetterUtil.getBoolean(
753                            typeSettingsProperties.getProperty("directoryIndexingEnabled"),
754                            PropsValues.WEB_SERVER_SERVLET_DIRECTORY_INDEXING_ENABLED);
755    
756                    if (!directoryIndexingEnabled) {
757                            throw new NoSuchFolderException();
758                    }
759    
760                    long folderId = DLFolderConstants.DEFAULT_PARENT_FOLDER_ID;
761    
762                    for (int i = 1; i < pathArray.length; i++) {
763                            String name = pathArray[i];
764    
765                            try {
766                                    Folder folder = DLAppServiceUtil.getFolder(
767                                            groupId, folderId, name);
768    
769                                    folderId = folder.getFolderId();
770                            }
771                            catch (NoSuchFolderException nsfe) {
772                                    if (i != (pathArray.length - 1)) {
773                                            throw nsfe;
774                                    }
775    
776                                    String title = name;
777    
778                                    sendFile(response, user, groupId, folderId, title);
779    
780                                    return;
781                            }
782                    }
783    
784                    try {
785                            sendFile(response, user, groupId, folderId, "index.html");
786    
787                            return;
788                    }
789                    catch (Exception e) {
790                            if ((e instanceof NoSuchFileEntryException) ||
791                                    (e instanceof PrincipalException)) {
792    
793                                    try {
794                                            sendFile(response, user, groupId, folderId, "index.htm");
795    
796                                            return;
797                                    }
798                                    catch (NoSuchFileEntryException nsfee) {
799                                    }
800                                    catch (PrincipalException pe) {
801                                    }
802                            }
803                            else {
804                                    throw e;
805                            }
806                    }
807    
808                    List<WebServerEntry> webServerEntries = new ArrayList<WebServerEntry>();
809    
810                    webServerEntries.add(new WebServerEntry(path, "../"));
811    
812                    List<Folder> folders = DLAppServiceUtil.getFolders(groupId, folderId);
813    
814                    for (Folder folder : folders) {
815                            WebServerEntry webServerEntry = new WebServerEntry(
816                                    path, folder.getName() + StringPool.SLASH,
817                                    folder.getCreateDate(), folder.getModifiedDate(),
818                                    folder.getDescription(), 0);
819    
820                            webServerEntries.add(webServerEntry);
821                    }
822    
823                    List<FileEntry> fileEntries = DLAppServiceUtil.getFileEntries(
824                            groupId, folderId);
825    
826                    for (FileEntry fileEntry : fileEntries) {
827                            WebServerEntry webServerEntry = new WebServerEntry(
828                                    path, fileEntry.getTitle(), fileEntry.getCreateDate(),
829                                    fileEntry.getModifiedDate(), fileEntry.getDescription(),
830                                    fileEntry.getSize());
831    
832                            webServerEntries.add(webServerEntry);
833                    }
834    
835                    sendHTML(response, path, webServerEntries);
836            }
837    
838            protected void sendFile(
839                            HttpServletRequest request, HttpServletResponse response, User user,
840                            String[] pathArray)
841                    throws Exception {
842    
843                    // Retrieve file details
844    
845                    FileEntry fileEntry = getFileEntry(pathArray);
846    
847                    if (fileEntry == null) {
848                            throw new NoSuchFileEntryException();
849                    }
850    
851                    String version = ParamUtil.getString(request, "version");
852    
853                    if (Validator.isNull(version)) {
854                            if (Validator.isNotNull(fileEntry.getVersion())) {
855                                    version = fileEntry.getVersion();
856                            }
857                    }
858    
859                    String tempFileId = DLUtil.getTempFileId(
860                            fileEntry.getFileEntryId(), version);
861    
862                    if (fileEntry.isInTrash()) {
863                            int status = ParamUtil.getInteger(
864                                    request, "status", WorkflowConstants.STATUS_APPROVED);
865    
866                            if (status != WorkflowConstants.STATUS_IN_TRASH) {
867                                    throw new NoSuchFileEntryException();
868                            }
869    
870                            PermissionChecker permissionChecker =
871                                    PermissionThreadLocal.getPermissionChecker();
872    
873                            if (!PortletPermissionUtil.hasControlPanelAccessPermission(
874                                            permissionChecker, fileEntry.getGroupId(),
875                                            PortletKeys.TRASH)) {
876    
877                                    throw new PrincipalException();
878                            }
879                    }
880    
881                    FileVersion fileVersion = fileEntry.getFileVersion(version);
882    
883                    if ((ParamUtil.getInteger(request, "height") > 0) ||
884                            (ParamUtil.getInteger(request, "width") > 0)) {
885    
886                            InputStream inputStream = fileVersion.getContentStream(true);
887    
888                            Image image = ImageToolUtil.getImage(inputStream);
889    
890                            writeImage(image, request, response);
891    
892                            return;
893                    }
894    
895                    String fileName = fileVersion.getFileName();
896    
897                    // Handle requested conversion
898    
899                    boolean converted = false;
900    
901                    String targetExtension = ParamUtil.getString(
902                            request, "targetExtension");
903                    int imageThumbnail = ParamUtil.getInteger(request, "imageThumbnail");
904                    int documentThumbnail = ParamUtil.getInteger(
905                            request, "documentThumbnail");
906                    int previewFileIndex = ParamUtil.getInteger(
907                            request, "previewFileIndex");
908                    boolean audioPreview = ParamUtil.getBoolean(request, "audioPreview");
909                    boolean imagePreview = ParamUtil.getBoolean(request, "imagePreview");
910                    boolean videoPreview = ParamUtil.getBoolean(request, "videoPreview");
911                    int videoThumbnail = ParamUtil.getInteger(request, "videoThumbnail");
912    
913                    InputStream inputStream = null;
914                    long contentLength = 0;
915    
916                    if ((imageThumbnail > 0) && (imageThumbnail <= 3)) {
917                            fileName = FileUtil.stripExtension(fileName).concat(
918                                    StringPool.PERIOD).concat(
919                                            ImageProcessorUtil.getThumbnailType(fileVersion));
920    
921                            int thumbnailIndex = imageThumbnail - 1;
922    
923                            inputStream = ImageProcessorUtil.getThumbnailAsStream(
924                                    fileVersion, thumbnailIndex);
925                            contentLength = ImageProcessorUtil.getThumbnailFileSize(
926                                    fileVersion, thumbnailIndex);
927    
928                            converted = true;
929                    }
930                    else if ((documentThumbnail > 0) && (documentThumbnail <= 3)) {
931                            fileName = FileUtil.stripExtension(fileName).concat(
932                                    StringPool.PERIOD).concat(PDFProcessor.THUMBNAIL_TYPE);
933    
934                            int thumbnailIndex = documentThumbnail - 1;
935    
936                            inputStream = PDFProcessorUtil.getThumbnailAsStream(
937                                    fileVersion, thumbnailIndex);
938                            contentLength = PDFProcessorUtil.getThumbnailFileSize(
939                                    fileVersion, thumbnailIndex);
940    
941                            converted = true;
942                    }
943                    else if (previewFileIndex > 0) {
944                            fileName = FileUtil.stripExtension(fileName).concat(
945                                    StringPool.PERIOD).concat(PDFProcessor.PREVIEW_TYPE);
946                            inputStream = PDFProcessorUtil.getPreviewAsStream(
947                                    fileVersion, previewFileIndex);
948                            contentLength = PDFProcessorUtil.getPreviewFileSize(
949                                    fileVersion, previewFileIndex);
950    
951                            converted = true;
952                    }
953                    else if (audioPreview || videoPreview) {
954                            String type = ParamUtil.getString(request, "type");
955    
956                            fileName = FileUtil.stripExtension(fileName).concat(
957                                    StringPool.PERIOD).concat(type);
958    
959                            if (audioPreview) {
960                                    inputStream = AudioProcessorUtil.getPreviewAsStream(
961                                            fileVersion, type);
962                                    contentLength = AudioProcessorUtil.getPreviewFileSize(
963                                            fileVersion, type);
964                            }
965                            else {
966                                    inputStream = VideoProcessorUtil.getPreviewAsStream(
967                                            fileVersion, type);
968                                    contentLength = VideoProcessorUtil.getPreviewFileSize(
969                                            fileVersion, type);
970                            }
971    
972                            converted = true;
973                    }
974                    else if (imagePreview) {
975                            String type = ImageProcessorUtil.getPreviewType(fileVersion);
976    
977                            fileName = FileUtil.stripExtension(fileName).concat(
978                                    StringPool.PERIOD).concat(type);
979    
980                            inputStream = ImageProcessorUtil.getPreviewAsStream(fileVersion);
981    
982                            contentLength = ImageProcessorUtil.getPreviewFileSize(fileVersion);
983    
984                            converted = true;
985                    }
986                    else if ((videoThumbnail > 0) && (videoThumbnail <= 3)) {
987                            fileName = FileUtil.stripExtension(fileName).concat(
988                                    StringPool.PERIOD).concat(VideoProcessor.THUMBNAIL_TYPE);
989    
990                            int thumbnailIndex = videoThumbnail - 1;
991    
992                            inputStream = VideoProcessorUtil.getThumbnailAsStream(
993                                    fileVersion, thumbnailIndex);
994                            contentLength = VideoProcessorUtil.getThumbnailFileSize(
995                                    fileVersion, thumbnailIndex);
996    
997                            converted = true;
998                    }
999                    else {
1000                            inputStream = fileVersion.getContentStream(true);
1001                            contentLength = fileVersion.getSize();
1002    
1003                            if (Validator.isNotNull(targetExtension)) {
1004                                    File convertedFile = DocumentConversionUtil.convert(
1005                                            tempFileId, inputStream, fileVersion.getExtension(),
1006                                            targetExtension);
1007    
1008                                    if (convertedFile != null) {
1009                                            fileName = FileUtil.stripExtension(fileName).concat(
1010                                                    StringPool.PERIOD).concat(targetExtension);
1011                                            inputStream = new FileInputStream(convertedFile);
1012                                            contentLength = convertedFile.length();
1013    
1014                                            converted = true;
1015                                    }
1016                            }
1017                    }
1018    
1019                    // Determine proper content type
1020    
1021                    String contentType = null;
1022    
1023                    if (converted) {
1024                            contentType = MimeTypesUtil.getContentType(fileName);
1025                    }
1026                    else {
1027                            contentType = fileVersion.getMimeType();
1028                    }
1029    
1030                    if (_log.isDebugEnabled()) {
1031                            _log.debug("Content type set to " + contentType);
1032                    }
1033    
1034                    // Send file
1035    
1036                    if (isSupportsRangeHeader(contentType)) {
1037                            sendFileWithRangeHeader(
1038                                    request, response, fileName, inputStream, contentLength,
1039                                    contentType);
1040                    }
1041                    else {
1042                            boolean download = ParamUtil.getBoolean(request, "download");
1043    
1044                            if (download) {
1045                                    ServletResponseUtil.sendFile(
1046                                            request, response, fileName, inputStream, contentLength,
1047                                            contentType, HttpHeaders.CONTENT_DISPOSITION_ATTACHMENT);
1048                            }
1049                            else {
1050                                    ServletResponseUtil.sendFile(
1051                                            request, response, fileName, inputStream, contentLength,
1052                                            contentType);
1053                            }
1054                    }
1055            }
1056    
1057            protected void sendFile(
1058                            HttpServletResponse response, User user, long groupId,
1059                            long folderId, String title)
1060                    throws Exception {
1061    
1062                    FileEntry fileEntry = DLAppServiceUtil.getFileEntry(
1063                            groupId, folderId, title);
1064    
1065                    String contentType = fileEntry.getMimeType();
1066    
1067                    response.setContentType(contentType);
1068    
1069                    InputStream inputStream = fileEntry.getContentStream();
1070    
1071                    ServletResponseUtil.write(response, inputStream, fileEntry.getSize());
1072            }
1073    
1074            protected void sendFileWithRangeHeader(
1075                            HttpServletRequest request, HttpServletResponse response,
1076                            String fileName, InputStream inputStream, long contentLength,
1077                            String contentType)
1078                    throws IOException {
1079    
1080                    if (_log.isDebugEnabled()) {
1081                            _log.debug("Accepting ranges for the file " + fileName);
1082                    }
1083    
1084                    response.setHeader(
1085                            HttpHeaders.ACCEPT_RANGES, HttpHeaders.ACCEPT_RANGES_BYTES_VALUE);
1086    
1087                    List<Range> ranges = null;
1088    
1089                    try {
1090                            ranges = ServletResponseUtil.getRanges(
1091                                    request, response, contentLength);
1092                    }
1093                    catch (IOException ioe) {
1094                            if (_log.isErrorEnabled()) {
1095                                    _log.error(ioe);
1096                            }
1097    
1098                            response.setHeader(
1099                                    HttpHeaders.CONTENT_RANGE, "bytes */" + contentLength);
1100    
1101                            response.sendError(
1102                                    HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
1103    
1104                            return;
1105                    }
1106    
1107                    if ((ranges == null) || ranges.isEmpty()) {
1108                            ServletResponseUtil.sendFile(
1109                                    request, response, fileName, inputStream, contentLength,
1110                                    contentType);
1111                    }
1112                    else {
1113                            if (_log.isDebugEnabled()) {
1114                                    _log.debug(
1115                                            "Request has range header " +
1116                                                    request.getHeader(HttpHeaders.RANGE));
1117                            }
1118    
1119                            ServletResponseUtil.write(
1120                                    request, response, fileName, ranges, inputStream, contentLength,
1121                                    contentType);
1122                    }
1123            }
1124    
1125            protected void sendGroups(
1126                            HttpServletResponse response, User user, String path)
1127                    throws Exception {
1128    
1129                    if (!PropsValues.WEB_SERVER_SERVLET_DIRECTORY_INDEXING_ENABLED) {
1130                            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
1131    
1132                            return;
1133                    }
1134    
1135                    List<WebServerEntry> webServerEntries = new ArrayList<WebServerEntry>();
1136    
1137                    List<Group> groups = WebDAVUtil.getGroups(user);
1138    
1139                    for (Group group : groups) {
1140                            String name = HttpUtil.fixPath(group.getFriendlyURL());
1141    
1142                            WebServerEntry webServerEntry = new WebServerEntry(
1143                                    path, name + StringPool.SLASH, null, null,
1144                                    group.getDescription(), 0);
1145    
1146                            webServerEntries.add(webServerEntry);
1147                    }
1148    
1149                    sendHTML(response, path, webServerEntries);
1150            }
1151    
1152            protected void sendHTML(
1153                            HttpServletResponse response, String path,
1154                            List<WebServerEntry> webServerEntries)
1155                    throws Exception {
1156    
1157                    Template template = TemplateManagerUtil.getTemplate(
1158                            TemplateConstants.LANG_TYPE_FTL, _templateResource, true);
1159    
1160                    template.put("dateFormat", _dateFormat);
1161                    template.put("entries", webServerEntries);
1162                    template.put("path", HttpUtil.encodePath(path));
1163    
1164                    if (_WEB_SERVER_SERVLET_VERSION_VERBOSITY_DEFAULT) {
1165                    }
1166                    else if (_WEB_SERVER_SERVLET_VERSION_VERBOSITY_PARTIAL) {
1167                            template.put("releaseInfo", ReleaseInfo.getName());
1168                    }
1169                    else {
1170                            template.put("releaseInfo", ReleaseInfo.getReleaseInfo());
1171                    }
1172    
1173                    template.put("validator", Validator_IW.getInstance());
1174    
1175                    response.setContentType(ContentTypes.TEXT_HTML_UTF8);
1176    
1177                    template.processTemplate(response.getWriter());
1178            }
1179    
1180            protected void sendPortletFileEntry(
1181                            HttpServletRequest request, HttpServletResponse response,
1182                            String[] pathArray)
1183                    throws Exception {
1184    
1185                    FileEntry fileEntry = getPortletFileEntry(request, pathArray);
1186    
1187                    if (fileEntry == null) {
1188                            return;
1189                    }
1190    
1191                    String fileName = HttpUtil.decodeURL(HtmlUtil.escape(pathArray[2]));
1192    
1193                    if (fileEntry.isInTrash()) {
1194                            fileName = TrashUtil.getOriginalTitle(fileName);
1195                    }
1196    
1197                    boolean download = ParamUtil.getBoolean(request, "download");
1198    
1199                    if (download) {
1200                            ServletResponseUtil.sendFile(
1201                                    request, response, fileName, fileEntry.getContentStream(),
1202                                    fileEntry.getSize(), fileEntry.getMimeType(),
1203                                    HttpHeaders.CONTENT_DISPOSITION_ATTACHMENT);
1204                    }
1205                    else {
1206                            ServletResponseUtil.sendFile(
1207                                    request, response, fileName, fileEntry.getContentStream(),
1208                                    fileEntry.getSize(), fileEntry.getMimeType());
1209                    }
1210            }
1211    
1212            protected void writeImage(
1213                    Image image, HttpServletRequest request, HttpServletResponse response) {
1214    
1215                    if (image == null) {
1216                            return;
1217                    }
1218    
1219                    String contentType = null;
1220    
1221                    String type = image.getType();
1222    
1223                    if (!type.equals(ImageConstants.TYPE_NOT_AVAILABLE)) {
1224                            contentType = MimeTypesUtil.getExtensionContentType(type);
1225    
1226                            response.setContentType(contentType);
1227                    }
1228    
1229                    String fileName = ParamUtil.getString(request, "fileName");
1230    
1231                    try {
1232                            byte[] bytes = getImageBytes(request, image);
1233    
1234                            if (Validator.isNotNull(fileName)) {
1235                                    ServletResponseUtil.sendFile(
1236                                            request, response, fileName, bytes, contentType);
1237                            }
1238                            else {
1239                                    ServletResponseUtil.write(response, bytes);
1240                            }
1241                    }
1242                    catch (Exception e) {
1243                            if (_log.isWarnEnabled()) {
1244                                    _log.warn(e, e);
1245                            }
1246                    }
1247            }
1248    
1249            private static void _checkFileEntry(String[] pathArray) throws Exception {
1250                    if (pathArray.length == 1) {
1251                            long dlFileShortcutId = GetterUtil.getLong(pathArray[0]);
1252    
1253                            DLFileShortcut dlFileShortcut =
1254                                    DLAppLocalServiceUtil.getFileShortcut(dlFileShortcutId);
1255    
1256                            DLAppLocalServiceUtil.getFileEntry(
1257                                    dlFileShortcut.getToFileEntryId());
1258                    }
1259                    else if (pathArray.length == 2) {
1260    
1261                            // Unable to check with UUID because of multiple repositories
1262    
1263                    }
1264                    else if (pathArray.length == 3) {
1265                            long groupId = GetterUtil.getLong(pathArray[0]);
1266                            long folderId = GetterUtil.getLong(pathArray[1]);
1267                            String fileName = HttpUtil.decodeURL(pathArray[2]);
1268    
1269                            try {
1270                                    DLAppLocalServiceUtil.getFileEntry(groupId, folderId, fileName);
1271                            }
1272                            catch (RepositoryException re) {
1273                            }
1274                    }
1275                    else {
1276                            long groupId = GetterUtil.getLong(pathArray[0]);
1277    
1278                            String uuid = pathArray[3];
1279    
1280                            try {
1281                                    DLAppLocalServiceUtil.getFileEntryByUuidAndGroupId(
1282                                            uuid, groupId);
1283                            }
1284                            catch (RepositoryException re) {
1285                            }
1286                    }
1287            }
1288    
1289            private static long _getGroupId(long companyId, String name)
1290                    throws Exception {
1291    
1292                    Group group = GroupLocalServiceUtil.fetchFriendlyURLGroup(
1293                            companyId, StringPool.SLASH + name);
1294    
1295                    if (group != null) {
1296                            return group.getGroupId();
1297                    }
1298    
1299                    User user = UserLocalServiceUtil.getUserByScreenName(companyId, name);
1300    
1301                    group = user.getGroup();
1302    
1303                    return group.getGroupId();
1304            }
1305    
1306            private static User _getUser(HttpServletRequest request) throws Exception {
1307                    HttpSession session = request.getSession();
1308    
1309                    if (PortalSessionThreadLocal.getHttpSession() == null) {
1310                            PortalSessionThreadLocal.setHttpSession(session);
1311                    }
1312    
1313                    User user = PortalUtil.getUser(request);
1314    
1315                    if (user != null) {
1316                            return user;
1317                    }
1318    
1319                    String userIdString = (String)session.getAttribute("j_username");
1320                    String password = (String)session.getAttribute("j_password");
1321    
1322                    if ((userIdString != null) && (password != null)) {
1323                            long userId = GetterUtil.getLong(userIdString);
1324    
1325                            user = UserLocalServiceUtil.getUser(userId);
1326                    }
1327                    else {
1328                            long companyId = PortalUtil.getCompanyId(request);
1329    
1330                            Company company = CompanyLocalServiceUtil.getCompany(companyId);
1331    
1332                            user = company.getDefaultUser();
1333                    }
1334    
1335                    return user;
1336            }
1337    
1338            private static final boolean _WEB_SERVER_SERVLET_VERSION_VERBOSITY_DEFAULT =
1339                    StringUtil.equalsIgnoreCase(
1340                            PropsValues.WEB_SERVER_SERVLET_VERSION_VERBOSITY,
1341                            ReleaseInfo.getName());
1342    
1343            private static final boolean _WEB_SERVER_SERVLET_VERSION_VERBOSITY_PARTIAL =
1344                    StringUtil.equalsIgnoreCase(
1345                            PropsValues.WEB_SERVER_SERVLET_VERSION_VERBOSITY, "partial");
1346    
1347            private static Log _log = LogFactoryUtil.getLog(WebServerServlet.class);
1348    
1349            private static Set<String> _acceptRangesMimeTypes = SetUtil.fromArray(
1350                    PropsValues.WEB_SERVER_SERVLET_ACCEPT_RANGES_MIME_TYPES);
1351            private static Format _dateFormat =
1352                    FastDateFormatFactoryUtil.getSimpleDateFormat("d MMM yyyy HH:mm z");
1353    
1354            private boolean _lastModified = true;
1355            private TemplateResource _templateResource;
1356    
1357    }