23 package org.sleuthkit.autopsy.recentactivity;
 
   25 import java.io.BufferedReader;
 
   27 import org.openide.util.NbBundle;
 
   30 import java.io.FileInputStream;
 
   31 import java.io.FileNotFoundException;
 
   32 import java.io.IOException;
 
   33 import java.io.InputStreamReader;
 
   34 import java.text.ParseException;
 
   35 import java.text.SimpleDateFormat;
 
   36 import java.util.ArrayList;
 
   37 import java.util.List;
 
   39 import java.util.HashSet;
 
   40 import java.util.logging.Level;
 
   42 import java.util.Collection;
 
   43 import java.util.Scanner;
 
   44 import java.util.stream.Collectors;
 
   45 import org.openide.modules.InstalledFileLocator;
 
   64 class ExtractIE 
extends Extract {
 
   66     private static final Logger logger = Logger.getLogger(ExtractIE.class.getName());
 
   67     private final IngestServices services = IngestServices.getInstance();
 
   68     private final String moduleTempResultsDir;
 
   69     private String PASCO_LIB_PATH;
 
   70     private final String JAVA_PATH;
 
   71     private static final SimpleDateFormat dateFormatter = 
new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
 
   73     private IngestJobContext context;
 
   76         moduleName = NbBundle.getMessage(ExtractIE.class, 
"ExtractIE.moduleName.text");
 
   77         moduleTempResultsDir = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), 
"IE") + 
File.separator + 
"results"; 
 
   78         JAVA_PATH = PlatformUtil.getJavaPath();
 
   82     public void process(
Content dataSource, IngestJobContext context) {
 
   83         this.dataSource = dataSource;
 
   84         this.context = context;
 
   94     private void getBookmark() {
 
   96         List<AbstractFile> favoritesFiles;
 
   98             favoritesFiles = fileManager.
findFiles(dataSource, 
"%.url", 
"Favorites"); 
 
  100             logger.log(Level.WARNING, 
"Error fetching 'url' files for Internet Explorer bookmarks.", ex); 
 
  101             this.addErrorMessage(
 
  102                     NbBundle.getMessage(
this.getClass(), 
"ExtractIE.getBookmark.errMsg.errGettingBookmarks",
 
  107         if (favoritesFiles.isEmpty()) {
 
  108             logger.log(Level.INFO, 
"Didn't find any IE bookmark files."); 
 
  113         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  115             if (fav.getSize() == 0) {
 
  119             if (context.dataSourceIngestIsCancelled()) {
 
  123             String url = getURLFromIEBookmarkFile(fav);
 
  125             String name = fav.getName();
 
  126             Long datetime = fav.getCrtime();
 
  127             String Tempdate = datetime.toString();
 
  128             datetime = Long.valueOf(Tempdate);
 
  129             String domain = Util.extractDomain(url);
 
  131             Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  133                     NbBundle.getMessage(
this.getClass(),
 
  134                             "ExtractIE.parentModuleName.noSpace"), url));
 
  136                     NbBundle.getMessage(
this.getClass(),
 
  137                             "ExtractIE.parentModuleName.noSpace"), name));
 
  139                     NbBundle.getMessage(
this.getClass(),
 
  140                             "ExtractIE.parentModuleName.noSpace"), datetime));
 
  142                     NbBundle.getMessage(
this.getClass(),
 
  143                             "ExtractIE.parentModuleName.noSpace"),
 
  144                     NbBundle.getMessage(
this.getClass(), 
"ExtractIE.moduleName.text")));
 
  146                     NbBundle.getMessage(
this.getClass(),
 
  147                             "ExtractIE.parentModuleName.noSpace"), domain));
 
  149             BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, fav, bbattributes);
 
  151                 bbartifacts.add(bbart);
 
  154         services.fireModuleDataEvent(
new ModuleDataEvent(
 
  155                 NbBundle.getMessage(
this.getClass(), 
"ExtractIE.parentModuleName"),
 
  159     private String getURLFromIEBookmarkFile(
AbstractFile fav) {
 
  161         String line, url = 
"";
 
  163             line = reader.readLine();
 
  164             while (null != line) {
 
  167                 if (line.startsWith(
"URL")) { 
 
  168                     url = line.substring(line.indexOf(
"=") + 1);
 
  171                 line = reader.readLine();
 
  173         } 
catch (IOException ex) {
 
  174             logger.log(Level.WARNING, 
"Failed to read from content: " + fav.
getName(), ex); 
 
  175             this.addErrorMessage(
 
  176                     NbBundle.getMessage(
this.getClass(), 
"ExtractIE.getURLFromIEBmkFile.errMsg", this.getName(),
 
  178         } 
catch (IndexOutOfBoundsException ex) {
 
  179             logger.log(Level.WARNING, 
"Failed while getting URL of IE bookmark. Unexpected format of the bookmark file: " + fav.
getName(), ex); 
 
  180             this.addErrorMessage(
 
  181                     NbBundle.getMessage(
this.getClass(), 
"ExtractIE.getURLFromIEBmkFile.errMsg2", this.getName(),
 
  186             } 
catch (IOException ex) {
 
  187                 logger.log(Level.WARNING, 
"Failed to close reader.", ex); 
 
  197     private void getCookie() {
 
  199         List<AbstractFile> cookiesFiles;
 
  201             cookiesFiles = fileManager.
findFiles(dataSource, 
"%.txt", 
"Cookies"); 
 
  203             logger.log(Level.WARNING, 
"Error getting cookie files for IE"); 
 
  204             this.addErrorMessage(
 
  205                     NbBundle.getMessage(
this.getClass(), 
"ExtractIE.getCookie.errMsg.errGettingFile", this.getName()));
 
  209         if (cookiesFiles.isEmpty()) {
 
  210             logger.log(Level.INFO, 
"Didn't find any IE cookies files."); 
 
  215         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  217             if (context.dataSourceIngestIsCancelled()) {
 
  220             if (cookiesFile.getSize() == 0) {
 
  224             byte[] t = 
new byte[(int) cookiesFile.getSize()];
 
  226                 final int bytesRead = cookiesFile.read(t, 0, cookiesFile.getSize());
 
  228                 logger.log(Level.WARNING, 
"Error reading bytes of Internet Explorer cookie.", ex); 
 
  229                 this.addErrorMessage(
 
  230                         NbBundle.getMessage(
this.getClass(), 
"ExtractIE.getCookie.errMsg.errReadingIECookie",
 
  231                                 this.getName(), cookiesFile.getName()));
 
  234             String cookieString = 
new String(t);
 
  235             String[] values = cookieString.split(
"\n");
 
  236             String url = values.length > 2 ? values[2] : 
"";
 
  237             String value = values.length > 1 ? values[1] : 
"";
 
  238             String name = values.length > 0 ? values[0] : 
"";
 
  239             Long datetime = cookiesFile.getCrtime();
 
  240             String tempDate = datetime.toString();
 
  241             datetime = Long.valueOf(tempDate);
 
  242             String domain = Util.extractDomain(url);
 
  244             Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  246                     NbBundle.getMessage(
this.getClass(),
 
  247                             "ExtractIE.parentModuleName.noSpace"), url));
 
  249                     NbBundle.getMessage(
this.getClass(),
 
  250                             "ExtractIE.parentModuleName.noSpace"), datetime));
 
  252                     NbBundle.getMessage(
this.getClass(),
 
  253                             "ExtractIE.parentModuleName.noSpace"), (name != null) ? name : 
""));
 
  255                     NbBundle.getMessage(
this.getClass(),
 
  256                             "ExtractIE.parentModuleName.noSpace"), value));
 
  258                     NbBundle.getMessage(
this.getClass(),
 
  259                             "ExtractIE.parentModuleName.noSpace"),
 
  260                     NbBundle.getMessage(
this.getClass(), 
"ExtractIE.moduleName.text")));
 
  262                     NbBundle.getMessage(
this.getClass(),
 
  263                             "ExtractIE.parentModuleName.noSpace"), domain));
 
  264             BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
 
  266                 bbartifacts.add(bbart);
 
  269         services.fireModuleDataEvent(
new ModuleDataEvent(
 
  270                 NbBundle.getMessage(
this.getClass(), 
"ExtractIE.parentModuleName"),
 
  277     private void getHistory() {
 
  278         logger.log(Level.INFO, 
"Pasco results path: {0}", moduleTempResultsDir); 
 
  279         boolean foundHistory = 
false;
 
  281         final File pascoRoot = InstalledFileLocator.getDefault().locate(
"pasco2", ExtractIE.class.getPackage().getName(), 
false); 
 
  282         if (pascoRoot == null) {
 
  283             this.addErrorMessage(
 
  284                     NbBundle.getMessage(
this.getClass(), 
"ExtractIE.getHistory.errMsg.unableToGetHist", this.getName()));
 
  285             logger.log(Level.SEVERE, 
"Error finding pasco program "); 
 
  289         final String pascoHome = pascoRoot.getAbsolutePath();
 
  290         logger.log(Level.INFO, 
"Pasco2 home: {0}", pascoHome); 
 
  292         PASCO_LIB_PATH = pascoHome + 
File.separator + 
"pasco2.jar" + 
File.pathSeparator 
 
  293                 + pascoHome + 
File.separator + 
"*";
 
  295         File resultsDir = 
new File(moduleTempResultsDir);
 
  300         List<AbstractFile> indexFiles;
 
  302             indexFiles = fileManager.
findFiles(dataSource, 
"index.dat"); 
 
  304             this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"ExtractIE.getHistory.errMsg.errGettingHistFiles",
 
  306             logger.log(Level.WARNING, 
"Error fetching 'index.data' files for Internet Explorer history."); 
 
  310         if (indexFiles.isEmpty()) {
 
  311             String msg = NbBundle.getMessage(this.getClass(), 
"ExtractIE.getHistory.errMsg.noHistFiles");
 
  312             logger.log(Level.INFO, msg);
 
  317         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  319         String indexFileName;
 
  326             indexFileName = 
"index" + Integer.toString((
int) indexFile.getId()) + 
".dat"; 
 
  328             temps = RAImageIngestModule.getRATempPath(currentCase, 
"IE") + 
File.separator + indexFileName; 
 
  330             if (context.dataSourceIngestIsCancelled()) {
 
  334                 ContentUtils.writeToFile(indexFile, datFile, context::dataSourceIngestIsCancelled);
 
  335             } 
catch (IOException e) {
 
  336                 logger.log(Level.WARNING, 
"Error while trying to write index.dat file " + datFile.getAbsolutePath(), e); 
 
  337                 this.addErrorMessage(
 
  338                         NbBundle.getMessage(
this.getClass(), 
"ExtractIE.getHistory.errMsg.errWriteFile", this.getName(),
 
  339                                 datFile.getAbsolutePath()));
 
  343             String filename = 
"pasco2Result." + indexFile.getId() + 
".txt"; 
 
  344             boolean bPascProcSuccess = executePasco(temps, filename);
 
  345             if (context.dataSourceIngestIsCancelled()) {
 
  351             if (bPascProcSuccess) {
 
  353                 bbartifacts.addAll(parsePascoOutput(indexFile, filename).stream()
 
  354                         .filter(bbart -> bbart.
getArtifactTypeID() == ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID())
 
  355                         .collect(Collectors.toList()));
 
  361                 logger.log(Level.WARNING, 
"pasco execution failed on: {0}", 
this.getName()); 
 
  362                 this.addErrorMessage(
 
  363                         NbBundle.getMessage(
this.getClass(), 
"ExtractIE.getHistory.errMsg.errProcHist", this.getName()));
 
  368             services.fireModuleDataEvent(
new ModuleDataEvent(
 
  369                     NbBundle.getMessage(
this.getClass(), 
"ExtractIE.parentModuleName"),
 
  382     private boolean executePasco(String indexFilePath, String outputFileName) {
 
  383         boolean success = 
true;
 
  385             final String outputFileFullPath = moduleTempResultsDir + 
File.separator + outputFileName;
 
  386             final String errFileFullPath = moduleTempResultsDir + 
File.separator + outputFileName + 
".err"; 
 
  387             logger.log(Level.INFO, 
"Writing pasco results to: {0}", outputFileFullPath); 
 
  388             List<String> commandLine = 
new ArrayList<>();
 
  389             commandLine.add(JAVA_PATH);
 
  390             commandLine.add(
"-cp"); 
 
  391             commandLine.add(PASCO_LIB_PATH);
 
  392             commandLine.add(
"isi.pasco2.Main"); 
 
  393             commandLine.add(
"-T"); 
 
  394             commandLine.add(
"history");  
 
  395             commandLine.add(indexFilePath);
 
  396             ProcessBuilder processBuilder = 
new ProcessBuilder(commandLine);
 
  397             processBuilder.redirectOutput(
new File(outputFileFullPath));
 
  398             processBuilder.redirectError(
new File(errFileFullPath));
 
  408             ExecUtil.execute(processBuilder, 
new DataSourceIngestModuleProcessTerminator(context));
 
  410         } 
catch (IOException ex) {
 
  412             logger.log(Level.SEVERE, 
"Unable to execute Pasco to process Internet Explorer web history.", ex); 
 
  426     private Collection<BlackboardArtifact> parsePascoOutput(
AbstractFile origFile, String pascoOutputFileName) {
 
  428         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  429         String fnAbs = moduleTempResultsDir + 
File.separator + pascoOutputFileName;
 
  432         if (file.
exists() == 
false) {
 
  433             this.addErrorMessage(
 
  434                     NbBundle.getMessage(
this.getClass(), 
"ExtractIE.parsePascoOutput.errMsg.notFound", this.getName(),
 
  436             logger.log(Level.WARNING, 
"Pasco Output not found: {0}", file.getPath()); 
 
  442         if (file.length() == 0) {
 
  448             fileScanner = 
new Scanner(
new FileInputStream(file.
toString()));
 
  449         } 
catch (FileNotFoundException ex) {
 
  450             this.addErrorMessage(
 
  451                     NbBundle.getMessage(
this.getClass(), 
"ExtractIE.parsePascoOutput.errMsg.errParsing", this.getName(),
 
  453             logger.log(Level.WARNING, 
"Unable to find the Pasco file at " + file.getPath(), ex); 
 
  458         Set<String> reportedUserAccounts = 
new HashSet<>();
 
  460         while (fileScanner.hasNext()) {
 
  461             String line = fileScanner.nextLine();
 
  462             if (!line.startsWith(
"URL")) {   
 
  466             String[] lineBuff = line.split(
"\\t"); 
 
  468             if (lineBuff.length < 4) {
 
  469                 logger.log(Level.INFO, 
"Found unrecognized IE history format."); 
 
  473             String actime = lineBuff[3];
 
  474             Long ftime = (long) 0;
 
  483             if (lineBuff[1].contains(
"@")) {
 
  484                 String url[] = lineBuff[1].split(
"@", 2);
 
  486                 user = user.replace(
"Visited:", 
""); 
 
  487                 user = user.replace(
":Host:", 
""); 
 
  488                 user = user.replaceAll(
"(:)(.*?)(:)", 
"");
 
  491                 realurl = realurl.replace(
"Visited:", 
""); 
 
  492                 realurl = realurl.replaceAll(
":(.*?):", 
"");
 
  493                 realurl = realurl.replace(
":Host:", 
""); 
 
  494                 realurl = realurl.trim();
 
  497                 realurl = lineBuff[1].trim();
 
  500             domain = Util.extractDomain(realurl);
 
  502             if (!actime.isEmpty()) {
 
  504                     Long epochtime = dateFormatter.parse(actime).getTime();
 
  505                     ftime = epochtime / 1000;
 
  506                 } 
catch (ParseException e) {
 
  507                     this.addErrorMessage(
 
  508                             NbBundle.getMessage(
this.getClass(), 
"ExtractIE.parsePascoOutput.errMsg.errParsingEntry",
 
  510                     logger.log(Level.WARNING, String.format(
"Error parsing Pasco results, may have partial processing of corrupt file (id=%d)", origFile.
getId()), e); 
 
  516                 Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  518                         NbBundle.getMessage(
this.getClass(),
 
  519                                 "ExtractIE.parentModuleName.noSpace"), realurl));
 
  523                         NbBundle.getMessage(
this.getClass(),
 
  524                                 "ExtractIE.parentModuleName.noSpace"), ftime));
 
  526                         NbBundle.getMessage(
this.getClass(),
 
  527                                 "ExtractIE.parentModuleName.noSpace"), 
""));
 
  530                         NbBundle.getMessage(
this.getClass(),
 
  531                                 "ExtractIE.parentModuleName.noSpace"),
 
  532                         NbBundle.getMessage(
this.getClass(),
 
  533                                 "ExtractIE.moduleName.text")));
 
  535                         NbBundle.getMessage(
this.getClass(),
 
  536                                 "ExtractIE.parentModuleName.noSpace"), domain));
 
  538                         NbBundle.getMessage(
this.getClass(),
 
  539                                 "ExtractIE.parentModuleName.noSpace"), user));
 
  543                 this.indexArtifact(bbart);
 
  544                 bbartifacts.add(bbart);
 
  546                 if ((!user.isEmpty()) && (!reportedUserAccounts.contains(user))) {
 
  549                             NbBundle.getMessage(
this.getClass(), 
"ExtractIE.parentModuleName.noSpace"), user));
 
  552                     this.indexArtifact(osAttr);
 
  553                     bbartifacts.add(osAttr);
 
  555                     reportedUserAccounts.add(user);
 
  558                 logger.log(Level.SEVERE, 
"Error writing Internet Explorer web history artifact to the blackboard.", ex); 
 
void addAttributes(Collection< BlackboardAttribute > attributes)
 
void addAttribute(BlackboardAttribute attr)
 
BlackboardArtifact newArtifact(int artifactTypeID)
 
synchronized List< AbstractFile > findFiles(String fileName)
 
String toString(boolean preserveState)