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