~ubuntu-branches/ubuntu/utopic/jing-trang/utopic

« back to all changes in this revision

Viewing changes to mod/util/src/main/com/thaiopensource/util/UriEncoder.java

  • Committer: Bazaar Package Importer
  • Author(s): Samuel Thibault
  • Date: 2009-09-01 15:53:03 UTC
  • Revision ID: james.westby@ubuntu.com-20090901155303-2kweef05h5v9j3ni
Tags: upstream-20090818
ImportĀ upstreamĀ versionĀ 20090818

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package com.thaiopensource.util;
 
2
 
 
3
/**
 
4
 *  Selectively percent-encodes characters in a URI.
 
5
 */
 
6
public class UriEncoder {
 
7
  /**
 
8
   * Flag to include U+0000 - U+001F.
 
9
   */
 
10
  static private final int C0_CONTROL = 0x01;
 
11
  /**
 
12
   * Flag to include U+0020
 
13
   */
 
14
  static private final int SPACE = 0x02;
 
15
  /**
 
16
   * Flag to include '<', '>', '"'
 
17
   */
 
18
  static private final int DELIM = 0x04;
 
19
  /**
 
20
   * Flag to include '{', '}', '|', '\\', '^', U+007E
 
21
   */
 
22
  static private final int UNWISE = 0x08;
 
23
  /**
 
24
   * Flag to include U+007F
 
25
   */
 
26
  static private final int DELETE = 0x10;
 
27
  /**
 
28
   * Flag to include U+0080 - U+009F
 
29
   */
 
30
  static private final int C1_CONTROL = 0x20;
 
31
  /**
 
32
   * Flag to include any non-ASCII character with category Zs, Zl, and Zp
 
33
   */
 
34
  static private final int NON_ASCII_SEPARATOR = 0x40;
 
35
  /**
 
36
   * Flag to include any other character with code-point >= U+0080
 
37
   */
 
38
  static private final int OTHER_NON_ASCII = 0x80;
 
39
 
 
40
  static private final int ASCII_CONTROL = C0_CONTROL|DELETE;
 
41
  static private final int CONTROL = ASCII_CONTROL|C1_CONTROL;
 
42
  static private final int SEPARATOR = NON_ASCII_SEPARATOR|SPACE;
 
43
  static private final int ASCII_GRAPHIC_FORBIDDEN = DELIM|UNWISE;
 
44
  static private final int ASCII_PRINTABLE_FORBIDDEN = ASCII_GRAPHIC_FORBIDDEN|SPACE;
 
45
  static private final int ASCII_FORBIDDEN = ASCII_CONTROL|ASCII_PRINTABLE_FORBIDDEN;
 
46
  static private final int NON_ASCII = C1_CONTROL|NON_ASCII_SEPARATOR|OTHER_NON_ASCII;
 
47
  static private final int JAVA_URI_FORBIDDEN = CONTROL|SEPARATOR|ASCII_PRINTABLE_FORBIDDEN;
 
48
  static private final int URI_FORBIDDEN = ASCII_FORBIDDEN|NON_ASCII;
 
49
 
 
50
  static public String encode(String s) {
 
51
    return encode(s, JAVA_URI_FORBIDDEN);
 
52
  }
 
53
 
 
54
  static public String encodeAsAscii(String s) {
 
55
    return encode(s, URI_FORBIDDEN);
 
56
  }
 
57
 
 
58
  static private String encode(String s, int flags) {
 
59
    StringBuffer encoded = null;
 
60
    final int len = s.length();
 
61
    for (int i = 0; i < len; i++) {
 
62
      char c = s.charAt(i);
 
63
      boolean mustEncode;
 
64
      switch (c) {
 
65
      case '<':
 
66
      case '>':
 
67
      case '"':
 
68
        mustEncode = ((flags & DELIM) != 0);
 
69
        break;
 
70
      case '{':
 
71
      case '}':
 
72
      case '|':
 
73
      case '\\':
 
74
      case '^':
 
75
      case '`':
 
76
        mustEncode = ((flags & UNWISE) != 0);
 
77
        break;
 
78
      case 0x20:
 
79
        mustEncode = ((flags & SPACE) != 0);
 
80
        break;
 
81
      case 0x7F:
 
82
        mustEncode = ((flags & DELETE) != 0);
 
83
        break;
 
84
      default:
 
85
        if (c < 0x20)
 
86
          mustEncode = ((flags & C0_CONTROL) != 0);
 
87
        else if (c < 0x80)
 
88
          mustEncode = false;
 
89
        else {
 
90
          switch (flags & NON_ASCII) {
 
91
          case NON_ASCII:
 
92
            // all non-ASCII chars need to be escaped
 
93
            mustEncode = true;
 
94
            break;
 
95
          case 0:
 
96
            // no non-ASCII chars need to be escaped
 
97
            mustEncode = false;
 
98
            break;
 
99
          default:
 
100
            if (Character.isISOControl(c))
 
101
              mustEncode = ((flags & C1_CONTROL) != 0);
 
102
            else if (Character.isSpaceChar(c))
 
103
              mustEncode = ((flags & NON_ASCII_SEPARATOR) != 0);
 
104
            else
 
105
              mustEncode = ((flags & OTHER_NON_ASCII) != 0);
 
106
            break;
 
107
          }
 
108
        }
 
109
      }
 
110
      if (mustEncode) {
 
111
        if (encoded == null)
 
112
          encoded = new StringBuffer(s.substring(0, i));
 
113
        int codePoint;
 
114
        if (Utf16.isSurrogate1(c)
 
115
            && i + 1 < len
 
116
            && Utf16.isSurrogate2(s.charAt(i + 1)))
 
117
          codePoint = Utf16.scalarValue(c, s.charAt(++i));
 
118
        else
 
119
          codePoint = c;
 
120
        encoded.append(percentEncode(Utf8.encode(codePoint)));
 
121
      }
 
122
      else if (encoded != null)
 
123
        encoded.append(c);
 
124
    }
 
125
    if (encoded != null)
 
126
      return encoded.toString();
 
127
    return s;
 
128
  }
 
129
 
 
130
  static private final String hexDigits = "0123456789ABCDEF";
 
131
 
 
132
  static char[] percentEncode(byte[] bytes) {
 
133
    char[] buf = new char[bytes.length * 3];
 
134
    int j = 0;
 
135
    for (int i = 0; i < bytes.length; i++) {
 
136
      int b = bytes[i];
 
137
      buf[j++] = '%';
 
138
      buf[j++] = hexDigits.charAt((b >> 4) & 0xF);
 
139
      buf[j++] = hexDigits.charAt(b & 0xF);
 
140
    }
 
141
    return buf;
 
142
  }
 
143
}