19 package org.sleuthkit.autopsy.discovery.search;
 
   21 import com.google.common.io.Files;
 
   22 import java.awt.Image;
 
   23 import java.io.BufferedReader;
 
   25 import java.io.FileReader;
 
   26 import java.io.FileWriter;
 
   27 import java.io.IOException;
 
   28 import java.io.Reader;
 
   29 import java.nio.file.Paths;
 
   30 import java.util.Collection;
 
   31 import java.util.logging.Level;
 
   32 import org.apache.commons.lang.StringUtils;
 
   33 import org.openide.util.Lookup;
 
   34 import org.openide.util.NbBundle;
 
   53 class SummaryHelpers {
 
   55     private static final int PREVIEW_SIZE = 256;
 
   56     private final static Logger logger = Logger.getLogger(SummaryHelpers.class.getName());
 
   57     private static volatile TextSummarizer summarizerToUse = null;
 
   59     private SummaryHelpers() {
 
   70     static TextSummary getDefaultSummary(AbstractFile file) {
 
   72         int countOfImages = 0;
 
   74             Content largestChild = null;
 
   75             for (Content child : file.getChildren()) {
 
   76                 if (child instanceof AbstractFile && ImageUtils.isImageThumbnailSupported((AbstractFile) child)) {
 
   78                     if (largestChild == null || child.getSize() > largestChild.getSize()) {
 
   83             if (largestChild != null) {
 
   84                 image = ImageUtils.getThumbnail(largestChild, ImageUtils.ICON_SIZE_LARGE);
 
   86         } 
catch (TskCoreException ex) {
 
   87             logger.log(Level.WARNING, 
"Error getting children for file: " + file.getId(), ex);
 
   89         image = image == null ? image : image.getScaledInstance(ImageUtils.ICON_SIZE_MEDIUM, ImageUtils.ICON_SIZE_MEDIUM,
 
   91         String summaryText = null;
 
   92         if (file.getMd5Hash() != null) {
 
   94                 summaryText = getSavedSummary(Paths.get(Case.getCurrentCaseThrows().getCacheDirectory(), 
"summaries", file.getMd5Hash() + 
"-default-" + PREVIEW_SIZE + 
"-translated.txt").toString());
 
   95             } 
catch (NoCurrentCaseException ex) {
 
   96                 logger.log(Level.WARNING, 
"Unable to retrieve saved summary. No case is open.", ex);
 
   99         if (StringUtils.isBlank(summaryText)) {
 
  100             String firstLines = getFirstLines(file);
 
  101             String translatedFirstLines = getTranslatedVersion(firstLines);
 
  102             if (!StringUtils.isBlank(translatedFirstLines)) {
 
  103                 summaryText = translatedFirstLines;
 
  104                 if (file.getMd5Hash() != null) {
 
  106                         saveSummary(summaryText, Paths.get(Case.getCurrentCaseThrows().getCacheDirectory(), 
"summaries", file.getMd5Hash() + 
"-default-" + PREVIEW_SIZE + 
"-translated.txt").toString());
 
  107                     } 
catch (NoCurrentCaseException ex) {
 
  108                         logger.log(Level.WARNING, 
"Unable to save translated summary. No case is open.", ex);
 
  112                 summaryText = firstLines;
 
  115         return new TextSummary(summaryText, image, countOfImages);
 
  127     static String getTranslatedVersion(String documentString) {
 
  129             TextTranslationService translatorInstance = TextTranslationService.getInstance();
 
  130             if (translatorInstance.hasProvider()) {
 
  131                 String translatedResult = translatorInstance.translate(documentString);
 
  132                 if (translatedResult.isEmpty() == 
false) {
 
  133                     return translatedResult;
 
  136         } 
catch (NoServiceProviderException | TranslationException ex) {
 
  137             logger.log(Level.INFO, 
"Error translating string for summary", ex);
 
  151     static String getSavedSummary(String summarySavePath) {
 
  152         if (summarySavePath == null) {
 
  155         File savedFile = 
new File(summarySavePath);
 
  156         if (savedFile.exists()) {
 
  157             try (BufferedReader bReader = 
new BufferedReader(
new FileReader(savedFile))) {
 
  159                 StringBuilder sBuilder = 
new StringBuilder(PREVIEW_SIZE);
 
  160                 String sCurrentLine = bReader.readLine();
 
  161                 while (sCurrentLine != null) {
 
  162                     sBuilder.append(sCurrentLine).append(
'\n');
 
  163                     sCurrentLine = bReader.readLine();
 
  165                 return sBuilder.toString();
 
  166             } 
catch (IOException ingored) {
 
  172                 Files.createParentDirs(savedFile);
 
  173             } 
catch (IOException ex) {
 
  174                 logger.log(Level.WARNING, 
"Unable to create summaries directory in case folder for file at: " + summarySavePath, ex);
 
  187     static void saveSummary(String summary, String summarySavePath) {
 
  188         if (summarySavePath == null) {
 
  191         try (FileWriter myWriter = 
new FileWriter(summarySavePath)) {
 
  192             myWriter.write(summary);
 
  193         } 
catch (IOException ex) {
 
  194             logger.log(Level.WARNING, 
"Unable to save summary at: " + summarySavePath, ex);
 
  198     @NbBundle.Messages({
"SummaryHelper.documentSummary.unable.to.read=Error trying to extract text from file."})
 
  206     static String getFirstLines(AbstractFile file) {
 
  207         TextExtractor extractor;
 
  209             extractor = TextExtractorFactory.getExtractor(file, null);
 
  210         } 
catch (TextExtractorFactory.NoTextExtractorFound ignored) {
 
  212             extractor = TextExtractorFactory.getStringsExtractor(file, null);
 
  215         try (Reader reader = extractor.getReader()) {
 
  216             char[] cbuf = 
new char[PREVIEW_SIZE];
 
  217             reader.read(cbuf, 0, PREVIEW_SIZE);
 
  218             return new String(cbuf);
 
  219         } 
catch (IOException ex) {
 
  220             return Bundle.FileSearch_documentSummary_noBytes();
 
  221         } 
catch (TextExtractor.InitReaderException ex) {
 
  222             return Bundle.SummaryHelper_documentSummary_unable_to_read();
 
  233     static TextSummarizer getLocalSummarizer() {
 
  234         if (summarizerToUse == null) {
 
  235             Collection<? extends TextSummarizer> summarizers
 
  236                     = Lookup.getDefault().lookupAll(TextSummarizer.class
 
  238             if (!summarizers.isEmpty()) {
 
  239                 summarizerToUse = summarizers.iterator().next();
 
  242         return summarizerToUse;