content: /*
   * Copyright 2014 A.C.R. Development
   */
  package acr.browser.lightning.download;
  
  
  import java.util.Locale;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  
  import androidx.annotation.NonNull;
  import androidx.annotation.Nullable;
  
  import static android.util.Patterns.GOOD_IRI_CHAR;
  
  /**
   * Web Address Parser
   * <p/>
   * This is called WebAddress, rather than URL or URI, because it attempts to
   * parse the stuff that a user will actually type into a browser address widget.
   * <p/>
   * Unlike java.net.uri, this parser will not choke on URIs missing schemes. It
   * will only throw a ParseException if the input is really hosed.
   * <p/>
   * If given an https scheme but no port, fills in port
   */
  class WebAddress {
  
      private String mScheme;
      private String mHost;
      private int mPort;
      private String mPath;
      private String mAuthInfo;
      private static final int MATCH_GROUP_SCHEME = 1;
      private static final int MATCH_GROUP_AUTHORITY = 2;
      private static final int MATCH_GROUP_HOST = 3;
      private static final int MATCH_GROUP_PORT = 4;
      private static final int MATCH_GROUP_PATH = 5;
      private static final Pattern sAddressPattern = Pattern.compile(
      /* scheme */"(?:(http|https|file)://)?" +
      /* authority */"(?:([-A-Za-z0-9$_.+!*'(),;?&=]+(?::[-A-Za-z0-9$_.+!*'(),;?&=]+)?)@)?" +
      /* host */"([" + GOOD_IRI_CHAR + "%_-][" + GOOD_IRI_CHAR + "%_\\.-]*|\\[[0-9a-fA-F:\\.]+\\])?" +
      /* port */"(?::([0-9]*))?" +
      /* path */"(/?[^#]*)?" +
      /* anchor */".*", Pattern.CASE_INSENSITIVE);
  
      /**
       * Parses given URI-like string.
       */
      public WebAddress(@Nullable String address) throws IllegalArgumentException {
  
          if (address == null) {
              throw new IllegalArgumentException("address can't be null");
          }
  
          mScheme = "";
          mHost = "";
          mPort = -1;
          mPath = "/";
          mAuthInfo = "";
  
          Matcher m = sAddressPattern.matcher(address);
          String t;
          if (!m.matches()) {
              throw new IllegalArgumentException("Parsing of address '" + address + "' failed");
          }
  
          t = m.group(MATCH_GROUP_SCHEME);
          if (t != null) {
              mScheme = t.toLowerCase(Locale.ROOT);
          }
          t = m.group(MATCH_GROUP_AUTHORITY);
          if (t != null) {
              mAuthInfo = t;
          }
          t = m.group(MATCH_GROUP_HOST);
          if (t != null) {
              mHost = t;
          }
          t = m.group(MATCH_GROUP_PORT);
          if (t != null && !t.isEmpty()) {
              // The ':' character is not returned by the regex.
              try {
                  mPort = Integer.parseInt(t);
              } catch (NumberFormatException ex) {
                  throw new RuntimeException("Parsing of port number failed", ex);
              }
          }
          t = m.group(MATCH_GROUP_PATH);
          if (t != null && !t.isEmpty()) {
              /*
               * handle busted myspace frontpage redirect with missing initial "/"
               */
              if (t.charAt(0) == '/') {
                  mPath = t;
              } else {
                  mPath = '/' + t;
              }
          }
  
          /*
           * Get port from scheme or scheme from port, if necessary and possible
           */
          if (mPort == 443 && mScheme != null && mScheme.isEmpty()) {
              mScheme = "https";
          } else if (mPort == -1) {
              if ("https".equals(mScheme)) {
                  mPort = 443;
              } else {
                  mPort = 80; // default
              }
          }
          if (mScheme != null && mScheme.isEmpty()) {
              mScheme = "http";
          }
      }
  
      @NonNull
      @Override
      public String toString() {
  
          String port = "";
          if ((mPort != 443 && "https".equals(mScheme)) || (mPort != 80 && "http".equals(mScheme))) {
              port = ':' + Integer.toString(mPort);
          }
          String authInfo = "";
          if (!mAuthInfo.isEmpty()) {
              authInfo = mAuthInfo + '@';
          }
  
          return mScheme + "://" + authInfo + mHost + port + mPath;
      }
  
      public void setScheme(String scheme) {
          mScheme = scheme;
      }
  
      public String getScheme() {
          return mScheme;
      }
  
      public void setHost(@NonNull String host) {
          mHost = host;
      }
  
      public String getHost() {
          return mHost;
      }
  
      public void setPort(int port) {
          mPort = port;
      }
  
      public int getPort() {
          return mPort;
      }
  
      public void setPath(String path) {
          mPath = path;
      }
  
      public String getPath() {
          return mPath;
      }
  
      public void setAuthInfo(String authInfo) {
          mAuthInfo = authInfo;
      }
  
      public String getAuthInfo() {
          return mAuthInfo;
      }
  }
  