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 totalPageLabel =
new javax.swing.JLabel();
95 ofLabel =
new javax.swing.JLabel();
96 currentPageLabel =
new javax.swing.JLabel();
97 pageLabel =
new javax.swing.JLabel();
98 prevPageButton =
new javax.swing.JButton();
99 nextPageButton =
new javax.swing.JButton();
100 pageLabel2 =
new javax.swing.JLabel();
101 goToPageTextField =
new javax.swing.JTextField();
102 goToPageLabel =
new javax.swing.JLabel();
103 goToOffsetLabel =
new javax.swing.JLabel();
104 goToOffsetTextField =
new javax.swing.JTextField();
105 jScrollPane1 =
new javax.swing.JScrollPane();
106 outputViewPane =
new JTextPane(){
107 public boolean getScrollableTracksViewportWidth() {
108 return (getSize().width < 400);
110 this.outputViewPane.setBackground(
new java.awt.Color(255, 255, 255));
111 this.outputViewPane.requestFocusInWindow();
112 this.outputViewPane.setCursor(Cursor.getDefaultCursor());
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 setPreferredSize(
new java.awt.Dimension(610, 58));
122 hexViewerPanel.setPreferredSize(
new java.awt.Dimension(610, 23));
124 totalPageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.totalPageLabel.text_1"));
126 ofLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.ofLabel.text_1"));
128 currentPageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.currentPageLabel.text_1"));
129 currentPageLabel.setMaximumSize(
new java.awt.Dimension(18, 14));
130 currentPageLabel.setMinimumSize(
new java.awt.Dimension(18, 14));
131 currentPageLabel.setPreferredSize(
new java.awt.Dimension(18, 14));
133 pageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.pageLabel.text_1"));
134 pageLabel.setMaximumSize(
new java.awt.Dimension(33, 14));
135 pageLabel.setMinimumSize(
new java.awt.Dimension(33, 14));
136 pageLabel.setPreferredSize(
new java.awt.Dimension(33, 14));
138 prevPageButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back.png")));
139 prevPageButton.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.prevPageButton.text"));
140 prevPageButton.setBorderPainted(
false);
141 prevPageButton.setContentAreaFilled(
false);
142 prevPageButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png")));
143 prevPageButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
144 prevPageButton.setPreferredSize(
new java.awt.Dimension(23, 23));
145 prevPageButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png")));
146 prevPageButton.addActionListener(
new java.awt.event.ActionListener() {
147 public void actionPerformed(java.awt.event.ActionEvent evt) {
148 prevPageButtonActionPerformed(evt);
152 nextPageButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png")));
153 nextPageButton.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.nextPageButton.text"));
154 nextPageButton.setBorderPainted(
false);
155 nextPageButton.setContentAreaFilled(
false);
156 nextPageButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png")));
157 nextPageButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
158 nextPageButton.setPreferredSize(
new java.awt.Dimension(23, 23));
159 nextPageButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png")));
160 nextPageButton.addActionListener(
new java.awt.event.ActionListener() {
161 public void actionPerformed(java.awt.event.ActionEvent evt) {
162 nextPageButtonActionPerformed(evt);
166 pageLabel2.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.pageLabel2.text"));
167 pageLabel2.setMaximumSize(
new java.awt.Dimension(29, 14));
168 pageLabel2.setMinimumSize(
new java.awt.Dimension(29, 14));
169 pageLabel2.setPreferredSize(
new java.awt.Dimension(29, 14));
171 goToPageTextField.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.goToPageTextField.text"));
172 goToPageTextField.addActionListener(
new java.awt.event.ActionListener() {
173 public void actionPerformed(java.awt.event.ActionEvent evt) {
174 goToPageTextFieldActionPerformed(evt);
178 goToPageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.goToPageLabel.text"));
180 goToOffsetLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.goToOffsetLabel.text"));
182 goToOffsetTextField.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.goToOffsetTextField.text"));
183 goToOffsetTextField.addActionListener(
new java.awt.event.ActionListener() {
184 public void actionPerformed(java.awt.event.ActionEvent evt) {
185 goToOffsetTextFieldActionPerformed(evt);
189 javax.swing.GroupLayout hexViewerPanelLayout =
new javax.swing.GroupLayout(hexViewerPanel);
190 hexViewerPanel.setLayout(hexViewerPanelLayout);
191 hexViewerPanelLayout.setHorizontalGroup(
192 hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
193 .addGroup(hexViewerPanelLayout.createSequentialGroup()
195 .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
197 .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
198 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
199 .addComponent(ofLabel)
200 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
201 .addComponent(totalPageLabel)
203 .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
204 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
205 .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
207 .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
209 .addComponent(goToPageLabel)
210 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
211 .addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
213 .addComponent(goToOffsetLabel)
214 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
215 .addComponent(goToOffsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
216 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
218 hexViewerPanelLayout.setVerticalGroup(
219 hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
220 .addGroup(hexViewerPanelLayout.createSequentialGroup()
221 .addGroup(hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
222 .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
223 .addGroup(hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
224 .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
225 .addComponent(ofLabel)
226 .addComponent(totalPageLabel))
227 .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
228 .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
229 .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
230 .addComponent(goToPageLabel)
231 .addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
232 .addComponent(goToOffsetLabel)
233 .addComponent(goToOffsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
237 jScrollPane1.setBackground(
new java.awt.Color(255, 255, 255));
238 jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
239 jScrollPane1.setPreferredSize(
new java.awt.Dimension(610, 402));
241 outputViewPane.setEditable(
false);
242 outputViewPane.setFont(
new java.awt.Font(
"Courier New", 0, 11));
243 outputViewPane.setCursor(
new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
244 outputViewPane.setMinimumSize(
new java.awt.Dimension(600, 20));
245 outputViewPane.setPreferredSize(
new java.awt.Dimension(700, 400));
246 jScrollPane1.setViewportView(outputViewPane);
248 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
249 this.setLayout(layout);
250 layout.setHorizontalGroup(
251 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
252 .addComponent(hexViewerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
253 .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
255 layout.setVerticalGroup(
256 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
257 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
258 .addComponent(hexViewerPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
259 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
260 .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 29, Short.MAX_VALUE)
266 setDataViewByPageNumber(currentPage - 1);
267 goToPageTextField.setText(Integer.toString(currentPage));
271 setDataViewByPageNumber(currentPage + 1);
272 goToPageTextField.setText(Integer.toString(currentPage));
276 String pageNumberStr = goToPageTextField.getText();
280 pageNumber = Integer.parseInt(pageNumberStr);
281 }
catch (NumberFormatException ex) {
282 pageNumber = totalPages + 1;
284 if (pageNumber > totalPages || pageNumber < 1) {
285 JOptionPane.showMessageDialog(
this,
286 NbBundle.getMessage(
this.getClass(),
287 "DataContentViewerHex.goToPageTextField.msgDlg",
289 NbBundle.getMessage(
this.getClass(),
290 "DataContentViewerHex.goToPageTextField.err"),
291 JOptionPane.WARNING_MESSAGE);
294 setDataViewByPageNumber(pageNumber);
308 String userSelectedLine;
311 userSelectedLine = outputViewPane.getText().subSequence(
312 Utilities.getRowStart(outputViewPane, outputViewPane.getCaretPosition()),
313 Utilities.getRowEnd(outputViewPane, outputViewPane.getCaretPosition()))
316 String hexForUserSelectedLine = userSelectedLine.substring(0, userSelectedLine.indexOf(
":"));
318 return Long.decode(hexForUserSelectedLine) + userInput;
319 }
catch (BadLocationException | StringIndexOutOfBoundsException | NumberFormatException ex) {
328 if (goToOffsetTextField.getText().startsWith(
"+") || goToOffsetTextField.getText().startsWith(
"-")) {
329 offset = getOffsetRelativeToCaretPosition(Long.decode(goToOffsetTextField.getText()));
331 offset = Long.decode(goToOffsetTextField.getText());
333 }
catch (NumberFormatException ex) {
335 JOptionPane.showMessageDialog(
this, NbBundle.getMessage(
this.getClass(),
"DataContentViewerHex.goToOffsetTextField.msgDlg", goToOffsetTextField.getText()));
340 setDataViewByOffset(offset);
342 outputViewPane.setText(NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.setDataView.invalidOffset.negativeOffsetValue"));
372 if (this.dataSource == null) {
379 long offset = (currentPage - 1) * pageLength;
381 goToOffsetTextField.setText(Long.toString(offset));
390 if (this.dataSource == null) {
393 currentPage = (int) (offset / pageLength) + 1;
395 goToPageTextField.setText(Integer.toString(currentPage));
400 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
402 String errorText = null;
405 if (dataSource.getSize() > 0) {
407 bytesRead = dataSource.read(data, offset, pageLength);
408 }
catch (TskException ex) {
409 errorText = NbBundle.getMessage(this.getClass(),
"DataContentViewerHex.setDataView.errorText", offset,
410 offset + pageLength);
411 logger.log(Level.WARNING,
"Error while trying to show the hex content.", ex);
416 if (bytesRead <= 0) {
417 errorText = NbBundle.getMessage(this.getClass(),
"DataContentViewerHex.setDataView.errorText", offset,
418 offset + pageLength);
422 if ((errorText == null) && (currentPage < totalPages)) {
423 nextPageButton.setEnabled(
true);
425 nextPageButton.setEnabled(
false);
428 if ((errorText == null) && (currentPage > 1)) {
429 prevPageButton.setEnabled(
true);
431 prevPageButton.setEnabled(
false);
434 currentPageLabel.setText(Integer.toString(currentPage));
435 setComponentsVisibility(
true);
438 if (errorText == null) {
439 int showLength = bytesRead < pageLength ? bytesRead : (int) pageLength;
442 outputViewPane.setText(errorText);
445 outputViewPane.setCaretPosition(0);
446 this.setCursor(null);
451 if ((selectedNode == null) || (!isSupported(selectedNode))) {
456 Content content = DataContentViewerUtility.getDefaultContent(selectedNode);
457 if (content == null) {
462 dataSource = content;
464 if (dataSource.getSize() > 0) {
465 totalPages = Math.round((dataSource.getSize() - 1) / pageLength) + 1;
467 totalPageLabel.setText(Integer.toString(totalPages));
469 this.setDataViewByPageNumber(1);
474 return NbBundle.getMessage(this.getClass(),
"DataContentViewerHex.title");
479 return NbBundle.getMessage(this.getClass(),
"DataContentViewerHex.toolTip");
491 this.dataSource = null;
492 currentPageLabel.setText(
"");
493 totalPageLabel.setText(
"");
494 outputViewPane.setText(
"");
495 setComponentsVisibility(
false);
504 currentPageLabel.setVisible(isVisible);
505 totalPageLabel.setVisible(isVisible);
506 ofLabel.setVisible(isVisible);
507 prevPageButton.setVisible(isVisible);
508 nextPageButton.setVisible(isVisible);
509 pageLabel.setVisible(isVisible);
510 pageLabel2.setVisible(isVisible);
511 goToPageTextField.setVisible(isVisible);
512 goToPageLabel.setVisible(isVisible);
513 goToOffsetTextField.setVisible(isVisible);
514 goToOffsetLabel.setVisible(isVisible);
522 Content content = node.getLookup().lookup(Content.class);
523 if (content != null && content.getSize() > 0) {
544 if (evt.isPopupTrigger()) {
545 rightClickMenu.setLocation(evt.getLocationOnScreen());
546 rightClickMenu.setVisible(
true);
547 copyMenuItem.setEnabled(outputViewPane.getSelectedText() != null);
549 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()