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