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