Simplified much of the code based on more basic configuration of default charsets and cooresponding encodings.
1 | /* |
2 | * The contents of this file are subject to the AOLserver Public License |
3 | * Version 1.1 (the "License"); you may not use this file except in |
4 | * compliance with the License. You may obtain a copy of the License at |
5 | * http://aolserver.com/. |
6 | * |
7 | * Software distributed under the License is distributed on an "AS IS" |
8 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See |
9 | * the License for the specific language governing rights and limitations |
10 | * under the License. |
11 | * |
12 | * The Original Code is AOLserver Code and related documentation |
13 | * distributed by AOL. |
14 | * |
15 | * The Initial Developer of the Original Code is America Online, |
16 | * Inc. Portions created by AOL are Copyright (C) 1999 America Online, |
17 | * Inc. All Rights Reserved. |
18 | * |
19 | * Alternatively, the contents of this file may be used under the terms |
20 | * of the GNU General Public License (the "GPL"), in which case the |
21 | * provisions of GPL are applicable instead of those above. If you wish |
22 | * to allow use of your version of this file only under the terms of the |
23 | * GPL and not to allow others to use your version of this file under the |
24 | * License, indicate your decision by deleting the provisions above and |
25 | * replace them with the notice and other provisions required by the GPL. |
26 | * If you do not delete the provisions above, a recipient may use your |
27 | * version of this file under either the License or the GPL. |
28 | */ |
29 | |
30 | |
31 | /* |
32 | * urlencode.c -- |
33 | * |
34 | * Encode and decode URLs, as described in RFC 1738. |
35 | */ |
36 | |
37 | static const char *RCSID = "@(#) $Header: /cvsroot-fuse/aolserver/aolserver/nsd/urlencode.c,v 1.17 2005/03/25 00:39:47 jgdavidson Exp $, compiled: " __DATE__ " " __TIME__; |
38 | |
39 | #include "nsd.h" |
40 | |
41 | /* |
42 | * Static functions defined in this file. |
43 | */ |
44 | |
45 | static Tcl_Encoding <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_GetUrlEncoding">GetUrlEncoding</a>(char *charset); |
46 | |
47 | /* |
48 | * The following table is used for URL encoding and decoding |
49 | * all 256 characters. |
50 | */ |
51 | |
52 | struct { |
53 | int hex; /* Valid hex value or -1. */ |
54 | int len; /* Length required to encode string. */ |
55 | char *str; /* String for multibyte encoded character. */ |
56 | } enc[] = { |
57 | {-1, 3, "00"}, {-1, 3, "01"}, {-1, 3, "02"}, {-1, 3, "03"}, |
58 | {-1, 3, "04"}, {-1, 3, "05"}, {-1, 3, "06"}, {-1, 3, "07"}, |
59 | {-1, 3, "08"}, {-1, 3, "09"}, {-1, 3, "0a"}, {-1, 3, "0b"}, |
60 | {-1, 3, "0c"}, {-1, 3, "0d"}, {-1, 3, "0e"}, {-1, 3, "0f"}, |
61 | {-1, 3, "10"}, {-1, 3, "11"}, {-1, 3, "12"}, {-1, 3, "13"}, |
62 | {-1, 3, "14"}, {-1, 3, "15"}, {-1, 3, "16"}, {-1, 3, "17"}, |
63 | {-1, 3, "18"}, {-1, 3, "19"}, {-1, 3, "1a"}, {-1, 3, "1b"}, |
64 | {-1, 3, "1c"}, {-1, 3, "1d"}, {-1, 3, "1e"}, {-1, 3, "1f"}, |
65 | {-1, 1, NULL}, {-1, 3, "21"}, {-1, 3, "22"}, {-1, 3, "23"}, |
66 | {-1, 3, "24"}, {-1, 3, "25"}, {-1, 3, "26"}, {-1, 3, "27"}, |
67 | {-1, 3, "28"}, {-1, 3, "29"}, {-1, 3, "2a"}, {-1, 3, "2b"}, |
68 | {-1, 3, "2c"}, {-1, 3, "2d"}, {-1, 3, "2e"}, {-1, 3, "2f"}, |
69 | { 0, 1, NULL}, { 1, 1, NULL}, { 2, 1, NULL}, { 3, 1, NULL}, |
70 | { 4, 1, NULL}, { 5, 1, NULL}, { 6, 1, NULL}, { 7, 1, NULL}, |
71 | { 8, 1, NULL}, { 9, 1, NULL}, {-1, 3, "3a"}, {-1, 3, "3b"}, |
72 | {-1, 3, "3c"}, {-1, 3, "3d"}, {-1, 3, "3e"}, {-1, 3, "3f"}, |
73 | {-1, 3, "40"}, {10, 1, NULL}, {11, 1, NULL}, {12, 1, NULL}, |
74 | {13, 1, NULL}, {14, 1, NULL}, {15, 1, NULL}, {-1, 1, NULL}, |
75 | {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, |
76 | {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, |
77 | {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, |
78 | {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, |
79 | {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, {-1, 3, "5b"}, |
80 | {-1, 3, "5c"}, {-1, 3, "5d"}, {-1, 3, "5e"}, {-1, 3, "5f"}, |
81 | {-1, 3, "60"}, {10, 1, NULL}, {11, 1, NULL}, {12, 1, NULL}, |
82 | {13, 1, NULL}, {14, 1, NULL}, {15, 1, NULL}, {-1, 1, NULL}, |
83 | {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, |
84 | {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, |
85 | {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, |
86 | {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, |
87 | {-1, 1, NULL}, {-1, 1, NULL}, {-1, 1, NULL}, {-1, 3, "7b"}, |
88 | {-1, 3, "7c"}, {-1, 3, "7d"}, {-1, 3, "7e"}, {-1, 3, "7f"}, |
89 | {-1, 3, "80"}, {-1, 3, "81"}, {-1, 3, "82"}, {-1, 3, "83"}, |
90 | {-1, 3, "84"}, {-1, 3, "85"}, {-1, 3, "86"}, {-1, 3, "87"}, |
91 | {-1, 3, "88"}, {-1, 3, "89"}, {-1, 3, "8a"}, {-1, 3, "8b"}, |
92 | {-1, 3, "8c"}, {-1, 3, "8d"}, {-1, 3, "8e"}, {-1, 3, "8f"}, |
93 | {-1, 3, "90"}, {-1, 3, "91"}, {-1, 3, "92"}, {-1, 3, "93"}, |
94 | {-1, 3, "94"}, {-1, 3, "95"}, {-1, 3, "96"}, {-1, 3, "97"}, |
95 | {-1, 3, "98"}, {-1, 3, "99"}, {-1, 3, "9a"}, {-1, 3, "9b"}, |
96 | {-1, 3, "9c"}, {-1, 3, "9d"}, {-1, 3, "9e"}, {-1, 3, "9f"}, |
97 | {-1, 3, "a0"}, {-1, 3, "a1"}, {-1, 3, "a2"}, {-1, 3, "a3"}, |
98 | {-1, 3, "a4"}, {-1, 3, "a5"}, {-1, 3, "a6"}, {-1, 3, "a7"}, |
99 | {-1, 3, "a8"}, {-1, 3, "a9"}, {-1, 3, "aa"}, {-1, 3, "ab"}, |
100 | {-1, 3, "ac"}, {-1, 3, "ad"}, {-1, 3, "ae"}, {-1, 3, "af"}, |
101 | {-1, 3, "b0"}, {-1, 3, "b1"}, {-1, 3, "b2"}, {-1, 3, "b3"}, |
102 | {-1, 3, "b4"}, {-1, 3, "b5"}, {-1, 3, "b6"}, {-1, 3, "b7"}, |
103 | {-1, 3, "b8"}, {-1, 3, "b9"}, {-1, 3, "ba"}, {-1, 3, "bb"}, |
104 | {-1, 3, "bc"}, {-1, 3, "bd"}, {-1, 3, "be"}, {-1, 3, "bf"}, |
105 | {-1, 3, "c0"}, {-1, 3, "c1"}, {-1, 3, "c2"}, {-1, 3, "c3"}, |
106 | {-1, 3, "c4"}, {-1, 3, "c5"}, {-1, 3, "c6"}, {-1, 3, "c7"}, |
107 | {-1, 3, "c8"}, {-1, 3, "c9"}, {-1, 3, "ca"}, {-1, 3, "cb"}, |
108 | {-1, 3, "cc"}, {-1, 3, "cd"}, {-1, 3, "ce"}, {-1, 3, "cf"}, |
109 | {-1, 3, "d0"}, {-1, 3, "d1"}, {-1, 3, "d2"}, {-1, 3, "d3"}, |
110 | {-1, 3, "d4"}, {-1, 3, "d5"}, {-1, 3, "d6"}, {-1, 3, "d7"}, |
111 | {-1, 3, "d8"}, {-1, 3, "d9"}, {-1, 3, "da"}, {-1, 3, "db"}, |
112 | {-1, 3, "dc"}, {-1, 3, "dd"}, {-1, 3, "de"}, {-1, 3, "df"}, |
113 | {-1, 3, "e0"}, {-1, 3, "e1"}, {-1, 3, "e2"}, {-1, 3, "e3"}, |
114 | {-1, 3, "e4"}, {-1, 3, "e5"}, {-1, 3, "e6"}, {-1, 3, "e7"}, |
115 | {-1, 3, "e8"}, {-1, 3, "e9"}, {-1, 3, "ea"}, {-1, 3, "eb"}, |
116 | {-1, 3, "ec"}, {-1, 3, "ed"}, {-1, 3, "ee"}, {-1, 3, "ef"}, |
117 | {-1, 3, "f0"}, {-1, 3, "f1"}, {-1, 3, "f2"}, {-1, 3, "f3"}, |
118 | {-1, 3, "f4"}, {-1, 3, "f5"}, {-1, 3, "f6"}, {-1, 3, "f7"}, |
119 | {-1, 3, "f8"}, {-1, 3, "f9"}, {-1, 3, "fa"}, {-1, 3, "fb"}, |
120 | {-1, 3, "fc"}, {-1, 3, "fd"}, {-1, 3, "fe"}, {-1, 3, "ff"} |
121 | }; |
122 | |
123 | |
124 | /* |
125 | *---------------------------------------------------------------------- |
126 | * |
127 | * <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_Ns_EncodeUrlWithEncoding">Ns_EncodeUrlWithEncoding</a> -- |
128 | * |
129 | * Take a URL and encode any non-alphanumeric characters into |
130 | * %hexcode |
131 | * |
132 | * Results: |
133 | * A pointer to the encoded string (which is part of the |
134 | * passed-in DString's memory) |
135 | * |
136 | * Side effects: |
137 | * Encoded URL will be copied to given dstring. |
138 | * |
139 | *---------------------------------------------------------------------- |
140 | */ |
141 | |
142 | char * |
143 | <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_Ns_EncodeUrlWithEncoding">Ns_EncodeUrlWithEncoding</a>(Ns_DString *dsPtr, char *string, Tcl_Encoding encoding) |
144 | { |
145 | register int i, n; |
146 | register char *p, *q; |
147 | Tcl_DString ds; |
148 | |
149 | Tcl_DStringInit(&ds); |
150 | if (encoding != NULL) { |
151 | string = Tcl_UtfToExternalDString(encoding, string, -1, &ds); |
152 | } |
153 | |
154 | /* |
155 | * Determine and set the required dstring length. |
156 | */ |
157 | |
158 | p = string; |
159 | n = 0; |
160 | while ((i = UCHAR(*p)) != 0) { |
161 | n += enc[i].len; |
162 | ++p; |
163 | } |
164 | i = dsPtr->length; |
165 | <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringSetLength">Ns_DStringSetLength</a>(dsPtr, dsPtr->length + n); |
166 | |
167 | /* |
168 | * Copy the result directly to the pre-sized dstring. |
169 | */ |
170 | |
171 | q = dsPtr->string + i; |
172 | p = string; |
173 | while ((i = UCHAR(*p)) != 0) { |
174 | if (UCHAR(*p) == ' ') { |
175 | *q++ = '+'; |
176 | } else if (enc[i].str == NULL) { |
177 | *q++ = *p; |
178 | } else { |
179 | *q++ = '%'; |
180 | *q++ = enc[i].str[0]; |
181 | *q++ = enc[i].str[1]; |
182 | } |
183 | ++p; |
184 | } |
185 | Tcl_DStringFree(&ds); |
186 | return dsPtr->string; |
187 | } |
188 | |
189 | |
190 | |
191 | /* |
192 | *---------------------------------------------------------------------- |
193 | * |
194 | * <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_Ns_EncodeUrlCharset">Ns_EncodeUrlCharset</a> -- |
195 | * |
196 | * Take a URL and encode any non-alphanumeric characters into |
197 | * %hexcode |
198 | * |
199 | * Results: |
200 | * A pointer to the encoded string (which is part of the |
201 | * passed-in DString's memory) |
202 | * |
203 | * Side effects: |
204 | * Encoded URL will be copied to given dstring. |
205 | * |
206 | *---------------------------------------------------------------------- |
207 | */ |
208 | |
209 | char * |
210 | <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_Ns_EncodeUrlCharset">Ns_EncodeUrlCharset</a>(Ns_DString *dsPtr, char *string, char *charset) |
211 | { |
212 | Tcl_Encoding encoding = <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_GetUrlEncoding">GetUrlEncoding</a>(charset); |
213 | |
214 | return <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_Ns_EncodeUrlWithEncoding">Ns_EncodeUrlWithEncoding</a>(dsPtr, string, encoding); |
215 | |
216 | } |
217 | |
218 | /* |
219 | *---------------------------------------------------------------------- |
220 | * |
221 | * <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_Ns_DecodeUrlCharset">Ns_DecodeUrlCharset</a> -- |
222 | * |
223 | * Decode an encoded URL (with %hexcode, etc.). |
224 | * |
225 | * Results: |
226 | * A pointer to the dstring's value, containing the decoded |
227 | * URL. |
228 | * |
229 | * Side effects: |
230 | * Decoded URL will be copied to given dstring. |
231 | * |
232 | *---------------------------------------------------------------------- |
233 | */ |
234 | |
235 | char * |
236 | <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_Ns_DecodeUrlCharset">Ns_DecodeUrlCharset</a>(Ns_DString *dsPtr, char *string, char *charset) |
237 | { |
238 | Tcl_Encoding encoding = <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_GetUrlEncoding">GetUrlEncoding</a>(charset); |
239 | |
240 | return <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_Ns_DecodeUrlWithEncoding">Ns_DecodeUrlWithEncoding</a>(dsPtr, string, encoding); |
241 | } |
242 | |
243 | |
244 | |
245 | /* |
246 | *---------------------------------------------------------------------- |
247 | * |
248 | * <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_Ns_DecodeUrlWithEncoding">Ns_DecodeUrlWithEncoding</a> -- |
249 | * |
250 | * Decode an encoded URL (with %hexcode, etc.). |
251 | * |
252 | * Results: |
253 | * A pointer to the dstring's value, containing the decoded |
254 | * URL. |
255 | * |
256 | * Side effects: |
257 | * Decoded URL will be copied to given dstring. |
258 | * |
259 | *---------------------------------------------------------------------- |
260 | */ |
261 | |
262 | char * |
263 | <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_Ns_DecodeUrlWithEncoding">Ns_DecodeUrlWithEncoding</a>(Ns_DString *dsPtr, char *string, Tcl_Encoding encoding) |
264 | { |
265 | register int i, j, n; |
266 | register char *p, *q; |
267 | char c; |
268 | Ns_DString *outPtr, out; |
269 | Tcl_DString ds; |
270 | |
271 | /* |
272 | * If using an encoding, copy output to a scratch buffer instead |
273 | * of directly to given dstring. |
274 | */ |
275 | |
276 | if (encoding == NULL) { |
277 | outPtr = dsPtr; |
278 | } else { |
279 | <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringInit">Ns_DStringInit</a>(&out); |
280 | outPtr = &out; |
281 | } |
282 | |
283 | /* |
284 | * Expand the output to the length of the input |
285 | * string which will be the largest size required. |
286 | */ |
287 | |
288 | n = strlen(string); |
289 | i = dsPtr->length; |
290 | <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringSetLength">Ns_DStringSetLength</a>(outPtr, i + n); |
291 | q = outPtr->string + i; |
292 | p = string; |
293 | while ((c = UCHAR(*p)) != '\0') { |
294 | if (c == '%' && n > 2 && |
295 | (i = enc[UCHAR(p[1])].hex) >= 0 && |
296 | (j = enc[UCHAR(p[2])].hex) >= 0) { |
297 | *q = (unsigned char) ((i << 4) + j); |
298 | n -= 2; |
299 | p += 2; |
300 | } else if (c == '+') { |
301 | *q = ' '; |
302 | } else { |
303 | *q = c; |
304 | } |
305 | --n, ++q, ++p; |
306 | } |
307 | |
308 | /* |
309 | * Terminate the dstring, decoding to utf8 if necessary. |
310 | */ |
311 | |
312 | n = q - outPtr->string; |
313 | if (outPtr == dsPtr) { |
314 | <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringSetLength">Ns_DStringSetLength</a>(dsPtr, n); |
315 | } else { |
316 | Tcl_ExternalToUtfDString(encoding, outPtr->string, n, &ds); |
317 | <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(dsPtr, ds.string); |
318 | Tcl_DStringFree(&ds); |
319 | <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringFree">Ns_DStringFree</a>(outPtr); |
320 | } |
321 | return dsPtr->string; |
322 | } |
323 | |
324 | |
325 | /* |
326 | *---------------------------------------------------------------------- |
327 | * |
328 | * <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_NsTclUrlEncodeObjCmd">NsTclUrlEncodeObjCmd</a>, <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_NsTclUrlDecodeObjCmd">NsTclUrlDecodeObjCmd</a> -- |
329 | * |
330 | * Implements ns_urlencode and ns_urldecode. |
331 | * |
332 | * Results: |
333 | * Tcl result. |
334 | * |
335 | * Side effects: |
336 | * See docs. |
337 | * |
338 | *---------------------------------------------------------------------- |
339 | */ |
340 | |
341 | static int |
342 | <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_EncodeObjCmd">EncodeObjCmd</a>(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int encode) |
343 | { |
344 | Tcl_DString ds; |
345 | char *charset; |
346 | char *data; |
347 | |
348 | if (objc == 2) { |
349 | charset = NULL; |
350 | data = Tcl_GetString(objv[1]); |
351 | } else if (objc == 4 && STREQ(Tcl_GetString(objv[1]), "-charset")) { |
352 | charset = Tcl_GetString(objv[2]); |
353 | data = Tcl_GetString(objv[3]); |
354 | } else { |
355 | Tcl_WrongNumArgs(interp, 1, objv, "?-charset charset? data"); |
356 | return TCL_ERROR; |
357 | } |
358 | Tcl_DStringInit(&ds); |
359 | if (encode) { |
360 | <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_Ns_EncodeUrlCharset">Ns_EncodeUrlCharset</a>(&ds, data, charset); |
361 | } else { |
362 | <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_Ns_DecodeUrlCharset">Ns_DecodeUrlCharset</a>(&ds, data, charset); |
363 | } |
364 | Tcl_DStringResult(interp, &ds); |
365 | Tcl_DStringFree(&ds); |
366 | return TCL_OK; |
367 | } |
368 | |
369 | int |
370 | <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_NsTclUrlDecodeObjCmd">NsTclUrlDecodeObjCmd</a>(ClientData arg, Tcl_Interp *interp, int objc, |
371 | Tcl_Obj *CONST objv[]) |
372 | { |
373 | return <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_EncodeObjCmd">EncodeObjCmd</a>(interp, objc, objv, 0); |
374 | } |
375 | |
376 | int |
377 | <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_NsTclUrlEncodeObjCmd">NsTclUrlEncodeObjCmd</a>(ClientData arg, Tcl_Interp *interp, int objc, |
378 | Tcl_Obj *CONST objv[]) |
379 | { |
380 | return <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_EncodeObjCmd">EncodeObjCmd</a>(interp, objc, objv, 1); |
381 | } |
382 | |
383 | |
384 | /* |
385 | *---------------------------------------------------------------------- |
386 | * |
387 | * <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_GetUrlEncoding">GetUrlEncoding</a> -- |
388 | * |
389 | * Get the encoding to use in Ns_EncodeUrl/Ns_DecodeUrl, |
390 | * utilizing server defaults for current connection if |
391 | * necessary. |
392 | * |
393 | * Results: |
394 | * A Tcl_Encoding. |
395 | * |
396 | * Side effects: |
397 | * None. |
398 | * |
399 | *---------------------------------------------------------------------- |
400 | */ |
401 | |
402 | static Tcl_Encoding |
403 | <a href="/cvs/aolserver/aolserver/nsd/urlencode.c#A_GetUrlEncoding">GetUrlEncoding</a>(char *charset) |
404 | { |
405 | Tcl_Encoding encoding = NULL; |
406 | Ns_Conn *conn; |
407 | |
408 | if (charset != NULL) { |
409 | encoding = <a href="/cvs/aolserver/aolserver/nsd/encoding.c#A_Ns_GetCharsetEncoding">Ns_GetCharsetEncoding</a>(charset); |
410 | } |
411 | |
412 | /* |
413 | * Use server default for current connection, if any. |
414 | */ |
415 | |
416 | if (encoding == NULL && (conn = <a href="/cvs/aolserver/aolserver/nsd/queue.c#A_Ns_GetConn">Ns_GetConn</a>()) != NULL) { |
417 | encoding = <a href="/cvs/aolserver/aolserver/nsd/conn.c#A_Ns_ConnGetUrlEncoding">Ns_ConnGetUrlEncoding</a>(conn); |
418 | } |
419 | return encoding; |
420 | } |
Copyright © 2010 Geeknet, Inc. All rights reserved. Terms of Use