2 Copyright (C) 2000-2003 SKYRIX Software AG
4 This file is part of OGo
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
24 #import "NGUrlFormCoder.h"
26 static inline BOOL isURLSafeChar(unsigned char _c) {
27 if ((_c > 64) && (_c < 91))
30 if ((_c > 96) && (_c < 123))
36 if ((_c > 47) && (_c < 58))
42 static inline int _valueOfHexChar(unsigned char _c) {
44 case '0': case '1': case '2': case '3': case '4':
45 case '5': case '6': case '7': case '8': case '9':
46 return (_c - 48); // 0-9 (ascii-char)'0' - 48 => (int)0
48 case 'A': case 'B': case 'C':
49 case 'D': case 'E': case 'F':
50 return (_c - 55); // A-F, A=10..F=15, 'A'=65..'F'=70
52 case 'a': case 'b': case 'c':
53 case 'd': case 'e': case 'f':
54 return (_c - 87); // a-f, a=10..F=15, 'a'=97..'f'=102
61 static inline unsigned _unescapeUrl(const char *_src, unsigned _len, char *_dest) {
62 register unsigned i, i2;
64 for (i = 0, i2 = 0; i < _len; i++, i2++) {
65 register char c = _src[i];
68 case '+': // encoded space
72 case '%': // encoded hex ('%FF')
73 _dest[i2] = _valueOfHexChar(_src[i + 1]) * 16 +
74 _valueOfHexChar(_src[i + 2]);
75 i += 2; // skip the two hexchars
78 default: // normal char
83 return i2; // return unescaped length
86 NGHashMap *NGDecodeUrlFormParameters(const char *_buffer, unsigned _len) {
87 Class StrClass = [NSString class];
88 NGMutableHashMap *dict = nil;
91 if (_len == 0) return nil;
93 dict = [[NGMutableHashMap alloc] initWithCapacity:16];
96 NSString *key = nil, *value = nil;
102 while ((pos < _len) && (_buffer[pos] != '='))
105 len = _unescapeUrl(&(_buffer[tmp]), (pos - tmp), buffer);
107 key = [[StrClass allocWithZone:[dict zone]]
108 initWithCString:buffer length:len];
113 //NSLog(@"read key %@", key);
115 if (pos < _len) { // value pending
116 NSCAssert(_buffer[pos] == '=', @"invalid parser state ..");
121 while ((pos < _len) && (_buffer[pos] != '&') && (_buffer[pos] != '?')) {
125 len = _unescapeUrl(&(_buffer[tmp]), (pos - tmp), buffer);
128 value = [[StrClass allocWithZone:[dict zone]]
129 initWithCString:buffer length:len];
134 //NSLog(@"read value: %@", value);
137 if (_buffer[pos] == '&' || _buffer[pos] == '?') pos++;
143 /* store in dictionary */
145 [dict addObject:value forKey:key];
147 RELEASE(key); key = nil;
148 RELEASE(value); value = nil;
155 @implementation NSString(FormURLCoding)
157 - (NSString *)stringByApplyingURLEncoding {
159 /* NGExtensions/NSString+misc.h */
160 return [self stringByEscapingURL];
165 if ((clen = [self cStringLength]) == 0)
168 buf = malloc(clen + 1);
169 [self getCString:buf]; buf[clen] = '\0';
171 encBuf = malloc(clen * 3 + 1);
173 for (i = 0, j = 0; i < clen; i++) {
174 register unsigned char c = buf[i];
176 if (isURLSafeChar(c)) {
185 sprintf(&(encBuf[j]), "%%%02X", (int)c);
189 return [NSString stringWithCString:encBuf length:j];
190 /* was buggy, does not release encbuf .. */
194 @end /* NSString(FormURLCoding) */