001    /**
002     * Copyright (c) 2000-2011 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.portlet.documentlibrary.store;
016    
017    import com.liferay.portal.kernel.bean.BeanReference;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.io.ByteArrayFileInputStream;
021    import com.liferay.portal.kernel.search.BooleanClauseOccur;
022    import com.liferay.portal.kernel.search.BooleanQuery;
023    import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
024    import com.liferay.portal.kernel.search.Field;
025    import com.liferay.portal.kernel.search.Hits;
026    import com.liferay.portal.kernel.search.SearchContext;
027    import com.liferay.portal.kernel.search.SearchEngineUtil;
028    import com.liferay.portal.kernel.search.TermQuery;
029    import com.liferay.portal.kernel.search.TermQueryFactoryUtil;
030    import com.liferay.portal.kernel.util.FileUtil;
031    import com.liferay.portal.kernel.util.PropsKeys;
032    import com.liferay.portal.kernel.util.StringPool;
033    import com.liferay.portal.kernel.util.StringUtil;
034    import com.liferay.portal.kernel.util.Validator;
035    import com.liferay.portal.model.Group;
036    import com.liferay.portal.security.permission.ActionKeys;
037    import com.liferay.portal.security.permission.PermissionChecker;
038    import com.liferay.portal.security.permission.PermissionThreadLocal;
039    import com.liferay.portal.service.GroupLocalService;
040    import com.liferay.portal.util.PrefsPropsUtil;
041    import com.liferay.portal.util.PropsValues;
042    import com.liferay.portlet.documentlibrary.DirectoryNameException;
043    import com.liferay.portlet.documentlibrary.FileExtensionException;
044    import com.liferay.portlet.documentlibrary.FileNameException;
045    import com.liferay.portlet.documentlibrary.FileSizeException;
046    import com.liferay.portlet.documentlibrary.SourceFileNameException;
047    import com.liferay.portlet.documentlibrary.antivirus.AntivirusScannerUtil;
048    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
049    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
050    import com.liferay.portlet.documentlibrary.service.permission.DLFolderPermission;
051    
052    import java.io.File;
053    import java.io.IOException;
054    import java.io.InputStream;
055    
056    /**
057     * @author Brian Wing Shun Chan
058     * @author Alexander Chow
059     * @author Edward Han
060     */
061    public class DLStoreImpl implements DLStore {
062    
063            public void addDirectory(long companyId, long repositoryId, String dirName)
064                    throws PortalException, SystemException {
065    
066                    if (!isValidName(dirName) || dirName.equals("/")) {
067                            throw new DirectoryNameException(dirName);
068                    }
069    
070                    store.addDirectory(companyId, repositoryId, dirName);
071            }
072    
073            public void addFile(
074                            long companyId, long repositoryId, String fileName,
075                            boolean validateFileExtension, byte[] bytes)
076                    throws PortalException, SystemException {
077    
078                    validate(fileName, validateFileExtension, bytes);
079    
080                    if (!PropsValues.DL_STORE_ANTIVIRUS_ENABLED) {
081                            AntivirusScannerUtil.scan(bytes);
082                    }
083    
084                    store.addFile(companyId, repositoryId, fileName, bytes);
085            }
086    
087            public void addFile(
088                            long companyId, long repositoryId, String fileName,
089                            boolean validateFileExtension, File file)
090                    throws PortalException, SystemException {
091    
092                    validate(fileName, validateFileExtension, file);
093    
094                    if (PropsValues.DL_STORE_ANTIVIRUS_ENABLED) {
095                            AntivirusScannerUtil.scan(file);
096                    }
097    
098                    store.addFile(companyId, repositoryId, fileName, file);
099            }
100    
101            public void addFile(
102                            long companyId, long repositoryId, String fileName,
103                            boolean validateFileExtension, InputStream is)
104                    throws PortalException, SystemException {
105    
106                    if (is instanceof ByteArrayFileInputStream) {
107                            ByteArrayFileInputStream byteArrayFileInputStream =
108                                    (ByteArrayFileInputStream)is;
109    
110                            File file = byteArrayFileInputStream.getFile();
111    
112                            addFile(
113                                    companyId, repositoryId, fileName, validateFileExtension, file);
114    
115                            return;
116                    }
117    
118                    validate(fileName, validateFileExtension, is);
119    
120                    if (!PropsValues.DL_STORE_ANTIVIRUS_ENABLED ||
121                            !AntivirusScannerUtil.isActive()) {
122    
123                            store.addFile(companyId, repositoryId, fileName, is);
124                    }
125                    else {
126                            File tempFile = null;
127    
128                            try {
129                                    if (is.markSupported()) {
130                                            is.mark(is.available() + 1);
131    
132                                            AntivirusScannerUtil.scan(is);
133    
134                                            is.reset();
135    
136                                            store.addFile(companyId, repositoryId, fileName, is);
137                                    }
138                                    else {
139                                            tempFile = FileUtil.createTempFile();
140    
141                                            FileUtil.write(tempFile, is);
142    
143                                            AntivirusScannerUtil.scan(tempFile);
144    
145                                            store.addFile(companyId, repositoryId, fileName, tempFile);
146                                    }
147                            }
148                            catch (IOException ioe) {
149                                    throw new SystemException(
150                                            "Unable to scan file " + fileName, ioe);
151                            }
152                            finally {
153                                    if (tempFile != null) {
154                                            tempFile.delete();
155                                    }
156                            }
157                    }
158            }
159    
160            public void addFile(
161                            long companyId, long repositoryId, String fileName, byte[] bytes)
162                    throws PortalException, SystemException {
163    
164                    addFile(companyId, repositoryId, fileName, true, bytes);
165            }
166    
167            public void addFile(
168                            long companyId, long repositoryId, String fileName, File file)
169                    throws PortalException, SystemException {
170    
171                    addFile(companyId, repositoryId, fileName, true, file);
172            }
173    
174            public void addFile(
175                            long companyId, long repositoryId, String fileName, InputStream is)
176                    throws PortalException, SystemException {
177    
178                    addFile(companyId, repositoryId, fileName, true, is);
179            }
180    
181            public void checkRoot(long companyId) throws SystemException {
182                    store.checkRoot(companyId);
183            }
184    
185            public void copyFileVersion(
186                            long companyId, long repositoryId, String fileName,
187                            String fromVersionLabel, String toVersionLabel)
188                    throws PortalException, SystemException {
189    
190                    store.copyFileVersion(
191                            companyId, repositoryId, fileName, fromVersionLabel,
192                            toVersionLabel);
193            }
194    
195            public void deleteDirectory(
196                            long companyId, long repositoryId, String dirName)
197                    throws PortalException, SystemException {
198    
199                    store.deleteDirectory(companyId, repositoryId, dirName);
200            }
201    
202            public void deleteFile(long companyId, long repositoryId, String fileName)
203                    throws PortalException, SystemException {
204    
205                    store.deleteFile(companyId, repositoryId, fileName);
206            }
207    
208            public void deleteFile(
209                            long companyId, long repositoryId, String fileName,
210                            String versionLabel)
211                    throws PortalException, SystemException {
212    
213                    store.deleteFile(companyId, repositoryId, fileName, versionLabel);
214            }
215    
216            public File getFile(long companyId, long repositoryId, String fileName)
217                    throws PortalException, SystemException {
218    
219                    return store.getFile(companyId, repositoryId, fileName);
220            }
221    
222            public File getFile(
223                            long companyId, long repositoryId, String fileName,
224                            String versionLabel)
225                    throws PortalException, SystemException {
226    
227                    return store.getFile(companyId, repositoryId, fileName, versionLabel);
228            }
229    
230            public byte[] getFileAsBytes(
231                            long companyId, long repositoryId, String fileName)
232                    throws PortalException, SystemException {
233    
234                    return store.getFileAsBytes(companyId, repositoryId, fileName);
235            }
236    
237            public byte[] getFileAsBytes(
238                            long companyId, long repositoryId, String fileName,
239                            String versionLabel)
240                    throws PortalException, SystemException {
241    
242                    return store.getFileAsBytes(
243                            companyId, repositoryId, fileName, versionLabel);
244            }
245    
246            public InputStream getFileAsStream(
247                            long companyId, long repositoryId, String fileName)
248                    throws PortalException, SystemException {
249    
250                    return store.getFileAsStream(companyId, repositoryId, fileName);
251            }
252    
253            public InputStream getFileAsStream(
254                            long companyId, long repositoryId, String fileName,
255                            String versionLabel)
256                    throws PortalException, SystemException {
257    
258                    return store.getFileAsStream(
259                            companyId, repositoryId, fileName, versionLabel);
260            }
261    
262            public String[] getFileNames(
263                            long companyId, long repositoryId, String dirName)
264                    throws PortalException, SystemException {
265    
266                    return store.getFileNames(companyId, repositoryId, dirName);
267            }
268    
269            public long getFileSize(long companyId, long repositoryId, String fileName)
270                    throws PortalException, SystemException {
271    
272                    return store.getFileSize(companyId, repositoryId, fileName);
273            }
274    
275            public boolean hasDirectory(
276                            long companyId, long repositoryId, String dirName)
277                    throws PortalException, SystemException {
278    
279                    return store.hasDirectory(companyId, repositoryId, dirName);
280            }
281    
282            public boolean hasFile(long companyId, long repositoryId, String fileName)
283                    throws PortalException, SystemException {
284    
285                    return store.hasFile(companyId, repositoryId, fileName);
286            }
287    
288            public boolean hasFile(
289                            long companyId, long repositoryId, String fileName,
290                            String versionLabel)
291                    throws PortalException, SystemException {
292    
293                    return store.hasFile(companyId, repositoryId, fileName, versionLabel);
294            }
295    
296            public void move(String srcDir, String destDir) throws SystemException {
297                    store.move(srcDir, destDir);
298            }
299    
300            public Hits search(
301                            long companyId, long userId, String portletId, long groupId,
302                            long[] repositoryIds, String keywords, int start, int end)
303                    throws SystemException {
304    
305                    try {
306                            SearchContext searchContext = new SearchContext();
307    
308                            searchContext.setSearchEngineId(SearchEngineUtil.SYSTEM_ENGINE_ID);
309    
310                            BooleanQuery contextQuery = BooleanQueryFactoryUtil.create(
311                                    searchContext);
312    
313                            contextQuery.addRequiredTerm(Field.PORTLET_ID, portletId);
314    
315                            if (groupId > 0) {
316                                    Group group = groupLocalService.getGroup(groupId);
317    
318                                    if (group.isLayout()) {
319                                            contextQuery.addRequiredTerm(Field.SCOPE_GROUP_ID, groupId);
320    
321                                            groupId = group.getParentGroupId();
322                                    }
323    
324                                    contextQuery.addRequiredTerm(Field.GROUP_ID, groupId);
325                            }
326    
327                            if ((repositoryIds != null) && (repositoryIds.length > 0)) {
328                                    BooleanQuery repositoryIdsQuery =
329                                            BooleanQueryFactoryUtil.create(searchContext);
330    
331                                    for (long repositoryId : repositoryIds) {
332                                            try {
333                                                    if (userId > 0) {
334                                                            PermissionChecker permissionChecker =
335                                                                    PermissionThreadLocal.getPermissionChecker();
336    
337                                                            DLFolderPermission.check(
338                                                                    permissionChecker, groupId, repositoryId,
339                                                                    ActionKeys.VIEW);
340                                                    }
341    
342                                                    if (repositoryId ==
343                                                                    DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
344    
345                                                            repositoryId = groupId;
346                                                    }
347    
348                                                    TermQuery termQuery = TermQueryFactoryUtil.create(
349                                                            searchContext, "repositoryId", repositoryId);
350    
351                                                    repositoryIdsQuery.add(
352                                                            termQuery, BooleanClauseOccur.SHOULD);
353                                            }
354                                            catch (Exception e) {
355                                            }
356                                    }
357    
358                                    contextQuery.add(repositoryIdsQuery, BooleanClauseOccur.MUST);
359                            }
360    
361                            BooleanQuery searchQuery = BooleanQueryFactoryUtil.create(
362                                    searchContext);
363    
364                            searchQuery.addTerms(_KEYWORDS_FIELDS, keywords);
365    
366                            BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(
367                                    searchContext);
368    
369                            fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
370    
371                            if (searchQuery.clauses().size() > 0) {
372                                    fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
373                            }
374    
375                            return SearchEngineUtil.search(
376                                    companyId, new long[] {groupId}, userId,
377                                    DLFileEntry.class.getName(), fullQuery, start, end);
378                    }
379                    catch (Exception e) {
380                            throw new SystemException(e);
381                    }
382            }
383    
384            public void updateFile(
385                            long companyId, long repositoryId, long newRepositoryId,
386                            String fileName)
387                    throws PortalException, SystemException {
388    
389                    store.updateFile(companyId, repositoryId, newRepositoryId, fileName);
390            }
391    
392            public void updateFile(
393                            long companyId, long repositoryId, String fileName,
394                            String newFileName)
395                    throws PortalException, SystemException {
396    
397                    store.updateFile(companyId, repositoryId, fileName, newFileName);
398            }
399    
400            public void updateFile(
401                            long companyId, long repositoryId, String fileName,
402                            String fileExtension, boolean validateFileExtension,
403                            String versionLabel, String sourceFileName, File file)
404                    throws PortalException, SystemException {
405    
406                    validate(
407                            fileName, fileExtension, sourceFileName,
408                            validateFileExtension, file);
409    
410                    if (!PropsValues.DL_STORE_ANTIVIRUS_ENABLED) {
411                            AntivirusScannerUtil.scan(file);
412                    }
413    
414                    store.updateFile(companyId, repositoryId, fileName, versionLabel, file);
415            }
416    
417            public void updateFile(
418                            long companyId, long repositoryId, String fileName,
419                            String fileExtension, boolean validateFileExtension,
420                            String versionLabel, String sourceFileName, InputStream is)
421                    throws PortalException, SystemException {
422    
423                    if (is instanceof ByteArrayFileInputStream) {
424                            ByteArrayFileInputStream byteArrayFileInputStream =
425                                    (ByteArrayFileInputStream)is;
426    
427                            File file = byteArrayFileInputStream.getFile();
428    
429                            updateFile(
430                                    companyId, repositoryId, fileName, fileExtension,
431                                    validateFileExtension, versionLabel, sourceFileName, file);
432    
433                            return;
434                    }
435    
436                    validate(
437                            fileName, fileExtension, sourceFileName,
438                            validateFileExtension, is);
439    
440                    if (!PropsValues.DL_STORE_ANTIVIRUS_ENABLED ||
441                            !AntivirusScannerUtil.isActive()) {
442    
443                            store.updateFile(
444                                    companyId, repositoryId, fileName, versionLabel, is);
445                    }
446                    else {
447                            File tempFile = null;
448    
449                            try {
450                                    if (is.markSupported()) {
451                                            is.mark(is.available() + 1);
452    
453                                            AntivirusScannerUtil.scan(is);
454    
455                                            is.reset();
456    
457                                            store.updateFile(
458                                                    companyId, repositoryId, fileName, versionLabel, is);
459                                    }
460                                    else {
461                                            tempFile = FileUtil.createTempFile();
462    
463                                            FileUtil.write(tempFile, is);
464    
465                                            AntivirusScannerUtil.scan(tempFile);
466    
467                                            store.updateFile(
468                                                    companyId, repositoryId, fileName, versionLabel,
469                                                    tempFile);
470                                    }
471                            }
472                            catch (IOException ioe) {
473                                    throw new SystemException(
474                                            "Unable to scan file " + fileName, ioe);
475                            }
476                            finally {
477                                    if (tempFile != null) {
478                                            tempFile.delete();
479                                    }
480                            }
481                    }
482            }
483    
484            public void updateFileVersion(
485                            long companyId, long repositoryId, String fileName,
486                            String fromVersionLabel, String toVersionLabel)
487                    throws PortalException, SystemException {
488    
489                    store.updateFileVersion(
490                            companyId, repositoryId, fileName, fromVersionLabel,
491                            toVersionLabel);
492            }
493    
494            public void validate(String fileName, boolean validateFileExtension)
495                    throws PortalException, SystemException {
496    
497                    if (!isValidName(fileName)) {
498                            throw new FileNameException(fileName);
499                    }
500    
501                    if (validateFileExtension) {
502                            boolean validFileExtension = false;
503    
504                            String[] fileExtensions = PrefsPropsUtil.getStringArray(
505                                    PropsKeys.DL_FILE_EXTENSIONS, StringPool.COMMA);
506    
507                            for (int i = 0; i < fileExtensions.length; i++) {
508                                    if (StringPool.STAR.equals(fileExtensions[i]) ||
509                                            StringUtil.endsWith(fileName, fileExtensions[i])) {
510    
511                                            validFileExtension = true;
512    
513                                            break;
514                                    }
515                            }
516    
517                            if (!validFileExtension) {
518                                    throw new FileExtensionException(fileName);
519                            }
520                    }
521            }
522    
523            public void validate(
524                            String fileName, boolean validateFileExtension, byte[] bytes)
525                    throws PortalException, SystemException {
526    
527                    validate(fileName, validateFileExtension);
528    
529                    if ((PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE) > 0) &&
530                            ((bytes == null) ||
531                             (bytes.length >
532                                     PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE)))) {
533    
534                            throw new FileSizeException(fileName);
535                    }
536            }
537    
538            public void validate(
539                            String fileName, boolean validateFileExtension, File file)
540                    throws PortalException, SystemException {
541    
542                    validate(fileName, validateFileExtension);
543    
544                    if ((PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE) > 0) &&
545                            ((file == null) ||
546                             (file.length() >
547                                    PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE)))) {
548    
549                            throw new FileSizeException(fileName);
550                    }
551            }
552    
553            public void validate(
554                            String fileName, boolean validateFileExtension, InputStream is)
555                    throws PortalException, SystemException {
556    
557                    validate(fileName, validateFileExtension);
558    
559                    // LEP-4851
560    
561                    try {
562                            if ((is == null) ||
563                                    ((PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE) > 0) &&
564                                     (is.available() >
565                                            PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE)))) {
566    
567                                    throw new FileSizeException(fileName);
568                            }
569                    }
570                    catch (IOException ioe) {
571                            throw new FileSizeException(ioe.getMessage());
572                    }
573            }
574    
575            public void validate(
576                            String fileName, String fileExtension, String sourceFileName,
577                            boolean validateFileExtension, File file)
578                    throws PortalException, SystemException {
579    
580                    validate(
581                            fileName, fileExtension, sourceFileName, validateFileExtension);
582    
583                    if ((file != null) &&
584                            (PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE) > 0) &&
585                            (file.length() >
586                                    PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE))) {
587    
588                            throw new FileSizeException(fileName);
589                    }
590            }
591    
592            public void validate(
593                            String fileName, String fileExtension, String sourceFileName,
594                            boolean validateFileExtension, InputStream is)
595                    throws PortalException, SystemException {
596    
597                    validate(
598                            fileName, fileExtension, sourceFileName, validateFileExtension);
599    
600                    try {
601                            if ((is != null) &&
602                                    (PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE) > 0) &&
603                                    (is.available() >
604                                            PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE))) {
605    
606                                    throw new FileSizeException(fileName);
607                            }
608                    }
609                    catch (IOException ioe) {
610                            throw new FileSizeException(ioe.getMessage());
611                    }
612            }
613    
614            protected boolean isValidName(String name) {
615                    if ((name == null) ||
616                            (name.contains("\\")) ||
617                            (name.contains("\\\\")) ||
618                            (name.contains("//")) ||
619                            (name.contains(":")) ||
620                            (name.contains("*")) ||
621                            (name.contains("?")) ||
622                            (name.contains("\"")) ||
623                            (name.contains("<")) ||
624                            (name.contains(">")) ||
625                            (name.contains("|")) ||
626                            (name.contains("[")) ||
627                            (name.contains("]")) ||
628                            (name.contains("../")) ||
629                            (name.contains("/.."))) {
630    
631                            return false;
632                    }
633    
634                    return true;
635            }
636    
637            protected void validate(
638                            String fileName, String fileExtension, String sourceFileName,
639                            boolean validateFileExtension)
640                    throws PortalException, SystemException {
641    
642                    String sourceFileExtension = FileUtil.getExtension(sourceFileName);
643    
644                    if (Validator.isNotNull(sourceFileName) &&
645                            PropsValues.DL_FILE_EXTENSIONS_STRICT_CHECK &&
646                            !fileExtension.equals(sourceFileExtension)) {
647    
648                            throw new SourceFileNameException(sourceFileExtension);
649                    }
650    
651                    validate(fileName, validateFileExtension);
652            }
653    
654            @BeanReference(type = GroupLocalService.class)
655            protected GroupLocalService groupLocalService;
656    
657            @BeanReference(type = Store.class)
658            protected Store store;
659    
660            private static final String[] _KEYWORDS_FIELDS = {
661                    Field.ASSET_TAG_NAMES, Field.CONTENT, Field.PROPERTIES
662            };
663    
664    }