Overview
Comment: | OFURL: Add queryDictionary property |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
a151f9c31ff8145fde562e755af7f369 |
User & Date: | js on 2020-10-03 23:25:55 |
Other Links: | manifest | tags |
Context
2020-10-04
| ||
01:13 | OFURL: Improve nil handling for queryDictionary check-in: a847536ef2 user: js tags: trunk | |
2020-10-03
| ||
23:25 | OFURL: Add queryDictionary property check-in: a151f9c31f user: js tags: trunk | |
21:46 | OFHTTPRequest: Fix handling of remoteAddress check-in: 8d78a77f79 user: js tags: trunk | |
Changes
Modified src/OFMutableURL.h from [814acc8820] to [781d0b7833].
︙ | |||
122 123 124 125 126 127 128 129 130 131 132 133 134 135 | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | + + + + + + + + + + + + + + | * * Setting this retains the original URL-encoding used - if more characters * than necessary are URL-encoded, it is kept this way. */ @property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *URLEncodedQuery; /** * @brief The query part of the URL as a dictionary. * * For example, a query like `key1=value1&key2=value2` would correspond to the * following dictionary: * * @{ * @"key1": "value1", * @"key2": "value2" * } */ @property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFDictionary OF_GENERIC(OFString *, OFString *) *queryDictionary; /** * @brief The fragment part of the URL. */ @property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *fragment; /** * @brief The fragment part of the URL in URL-encoded form. |
︙ |
Modified src/OFMutableURL.m from [1206224cb0] to [714703bda1].
︙ | |||
28 29 30 31 32 33 34 | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | - + + | #import "OFInvalidFormatException.h" extern void of_url_verify_escaped(OFString *, OFCharacterSet *); @implementation OFMutableURL @dynamic scheme, URLEncodedScheme, host, URLEncodedHost, port, user; @dynamic URLEncodedUser, password, URLEncodedPassword, path, URLEncodedPath; |
︙ | |||
228 229 230 231 232 233 234 235 236 237 238 239 240 241 | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | of_url_verify_escaped(URLEncodedQuery, [OFCharacterSet URLQueryAllowedCharacterSet]); old = _URLEncodedQuery; _URLEncodedQuery = [URLEncodedQuery copy]; [old release]; } - (void)setQueryDictionary: (OFDictionary OF_GENERIC(OFString *, OFString *) *)dictionary { void *pool = objc_autoreleasePoolPush(); OFMutableString *URLEncodedQuery = [OFMutableString string]; OFEnumerator *keyEnumerator = [dictionary keyEnumerator]; OFEnumerator *objectEnumerator = [dictionary objectEnumerator]; OFCharacterSet *characterSet = [OFCharacterSet URLQueryKeyValueAllowedCharacterSet]; OFString *key, *object, *old; while ((key = [keyEnumerator nextObject]) != nil && (object = [objectEnumerator nextObject]) != nil) { key = [key stringByURLEncodingWithAllowedCharacters: characterSet]; object = [object stringByURLEncodingWithAllowedCharacters: characterSet]; if (URLEncodedQuery.length > 0) [URLEncodedQuery appendString: @"&"]; [URLEncodedQuery appendFormat: @"%@=%@", key, object]; } old = _URLEncodedQuery; _URLEncodedQuery = [URLEncodedQuery copy]; [old release]; objc_autoreleasePoolPop(pool); } - (void)setFragment: (OFString *)fragment { void *pool = objc_autoreleasePoolPush(); OFString *old = _URLEncodedFragment; _URLEncodedFragment = [[fragment |
︙ |
Modified src/OFURL.h from [7ab8abd7a3] to [125797e09d].
︙ | |||
18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | + | #import "OFObject.h" #import "OFCharacterSet.h" #import "OFSerialization.h" OF_ASSUME_NONNULL_BEGIN @class OFArray OF_GENERIC(ObjectType); @class OFDictionary OF_GENERIC(KeyType, ObjectType); @class OFNumber; @class OFString; /** * @class OFURL OFURL.h ObjFW/OFURL.h * * @brief A class for parsing URLs and accessing parts of it. |
︙ | |||
123 124 125 126 127 128 129 130 131 132 133 134 135 136 | 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | + + + + + + + + + + + + + + | /** * @brief The query part of the URL in URL-encoded form. */ @property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *URLEncodedQuery; /** * @brief The query part of the URL as a dictionary. * * For example, a query like `key1=value1&key2=value2` would correspond to the * following dictionary: * * @{ * @"key1": "value1", * @"key2": "value2" * } */ @property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFDictionary OF_GENERIC(OFString *, OFString *) *queryDictionary; /** * @brief The fragment part of the URL. */ @property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *fragment; /** * @brief The fragment part of the URL in URL-encoded form. |
︙ | |||
286 287 288 289 290 291 292 293 294 295 296 297 298 299 | 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | + + | @property (class, readonly, nonatomic) OFCharacterSet *URLPasswordAllowedCharacterSet; @property (class, readonly, nonatomic) OFCharacterSet *URLPathAllowedCharacterSet; @property (class, readonly, nonatomic) OFCharacterSet *URLQueryAllowedCharacterSet; @property (class, readonly, nonatomic) OFCharacterSet *URLQueryKeyValueAllowedCharacterSet; @property (class, readonly, nonatomic) OFCharacterSet *URLFragmentAllowedCharacterSet; #endif /** * @brief Returns the characters allowed in the scheme part of a URL. * * @return The characters allowed in the scheme part of a URL. |
︙ | |||
331 332 333 334 335 336 337 338 339 340 341 342 343 344 | 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 | + + + + + + + + | /** * @brief Returns the characters allowed in the query part of a URL. * * @return The characters allowed in the query part of a URL. */ + (OFCharacterSet *)URLQueryAllowedCharacterSet; /** * @brief Returns the characters allowed in a key/value in the query part of a * URL. * * @return The characters allowed in a key/value in the query part of a URL. */ + (OFCharacterSet *)URLQueryKeyValueAllowedCharacterSet; /** * @brief Returns the characters allowed in the fragment part of a URL. * * @return The characters allowed in the fragment part of a URL. */ + (OFCharacterSet *)URLFragmentAllowedCharacterSet; @end |
︙ |
Modified src/OFURL.m from [a6ef5631a2] to [529e3fc99f].
︙ | |||
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | + + + + | @end @interface OFURLPathAllowedCharacterSet: OFURLAllowedCharacterSetBase @end @interface OFURLQueryOrFragmentAllowedCharacterSet: OFURLAllowedCharacterSetBase @end @interface OFURLQueryKeyValueAllowedCharacterSet: OFURLAllowedCharacterSetBase @end static OFCharacterSet *URLAllowedCharacterSet = nil; static OFCharacterSet *URLSchemeAllowedCharacterSet = nil; static OFCharacterSet *URLPathAllowedCharacterSet = nil; static OFCharacterSet *URLQueryOrFragmentAllowedCharacterSet = nil; static OFCharacterSet *URLQueryKeyValueAllowedCharacterSet = nil; static of_once_t URLAllowedCharacterSetOnce = OF_ONCE_INIT; static of_once_t URLQueryOrFragmentAllowedCharacterSetOnce = OF_ONCE_INIT; static void initURLAllowedCharacterSet(void) { |
︙ | |||
82 83 84 85 86 87 88 89 90 91 92 93 94 95 | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | + + + + + + + | static void initURLQueryOrFragmentAllowedCharacterSet(void) { URLQueryOrFragmentAllowedCharacterSet = [[OFURLQueryOrFragmentAllowedCharacterSet alloc] init]; } static void initURLQueryKeyValueAllowedCharacterSet(void) { URLQueryKeyValueAllowedCharacterSet = [[OFURLQueryKeyValueAllowedCharacterSet alloc] init]; } OF_DIRECT_MEMBERS @interface OFInvertedCharacterSetWithoutPercent: OFCharacterSet { OFCharacterSet *_characterSet; bool (*_characterIsMember)(id, SEL, of_unichar_t); } |
︙ | |||
245 246 247 248 249 250 251 252 253 254 255 256 257 258 | 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | case '?': return true; default: return false; } } @end @implementation OFURLQueryKeyValueAllowedCharacterSet - (bool)characterIsMember: (of_unichar_t)character { if (character < CHAR_MAX && of_ascii_isalnum(character)) return true; switch (character) { case '-': case '.': case '_': case '~': case '!': case '$': case '\'': case '(': case ')': case '*': case '+': case ',': case ';': case ':': case '@': case '/': case '?': return true; default: return false; } } @end @implementation OFInvertedCharacterSetWithoutPercent - (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet { self = [super init]; @try { |
︙ | |||
337 338 339 340 341 342 343 344 345 346 347 348 349 350 | 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 | + + + + + + + + | + (OFCharacterSet *)URLQueryAllowedCharacterSet { of_once(&URLQueryOrFragmentAllowedCharacterSetOnce, initURLQueryOrFragmentAllowedCharacterSet); return URLQueryOrFragmentAllowedCharacterSet; } + (OFCharacterSet *)URLQueryKeyValueAllowedCharacterSet { static of_once_t onceControl = OF_ONCE_INIT; of_once(&onceControl, initURLQueryKeyValueAllowedCharacterSet); return URLQueryKeyValueAllowedCharacterSet; } + (OFCharacterSet *)URLFragmentAllowedCharacterSet { of_once(&URLQueryOrFragmentAllowedCharacterSetOnce, initURLQueryOrFragmentAllowedCharacterSet); return URLQueryOrFragmentAllowedCharacterSet; |
︙ | |||
981 982 983 984 985 986 987 988 989 990 991 992 993 994 | 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 | + + + + + + + + + + + + + + + + + + + + + + + + + | return _URLEncodedQuery.stringByURLDecoding; } - (OFString *)URLEncodedQuery { return _URLEncodedQuery; } - (OFDictionary OF_GENERIC(OFString *, OFString *) *)queryDictionary { void *pool = objc_autoreleasePoolPush(); OFArray *pairs = [_URLEncodedQuery componentsSeparatedByString: @"&"]; OFMutableDictionary *ret = [OFMutableDictionary dictionaryWithCapacity: pairs.count]; for (OFString *pair in pairs) { OFArray *parts = [pair componentsSeparatedByString: @"="]; if (parts.count != 2) @throw [OFInvalidFormatException exception]; [ret setObject: [[parts objectAtIndex: 1] stringByURLDecoding] forKey: [[parts objectAtIndex: 0] stringByURLDecoding]]; } [ret makeImmutable]; [ret retain]; objc_autoreleasePoolPop(pool); return [ret autorelease]; } - (OFString *)fragment { return _URLEncodedFragment.stringByURLDecoding; } - (OFString *)URLEncodedFragment |
︙ |
Modified tests/OFURLTests.m from [52cea266a3] to [307ed6832b].
︙ | |||
17 18 19 20 21 22 23 | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | - + | #include "config.h" #import "TestsAppDelegate.h" static OFString *module = @"OFURL"; static OFString *url_str = @"ht%3atp://us%3Aer:p%40w@ho%3Ast:1234/" |
︙ | |||
174 175 176 177 178 179 180 | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | - + + + + + | lastPathComponent] isEqual: @"baz"] && [[[OFURL URLWithString: @"http://host/foo/"] lastPathComponent] isEqual: @"foo"] && [[[OFURL URLWithString: @"http://host/"] lastPathComponent] isEqual: @"/"] && [u5.lastPathComponent isEqual: @"foo/bar"]) TEST(@"-[query]", |
︙ | |||
265 266 267 268 269 270 271 272 273 274 275 276 277 278 | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | + + + + + + | (mu.URLEncodedQuery = @"que/ry?%23") && [mu.query isEqual: @"que/ry?#"]) EXPECT_EXCEPTION( @"-[setURLEncodedQuery:] with invalid characters fails", OFInvalidFormatException, mu.URLEncodedQuery = @"`") TEST(@"-[setQueryDictionary:]", (mu.queryDictionary = [OFDictionary dictionaryWithKeysAndObjects: @"foo&bar", @"baz=qux", @"f=oobar", @"b&azqux", nil]) && [mu.URLEncodedQuery isEqual: @"foo%26bar=baz%3Dqux&f%3Doobar=b%26azqux"]) TEST(@"-[setFragment:]", (mu.fragment = @"frag/ment?#") && [mu.URLEncodedFragment isEqual: @"frag/ment?%23"]) TEST(@"-[setURLEncodedFragment:]", (mu.URLEncodedFragment = @"frag/ment?%23") && [mu.fragment isEqual: @"frag/ment?#"]) |
︙ |