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