/**
   * @return The HTTP-authentication object or null if there is no supported scheme in the header.
   *     If there are several valid schemes present, we pick the strongest one. If there are several
   *     schemes of the same strength, we pick the one that comes first.
   */
  private HttpAuthHeader parseAuthHeader(String header) {
    if (header != null) {
      int posMax = 256;
      int posLen = 0;
      int[] pos = new int[posMax];

      int headerLen = header.length();
      if (headerLen > 0) {
        // first, we find all unquoted instances of 'Basic' and 'Digest'
        boolean quoted = false;
        for (int i = 0; i < headerLen && posLen < posMax; ++i) {
          if (header.charAt(i) == '\"') {
            quoted = !quoted;
          } else {
            if (!quoted) {
              if (header.startsWith(HttpAuthHeader.BASIC_TOKEN, i)) {
                pos[posLen++] = i;
                continue;
              }

              if (header.startsWith(HttpAuthHeader.DIGEST_TOKEN, i)) {
                pos[posLen++] = i;
                continue;
              }
            }
          }
        }
      }

      if (posLen > 0) {
        // consider all digest schemes first (if any)
        for (int i = 0; i < posLen; i++) {
          if (header.startsWith(HttpAuthHeader.DIGEST_TOKEN, pos[i])) {
            String sub = header.substring(pos[i], (i + 1 < posLen ? pos[i + 1] : headerLen));

            HttpAuthHeader rval = new HttpAuthHeader(sub);
            if (rval.isSupportedScheme()) {
              // take the first match
              return rval;
            }
          }
        }

        // ...then consider all basic schemes (if any)
        for (int i = 0; i < posLen; i++) {
          if (header.startsWith(HttpAuthHeader.BASIC_TOKEN, pos[i])) {
            String sub = header.substring(pos[i], (i + 1 < posLen ? pos[i + 1] : headerLen));

            HttpAuthHeader rval = new HttpAuthHeader(sub);
            if (rval.isSupportedScheme()) {
              // take the first match
              return rval;
            }
          }
        }
      }
    }

    return null;
  }