Autopsy  4.19.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ExtractEdge.java
Go to the documentation of this file.
1 /*
2  *
3  * Autopsy Forensic Browser
4  *
5  * Copyright 2019-2021 Basis Technology Corp.
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  */
19 package org.sleuthkit.autopsy.recentactivity;
20 
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.text.ParseException;
28 import java.text.SimpleDateFormat;
29 import java.text.DateFormat;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.Collection;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Locale;
36 import java.util.Scanner;
37 import java.util.logging.Level;
38 import java.util.regex.Matcher;
39 import java.util.regex.Pattern;
40 import org.openide.modules.InstalledFileLocator;
41 import org.openide.util.NbBundle.Messages;
53 import org.sleuthkit.datamodel.AbstractFile;
54 import org.sleuthkit.datamodel.BlackboardArtifact;
55 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK;
56 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE;
57 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY;
58 import org.sleuthkit.datamodel.Content;
59 import org.sleuthkit.datamodel.TskCoreException;
60 
64 final class ExtractEdge extends Extract {
65 
66  private static final Logger LOG = Logger.getLogger(ExtractEdge.class.getName());
67  private Content dataSource;
68  private IngestJobContext context;
69  private HashMap<String, ArrayList<String>> containersTable;
70 
71  private static final String EDGE = "Edge"; //NON-NLS
72 
73  private static final String EDGE_KEYWORD_VISIT = "Visited:"; //NON-NLS
74  private static final String IGNORE_COMMA_IN_QUOTES_REGEX = ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)"; //NON-NLS
75 
76  private static final String EDGE_TABLE_TYPE_DOWNLOAD = "iedownload"; //NON-NLS
77  private static final String EDGE_TABLE_TYPE_HISTORY = "History"; //NON-NLS
78  private static final String EDGE_TABLE_TYPE_COOKIE = "cookie"; //NON-NLS
79 
80  private static final String EDGE_HEAD_URL = "url"; //NON-NLS
81  private static final String EDGE_HEAD_ACCESSTIME = "accessedtime"; //NON-NLS
82  private static final String EDGE_HEAD_NAME = "name"; //NON-NLS
83  private static final String EDGE_HEAD_CONTAINER_ID = "containerid"; //NON-NLS
84  private static final String EDGE_HEAD_RESPONSEHEAD = "responseheaders"; //NON-NLS
85  private static final String EDGE_HEAD_TITLE = "title"; //NON-NLS
86  private static final String EDGE_HEAD_RDOMAIN = "rdomain"; //NON-NLS
87  private static final String EDGE_HEAD_VALUE = "value"; //NON-NLS
88  private static final String EDGE_HEAD_LASTMOD = "lastmodified"; //NON-NLS
89 
90  private static final String EDGE_WEBCACHE_PREFIX = "WebCacheV01"; //NON-NLS
91  private static final String EDGE_CONTAINER_FILE_PREFIX = "Container_"; //NON-NLS
92  private static final String EDGE_CONTAINER_FILE_EXT = ".csv"; //NON-NLS
93  private static final String EDGE_WEBCACHE_EXT = ".dat"; //NON-NLS
94 
95  private static final String ESE_TOOL_NAME = "ESEDatabaseView.exe"; //NON-NLS
96  private static final String EDGE_WEBCACHE_NAME = "WebCacheV01.dat"; //NON-NLS
97  private static final String EDGE_SPARTAN_NAME = "Spartan.edb"; //NON-NLS
98  private static final String EDGE_CONTAINTERS_FILE_NAME = "Containers.csv"; //NON-NLS
99  private static final String EDGE_FAVORITE_FILE_NAME = "Favorites.csv"; //NON-NLS
100  private static final String EDGE_OUTPUT_FILE_NAME = "Output.txt"; //NON-NLS
101  private static final String EDGE_ERROR_FILE_NAME = "File.txt"; //NON-NLS
102  private static final String EDGE_WEBCACHE_FOLDER_NAME = "WebCache"; //NON-NLS
103  private static final String EDGE_SPARTAN_FOLDER_NAME = "MicrosoftEdge"; //NON-NLS
104 
105  private static final String ESE_TOOL_FOLDER = "ESEDatabaseView"; //NON-NLS
106  private static final String EDGE_RESULT_FOLDER_NAME = "results"; //NON-NLS
107 
108  // ESEDatabaseView converts long timestamps into a string based on the current locale,
109  // so the default format may not always work.
110  private SimpleDateFormat previouslyValidDateFormat = null;
111 
112  @Messages({
113  "ExtractEdge_process_errMsg_unableFindESEViewer=Unable to find ESEDatabaseViewer",
114  "ExtractEdge_process_errMsg_errGettingWebCacheFiles=Error trying to retrieving Edge WebCacheV01 file",
115  "ExtractEdge_process_errMsg_webcacheFail=Failure processing Microsoft Edge WebCacheV01.dat file",
116  "ExtractEdge_process_errMsg_spartanFail=Failure processing Microsoft Edge spartan.edb file",
117  "ExtractEdge_Module_Name=Microsoft Edge",
118  "ExtractEdge_getHistory_containerFileNotFound=Error while trying to analyze Edge history",
119  "Progress_Message_Edge_History=Microsoft Edge History",
120  "Progress_Message_Edge_Bookmarks=Microsoft Edge Bookmarks",
121  "Progress_Message_Edge_Cookies=Microsoft Edge Cookies",
122  })
123 
127  ExtractEdge() {
128  super(Bundle.ExtractEdge_Module_Name());
129  }
130 
131  @Override
132  protected String getName() {
133  return Bundle.ExtractEdge_Module_Name();
134  }
135 
136  @Override
137  void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
138  String moduleTempDir = RAImageIngestModule.getRATempPath(getCurrentCase(), EDGE, context.getJobId());
139  String moduleTempResultDir = Paths.get(moduleTempDir, EDGE_RESULT_FOLDER_NAME).toString();
140 
141  this.dataSource = dataSource;
142  this.context = context;
143  this.setFoundData(false);
144 
145  List<AbstractFile> webCacheFiles = null;
146  List<AbstractFile> spartanFiles = null;
147 
148  try {
149  webCacheFiles = fetchWebCacheDBFiles();
150  } catch (TskCoreException ex) {
151  this.addErrorMessage(Bundle.ExtractEdge_process_errMsg_errGettingWebCacheFiles());
152  LOG.log(Level.SEVERE, "Error fetching 'WebCacheV01.dat' files for Microsoft Edge", ex); //NON-NLS
153  }
154 
155  if (context.dataSourceIngestIsCancelled()) {
156  return;
157  }
158 
159  try {
160  spartanFiles = fetchSpartanDBFiles(); // For later use with bookmarks
161  } catch (TskCoreException ex) {
162  this.addErrorMessage(Bundle.ExtractEdge_process_errMsg_spartanFail());
163  LOG.log(Level.SEVERE, "Error fetching 'spartan.edb' files for Microsoft Edge", ex); //NON-NLS
164  }
165 
166  // No edge files found
167  if (webCacheFiles == null && spartanFiles == null) {
168  return;
169  }
170 
171  this.setFoundData(true);
172 
173  if (!PlatformUtil.isWindowsOS()) {
174  LOG.log(Level.WARNING, "Microsoft Edge files found, unable to parse on Non-Windows system"); //NON-NLS
175  return;
176  }
177 
178  if (context.dataSourceIngestIsCancelled()) {
179  return;
180  }
181 
182  final String esedumper = getPathForESEDumper();
183  if (esedumper == null) {
184  LOG.log(Level.SEVERE, "Error finding ESEDatabaseViewer program"); //NON-NLS
185  this.addErrorMessage(Bundle.ExtractEdge_process_errMsg_unableFindESEViewer());
186  return; //If we cannot find the ESEDatabaseView we cannot proceed
187  }
188 
189  try {
190  this.processWebCacheDbFile(esedumper, webCacheFiles, progressBar, moduleTempDir, moduleTempResultDir);
191  } catch (IOException | TskCoreException ex) {
192  LOG.log(Level.SEVERE, "Error processing 'WebCacheV01.dat' files for Microsoft Edge", ex); // NON-NLS
193  this.addErrorMessage(Bundle.ExtractEdge_process_errMsg_webcacheFail());
194  }
195 
196  progressBar.progress(Bundle.Progress_Message_Edge_Bookmarks());
197  try {
198  this.processSpartanDbFile(esedumper, spartanFiles, moduleTempDir, moduleTempResultDir);
199  } catch (IOException | TskCoreException ex) {
200  LOG.log(Level.SEVERE, "Error processing 'spartan.edb' files for Microsoft Edge", ex); // NON-NLS
201  this.addErrorMessage(Bundle.ExtractEdge_process_errMsg_spartanFail());
202  }
203  }
204 
216  void processWebCacheDbFile(String eseDumperPath, List<AbstractFile> webCacheFiles, DataSourceIngestModuleProgress progressBar,
217  String moduleTempDir, String moduleTempResultDir) throws IOException, TskCoreException {
218 
219  for (AbstractFile webCacheFile : webCacheFiles) {
220 
221  if (context.dataSourceIngestIsCancelled()) {
222  return;
223  }
224 
225  clearContainerTable();
226 
227  //Run the dumper
228  String tempWebCacheFileName = EDGE_WEBCACHE_PREFIX
229  + Integer.toString((int) webCacheFile.getId()) + EDGE_WEBCACHE_EXT; //NON-NLS
230  File tempWebCacheFile = new File(moduleTempDir, tempWebCacheFileName);
231 
232  try {
233  ContentUtils.writeToFile(webCacheFile, tempWebCacheFile,
234  context::dataSourceIngestIsCancelled);
235  } catch (IOException ex) {
236  throw new IOException("Error writingToFile: " + webCacheFile, ex); //NON-NLS
237  }
238 
239  File resultsDir = new File(moduleTempDir, Integer.toString((int) webCacheFile.getId()));
240  resultsDir.mkdirs();
241  try {
242  executeDumper(eseDumperPath, tempWebCacheFile.getAbsolutePath(),
243  resultsDir.getAbsolutePath());
244 
245  if (context.dataSourceIngestIsCancelled()) {
246  return;
247  }
248 
249  progressBar.progress(Bundle.Progress_Message_Edge_History());
250 
251  this.getHistory(webCacheFile, resultsDir);
252 
253  if (context.dataSourceIngestIsCancelled()) {
254  return;
255  }
256 
257  progressBar.progress(Bundle.Progress_Message_Edge_Cookies());
258 
259  this.getCookies(webCacheFile, resultsDir);
260 
261  } finally {
262  tempWebCacheFile.delete();
263  FileUtil.deleteFileDir(resultsDir);
264  }
265  }
266  }
267 
279  void processSpartanDbFile(String eseDumperPath, List<AbstractFile> spartanFiles,
280  String moduleTempDir, String moduleTempResultDir) throws IOException, TskCoreException {
281 
282  for (AbstractFile spartanFile : spartanFiles) {
283 
284  if (context.dataSourceIngestIsCancelled()) {
285  return;
286  }
287 
288  //Run the dumper
289  String tempSpartanFileName = EDGE_WEBCACHE_PREFIX
290  + Integer.toString((int) spartanFile.getId()) + EDGE_WEBCACHE_EXT;
291  File tempSpartanFile = new File(moduleTempDir, tempSpartanFileName);
292 
293  try {
294  ContentUtils.writeToFile(spartanFile, tempSpartanFile,
295  context::dataSourceIngestIsCancelled);
296  } catch (IOException ex) {
297  throw new IOException("Error writingToFile: " + spartanFile, ex); //NON-NLS
298  }
299 
300  File resultsDir = new File(moduleTempResultDir, Integer.toString((int) spartanFile.getId()));
301  resultsDir.mkdirs();
302  try {
303  executeDumper(eseDumperPath, tempSpartanFile.getAbsolutePath(),
304  resultsDir.getAbsolutePath());
305 
306  if (context.dataSourceIngestIsCancelled()) {
307  return;
308  }
309 
310  this.getBookmarks(spartanFile, resultsDir);
311 
312  } finally {
313  tempSpartanFile.delete();
314  FileUtil.deleteFileDir(resultsDir);
315  }
316  }
317  }
318 
328  private void getHistory(AbstractFile origFile, File resultDir) throws TskCoreException, FileNotFoundException {
329  ArrayList<File> historyFiles = getHistoryFiles(resultDir);
330 
331  if (historyFiles == null) {
332  return;
333  }
334 
335  for (File file : historyFiles) {
336  if (context.dataSourceIngestIsCancelled()) {
337  return;
338  }
339 
340  Scanner fileScanner;
341  try {
342  fileScanner = new Scanner(new FileInputStream(file.toString()));
343  } catch (FileNotFoundException ex) {
344  LOG.log(Level.WARNING, "Unable to find the ESEDatabaseView file at " + file.getPath(), ex); //NON-NLS
345  continue; // If we couldn't open this file, continue to the next file
346  }
347 
348  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
349 
350  try {
351  List<String> headers = null;
352  while (fileScanner.hasNext()) {
353  if (context.dataSourceIngestIsCancelled()) {
354  return;
355  }
356 
357  String line = fileScanner.nextLine();
358  if (headers == null) {
359  headers = Arrays.asList(line.toLowerCase().split(","));
360  continue;
361  }
362 
363  if (line.contains(EDGE_KEYWORD_VISIT)) {
364  BlackboardArtifact ba = getHistoryArtifact(origFile, headers, line);
365  if (ba != null) {
366  bbartifacts.add(ba);
367  }
368  }
369  }
370  } finally {
371  fileScanner.close();
372  }
373 
374  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
375  postArtifacts(bbartifacts);
376  }
377  }
378  }
379 
388  private void getBookmarks(AbstractFile origFile, File resultDir) throws TskCoreException {
389  Scanner fileScanner;
390  File favoriteFile = new File(resultDir, EDGE_FAVORITE_FILE_NAME);
391 
392  try {
393  fileScanner = new Scanner(new FileInputStream(favoriteFile));
394  } catch (FileNotFoundException ex) {
395  // This is a non-fatal error, if the favorites file is not found
396  // there might have not been any favorites\bookmarks
397  return;
398  }
399 
400  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
401 
402  try {
403  List<String> headers = null;
404  while (fileScanner.hasNext()) {
405  String line = fileScanner.nextLine();
406  if (headers == null) {
407  headers = Arrays.asList(line.toLowerCase().split(","));
408  continue;
409  }
410 
411  BlackboardArtifact ba = getBookmarkArtifact(origFile, headers, line);
412  if (ba != null) {
413  bbartifacts.add(ba);
414  }
415  }
416  } finally {
417  fileScanner.close();
418  }
419 
420  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
421  postArtifacts(bbartifacts);
422  }
423  }
424 
432  private void getCookies(AbstractFile origFile, File resultDir) throws TskCoreException {
433  File containerFiles[] = resultDir.listFiles((dir, name) -> name.toLowerCase().contains(EDGE_TABLE_TYPE_COOKIE));
434 
435  if (containerFiles == null) {
436  return;
437  }
438 
439  for (File file : containerFiles) {
440  if (context.dataSourceIngestIsCancelled()) {
441  return;
442  }
443 
444  Scanner fileScanner;
445  try {
446  fileScanner = new Scanner(new FileInputStream(file.toString()));
447  } catch (FileNotFoundException ex) {
448  LOG.log(Level.WARNING, "Unable to find the ESEDatabaseView file at " + file.getPath(), ex); //NON-NLS
449  continue; // If we couldn't open this file, continue to the next file
450  }
451 
452  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
453 
454  try {
455  List<String> headers = null;
456  while (fileScanner.hasNext()) {
457  if (context.dataSourceIngestIsCancelled()) {
458  return;
459  }
460 
461  String line = fileScanner.nextLine();
462  if (headers == null) {
463  headers = Arrays.asList(line.toLowerCase().split(","));
464  continue;
465  }
466 
467  BlackboardArtifact ba = getCookieArtifact(origFile, headers, line);
468  if (ba != null) {
469  bbartifacts.add(ba);
470  }
471  }
472  } finally {
473  fileScanner.close();
474  }
475 
476  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
477  postArtifacts(bbartifacts);
478  }
479  }
480  }
481 
492  private void getDownloads(AbstractFile origFile, File resultDir) throws TskCoreException, FileNotFoundException {
493  ArrayList<File> downloadFiles = getDownloadFiles(resultDir);
494 
495  if (downloadFiles == null) {
496  return;
497  }
498 
499  for (File file : downloadFiles) {
500  if (context.dataSourceIngestIsCancelled()) {
501  return;
502  }
503 
504  Scanner fileScanner;
505  try {
506  fileScanner = new Scanner(new FileInputStream(file.toString()));
507  } catch (FileNotFoundException ex) {
508  LOG.log(Level.WARNING, "Unable to find the ESEDatabaseView file at " + file.getPath(), ex); //NON-NLS
509  continue; // If we couldn't open this file, continue to the next file
510  }
511  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
512 
513  try {
514  List<String> headers = null;
515  while (fileScanner.hasNext()) {
516  if (context.dataSourceIngestIsCancelled()) {
517  return;
518  }
519 
520  String line = fileScanner.nextLine();
521  if (headers == null) {
522  headers = Arrays.asList(line.toLowerCase().split(","));
523  continue;
524  }
525 
526  if (line.contains(EDGE_TABLE_TYPE_DOWNLOAD)) {
527 
528  BlackboardArtifact ba = getDownloadArtifact(origFile, headers, line);
529  if (ba != null) {
530  bbartifacts.add(ba);
531  }
532  }
533  }
534  } finally {
535  fileScanner.close();
536  }
537 
538  if(!context.dataSourceIngestIsCancelled()) {
539  postArtifacts(bbartifacts);
540  }
541  }
542  }
543 
549  private String getPathForESEDumper() {
550  Path path = Paths.get(ESE_TOOL_FOLDER, ESE_TOOL_NAME);
551  File eseToolFile = InstalledFileLocator.getDefault().locate(path.toString(),
552  ExtractEdge.class.getPackage().getName(), false);
553  if (eseToolFile != null) {
554  return eseToolFile.getAbsolutePath();
555  }
556 
557  return null;
558  }
559 
566  private List<AbstractFile> fetchWebCacheDBFiles() throws TskCoreException {
568  = currentCase.getServices().getFileManager();
569  return fileManager.findFiles(dataSource, EDGE_WEBCACHE_NAME, EDGE_WEBCACHE_FOLDER_NAME);
570  }
571 
578  private List<AbstractFile> fetchSpartanDBFiles() throws TskCoreException {
580  = currentCase.getServices().getFileManager();
581  return fileManager.findFiles(dataSource, EDGE_SPARTAN_NAME, EDGE_SPARTAN_FOLDER_NAME);
582  }
583 
595  private void executeDumper(String dumperPath, String inputFilePath,
596  String outputDir) throws IOException {
597 
598  final Path outputFilePath = Paths.get(outputDir, EDGE_OUTPUT_FILE_NAME);
599  final Path errFilePath = Paths.get(outputDir, EDGE_ERROR_FILE_NAME);
600  LOG.log(Level.INFO, "Writing ESEDatabaseViewer results to: {0}", outputDir); //NON-NLS
601 
602  List<String> commandLine = new ArrayList<>();
603  commandLine.add(dumperPath);
604  commandLine.add("/table"); //NON-NLS
605  commandLine.add(inputFilePath);
606  commandLine.add("*"); //NON-NLS
607  commandLine.add("/scomma"); //NON-NLS
608  commandLine.add(outputDir + "\\" + "*.csv"); //NON-NLS
609 
610  ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
611  processBuilder.redirectOutput(outputFilePath.toFile());
612  processBuilder.redirectError(errFilePath.toFile());
613 
614  ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context, true));
615  }
616 
627  private BlackboardArtifact getHistoryArtifact(AbstractFile origFile, List<String> headers, String line) throws TskCoreException {
628  String[] rowSplit = line.split(",");
629 
630  int index = headers.indexOf(EDGE_HEAD_URL);
631  String urlUserStr = rowSplit[index];
632 
633  String[] str = urlUserStr.split("@");
634  String user = (str[0].replace(EDGE_KEYWORD_VISIT, "")).trim();
635  String url = str[1];
636 
637  index = headers.indexOf(EDGE_HEAD_ACCESSTIME);
638  String accessTime = rowSplit[index].trim();
639  Long ftime = parseTimestamp(accessTime);
640 
641  return createArtifactWithAttributes(TSK_WEB_HISTORY, origFile, createHistoryAttribute(url, ftime,
642  null, null,
643  this.getName(),
644  NetworkUtils.extractDomain(url), user));
645  }
646 
656  private BlackboardArtifact getCookieArtifact(AbstractFile origFile, List<String> headers, String line) throws TskCoreException {
657  String[] lineSplit = line.split(","); // NON-NLS
658 
659  String accessTime = lineSplit[headers.indexOf(EDGE_HEAD_LASTMOD)].trim();
660  Long ftime = parseTimestamp(accessTime);
661 
662  String domain = lineSplit[headers.indexOf(EDGE_HEAD_RDOMAIN)].trim();
663  String name = hexToChar(lineSplit[headers.indexOf(EDGE_HEAD_NAME)].trim());
664  String value = hexToChar(lineSplit[headers.indexOf(EDGE_HEAD_VALUE)].trim());
665  String url = flipDomain(domain);
666 
667  return createArtifactWithAttributes(TSK_WEB_COOKIE, origFile, createCookieAttributes(url, null, ftime, null, name, value, this.getName(), NetworkUtils.extractDomain(url)));
668  }
669 
683  private BlackboardArtifact getDownloadArtifact(AbstractFile origFile, List<String> headers, String line) throws TskCoreException {
684  BlackboardArtifact bbart = null;
685 
686  String[] lineSplit = line.split(","); // NON-NLS
687  String rheader = lineSplit[headers.indexOf(EDGE_HEAD_RESPONSEHEAD)];
688 
689  return bbart;
690  }
691 
704  private BlackboardArtifact getBookmarkArtifact(AbstractFile origFile, List<String> headers, String line) throws TskCoreException {
705  // split on all commas as long as they are not inbetween quotes
706  String[] lineSplit = line.split(IGNORE_COMMA_IN_QUOTES_REGEX, -1);
707 
708  String url = lineSplit[headers.indexOf(EDGE_HEAD_URL)];
709  String title = lineSplit[headers.indexOf(EDGE_HEAD_TITLE)].replace("\"", ""); // NON-NLS
710 
711  if (url.isEmpty()) {
712  return null;
713  }
714 
715  return createArtifactWithAttributes(TSK_WEB_BOOKMARK, origFile, createBookmarkAttributes(url, title, null,
716  this.getName(), NetworkUtils.extractDomain(url)));
717  }
718 
719 
734  private Long parseTimestamp(String timeStr) {
735 
736  // If we had a pattern that worked on the last date, use it again.
737  if (previouslyValidDateFormat != null) {
738  try {
739  return previouslyValidDateFormat.parse(timeStr).getTime() / 1000;
740  } catch (ParseException ex) {
741  // Continue on to format detection
742  }
743  }
744 
745  // Try the default US pattern
746  try {
747  SimpleDateFormat usDateFormat = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a"); //NON-NLS
748  usDateFormat.setLenient(false); // Fail if month or day are out of range
749  Long epochTime = usDateFormat.parse(timeStr).getTime();
750  previouslyValidDateFormat = usDateFormat;
751  return epochTime / 1000;
752  } catch (ParseException ex) {
753  // Continue on to format detection
754  }
755 
756  // This generally doesn't match the data in the file but can give information on whether
757  // the month or day is first.
758  boolean monthFirstFromLocale = true;
759  String localeDatePattern = ((SimpleDateFormat) DateFormat.getDateInstance(
760  DateFormat.SHORT, Locale.getDefault())).toPattern();
761  if (localeDatePattern.startsWith("d")) {
762  monthFirstFromLocale = false;
763  }
764 
765  // Try to determine if the month or day is first by looking at the data.
766  // If both variations appear valid, use the locale result.
767  boolean monthFirst = monthFirstFromLocale;
768  Pattern pattern = Pattern.compile("^([0-9]{1,2})[^0-9]([0-9]{1,2})");
769  Matcher matcher = pattern.matcher(timeStr);
770  if (matcher.find()) {
771  int firstVal = Integer.parseInt(matcher.group(1));
772  int secondVal = Integer.parseInt(matcher.group(2));
773 
774  if (firstVal > 12) {
775  monthFirst = false;
776  } else if (secondVal > 12) {
777  monthFirst = true;
778  }
779  // Otherwise keep the setting from the locale
780  }
781 
782  // See if the time has AM/PM attached
783  boolean hasAmPm = false;
784  if (timeStr.endsWith("M") || timeStr.endsWith("m")) {
785  hasAmPm = true;
786  }
787 
788  // See if the date appears to use forward slashes. If not, assume '.' is being used.
789  boolean hasSlashes = false;
790  if (timeStr.contains("/")) {
791  hasSlashes = true;
792  }
793 
794  // Make our best guess at the pattern
795  String dateFormatPattern;
796  if (monthFirst) {
797  if (hasSlashes) {
798  dateFormatPattern = "MM/dd/yyyy ";
799  } else {
800  dateFormatPattern = "MM.dd.yyyy ";
801  }
802  } else {
803  if (hasSlashes) {
804  dateFormatPattern = "dd/MM/yyyy ";
805  } else {
806  dateFormatPattern = "dd.MM.yyyy ";
807  }
808  }
809 
810  if (hasAmPm) {
811  dateFormatPattern += "hh:mm:ss a";
812  } else {
813  dateFormatPattern += "HH:mm:ss";
814  }
815 
816  try {
817  SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatPattern); //NON-NLS
818  dateFormat.setLenient(false); // Fail if month or day are out of range
819  Long epochTime = dateFormat.parse(timeStr).getTime();
820  previouslyValidDateFormat = dateFormat;
821  return epochTime / 1000;
822  } catch (ParseException ex) {
823  LOG.log(Level.WARNING, "Timestamp could not be parsed ({0})", timeStr); //NON-NLS
824  return null;
825  }
826  }
827 
834  private String hexToChar(String hexString) {
835  String[] hexValues = hexString.split(" "); // NON-NLS
836  StringBuilder output = new StringBuilder();
837 
838  for (String str : hexValues) {
839  try {
840  int value = Integer.parseInt(str, 16);
841  if (value > 31) { // Ignore non-print characters
842  output.append((char) value);
843  }
844  } catch (NumberFormatException ex) {
845  return null;
846  }
847  }
848 
849  return output.toString();
850  }
851 
863  private String flipDomain(String domain) {
864  if (domain == null || domain.isEmpty()) {
865  return null;
866  }
867 
868  String[] tokens = domain.split("\\."); // NON-NLS
869 
870  if (tokens.length < 2 || tokens.length > 3) {
871  return domain; // don't know what to do, just send it back as is
872  }
873 
874  StringBuilder buf = new StringBuilder();
875  if (tokens.length > 2) {
876  buf.append(tokens[2]);
877  buf.append(".");
878  }
879  buf.append(tokens[1]);
880  buf.append(".");
881  buf.append(tokens[0]);
882 
883  return buf.toString();
884  }
885 
893  private ArrayList<File> getDownloadFiles(File resultDir) throws FileNotFoundException {
894  return getContainerFiles(resultDir, EDGE_TABLE_TYPE_DOWNLOAD);
895  }
896 
904  private ArrayList<File> getHistoryFiles(File resultDir) throws FileNotFoundException {
905  return getContainerFiles(resultDir, EDGE_TABLE_TYPE_HISTORY);
906  }
907 
916  private ArrayList<File> getContainerFiles(File resultDir, String type) throws FileNotFoundException {
917  HashMap<String, ArrayList<String>> idTable = getContainerIDTable(resultDir);
918 
919  ArrayList<String> idList = idTable.get(type);
920  if (idList == null) {
921  return null;
922  }
923 
924  ArrayList<File> fileList = new ArrayList<>();
925  for (String str : idList) {
926  String fileName = EDGE_CONTAINER_FILE_PREFIX + str + EDGE_CONTAINER_FILE_EXT;
927  fileList.add(new File(resultDir, fileName));
928  }
929 
930  return fileList;
931  }
932 
943  private HashMap<String, ArrayList<String>> getContainerIDTable(File resultDir) throws FileNotFoundException {
944 
945  if (containersTable == null) {
946  File containerFile = new File(resultDir, EDGE_CONTAINTERS_FILE_NAME);
947 
948  try (Scanner fileScanner = new Scanner(new FileInputStream(containerFile))) {
949  List<String> headers = null;
950  containersTable = new HashMap<>();
951  int nameIdx = 0;
952  int idIdx = 0;
953  while (fileScanner.hasNext()) {
954  String line = fileScanner.nextLine();
955  if (headers == null) {
956  headers = Arrays.asList(line.toLowerCase().split(","));
957  nameIdx = headers.indexOf(EDGE_HEAD_NAME);
958  idIdx = headers.indexOf(EDGE_HEAD_CONTAINER_ID);
959  } else {
960  String[] row = line.split(","); // NON-NLS
961  String name = row[nameIdx];
962  String id = row[idIdx];
963 
964  ArrayList<String> idList = containersTable.get(name);
965  if (idList == null) {
966  idList = new ArrayList<>();
967  containersTable.put(name, idList);
968  }
969 
970  idList.add(id);
971  }
972  }
973  }
974  }
975 
976  return containersTable;
977  }
978 
982  private void clearContainerTable(){
983  containersTable = null;
984  }
985 }
List< AbstractFile > findFiles(String fileName)

Copyright © 2012-2021 Basis Technology. Generated on: Thu Sep 30 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.