Autopsy 4.22.1
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 */
19package org.sleuthkit.autopsy.corecomponents;
20
21import java.awt.Component;
22import java.awt.Cursor;
23import java.awt.Font;
24import java.awt.event.ActionEvent;
25import java.awt.event.ActionListener;
26import java.io.File;
27import java.io.IOException;
28import java.nio.file.Paths;
29import java.util.concurrent.ExecutionException;
30import java.util.logging.Level;
31import org.sleuthkit.autopsy.coreutils.PlatformUtil;
32import org.openide.util.NbBundle;
33import org.sleuthkit.autopsy.coreutils.Logger;
34import javax.swing.JMenuItem;
35import javax.swing.JOptionPane;
36import javax.swing.SwingWorker;
37import javax.swing.text.BadLocationException;
38import javax.swing.text.Utilities;
39import org.netbeans.api.progress.ProgressHandle;
40import org.openide.nodes.Node;
41import org.openide.util.NbBundle.Messages;
42import org.openide.util.lookup.ServiceProvider;
43import org.sleuthkit.autopsy.casemodule.Case;
44import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
45import org.sleuthkit.autopsy.contentviewers.utils.ViewerPriority;
46import org.sleuthkit.autopsy.core.UserPreferences;
47import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
48import static org.sleuthkit.autopsy.corecomponents.Bundle.*;
49import org.sleuthkit.autopsy.coreutils.FileUtil;
50import org.sleuthkit.autopsy.datamodel.ContentUtils;
51import org.sleuthkit.autopsy.datamodel.DataConversion;
52import org.sleuthkit.datamodel.BlackboardArtifact;
53import org.sleuthkit.datamodel.Content;
54import org.sleuthkit.datamodel.TskCoreException;
55
59@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
60@ServiceProvider(service = DataContentViewer.class, position = 1)
61public 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
70
71 private static final Logger logger = Logger.getLogger(DataContentViewerHex.class.getName());
72
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
131
132 selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.selectAllMenuItem.text")); // NOI18N
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
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
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
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
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
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,
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,
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));
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}
void launchHxDButtonActionPerformed(java.awt.event.ActionEvent evt)
void goToPageTextFieldActionPerformed(java.awt.event.ActionEvent evt)
void launchWorker(Content source, long offset, int page)
void goToOffsetTextFieldActionPerformed(java.awt.event.ActionEvent evt)
static String escapeFileName(String fileName)
synchronized static Logger getLogger(String name)
Definition Logger.java:124
static< T > long writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, Future< T > worker, boolean source)
static String byteArrayToHex(byte[] array, int length, long arrayOffset, Font font)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.