19 package org.sleuthkit.autopsy.geolocation;
 
   21 import java.awt.Color;
 
   23 import java.sql.SQLException;
 
   24 import java.util.Arrays;
 
   25 import java.util.logging.Level;
 
   26 import javax.swing.JFileChooser;
 
   27 import javax.swing.JOptionPane;
 
   28 import org.apache.commons.validator.routines.UrlValidator;
 
   29 import org.jxmapviewer.OSMTileFactoryInfo;
 
   30 import org.jxmapviewer.viewer.TileFactoryInfo;
 
   31 import org.jxmapviewer.viewer.util.GeoUtil;
 
   32 import org.netbeans.spi.options.OptionsPanelController;
 
   33 import org.openide.util.NbBundle.Messages;
 
   45 final class GeolocationSettingsPanel 
extends javax.swing.JPanel implements OptionsPanel {
 
   47     private static final long serialVersionUID = 1L;
 
   49     private static final Logger logger = Logger.getLogger(GeolocationSettingsPanel.class.getName());
 
   51     private static final JFileChooserFactory chooserHelper = 
new JFileChooserFactory();
 
   56     GeolocationSettingsPanel() {
 
   63         UserPreferences.setGeolocationTileOption(getDataSourceOption().getValue());
 
   64         UserPreferences.setGeolocationOsmZipPath(zipFilePathField.getText());
 
   65         UserPreferences.setGeolocationOsmServerAddress(osmServerAddressField.getText());
 
   66         UserPreferences.setGeolocationMBTilesFilePath(mbtileFileField.getText());
 
   71         osmServerAddressField.setText(UserPreferences.getGeolocationOsmServerAddress());
 
   72         zipFilePathField.setText(UserPreferences.getGeolocationOsmZipPath());
 
   73         mbtileFileField.setText(UserPreferences.getGeolocationMBTilesFilePath());
 
   74         switch (GeolocationDataSourceType.getOptionForValue(UserPreferences.getGeolocationtTileOption())) {
 
   75             case ONLINE_USER_DEFINED_OSM_SERVER:
 
   76                 osmServerRBnt.setSelected(
true);
 
   79                 zipFileRBnt.setSelected(
true);
 
   81             case OFFILE_MBTILES_FILE:
 
   82                 mbtilesRBtn.setSelected(
true);
 
   85                 defaultDataSource.setSelected(
true);
 
   96     private void updateControlState() {
 
   97         osmServerAddressField.setEnabled(osmServerRBnt.isSelected());
 
   98         serverTestBtn.setEnabled(osmServerRBnt.isSelected());
 
   99         zipFilePathField.setEnabled(zipFileRBnt.isSelected());
 
  100         zipFileBrowseBnt.setEnabled(zipFileRBnt.isSelected());
 
  101         mbtileFileField.setEnabled(mbtilesRBtn.isSelected());
 
  102         mbtilesBrowseBtn.setEnabled(mbtilesRBtn.isSelected());
 
  103         mbtileTestBtn.setEnabled(mbtilesRBtn.isSelected());
 
  112     private GeolocationDataSourceType getDataSourceOption() {
 
  113         if (osmServerRBnt.isSelected()) {
 
  114             return GeolocationDataSourceType.ONLINE_USER_DEFINED_OSM_SERVER;
 
  115         } 
else if (zipFileRBnt.isSelected()) {
 
  116             return GeolocationDataSourceType.OFFLINE_OSM_ZIP;
 
  117         } 
else if (mbtilesRBtn.isSelected()) {
 
  118             return GeolocationDataSourceType.OFFILE_MBTILES_FILE;
 
  120         return GeolocationDataSourceType.ONLINE_DEFAULT_SERVER;
 
  135     private boolean testOSMServer(String url) {
 
  136         TileFactoryInfo info = 
new OSMTileFactoryInfo(
"User Defined Server", url); 
 
  137         return GeoUtil.isValidTile(1, 1, 1, info);
 
  140     void cancelChanges() {
 
  149     @SuppressWarnings(
"unchecked")
 
  151     private 
void initComponents() {
 
  152         java.awt.GridBagConstraints gridBagConstraints;
 
  154         javax.swing.ButtonGroup buttonGroup = 
new javax.swing.ButtonGroup();
 
  155         javax.swing.JPanel tilePane = 
new javax.swing.JPanel();
 
  156         defaultDataSource = 
new javax.swing.JRadioButton();
 
  157         osmServerRBnt = 
new javax.swing.JRadioButton();
 
  158         osmServerAddressField = 
new javax.swing.JTextField();
 
  159         zipFileRBnt = 
new javax.swing.JRadioButton();
 
  160         zipFilePathField = 
new javax.swing.JTextField();
 
  161         zipFileBrowseBnt = 
new javax.swing.JButton();
 
  162         serverTestBtn = 
new javax.swing.JButton();
 
  163         mbtilesRBtn = 
new javax.swing.JRadioButton();
 
  164         mbtileFileField = 
new javax.swing.JTextField();
 
  165         javax.swing.JPanel MBTilesBtnPanel = 
new javax.swing.JPanel();
 
  166         mbtilesBrowseBtn = 
new javax.swing.JButton();
 
  167         mbtileTestBtn = 
new javax.swing.JButton();
 
  169         setLayout(
new java.awt.GridBagLayout());
 
  171         tilePane.setBorder(javax.swing.BorderFactory.createTitledBorder(
org.openide.util.NbBundle.getMessage(GeolocationSettingsPanel.class, 
"GeolocationSettingsPanel.tilePane.border.title"))); 
 
  172         tilePane.setLayout(
new java.awt.GridBagLayout());
 
  174         buttonGroup.add(defaultDataSource);
 
  175         defaultDataSource.setSelected(
true);
 
  176         org.openide.awt.Mnemonics.setLocalizedText(defaultDataSource, 
org.openide.util.NbBundle.getMessage(GeolocationSettingsPanel.class, 
"GeolocationSettingsPanel.defaultDataSource.text")); 
 
  177         defaultDataSource.addActionListener(
new java.awt.event.ActionListener() {
 
  178             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  179                 defaultDataSourceActionPerformed(evt);
 
  182         gridBagConstraints = 
new java.awt.GridBagConstraints();
 
  183         gridBagConstraints.gridx = 0;
 
  184         gridBagConstraints.gridy = 0;
 
  185         gridBagConstraints.gridwidth = 4;
 
  186         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 
  187         gridBagConstraints.weightx = 1.0;
 
  188         gridBagConstraints.insets = 
new java.awt.Insets(9, 0, 9, 0);
 
  189         tilePane.add(defaultDataSource, gridBagConstraints);
 
  191         buttonGroup.add(osmServerRBnt);
 
  192         org.openide.awt.Mnemonics.setLocalizedText(osmServerRBnt, 
org.openide.util.NbBundle.getMessage(GeolocationSettingsPanel.class, 
"GeolocationSettingsPanel.osmServerRBnt.text")); 
 
  193         osmServerRBnt.addActionListener(
new java.awt.event.ActionListener() {
 
  194             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  195                 osmServerRBntActionPerformed(evt);
 
  198         gridBagConstraints = 
new java.awt.GridBagConstraints();
 
  199         gridBagConstraints.gridx = 0;
 
  200         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 
  201         gridBagConstraints.insets = 
new java.awt.Insets(0, 0, 9, 0);
 
  202         tilePane.add(osmServerRBnt, gridBagConstraints);
 
  204         osmServerAddressField.setText(
org.openide.util.NbBundle.getMessage(GeolocationSettingsPanel.class, 
"GeolocationSettingsPanel.osmServerAddressField.text")); 
 
  205         osmServerAddressField.setPreferredSize(
new java.awt.Dimension(300, 26));
 
  206         gridBagConstraints = 
new java.awt.GridBagConstraints();
 
  207         gridBagConstraints.gridx = 1;
 
  208         gridBagConstraints.gridy = 1;
 
  209         gridBagConstraints.insets = 
new java.awt.Insets(0, 0, 9, 0);
 
  210         tilePane.add(osmServerAddressField, gridBagConstraints);
 
  212         buttonGroup.add(zipFileRBnt);
 
  213         org.openide.awt.Mnemonics.setLocalizedText(zipFileRBnt, 
org.openide.util.NbBundle.getMessage(GeolocationSettingsPanel.class, 
"GeolocationSettingsPanel.zipFileRBnt.text")); 
 
  214         zipFileRBnt.setActionCommand(
org.openide.util.NbBundle.getMessage(GeolocationSettingsPanel.class, 
"GeolocationSettingsPanel.zipFileRBnt.actionCommand")); 
 
  215         zipFileRBnt.addActionListener(
new java.awt.event.ActionListener() {
 
  216             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  217                 zipFileRBntActionPerformed(evt);
 
  220         gridBagConstraints = 
new java.awt.GridBagConstraints();
 
  221         gridBagConstraints.gridx = 0;
 
  222         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 
  223         gridBagConstraints.insets = 
new java.awt.Insets(0, 0, 9, 0);
 
  224         tilePane.add(zipFileRBnt, gridBagConstraints);
 
  226         zipFilePathField.setText(
org.openide.util.NbBundle.getMessage(GeolocationSettingsPanel.class, 
"GeolocationSettingsPanel.zipFilePathField.text")); 
 
  227         zipFilePathField.setPreferredSize(
new java.awt.Dimension(300, 26));
 
  228         gridBagConstraints = 
new java.awt.GridBagConstraints();
 
  229         gridBagConstraints.gridx = 1;
 
  230         gridBagConstraints.gridy = 2;
 
  231         gridBagConstraints.insets = 
new java.awt.Insets(0, 0, 9, 0);
 
  232         tilePane.add(zipFilePathField, gridBagConstraints);
 
  234         org.openide.awt.Mnemonics.setLocalizedText(zipFileBrowseBnt, 
org.openide.util.NbBundle.getMessage(GeolocationSettingsPanel.class, 
"GeolocationSettingsPanel.zipFileBrowseBnt.text")); 
 
  235         zipFileBrowseBnt.addActionListener(
new java.awt.event.ActionListener() {
 
  236             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  237                 zipFileBrowseBntActionPerformed(evt);
 
  240         gridBagConstraints = 
new java.awt.GridBagConstraints();
 
  241         gridBagConstraints.gridx = 2;
 
  242         gridBagConstraints.gridy = 2;
 
  243         gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 
  244         gridBagConstraints.insets = 
new java.awt.Insets(0, 9, 9, 9);
 
  245         tilePane.add(zipFileBrowseBnt, gridBagConstraints);
 
  247         org.openide.awt.Mnemonics.setLocalizedText(serverTestBtn, 
org.openide.util.NbBundle.getMessage(GeolocationSettingsPanel.class, 
"GeolocationSettingsPanel.serverTestBtn.text")); 
 
  248         serverTestBtn.addActionListener(
new java.awt.event.ActionListener() {
 
  249             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  250                 serverTestBtnActionPerformed(evt);
 
  253         gridBagConstraints = 
new java.awt.GridBagConstraints();
 
  254         gridBagConstraints.gridx = 2;
 
  255         gridBagConstraints.gridy = 1;
 
  256         gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
 
  257         gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 
  258         gridBagConstraints.insets = 
new java.awt.Insets(0, 9, 9, 9);
 
  259         tilePane.add(serverTestBtn, gridBagConstraints);
 
  261         buttonGroup.add(mbtilesRBtn);
 
  262         org.openide.awt.Mnemonics.setLocalizedText(mbtilesRBtn, 
org.openide.util.NbBundle.getMessage(GeolocationSettingsPanel.class, 
"GeolocationSettingsPanel.mbtilesRBtn.text")); 
 
  263         mbtilesRBtn.addActionListener(
new java.awt.event.ActionListener() {
 
  264             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  265                 mbtilesRBtnActionPerformed(evt);
 
  268         gridBagConstraints = 
new java.awt.GridBagConstraints();
 
  269         gridBagConstraints.gridx = 0;
 
  270         gridBagConstraints.gridy = 3;
 
  271         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 
  272         gridBagConstraints.insets = 
new java.awt.Insets(0, 0, 9, 0);
 
  273         tilePane.add(mbtilesRBtn, gridBagConstraints);
 
  275         mbtileFileField.setText(
org.openide.util.NbBundle.getMessage(GeolocationSettingsPanel.class, 
"GeolocationSettingsPanel.mbtileFileField.text")); 
 
  276         mbtileFileField.setToolTipText(
org.openide.util.NbBundle.getMessage(GeolocationSettingsPanel.class, 
"GeolocationSettingsPanel.mbtileFileField.toolTipText")); 
 
  277         mbtileFileField.setPreferredSize(
new java.awt.Dimension(300, 26));
 
  278         gridBagConstraints = 
new java.awt.GridBagConstraints();
 
  279         gridBagConstraints.gridx = 1;
 
  280         gridBagConstraints.gridy = 3;
 
  281         gridBagConstraints.insets = 
new java.awt.Insets(0, 0, 9, 0);
 
  282         tilePane.add(mbtileFileField, gridBagConstraints);
 
  284         MBTilesBtnPanel.setLayout(
new java.awt.GridLayout(1, 0, 5, 0));
 
  286         org.openide.awt.Mnemonics.setLocalizedText(mbtilesBrowseBtn, 
org.openide.util.NbBundle.getMessage(GeolocationSettingsPanel.class, 
"GeolocationSettingsPanel.mbtilesBrowseBtn.text")); 
 
  287         mbtilesBrowseBtn.addActionListener(
new java.awt.event.ActionListener() {
 
  288             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  289                 mbtilesBrowseBtnActionPerformed(evt);
 
  292         MBTilesBtnPanel.add(mbtilesBrowseBtn);
 
  294         org.openide.awt.Mnemonics.setLocalizedText(mbtileTestBtn, 
org.openide.util.NbBundle.getMessage(GeolocationSettingsPanel.class, 
"GeolocationSettingsPanel.mbtileTestBtn.text")); 
 
  295         mbtileTestBtn.addActionListener(
new java.awt.event.ActionListener() {
 
  296             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  297                 mbtileTestBtnActionPerformed(evt);
 
  300         MBTilesBtnPanel.add(mbtileTestBtn);
 
  302         gridBagConstraints = 
new java.awt.GridBagConstraints();
 
  303         gridBagConstraints.gridx = 2;
 
  304         gridBagConstraints.gridy = 3;
 
  305         gridBagConstraints.gridwidth = 2;
 
  306         gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 
  307         gridBagConstraints.insets = 
new java.awt.Insets(0, 9, 9, 9);
 
  308         tilePane.add(MBTilesBtnPanel, gridBagConstraints);
 
  310         gridBagConstraints = 
new java.awt.GridBagConstraints();
 
  311         gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
 
  312         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 
  313         gridBagConstraints.weightx = 1.0;
 
  314         gridBagConstraints.weighty = 1.0;
 
  315         add(tilePane, gridBagConstraints);
 
  318     private void zipFileBrowseBntActionPerformed(java.awt.event.ActionEvent evt) {
 
  319         JFileChooser fileWindow = chooserHelper.getChooser();
 
  320         fileWindow.setFileSelectionMode(JFileChooser.FILES_ONLY);
 
  321         GeneralFilter fileFilter = 
new GeneralFilter(Arrays.asList(
".zip"), 
"Zips (*.zip)"); 
 
  322         fileWindow.setDragEnabled(
false);
 
  323         fileWindow.setFileFilter(fileFilter);
 
  324         fileWindow.setMultiSelectionEnabled(
false);
 
  325         int returnVal = fileWindow.showSaveDialog(
this);
 
  326         if (returnVal == JFileChooser.APPROVE_OPTION) {
 
  327             File zipFile = fileWindow.getSelectedFile();
 
  328             zipFilePathField.setForeground(Color.BLACK);
 
  329             zipFilePathField.setText(zipFile.getAbsolutePath());
 
  330             firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
 
  334     private void defaultDataSourceActionPerformed(java.awt.event.ActionEvent evt) {
 
  335         updateControlState();
 
  336         firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
 
  339     private void osmServerRBntActionPerformed(java.awt.event.ActionEvent evt) {
 
  340         updateControlState();
 
  341         firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
 
  344     private void zipFileRBntActionPerformed(java.awt.event.ActionEvent evt) {
 
  345         updateControlState();
 
  346         firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
 
  350         "GeolocationSettingsPanel_malformed_url_message=The supplied OSM tile server address is invalid.\nPlease supply a well formed url prefixed with http://",
 
  351         "GeolocationSettingsPanel_malformed_url_message_tile=Malformed URL",
 
  352         "GeolocationSettingsPanel_osm_server_test_fail_message=OSM tile server test failed.\nUnable to connect to server.",
 
  353         "GeolocationSettingsPanel_osm_server_test_fail_message_title=Error",
 
  354         "GeolocationSettingsPanel_osm_server_test_success_message=The provided OSM tile server address is valid.",
 
  355         "GeolocationSettingsPanel_osm_server_test_success_message_title=Success",})
 
  356     private void serverTestBtnActionPerformed(java.awt.event.ActionEvent evt) {
 
  357         String address = osmServerAddressField.getText();
 
  358         String message = Bundle.GeolocationSettingsPanel_osm_server_test_fail_message();
 
  359         String title = Bundle.GeolocationSettingsPanel_osm_server_test_fail_message_title();
 
  361         String[] schemes = {
"http", 
"https"}; 
 
  362         UrlValidator urlValidator = 
new UrlValidator(schemes);
 
  363         if (!urlValidator.isValid(address)) {
 
  364             message = Bundle.GeolocationSettingsPanel_malformed_url_message();
 
  365             title = Bundle.GeolocationSettingsPanel_malformed_url_message_tile();
 
  366         } 
else if (testOSMServer(address)) {
 
  367             message = Bundle.GeolocationSettingsPanel_osm_server_test_success_message();
 
  368             title = Bundle.GeolocationSettingsPanel_osm_server_test_success_message_title();
 
  371         JOptionPane.showMessageDialog(
this, message, title, JOptionPane.INFORMATION_MESSAGE);
 
  374     private void mbtilesRBtnActionPerformed(java.awt.event.ActionEvent evt) {
 
  375         updateControlState();
 
  376         firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
 
  379     private void mbtilesBrowseBtnActionPerformed(java.awt.event.ActionEvent evt) {
 
  380         JFileChooser fileWindow = chooserHelper.getChooser();
 
  381         fileWindow.setFileSelectionMode(JFileChooser.FILES_ONLY);
 
  382         GeneralFilter fileFilter = 
new GeneralFilter(Arrays.asList(
".mbtiles"), 
"MBTiles (*.mbtiles)"); 
 
  383         fileWindow.setDragEnabled(
false);
 
  384         fileWindow.setFileFilter(fileFilter);
 
  385         fileWindow.setMultiSelectionEnabled(
false);
 
  386         int returnVal = fileWindow.showSaveDialog(
this);
 
  387         if (returnVal == JFileChooser.APPROVE_OPTION) {
 
  388             File zipFile = fileWindow.getSelectedFile();
 
  389             mbtileFileField.setForeground(Color.BLACK);
 
  390             mbtileFileField.setText(zipFile.getAbsolutePath());
 
  391             firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
 
  396         "GeolocationSettings_mbtile_does_not_exist_message=The file supplied does not exist.\nPlease verify that the file exists and try again.",
 
  397         "GeolocationSettings_mbtile_does_not_exist_title=File Not Found",
 
  398         "GeolocationSettings_mbtile_not_valid_message=The supplied file is not a raster tile file.",
 
  399         "GeolocationSettings_mbtile_not_valid_title=File Not Valid",
 
  400         "GeolocationSettings_path_not_valid_message=The supplied file path is empty.\nPlease supply a valid file path.",
 
  401         "GeolocationSettings_path_not_valid_title=File Not Valid",
 
  402         "GeolocationSettings_mbtile_test_success_message=The supplied file is a valid mbtile raster file.",
 
  403         "GeolocationSettings_mbtile_test_success_title=Success",
 
  405     private void mbtileTestBtnActionPerformed(java.awt.event.ActionEvent evt) {
 
  406         String mbtilePath = mbtileFileField.getText();
 
  408         if(mbtilePath.isEmpty()) {
 
  409             JOptionPane.showMessageDialog(
this, Bundle.GeolocationSettings_path_not_valid_message(), Bundle.GeolocationSettings_path_not_valid_title(), JOptionPane.ERROR_MESSAGE);
 
  413         File file = 
new File(mbtilePath);
 
  415             JOptionPane.showMessageDialog(
this, Bundle.GeolocationSettings_mbtile_does_not_exist_message(), Bundle.GeolocationSettings_mbtile_does_not_exist_title(), JOptionPane.ERROR_MESSAGE);
 
  420             if(!MBTilesFileConnector.isValidMBTileRasterFile(mbtilePath)) {
 
  421                 JOptionPane.showMessageDialog(
this, Bundle.GeolocationSettings_mbtile_not_valid_message(), Bundle.GeolocationSettings_mbtile_not_valid_title(), JOptionPane.ERROR_MESSAGE);
 
  424         } 
catch (SQLException ex) {
 
  425             JOptionPane.showMessageDialog(
this, Bundle.GeolocationSettings_mbtile_not_valid_message(), Bundle.GeolocationSettings_mbtile_not_valid_title(), JOptionPane.ERROR_MESSAGE);
 
  426             logger.log(Level.WARNING, String.format(
"Exception thrown while testing mbtile file %s", mbtilePath), ex);
 
  430         JOptionPane.showMessageDialog(
this, Bundle.GeolocationSettings_mbtile_test_success_message(), Bundle.GeolocationSettings_mbtile_test_success_title(), JOptionPane.INFORMATION_MESSAGE);
 
  435     private javax.swing.JRadioButton defaultDataSource;
 
  436     private javax.swing.JTextField mbtileFileField;
 
  437     private javax.swing.JButton mbtileTestBtn;
 
  438     private javax.swing.JButton mbtilesBrowseBtn;
 
  439     private javax.swing.JRadioButton mbtilesRBtn;
 
  440     private javax.swing.JTextField osmServerAddressField;
 
  441     private javax.swing.JRadioButton osmServerRBnt;
 
  442     private javax.swing.JButton serverTestBtn;
 
  443     private javax.swing.JButton zipFileBrowseBnt;
 
  444     private javax.swing.JTextField zipFilePathField;
 
  445     private javax.swing.JRadioButton zipFileRBnt;
 
  452     enum GeolocationDataSourceType{
 
  453         ONLINE_DEFAULT_SERVER(0),
 
  454         ONLINE_USER_DEFINED_OSM_SERVER(1),
 
  456         OFFILE_MBTILES_FILE(3);
 
  458         private final int value;
 
  460         GeolocationDataSourceType(
int value) {
 
  468         static GeolocationDataSourceType getOptionForValue(
int value) {
 
  469             for (GeolocationDataSourceType option : GeolocationDataSourceType.values()) {
 
  470                 if (option.getValue() == value) {
 
  475             return ONLINE_DEFAULT_SERVER;