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