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