001
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.ArrayUtil;
033 import com.liferay.portal.kernel.util.FileUtil;
034 import com.liferay.portal.kernel.util.PropsKeys;
035 import com.liferay.portal.kernel.util.StringPool;
036 import com.liferay.portal.kernel.util.StringUtil;
037 import com.liferay.portal.kernel.util.UnicodeFormatter;
038 import com.liferay.portal.kernel.util.Validator;
039 import com.liferay.portal.model.Group;
040 import com.liferay.portal.security.permission.ActionKeys;
041 import com.liferay.portal.security.permission.PermissionChecker;
042 import com.liferay.portal.security.permission.PermissionThreadLocal;
043 import com.liferay.portal.service.GroupLocalService;
044 import com.liferay.portal.util.PrefsPropsUtil;
045 import com.liferay.portal.util.PropsValues;
046 import com.liferay.portlet.documentlibrary.DirectoryNameException;
047 import com.liferay.portlet.documentlibrary.FileExtensionException;
048 import com.liferay.portlet.documentlibrary.FileNameException;
049 import com.liferay.portlet.documentlibrary.FileSizeException;
050 import com.liferay.portlet.documentlibrary.FolderNameException;
051 import com.liferay.portlet.documentlibrary.InvalidFileVersionException;
052 import com.liferay.portlet.documentlibrary.SourceFileNameException;
053 import com.liferay.portlet.documentlibrary.antivirus.AntivirusScannerUtil;
054 import com.liferay.portlet.documentlibrary.model.DLFileEntryConstants;
055 import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
056 import com.liferay.portlet.documentlibrary.service.permission.DLFolderPermission;
057 import com.liferay.portlet.documentlibrary.util.DLUtil;
058
059 import java.io.File;
060 import java.io.IOException;
061 import java.io.InputStream;
062
063
068 public class DLStoreImpl implements DLStore {
069
070 @Override
071 public void addDirectory(long companyId, long repositoryId, String dirName)
072 throws PortalException, SystemException {
073
074 if (!isValidName(dirName) || dirName.equals("/")) {
075 throw new DirectoryNameException(dirName);
076 }
077
078 store.addDirectory(companyId, repositoryId, dirName);
079 }
080
081 @Override
082 public void addFile(
083 long companyId, long repositoryId, String fileName,
084 boolean validateFileExtension, byte[] bytes)
085 throws PortalException, SystemException {
086
087 validate(fileName, validateFileExtension, bytes);
088
089 if (PropsValues.DL_STORE_ANTIVIRUS_ENABLED) {
090 AntivirusScannerUtil.scan(bytes);
091 }
092
093 store.addFile(companyId, repositoryId, fileName, bytes);
094 }
095
096 @Override
097 public void addFile(
098 long companyId, long repositoryId, String fileName,
099 boolean validateFileExtension, File file)
100 throws PortalException, SystemException {
101
102 validate(fileName, validateFileExtension, file);
103
104 if (PropsValues.DL_STORE_ANTIVIRUS_ENABLED) {
105 AntivirusScannerUtil.scan(file);
106 }
107
108 store.addFile(companyId, repositoryId, fileName, file);
109 }
110
111 @Override
112 public void addFile(
113 long companyId, long repositoryId, String fileName,
114 boolean validateFileExtension, InputStream is)
115 throws PortalException, SystemException {
116
117 if (is instanceof ByteArrayFileInputStream) {
118 ByteArrayFileInputStream byteArrayFileInputStream =
119 (ByteArrayFileInputStream)is;
120
121 File file = byteArrayFileInputStream.getFile();
122
123 addFile(
124 companyId, repositoryId, fileName, validateFileExtension, file);
125
126 return;
127 }
128
129 validate(fileName, validateFileExtension, is);
130
131 if (!PropsValues.DL_STORE_ANTIVIRUS_ENABLED ||
132 !AntivirusScannerUtil.isActive()) {
133
134 store.addFile(companyId, repositoryId, fileName, is);
135 }
136 else {
137 File tempFile = null;
138
139 try {
140 if (is.markSupported()) {
141 is.mark(is.available() + 1);
142
143 AntivirusScannerUtil.scan(is);
144
145 is.reset();
146
147 store.addFile(companyId, repositoryId, fileName, is);
148 }
149 else {
150 tempFile = FileUtil.createTempFile();
151
152 FileUtil.write(tempFile, is);
153
154 AntivirusScannerUtil.scan(tempFile);
155
156 store.addFile(companyId, repositoryId, fileName, tempFile);
157 }
158 }
159 catch (IOException ioe) {
160 throw new SystemException(
161 "Unable to scan file " + fileName, ioe);
162 }
163 finally {
164 if (tempFile != null) {
165 tempFile.delete();
166 }
167 }
168 }
169 }
170
171 @Override
172 public void addFile(
173 long companyId, long repositoryId, String fileName, byte[] bytes)
174 throws PortalException, SystemException {
175
176 addFile(companyId, repositoryId, fileName, true, bytes);
177 }
178
179 @Override
180 public void addFile(
181 long companyId, long repositoryId, String fileName, File file)
182 throws PortalException, SystemException {
183
184 addFile(companyId, repositoryId, fileName, true, file);
185 }
186
187 @Override
188 public void addFile(
189 long companyId, long repositoryId, String fileName, InputStream is)
190 throws PortalException, SystemException {
191
192 addFile(companyId, repositoryId, fileName, true, is);
193 }
194
195 @Override
196 public void checkRoot(long companyId) throws SystemException {
197 store.checkRoot(companyId);
198 }
199
200 @Override
201 public void copyFileVersion(
202 long companyId, long repositoryId, String fileName,
203 String fromVersionLabel, String toVersionLabel)
204 throws PortalException, SystemException {
205
206 store.copyFileVersion(
207 companyId, repositoryId, fileName, fromVersionLabel,
208 toVersionLabel);
209 }
210
211 @Override
212 public void deleteDirectory(
213 long companyId, long repositoryId, String dirName)
214 throws PortalException, SystemException {
215
216 store.deleteDirectory(companyId, repositoryId, dirName);
217 }
218
219 @Override
220 public void deleteFile(long companyId, long repositoryId, String fileName)
221 throws PortalException, SystemException {
222
223 validate(fileName, false);
224
225 store.deleteFile(companyId, repositoryId, fileName);
226 }
227
228 @Override
229 public void deleteFile(
230 long companyId, long repositoryId, String fileName,
231 String versionLabel)
232 throws PortalException, SystemException {
233
234 validate(fileName, false, versionLabel);
235
236 store.deleteFile(companyId, repositoryId, fileName, versionLabel);
237 }
238
239 @Override
240 public File getFile(long companyId, long repositoryId, String fileName)
241 throws PortalException, SystemException {
242
243 validate(fileName, false);
244
245 return store.getFile(companyId, repositoryId, fileName);
246 }
247
248 @Override
249 public File getFile(
250 long companyId, long repositoryId, String fileName,
251 String versionLabel)
252 throws PortalException, SystemException {
253
254 validate(fileName, false, versionLabel);
255
256 return store.getFile(companyId, repositoryId, fileName, versionLabel);
257 }
258
259 @Override
260 public byte[] getFileAsBytes(
261 long companyId, long repositoryId, String fileName)
262 throws PortalException, SystemException {
263
264 validate(fileName, false);
265
266 return store.getFileAsBytes(companyId, repositoryId, fileName);
267 }
268
269 @Override
270 public byte[] getFileAsBytes(
271 long companyId, long repositoryId, String fileName,
272 String versionLabel)
273 throws PortalException, SystemException {
274
275 validate(fileName, false, versionLabel);
276
277 return store.getFileAsBytes(
278 companyId, repositoryId, fileName, versionLabel);
279 }
280
281 @Override
282 public InputStream getFileAsStream(
283 long companyId, long repositoryId, String fileName)
284 throws PortalException, SystemException {
285
286 validate(fileName, false);
287
288 return store.getFileAsStream(companyId, repositoryId, fileName);
289 }
290
291 @Override
292 public InputStream getFileAsStream(
293 long companyId, long repositoryId, String fileName,
294 String versionLabel)
295 throws PortalException, SystemException {
296
297 validate(fileName, false, versionLabel);
298
299 return store.getFileAsStream(
300 companyId, repositoryId, fileName, versionLabel);
301 }
302
303 @Override
304 public String[] getFileNames(
305 long companyId, long repositoryId, String dirName)
306 throws PortalException, SystemException {
307
308 if (!isValidName(dirName)) {
309 throw new DirectoryNameException(dirName);
310 }
311
312 return store.getFileNames(companyId, repositoryId, dirName);
313 }
314
315 @Override
316 public long getFileSize(long companyId, long repositoryId, String fileName)
317 throws PortalException, SystemException {
318
319 validate(fileName, false);
320
321 return store.getFileSize(companyId, repositoryId, fileName);
322 }
323
324 @Override
325 public boolean hasDirectory(
326 long companyId, long repositoryId, String dirName)
327 throws PortalException, SystemException {
328
329 if (!isValidName(dirName)) {
330 throw new DirectoryNameException(dirName);
331 }
332
333 return store.hasDirectory(companyId, repositoryId, dirName);
334 }
335
336 @Override
337 public boolean hasFile(long companyId, long repositoryId, String fileName)
338 throws PortalException, SystemException {
339
340 validate(fileName, false);
341
342 return store.hasFile(companyId, repositoryId, fileName);
343 }
344
345 @Override
346 public boolean hasFile(
347 long companyId, long repositoryId, String fileName,
348 String versionLabel)
349 throws PortalException, SystemException {
350
351 validate(fileName, false, versionLabel);
352
353 return store.hasFile(companyId, repositoryId, fileName, versionLabel);
354 }
355
356 @Override
357 public boolean isValidName(String name) {
358 if (Validator.isNull(name)) {
359 return false;
360 }
361
362 for (String blacklistChar : PropsValues.DL_CHAR_BLACKLIST) {
363 if (name.contains(blacklistChar)) {
364 return false;
365 }
366 }
367
368 for (String blacklistLastChar : PropsValues.DL_CHAR_LAST_BLACKLIST) {
369 if (blacklistLastChar.startsWith(_UNICODE_PREFIX)) {
370 blacklistLastChar = UnicodeFormatter.parseString(
371 blacklistLastChar);
372 }
373
374 if (name.endsWith(blacklistLastChar)) {
375 return false;
376 }
377 }
378
379 String nameWithoutExtension = name;
380
381 if (name.contains(StringPool.PERIOD)) {
382 int index = name.lastIndexOf(StringPool.PERIOD);
383
384 nameWithoutExtension = name.substring(0, index);
385 }
386
387 for (String blacklistName : PropsValues.DL_NAME_BLACKLIST) {
388 if (StringUtil.equalsIgnoreCase(
389 nameWithoutExtension, blacklistName)) {
390
391 return false;
392 }
393 }
394
395 return true;
396 }
397
398 @Override
399 public void move(String srcDir, String destDir) throws SystemException {
400 store.move(srcDir, destDir);
401 }
402
403 public Hits search(
404 long companyId, long userId, String portletId, long groupId,
405 long[] repositoryIds, String keywords, int start, int end)
406 throws SystemException {
407
408 try {
409 SearchContext searchContext = new SearchContext();
410
411 searchContext.setCompanyId(companyId);
412 searchContext.setEnd(end);
413 searchContext.setEntryClassNames(
414 new String[] {DLFileEntryConstants.getClassName()});
415 searchContext.setGroupIds(new long[] {groupId});
416
417 Indexer indexer = IndexerRegistryUtil.getIndexer(
418 DLFileEntryConstants.getClassName());
419
420 searchContext.setSearchEngineId(indexer.getSearchEngineId());
421
422 searchContext.setStart(start);
423 searchContext.setUserId(userId);
424
425 BooleanQuery contextQuery = BooleanQueryFactoryUtil.create(
426 searchContext);
427
428 contextQuery.addRequiredTerm(Field.PORTLET_ID, portletId);
429
430 if (groupId > 0) {
431 Group group = groupLocalService.getGroup(groupId);
432
433 if (group.isLayout()) {
434 contextQuery.addRequiredTerm(Field.SCOPE_GROUP_ID, groupId);
435
436 groupId = group.getParentGroupId();
437 }
438
439 contextQuery.addRequiredTerm(Field.GROUP_ID, groupId);
440 }
441
442 if (ArrayUtil.isNotEmpty(repositoryIds)) {
443 BooleanQuery repositoryIdsQuery =
444 BooleanQueryFactoryUtil.create(searchContext);
445
446 for (long repositoryId : repositoryIds) {
447 try {
448 if (userId > 0) {
449 PermissionChecker permissionChecker =
450 PermissionThreadLocal.getPermissionChecker();
451
452 DLFolderPermission.check(
453 permissionChecker, groupId, repositoryId,
454 ActionKeys.VIEW);
455 }
456
457 if (repositoryId ==
458 DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
459
460 repositoryId = groupId;
461 }
462
463 TermQuery termQuery = TermQueryFactoryUtil.create(
464 searchContext, "repositoryId", repositoryId);
465
466 repositoryIdsQuery.add(
467 termQuery, BooleanClauseOccur.SHOULD);
468 }
469 catch (Exception e) {
470 }
471 }
472
473 contextQuery.add(repositoryIdsQuery, BooleanClauseOccur.MUST);
474 }
475
476 BooleanQuery searchQuery = BooleanQueryFactoryUtil.create(
477 searchContext);
478
479 searchQuery.addTerms(_KEYWORDS_FIELDS, keywords);
480
481 BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(
482 searchContext);
483
484 fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
485
486 if (searchQuery.clauses().size() > 0) {
487 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
488 }
489
490 return SearchEngineUtil.search(searchContext, fullQuery);
491 }
492 catch (Exception e) {
493 throw new SystemException(e);
494 }
495 }
496
497 @Override
498 public void updateFile(
499 long companyId, long repositoryId, long newRepositoryId,
500 String fileName)
501 throws PortalException, SystemException {
502
503 store.updateFile(companyId, repositoryId, newRepositoryId, fileName);
504 }
505
506 @Override
507 public void updateFile(
508 long companyId, long repositoryId, String fileName,
509 String newFileName)
510 throws PortalException, SystemException {
511
512 store.updateFile(companyId, repositoryId, fileName, newFileName);
513 }
514
515 @Override
516 public void updateFile(
517 long companyId, long repositoryId, String fileName,
518 String fileExtension, boolean validateFileExtension,
519 String versionLabel, String sourceFileName, File file)
520 throws PortalException, SystemException {
521
522 validate(
523 fileName, fileExtension, sourceFileName, validateFileExtension,
524 file, versionLabel);
525
526 if (PropsValues.DL_STORE_ANTIVIRUS_ENABLED) {
527 AntivirusScannerUtil.scan(file);
528 }
529
530 store.updateFile(companyId, repositoryId, fileName, versionLabel, file);
531 }
532
533 @Override
534 public void updateFile(
535 long companyId, long repositoryId, String fileName,
536 String fileExtension, boolean validateFileExtension,
537 String versionLabel, String sourceFileName, InputStream is)
538 throws PortalException, SystemException {
539
540 if (is instanceof ByteArrayFileInputStream) {
541 ByteArrayFileInputStream byteArrayFileInputStream =
542 (ByteArrayFileInputStream)is;
543
544 File file = byteArrayFileInputStream.getFile();
545
546 updateFile(
547 companyId, repositoryId, fileName, fileExtension,
548 validateFileExtension, versionLabel, sourceFileName, file);
549
550 return;
551 }
552
553 validate(
554 fileName, fileExtension, sourceFileName, validateFileExtension, is,
555 versionLabel);
556
557 if (!PropsValues.DL_STORE_ANTIVIRUS_ENABLED ||
558 !AntivirusScannerUtil.isActive()) {
559
560 store.updateFile(
561 companyId, repositoryId, fileName, versionLabel, is);
562 }
563 else {
564 File tempFile = null;
565
566 try {
567 if (is.markSupported()) {
568 is.mark(is.available() + 1);
569
570 AntivirusScannerUtil.scan(is);
571
572 is.reset();
573
574 store.updateFile(
575 companyId, repositoryId, fileName, versionLabel, is);
576 }
577 else {
578 tempFile = FileUtil.createTempFile();
579
580 FileUtil.write(tempFile, is);
581
582 AntivirusScannerUtil.scan(tempFile);
583
584 store.updateFile(
585 companyId, repositoryId, fileName, versionLabel,
586 tempFile);
587 }
588 }
589 catch (IOException ioe) {
590 throw new SystemException(
591 "Unable to scan file " + fileName, ioe);
592 }
593 finally {
594 if (tempFile != null) {
595 tempFile.delete();
596 }
597 }
598 }
599 }
600
601 @Override
602 public void updateFileVersion(
603 long companyId, long repositoryId, String fileName,
604 String fromVersionLabel, String toVersionLabel)
605 throws PortalException, SystemException {
606
607 store.updateFileVersion(
608 companyId, repositoryId, fileName, fromVersionLabel,
609 toVersionLabel);
610 }
611
612 @Override
613 public void validate(String fileName, boolean validateFileExtension)
614 throws PortalException, SystemException {
615
616 if (!isValidName(fileName)) {
617 throw new FileNameException(fileName);
618 }
619
620 if (validateFileExtension) {
621 boolean validFileExtension = false;
622
623 String[] fileExtensions = PrefsPropsUtil.getStringArray(
624 PropsKeys.DL_FILE_EXTENSIONS, StringPool.COMMA);
625
626 for (String fileExtension : fileExtensions) {
627 if (StringPool.STAR.equals(fileExtension) ||
628 StringUtil.endsWith(fileName, fileExtension)) {
629
630 validFileExtension = true;
631
632 break;
633 }
634 }
635
636 if (!validFileExtension) {
637 throw new FileExtensionException(fileName);
638 }
639 }
640 }
641
642 @Override
643 public void validate(
644 String fileName, boolean validateFileExtension, byte[] bytes)
645 throws PortalException, SystemException {
646
647 validate(fileName, validateFileExtension);
648
649 if ((PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE) > 0) &&
650 ((bytes == null) ||
651 (bytes.length >
652 PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE)))) {
653
654 throw new FileSizeException(fileName);
655 }
656 }
657
658 @Override
659 public void validate(
660 String fileName, boolean validateFileExtension, File file)
661 throws PortalException, SystemException {
662
663 validate(fileName, validateFileExtension);
664
665 if ((PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE) > 0) &&
666 ((file == null) ||
667 (file.length() >
668 PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE)))) {
669
670 throw new FileSizeException(fileName);
671 }
672 }
673
674 @Override
675 public void validate(
676 String fileName, boolean validateFileExtension, InputStream is)
677 throws PortalException, SystemException {
678
679 validate(fileName, validateFileExtension);
680
681
682
683 try {
684 if ((is == null) ||
685 ((PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE) > 0) &&
686 (is.available() >
687 PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE)))) {
688
689 throw new FileSizeException(fileName);
690 }
691 }
692 catch (IOException ioe) {
693 throw new FileSizeException(ioe.getMessage());
694 }
695 }
696
697 @Override
698 public void validate(
699 String fileName, String fileExtension, String sourceFileName,
700 boolean validateFileExtension, File file)
701 throws PortalException, SystemException {
702
703 validate(
704 fileName, fileExtension, sourceFileName, validateFileExtension,
705 StringPool.BLANK);
706
707 if ((file != null) &&
708 (PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE) > 0) &&
709 (file.length() >
710 PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE))) {
711
712 throw new FileSizeException(fileName);
713 }
714 }
715
716 @Override
717 public void validate(
718 String fileName, String fileExtension, String sourceFileName,
719 boolean validateFileExtension, InputStream is)
720 throws PortalException, SystemException {
721
722 validate(
723 fileName, fileExtension, sourceFileName, validateFileExtension,
724 StringPool.BLANK);
725
726 try {
727 if ((is != null) &&
728 (PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE) > 0) &&
729 (is.available() >
730 PrefsPropsUtil.getLong(PropsKeys.DL_FILE_MAX_SIZE))) {
731
732 throw new FileSizeException(fileName);
733 }
734 }
735 catch (IOException ioe) {
736 throw new FileSizeException(ioe.getMessage());
737 }
738 }
739
740 @Override
741 public void validateDirectoryName(String directoryName)
742 throws PortalException {
743
744 if (!isValidName(directoryName)) {
745 throw new FolderNameException(directoryName);
746 }
747 }
748
749 protected void isValidVersion(String versionLabel) throws PortalException {
750 if (Validator.isNull(versionLabel)) {
751 return;
752 }
753
754 if (!DLUtil.isValidVersion(versionLabel)) {
755 throw new InvalidFileVersionException();
756 }
757 }
758
759 protected void validate(
760 String fileName, boolean validateFileExtension, String versionLabel)
761 throws PortalException, SystemException {
762
763 isValidVersion(versionLabel);
764
765 validate(fileName, validateFileExtension);
766 }
767
768 protected void validate(
769 String fileName, String fileExtension, String sourceFileName,
770 boolean validateFileExtension, File file, String versionLabel)
771 throws PortalException, SystemException {
772
773 isValidVersion(versionLabel);
774
775 validate(
776 fileName, fileExtension, sourceFileName, validateFileExtension,
777 file);
778 }
779
780 protected void validate(
781 String fileName, String fileExtension, String sourceFileName,
782 boolean validateFileExtension, InputStream is, String versionLabel)
783 throws PortalException, SystemException {
784
785 isValidVersion(versionLabel);
786
787 validate(
788 fileName, fileExtension, sourceFileName, validateFileExtension, is);
789 }
790
791 protected void validate(
792 String fileName, String fileExtension, String sourceFileName,
793 boolean validateFileExtension, String versionLabel)
794 throws PortalException, SystemException {
795
796 String sourceFileExtension = FileUtil.getExtension(sourceFileName);
797
798 if (Validator.isNotNull(sourceFileName) &&
799 PropsValues.DL_FILE_EXTENSIONS_STRICT_CHECK &&
800 !fileExtension.equals(sourceFileExtension)) {
801
802 throw new SourceFileNameException(sourceFileExtension);
803 }
804
805 validate(fileName, validateFileExtension, versionLabel);
806 }
807
808 @BeanReference(type = GroupLocalService.class)
809 protected GroupLocalService groupLocalService;
810
811 @BeanReference(type = Store.class)
812 protected Store store;
813
814 private static final String[] _KEYWORDS_FIELDS = {
815 Field.ASSET_TAG_NAMES, Field.CONTENT, Field.PROPERTIES
816 };
817
818 private static final String _UNICODE_PREFIX = "\\u";
819
820 }