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