Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
SummaryHelpers.java
Go to the documentation of this file.
1/*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2020 Basis Technology Corp.
5 * Contact: carrier <at> sleuthkit <dot> org
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19package org.sleuthkit.autopsy.discovery.search;
20
21import com.google.common.io.Files;
22import java.awt.Image;
23import java.io.BufferedReader;
24import java.io.File;
25import java.io.FileReader;
26import java.io.FileWriter;
27import java.io.IOException;
28import java.io.Reader;
29import java.nio.file.Paths;
30import java.util.Collection;
31import java.util.logging.Level;
32import org.apache.commons.lang.StringUtils;
33import org.openide.util.Lookup;
34import org.openide.util.NbBundle;
35import org.sleuthkit.autopsy.casemodule.Case;
36import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
37import org.sleuthkit.autopsy.coreutils.ImageUtils;
38import org.sleuthkit.autopsy.coreutils.Logger;
39import org.sleuthkit.autopsy.textextractors.TextExtractor;
40import org.sleuthkit.autopsy.textextractors.TextExtractorFactory;
41import org.sleuthkit.autopsy.textsummarizer.TextSummarizer;
42import org.sleuthkit.autopsy.textsummarizer.TextSummary;
43import org.sleuthkit.autopsy.texttranslation.NoServiceProviderException;
44import org.sleuthkit.autopsy.texttranslation.TextTranslationService;
45import org.sleuthkit.autopsy.texttranslation.TranslationException;
46import org.sleuthkit.datamodel.AbstractFile;
47import org.sleuthkit.datamodel.Content;
48import org.sleuthkit.datamodel.TskCoreException;
49
53class SummaryHelpers {
54
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;
58
59 private SummaryHelpers() {
60 // Class should not be instantiated
61 }
62
70 static TextSummary getDefaultSummary(AbstractFile file) {
71 Image image = null;
72 int countOfImages = 0;
73 try {
74 Content largestChild = null;
75 for (Content child : file.getChildren()) {
76 if (child instanceof AbstractFile && ImageUtils.isImageThumbnailSupported((AbstractFile) child)) {
77 countOfImages++;
78 if (largestChild == null || child.getSize() > largestChild.getSize()) {
79 largestChild = child;
80 }
81 }
82 }
83 if (largestChild != null) {
84 image = ImageUtils.getThumbnail(largestChild, ImageUtils.ICON_SIZE_LARGE);
85 }
86 } catch (TskCoreException ex) {
87 logger.log(Level.WARNING, "Error getting children for file: " + file.getId(), ex);
88 }
89 image = image == null ? image : image.getScaledInstance(ImageUtils.ICON_SIZE_MEDIUM, ImageUtils.ICON_SIZE_MEDIUM,
90 Image.SCALE_SMOOTH);
91 String summaryText = null;
92 if (file.getMd5Hash() != null) {
93 try {
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);
97 }
98 }
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) {
105 try {
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);
109 }
110 }
111 } else {
112 summaryText = firstLines;
113 }
114 }
115 return new TextSummary(summaryText, image, countOfImages);
116 }
117
127 static String getTranslatedVersion(String documentString) {
128 try {
129 TextTranslationService translatorInstance = TextTranslationService.getInstance();
130 if (translatorInstance.hasProvider()) {
131 String translatedResult = translatorInstance.translate(documentString);
132 if (translatedResult.isEmpty() == false) {
133 return translatedResult;
134 }
135 }
136 } catch (NoServiceProviderException | TranslationException ex) {
137 logger.log(Level.INFO, "Error translating string for summary", ex);
138 }
139 return null;
140 }
141
151 static String getSavedSummary(String summarySavePath) {
152 if (summarySavePath == null) {
153 return null;
154 }
155 File savedFile = new File(summarySavePath);
156 if (savedFile.exists()) {
157 try (BufferedReader bReader = new BufferedReader(new FileReader(savedFile))) {
158 // pass the path to the file as a parameter
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();
164 }
165 return sBuilder.toString();
166 } catch (IOException ingored) {
167 //summary file may not exist or may be incomplete in which case return null so a summary can be generated
168 return null; //no saved summary was able to be found
169 }
170 } else {
171 try { //if the file didn't exist make sure the parent directories exist before we move on to creating a summary
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);
175 }
176 return null; //no saved summary was able to be found
177 }
178
179 }
180
187 static void saveSummary(String summary, String summarySavePath) {
188 if (summarySavePath == null) {
189 return; //can't save a summary if we don't have a path
190 }
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);
195 }
196 }
197
198 @NbBundle.Messages({"SummaryHelper.documentSummary.unable.to.read=Error trying to extract text from file."})
206 static String getFirstLines(AbstractFile file) {
207 TextExtractor extractor;
208 try {
209 extractor = TextExtractorFactory.getExtractor(file, null);
210 } catch (TextExtractorFactory.NoTextExtractorFound ignored) {
211 //no extractor found, use Strings Extractor
212 extractor = TextExtractorFactory.getStringsExtractor(file, null);
213 }
214
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();
223 }
224 }
225
233 static TextSummarizer getLocalSummarizer() {
234 if (summarizerToUse == null) {
235 Collection<? extends TextSummarizer> summarizers
236 = Lookup.getDefault().lookupAll(TextSummarizer.class
237 );
238 if (!summarizers.isEmpty()) {
239 summarizerToUse = summarizers.iterator().next();
240 }
241 }
242 return summarizerToUse;
243 }
244
245}

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.