1
2
3
4
5 package org.rcfaces.core.internal.codec;
6
7 import java.io.IOException;
8 import java.io.UnsupportedEncodingException;
9 import java.net.URLDecoder;
10 import java.net.URLEncoder;
11 import java.util.BitSet;
12
13 import javax.faces.FacesException;
14 import javax.servlet.jsp.JspWriter;
15
16 import org.rcfaces.core.internal.lang.StringAppender;
17
18
19
20
21
22 public final class URLFormCodec {
23
24 private static final String REVISION = "$Revision: 1.18 $";
25
26 private static final String FORM_DECODER_INPUT_CHARSET = "UTF8";
27
28 private static final String FORM_DECODER_UTF8_CHARSET = "UTF8";
29
30 private static final int CASE_DIFF = 'a' - 'A';
31
32 private static final BitSet dontNeedEncoding;
33 static {
34 dontNeedEncoding = new BitSet(127);
35 int i;
36 for (i = 'a'; i <= 'z'; i++) {
37 dontNeedEncoding.set(i);
38 }
39 for (i = 'A'; i <= 'Z'; i++) {
40 dontNeedEncoding.set(i);
41 }
42 for (i = '0'; i <= '9'; i++) {
43 dontNeedEncoding.set(i);
44 }
45 dontNeedEncoding.set('-');
46 dontNeedEncoding.set('_');
47 dontNeedEncoding.set('.');
48 dontNeedEncoding.set('*');
49 }
50
51 private static final BitSet urlDontNeedEncoding;
52 static {
53 urlDontNeedEncoding = new BitSet(127);
54 urlDontNeedEncoding.or(dontNeedEncoding);
55
56
57 urlDontNeedEncoding.set('/');
58 urlDontNeedEncoding.set(':');
59 urlDontNeedEncoding.set('?');
60 urlDontNeedEncoding.set('#');
61 }
62
63 public static String decodeUTF8(String source) {
64 if (source == null) {
65 return null;
66 }
67
68 int length = source.length();
69 if (length < 3) {
70 return source;
71 }
72
73 try {
74 return URLDecoder.decode(source, FORM_DECODER_INPUT_CHARSET);
75
76 } catch (UnsupportedEncodingException e) {
77 throw new FacesException("Can not decode '" + source + "'.", e);
78 }
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 }
103
104 private static void append(StringAppender sb, String url, BitSet bitSet,
105 boolean convertSpace) {
106 char chs[] = url.toCharArray();
107
108 for (int i = 0; i < chs.length; i++) {
109 int c = chs[i];
110
111 if (c < 256 && bitSet.get(c)) {
112 sb.append((char) c);
113 continue;
114 }
115 if (c == 32 && convertSpace) {
116 sb.append('+');
117 continue;
118 }
119
120
121
122 if (c < 128) {
123 sb.append('%');
124 char ch = Character.forDigit((c >> 4) & 0xF, 16);
125 if (Character.isLetter(ch)) {
126 ch -= CASE_DIFF;
127 }
128 sb.append(ch);
129 ch = Character.forDigit(c & 0xF, 16);
130 if (Character.isLetter(ch)) {
131 ch -= CASE_DIFF;
132 }
133 sb.append(ch);
134
135 continue;
136 }
137
138 String form;
139 try {
140 form = URLEncoder.encode(url.substring(i, i + 1),
141 FORM_DECODER_UTF8_CHARSET);
142
143 } catch (UnsupportedEncodingException e) {
144 throw new FacesException("Can not encode '" + url + "'.", e);
145 }
146 sb.append(form);
147
148 }
149 }
150
151 public static void main(String args[]) {
152 System.out.println("DecodeUTF8: '" + args[0] + "' => '"
153 + decodeUTF8(args[0]) + "'");
154 }
155
156 public static void writeURL(JspWriter writer, String url)
157 throws IOException {
158 int length = url.length();
159 StringAppender sa = new StringAppender(length * 3 / 2);
160
161 appendURL(sa, url);
162
163 sa.copyInto(writer);
164 }
165
166 public static String decodeURL(String url) {
167 char chs[] = url.toCharArray();
168
169 return decodeURL(chs, 0, chs.length);
170 }
171
172 public static String decodeURL(char chs[], int offset, int end) {
173 if (false) {
174 StringAppender sa = new StringAppender(end - offset);
175
176 next_char: for (; offset < end; offset++) {
177 int c = chs[offset];
178 if (c != '%') {
179 sa.append((char) c);
180 continue;
181 }
182
183 int v = 0;
184 for (int j = 0; j < 2; j++) {
185 offset++;
186 if (offset >= end) {
187 break next_char;
188 }
189
190 v <<= 4;
191 c = chs[offset];
192 if (c >= '0' && c <= '9') {
193 v |= (c - '0');
194
195 } else if (c >= 'A' && c <= 'F') {
196 v |= (c - 'A' + 10);
197
198 } else if (c >= 'a' && c <= 'f') {
199 v |= (c - 'a' + 10);
200 } else {
201 throw new IllegalStateException(
202 "Invalid hexadecimal character " + v);
203 }
204 }
205
206 sa.append((char) v);
207 }
208
209 return sa.toString();
210 }
211
212 return decodeUTF8(new String(chs, offset, end - offset));
213 }
214
215 public static void appendURL(StringAppender sa, String url) {
216 append(sa, url, urlDontNeedEncoding, false);
217 }
218
219 public static void encode(StringAppender sa, String value) {
220 append(sa, value, dontNeedEncoding, true);
221 }
222 }