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