diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/OfflineHelpAction.java b/Core/src/org/sleuthkit/autopsy/corecomponents/OfflineHelpAction.java index 919bdd255f..be018cff3b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/OfflineHelpAction.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/OfflineHelpAction.java @@ -21,9 +21,10 @@ package org.sleuthkit.autopsy.corecomponents; import org.sleuthkit.autopsy.coreutils.Desktop; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.io.File; import java.io.IOException; import java.net.MalformedURLException; -import java.net.URI; +import java.nio.file.Paths; import org.netbeans.core.actions.HTMLViewAction; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; @@ -33,6 +34,7 @@ import org.openide.awt.HtmlBrowser; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import java.util.logging.Level; +import org.openide.modules.InstalledFileLocator; import org.sleuthkit.autopsy.coreutils.Logger; /** @@ -52,6 +54,9 @@ import org.sleuthkit.autopsy.coreutils.Logger; @Messages("CTL_OfflineHelpAction=Offline Autopsy Documentation") public final class OfflineHelpAction implements ActionListener { + private static final String DOCS_FOLDER = "docs"; + private static final String HELP_HTML_FILE = "index.html"; + private static final Logger logger = org.sleuthkit.autopsy.coreutils.Logger.getLogger(AboutWindowPanel.class.getName()); @@ -67,41 +72,40 @@ public final class OfflineHelpAction implements ActionListener { * Tested and working: Chrome, Firefox, IE Not tested: Opera, Safari */ private void viewOfflineHelp() { - String fileForHelp = ""; - String indexForHelp = ""; - String currentDirectory = ""; - URI uri = null; - - try { - // Match the form: file:///C:/some/directory/AutopsyXYZ/docs/index.html - fileForHelp = NbBundle.getMessage(OfflineHelpAction.class, "FILE_FOR_LOCAL_HELP"); - indexForHelp = NbBundle.getMessage(OfflineHelpAction.class, "INDEX_FOR_LOCAL_HELP"); - currentDirectory = System.getProperty("user.dir").replace("\\", "/").replace(" ", "%20"); //NON-NLS - uri = new URI(fileForHelp + currentDirectory + indexForHelp); - } catch (Exception ex) { - logger.log(Level.SEVERE, "Unable to load Offline Documentation: " - + fileForHelp + currentDirectory + indexForHelp, ex); //NON-NLS + + File systemHelpFile = getOfflineHelpFile(); + if (systemHelpFile == null) { + logger.log(Level.SEVERE, "Unable to load Offline Documentation file"); + return; } - if (uri != null) { - // Display URL in the System browser - if (Desktop.isDesktopSupported()) { - Desktop desktop = Desktop.getDesktop(); - try { - desktop.browse(uri); - } catch (IOException ex) { - logger.log(Level.SEVERE, "Unable to launch the system browser: " - + fileForHelp + currentDirectory + indexForHelp, ex); //NON-NLS - } - } else { - org.openide.awt.StatusDisplayer.getDefault().setStatusText( - NbBundle.getMessage(HTMLViewAction.class, "CTL_OpeningBrowser")); //NON-NLS - try { - HtmlBrowser.URLDisplayer.getDefault().showURL(uri.toURL()); - } catch (MalformedURLException ex) { - logger.log(Level.SEVERE, "Unable to launch the built-in browser: " - + fileForHelp + currentDirectory + indexForHelp, ex); //NON-NLS - } + + // Display URL in the System browser + if (Desktop.isDesktopSupported()) { + Desktop desktop = Desktop.getDesktop(); + try { + desktop.open(systemHelpFile); + return; + } catch (IOException ex) { + logger.log(Level.SEVERE, "Unable to launch the system browser: " + + systemHelpFile, ex); //NON-NLS } } + + org.openide.awt.StatusDisplayer.getDefault().setStatusText( + NbBundle.getMessage(HTMLViewAction.class, "CTL_OpeningBrowser")); //NON-NLS + try { + HtmlBrowser.URLDisplayer.getDefault().showURL(systemHelpFile.toURI().toURL()); + } catch (MalformedURLException ex) { + logger.log(Level.SEVERE, "Unable to launch the built-in browser: " + + systemHelpFile, ex); //NON-NLS + } + + } + + private File getOfflineHelpFile() { + return InstalledFileLocator.getDefault().getDefault().locate( + Paths.get(DOCS_FOLDER, HELP_HTML_FILE).toString(), + OfflineHelpAction.class.getPackage().getName(), + false); } } diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/Desktop.java b/Core/src/org/sleuthkit/autopsy/coreutils/Desktop.java index 84a218d6f7..bb7302ba98 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/Desktop.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/Desktop.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.coreutils; import java.io.File; import java.io.IOException; import java.net.URI; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import org.apache.commons.lang3.SystemUtils; @@ -31,6 +32,7 @@ import org.apache.commons.lang3.SystemUtils; public class Desktop { private static final Logger LOGGER = Logger.getLogger(Desktop.class.getName()); + private static final long XDG_TIMEOUT_SECS = 30; private static Boolean xdgSupported = null; @@ -74,6 +76,7 @@ public class Desktop { /** * Private constructor for this wrapper. + * * @param awtDesktop The delegate java.awt.Desktop. */ private Desktop(java.awt.Desktop awtDesktop) { @@ -82,17 +85,28 @@ public class Desktop { /** * Opens a given path using `xdg-open` on linux. + * * @param path The path. - * @throws IOException + * @throws IOException */ private void xdgOpen(String path) throws IOException { - Runtime.getRuntime().exec(new String[]{"xdg-open", path}); + Process process = Runtime.getRuntime().exec(new String[]{"xdg-open", path}); + try { + process.waitFor(XDG_TIMEOUT_SECS, TimeUnit.SECONDS); + } catch (InterruptedException ex) { + throw new IOException("xdg-open timed out", ex); + } + int exitCode = process.exitValue(); + if (exitCode != 0) { + throw new IOException("Received non-zero exit code from xdg-open: " + exitCode); + } } /** * Triggers the OS to navigate to the given uri. + * * @param uri The uri. - * @throws IOException + * @throws IOException */ public void browse(URI uri) throws IOException { if (!awtDesktop.isSupported(java.awt.Desktop.Action.BROWSE) && isXdgSupported()) { @@ -104,8 +118,9 @@ public class Desktop { /** * Triggers the OS to open the given file. + * * @param file The file. - * @throws IOException + * @throws IOException */ public void open(File file) throws IOException { if (!awtDesktop.isSupported(java.awt.Desktop.Action.OPEN) && isXdgSupported()) { @@ -117,8 +132,9 @@ public class Desktop { /** * Triggers the OS to edit the given file. + * * @param file The file. - * @throws IOException + * @throws IOException */ public void edit(File file) throws IOException { if (!awtDesktop.isSupported(java.awt.Desktop.Action.EDIT) && isXdgSupported()) {