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