001    /**
002     * Copyright (c) 2000-2012 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, validateFileExtension,
408                            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, validateFileExtension, is);
438    
439                    if (!PropsValues.DL_STORE_ANTIVIRUS_ENABLED ||
440                            !AntivirusScannerUtil.isActive()) {
441    
442                            store.updateFile(
443                                    companyId, repositoryId, fileName, versionLabel, is);
444                    }
445                    else {
446                            File tempFile = null;
447    
448                            try {
449                                    if (is.markSupported()) {
450                                            is.mark(is.available() + 1);
451    
452                                            AntivirusScannerUtil.scan(is);
453    
454                                            is.reset();
455    
456                                            store.updateFile(
457                                                    companyId, repositoryId, fileName, versionLabel, is);
458                                    }
459                                    else {
460                                            tempFile = FileUtil.createTempFile();
461    
462                                            FileUtil.write(tempFile, is);
463    
464                                            AntivirusScannerUtil.scan(tempFile);
465    
466                                            store.updateFile(
467                                                    companyId, repositoryId, fileName, versionLabel,
468                                                    tempFile);
469                                    }
470                            }
471                            catch (IOException ioe) {
472                                    throw new SystemException(
473                                            "Unable to scan file " + fileName, ioe);
474                            }
475                            finally {
476                                    if (tempFile != null) {
477                                            tempFile.delete();
478                                    }
479                            }
480                    }
481            }
482    
483            public void updateFileVersion(
484                            long companyId, long repositoryId, String fileName,
485                            String fromVersionLabel, String toVersionLabel)
486                    throws PortalException, SystemException {
487    
488                    store.updateFileVersion(
489                            companyId, repositoryId, fileName, fromVersionLabel,
490                            toVersionLabel);
491            }
492    
493            public void validate(String fileName, boolean validateFileExtension)
494                    throws PortalException, SystemException {
495    
496                    if (!isValidName(fileName)) {
497                            throw new FileNameException(fileName);
498                    }
499    
500                    if (validateFileExtension) {
501                            boolean validFileExtension = false;
502    
503                            String[] fileExtensions = PrefsPropsUtil.getStringArray(
504                                    PropsKeys.DL_FILE_EXTENSIONS, StringPool.COMMA);
505    
506                            for (int i = 0; i < fileExtensions.length; i++) {
507                                    if (StringPool.STAR.equals(fileExtensions[i]) ||
508                                            StringUtil.endsWith(fileName, fileExtensions[i])) {
509    
510                                            validFileExtension = true;
511    
512                                            break;
513                                    }
514                            }
515    
516                            if (!validFileExtension) {
517                                    throw new FileExtensionException(fileName);
518                            }
519                    }
520            }
521    
522            public void validate(
523                            String fileName, boolean validateFileExtension, byte[] bytes)
524                    throws PortalException, SystemException {
525    
526                    validate(fileName, validateFileExtension);
527    
528                    if ((PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE) > 0) &&
529                            ((bytes == null) ||
530                             (bytes.length >
531                                     PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE)))) {
532    
533                            throw new FileSizeException(fileName);
534                    }
535            }
536    
537            public void validate(
538                            String fileName, boolean validateFileExtension, File file)
539                    throws PortalException, SystemException {
540    
541                    validate(fileName, validateFileExtension);
542    
543                    if ((PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE) > 0) &&
544                            ((file == null) ||
545                             (file.length() >
546                                    PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE)))) {
547    
548                            throw new FileSizeException(fileName);
549                    }
550            }
551    
552            public void validate(
553                            String fileName, boolean validateFileExtension, InputStream is)
554                    throws PortalException, SystemException {
555    
556                    validate(fileName, validateFileExtension);
557    
558                    // LEP-4851
559    
560                    try {
561                            if ((is == null) ||
562                                    ((PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE) > 0) &&
563                                     (is.available() >
564                                            PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE)))) {
565    
566                                    throw new FileSizeException(fileName);
567                            }
568                    }
569                    catch (IOException ioe) {
570                            throw new FileSizeException(ioe.getMessage());
571                    }
572            }
573    
574            public void validate(
575                            String fileName, String fileExtension, String sourceFileName,
576                            boolean validateFileExtension, File file)
577                    throws PortalException, SystemException {
578    
579                    validate(
580                            fileName, fileExtension, sourceFileName, validateFileExtension);
581    
582                    if ((file != null) &&
583                            (PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE) > 0) &&
584                            (file.length() >
585                                    PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE))) {
586    
587                            throw new FileSizeException(fileName);
588                    }
589            }
590    
591            public void validate(
592                            String fileName, String fileExtension, String sourceFileName,
593                            boolean validateFileExtension, InputStream is)
594                    throws PortalException, SystemException {
595    
596                    validate(
597                            fileName, fileExtension, sourceFileName, validateFileExtension);
598    
599                    try {
600                            if ((is != null) &&
601                                    (PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE) > 0) &&
602                                    (is.available() >
603                                            PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE))) {
604    
605                                    throw new FileSizeException(fileName);
606                            }
607                    }
608                    catch (IOException ioe) {
609                            throw new FileSizeException(ioe.getMessage());
610                    }
611            }
612    
613            protected boolean isValidName(String name) {
614                    if ((name == null) ||
615                            name.contains("\\") ||
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    
630                            return false;
631                    }
632    
633                    return true;
634            }
635    
636            protected void validate(
637                            String fileName, String fileExtension, String sourceFileName,
638                            boolean validateFileExtension)
639                    throws PortalException, SystemException {
640    
641                    String sourceFileExtension = FileUtil.getExtension(sourceFileName);
642    
643                    if (Validator.isNotNull(sourceFileName) &&
644                            PropsValues.DL_FILE_EXTENSIONS_STRICT_CHECK &&
645                            !fileExtension.equals(sourceFileExtension)) {
646    
647                            throw new SourceFileNameException(sourceFileExtension);
648                    }
649    
650                    validate(fileName, validateFileExtension);
651            }
652    
653            @BeanReference(type = GroupLocalService.class)
654            protected GroupLocalService groupLocalService;
655    
656            @BeanReference(type = Store.class)
657            protected Store store;
658    
659            private static final String[] _KEYWORDS_FIELDS = {
660                    Field.ASSET_TAG_NAMES, Field.CONTENT, Field.PROPERTIES
661            };
662    
663    }