19 package org.sleuthkit.autopsy.contentviewers;
 
   21 import java.io.IOException;
 
   22 import java.io.StringReader;
 
   23 import java.util.List;
 
   24 import java.util.logging.Level;
 
   26 import javafx.application.Platform;
 
   27 import javafx.beans.value.ChangeListener;
 
   28 import javafx.beans.value.ObservableValue;
 
   29 import javafx.concurrent.Worker;
 
   30 import javafx.scene.web.WebView;
 
   31 import javafx.embed.swing.JFXPanel;
 
   32 import javafx.scene.Scene;
 
   33 import net.htmlparser.jericho.Attribute;
 
   34 import net.htmlparser.jericho.OutputDocument;
 
   35 import net.htmlparser.jericho.Source;
 
   36 import org.openide.util.NbBundle.Messages;
 
   37 import org.w3c.dom.Document;
 
   38 import org.w3c.dom.NodeList;
 
   39 import org.w3c.dom.events.EventTarget;
 
   44 @SuppressWarnings(
"PMD.SingularField") 
 
   45 public final class 
HtmlPanel extends javax.swing.JPanel {
 
   48     private static final long serialVersionUID = 1L;
 
   49     private static final String TEXT_TYPE = 
"text/plain";
 
   50     private final JFXPanel jfxPanel = 
new JFXPanel();
 
   59         Platform.runLater(() -> {
 
   60             webView = 
new WebView();
 
   62             webView.setContextMenuEnabled(
false);
 
   64             webView.getEngine().setJavaScriptEnabled(
false);
 
   66             webView.getEngine().getLoadWorker().stateProperty().addListener(
new ChangeListener<Worker.State>() {
 
   68                 public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) {
 
   69                     if (newValue == Worker.State.SUCCEEDED) {
 
   74             Scene scene = 
new Scene(webView);
 
   75             jfxPanel.setScene(scene);
 
   76             jfxPanel.setPreferredSize(htmlJPanel.getPreferredSize());
 
   77             htmlJPanel.add(jfxPanel);
 
   87         this.htmlText = htmlText;
 
   95         Platform.runLater(() -> {
 
   96             webView.getEngine().loadContent(
"", TEXT_TYPE);
 
   98         showImagesToggleButton.setEnabled(
false);
 
  109         String returnString = 
"";
 
  111             Source source = 
new Source(
new StringReader(htmlInString));
 
  112             OutputDocument document = 
new OutputDocument(source);
 
  114             source.getAllTags().stream().filter((tag) -> (tag.toString().contains(
"background-image"))).forEachOrdered((tag) -> {
 
  115                 document.remove(tag);
 
  118             source.getAllElements(
"img").forEach((element) -> {
 
  119                 document.remove(element.getAllTags());
 
  122             source.getAllElements(
"frame").forEach((element) -> {
 
  123                 document.remove(element.getAllTags());
 
  126             source.getAllElements(
"iframe").forEach((element) -> {
 
  127                 document.remove(element.getAllTags());
 
  130             source.getAllElements(
"picture").forEach((element) -> {
 
  131                 document.remove(element.getAllTags());
 
  134             source.getAllElements(
"svg").forEach((element) -> {
 
  135                 document.remove(element.getAllTags());
 
  138             source.getAllElements(
"audio").forEach((element) -> {
 
  139                 document.remove(element.getAllTags());
 
  142             source.getAllElements(
"video").forEach((element) -> {
 
  143                 document.remove(element.getAllTags());
 
  146             source.getAllElements(
"track").forEach((element) -> {
 
  147                 document.remove(element.getAllTags());
 
  150             source.getAllElements(
"embed").forEach((element) -> {
 
  151                 document.remove(element.getAllTags());
 
  154             source.getAllElements(
"link").forEach((element) -> {
 
  155                 document.remove(element.getAllTags());
 
  158             List<Attribute> attributesToRemove = source.getURIAttributes();
 
  159             document.remove(attributesToRemove);
 
  160             returnString = document.toString();
 
  161         } 
catch (IOException ex) {
 
  162             logger.log(Level.WARNING, 
"Unable to read html for cleaning out URI elements with Jericho", ex);
 
  171         "HtmlPanel_showImagesToggleButton_show=Download Images",
 
  172         "HtmlPanel_showImagesToggleButton_hide=Hide Images",
 
  173         "Html_text_display_error=The HTML text cannot be displayed, it may not be correctly formed HTML.",})
 
  175         if (
false == htmlText.isEmpty()) {
 
  177                 if (showImagesToggleButton.isSelected()) {
 
  178                     showImagesToggleButton.setText(Bundle.HtmlPanel_showImagesToggleButton_hide());
 
  179                     Platform.runLater(() -> {
 
  180                         webView.getEngine().loadContent(htmlText);
 
  183                     showImagesToggleButton.setText(Bundle.HtmlPanel_showImagesToggleButton_show());
 
  184                     Platform.runLater(() -> {
 
  185                         webView.getEngine().loadContent(cleanseHTML(htmlText));
 
  188                 showImagesToggleButton.setEnabled(
true);
 
  189             } 
catch (Exception ignored) {
 
  190                 Platform.runLater(() -> {
 
  191                     webView.getEngine().loadContent(Bundle.Html_text_display_error(), TEXT_TYPE);
 
  202     @SuppressWarnings(
"unchecked")
 
  204     private 
void initComponents() {
 
  206         showImagesToggleButton = 
new javax.swing.JToggleButton();
 
  207         htmlJPanel = 
new javax.swing.JPanel();
 
  209         org.openide.awt.Mnemonics.setLocalizedText(showImagesToggleButton, 
org.openide.util.NbBundle.getMessage(
HtmlPanel.class, 
"HtmlPanel.showImagesToggleButton.text")); 
 
  210         showImagesToggleButton.addActionListener(
new java.awt.event.ActionListener() {
 
  211             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  212                 showImagesToggleButtonActionPerformed(evt);
 
  216         htmlJPanel.setLayout(
new java.awt.BorderLayout());
 
  218         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  219         this.setLayout(layout);
 
  220         layout.setHorizontalGroup(
 
  221             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  222             .addGroup(layout.createSequentialGroup()
 
  223                 .addComponent(showImagesToggleButton)
 
  224                 .addGap(0, 75, Short.MAX_VALUE))
 
  225             .addComponent(htmlJPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  227         layout.setVerticalGroup(
 
  228             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  229             .addGroup(layout.createSequentialGroup()
 
  230                 .addComponent(showImagesToggleButton)
 
  231                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  232                 .addComponent(htmlJPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 33, Short.MAX_VALUE))
 
  245         Platform.runLater(() -> {
 
  246             Document document = webView.getEngine().getDocument();
 
  247             if (document != null) {
 
  248                 NodeList nodeList = document.getElementsByTagName(
"a");
 
  249                 for (
int i = 0; i < nodeList.getLength(); i++) {
 
  250                     ((EventTarget) nodeList.item(i)).addEventListener(
"click", (evt) -> {
 
  251                         evt.preventDefault();
 
  252                         evt.stopPropagation();
 
javax.swing.JPanel htmlJPanel
void showImagesToggleButtonActionPerformed(java.awt.event.ActionEvent evt)
javax.swing.JToggleButton showImagesToggleButton
void setHtmlText(String htmlText)
synchronized static Logger getLogger(String name)
String cleanseHTML(String htmlInString)