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