From 6774af6910403dba4a2e2c9bdb06d0c8257bff50 Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Thu, 27 Feb 2020 17:30:16 +0000
Subject: [PATCH] Systray: Don't attempt to launch browser when running as a
 service Console: Hide/show things on /configservice when running as a service
 Util: Add isWindowsService() and isService()

---
 apps/routerconsole/jsp/configservice.jsp      | 24 +++++++++++++++----
 .../src/net/i2p/apps/systray/UrlLauncher.java | 16 +++++++++++++
 core/java/src/net/i2p/util/SystemVersion.java | 23 +++++++++++++++++-
 3 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/apps/routerconsole/jsp/configservice.jsp b/apps/routerconsole/jsp/configservice.jsp
index 940635a6b1..1a3bfe4610 100644
--- a/apps/routerconsole/jsp/configservice.jsp
+++ b/apps/routerconsole/jsp/configservice.jsp
@@ -52,7 +52,7 @@
  </div>
 <%
    }  
-   if ( (System.getProperty("os.name") != null) && (System.getProperty("os.name").startsWith("Win")) ) {
+   if (net.i2p.util.SystemVersion.isWindows()) {
 %>
  <h3 class="ptitle" id="runonstartup"><%=intl._t("Run on startup")%></h3>
  <p class="infohelp">
@@ -60,13 +60,24 @@
     <%=intl._t("If you prefer the command line, you can also run the ")%> <code>install_i2p_service_winnt.bat</code> (<%=intl._t("or")%>
  <code>uninstall_i2p_service_winnt.bat</code>).</p>
  <hr><div class="formaction" id="runonstart">
+<%
+     if (net.i2p.util.SystemVersion.isWindowsService()) {
+%>
+ <input type="submit" name="action" class="cancel" value="<%=intl._t("Don't run I2P on startup")%>" >
+<%   } else { %>
  <input type="submit" name="action" class="accept" value="<%=intl._t("Run I2P on startup")%>" >
- <input type="submit" name="action" class="cancel" value="<%=intl._t("Don't run I2P on startup")%>" ></div>
+<%   } %>
+  </div>
+<%
+     if (net.i2p.util.SystemVersion.isWindowsService()) {
+%>
  <p class="infohelp" id="winfoservice"><b>
     <%=intl._t("Note")%>:</b> <%=intl._t("If you are running I2P as service right now, removing it will shut down your router immediately.")%>
     <%=intl._t("You may want to consider shutting down gracefully, as above, then running uninstall_i2p_service_winnt.bat.")%></p>
- <% } %>
-
+<%
+     }
+   }
+%>
  <h3 class="ptitle" id="servicedebug"><%=intl._t("Debugging")%>&nbsp;<a href="/jobs">[<%=intl._t("View the job queue")%>]</a></h3>
  <p class="infohelp">
 <% if (net.i2p.util.SystemVersion.hasWrapper()) { %>
@@ -83,6 +94,7 @@
 <% } %>
  </div>
 
+<% if (!net.i2p.util.SystemVersion.isService()) { %>
  <h3 class="ptitle" id="browseronstart"><%=intl._t("Launch browser on router startup?")%></h3>
  <p class="infohelp">
     <% String consoleURL = formhandler.getConsoleURL(); %>
@@ -91,4 +103,6 @@
  <hr><div class="formaction" id="browserstart">
  <input type="submit" class="check" name="action" value="<%=intl._t("View console on startup")%>" >
  <input type="submit" class="delete" name="action" value="<%=intl._t("Do not view console on startup")%>" >
-</div></form></div></body></html>
+ </div>
+<% } %>
+</form></div></body></html>
diff --git a/apps/systray/java/src/net/i2p/apps/systray/UrlLauncher.java b/apps/systray/java/src/net/i2p/apps/systray/UrlLauncher.java
index 77a31fe9af..49f6dc1e1a 100644
--- a/apps/systray/java/src/net/i2p/apps/systray/UrlLauncher.java
+++ b/apps/systray/java/src/net/i2p/apps/systray/UrlLauncher.java
@@ -57,6 +57,7 @@ public class UrlLauncher implements ClientApp {
     private static final int MAX_TRIES = 99;
     private static final String REGISTERED_NAME = "UrlLauncher";
     private static final String PROP_BROWSER = "routerconsole.browser";
+    private static final boolean IS_SERVICE = SystemVersion.isService();
 
     /**
      *  Browsers to try IN-ORDER
@@ -177,6 +178,8 @@ public class UrlLauncher implements ClientApp {
      * unsuccessful, an attempt is made to launch the URL using the most common
      * browsers.
      * 
+     * As of 0.9.46, fails immediately if JVM is a Windows or Linux Service.
+     * 
      * BLOCKING. This repeatedly probes the server port at the given url
      * until it is apparently ready.
      * 
@@ -187,6 +190,8 @@ public class UrlLauncher implements ClientApp {
      * @throws IOException
      */ 
     public boolean openUrl(String url) throws IOException {
+        if (IS_SERVICE)
+            return false;
         if (_log.shouldDebug()) _log.debug("Waiting for server");
         waitForServer(url);
         if (_log.shouldDebug()) _log.debug("Done waiting for server");
@@ -278,6 +283,8 @@ public class UrlLauncher implements ClientApp {
      * they contain spaces or tabs.
      * There is no mechanism to escape quotes or other chars with backslashes.
      * 
+     * As of 0.9.46, fails immediately if JVM is a Windows or Linux Service.
+     * 
      * BLOCKING. However, this does NOT probe the server port to see if it is ready.
      * 
      * @param  url     The URL to open.
@@ -288,6 +295,8 @@ public class UrlLauncher implements ClientApp {
      * @throws IOException
      */
     public boolean openUrl(String url, String browser) throws IOException {
+        if (IS_SERVICE)
+            return false;
         waitForServer(url);
         if (validateUrlFormat(url)) {
             String[] args = parseArgs(browser, url);
@@ -383,9 +392,16 @@ public class UrlLauncher implements ClientApp {
 
     /**
      *  ClientApp interface
+     *  As of 0.9.46, stops immediately if JVM is a Windows or Linux Service.
+     * 
      *  @since 0.9.18
      */
     public void startup() {
+        if (IS_SERVICE) {
+            // not START_FAILED so manager doesn't log CRIT
+            changeState(STOPPED);
+            return;
+        }
         String url = _args[0];
         if (!validateUrlFormat(url)) {
             changeState(START_FAILED, new MalformedURLException("Bad url: " + url));
diff --git a/core/java/src/net/i2p/util/SystemVersion.java b/core/java/src/net/i2p/util/SystemVersion.java
index 79504e5e88..e77cd962da 100644
--- a/core/java/src/net/i2p/util/SystemVersion.java
+++ b/core/java/src/net/i2p/util/SystemVersion.java
@@ -43,6 +43,9 @@ public abstract class SystemVersion {
     private static final boolean _is64;
     private static final boolean _hasWrapper = System.getProperty("wrapper.version") != null;
     private static final boolean _isLinuxService;
+    // found in Tanuki WrapperManager source so we don't need the WrapperManager class here
+    private static final boolean _isWindowsService = _isWin && _hasWrapper && Boolean.valueOf(System.getProperty("wrapper.service"));
+    private static final boolean _isService;
     private static final boolean _isSlow;
 
     private static final boolean _oneDotSix;
@@ -76,6 +79,7 @@ public abstract class SystemVersion {
         _isLinuxService = !_isWin && !_isMac && !_isAndroid &&
                           (DAEMON_USER.equals(System.getProperty("user.name")) ||
                            (_isGentoo && GENTOO_USER.equals(System.getProperty("user.name"))));
+        _isService = _isLinuxService || _isWindowsService;
         _isSlow = _isAndroid || _isApache || _isArm || _isGNU || _isZero || getMaxMemory() < 48*1024*1024L;
 
         int sdk = 0;
@@ -298,6 +302,20 @@ public abstract class SystemVersion {
         return _isLinuxService;
     }
 
+    /*
+     *  @since 0.9.46
+     */
+    public static boolean isWindowsService() {
+        return _isWindowsService;
+    }
+
+    /*
+     *  @since 0.9.46
+     */
+    public static boolean isService() {
+        return _isService;
+    }
+
     /**
      *  Identical to android.os.Build.VERSION.SDK_INT.
      *  For use outside of Android code.
@@ -376,7 +394,9 @@ public abstract class SystemVersion {
         System.out.println("Java 9   : " + isJava9());
         System.out.println("Java 10  : " + isJava10());
         System.out.println("Java 11  : " + isJava11());
-        System.out.println("Java 12  : " + isJava(12));
+        for (int i = 12; i <= 15; i++) {
+            System.out.println("Java " + i + "  : " + isJava(i));
+        }
         System.out.println("Android  : " + isAndroid());
         if (isAndroid())
             System.out.println("  Version: " + getAndroidVersion());
@@ -391,6 +411,7 @@ public abstract class SystemVersion {
         System.out.println("OpenJDK  : " + isOpenJDK());
         System.out.println("Slow     : " + isSlow());
         System.out.println("Windows  : " + isWindows());
+        System.out.println("Win. Svc : " + isWindowsService());
         System.out.println("Wrapper  : " + hasWrapper());
         System.out.println("x86      : " + isX86());
         System.out.println("Zero JVM : " + isZeroVM());
-- 
GitLab