19 package org.sleuthkit.autopsy.corecomponents;
 
   22 import java.awt.event.ActionEvent;
 
   23 import java.awt.event.ActionListener;
 
   24 import java.util.logging.Level;
 
   26 import org.openide.util.NbBundle;
 
   28 import javax.swing.JMenuItem;
 
   29 import javax.swing.JOptionPane;
 
   30 import javax.swing.JTextPane;
 
   31 import javax.swing.text.BadLocationException;
 
   32 import javax.swing.text.Utilities;
 
   33 import org.openide.nodes.Node;
 
   34 import org.openide.util.lookup.ServiceProvider;
 
   43 @ServiceProvider(service = DataContentViewer.class, position = 1)
 
   46     private static final long pageLength = 16384;
 
   47     private final byte[] data = 
new byte[(int) pageLength];
 
   48     private static int currentPage = 1;
 
   59         customizeComponents();
 
   60         this.resetComponent();
 
   61         logger.log(Level.INFO, 
"Created HexView instance: " + 
this); 
 
   65         outputViewPane.setComponentPopupMenu(rightClickMenu);
 
   66         ActionListener actList = 
new ActionListener() {
 
   68             public void actionPerformed(ActionEvent e) {
 
   69                 JMenuItem jmi = (JMenuItem) e.getSource();
 
   70                 if (jmi.equals(copyMenuItem)) {
 
   71                     outputViewPane.copy();
 
   72                 } 
else if (jmi.equals(selectAllMenuItem)) {
 
   73                     outputViewPane.selectAll();
 
   77         copyMenuItem.addActionListener(actList);
 
   78         selectAllMenuItem.addActionListener(actList);
 
   86     @SuppressWarnings(
"unchecked")
 
   88     private 
void initComponents() {
 
   90         rightClickMenu = 
new javax.swing.JPopupMenu();
 
   91         copyMenuItem = 
new javax.swing.JMenuItem();
 
   92         selectAllMenuItem = 
new javax.swing.JMenuItem();
 
   93         hexViewerPanel = 
new javax.swing.JPanel();
 
   94         jScrollPane1 = 
new javax.swing.JScrollPane();
 
   95         outputViewPane = 
new JTextPane(){
 
   96      public boolean getScrollableTracksViewportWidth() {
 
   97      return (getSize().width < 400);
 
   99         this.outputViewPane.setBackground(
new java.awt.Color(255, 255, 255)); 
 
  100         this.outputViewPane.requestFocusInWindow();
 
  101         this.outputViewPane.setCursor(Cursor.getDefaultCursor());
 
  102         totalPageLabel = 
new javax.swing.JLabel();
 
  103         ofLabel = 
new javax.swing.JLabel();
 
  104         currentPageLabel = 
new javax.swing.JLabel();
 
  105         pageLabel = 
new javax.swing.JLabel();
 
  106         prevPageButton = 
new javax.swing.JButton();
 
  107         nextPageButton = 
new javax.swing.JButton();
 
  108         pageLabel2 = 
new javax.swing.JLabel();
 
  109         goToPageTextField = 
new javax.swing.JTextField();
 
  110         goToPageLabel = 
new javax.swing.JLabel();
 
  111         goToOffsetLabel = 
new javax.swing.JLabel();
 
  112         goToOffsetTextField = 
new javax.swing.JTextField();
 
  114         copyMenuItem.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class, 
"DataContentViewerHex.copyMenuItem.text")); 
 
  115         rightClickMenu.add(copyMenuItem);
 
  117         selectAllMenuItem.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class, 
"DataContentViewerHex.selectAllMenuItem.text")); 
 
  118         rightClickMenu.add(selectAllMenuItem);
 
  120         jScrollPane1.setBackground(
new java.awt.Color(255, 255, 255));
 
  122         outputViewPane.setEditable(
false);
 
  123         outputViewPane.setFont(
new java.awt.Font(
"Courier New", 0, 11)); 
 
  124         outputViewPane.setCursor(
new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
 
  125         outputViewPane.setMinimumSize(
new java.awt.Dimension(700, 20));
 
  126         outputViewPane.setPreferredSize(
new java.awt.Dimension(700, 400));
 
  127         jScrollPane1.setViewportView(outputViewPane);
 
  129         totalPageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class, 
"DataContentViewerHex.totalPageLabel.text_1")); 
 
  131         ofLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class, 
"DataContentViewerHex.ofLabel.text_1")); 
 
  133         currentPageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class, 
"DataContentViewerHex.currentPageLabel.text_1")); 
 
  134         currentPageLabel.setMaximumSize(
new java.awt.Dimension(18, 14));
 
  135         currentPageLabel.setMinimumSize(
new java.awt.Dimension(18, 14));
 
  136         currentPageLabel.setPreferredSize(
new java.awt.Dimension(18, 14));
 
  138         pageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class, 
"DataContentViewerHex.pageLabel.text_1")); 
 
  139         pageLabel.setMaximumSize(
new java.awt.Dimension(33, 14));
 
  140         pageLabel.setMinimumSize(
new java.awt.Dimension(33, 14));
 
  141         pageLabel.setPreferredSize(
new java.awt.Dimension(33, 14));
 
  143         prevPageButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back.png"))); 
 
  144         prevPageButton.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class, 
"DataContentViewerHex.prevPageButton.text")); 
 
  145         prevPageButton.setBorderPainted(
false);
 
  146         prevPageButton.setContentAreaFilled(
false);
 
  147         prevPageButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png"))); 
 
  148         prevPageButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
 
  149         prevPageButton.setPreferredSize(
new java.awt.Dimension(23, 23));
 
  150         prevPageButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"))); 
 
  151         prevPageButton.addActionListener(
new java.awt.event.ActionListener() {
 
  152             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  153                 prevPageButtonActionPerformed(evt);
 
  157         nextPageButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png"))); 
 
  158         nextPageButton.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class, 
"DataContentViewerHex.nextPageButton.text")); 
 
  159         nextPageButton.setBorderPainted(
false);
 
  160         nextPageButton.setContentAreaFilled(
false);
 
  161         nextPageButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png"))); 
 
  162         nextPageButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
 
  163         nextPageButton.setPreferredSize(
new java.awt.Dimension(23, 23));
 
  164         nextPageButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"))); 
 
  165         nextPageButton.addActionListener(
new java.awt.event.ActionListener() {
 
  166             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  167                 nextPageButtonActionPerformed(evt);
 
  171         pageLabel2.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class, 
"DataContentViewerHex.pageLabel2.text")); 
 
  172         pageLabel2.setMaximumSize(
new java.awt.Dimension(29, 14));
 
  173         pageLabel2.setMinimumSize(
new java.awt.Dimension(29, 14));
 
  174         pageLabel2.setPreferredSize(
new java.awt.Dimension(29, 14));
 
  176         goToPageTextField.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class, 
"DataContentViewerHex.goToPageTextField.text")); 
 
  177         goToPageTextField.addActionListener(
new java.awt.event.ActionListener() {
 
  178             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  179                 goToPageTextFieldActionPerformed(evt);
 
  183         goToPageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class, 
"DataContentViewerHex.goToPageLabel.text")); 
 
  185         goToOffsetLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class, 
"DataContentViewerHex.goToOffsetLabel.text")); 
 
  187         goToOffsetTextField.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class, 
"DataContentViewerHex.goToOffsetTextField.text")); 
 
  188         goToOffsetTextField.addActionListener(
new java.awt.event.ActionListener() {
 
  189             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  190                 goToOffsetTextFieldActionPerformed(evt);
 
  194         javax.swing.GroupLayout hexViewerPanelLayout = 
new javax.swing.GroupLayout(hexViewerPanel);
 
  195         hexViewerPanel.setLayout(hexViewerPanelLayout);
 
  196         hexViewerPanelLayout.setHorizontalGroup(
 
  197             hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  198             .addGroup(hexViewerPanelLayout.createSequentialGroup()
 
  200                 .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  202                 .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  203                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  204                 .addComponent(ofLabel)
 
  205                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  206                 .addComponent(totalPageLabel)
 
  208                 .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  209                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  210                 .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  212                 .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  214                 .addComponent(goToPageLabel)
 
  215                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  216                 .addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  218                 .addComponent(goToOffsetLabel)
 
  219                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  220                 .addComponent(goToOffsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  221                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 
  222             .addComponent(jScrollPane1)
 
  224         hexViewerPanelLayout.setVerticalGroup(
 
  225             hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  226             .addGroup(hexViewerPanelLayout.createSequentialGroup()
 
  227                 .addGroup(hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  228                     .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  229                     .addGroup(hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  230                         .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  231                         .addComponent(ofLabel)
 
  232                         .addComponent(totalPageLabel))
 
  233                     .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  234                     .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  235                     .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  236                     .addComponent(goToPageLabel)
 
  237                     .addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  238                     .addComponent(goToOffsetLabel)
 
  239                     .addComponent(goToOffsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  240                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  241                 .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE))
 
  244         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  245         this.setLayout(layout);
 
  246         layout.setHorizontalGroup(
 
  247             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  248             .addGap(0, 622, Short.MAX_VALUE)
 
  249             .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  250                 .addGroup(layout.createSequentialGroup()
 
  252                     .addComponent(hexViewerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  255         layout.setVerticalGroup(
 
  256             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  257             .addGap(0, 411, Short.MAX_VALUE)
 
  258             .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  259                 .addGroup(layout.createSequentialGroup()
 
  261                     .addComponent(hexViewerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  267         setDataViewByPageNumber(currentPage - 1);
 
  268         goToPageTextField.setText(Integer.toString(currentPage));
 
  272         setDataViewByPageNumber(currentPage + 1);
 
  273         goToPageTextField.setText(Integer.toString(currentPage));
 
  277         String pageNumberStr = goToPageTextField.getText();
 
  281             pageNumber = Integer.parseInt(pageNumberStr);
 
  282         } 
catch (NumberFormatException ex) {
 
  283             pageNumber = totalPages + 1;
 
  285         if (pageNumber > totalPages || pageNumber < 1) {
 
  286             JOptionPane.showMessageDialog(
this,
 
  287                     NbBundle.getMessage(
this.getClass(),
 
  288                             "DataContentViewerHex.goToPageTextField.msgDlg",
 
  290                     NbBundle.getMessage(
this.getClass(),
 
  291                             "DataContentViewerHex.goToPageTextField.err"),
 
  292                     JOptionPane.WARNING_MESSAGE);
 
  295         setDataViewByPageNumber(pageNumber);
 
  309         String userSelectedLine;
 
  312             userSelectedLine = outputViewPane.getText().subSequence(
 
  313                     Utilities.getRowStart(outputViewPane, outputViewPane.getCaretPosition()),
 
  314                     Utilities.getRowEnd(outputViewPane, outputViewPane.getCaretPosition()))
 
  317             String hexForUserSelectedLine = userSelectedLine.substring(0, userSelectedLine.indexOf(
":"));
 
  319             return Long.decode(hexForUserSelectedLine) + userInput;
 
  320         } 
catch (BadLocationException | StringIndexOutOfBoundsException | NumberFormatException ex) {
 
  329             if (goToOffsetTextField.getText().startsWith(
"+") || goToOffsetTextField.getText().startsWith(
"-")) {
 
  330                 offset = getOffsetRelativeToCaretPosition(Long.decode(goToOffsetTextField.getText()));
 
  332                 offset = Long.decode(goToOffsetTextField.getText());
 
  334         } 
catch (NumberFormatException ex) {
 
  336             JOptionPane.showMessageDialog(
this, NbBundle.getMessage(
this.getClass(), 
"DataContentViewerHex.goToOffsetTextField.msgDlg", goToOffsetTextField.getText()));
 
  341             setDataViewByOffset(offset);
 
  343             outputViewPane.setText(NbBundle.getMessage(
DataContentViewerHex.class, 
"DataContentViewerHex.setDataView.invalidOffset.negativeOffsetValue"));
 
  373         if (this.dataSource == null) {
 
  380         long offset = (currentPage - 1) * pageLength;
 
  382         goToOffsetTextField.setText(Long.toString(offset));
 
  391         if (this.dataSource == null) {
 
  394         currentPage = (int) (offset / pageLength) + 1;
 
  396         goToPageTextField.setText(Integer.toString(currentPage));
 
  401         this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  403         String errorText = null;
 
  406         if (dataSource.getSize() > 0) {
 
  408                 bytesRead = dataSource.read(data, offset, pageLength); 
 
  409             } 
catch (TskException ex) {
 
  410                 errorText = NbBundle.getMessage(this.getClass(), 
"DataContentViewerHex.setDataView.errorText", offset,
 
  411                         offset + pageLength);
 
  412                 logger.log(Level.WARNING, 
"Error while trying to show the hex content.", ex); 
 
  417         if (bytesRead <= 0) {
 
  418             errorText = NbBundle.getMessage(this.getClass(), 
"DataContentViewerHex.setDataView.errorText", offset,
 
  419                     offset + pageLength);
 
  423         if ((errorText == null) && (currentPage < totalPages)) {
 
  424             nextPageButton.setEnabled(
true);
 
  426             nextPageButton.setEnabled(
false);
 
  429         if ((errorText == null) && (currentPage > 1)) {
 
  430             prevPageButton.setEnabled(
true);
 
  432             prevPageButton.setEnabled(
false);
 
  435         currentPageLabel.setText(Integer.toString(currentPage));
 
  436         setComponentsVisibility(
true); 
 
  439         if (errorText == null) {
 
  440             int showLength = bytesRead < pageLength ? bytesRead : (int) pageLength;
 
  443             outputViewPane.setText(errorText);
 
  446         outputViewPane.setCaretPosition(0);
 
  447         this.setCursor(null);
 
  452         if ((selectedNode == null) || (!isSupported(selectedNode))) {
 
  457         Content content = (selectedNode).getLookup().lookup(Content.class);
 
  458         if (content == null) {
 
  463         dataSource = content;
 
  465         if (dataSource.getSize() > 0) {
 
  466             totalPages = Math.round((dataSource.getSize() - 1) / pageLength) + 1;
 
  468         totalPageLabel.setText(Integer.toString(totalPages));
 
  470         this.setDataViewByPageNumber(1);
 
  475         return NbBundle.getMessage(this.getClass(), 
"DataContentViewerHex.title");
 
  480         return NbBundle.getMessage(this.getClass(), 
"DataContentViewerHex.toolTip");
 
  492         this.dataSource = null;
 
  493         currentPageLabel.setText(
"");
 
  494         totalPageLabel.setText(
"");
 
  495         outputViewPane.setText(
"");
 
  496         setComponentsVisibility(
false); 
 
  505         currentPageLabel.setVisible(isVisible);
 
  506         totalPageLabel.setVisible(isVisible);
 
  507         ofLabel.setVisible(isVisible);
 
  508         prevPageButton.setVisible(isVisible);
 
  509         nextPageButton.setVisible(isVisible);
 
  510         pageLabel.setVisible(isVisible);
 
  511         pageLabel2.setVisible(isVisible);
 
  512         goToPageTextField.setVisible(isVisible);
 
  513         goToPageLabel.setVisible(isVisible);
 
  514         goToOffsetTextField.setVisible(isVisible);
 
  515         goToOffsetLabel.setVisible(isVisible);
 
  523         Content content = node.getLookup().lookup(Content.class);
 
  524         if (content != null && content.getSize() > 0) {
 
  545         if (evt.isPopupTrigger()) {
 
  546             rightClickMenu.setLocation(evt.getLocationOnScreen());
 
  547             rightClickMenu.setVisible(
true);
 
  548             copyMenuItem.setEnabled(outputViewPane.getSelectedText() != null);
 
  550             rightClickMenu.setVisible(
false);
 
void setNode(Node selectedNode)
javax.swing.JLabel currentPageLabel
javax.swing.JPopupMenu rightClickMenu
void setComponentsVisibility(boolean isVisible)
javax.swing.JButton prevPageButton
int isPreferred(Node node)
javax.swing.JTextField goToOffsetTextField
javax.swing.JScrollPane jScrollPane1
javax.swing.JLabel goToPageLabel
void setDataView(long offset)
void maybeShowPopup(java.awt.event.MouseEvent evt)
javax.swing.JTextField goToPageTextField
void goToOffsetTextFieldActionPerformed(java.awt.event.ActionEvent evt)
boolean isSupported(Node node)
javax.swing.JMenuItem copyMenuItem
long getOffsetRelativeToCaretPosition(Long userInput)
void goToPageTextFieldActionPerformed(java.awt.event.ActionEvent evt)
void setDataViewByOffset(long offset)
static String byteArrayToHex(byte[] array, int length, long arrayOffset, Font font)
javax.swing.JPanel hexViewerPanel
void setDataViewByPageNumber(int page)
javax.swing.JButton nextPageButton
javax.swing.JMenuItem selectAllMenuItem
synchronized static Logger getLogger(String name)
javax.swing.JTextPane outputViewPane
javax.swing.JLabel goToOffsetLabel
javax.swing.JLabel ofLabel
void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt)
javax.swing.JLabel totalPageLabel
javax.swing.JLabel pageLabel2
javax.swing.JLabel pageLabel
void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt)
DataContentViewer createInstance()
void customizeComponents()