예제 #1
0
  /*
   * Perform an unescape operation based on char[].
   */
  static void unescape(
      final char[] text,
      final int offset,
      final int len,
      final Writer writer,
      final UriEscapeType escapeType,
      final String encoding)
      throws IOException {

    if (text == null) {
      return;
    }

    final int max = (offset + len);

    int readOffset = offset;

    for (int i = offset; i < max; i++) {

      final char c = text[i];

      /*
       * Check the need for an unescape operation at this point
       */

      if (c != ESCAPE_PREFIX && (c != '+' || !escapeType.canPlusEscapeWhitespace())) {
        continue;
      }

      /*
       * At this point we know for sure we will need some kind of unescape, so we
       * can increase the offset copy all the contents pending up to this point.
       */

      if (i - readOffset > 0) {
        writer.write(text, readOffset, (i - readOffset));
      }

      /*
       * Deal with possible '+'-escaped whitespace (application/x-www-form-urlencoded)
       */
      if (c == '+') {
        // if we reached this point with c == '+', it's escaping a whitespace
        writer.write(' ');
        readOffset = i + 1;
        continue;
      }

      /*
       * ESCAPE PROCESS
       * --------------
       * If there are more than one percent-encoded/escaped sequences together, we will
       * need to unescape them all at once (because they might be bytes --up to 4-- of
       * the same char).
       */

      // Max possible size will be the remaining amount of chars / 3
      final byte[] bytes = new byte[(max - i) / 3];
      char aheadC = c;
      int pos = 0;

      while (((i + 2) < max) && aheadC == ESCAPE_PREFIX) {
        bytes[pos++] = parseHexa(text[i + 1], text[i + 2]);
        i += 3;
        if (i < max) {
          aheadC = text[i];
        }
      }

      if (i < max && aheadC == ESCAPE_PREFIX) {
        // Incomplete escape sequence!
        throw new IllegalArgumentException("Incomplete escaping sequence in input");
      }

      try {
        writer.write(new String(bytes, 0, pos, encoding));
      } catch (final UnsupportedEncodingException e) {
        throw new IllegalArgumentException(
            "Exception while escaping URI: Bad encoding '" + encoding + "'", e);
      }

      readOffset = i;
    }

    /*
     * -----------------------------------------------------------------------------------------------
     * Final cleaning: return the original String object if no unescape was actually needed. Otherwise
     *                 append the remaining escaped text and return.
     * -----------------------------------------------------------------------------------------------
     */

    if (max - readOffset > 0) {
      writer.write(text, readOffset, (max - readOffset));
    }
  }
예제 #2
0
  /*
   * Perform an escape operation, based on char[], according to the specified type
   */
  static void escape(
      final char[] text,
      final int offset,
      final int len,
      final Writer writer,
      final UriEscapeType escapeType,
      final String encoding)
      throws IOException {

    if (text == null || text.length == 0) {
      return;
    }

    final int max = (offset + len);

    int readOffset = offset;

    for (int i = offset; i < max; i++) {

      final int codepoint = Character.codePointAt(text, i);

      /*
       * Shortcut: most characters will be alphabetic, and we won't need to do anything at
       * all for them. No need to use the complete UriEscapeType check system at all.
       */
      if (UriEscapeType.isAlpha(codepoint)) {
        continue;
      }

      /*
       * Check whether the character is allowed or not
       */
      if (escapeType.isAllowed(codepoint)) {
        continue;
      }

      /*
       * At this point we know for sure we will need some kind of escape, so we
       * can write all the contents pending up to this point.
       */

      if (i - readOffset > 0) {
        writer.write(text, readOffset, (i - readOffset));
      }

      if (Character.charCount(codepoint) > 1) {
        // This is to compensate that we are actually reading two char[] positions with a single
        // codepoint.
        i++;
      }

      readOffset = i + 1;

      /*
       * -----------------------------------------------------------------------------------------
       *
       * Peform the real escape
       *
       * -----------------------------------------------------------------------------------------
       */

      final byte[] charAsBytes;
      try {
        charAsBytes = new String(Character.toChars(codepoint)).getBytes(encoding);
      } catch (final UnsupportedEncodingException e) {
        throw new IllegalArgumentException(
            "Exception while escaping URI: Bad encoding '" + encoding + "'", e);
      }
      for (final byte b : charAsBytes) {
        writer.write('%');
        writer.write(printHexa(b));
      }
    }

    /*
     * -----------------------------------------------------------------------------------------------
     * Final cleaning: return the original String object if no escape was actually needed. Otherwise
     *                 append the remaining unescaped text to the string builder and return.
     * -----------------------------------------------------------------------------------------------
     */

    if (max - readOffset > 0) {
      writer.write(text, readOffset, (max - readOffset));
    }
  }