Autopsy  4.20.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
DataContentViewerHex.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2019 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.corecomponents;
20 
21 import java.awt.Component;
22 import java.awt.Cursor;
23 import java.awt.Font;
24 import java.awt.event.ActionEvent;
25 import java.awt.event.ActionListener;
26 import java.io.File;
27 import java.io.IOException;
28 import java.nio.file.Paths;
29 import java.util.concurrent.ExecutionException;
30 import java.util.logging.Level;
32 import org.openide.util.NbBundle;
34 import javax.swing.JMenuItem;
35 import javax.swing.JOptionPane;
36 import javax.swing.SwingWorker;
37 import javax.swing.text.BadLocationException;
38 import javax.swing.text.Utilities;
39 import org.netbeans.api.progress.ProgressHandle;
40 import org.openide.nodes.Node;
41 import org.openide.util.NbBundle.Messages;
42 import org.openide.util.lookup.ServiceProvider;
48 import static org.sleuthkit.autopsy.corecomponents.Bundle.*;
52 import org.sleuthkit.datamodel.BlackboardArtifact;
53 import org.sleuthkit.datamodel.Content;
54 import org.sleuthkit.datamodel.TskCoreException;
55 
59 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
60 @ServiceProvider(service = DataContentViewer.class, position = 1)
61 public class DataContentViewerHex extends javax.swing.JPanel implements DataContentViewer {
62 
63  private static final long PAGE_LENGTH = 16384;
64  private final byte[] data = new byte[(int) PAGE_LENGTH];
65  private static int currentPage = 1;
66  private int totalPages;
67  private Content dataSource;
68 
69  private HexWorker worker;
70 
71  private static final Logger logger = Logger.getLogger(DataContentViewerHex.class.getName());
72 
77  initComponents();
78  customizeComponents();
79  this.resetComponent();
80  logger.log(Level.INFO, "Created HexView instance: " + this); //NON-NLS
81  }
82 
83  private void customizeComponents() {
84  outputTextArea.setComponentPopupMenu(rightClickMenu);
85  ActionListener actList = new ActionListener() {
86  @Override
87  public void actionPerformed(ActionEvent e) {
88  JMenuItem jmi = (JMenuItem) e.getSource();
89  if (jmi.equals(copyMenuItem)) {
90  outputTextArea.copy();
91  } else if (jmi.equals(selectAllMenuItem)) {
92  outputTextArea.selectAll();
93  }
94  }
95  };
96  copyMenuItem.addActionListener(actList);
97  selectAllMenuItem.addActionListener(actList);
98  }
99 
105  @SuppressWarnings("unchecked")
106  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
107  private void initComponents() {
108 
109  rightClickMenu = new javax.swing.JPopupMenu();
110  copyMenuItem = new javax.swing.JMenuItem();
111  selectAllMenuItem = new javax.swing.JMenuItem();
112  jScrollPane3 = new javax.swing.JScrollPane();
113  outputTextArea = new javax.swing.JTextArea();
114  jScrollPane2 = new javax.swing.JScrollPane();
115  hexViewerPanel = new javax.swing.JPanel();
116  totalPageLabel = new javax.swing.JLabel();
117  ofLabel = new javax.swing.JLabel();
118  currentPageLabel = new javax.swing.JLabel();
119  pageLabel = new javax.swing.JLabel();
120  prevPageButton = new javax.swing.JButton();
121  nextPageButton = new javax.swing.JButton();
122  pageLabel2 = new javax.swing.JLabel();
123  goToPageTextField = new javax.swing.JTextField();
124  goToPageLabel = new javax.swing.JLabel();
125  goToOffsetLabel = new javax.swing.JLabel();
126  goToOffsetTextField = new javax.swing.JTextField();
127  launchHxDButton = new javax.swing.JButton();
128 
129  copyMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.copyMenuItem.text")); // NOI18N
130  rightClickMenu.add(copyMenuItem);
131 
132  selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.selectAllMenuItem.text")); // NOI18N
133  rightClickMenu.add(selectAllMenuItem);
134 
135  setPreferredSize(new java.awt.Dimension(100, 58));
136 
137  jScrollPane3.setPreferredSize(new java.awt.Dimension(300, 33));
138 
139  outputTextArea.setEditable(false);
140  outputTextArea.setFont(new Font("Monospaced", Font.PLAIN, 11));
141  outputTextArea.setTabSize(0);
142  outputTextArea.setInheritsPopupMenu(true);
143  jScrollPane3.setViewportView(outputTextArea);
144 
145  jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
146  jScrollPane2.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
147 
148  totalPageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.totalPageLabel.text_1")); // NOI18N
149 
150  ofLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.ofLabel.text_1")); // NOI18N
151 
152  currentPageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.currentPageLabel.text_1")); // NOI18N
153  currentPageLabel.setMaximumSize(new java.awt.Dimension(18, 14));
154  currentPageLabel.setMinimumSize(new java.awt.Dimension(18, 14));
155 
156  pageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.pageLabel.text_1")); // NOI18N
157  pageLabel.setMaximumSize(new java.awt.Dimension(33, 14));
158  pageLabel.setMinimumSize(new java.awt.Dimension(33, 14));
159 
160  prevPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back.png"))); // NOI18N
161  prevPageButton.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.prevPageButton.text")); // NOI18N
162  prevPageButton.setBorderPainted(false);
163  prevPageButton.setContentAreaFilled(false);
164  prevPageButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png"))); // NOI18N
165  prevPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
166  prevPageButton.setPreferredSize(new java.awt.Dimension(23, 23));
167  prevPageButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"))); // NOI18N
168  prevPageButton.addActionListener(new java.awt.event.ActionListener() {
169  public void actionPerformed(java.awt.event.ActionEvent evt) {
170  prevPageButtonActionPerformed(evt);
171  }
172  });
173 
174  nextPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png"))); // NOI18N
175  nextPageButton.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.nextPageButton.text")); // NOI18N
176  nextPageButton.setBorderPainted(false);
177  nextPageButton.setContentAreaFilled(false);
178  nextPageButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png"))); // NOI18N
179  nextPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
180  nextPageButton.setPreferredSize(new java.awt.Dimension(23, 23));
181  nextPageButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"))); // NOI18N
182  nextPageButton.addActionListener(new java.awt.event.ActionListener() {
183  public void actionPerformed(java.awt.event.ActionEvent evt) {
184  nextPageButtonActionPerformed(evt);
185  }
186  });
187 
188  pageLabel2.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.pageLabel2.text")); // NOI18N
189  pageLabel2.setMaximumSize(new java.awt.Dimension(29, 14));
190  pageLabel2.setMinimumSize(new java.awt.Dimension(29, 14));
191 
192  goToPageTextField.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.goToPageTextField.text")); // NOI18N
193  goToPageTextField.addActionListener(new java.awt.event.ActionListener() {
194  public void actionPerformed(java.awt.event.ActionEvent evt) {
195  goToPageTextFieldActionPerformed(evt);
196  }
197  });
198 
199  goToPageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.goToPageLabel.text")); // NOI18N
200 
201  goToOffsetLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.goToOffsetLabel.text")); // NOI18N
202 
203  goToOffsetTextField.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.goToOffsetTextField.text")); // NOI18N
204  goToOffsetTextField.addActionListener(new java.awt.event.ActionListener() {
205  public void actionPerformed(java.awt.event.ActionEvent evt) {
206  goToOffsetTextFieldActionPerformed(evt);
207  }
208  });
209 
210  launchHxDButton.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.launchHxDButton.text")); // NOI18N
211  launchHxDButton.addActionListener(new java.awt.event.ActionListener() {
212  public void actionPerformed(java.awt.event.ActionEvent evt) {
213  launchHxDButtonActionPerformed(evt);
214  }
215  });
216 
217  javax.swing.GroupLayout hexViewerPanelLayout = new javax.swing.GroupLayout(hexViewerPanel);
218  hexViewerPanel.setLayout(hexViewerPanelLayout);
219  hexViewerPanelLayout.setHorizontalGroup(
220  hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
221  .addGroup(hexViewerPanelLayout.createSequentialGroup()
222  .addContainerGap()
223  .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
224  .addGap(18, 18, 18)
225  .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
226  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
227  .addComponent(ofLabel)
228  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
229  .addComponent(totalPageLabel)
230  .addGap(50, 50, 50)
231  .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
232  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
233  .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
234  .addGap(0, 0, 0)
235  .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
236  .addGap(18, 18, 18)
237  .addComponent(goToPageLabel)
238  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
239  .addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
240  .addGap(18, 18, 18)
241  .addComponent(goToOffsetLabel)
242  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
243  .addComponent(goToOffsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
244  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
245  .addComponent(launchHxDButton)
246  .addContainerGap(146, Short.MAX_VALUE))
247  );
248  hexViewerPanelLayout.setVerticalGroup(
249  hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
250  .addGroup(hexViewerPanelLayout.createSequentialGroup()
251  .addGroup(hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
252  .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
253  .addGroup(hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
254  .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
255  .addComponent(ofLabel)
256  .addComponent(totalPageLabel))
257  .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
258  .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
259  .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
260  .addComponent(goToPageLabel)
261  .addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
262  .addComponent(goToOffsetLabel)
263  .addGroup(hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
264  .addComponent(goToOffsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
265  .addComponent(launchHxDButton)))
266  .addGap(0, 0, 0))
267  );
268 
269  launchHxDButton.setEnabled(PlatformUtil.isWindowsOS());
270 
271  jScrollPane2.setViewportView(hexViewerPanel);
272 
273  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
274  this.setLayout(layout);
275  layout.setHorizontalGroup(
276  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
277  .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 827, Short.MAX_VALUE)
278  .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
279  );
280  layout.setVerticalGroup(
281  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
282  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
283  .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
284  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
285  .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 239, Short.MAX_VALUE))
286  );
287  }// </editor-fold>//GEN-END:initComponents
288 
289  private void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prevPageButtonActionPerformed
290  setDataViewByPageNumber(currentPage - 1);
291  goToPageTextField.setText(Integer.toString(currentPage));
292  }//GEN-LAST:event_prevPageButtonActionPerformed
293 
294  private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed
295  setDataViewByPageNumber(currentPage + 1);
296  goToPageTextField.setText(Integer.toString(currentPage));
297  }//GEN-LAST:event_nextPageButtonActionPerformed
298 
299  private void goToPageTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_goToPageTextFieldActionPerformed
300  String pageNumberStr = goToPageTextField.getText();
301  int pageNumber;
302  try {
303  pageNumber = Integer.parseInt(pageNumberStr);
304  } catch (NumberFormatException ex) {
305  pageNumber = totalPages + 1;
306  }
307  if (pageNumber > totalPages || pageNumber < 1) {
308  JOptionPane.showMessageDialog(this,
309  NbBundle.getMessage(this.getClass(),
310  "DataContentViewerHex.goToPageTextField.msgDlg",
311  totalPages),
312  NbBundle.getMessage(this.getClass(),
313  "DataContentViewerHex.goToPageTextField.err"),
314  JOptionPane.WARNING_MESSAGE);
315  return;
316  }
317  setDataViewByPageNumber(pageNumber);
318  }//GEN-LAST:event_goToPageTextFieldActionPerformed
319 
330  private long getOffsetRelativeToCaretPosition(Long userInput) {
331  String userSelectedLine;
332  try {
333  // get the selected line. Extract the current hex offset location.
334  userSelectedLine = outputTextArea.getText().subSequence(
335  Utilities.getRowStart(outputTextArea, outputTextArea.getCaretPosition()),
336  Utilities.getRowEnd(outputTextArea, outputTextArea.getCaretPosition()))
337  .toString();
338  // NOTE: This needs to change if the outputFormat of outputTextArea changes.
339  String hexForUserSelectedLine = userSelectedLine.substring(0, userSelectedLine.indexOf(':'));
340 
341  return Long.decode(hexForUserSelectedLine) + userInput;
342  } catch (BadLocationException | StringIndexOutOfBoundsException | NumberFormatException ex) {
343  // thrown in case the caret location is out of the range of the outputTextArea.
344  return -1L;
345  }
346  }
347 
348  private void goToOffsetTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_goToOffsetTextFieldActionPerformed
349  long offset;
350  try {
351  if (goToOffsetTextField.getText().startsWith("+") || goToOffsetTextField.getText().startsWith("-")) {
352  offset = getOffsetRelativeToCaretPosition(Long.decode(goToOffsetTextField.getText()));
353  } else {
354  offset = Long.decode(goToOffsetTextField.getText());
355  }
356  } catch (NumberFormatException ex) {
357  // notify the user and return
358  JOptionPane.showMessageDialog(this, NbBundle.getMessage(this.getClass(), "DataContentViewerHex.goToOffsetTextField.msgDlg", goToOffsetTextField.getText()));
359  return;
360  }
361 
362  if (offset >= 0) {
363  setDataViewByOffset(offset);
364  } else {
365  outputTextArea.setText(NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.setDataView.invalidOffset.negativeOffsetValue"));
366  }
367  }//GEN-LAST:event_goToOffsetTextFieldActionPerformed
368 
369  @NbBundle.Messages({"DataContentViewerHex.launchError=Unable to launch HxD Editor. "
370  + "Please specify the HxD install location in Tools -> Options -> External Viewer",
371  "DataContentViewerHex.copyingFile=Copying file to open in HxD..."})
372  private void launchHxDButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_launchHxDButtonActionPerformed
373  new BackgroundFileCopyTask().execute();
374  }//GEN-LAST:event_launchHxDButtonActionPerformed
375 
380  private class BackgroundFileCopyTask extends SwingWorker<Void, Void> {
381 
382  private boolean wasCancelled = false;
383 
384  @Override
385  public Void doInBackground() throws InterruptedException {
386  ProgressHandle progress = ProgressHandle.createHandle(DataContentViewerHex_copyingFile(), () -> {
387  //Cancel the swing worker (which will interrupt the ContentUtils call below)
388  this.cancel(true);
389  wasCancelled = true;
390  return true;
391  });
392 
393  try {
394  File HxDExecutable = new File(UserPreferences.getExternalHexEditorPath());
395  if (!HxDExecutable.exists() || !HxDExecutable.canExecute()) {
396  JOptionPane.showMessageDialog(null, DataContentViewerHex_launchError());
397  return null;
398  }
399 
400  String tempDirectory = Case.getCurrentCaseThrows().getTempDirectory();
401  File tempFile = Paths.get(tempDirectory,
402  FileUtil.escapeFileName(dataSource.getId() + dataSource.getName())).toFile();
403 
404  progress.start(100);
405  ContentUtils.writeToFile(dataSource, tempFile, progress, this, true);
406 
407  if (wasCancelled) {
408  tempFile.delete();
409  progress.finish();
410  return null;
411  }
412 
413  try {
414  ProcessBuilder launchHxDExecutable = new ProcessBuilder();
415  launchHxDExecutable.command(String.format("\"%s\" \"%s\"",
416  HxDExecutable.getAbsolutePath(),
417  tempFile.getAbsolutePath()));
418  launchHxDExecutable.start();
419  } catch (IOException ex) {
420  logger.log(Level.WARNING, "Unsuccessful attempt to launch HxD", ex);
421  JOptionPane.showMessageDialog(null, DataContentViewerHex_launchError());
422  tempFile.delete();
423  }
424  } catch (NoCurrentCaseException | IOException ex) {
425  logger.log(Level.SEVERE, "Unable to copy file into temp directory", ex);
426  JOptionPane.showMessageDialog(null, DataContentViewerHex_launchError());
427  }
428 
429  progress.finish();
430  return null;
431  }
432  }
433 
434 
435  // Variables declaration - do not modify//GEN-BEGIN:variables
436  private javax.swing.JMenuItem copyMenuItem;
437  private javax.swing.JLabel currentPageLabel;
438  private javax.swing.JLabel goToOffsetLabel;
439  private javax.swing.JTextField goToOffsetTextField;
440  private javax.swing.JLabel goToPageLabel;
441  private javax.swing.JTextField goToPageTextField;
442  private javax.swing.JPanel hexViewerPanel;
443  private javax.swing.JScrollPane jScrollPane2;
444  private javax.swing.JScrollPane jScrollPane3;
445  private javax.swing.JButton launchHxDButton;
446  private javax.swing.JButton nextPageButton;
447  private javax.swing.JLabel ofLabel;
448  private javax.swing.JTextArea outputTextArea;
449  private javax.swing.JLabel pageLabel;
450  private javax.swing.JLabel pageLabel2;
451  private javax.swing.JButton prevPageButton;
452  private javax.swing.JPopupMenu rightClickMenu;
453  private javax.swing.JMenuItem selectAllMenuItem;
454  private javax.swing.JLabel totalPageLabel;
455  // End of variables declaration//GEN-END:variables
456 
462  private void setDataViewByPageNumber(int page) {
463  if (page == 0) {
464  return;
465  }
466 
467  launchWorker(dataSource, (page - 1) * PAGE_LENGTH, page);
468  }
469 
475  private void setDataViewByOffset(long offset) {
476  launchWorker(dataSource, offset, (int) (offset / PAGE_LENGTH) + 1);
477  }
478 
479  @Messages({
480  "DataContentViewerHex_loading_text=Loading hex from file..."
481  })
482 
490  private void launchWorker(Content source, long offset, int page) {
491  if (this.dataSource == null) {
492  return;
493  }
494 
495  worker = new HexWorker(source, offset, page);
496  setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
497  outputTextArea.setText(Bundle.DataContentViewerHex_loading_text());
498  worker.execute();
499  }
500 
501  @Override
502  public void setNode(Node selectedNode) {
503  if (worker != null) {
504  worker.cancel(true);
505  worker = null;
506  }
507 
508  resetComponent();
509 
510  if ((selectedNode == null)) {
511  return;
512  }
513 
514  Content content = DataContentViewerUtility.getDefaultContent(selectedNode);
515  if (content == null) {
516  return;
517  }
518 
519  dataSource = content;
520  totalPages = 0;
521  if (dataSource.getSize() > 0) {
522  totalPages = Math.round((dataSource.getSize() - 1) / PAGE_LENGTH) + 1;
523  }
524  totalPageLabel.setText(Integer.toString(totalPages));
525 
526  this.setDataViewByPageNumber(1);
527  }
528 
529  @Override
530  public String getTitle() {
531  return NbBundle.getMessage(this.getClass(), "DataContentViewerHex.title");
532  }
533 
534  @Override
535  public String getToolTip() {
536  return NbBundle.getMessage(this.getClass(), "DataContentViewerHex.toolTip");
537  }
538 
539  @Override
540  public DataContentViewer createInstance() {
541  return new DataContentViewerHex();
542  }
543 
544  @Override
545  public void resetComponent() {
546  // clear / reset the fields
547  currentPage = 1;
548  this.dataSource = null;
549  currentPageLabel.setText("");
550  totalPageLabel.setText("");
551  outputTextArea.setText("");
552  setComponentsVisibility(false); // hides the components that not needed
553  }
554 
560  private void setComponentsVisibility(boolean isVisible) {
561  currentPageLabel.setVisible(isVisible);
562  totalPageLabel.setVisible(isVisible);
563  ofLabel.setVisible(isVisible);
564  prevPageButton.setVisible(isVisible);
565  nextPageButton.setVisible(isVisible);
566  pageLabel.setVisible(isVisible);
567  pageLabel2.setVisible(isVisible);
568  goToPageTextField.setVisible(isVisible);
569  goToPageLabel.setVisible(isVisible);
570  goToOffsetTextField.setVisible(isVisible);
571  goToOffsetLabel.setVisible(isVisible);
572  launchHxDButton.setVisible(isVisible);
573  }
574 
575  @Override
576  public boolean isSupported(Node node) {
577  if (node == null) {
578  return false;
579  }
580  Content content = DataContentViewerUtility.getDefaultContent(node);
581  return content != null && !(content instanceof BlackboardArtifact) && content.getSize() > 0;
582  }
583 
584  @Override
585  public int isPreferred(Node node) {
586  return ViewerPriority.viewerPriority.LevelOne.getFlag();
587  }
588 
589  @Override
590  public Component getComponent() {
591  return this;
592  }
593 
597  private class HexWorker extends SwingWorker<String, Void> {
598 
599  private final byte[] data = new byte[(int) PAGE_LENGTH];
600  private final long offset;
601  private final Content content;
602  private final int newCurrentPage;
603  private String errorText = "";
604 
605  HexWorker(Content content, long offset, int newCurrentPage) {
606  this.content = content;
607  this.offset = offset;
608  this.newCurrentPage = newCurrentPage;
609  }
610 
611  @Override
612  protected String doInBackground() throws Exception {
613  int bytesRead = 0;
614  if (content.getSize() > 0) {
615  try {
616  bytesRead = content.read(data, offset, PAGE_LENGTH); // read the data
617  } catch (TskCoreException ex) {
618  errorText = NbBundle.getMessage(this.getClass(), "DataContentViewerHex.setDataView.errorText", offset,
619  offset + PAGE_LENGTH);
620  logger.log(Level.WARNING, "Error while trying to show the hex content.", ex); //NON-NLS
621  }
622  }
623 
624  // set the data on the bottom and show it
625  if (bytesRead <= 0) {
626  errorText = NbBundle.getMessage(this.getClass(), "DataContentViewerHex.setDataView.errorText", offset,
627  offset + PAGE_LENGTH);
628  }
629 
630  if (errorText.isEmpty()) {
631  int showLength = bytesRead < PAGE_LENGTH ? bytesRead : (int) PAGE_LENGTH;
632  return DataConversion.byteArrayToHex(data, showLength, offset);
633  } else {
634  return errorText;
635  }
636  }
637 
638  @Override
639  public void done() {
640  if (isCancelled()) {
641  return;
642  }
643 
644  try {
645  String text = get();
646  outputTextArea.setText(text);
647 
648  // disable or enable the next button
649  if ((errorText.isEmpty()) && (newCurrentPage < totalPages)) {
650  nextPageButton.setEnabled(true);
651  } else {
652  nextPageButton.setEnabled(false);
653  }
654 
655  if ((errorText.isEmpty()) && (newCurrentPage > 1)) {
656  prevPageButton.setEnabled(true);
657  } else {
658  prevPageButton.setEnabled(false);
659  }
660 
661  currentPageLabel.setText(Integer.toString(newCurrentPage));
662  setComponentsVisibility(true); // shows the components that not needed
663  outputTextArea.setCaretPosition(0);
664  goToPageTextField.setText(Integer.toString(newCurrentPage));
665  currentPage = newCurrentPage;
666  setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
667 
668  } catch (InterruptedException | ExecutionException ex) {
669  logger.log(Level.SEVERE, String.format("Failed to get hex data from content (%d)", content.getId()), ex);
670  }
671  }
672  }
673 }
static< T > long writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, Future< T > worker, boolean source)
void goToOffsetTextFieldActionPerformed(java.awt.event.ActionEvent evt)
void launchWorker(Content source, long offset, int page)
void goToPageTextFieldActionPerformed(java.awt.event.ActionEvent evt)
static String byteArrayToHex(byte[] array, int length, long arrayOffset, Font font)
void launchHxDButtonActionPerformed(java.awt.event.ActionEvent evt)
static String escapeFileName(String fileName)
Definition: FileUtil.java:169
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt)
void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt)

Copyright © 2012-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.