Changeset 9738db7 for apps/systray


Ignore:
Timestamp:
Dec 12, 2018 8:12:07 PM (18 months ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
6c3c227c
Parents:
51bf23a
Message:

UrlLauncher?:

  • Use arrays for exec
  • Randomize temp file name
  • Require quotes around args containing spaces in routerconsole.browser property
  • Add debug logging
  • Add chromium-browser to the default list
  • Parse and use full command line from Windows registry
  • Replace %1 with url in registry line and routerconsole.browser property

ShellCommand?:

  • Switch to i2p logging
File:
1 edited

Legend:

Unmodified
Added
Removed
  • apps/systray/java/src/net/i2p/apps/systray/UrlLauncher.java

    r51bf23a r9738db7  
    2121import java.net.URI;
    2222import java.net.URISyntaxException;
     23import java.util.Arrays;
     24import java.util.ArrayList;
     25import java.util.List;
    2326import java.util.Locale;
    2427
     
    2730import static net.i2p.app.ClientAppState.*;
    2831import net.i2p.util.I2PAppThread;
     32import net.i2p.util.Log;
    2933import net.i2p.util.ShellCommand;
    3034import net.i2p.util.SystemVersion;
     
    4751    private final ClientAppManager _mgr;
    4852    private final String[] _args;
     53    private final Log _log;
    4954
    5055    private static final int WAIT_TIME = 5*1000;
     
    7075            "opera -newpage",
    7176            "firefox",
     77            "chromium-browser",
    7278            "mozilla",
    7379            "netscape",
     
    8389     *  ClientApp constructor used from clients.config
    8490     *
     91     *  @param mgr null OK
     92     *  @param args URL in args[0] or null args for router console
    8593     *  @since 0.9.18
    8694     */
     
    8896        _state = UNINITIALIZED;
    8997        _context = context;
     98        _log = _context.logManager().getLog(UrlLauncher.class);
    9099        _mgr = mgr;
    91100        if (args == null || args.length <= 0)
     
    104113        _state = UNINITIALIZED;
    105114        _context = I2PAppContext.getGlobalContext();
     115        _log = _context.logManager().getLog(UrlLauncher.class);
    106116        _mgr = null;
    107117        _args = null;
     
    168178     * browsers.
    169179     *
    170      * BLOCKING
     180     * BLOCKING. This repeatedly probes the server port at the given url
     181     * until it is apparently ready.
    171182     *
    172183     * @param  url The URL to open.
     
    177188     */
    178189    public boolean openUrl(String url) throws IOException {
     190        if (_log.shouldDebug()) _log.debug("Waiting for server");
    179191        waitForServer(url);
     192        if (_log.shouldDebug()) _log.debug("Done waiting for server");
    180193        if (validateUrlFormat(url)) {
    181194            String cbrowser = _context.getProperty(PROP_BROWSER);
     
    186199                String osName = System.getProperty("os.name");
    187200                if (osName.toLowerCase(Locale.US).startsWith("mac os x")) {
    188 
    189                     if (_shellCommand.executeSilentAndWaitTimed("open " + url, 5))
     201                    String[] args = new String[] { "open", url };
     202                    if (_log.shouldDebug()) _log.debug("Execute: " + Arrays.toString(args));
     203                    if (_shellCommand.executeSilentAndWaitTimed(args , 5))
    190204                        return true;
    191 
    192205                } else {
    193206                    return false;
    194207                }
    195 
    196                 if (_shellCommand.executeSilentAndWaitTimed("iexplore " + url, 5))
     208                String[] args = new String[] { "iexplore", url };
     209                if (_log.shouldDebug()) _log.debug("Execute: " + Arrays.toString(args));
     210                if (_shellCommand.executeSilentAndWaitTimed(args , 5))
    197211                    return true;
    198212            } else if (SystemVersion.isWindows()) {
    199                 String         browserString  = "\"C:\\Program Files\\Internet Explorer\\iexplore.exe\" -nohome";
    200                 BufferedReader bufferedReader = null;
    201 
    202                 File foo = new File(_context.getTempDir(), "browser.reg");
    203                 _shellCommand.executeSilentAndWait("regedit /E \"" + foo.getAbsolutePath() + "\" \"HKEY_CLASSES_ROOT\\http\\shell\\open\\command\"");
    204 
    205                 try {
    206                     bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(foo), "UTF-16"));
    207                     for (String line; (line = bufferedReader.readLine()) != null; ) {
    208                         if (line.startsWith("@=")) {
    209                             // we should really use the whole line and replace %1 with the url
    210                             browserString = line.substring(3, line.toLowerCase(Locale.US).indexOf(".exe") + 4);
    211                             if (browserString.startsWith("\\\""))
    212                                 browserString = browserString.substring(2);
    213                             browserString = "\"" + browserString + "\"";
     213                String[] browserString  = new String[] { "C:\\Program Files\\Internet Explorer\\iexplore.exe", "-nohome", url };
     214                File foo = new File(_context.getTempDir(), "browser" + _context.random().nextLong() + ".reg");
     215                String[] args = new String[] { "regedit", "/E", foo.getAbsolutePath(), "HKEY_CLASSES_ROOT\\http\\shell\\open\\command" };
     216                if (_log.shouldDebug()) _log.debug("Execute: " + Arrays.toString(args));
     217                boolean ok = _shellCommand.executeSilentAndWait(args);
     218                if (ok) {
     219                    BufferedReader bufferedReader = null;
     220                    try {
     221                        bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(foo), "UTF-16"));
     222                        for (String line; (line = bufferedReader.readLine()) != null; ) {
     223                            // @="\"C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe\" -osint -url \"%1\""
     224                            if (line.startsWith("@=")) {
     225                                if (_log.shouldDebug()) _log.debug("From RegEdit: " + line);
     226                                line = line.substring(2).trim();
     227                                if (line.startsWith("\"") && line.endsWith("\""))
     228                                    line = line.substring(1, line.length() - 1);
     229                                line = line.replace("\\\\", "\\");
     230                                line = line.replace("\\\"", "\"");
     231                                if (_log.shouldDebug()) _log.debug("Mod RegEdit: " + line);
     232                                // "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -osint -url "%1"
     233                                // use the whole line
     234                                String[] aarg = parseArgs(line, url);
     235                                if (aarg.length > 0) {
     236                                    browserString = aarg;
     237                                    break;
     238                                }
     239                            }
    214240                        }
     241                    } catch (IOException e) {
     242                        if (_log.shouldWarn())
     243                            _log.warn("Reading regedit output", e);
     244                    } finally {
     245                        if (bufferedReader != null)
     246                            try { bufferedReader.close(); } catch (IOException ioe) {}
     247                        foo.delete();
    215248                    }
    216                     try {
    217                         bufferedReader.close();
    218                     } catch (IOException e) {
    219                         // No worries.
    220                     }
    221                     foo.delete();
    222                 } catch (IOException e) {
    223                     // Defaults to IE.
    224                 } finally {
    225                     if (bufferedReader != null)
    226                         try { bufferedReader.close(); } catch (IOException ioe) {}
     249                } else if (_log.shouldWarn()) {
     250                    _log.warn("Regedit Failed: " + Arrays.toString(args));
    227251                }
    228                 if (_shellCommand.executeSilentAndWaitTimed(browserString + ' ' + url, 5))
     252                if (_log.shouldDebug()) _log.debug("Execute: " + Arrays.toString(browserString));
     253                if (_shellCommand.executeSilentAndWaitTimed(browserString, 5))
    229254                    return true;
     255                if (_log.shouldInfo()) _log.info("Failed: " + Arrays.toString(browserString));
    230256            } else {
    231257                // fall through
    232258            }
     259            String[] args = new String[2];
     260            args[1] = url;
    233261            for (int i = 0; i < BROWSERS.length; i++) {
    234                 if (_shellCommand.executeSilentAndWaitTimed(BROWSERS[i] + ' ' + url, 5))
     262                args[0] = BROWSERS[i];
     263                if (_log.shouldDebug()) _log.debug("Execute: " + Arrays.toString(args));
     264                if (_shellCommand.executeSilentAndWaitTimed(args, 5))
    235265                    return true;
     266                if (_log.shouldInfo()) _log.info("Failed: " + Arrays.toString(args));
    236267            }
    237268        }
     
    241272    /**
    242273     * Opens the given URL with the given browser.
    243      *
    244      * BLOCKING
     274     * As of 0.9.38, the browser parameter will be parsed into arguments
     275     * separated by spaces or tabs.
     276     * %1, if present, will be replaced with the url.
     277     * Arguments may be surrounded by single or double quotes if
     278     * they contain spaces or tabs.
     279     * There is no mechanism to escape quotes or other chars with backslashes.
     280     *
     281     * BLOCKING. However, this does NOT probe the server port to see if it is ready.
    245282     *
    246283     * @param  url     The URL to open.
    247      * @param  browser The browser to use.
     284     * @param  browser The browser to use. See above for quoting rules.
    248285     * @return         <code>true</code> if the operation was successful,
    249286     *                 otherwise <code>false</code>.
     
    254291        waitForServer(url);
    255292        if (validateUrlFormat(url)) {
    256             if (_shellCommand.executeSilentAndWaitTimed(browser + " " + url, 5))
    257                 return true;
     293            String[] args = parseArgs(browser, url);
     294            if (args.length > 0) {
     295                if (_log.shouldDebug()) _log.debug("Execute: " + Arrays.toString(args));
     296                if (_shellCommand.executeSilentAndWaitTimed(args, 5))
     297                    return true;
     298            }
    258299        }
    259300        return false;
     301    }
     302
     303    /**
     304     *  Parse args into arguments
     305     *  separated by spaces or tabs.
     306     *  %1, if present, will be replaced with the url,
     307     *  otherwise it will be added as the last argument.
     308     *  Arguments may be surrounded by single or double quotes if
     309     *  they contain spaces or tabs.
     310     *  There is no mechanism to escape quotes or other chars with backslashes.
     311     *  Adapted from i2ptunnel SSLHelper.
     312     *
     313     *  @return param args non-null
     314     *  @return non-null
     315     *  @since 0.9.38
     316     */
     317    private static String[] parseArgs(String args, String url) {
     318        List<String> argList = new ArrayList<String>(4);
     319        StringBuilder buf = new StringBuilder(32);
     320        boolean isQuoted = false;
     321        for (int j = 0; j < args.length(); j++) {
     322            char c = args.charAt(j);
     323            switch (c) {
     324                case '\'':
     325                case '"':
     326                    if (isQuoted) {
     327                        String str = buf.toString().trim();
     328                        if (str.length() > 0)
     329                            argList.add(str);
     330                        buf.setLength(0);
     331                    }
     332                    isQuoted = !isQuoted;
     333                    break;
     334                case ' ':
     335                case '\t':
     336                    // whitespace - if we're in a quoted section, keep this as part of the quote,
     337                    // otherwise use it as a delim
     338                    if (isQuoted) {
     339                        buf.append(c);
     340                    } else {
     341                        String str = buf.toString().trim();
     342                        if (str.length() > 0)
     343                            argList.add(str);
     344                        buf.setLength(0);
     345                    }
     346                    break;
     347                default:
     348                    buf.append(c);
     349                    break;
     350            }
     351        }
     352        if (buf.length() > 0) {
     353            String str = buf.toString().trim();
     354            if (str.length() > 0)
     355                argList.add(str);
     356        }
     357        if (argList.isEmpty())
     358            return new String[] {};
     359        boolean foundpct = false;
     360        // replace %1 with the url
     361        for (int i = 0; i < argList.size(); i++) {
     362            String arg = argList.get(i);
     363            if (arg.contains("%1")) {
     364                argList.set(i, arg.replace("%1", url));
     365                foundpct = true;
     366            }
     367        }
     368        // add url if no %1
     369        if (!foundpct)
     370            argList.add(url);
     371        return argList.toArray(new String[argList.size()]);
    260372    }
    261373
Note: See TracChangeset for help on using the changeset viewer.