File Source: URLHandler.java

     1  /*
     2   * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
     3   *
     4   * Permission is hereby granted, free of charge, to any person obtaining a copy
     5   * of this software and associated documentation files (the "Software"), to deal
     6   * in the Software without restriction, including without limitation the rights
     7   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8   * copies of the Software, and to permit persons to whom the Software is
     9   * furnished to do so, subject to the following conditions:
    10   *
    11   * The above copyright notice and this permission notice shall be included in
    12   * all copies or substantial portions of the Software.
    13   *
    14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20   * SOFTWARE.
    21   */
    22  
    23  package com.dmdirc.util;
    24  
    25  import com.dmdirc.Main;
    26  import com.dmdirc.config.ConfigManager;
    27  import com.dmdirc.config.IdentityManager;
    28  import com.dmdirc.logger.ErrorLevel;
    29  import com.dmdirc.logger.Logger;
    30  
    31  import java.awt.Desktop;
    32  import java.io.IOException;
    33  import java.net.URI;
    34  import java.net.URISyntaxException;
    35  import java.net.URL;
    36  import java.util.ArrayList;
    37  import java.util.Date;
    38  import java.util.List;
    39  
    40  /** Handles URLs. */
    41  public class URLHandler {
    42  
    43      /** Config manager. */
    44      private final ConfigManager config;
    45      /** Singleton instance. */
             /* 
    P/P       *  Method: com.dmdirc.util.URLHandler__static_init
              * 
              *  Postconditions:
              *    me == &new URLHandler(URLHandler__static_init#1)
              *    new URLHandler(URLHandler__static_init#1) num objects == 1
              *    init'ed(me.config)
              *    init'ed(me.desktop)
              */
    46      private static final URLHandler me = new URLHandler();
    47      /** Desktop handler. */
    48      private final Desktop desktop;
    49      /** The time a browser was last launched. */
    50      private static Date lastLaunch;
    51  
    52      /** Instantiates a new URL Handler. */
             /* 
    P/P       *  Method: void com.dmdirc.util.URLHandler()
              * 
              *  Postconditions:
              *    init'ed(this.config)
              *    init'ed(this.desktop)
              * 
              *  Test Vectors:
              *    java.awt.Desktop:isDesktopSupported(...)@55: {0}, {1}
              */
    53      private URLHandler() {
    54          config = IdentityManager.getGlobalConfig();
    55          if (Desktop.isDesktopSupported()) {
    56              desktop = Desktop.getDesktop();
    57          } else {
    58              desktop = null;
    59          }
    60      }
    61  
    62      /**
    63       * Gets an instance of URLHandler.
    64       *
    65       * @return URLHandler instance
    66       */
    67      public static URLHandler getURLHander() {
                 /* 
    P/P           *  Method: URLHandler getURLHander()
                  * 
                  *  Postconditions:
                  *    return_value == &new URLHandler(URLHandler__static_init#1)
                  */
    68          synchronized (me) {
    69              return me;
    70          }
    71      }
    72  
    73      /**
    74       * Launches an application for a given url.
    75       *
    76       * @param urlString URL to parse
    77       */
    78      public void launchApp(final String urlString) {
    79          URI uri;
    80          try {
                     /* 
    P/P               *  Method: void launchApp(String)
                      * 
                      *  Preconditions:
                      *    (soft) init'ed(lastLaunch)
                      *    (soft) this.config != null
                      * 
                      *  Presumptions:
                      *    init'ed(com.dmdirc.logger.ErrorLevel.LOW)
                      * 
                      *  Postconditions:
                      *    lastLaunch == One-of{old lastLaunch, &new Date(launchApp#1*)}
                      *    init'ed(lastLaunch)
                      *    new Date(launchApp#1*) num objects <= 1
                      * 
                      *  Test Vectors:
                      *    java.net.URI:getScheme(...)@82: Inverse{null}, Addr_Set{null}
                      */
    81              uri = new URI(urlString);
    82              if (uri.getScheme() == null) {
    83                  uri = new URI("http://" + urlString);
    84              }
    85          } catch (URISyntaxException ex) {
    86              Logger.userError(ErrorLevel.LOW, "Invalid URL: " + ex.getMessage());
    87              return;
    88          }
    89  
    90          launchApp(uri);
    91      }
    92  
    93      /**
    94       * Launches an application for a given url.
    95       *
    96       * @param url URL to parse
    97       */
    98      public void launchApp(final URL url) {
    99          URI uri;
   100          try {
                     /* 
    P/P               *  Method: void launchApp(URL)
                      * 
                      *  Preconditions:
                      *    (soft) init'ed(lastLaunch)
                      *    (soft) this.config != null
                      *    (soft) url != null
                      * 
                      *  Presumptions:
                      *    init'ed(com.dmdirc.logger.ErrorLevel.LOW)
                      *    java.net.URL:toURI(...)@101 != null
                      * 
                      *  Postconditions:
                      *    lastLaunch == One-of{old lastLaunch, &amp;new Date(launchApp#1*)}
                      *    init'ed(lastLaunch)
                      *    new Date(launchApp#1*) num objects <= 1
                      * 
                      *  Test Vectors:
                      *    java.net.URI:getScheme(...)@102: Inverse{null}, Addr_Set{null}
                      */
   101              uri = url.toURI();
   102              if (uri.getScheme() == null) {
   103                  uri = new URI("http://" + url.toString());
   104              }
   105          } catch (URISyntaxException ex) {
   106              Logger.userError(ErrorLevel.LOW, "Invalid URL: " + ex.getMessage());
   107              return;
   108          }
   109  
   110          launchApp(uri);
   111      }
   112  
   113      /**
   114       * Launches an application for a given url.
   115       *
   116       * @param uri URL to parse
   117       */
   118      public void launchApp(final URI uri) {
                 /* 
    P/P           *  Method: void launchApp(URI)
                  * 
                  *  Preconditions:
                  *    init'ed(lastLaunch)
                  *    (soft) this.config != null
                  *    (soft) uri != null
                  * 
                  *  Presumptions:
                  *    com.dmdirc.Main:getUI(...)@133 != null
                  *    com.dmdirc.Main:getUI(...)@141 != null
                  *    com.dmdirc.Main:getUI(...)@149 != null
                  *    com.dmdirc.Main:getUI(...)@154 != null
                  *    com.dmdirc.config.ConfigManager:getOption(...)@137 != null
                  *    ...
                  * 
                  *  Postconditions:
                  *    lastLaunch == &amp;new Date(launchApp#1)
                  *    new Date(launchApp#1) num objects == 1
                  * 
                  *  Test Vectors:
                  *    lastLaunch: Addr_Set{null}, Inverse{null}
                  *    com.dmdirc.config.ConfigManager:getOptionBool(...)@122: {0}, {1}
                  *    com.dmdirc.config.ConfigManager:hasOptionString(...)@132: {1}, {0}
                  *    java.lang.String:equals(...)@139: {0}, {1}
                  *    java.lang.String:equals(...)@148: {0}, {1}
                  *    java.lang.String:equals(...)@151: {0}, {1}
                  */
   119          final Date oldLaunch = lastLaunch;
   120          lastLaunch = new Date();
   121  
   122          if (IdentityManager.getGlobalConfig().getOptionBool("browser",
   123                  "uselaunchdelay") && oldLaunch != null) {
   124              final Long diff = lastLaunch.getTime() - oldLaunch.getTime();
   125  
   126              if (diff < IdentityManager.getGlobalConfig().getOptionInt("browser",
   127                      "launchdelay")) {
   128                  return;
   129              }
   130          }
   131  
   132          if (!config.hasOptionString("protocol", uri.getScheme())) {
   133              Main.getUI().showURLDialog(uri);
   134              return;
   135          }
   136  
   137          final String command = config.getOption("protocol", uri.getScheme());
   138  
   139          if ("DMDIRC".equals(command)) {
   140              try {
   141                  Main.getUI().getStatusBar().setMessage("Connecting to: " +
   142                          uri.toString());
   143                  new IrcAddress(uri.toString()).connect();
   144              } catch (InvalidAddressException ex) {
   145                  Logger.userError(ErrorLevel.LOW, "Invalid IRC Address: " +
   146                          ex.getMessage());
   147              }
   148          } else if ("BROWSER".equals(command)) {
   149              Main.getUI().getStatusBar().setMessage("Opening: " + uri.toString());
   150              execBrowser(uri);
   151          } else if ("MAIL".equals(command)) {
   152              execMail(uri);
   153          } else {
   154              Main.getUI().getStatusBar().setMessage("Opening: " + uri.toString());
   155              execApp(substituteParams(uri, command));
   156          }
   157      }
   158  
   159      /**
   160       * Substitutes variables into a command
   161       * 
   162       * @param url data url
   163       * @param command command to be substituted
   164       * 
   165       * @return Substituted command
   166       */
   167      public String substituteParams(final URI url, final String command) {
                 /* 
    P/P           *  Method: String substituteParams(URI, String)
                  * 
                  *  Preconditions:
                  *    command != null
                  *    url != null
                  * 
                  *  Presumptions:
                  *    java.lang.String:indexOf(...)@207 <= 232-2
                  * 
                  *  Postconditions:
                  *    return_value != null
                  * 
                  *  Test Vectors:
                  *    java.lang.String:indexOf(...)@204: {-231..-2, 0..232-1}, {-1}
                  *    java.lang.String:isEmpty(...)@203: {1}, {0}
                  *    java.net.URI:getFragment(...)@179: Addr_Set{null}, Inverse{null}
                  *    java.net.URI:getHost(...)@183: Addr_Set{null}, Inverse{null}
                  *    java.net.URI:getPath(...)@187: Addr_Set{null}, Inverse{null}
                  *    java.net.URI:getPort(...)@199: {-231..0}, {1..232-1}
                  *    java.net.URI:getQuery(...)@195: Addr_Set{null}, Inverse{null}
                  *    java.net.URI:getScheme(...)@191: Addr_Set{null}, Inverse{null}
                  *    java.net.URI:getUserInfo(...)@168: Addr_Set{null}, Inverse{null}
                  */
   168          final String userInfo = url.getUserInfo();
   169          String fragment = "";
   170          String host = "";
   171          String path = "";
   172          String protocol = "";
   173          String query = "";
   174          String username = "";
   175          String password = "";
   176          String port = "";
   177          String newCommand = command;
   178  
   179          if (url.getFragment() != null) {
   180              fragment = url.getFragment();
   181          }
   182  
   183          if (url.getHost() != null) {
   184              host = url.getHost();
   185          }
   186  
   187          if (url.getPath() != null) {
   188              path = url.getPath();
   189          }
   190  
   191          if (url.getScheme() != null) {
   192              protocol = url.getScheme();
   193          }
   194  
   195          if (url.getQuery() != null) {
   196              query = url.getQuery();
   197          }
   198          
   199          if (url.getPort() > 0) {
   200              port = String.valueOf(url.getPort());
   201          }
   202  
   203          if (userInfo != null && !userInfo.isEmpty()) {
   204              if (userInfo.indexOf(':') == -1) {
   205                  username = userInfo;
   206              } else {
   207                  final int pos = userInfo.indexOf(':');
   208                  username = userInfo.substring(0, pos);
   209                  password = userInfo.substring(pos + 1);
   210              }
   211          }
   212  
   213          newCommand = newCommand.replaceAll("\\$url", url.toString());
   214          newCommand = newCommand.replaceAll("\\$fragment", fragment);
   215          newCommand = newCommand.replaceAll("\\$host", host);
   216          newCommand = newCommand.replaceAll("\\$path", path);
   217          newCommand = newCommand.replaceAll("\\$port", port);
   218          newCommand = newCommand.replaceAll("\\$query", query);
   219          newCommand = newCommand.replaceAll("\\$protocol", protocol);
   220          newCommand = newCommand.replaceAll("\\$username", username);
   221          newCommand = newCommand.replaceAll("\\$password", password);
   222  
   223          return newCommand;
   224      }
   225  
   226      /**
   227       * Launches an application.
   228       *
   229       * @param command Application and arguments
   230       */
   231      private void execApp(final String command) {
   232          try {
                     /* 
    P/P               *  Method: void execApp(String)
                      * 
                      *  Preconditions:
                      *    (soft) command != null
                      * 
                      *  Presumptions:
                      *    init'ed(com.dmdirc.logger.ErrorLevel.LOW)
                      *    java.lang.Runtime:getRuntime(...)@233 != null
                      */
   233              Runtime.getRuntime().exec(parseArguments(command));
   234          } catch (IOException ex) {
   235              Logger.userError(ErrorLevel.LOW, "Unable to run application: ",
   236                      ex.getMessage());
   237          }
   238      }
   239      
   240      /**
   241       * Parses the specified command into an array of arguments. Arguments are
   242       * separated by spaces. Multi-word arguments may be specified by starting
   243       * the argument with a quote (") and finishing it with a quote (").
   244       * 
   245       * @param command The command to parse
   246       * @return An array of arguments corresponding to the command
   247       */
   248      protected static String[] parseArguments(final String command) {
                 /* 
    P/P           *  Method: String[] parseArguments(String)
                  * 
                  *  Preconditions:
                  *    command != null
                  * 
                  *  Presumptions:
                  *    java.util.List:size(...)@278 >= 0
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   249          final List<String> args = new ArrayList<String>();
   250          final StringBuilder builder = new StringBuilder();
   251          boolean inquote = false;
   252          
   253          for (String word : command.split(" ")) {
   254              if (word.endsWith("\"") && inquote) {
   255                  args.add(builder.toString() + ' ' + word.substring(0, word.length() - 1));
   256                  builder.delete(0, builder.length());
   257                  inquote = false;
   258              } else if (inquote) {
   259                  if (builder.length() > 0) {
   260                      builder.append(' ');
   261                  }
   262                  
   263                  builder.append(word);
   264              } else if (word.startsWith("\"") && !word.endsWith("\"")) {
   265                  inquote = true;
   266                  builder.append(word.substring(1));
   267              } else if (word.startsWith("\"") && word.endsWith("\"")) {
   268                  if (word.length() == 1) {
   269                      inquote = true;
   270                  } else {
   271                      args.add(word.substring(1, word.length() - 1));
   272                  }
   273              } else {
   274                  args.add(word);
   275              }
   276          }
   277          
   278          return args.toArray(new String[args.size()]);
   279      }
   280  
   281      /**
   282       * Opens the specified URL in the users browser.
   283       *
   284       * @param url URL to open
   285       */
   286      private void execBrowser(final URI url) {
                 /* 
    P/P           *  Method: void execBrowser(URI)
                  * 
                  *  Presumptions:
                  *    init'ed(com.dmdirc.logger.ErrorLevel.LOW)
                  *    init'ed(java.awt.Desktop$Action.BROWSE)
                  * 
                  *  Test Vectors:
                  *    this.desktop: Addr_Set{null}, Inverse{null}
                  *    java.awt.Desktop:isSupported(...)@287: {0}, {1}
                  */
   287          if (desktop != null &&
   288                  desktop.isSupported(Desktop.Action.BROWSE)) {
   289              try {
   290                  desktop.browse(url);
   291              } catch (IOException ex) {
   292                  Logger.userError(ErrorLevel.LOW,
   293                          "Unable to open URL: " + ex.getMessage());
   294              }
   295          } else {
   296              Logger.userError(ErrorLevel.LOW,
   297                      "Unable to open your browser: Your desktop enviroment is " +
   298                      "not supported, please go to the URL Handlers section of " +
   299                      "the preferences dialog and set the path to your browser " +
   300                      "manually");
   301          }
   302      }
   303  
   304      /**
   305       * Opens the specified URL in the users mail client.
   306       *
   307       * @param url URL to open
   308       */
   309      private void execMail(final URI url) {
                 /* 
    P/P           *  Method: void execMail(URI)
                  * 
                  *  Presumptions:
                  *    init'ed(com.dmdirc.logger.ErrorLevel.LOW)
                  *    init'ed(java.awt.Desktop$Action.MAIL)
                  * 
                  *  Test Vectors:
                  *    this.desktop: Addr_Set{null}, Inverse{null}
                  *    java.awt.Desktop:isSupported(...)@310: {0}, {1}
                  */
   310          if (desktop != null && desktop.isSupported(Desktop.Action.MAIL)) {
   311              try {
   312                  desktop.mail(url);
   313              } catch (IOException ex) {
   314                  Logger.userError(ErrorLevel.LOW,
   315                          "Unable to open URL: " + ex.getMessage());
   316              }
   317          } else {
   318              Logger.userError(ErrorLevel.LOW,
   319                      "Unable to open your mail client: Your desktop enviroment is " +
   320                      "not supported, please go to the URL Handlers section of " +
   321                      "the preferences dialog and set the path to your browser " +
   322                      "manually");
   323          }
   324      }
   325  }








SofCheck Inspector Build Version : 2.17854
URLHandler.java 2009-Jun-25 01:54:24
URLHandler.class 2009-Sep-02 17:04:17