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