Overview
Comment: | Make OFURL more generic
This removes the special handling dependent on the scheme. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
0f995db06de3e97300ccfb67be50d770 |
User & Date: | js on 2017-10-28 21:08:37 |
Other Links: | manifest | tags |
Context
2017-10-28
| ||
21:26 | OFFileManager: Add -[currentDirectoryURL] check-in: 9713afbd6d user: js tags: trunk | |
21:08 | Make OFURL more generic check-in: 0f995db06d user: js tags: trunk | |
2017-10-24
| ||
22:07 | Update buildsys check-in: f529511190 user: js tags: trunk | |
Changes
Modified src/OFHTTPClient.m from [3d2d594ca8] to [b30a887ade].
︙ | ︙ | |||
18 19 20 21 22 23 24 25 26 | #include "config.h" #include <errno.h> #include <string.h> #import "OFHTTPClient.h" #import "OFHTTPRequest.h" #import "OFHTTPResponse.h" | > > | | < | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #include "config.h" #include <errno.h> #include <string.h> #import "OFHTTPClient.h" #import "OFData.h" #import "OFDictionary.h" #import "OFHTTPRequest.h" #import "OFHTTPResponse.h" #import "OFNumber.h" #import "OFString.h" #import "OFTCPSocket.h" #import "OFURL.h" #import "OFAlreadyConnectedException.h" #import "OFHTTPRequestFailedException.h" #import "OFInvalidEncodingException.h" #import "OFInvalidFormatException.h" #import "OFInvalidServerReplyException.h" #import "OFNotImplementedException.h" |
︙ | ︙ | |||
78 79 80 81 82 83 84 | static OFString * constructRequestString(OFHTTPRequest *request) { void *pool = objc_autoreleasePoolPush(); of_http_request_method_t method = [request method]; OFURL *URL = [request URL]; | | | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | static OFString * constructRequestString(OFHTTPRequest *request) { void *pool = objc_autoreleasePoolPush(); of_http_request_method_t method = [request method]; OFURL *URL = [request URL]; OFString *path = [URL path]; OFString *user = [URL user], *password = [URL password]; OFData *body = [request body]; OFMutableString *requestString; OFMutableDictionary OF_GENERIC(OFString *, OFString *) *headers; OFEnumerator OF_GENERIC(OFString *) *keyEnumerator, *objectEnumerator; OFString *key, *object; |
︙ | ︙ | |||
106 107 108 109 110 111 112 | [requestString appendString: @"\r\n"]; headers = [[[request headers] mutableCopy] autorelease]; if (headers == nil) headers = [OFMutableDictionary dictionary]; if ([headers objectForKey: @"Host"] == nil) { | | | > | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | [requestString appendString: @"\r\n"]; headers = [[[request headers] mutableCopy] autorelease]; if (headers == nil) headers = [OFMutableDictionary dictionary]; if ([headers objectForKey: @"Host"] == nil) { OFNumber *port = [URL port]; if (port != nil) { OFString *host = [OFString stringWithFormat: @"%@:%@", [URL host], port]; [headers setObject: host forKey: @"Host"]; } else [headers setObject: [URL host] forKey: @"Host"]; } |
︙ | ︙ | |||
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 | [self closeAndReconnect]; } - (void)closeAndReconnect { OFURL *URL = [_request URL]; OFTCPSocket *sock; [_client close]; if ([[URL scheme] isEqual: @"https"]) { if (of_tls_socket_class == Nil) @throw [OFUnsupportedProtocolException exceptionWithURL: URL]; sock = [[[of_tls_socket_class alloc] init] autorelease]; | > > > | > | > > > > > | | 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 | [self closeAndReconnect]; } - (void)closeAndReconnect { OFURL *URL = [_request URL]; OFTCPSocket *sock; uint16_t port; OFNumber *URLPort; [_client close]; if ([[URL scheme] isEqual: @"https"]) { if (of_tls_socket_class == Nil) @throw [OFUnsupportedProtocolException exceptionWithURL: URL]; sock = [[[of_tls_socket_class alloc] init] autorelease]; port = 443; } else { sock = [OFTCPSocket socket]; port = 80; } URLPort = [URL port]; if (URLPort != nil) port = [URLPort uInt16Value]; [sock asyncConnectToHost: [URL host] port: port target: self selector: @selector(socketDidConnect:context: exception:) context: nil]; } @end |
︙ | ︙ |
Modified src/OFHTTPServer.m from [a75e2ea261] to [380d4e5179].
︙ | ︙ | |||
19 20 21 22 23 24 25 | #include <stdlib.h> #include <string.h> #import "OFHTTPServer.h" #import "OFData.h" #import "OFDate.h" #import "OFDictionary.h" | | | | > | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include <stdlib.h> #include <string.h> #import "OFHTTPServer.h" #import "OFData.h" #import "OFDate.h" #import "OFDictionary.h" #import "OFHTTPRequest.h" #import "OFHTTPResponse.h" #import "OFNumber.h" #import "OFTCPSocket.h" #import "OFTimer.h" #import "OFURL.h" #import "OFAlreadyConnectedException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFNotOpenException.h" #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" |
︙ | ︙ | |||
650 651 652 653 654 655 656 | _host = [[_server host] retain]; _port = [_server port]; } URL = [OFMutableURL URL]; [URL setScheme: @"http"]; [URL setHost: _host]; | > | | 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 | _host = [[_server host] retain]; _port = [_server port]; } URL = [OFMutableURL URL]; [URL setScheme: @"http"]; [URL setHost: _host]; if (_port != 80) [URL setPort: [OFNumber numberWithUInt16: _port]]; if ((pos = [_path rangeOfString: @"?"].location) != OF_NOT_FOUND) { OFString *path, *query; path = [_path substringWithRange: of_range(0, pos)]; query = [_path substringWithRange: of_range(pos + 1, [_path length] - pos - 1)]; |
︙ | ︙ |
Modified src/OFMutableURL.h from [d41b6f1dcf] to [5b759a7789].
︙ | ︙ | |||
23 24 25 26 27 28 29 | * * @brief A class for parsing URLs and accessing parts of it. */ @interface OFMutableURL: OFURL /*! * The scheme part of the URL. */ | | | | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | * * @brief A class for parsing URLs and accessing parts of it. */ @interface OFMutableURL: OFURL /*! * The scheme part of the URL. */ @property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *scheme; /*! * The host part of the URL. */ @property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *host; /*! * The port part of the URL. */ @property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFNumber *port; /*! * The user part of the URL. */ @property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *user; /*! * The password part of the URL. */ @property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *password; /*! * The path part of the URL. */ @property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *path; /*! * The parameters part of the URL. */ @property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *parameters; |
︙ | ︙ |
Modified src/OFMutableURL.m from [aa49ba568a] to [514dff27bb].
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | * file. */ #include "config.h" #import "OFMutableURL.h" #import "OFURL+Private.h" #import "OFString.h" @implementation OFMutableURL @dynamic scheme, host, port, user, password, path, parameters, query, fragment; + (instancetype)URL { | > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | * file. */ #include "config.h" #import "OFMutableURL.h" #import "OFURL+Private.h" #import "OFNumber.h" #import "OFString.h" @implementation OFMutableURL @dynamic scheme, host, port, user, password, path, parameters, query, fragment; + (instancetype)URL { |
︙ | ︙ | |||
43 44 45 46 47 48 49 | - (void)setHost: (OFString *)host { OFString *old = _host; _host = [host copy]; [old release]; } | | > | > | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | - (void)setHost: (OFString *)host { OFString *old = _host; _host = [host copy]; [old release]; } - (void)setPort: (OFNumber *)port { OFNumber *old = _port; _port = [port copy]; [old release]; } - (void)setUser: (OFString *)user { OFString *old = _user; _user = [user copy]; [old release]; |
︙ | ︙ |
Modified src/OFURL.h from [c55211ca68] to [eee6f35b3b].
︙ | ︙ | |||
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | */ #import "OFObject.h" #import "OFSerialization.h" OF_ASSUME_NONNULL_BEGIN @class OFString; /*! * @class OFURL OFURL.h ObjFW/OFURL.h * * @brief A class for parsing URLs and accessing parts of it. */ @interface OFURL: OFObject <OFCopying, OFMutableCopying, OFSerialization> { | > | | | | | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | */ #import "OFObject.h" #import "OFSerialization.h" OF_ASSUME_NONNULL_BEGIN @class OFNumber; @class OFString; /*! * @class OFURL OFURL.h ObjFW/OFURL.h * * @brief A class for parsing URLs and accessing parts of it. */ @interface OFURL: OFObject <OFCopying, OFMutableCopying, OFSerialization> { OFString *_Nullable _scheme, *_Nullable _host; OFNumber *_Nullable _port; OFString *_Nullable _user, *_Nullable _password, *_path; OFString *_Nullable _parameters, *_Nullable _query; OFString *_Nullable _fragment; } /*! * The scheme part of the URL. */ @property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *scheme; /*! * The host part of the URL. */ @property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *host; /*! * The port part of the URL. */ @property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFNumber *port; /*! * The user part of the URL. */ @property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *user; /*! * The password part of the URL. */ @property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *password; /*! * The path part of the URL. */ @property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *path; /*! * The parameters part of the URL. */ @property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *parameters; /*! |
︙ | ︙ |
Modified src/OFURL.m from [bc22950fc0] to [6274573b21].
︙ | ︙ | |||
17 18 19 20 21 22 23 | #include "config.h" #include <stdlib.h> #include <string.h> #import "OFURL.h" #import "OFURL+Private.h" | | | > | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #include "config.h" #include <stdlib.h> #include <string.h> #import "OFURL.h" #import "OFURL+Private.h" #import "OFArray.h" #import "OFNumber.h" #import "OFString.h" #import "OFXMLElement.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFOutOfMemoryException.h" @implementation OFURL |
︙ | ︙ | |||
85 86 87 88 89 90 91 | if ((UTF8String2 = of_strdup([string UTF8String])) == NULL) @throw [OFOutOfMemoryException exceptionWithRequestedSize: [string UTF8StringLength]]; UTF8String = UTF8String2; | > > | > < < < < < < < < | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | if ((UTF8String2 = of_strdup([string UTF8String])) == NULL) @throw [OFOutOfMemoryException exceptionWithRequestedSize: [string UTF8StringLength]]; UTF8String = UTF8String2; if ((tmp = strchr(UTF8String, ':')) == NULL) @throw [OFInvalidFormatException exception]; if (strncmp(tmp, "://", 3) != 0) @throw [OFInvalidFormatException exception]; for (tmp2 = UTF8String; tmp2 < tmp; tmp2++) *tmp2 = of_ascii_tolower(*tmp2); _scheme = [[OFString alloc] initWithUTF8String: UTF8String length: tmp - UTF8String]; UTF8String = tmp + 3; if ((tmp = strchr(UTF8String, '/')) != NULL) { *tmp = '\0'; tmp++; } if ((tmp2 = strchr(UTF8String, '@')) != NULL) { char *tmp3; |
︙ | ︙ | |||
147 148 149 150 151 152 153 | pool2 = objc_autoreleasePoolPush(); portString = [OFString stringWithUTF8String: tmp2]; if ([portString decimalValue] > 65535) @throw [OFInvalidFormatException exception]; | > | | < < < < < < < < | 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | pool2 = objc_autoreleasePoolPush(); portString = [OFString stringWithUTF8String: tmp2]; if ([portString decimalValue] > 65535) @throw [OFInvalidFormatException exception]; _port = [[OFNumber alloc] initWithUInt16: (uint16_t)[portString decimalValue]]; objc_autoreleasePoolPop(pool2); } else _host = [[OFString alloc] initWithUTF8String: UTF8String]; if ((UTF8String = tmp) != NULL) { if ((tmp = strchr(UTF8String, '#')) != NULL) { *tmp = '\0'; _fragment = [[OFString alloc] initWithUTF8String: tmp + 1]; } |
︙ | ︙ | |||
218 219 220 221 222 223 224 | @try { void *pool = objc_autoreleasePoolPush(); char *tmp; _scheme = [URL->_scheme copy]; _host = [URL->_host copy]; | | | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | @try { void *pool = objc_autoreleasePoolPush(); char *tmp; _scheme = [URL->_scheme copy]; _host = [URL->_host copy]; _port = [URL->_port copy]; _user = [URL->_user copy]; _password = [URL->_password copy]; if ((UTF8String2 = of_strdup([string UTF8String])) == NULL) @throw [OFOutOfMemoryException exceptionWithRequestedSize: [string UTF8StringLength]]; |
︙ | ︙ | |||
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | return self; } - (void)dealloc { [_scheme release]; [_host release]; [_user release]; [_password release]; [_path release]; [_parameters release]; [_query release]; [_fragment release]; [super dealloc]; } - (bool)isEqual: (id)object { OFURL *URL; if (![object isKindOfClass: [OFURL class]]) return false; URL = object; | > | | | | < | | < | < < | | 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 | return self; } - (void)dealloc { [_scheme release]; [_host release]; [_port release]; [_user release]; [_password release]; [_path release]; [_parameters release]; [_query release]; [_fragment release]; [super dealloc]; } - (bool)isEqual: (id)object { OFURL *URL; if (![object isKindOfClass: [OFURL class]]) return false; URL = object; if (URL->_scheme != _scheme && ![URL->_scheme isEqual: _scheme]) return false; if (URL->_host != _host && ![URL->_host isEqual: _host]) return false; if (URL->_port != _port && ![URL->_port isEqual: _port]) return false; if (URL->_user != _user && ![URL->_user isEqual: _user]) return false; if (URL->_password != _password && ![URL->_password isEqual: _password]) return false; if (URL->_path != _path && ![URL->_path isEqual: _path]) return false; if (URL->_parameters != _parameters && ![URL->_parameters isEqual: _parameters]) return false; if (URL->_query != _query && ![URL->_query isEqual: _query]) return false; if (URL->_fragment != _fragment && ![URL->_fragment isEqual: _fragment]) return false; return true; } - (uint32_t)hash { uint32_t hash; OF_HASH_INIT(hash); OF_HASH_ADD_HASH(hash, [_scheme hash]); OF_HASH_ADD_HASH(hash, [_host hash]); OF_HASH_ADD_HASH(hash, [_port hash]); OF_HASH_ADD_HASH(hash, [_user hash]); OF_HASH_ADD_HASH(hash, [_password hash]); OF_HASH_ADD_HASH(hash, [_path hash]); OF_HASH_ADD_HASH(hash, [_parameters hash]); OF_HASH_ADD_HASH(hash, [_query hash]); OF_HASH_ADD_HASH(hash, [_fragment hash]); |
︙ | ︙ | |||
377 378 379 380 381 382 383 | } - (OFString *)host { return _host; } | | | 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | } - (OFString *)host { return _host; } - (OFNumber *)port { return _port; } - (OFString *)user { return _user; |
︙ | ︙ | |||
446 447 448 449 450 451 452 | - (OFString *)string { OFMutableString *ret = [OFMutableString string]; void *pool = objc_autoreleasePoolPush(); [ret appendFormat: @"%@://", _scheme]; | < < < < < < < < | < < < | | 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | - (OFString *)string { OFMutableString *ret = [OFMutableString string]; void *pool = objc_autoreleasePoolPush(); [ret appendFormat: @"%@://", _scheme]; if (_user != nil && _password != nil) [ret appendFormat: @"%@:%@@", _user, _password]; else if (_user != nil) [ret appendFormat: @"%@@", _user]; if (_host != nil) [ret appendString: _host]; if (_port != nil) [ret appendFormat: @":%@", _port]; if (_path != nil) { if (![_path hasPrefix: @"/"]) @throw [OFInvalidFormatException exception]; [ret appendString: _path]; } |
︙ | ︙ |
Modified tests/OFStringTests.m from [33bc7fca89] to [e5125c6f6a].
︙ | ︙ | |||
355 356 357 358 359 360 361 | #ifdef OF_HAVE_FILES TEST(@"+[stringWithContentsOfFile:encoding]", (is = [stringClass stringWithContentsOfFile: @"testfile.txt" encoding: OF_STRING_ENCODING_ISO_8859_1]) && [is isEqual: @"testäöü"]) TEST(@"+[stringWithContentsOfURL:encoding]", (is = [stringClass | | < | 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 | #ifdef OF_HAVE_FILES TEST(@"+[stringWithContentsOfFile:encoding]", (is = [stringClass stringWithContentsOfFile: @"testfile.txt" encoding: OF_STRING_ENCODING_ISO_8859_1]) && [is isEqual: @"testäöü"]) TEST(@"+[stringWithContentsOfURL:encoding]", (is = [stringClass stringWithContentsOfURL: [OFURL fileURLWithPath: @"testfile.txt"] encoding: OF_STRING_ENCODING_ISO_8859_1]) && [is isEqual: @"testäöü"]) #endif TEST(@"-[appendUTFString:length:]", R([s[0] appendUTF8String: "foo\xEF\xBB\xBF" "barqux" + 3 length: 6]) && [s[0] isEqual: @"foobar"]) |
︙ | ︙ |
Modified tests/OFURLTests.m from [b43f4c978f] to [26f206153b].
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 | * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" #import "OFURL.h" #import "OFString.h" #import "OFAutoreleasePool.h" #import "OFInvalidFormatException.h" #import "TestsAppDelegate.h" | > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" #import "OFURL.h" #import "OFNumber.h" #import "OFString.h" #import "OFAutoreleasePool.h" #import "OFInvalidFormatException.h" #import "TestsAppDelegate.h" |
︙ | ︙ | |||
51 52 53 54 55 56 57 | relativeToURL: [OFURL URLWithString: @"http://h/qux/?x"]] string] isEqual: @"http://h/qux/foo/bar"] && [[[OFURL URLWithString: @"http://foo/?q" relativeToURL: u1] string] isEqual: @"http://foo/?q"]) TEST(@"-[string]", [[u1 string] isEqual: url_str] && | | | | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | relativeToURL: [OFURL URLWithString: @"http://h/qux/?x"]] string] isEqual: @"http://h/qux/foo/bar"] && [[[OFURL URLWithString: @"http://foo/?q" relativeToURL: u1] string] isEqual: @"http://foo/?q"]) TEST(@"-[string]", [[u1 string] isEqual: url_str] && [[u2 string] isEqual: @"http://foo:80"] && [[u3 string] isEqual: @"http://bar/"] && [[u4 string] isEqual: @"file:///etc/passwd"]) TEST(@"-[scheme]", [[u1 scheme] isEqual: @"ht%3atp"] && [[u4 scheme] isEqual: @"file"]) TEST(@"-[user]", [[u1 user] isEqual: @"us%3Aer"] && [u4 user] == nil) TEST(@"-[password]", [[u1 password] isEqual: @"p%40w"] && [u4 password] == nil) TEST(@"-[host]", [[u1 host] isEqual: @"ho%3Ast"] && [u4 port] == 0) TEST(@"-[port]", [[u1 port] isEqual: [OFNumber numberWithUInt16: 1234]]) TEST(@"-[path]", [[u1 path] isEqual: @"/pa%3Bth"] && [[u4 path] isEqual: @"/etc/passwd"]) TEST(@"-[parameters]", [[u1 parameters] isEqual: @"pa%3Fram"] && [u4 parameters] == nil) TEST(@"-[query]", [[u1 query] isEqual: @"que%23ry"] && [u4 query] == nil) |
︙ | ︙ |
Modified tests/serialization.xml from [6c06fe27b7] to [9ca884a2b7].
︙ | ︙ | |||
35 36 37 38 39 40 41 | </OFCountedSet> </OFList> </key> <object> <OFString>list</OFString> </object> <key> | < < < < < < > > > > > > | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | </OFCountedSet> </OFList> </key> <object> <OFString>list</OFString> </object> <key> <OFArray> <OFString>Qu"xbar test</OFString> <OFNumber type='signed'>1234</OFNumber> <OFNumber type='double'>40934a456d5cfaad</OFNumber> <OFMutableString>asd</OFMutableString> <OFDate>40934a456d5cfaad</OFDate> </OFArray> </key> <object> <OFString>Hello</OFString> </object> <key> <OFData>MDEyMzQ1Njc4OTo7PEFCQ0RFRkdISklLTE1OT1BRUlNUVVZXWFla</OFData> </key> <object> <OFString>data</OFString> </object> </OFMutableDictionary> </serialization> |