Beispiel #1
0
  /*
   * Removes /./ and /../ sequences from absolute URLs.
   * Code borrowed heavily from CoyoteAdapter.normalize()
   */
  private void normalize(CharChunk cc) {
    // Strip query string and/or fragment first as doing it this way makes
    // the normalization logic a lot simpler
    int truncate = cc.indexOf('?');
    if (truncate == -1) {
      truncate = cc.indexOf('#');
    }
    char[] truncateCC = null;
    if (truncate > -1) {
      truncateCC = Arrays.copyOfRange(cc.getBuffer(), cc.getStart() + truncate, cc.getEnd());
      cc.setEnd(cc.getStart() + truncate);
    }

    if (cc.endsWith("/.") || cc.endsWith("/..")) {
      try {
        cc.append('/');
      } catch (IOException e) {
        throw new IllegalArgumentException(cc.toString(), e);
      }
    }

    char[] c = cc.getChars();
    int start = cc.getStart();
    int end = cc.getEnd();
    int index = 0;
    int startIndex = 0;

    // Advance past the first three / characters (should place index just
    // scheme://host[:port]

    for (int i = 0; i < 3; i++) {
      startIndex = cc.indexOf('/', startIndex + 1);
    }

    // Remove /./
    index = startIndex;
    while (true) {
      index = cc.indexOf("/./", 0, 3, index);
      if (index < 0) {
        break;
      }
      copyChars(c, start + index, start + index + 2, end - start - index - 2);
      end = end - 2;
      cc.setEnd(end);
    }

    // Remove /../
    index = startIndex;
    int pos;
    while (true) {
      index = cc.indexOf("/../", 0, 4, index);
      if (index < 0) {
        break;
      }
      // Can't go above the server root
      if (index == startIndex) {
        throw new IllegalArgumentException();
      }
      int index2 = -1;
      for (pos = start + index - 1; (pos >= 0) && (index2 < 0); pos--) {
        if (c[pos] == (byte) '/') {
          index2 = pos;
        }
      }
      copyChars(c, start + index2, start + index + 3, end - start - index - 3);
      end = end + index2 - index - 3;
      cc.setEnd(end);
      index = index2;
    }

    // Add the query string and/or fragment (if present) back in
    if (truncateCC != null) {
      try {
        cc.append(truncateCC, 0, truncateCC.length);
      } catch (IOException ioe) {
        throw new IllegalArgumentException(ioe);
      }
    }
  }
Beispiel #2
0
  /**
   * Convert (if necessary) and return the absolute URL that represents the resource referenced by
   * this possibly relative URL. If this URL is already absolute, return it unchanged.
   *
   * @param location URL to be (possibly) converted and then returned
   * @exception IllegalArgumentException if a MalformedURLException is thrown when converting the
   *     relative URL to an absolute one
   */
  protected String toAbsolute(String location) {

    if (location == null) {
      return (location);
    }

    boolean leadingSlash = location.startsWith("/");

    if (location.startsWith("//")) {
      // Scheme relative
      redirectURLCC.recycle();
      // Add the scheme
      String scheme = request.getScheme();
      try {
        redirectURLCC.append(scheme, 0, scheme.length());
        redirectURLCC.append(':');
        redirectURLCC.append(location, 0, location.length());
        return redirectURLCC.toString();
      } catch (IOException e) {
        IllegalArgumentException iae = new IllegalArgumentException(location);
        iae.initCause(e);
        throw iae;
      }

    } else if (leadingSlash || !hasScheme(location)) {

      redirectURLCC.recycle();

      String scheme = request.getScheme();
      String name = request.getServerName();
      int port = request.getServerPort();

      try {
        redirectURLCC.append(scheme, 0, scheme.length());
        redirectURLCC.append("://", 0, 3);
        redirectURLCC.append(name, 0, name.length());
        if ((scheme.equals("http") && port != 80) || (scheme.equals("https") && port != 443)) {
          redirectURLCC.append(':');
          String portS = port + "";
          redirectURLCC.append(portS, 0, portS.length());
        }
        if (!leadingSlash) {
          String relativePath = request.getDecodedRequestURI();
          int pos = relativePath.lastIndexOf('/');
          CharChunk encodedURI = null;
          final String frelativePath = relativePath;
          final int fend = pos;
          if (SecurityUtil.isPackageProtectionEnabled()) {
            try {
              encodedURI =
                  AccessController.doPrivileged(
                      new PrivilegedExceptionAction<CharChunk>() {
                        @Override
                        public CharChunk run() throws IOException {
                          return urlEncoder.encodeURL(frelativePath, 0, fend);
                        }
                      });
            } catch (PrivilegedActionException pae) {
              IllegalArgumentException iae = new IllegalArgumentException(location);
              iae.initCause(pae.getException());
              throw iae;
            }
          } else {
            encodedURI = urlEncoder.encodeURL(relativePath, 0, pos);
          }
          redirectURLCC.append(encodedURI);
          encodedURI.recycle();
          redirectURLCC.append('/');
        }
        redirectURLCC.append(location, 0, location.length());

        normalize(redirectURLCC);
      } catch (IOException e) {
        IllegalArgumentException iae = new IllegalArgumentException(location);
        iae.initCause(e);
        throw iae;
      }

      return redirectURLCC.toString();

    } else {

      return (location);
    }
  }