19 package org.sleuthkit.autopsy.contentviewers;
21 import java.awt.BorderLayout;
22 import java.awt.Component;
23 import java.awt.Cursor;
25 import java.io.IOException;
26 import java.sql.Connection;
27 import java.sql.DriverManager;
28 import java.sql.ResultSet;
29 import java.sql.ResultSetMetaData;
30 import java.sql.SQLException;
31 import java.sql.Statement;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.Collections;
35 import java.util.LinkedHashMap;
36 import java.util.List;
38 import java.util.Objects;
39 import java.util.TreeMap;
40 import java.util.logging.Level;
41 import javax.swing.JComboBox;
42 import org.openide.util.NbBundle;
43 import org.openide.windows.WindowManager;
85 @SuppressWarnings(
"unchecked")
91 jLabel1 =
new javax.swing.JLabel();
93 jLabel2 =
new javax.swing.JLabel();
95 jLabel3 =
new javax.swing.JLabel();
101 jHdrPanel.setPreferredSize(
new java.awt.Dimension(536, 40));
103 tablesDropdownList.setModel(
new javax.swing.DefaultComboBoxModel<>(
new String[] {
"Item 1",
"Item 2",
"Item 3",
"Item 4" }));
105 public void actionPerformed(java.awt.event.ActionEvent evt) {
110 org.openide.awt.Mnemonics.setLocalizedText(
jLabel1,
org.openide.util.NbBundle.getMessage(
SQLiteViewer.class,
"SQLiteViewer.jLabel1.text"));
116 org.openide.awt.Mnemonics.setLocalizedText(
jLabel2,
org.openide.util.NbBundle.getMessage(
SQLiteViewer.class,
"SQLiteViewer.jLabel2.text"));
118 org.openide.awt.Mnemonics.setLocalizedText(
currPageLabel,
org.openide.util.NbBundle.getMessage(
SQLiteViewer.class,
"SQLiteViewer.currPageLabel.text"));
120 org.openide.awt.Mnemonics.setLocalizedText(
jLabel3,
org.openide.util.NbBundle.getMessage(
SQLiteViewer.class,
"SQLiteViewer.jLabel3.text"));
122 org.openide.awt.Mnemonics.setLocalizedText(
numPagesLabel,
org.openide.util.NbBundle.getMessage(
SQLiteViewer.class,
"SQLiteViewer.numPagesLabel.text"));
124 prevPageButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back.png")));
128 prevPageButton.setDisabledSelectedIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png")));
131 prevPageButton.addActionListener(
new java.awt.event.ActionListener() {
132 public void actionPerformed(java.awt.event.ActionEvent evt) {
137 nextPageButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png")));
141 nextPageButton.setDisabledSelectedIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png")));
144 nextPageButton.addActionListener(
new java.awt.event.ActionListener() {
145 public void actionPerformed(java.awt.event.ActionEvent evt) {
150 javax.swing.GroupLayout jHdrPanelLayout =
new javax.swing.GroupLayout(
jHdrPanel);
152 jHdrPanelLayout.setHorizontalGroup(
153 jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
154 .addGroup(jHdrPanelLayout.createSequentialGroup()
157 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
158 .addComponent(
tablesDropdownList, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE)
160 .addComponent(
numEntriesField, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)
163 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
165 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
167 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
170 .addComponent(
prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
172 .addComponent(
nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
173 .addContainerGap(133, Short.MAX_VALUE))
175 jHdrPanelLayout.setVerticalGroup(
176 jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
177 .addGroup(jHdrPanelLayout.createSequentialGroup()
179 .addGroup(jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
180 .addComponent(
nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
181 .addComponent(
prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
182 .addGroup(jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
183 .addComponent(
tablesDropdownList, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
185 .addComponent(
numEntriesField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
195 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
196 this.setLayout(layout);
197 layout.setHorizontalGroup(
198 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
199 .addComponent(
jHdrPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
200 .addComponent(
jTableDataPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
202 layout.setVerticalGroup(
203 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
204 .addGroup(layout.createSequentialGroup()
205 .addComponent(
jHdrPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 53, javax.swing.GroupLayout.PREFERRED_SIZE)
207 .addComponent(
jTableDataPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 317, Short.MAX_VALUE))
212 WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
214 if (currPage * ROWS_PER_PAGE > numRows) {
222 readTable(tableName, (currPage - 1) * ROWS_PER_PAGE + 1, ROWS_PER_PAGE);
223 WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
228 WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
238 readTable(tableName, (currPage - 1) * ROWS_PER_PAGE + 1, ROWS_PER_PAGE);
239 WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
243 JComboBox<?> cb = (JComboBox<?>) evt.getSource();
244 String tableName = (String) cb.getSelectedItem();
245 if (null == tableName) {
248 WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
250 WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
270 return Arrays.asList(SUPPORTED_MIMETYPES);
275 WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
278 WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
288 tablesDropdownList.setEnabled(
true);
289 tablesDropdownList.removeAllItems();
293 if (null != connection) {
297 }
catch (SQLException ex) {
298 logger.log(Level.SEVERE,
"Failed to close DB connection to file.", ex);
309 "SQLiteViewer.comboBox.noTableEntry=No tables found",
310 "SQLiteViewer.errorMessage.interrupted=The processing of the file was interrupted.",
311 "SQLiteViewer.errorMessage.noCurrentCase=The case has been closed.",
312 "SQLiteViewer.errorMessage.failedToExtractFile=The file could not be extracted from the data source.",
313 "SQLiteViewer.errorMessage.failedToQueryDatabase=The database tables in the file could not be read.",
314 "SQLiteViewer.errorMessage.failedToinitJDBCDriver=The JDBC driver for SQLite could not be loaded.",
315 "# {0} - exception message",
"SQLiteViewer.errorMessage.unexpectedError=An unexpected error occurred:\n{0).",})
318 tablesDropdownList.removeAllItems();
321 String tmpDBPathName;
325 logger.log(Level.SEVERE,
"Current case has been closed", ex);
330 tmpDbFile =
new File(tmpDBPathName);
331 if (! tmpDbFile.exists()) {
339 logger.log(Level.SEVERE, String.format(
"Failed to create temp copy of DB file '%s' (objId=%d)", sqliteDbFile.getName(), sqliteDbFile.getId()), ex);
347 Class.forName(
"org.sqlite.JDBC");
348 connection = DriverManager.getConnection(
"jdbc:sqlite:" + tmpDBPathName);
350 Map<String, String> dbTablesMap =
getTables();
351 if (dbTablesMap.isEmpty()) {
352 tablesDropdownList.addItem(Bundle.SQLiteViewer_comboBox_noTableEntry());
353 tablesDropdownList.setEnabled(
false);
355 dbTablesMap.keySet().forEach((tableName) -> {
356 tablesDropdownList.addItem(tableName);
359 }
catch (ClassNotFoundException ex) {
360 logger.log(Level.SEVERE, String.format(
"Failed to initialize JDBC SQLite '%s' (objId=%d)", sqliteDbFile.getName(), sqliteDbFile.getId()), ex);
362 }
catch (SQLException ex) {
363 logger.log(Level.SEVERE, String.format(
"Failed to get tables from DB file '%s' (objId=%d)", sqliteDbFile.getName(), sqliteDbFile.getId()), ex);
380 List<AbstractFile> metaFiles = fileManager.
findFiles(sqliteFile.getDataSource(), metaFileName, sqliteFile.getParent().getName());
381 if (metaFiles != null) {
382 for (AbstractFile metaFile : metaFiles) {
383 String tmpMetafilePathName = openCase.
getTempDirectory() + File.separator + metaFile.getName();
384 File tmpMetafile =
new File(tmpMetafilePathName);
395 private Map<String, String>
getTables() throws SQLException {
396 Map<String, String> dbTablesMap =
new TreeMap<>();
397 Statement statement = null;
398 ResultSet resultSet = null;
400 statement = connection.createStatement();
401 resultSet = statement.executeQuery(
402 "SELECT name, sql FROM sqlite_master "
403 +
" WHERE type= 'table' "
404 +
" ORDER BY name;");
405 while (resultSet.next()) {
406 String tableName = resultSet.getString(
"name");
407 String tableSQL = resultSet.getString(
"sql");
408 dbTablesMap.put(tableName, tableSQL);
411 if (null != resultSet) {
414 if (null != statement) {
421 @NbBundle.Messages({
"# {0} - tableName",
422 "SQLiteViewer.selectTable.errorText=Error getting row count for table: {0}"
426 try (Statement statement = connection.createStatement();
427 ResultSet resultSet = statement.executeQuery(
428 "SELECT count (*) as count FROM " + tableName)) {
430 numRows = resultSet.getInt(
"count");
435 numPagesLabel.setText(Integer.toString((numRows / ROWS_PER_PAGE) + 1));
441 readTable(tableName, (currPage - 1) * ROWS_PER_PAGE + 1, ROWS_PER_PAGE);
444 selectedTableView.setupTable(Collections.emptyList());
447 }
catch (SQLException ex) {
448 logger.log(Level.SEVERE, String.format(
"Failed to load table %s from DB file '%s' (objId=%d)", tableName, sqliteDbFile.getName(), sqliteDbFile.getId()), ex);
453 @NbBundle.Messages({
"# {0} - tableName",
454 "SQLiteViewer.readTable.errorText=Error getting rows for table: {0}"})
455 private void readTable(String tableName,
int startRow,
int numRowsToRead) {
458 Statement statement = connection.createStatement();
459 ResultSet resultSet = statement.executeQuery(
460 "SELECT * FROM " + tableName
461 +
" LIMIT " + Integer.toString(numRowsToRead)
462 +
" OFFSET " + Integer.toString(startRow - 1))) {
465 if (Objects.nonNull(rows)) {
466 selectedTableView.setupTable(rows);
468 selectedTableView.setupTable(Collections.emptyList());
470 }
catch (SQLException ex) {
471 logger.log(Level.SEVERE, String.format(
"Failed to read table %s from DB file '%s' (objId=%d)", tableName, sqliteDbFile.getName(), sqliteDbFile.getId()), ex);
476 @NbBundle.Messages(
"SQLiteViewer.BlobNotShown.message=BLOB Data not shown")
478 ResultSetMetaData metaData = rs.getMetaData();
479 int columns = metaData.getColumnCount();
480 ArrayList<Map<String, Object>> rowlist =
new ArrayList<>();
482 Map<String, Object> row =
new LinkedHashMap<>(columns);
483 for (
int i = 1; i <= columns; ++i) {
484 if (rs.getObject(i) == null) {
485 row.put(metaData.getColumnName(i),
"");
487 if (metaData.getColumnTypeName(i).compareToIgnoreCase(
"blob") == 0) {
488 row.put(metaData.getColumnName(i), Bundle.SQLiteViewer_BlobNotShown_message());
490 row.put(metaData.getColumnName(i), rs.getObject(i));
static final int ROWS_PER_PAGE
FileManager getFileManager()
javax.swing.JLabel jLabel3
Map< String, String > getTables()
ArrayList< Map< String, Object > > resultSetToArrayList(ResultSet rs)
String getTempDirectory()
static final String[] SUPPORTED_MIMETYPES
javax.swing.JLabel numPagesLabel
static final Logger logger
javax.swing.JLabel currPageLabel
static Case getOpenCase()
void findAndCopySQLiteMetaFile(AbstractFile sqliteFile, String metaFileName)
void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt)
void tablesDropdownListActionPerformed(java.awt.event.ActionEvent evt)
void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt)
static< T > long writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, Future< T > worker, boolean source)
javax.swing.JPanel jHdrPanel
javax.swing.JButton prevPageButton
final SQLiteTableView selectedTableView
javax.swing.JLabel jLabel1
javax.swing.JTextField numEntriesField
void readTable(String tableName, int startRow, int numRowsToRead)
javax.swing.JComboBox< String > tablesDropdownList
javax.swing.JLabel jLabel2
List< String > getSupportedMIMETypes()
AbstractFile sqliteDbFile
static final long serialVersionUID
SleuthkitCase getSleuthkitCase()
synchronized List< AbstractFile > findFiles(String fileName)
javax.swing.JButton nextPageButton
synchronized static Logger getLogger(String name)
void selectTable(String tableName)
void setFile(AbstractFile file)
javax.swing.JPanel jTableDataPanel
static void error(String message)