23 package org.sleuthkit.autopsy.report.modules.html;
 
   27 import java.awt.image.BufferedImage;
 
   28 import java.io.BufferedWriter;
 
   30 import java.io.FileNotFoundException;
 
   31 import java.io.FileOutputStream;
 
   32 import java.io.IOException;
 
   33 import java.io.InputStream;
 
   34 import java.io.OutputStream;
 
   35 import java.io.OutputStreamWriter;
 
   36 import java.io.UnsupportedEncodingException;
 
   37 import java.io.Writer;
 
   38 import java.nio.file.Files;
 
   39 import java.nio.file.Path;
 
   40 import java.nio.file.Paths;
 
   41 import java.text.DateFormat;
 
   42 import java.text.SimpleDateFormat;
 
   43 import java.util.ArrayList;
 
   44 import java.util.Date;
 
   45 import java.util.HashMap;
 
   46 import java.util.List;
 
   49 import java.util.TreeMap;
 
   50 import java.util.concurrent.ExecutionException;
 
   51 import java.util.logging.Level;
 
   52 import javax.imageio.ImageIO;
 
   53 import javax.swing.JPanel;
 
   54 import org.apache.commons.io.FilenameUtils;
 
   55 import org.apache.commons.text.StringEscapeUtils;
 
   56 import org.openide.filesystems.FileUtil;
 
   57 import org.openide.util.NbBundle;
 
   58 import org.openide.util.NbBundle.Messages;
 
  111         if (instance == null) {
 
  129         if (configPanel == null) {
 
  130             configPanel = 
new HTMLReportConfigurationPanel();
 
  141         return new HTMLReportModuleSettings();
 
  152         return configPanel.getConfiguration();
 
  168         if (settings instanceof HTMLReportModuleSettings) {
 
  169             configPanel.setConfiguration((HTMLReportModuleSettings) settings);
 
  173         throw new IllegalArgumentException(
"Expected settings argument to be an instance of HTMLReportModuleSettings");
 
  180         dataTypes = 
new TreeMap<>();
 
  185         currentDataType = 
"";
 
  191             } 
catch (IOException ex) {
 
  207         fileName = fileName.replaceAll(
" ", 
"_");
 
  216     @SuppressWarnings(
"deprecation")
 
  221         OutputStream output = null;
 
  223         logger.log(Level.INFO, 
"useDataTypeIcon: dataType = {0}", dataType); 
 
  228             if (v.getDisplayName().equals(dataType)) {
 
  233         if (null != artifactType) {
 
  236             iconFilePath = subPath + File.separator + iconFileName;
 
  239             switch (artifactType) {
 
  240                 case TSK_WEB_BOOKMARK:
 
  241                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/bookmarks.png"); 
 
  244                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/cookies.png"); 
 
  246                 case TSK_WEB_HISTORY:
 
  247                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/history.png"); 
 
  249                 case TSK_WEB_DOWNLOAD:
 
  250                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/downloads.png"); 
 
  252                 case TSK_RECENT_OBJECT:
 
  253                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/recent.png"); 
 
  255                 case TSK_INSTALLED_PROG:
 
  256                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/installed.png"); 
 
  258                 case TSK_KEYWORD_HIT:
 
  259                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/keywords.png"); 
 
  261                 case TSK_HASHSET_HIT:
 
  262                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/hash.png"); 
 
  264                 case TSK_DEVICE_ATTACHED:
 
  265                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/devices.png"); 
 
  267                 case TSK_WEB_SEARCH_QUERY:
 
  268                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/search.png"); 
 
  270                 case TSK_METADATA_EXIF:
 
  271                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/exif.png"); 
 
  274                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/userbookmarks.png"); 
 
  276                 case TSK_TAG_ARTIFACT:
 
  277                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/userbookmarks.png"); 
 
  279                 case TSK_SERVICE_ACCOUNT:
 
  280                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/account-icon-16.png"); 
 
  283                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/contact.png"); 
 
  286                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/message.png"); 
 
  289                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/calllog.png"); 
 
  291                 case TSK_CALENDAR_ENTRY:
 
  292                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/calendar.png"); 
 
  294                 case TSK_SPEED_DIAL_ENTRY:
 
  295                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/speeddialentry.png"); 
 
  297                 case TSK_BLUETOOTH_PAIRING:
 
  298                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/bluetooth.png"); 
 
  300                 case TSK_GPS_BOOKMARK:
 
  301                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/gpsfav.png"); 
 
  303                 case TSK_GPS_LAST_KNOWN_LOCATION:
 
  304                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/gps-lastlocation.png"); 
 
  307                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/gps-search.png"); 
 
  310                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/computer.png"); 
 
  312                 case TSK_GPS_TRACKPOINT:
 
  313                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/gps_trackpoint.png"); 
 
  316                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/gps_trackpoint.png"); 
 
  319                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/mail-icon-16.png"); 
 
  321                 case TSK_ENCRYPTION_SUSPECTED:
 
  322                 case TSK_ENCRYPTION_DETECTED:
 
  323                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/encrypted-file.png"); 
 
  325                 case TSK_EXT_MISMATCH_DETECTED:
 
  326                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/mismatch-16.png"); 
 
  328                 case TSK_INTERESTING_ARTIFACT_HIT:
 
  330                 case TSK_INTERESTING_FILE_HIT:
 
  332                 case TSK_INTERESTING_ITEM:
 
  333                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/interesting_item.png"); 
 
  336                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/installed.png"); 
 
  338                 case TSK_REMOTE_DRIVE:
 
  339                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/drive_network.png"); 
 
  342                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/os-account.png"); 
 
  344                 case TSK_OBJECT_DETECTED:
 
  345                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/objects.png"); 
 
  347                 case TSK_WEB_FORM_AUTOFILL:
 
  348                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/web-form.png"); 
 
  351                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/cache.png"); 
 
  353                 case TSK_USER_CONTENT_SUSPECTED:
 
  354                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/user-content.png"); 
 
  357                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/metadata.png"); 
 
  359                 case TSK_CLIPBOARD_CONTENT:
 
  360                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/clipboard.png"); 
 
  363                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/accounts.png"); 
 
  365                 case TSK_WIFI_NETWORK:
 
  366                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/network-wifi.png"); 
 
  368                 case TSK_WIFI_NETWORK_ADAPTER:
 
  369                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/network-wifi.png"); 
 
  371                 case TSK_SIM_ATTACHED:
 
  372                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/sim_card.png"); 
 
  374                 case TSK_BLUETOOTH_ADAPTER:
 
  375                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/Bluetooth.png"); 
 
  377                 case TSK_DEVICE_INFO:
 
  378                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/devices.png"); 
 
  380                 case TSK_VERIFICATION_FAILED:
 
  381                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/validationFailed.png"); 
 
  383                 case TSK_WEB_ACCOUNT_TYPE:
 
  384                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/web-account-type.png"); 
 
  386                 case TSK_WEB_FORM_ADDRESS:
 
  387                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/web-form-address.png"); 
 
  390                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/gps-area.png"); 
 
  392                 case TSK_WEB_CATEGORIZATION:
 
  393                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/domain-16.png"); 
 
  396                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/yara_16.png"); 
 
  398                 case TSK_PREVIOUSLY_SEEN:
 
  399                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/previously-seen.png"); 
 
  401                 case TSK_PREVIOUSLY_UNSEEN:
 
  402                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/previously-unseen.png"); 
 
  404                 case TSK_PREVIOUSLY_NOTABLE:
 
  405                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/images/red-circle-exclamation.png"); 
 
  408                     logger.log(Level.WARNING, 
"useDataTypeIcon: unhandled artifact type = {0}", dataType); 
 
  409                     in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/star.png"); 
 
  410                     iconFileName = 
"star.png"; 
 
  411                     iconFilePath = subPath + File.separator + iconFileName;
 
  422             in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/accounts.png"); 
 
  423             iconFileName = 
"accounts.png"; 
 
  424             iconFilePath = subPath + File.separator + iconFileName;
 
  426             in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/star.png"); 
 
  427             iconFileName = 
"star.png"; 
 
  428             iconFilePath = subPath + File.separator + iconFileName;
 
  432             output = 
new FileOutputStream(iconFilePath);
 
  433             FileUtil.copy(in, output);
 
  436         } 
catch (IOException ex) {
 
  437             logger.log(Level.SEVERE, 
"Failed to extract images for HTML report.", ex); 
 
  439             if (output != null) {
 
  443                 } 
catch (IOException ex) {
 
  449                 } 
catch (IOException ex) {
 
  470             logger.log(Level.SEVERE, 
"Exception while getting open case."); 
 
  474         this.path = baseReportDir; 
 
  475         this.subPath = this.path + HTML_SUBDIR + File.separator;
 
  478             FileUtil.createFolder(
new File(this.subPath));
 
  479             FileUtil.createFolder(
new File(this.thumbsPath));
 
  480         } 
catch (IOException ex) {
 
  481             logger.log(Level.SEVERE, 
"Unable to make HTML report folder."); 
 
  499             } 
catch (IOException ex) {
 
  500                 logger.log(Level.WARNING, 
"Could not close the output writer when ending report.", ex); 
 
  517             out = 
new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(subPath + title + 
".html"), 
"UTF-8")); 
 
  518         } 
catch (FileNotFoundException ex) {
 
  519             logger.log(Level.SEVERE, 
"File not found: {0}", ex); 
 
  520         } 
catch (UnsupportedEncodingException ex) {
 
  521             logger.log(Level.SEVERE, 
"Unrecognized encoding"); 
 
  525             StringBuilder page = 
new StringBuilder();
 
  526             page.append(
"<html>\n<head>\n\t<title>").append(name).append(
"</title>\n\t<link rel=\"stylesheet\" type=\"text/css\" href=\"index.css\" />\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n</head>\n<body>\n") 
 
  528                     .append(
"<div id=\"header\">").append(name).append(
"</div>\n")
 
  529                     .append(
"<div id=\"content\">\n"); 
 
  530             if (!description.isEmpty()) {
 
  531                 page.append(
"<p><strong>"); 
 
  532                 page.append(description);
 
  533                 page.append(
"</strong></p>\n"); 
 
  535             out.write(page.toString());
 
  536             currentDataType = name;
 
  538         } 
catch (IOException ex) {
 
  539             logger.log(Level.SEVERE, 
"Failed to write page head: {0}", ex); 
 
  549         dataTypes.put(currentDataType, rowCount);
 
  551             StringBuilder builder = 
new StringBuilder();
 
  553             builder.append(
"</div>\n</body>\n</html>\n"); 
 
  554             out.write(builder.toString());
 
  555         } 
catch (IOException ex) {
 
  556             logger.log(Level.SEVERE, 
"Failed to write end of HTML report.", ex); 
 
  562                 } 
catch (IOException ex) {
 
  563                     logger.log(Level.WARNING, 
"Could not close the output writer when ending data type.", ex); 
 
  577         StringBuilder output = 
new StringBuilder();
 
  578         String pageHeader = configPanel.getHeader();
 
  579         if (pageHeader.isEmpty() == 
false) {
 
  580             output.append(
"<div id=\"pageHeaderFooter\">")
 
  581                     .append(StringEscapeUtils.escapeHtml4(pageHeader))
 
  584         return output.toString();
 
  594         StringBuilder output = 
new StringBuilder();
 
  595         String pageFooter = configPanel.getFooter();
 
  596         if (pageFooter.isEmpty() == 
false) {
 
  597             output.append(
"<br/><div id=\"pageHeaderFooter\">")
 
  598                     .append(StringEscapeUtils.escapeHtml4(pageFooter))
 
  601         return output.toString();
 
  611         StringBuilder set = 
new StringBuilder();
 
  612         set.append(
"<h1><a name=\"").append(setName).append(
"\">").append(setName).append(
"</a></h1>\n"); 
 
  613         set.append(
"<div class=\"keyword_list\">\n"); 
 
  616             out.write(set.toString());
 
  617         } 
catch (IOException ex) {
 
  618             logger.log(Level.SEVERE, 
"Failed to write set: {0}", ex); 
 
  628             out.write(
"</div>\n"); 
 
  629         } 
catch (IOException ex) {
 
  630             logger.log(Level.SEVERE, 
"Failed to write end of set: {0}", ex); 
 
  641         StringBuilder index = 
new StringBuilder();
 
  642         index.append(
"<ul>\n"); 
 
  643         for (String set : sets) {
 
  644             index.append(
"\t<li><a href=\"#").append(set).append(
"\">").append(set).append(
"</a></li>\n"); 
 
  646         index.append(
"</ul>\n"); 
 
  648             out.write(index.toString());
 
  649         } 
catch (IOException ex) {
 
  650             logger.log(Level.SEVERE, 
"Failed to add set index: {0}", ex); 
 
  662             out.write(
"<h4>" + elementName + 
"</h4>\n"); 
 
  663         } 
catch (IOException ex) {
 
  664             logger.log(Level.SEVERE, 
"Failed to write set element: {0}", ex); 
 
  675         StringBuilder ele = 
new StringBuilder();
 
  676         ele.append(
"<table>\n<thead>\n\t<tr>\n"); 
 
  677         for (String title : titles) {
 
  678             ele.append(
"\t\t<th>").append(title).append(
"</th>\n"); 
 
  680         ele.append(
"\t</tr>\n</thead>\n"); 
 
  683             out.write(ele.toString());
 
  684         } 
catch (IOException ex) {
 
  685             logger.log(Level.SEVERE, 
"Failed to write table start: {0}", ex); 
 
  696         StringBuilder htmlOutput = 
new StringBuilder();
 
  697         htmlOutput.append(
"<table>\n<thead>\n\t<tr>\n"); 
 
  700         for (String columnHeader : columnHeaders) {
 
  701             htmlOutput.append(
"\t\t<th>").append(columnHeader).append(
"</th>\n"); 
 
  705         htmlOutput.append(
"\t\t<th></th>\n"); 
 
  707         htmlOutput.append(
"\t</tr>\n</thead>\n"); 
 
  710             out.write(htmlOutput.toString());
 
  711         } 
catch (IOException ex) {
 
  712             logger.log(Level.SEVERE, 
"Failed to write table start: {0}", ex); 
 
  722             out.write(
"</table>\n"); 
 
  723         } 
catch (IOException ex) {
 
  724             logger.log(Level.SEVERE, 
"Failed to write end of table: {0}", ex); 
 
  746     private void addRow(List<String> row, 
boolean escapeText) {
 
  747         StringBuilder builder = 
new StringBuilder();
 
  748         builder.append(
"\t<tr>\n"); 
 
  749         for (String cell : row) {
 
  751             builder.append(
"\t\t<td>").append(cellText).append(
"</td>\n"); 
 
  753         builder.append(
"\t</tr>\n"); 
 
  757             out.write(builder.toString());
 
  758         } 
catch (IOException ex) {
 
  759             logger.log(Level.SEVERE, 
"Failed to write row to out.", ex); 
 
  760         } 
catch (NullPointerException ex) {
 
  761             logger.log(Level.SEVERE, 
"Output writer is null. Page was not initialized before writing.", ex); 
 
  780         StringBuilder localFileLink = 
new StringBuilder();
 
  785             localFileLink.append(
"<a href=\""); 
 
  788             localFileLink.append(localFilePath);
 
  789             localFileLink.append(
"\" target=\"_top\">");
 
  792         StringBuilder builder = 
new StringBuilder();
 
  793         builder.append(
"\t<tr>\n"); 
 
  794         int positionCounter = 0;
 
  795         for (String cell : row) {
 
  797             switch (positionCounter) {
 
  800                     builder.append(
"\t\t<td class=\"left_align_cell\">").append(localFileLink.toString()).append(cell).append(
"</a></td>\n"); 
 
  804                     builder.append(
"\t\t<td class=\"right_align_cell\">").append(cell).append(
"</td>\n"); 
 
  808                     builder.append(
"\t\t<td>").append(cell).append(
"</td>\n"); 
 
  813         builder.append(
"\t</tr>\n"); 
 
  817             out.write(builder.toString());
 
  818         } 
catch (IOException ex) {
 
  819             logger.log(Level.SEVERE, 
"Failed to write row to out.", ex); 
 
  820         } 
catch (NullPointerException ex) {
 
  821             logger.log(Level.SEVERE, 
"Output writer is null. Page was not initialized before writing.", ex); 
 
  833         ArrayList<ImageTagRegion> tagRegions = 
new ArrayList<>();
 
  834         contentTags.forEach((contentTag) -> {
 
  838                 if (contentViewerTag != null) {
 
  839                     tagRegions.add(contentViewerTag.
getDetails());
 
  842                 logger.log(Level.WARNING, 
"Could not get content viewer tag " 
  843                         + 
"from case db for content_tag with id %d", contentTag.getId());
 
  855         List<String> currentRow = 
new ArrayList<>();
 
  858         for (
Content content : images) {
 
  860                 addRow(currentRow, 
false);
 
  864             if (totalCount == MAX_THUMBS_PER_PAGE) {
 
  868                 rowCount = totalCount;
 
  873                 startDataType(NbBundle.getMessage(
this.getClass(), 
"ReportHTML.addThumbRows.dataType.title", pages),
 
  874                         NbBundle.getMessage(
this.getClass(), 
"ReportHTML.addThumbRows.dataType.msg"));
 
  875                 List<String> emptyHeaders = 
new ArrayList<>();
 
  877                     emptyHeaders.add(
"");
 
  887             List<ContentTag> contentTags = 
new ArrayList<>();
 
  889             String thumbnailPath = null;
 
  890             String imageWithTagsFullPath = null;
 
  897                 if (!imageTags.isEmpty()) {
 
  907                     File thumbnailImageWithTagsFile = Paths.get(thumbsPath, FilenameUtils.removeExtension(fileName) + 
".png").toFile();
 
  909                     fullImageWithTagsPath = FilenameUtils.removeExtension(fullImageWithTagsPath) + 
".png";
 
  910                     File fullImageWithTagsFile = Paths.get(fullImageWithTagsPath).toFile();
 
  913                     ImageIO.write(thumbnailWithTags, 
"png", thumbnailImageWithTagsFile);
 
  914                     ImageIO.write(fullImageWithTags, 
"png", fullImageWithTagsFile);
 
  916                     thumbnailPath = THUMBS_REL_PATH + thumbnailImageWithTagsFile.getName();
 
  918                     imageWithTagsFullPath = fullImageWithTagsPath.substring(subPath.length());
 
  921                 logger.log(Level.WARNING, 
"Could not get tags for file.", ex); 
 
  922             } 
catch (IOException | InterruptedException | ExecutionException ex) {
 
  923                 logger.log(Level.WARNING, 
"Could make marked up thumbnail.", ex); 
 
  927             if (thumbnailPath == null) {
 
  931             if (thumbnailPath == null) {
 
  934             String contentPath = 
saveContent(file, 
"original"); 
 
  942             StringBuilder linkToThumbnail = 
new StringBuilder();
 
  943             linkToThumbnail.append(
"<div id='thumbnail_link'><a href=\"")
 
  944                     .append((imageWithTagsFullPath != null) ? imageWithTagsFullPath : contentPath)
 
  945                     .append(
"\" target=\"_top\"><img src=\"")
 
  946                     .append(thumbnailPath).append(
"\" title=\"").append(nameInImage).append(
"\"/></a><br>") 
 
  947                     .append(file.
getName()).append(
"<br>"); 
 
  948             if (imageWithTagsFullPath != null) {
 
  949                 linkToThumbnail.append(
"<a href=\"").append(contentPath).append(
"\" target=\"_top\">View Original</a><br>");
 
  952             if (!contentTags.isEmpty()) {
 
  953                 linkToThumbnail.append(NbBundle.getMessage(
this.getClass(), 
"ReportHTML.thumbLink.tags"));
 
  955             for (
int i = 0; i < contentTags.size(); i++) {
 
  959                 if (i != contentTags.size() - 1) {
 
  960                     linkToThumbnail.append(
", ");
 
  964             linkToThumbnail.append(
"</div>");
 
  965             currentRow.add(linkToThumbnail.toString());
 
  970         if (currentRow.isEmpty() == 
false) {
 
  971             int extraCells = THUMBNAIL_COLUMNS - currentRow.size();
 
  972             for (
int i = 0; i < extraCells; i++) {
 
  976             addRow(currentRow, 
false);
 
  980         rowCount = totalCount;
 
  998         StringBuilder localFilePath = 
new StringBuilder();  
 
 1000         localFilePath.append(subPath);
 
 1001         localFilePath.append(dirName2);
 
 1002         File localFileFolder = 
new File(localFilePath.toString());
 
 1003         if (!localFileFolder.exists()) {
 
 1004             localFileFolder.mkdirs();
 
 1015         String objectIdSuffix = 
"_" + file.
getId();
 
 1016         int lastDotIndex = fileName.lastIndexOf(
".");
 
 1017         if (lastDotIndex != -1 && lastDotIndex != 0) {
 
 1019             fileName = fileName.substring(0, lastDotIndex) + objectIdSuffix + fileName.substring(lastDotIndex, fileName.length());
 
 1023             fileName += objectIdSuffix;
 
 1025         localFilePath.append(File.separator);
 
 1026         localFilePath.append(fileName);
 
 1028         return localFilePath.toString();
 
 1046         File localFile = 
new File(localFilePath);
 
 1047         if (!localFile.exists()) {
 
 1052         return localFilePath.substring(subPath.length());
 
 1064         SimpleDateFormat sdf = 
new java.text.SimpleDateFormat(
"yyyy/MM/dd HH:mm:ss");
 
 1065         return sdf.format(
new java.util.Date(date * 1000));
 
 1070         return "report.html"; 
 
 1075         return NbBundle.getMessage(this.getClass(), 
"ReportHTML.getName.text");
 
 1080         return NbBundle.getMessage(this.getClass(), 
"ReportHTML.getDesc.text");
 
 1087         Writer cssOut = null;
 
 1089             cssOut = 
new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(subPath + 
"index.css"), 
"UTF-8")); 
 
 1090             String css = 
"body {margin: 0px; padding: 0px; background: #FFFFFF; font: 13px/20px Arial, Helvetica, sans-serif; color: #535353;}\n" 
 1092                     "#content {padding: 30px;}\n" 
 1094                     "#header {width:100%; padding: 10px; line-height: 25px; background: #07A; color: #FFF; font-size: 20px;}\n" 
 1096                     "#pageHeaderFooter {width: 100%; padding: 10px; line-height: 25px; text-align: center; font-size: 20px;}\n" 
 1098                     "h1 {font-size: 20px; font-weight: normal; color: #07A; padding: 0 0 7px 0; margin-top: 25px; border-bottom: 1px solid #D6D6D6;}\n" 
 1100                     "h2 {font-size: 20px; font-weight: bolder; color: #07A;}\n" 
 1102                     "h3 {font-size: 16px; color: #07A;}\n" 
 1104                     "h4 {background: #07A; color: #FFF; font-size: 16px; margin: 0 0 0 25px; padding: 0; padding-left: 15px;}\n" 
 1106                     "ul.nav {list-style-type: none; line-height: 35px; padding: 0px; margin-left: 15px;}\n" 
 1108                     "ul li a {font-size: 14px; color: #444; text-decoration: none; padding-left: 25px;}\n" 
 1110                     "ul li a:hover {text-decoration: underline;}\n" 
 1112                     "p {margin: 0 0 20px 0;}\n" 
 1114                     "table {white-space:nowrap; min-width: 700px; padding: 2; margin: 0; border-collapse: collapse; border-bottom: 2px solid #e5e5e5;}\n" 
 1116                     ".keyword_list table {margin: 0 0 25px 25px; border-bottom: 2px solid #dedede;}\n" 
 1118                     "table th {white-space:nowrap; display: table-cell; text-align: center; padding: 2px 4px; background: #e5e5e5; color: #777; font-size: 11px; text-shadow: #e9f9fd 0 1px 0; border-top: 1px solid #dedede; border-bottom: 2px solid #e5e5e5;}\n" 
 1120                     "table .left_align_cell{display: table-cell; padding: 2px 4px; font: 13px/20px Arial, Helvetica, sans-serif; min-width: 125px; overflow: auto; text-align: left; }\n" 
 1122                     "table .right_align_cell{display: table-cell; padding: 2px 4px; font: 13px/20px Arial, Helvetica, sans-serif; min-width: 125px; overflow: auto; text-align: right; }\n" 
 1124                     "table td {white-space:nowrap; display: table-cell; padding: 2px 3px; font: 13px/20px Arial, Helvetica, sans-serif; min-width: 125px; overflow: auto; text-align:left; vertical-align: text-top;}\n" 
 1126                     "table tr:nth-child(even) td {background: #f3f3f3;}\n" 
 1128                     "div#thumbnail_link {max-width: 200px; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;}";
 
 1130         } 
catch (FileNotFoundException ex) {
 
 1131             logger.log(Level.SEVERE, 
"Could not find index.css file to write to.", ex); 
 
 1132         } 
catch (UnsupportedEncodingException ex) {
 
 1133             logger.log(Level.SEVERE, 
"Did not recognize encoding when writing index.css.", ex); 
 
 1134         } 
catch (IOException ex) {
 
 1135             logger.log(Level.SEVERE, 
"Error creating Writer for index.css.", ex); 
 
 1138                 if (cssOut != null) {
 
 1142             } 
catch (IOException ex) {
 
 1151         Writer indexOut = null;
 
 1152         String indexFilePath = path + 
"report.html"; 
 
 1157             logger.log(Level.SEVERE, 
"Exception while getting open case.", ex); 
 
 1161             indexOut = 
new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(indexFilePath), 
"UTF-8")); 
 
 1162             StringBuilder index = 
new StringBuilder();
 
 1165             if (iconPath == null) {
 
 1167                 iconPath = HTML_SUBDIR + 
"favicon.ico";
 
 1169                 iconPath = Paths.get(reportBranding.
getAgencyLogoPath()).getFileName().toString(); 
 
 1171             index.append(
"<head>\n<title>").append(reportTitle).append(
" ").append(
 
 1172                     NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeIndex.title", currentCase.
getDisplayName())).append(
 
 1174             index.append(
"<link rel=\"icon\" type=\"image/ico\" href=\"")
 
 1175                     .append(iconPath).append(
"\" />\n"); 
 
 1176             index.append(
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"); 
 
 1177             index.append(
"</head>\n"); 
 
 1178             index.append(
"<frameset cols=\"350px,*\">\n"); 
 
 1179             index.append(
"<frame src=\"" + HTML_SUBDIR).append(File.separator).append(
"nav.html\" name=\"nav\">\n"); 
 
 1180             index.append(
"<frame src=\"" + HTML_SUBDIR).append(File.separator).append(
"summary.html\" name=\"content\">\n"); 
 
 1181             index.append(
"<noframes>").append(NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeIndex.noFrames.msg")).append(
"<br />\n"); 
 
 1182             index.append(NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeIndex.noFrames.seeNav")).append(
"<br />\n"); 
 
 1183             index.append(NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeIndex.seeSum")).append(
"</noframes>\n"); 
 
 1184             index.append(
"</frameset>\n"); 
 
 1185             index.append(
"</html>"); 
 
 1186             indexOut.write(index.toString());
 
 1187             openCase.
addReport(indexFilePath, NbBundle.getMessage(
this.getClass(),
 
 1188                     "ReportHTML.writeIndex.srcModuleName.text"), 
"");
 
 1189         } 
catch (IOException ex) {
 
 1190             logger.log(Level.SEVERE, 
"Error creating Writer for report.html: {0}", ex); 
 
 1192             String errorMessage = String.format(
"Error adding %s to case as a report", indexFilePath); 
 
 1193             logger.log(Level.SEVERE, errorMessage, ex);
 
 1196                 if (indexOut != null) {
 
 1200             } 
catch (IOException ex) {
 
 1209         Writer navOut = null;
 
 1211             navOut = 
new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(subPath + 
"nav.html"), 
"UTF-8")); 
 
 1212             StringBuilder nav = 
new StringBuilder();
 
 1213             nav.append(
"<html>\n<head>\n\t<title>").append( 
 
 1214                     NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeNav.title"))
 
 1215                     .append(
"</title>\n\t<link rel=\"stylesheet\" type=\"text/css\" href=\"index.css\" />\n"); 
 
 1216             nav.append(
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n</head>\n<body>\n"); 
 
 1217             nav.append(
"<div id=\"content\">\n<h1>").append( 
 
 1218                     NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeNav.h1")).append(
"</h1>\n"); 
 
 1219             nav.append(
"<ul class=\"nav\">\n"); 
 
 1220             nav.append(
"<li style=\"background: url(summary.png) left center no-repeat;\"><a href=\"summary.html\" target=\"content\">") 
 
 1221                     .append(NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeNav.summary")).append(
"</a></li>\n"); 
 
 1223             for (String dataType : dataTypes.keySet()) {
 
 1226                 nav.append(
"<li style=\"background: url('").append(iconFileName) 
 
 1227                         .append(
"') left center no-repeat;\"><a href=\"") 
 
 1228                         .append(dataTypeEsc).append(
".html\" target=\"content\">") 
 
 1229                         .append(dataType).append(
" (").append(dataTypes.get(dataType))
 
 1230                         .append(
")</a></li>\n"); 
 
 1232             nav.append(
"</ul>\n"); 
 
 1233             nav.append(
"</div>\n</body>\n</html>"); 
 
 1234             navOut.write(nav.toString());
 
 1235         } 
catch (IOException ex) {
 
 1236             logger.log(Level.SEVERE, 
"Failed to write end of report navigation menu: {0}", ex); 
 
 1238             if (navOut != null) {
 
 1242                 } 
catch (IOException ex) {
 
 1243                     logger.log(Level.WARNING, 
"Could not close navigation out writer."); 
 
 1248         InputStream in = null;
 
 1249         OutputStream output = null;
 
 1254             if (generatorLogoPath != null && !generatorLogoPath.isEmpty()) {
 
 1255                 File from = 
new File(generatorLogoPath);
 
 1256                 File to = 
new File(subPath);
 
 1257                 FileUtil.copyFile(FileUtil.toFileObject(from), FileUtil.toFileObject(to), 
"generator_logo"); 
 
 1261             if (agencyLogoPath != null && !agencyLogoPath.isEmpty()) {
 
 1262                 Path destinationPath = Paths.get(subPath);
 
 1263                 Files.copy(Files.newInputStream(Paths.get(agencyLogoPath)), destinationPath.resolve(Paths.get(agencyLogoPath).getFileName())); 
 
 1266             in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/favicon.ico"); 
 
 1267             output = 
new FileOutputStream(
new File(subPath + 
"favicon.ico"));
 
 1268             FileUtil.copy(in, output);
 
 1272             in = getClass().getResourceAsStream(
"/org/sleuthkit/autopsy/report/images/summary.png"); 
 
 1273             output = 
new FileOutputStream(
new File(subPath + 
"summary.png"));
 
 1274             FileUtil.copy(in, output);
 
 1278         } 
catch (IOException ex) {
 
 1279             logger.log(Level.SEVERE, 
"Failed to extract images for HTML report.", ex); 
 
 1281             if (output != null) {
 
 1285                 } 
catch (IOException ex) {
 
 1291                 } 
catch (IOException ex) {
 
 1301         Writer output = null;
 
 1303             output = 
new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(subPath + 
"summary.html"), 
"UTF-8")); 
 
 1304             StringBuilder head = 
new StringBuilder();
 
 1305             head.append(
"<html>\n<head>\n<title>").append( 
 
 1306                     NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeSum.title")).append(
"</title>\n"); 
 
 1307             head.append(
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"); 
 
 1308             head.append(
"<style type=\"text/css\">\n"); 
 
 1309             head.append(
"#pageHeaderFooter {width: 100%; padding: 10px; line-height: 25px; text-align: center; font-size: 20px;}\n"); 
 
 1310             head.append(
"body { padding: 0px; margin: 0px; font: 13px/20px Arial, Helvetica, sans-serif; color: #535353; }\n"); 
 
 1311             head.append(
"#wrapper { width: 90%; margin: 0px auto; margin-top: 35px; }\n"); 
 
 1312             head.append(
"h1 { color: #07A; font-size: 36px; line-height: 42px; font-weight: normal; margin: 0px; border-bottom: 1px solid #81B9DB; }\n"); 
 
 1313             head.append(
"h1 span { color: #F00; display: block; font-size: 16px; font-weight: bold; line-height: 22px;}\n"); 
 
 1314             head.append(
"h2 { padding: 0 0 3px 0; margin: 0px; color: #07A; font-weight: normal; border-bottom: 1px dotted #81B9DB; }\n"); 
 
 1315             head.append(
"h3 { padding: 5 0 3px 0; margin: 0px; color: #07A; font-weight: normal; }\n");
 
 1316             head.append(
"table td { padding: 5px 25px 5px 0px; vertical-align:top;}\n"); 
 
 1317             head.append(
"p.subheadding { padding: 0px; margin: 0px; font-size: 11px; color: #B5B5B5; }\n"); 
 
 1318             head.append(
".title { width: 660px; margin-bottom: 50px; }\n"); 
 
 1319             head.append(
".left { float: left; width: 250px; margin-top: 20px; text-align: center; }\n"); 
 
 1320             head.append(
".left img { max-width: 250px; max-height: 250px; min-width: 200px; min-height: 200px; }\n"); 
 
 1321             head.append(
".right { float: right; width: 385px; margin-top: 25px; font-size: 14px; }\n"); 
 
 1322             head.append(
".clear { clear: both; }\n"); 
 
 1323             head.append(
".info { padding: 10px 0;}\n");
 
 1324             head.append(
".info p { padding: 3px 10px; background: #e5e5e5; color: #777; font-size: 12px; font-weight: bold; text-shadow: #e9f9fd 0 1px 0; border-top: 1px solid #dedede; border-bottom: 2px solid #dedede; }\n"); 
 
 1325             head.append(
".info table { margin: 10px 25px 10px 25px; }\n"); 
 
 1326             head.append(
"ul {padding: 0;margin: 0;list-style-type: none;}");
 
 1327             head.append(
"li {padding-bottom: 5px;}");
 
 1328             head.append(
"</style>\n"); 
 
 1329             head.append(
"</head>\n<body>\n"); 
 
 1330             output.write(head.toString());
 
 1332             DateFormat datetimeFormat = 
new SimpleDateFormat(
"yyyy/MM/dd HH:mm:ss");
 
 1333             Date date = 
new Date();
 
 1334             String datetime = datetimeFormat.format(date);
 
 1336             StringBuilder summary = 
new StringBuilder();
 
 1337             boolean running = 
false;
 
 1347             summary.append(
"<div id=\"wrapper\">\n"); 
 
 1349             summary.append(
"<h1>").append(reportTitle) 
 
 1350                     .append(running ? NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeSum.warningMsg") : 
"")
 
 1352             summary.append(
"<p class=\"subheadding\">").append( 
 
 1353                     NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeSum.reportGenOn.text", datetime)).append(
"</p>\n"); 
 
 1354             summary.append(
"<div class=\"title\">\n"); 
 
 1359             if (generatorLogoSet) {
 
 1360                 summary.append(
"<div class=\"left\">\n"); 
 
 1361                 summary.append(
"<img src=\"generator_logo.png\" />\n"); 
 
 1362                 summary.append(
"</div>\n"); 
 
 1364             summary.append(
"<div class=\"clear\"></div>\n"); 
 
 1365             if (reportFooter != null) {
 
 1366                 summary.append(
"<p class=\"subheadding\">").append(reportFooter).append(
"</p>\n"); 
 
 1368             summary.append(
"</div>\n"); 
 
 1370             summary.append(
"</body></html>"); 
 
 1371             output.write(summary.toString());
 
 1372         } 
catch (FileNotFoundException ex) {
 
 1373             logger.log(Level.SEVERE, 
"Could not find summary.html file to write to."); 
 
 1374         } 
catch (UnsupportedEncodingException ex) {
 
 1375             logger.log(Level.SEVERE, 
"Did not recognize encoding when writing summary.hmtl."); 
 
 1376         } 
catch (IOException ex) {
 
 1377             logger.log(Level.SEVERE, 
"Error creating Writer for summary.html."); 
 
 1379             logger.log(Level.WARNING, 
"Unable to get current sleuthkit Case for the HTML report.");
 
 1382                 if (output != null) {
 
 1386             } 
catch (IOException ex) {
 
 1392         "ReportHTML.writeSum.case=Case:",
 
 1393         "ReportHTML.writeSum.caseNumber=Case Number:",
 
 1394         "ReportHTML.writeSum.caseNumImages=Number of data sources in case:",
 
 1395         "ReportHTML.writeSum.caseNotes=Notes:",
 
 1396         "ReportHTML.writeSum.examiner=Examiner:" 
 1404         StringBuilder summary = 
new StringBuilder();
 
 1410         String caseNumber = currentCase.
getNumber();
 
 1423         summary.append(
"<div class=\"title\">\n"); 
 
 1424         if (agencyLogoSet) {
 
 1425             summary.append(
"<div class=\"left\">\n"); 
 
 1426             summary.append(
"<img src=\"");
 
 1427             summary.append(Paths.get(reportBranding.
getAgencyLogoPath()).getFileName().toString());
 
 1428             summary.append(
"\" />\n"); 
 
 1429             summary.append(
"</div>\n"); 
 
 1431         final String align = agencyLogoSet ? 
"right" : 
"left"; 
 
 1432         summary.append(
"<div class=\"").append(align).append(
"\">\n"); 
 
 1433         summary.append(
"<table>\n"); 
 
 1436         summary.append(
"<tr><td>").append(Bundle.ReportHTML_writeSum_case()).append(
"</td><td>") 
 
 1439         if (!caseNumber.isEmpty()) {
 
 1440             summary.append(
"<tr><td>").append(Bundle.ReportHTML_writeSum_caseNumber()).append(
"</td><td>") 
 
 1444         summary.append(
"<tr><td>").append(Bundle.ReportHTML_writeSum_caseNumImages()).append(
"</td><td>") 
 
 1445                 .append(imagecount).append(
"</td></tr>\n"); 
 
 1447         if (!caseNotes.isEmpty()) {
 
 1448             summary.append(
"<tr><td>").append(Bundle.ReportHTML_writeSum_caseNotes()).append(
"</td><td>") 
 
 1453         if (!examinerName.isEmpty()) {
 
 1454             summary.append(
"<tr><td>").append(Bundle.ReportHTML_writeSum_examiner()).append(
"</td><td>") 
 
 1459         summary.append(
"</table>\n"); 
 
 1460         summary.append(
"</div>\n"); 
 
 1461         summary.append(
"<div class=\"clear\"></div>\n"); 
 
 1462         summary.append(
"</div>\n"); 
 
 1472         StringBuilder summary = 
new StringBuilder();
 
 1473         summary.append(NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeSum.imageInfoHeading"));
 
 1474         summary.append(
"<div class=\"info\">\n"); 
 
 1477                 summary.append(
"<p>").append(c.getName()).append(
"</p>\n"); 
 
 1478                 if (c instanceof 
Image) {
 
 1479                     Image img = (Image) c;
 
 1481                     summary.append(
"<table>\n"); 
 
 1482                     summary.append(
"<tr><td>").append( 
 
 1483                             NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeSum.timezone"))
 
 1484                             .append(
"</td><td>").append(img.
getTimeZone()).append(
"</td></tr>\n"); 
 
 1485                     for (String imgPath : img.
getPaths()) {
 
 1486                         summary.append(
"<tr><td>").append( 
 
 1487                                 NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeSum.path"))
 
 1488                                 .append(
"</td><td>").append(imgPath).append(
"</td></tr>\n"); 
 
 1490                     summary.append(
"</table>\n"); 
 
 1494             logger.log(Level.WARNING, 
"Unable to get image information for the HTML report."); 
 
 1496         summary.append(
"</div>\n"); 
 
 1506         StringBuilder summary = 
new StringBuilder();
 
 1507         summary.append(NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeSum.softwareInfoHeading"));
 
 1508         summary.append(
"<div class=\"info\">\n");
 
 1509         summary.append(
"<table>\n");
 
 1510         summary.append(
"<tr><td>").append(NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeSum.autopsyVersion"))
 
 1512         Map<Long, IngestModuleInfo> moduleInfoHashMap = 
new HashMap<>();
 
 1514             List<IngestModuleInfo> ingestModules = ingestJob.getIngestModuleInfo();
 
 1516                 if (!moduleInfoHashMap.containsKey(ingestModule.getIngestModuleId())) {
 
 1517                     moduleInfoHashMap.put(ingestModule.getIngestModuleId(), ingestModule);
 
 1521         TreeMap<String, String> modules = 
new TreeMap<>();
 
 1523             modules.put(moduleinfo.getDisplayName(), moduleinfo.getVersion());
 
 1525         for (Map.Entry<String, String> module : modules.entrySet()) {
 
 1526             summary.append(
"<tr><td>").append(module.getKey()).append(
" Module:")
 
 1527                     .append(
"</td><td>").append(module.getValue()).append(
"</td></tr>\n");
 
 1529         summary.append(
"</table>\n");
 
 1530         summary.append(
"</div>\n");
 
 1531         summary.append(
"<div class=\"clear\"></div>\n"); 
 
 1541         StringBuilder summary = 
new StringBuilder();
 
 1543             summary.append(NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeSum.ingestHistoryHeading"));
 
 1544             summary.append(
"<div class=\"info\">\n");
 
 1548                 summary.append(
"<h3>Job ").append(jobnumber).append(
":</h3>\n");
 
 1549                 summary.append(
"<table>\n");
 
 1550                 summary.append(
"<tr><td>").append(
"Data Source:")
 
 1551                         .append(
"</td><td>").append(skCase.
getContentById(ingestJob.getObjectId()).
getName()).append(
"</td></tr>\n");
 
 1552                 summary.append(
"<tr><td>").append(
"Status:")
 
 1553                         .append(
"</td><td>").append(ingestJob.getStatus()).append(
"</td></tr>\n");
 
 1554                 summary.append(
"<tr><td>").append(NbBundle.getMessage(
this.getClass(), 
"ReportHTML.writeSum.modulesEnabledHeading"))
 
 1555                         .append(
"</td><td>");
 
 1556                 List<IngestModuleInfo> ingestModules = ingestJob.getIngestModuleInfo();
 
 1557                 summary.append(
"<ul>\n");
 
 1559                     summary.append(
"<li>").append(ingestModule.getDisplayName()).append(
"</li>");
 
 1561                 summary.append(
"</ul>\n");
 
 1563                 summary.append(
"</td></tr>\n");
 
 1564                 summary.append(
"</table>\n");
 
 1566             summary.append(
"</div>\n");
 
 1568             logger.log(Level.WARNING, 
"Unable to get ingest jobs for the HTML report.");
 
 1590         File thumbFile = Paths.get(thumbsPath, fileName + 
".png").toFile();
 
 1591         if (bufferedThumb == null) {
 
 1595             ImageIO.write(bufferedThumb, 
"png", thumbFile);
 
 1596         } 
catch (IOException ex) {
 
 1597             logger.log(Level.WARNING, 
"Failed to write thumb file to report directory.", ex); 
 
 1600         if (thumbFile.exists()
 
 1604         return THUMBS_REL_PATH
 
 1605                 + thumbFile.getName();
 
 1617         String formattedString = StringEscapeUtils.escapeHtml4(text);
 
 1618         return formattedString.replaceAll(
"(\r\n|\r|\n|\n\r)", 
"<br>");
 
List< Content > getDataSources()
static String escapeHtml(String toEscape)
String prepareThumbnail(AbstractFile file)
void startContentTagsTable(List< String > columnHeaders)
ReportModuleSettings getConfiguration()
String getAgencyLogoPath()
TskData.TagType getTagType()
List< ImageTagRegion > getTaggedRegions(List< ContentTag > contentTags)
String getGeneratorLogoPath()
static synchronized IngestManager getInstance()
void addRow(List< String > row, boolean escapeText)
static HTMLReport instance
TskData.TSK_DB_FILES_TYPE_ENUM getType()
String useDataTypeIcon(String dataType)
static final String HTML_SUBDIR
JPanel getConfigurationPanel()
Content getContentById(long id)
void addSetIndex(List< String > sets)
void setConfiguration(ReportModuleSettings settings)
String getRelativeFilePath()
boolean isIngestRunning()
StringBuilder writeSummaryImageInfo()
void addReport(String localPath, String srcModuleName, String reportName)
static BufferedImage getImageWithTags(AbstractFile file, Collection< ImageTagRegion > tagRegions)
static final String THUMBS_REL_PATH
void addThumbnailRows(Set< Content > images)
static final Logger logger
HTMLReportConfigurationPanel configPanel
void addRow(List< String > row)
static< T > ContentViewerTag< T > getTag(ContentTag contentTag, Class< T > clazz)
static BufferedImage getThumbnailWithTags(AbstractFile file, Collection< ImageTagRegion > tagRegions, IconSize iconSize)
Map< String, Integer > dataTypes
void startDataType(String name, String description)
void addRowWithTaggedContentHyperlink(List< String > row, ContentTag contentTag)
static final int ICON_SIZE_MEDIUM
static synchronized HTMLReport getDefault()
TagsManager getTagsManager()
String dataTypeToFileName(String dataType)
StringBuilder writeSummaryIngestHistoryInfo(SleuthkitCase skCase, List< IngestJobInfo > ingestJobs)
ReportModuleSettings getDefaultConfiguration()
StringBuilder writeSummaryCaseDetails()
String dateToString(long date)
void addSetElement(String elementName)
String formatHtmlString(String text)
boolean failsContentCheck(Content c)
void close(ProgressIndicator progressIndicator)
SleuthkitCase getSleuthkitCase()
static Integer THUMBNAIL_COLUMNS
static final int MAX_THUMBS_PER_PAGE
final ReportBranding reportBranding
static String escapeFileName(String fileName)
StringBuilder writeSummarySoftwareInfo(SleuthkitCase skCase, List< IngestJobInfo > ingestJobs)
void startTable(List< String > titles)
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
String makeCustomUniqueFilePath(AbstractFile file, String dirName)
void startReport(String baseReportDir)
static Case getCurrentCaseThrows()
String saveContent(AbstractFile file, String dirName)
final List< IngestJobInfo > getIngestJobs()
static BufferedImage getThumbnail(Content content, int iconSize)
static String getVersion()
void startSet(String setName)