This repository has been archived by the owner on Jan 3, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 54
/
NSURLRequest+postForm.m
97 lines (83 loc) · 3.4 KB
/
NSURLRequest+postForm.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*******************************************************************************
NSURLRequest+postForm.m
Copyright (c) 2008 Jonathan 'Wolf' Rentzsch: <http://rentzsch.com>
Some rights reserved: <http://opensource.org/licenses/mit-license.php>
***************************************************************************/
#import "NSURLRequest+postForm.h"
#include <unistd.h>
@interface NSMutableData (append)
- (void)appendString:(NSString*)string;
- (void)appendFormat:(NSString *)format, ...;
@end
@implementation NSMutableData (append)
- (void)appendString:(NSString*)string {
[self appendData:[string dataUsingEncoding:NSUTF8StringEncoding]];
}
- (void)appendFormat:(NSString *)format, ... {
va_list args;
va_start(args, format);
NSString *string = [[NSString alloc] initWithFormat:format arguments:args];
va_end(args);
[self appendString:string];
}
@end
@implementation NSURLRequest (postForm)
/*
Generates formData something like this:
--x-mime-boundary://BB2CAC15-E3EC-4B91-9102-68B02AEA5BBB
Content-Disposition: form-data; name="firstName"
Content-Type: text/plain; charset=utf-8
fred
--x-mime-boundary://BB2CAC15-E3EC-4B91-9102-68B02AEA5BBB
Content-Disposition: form-data; name="lastName"
Content-Type: text/plain; charset=utf-8
flintstone
--x-mime-boundary://BB2CAC15-E3EC-4B91-9102-68B02AEA5BBB--
*/
+ (id)requestWithURL:(NSURL*)url postForm:(NSDictionary*)values {
//--
// Create the mime multipart boundary.
// TODO scan `values` to ensure uniqueness of `boundary`. Loop+regen UUID if collision is discovered.
CFUUIDRef cfUuid = CFUUIDCreate(kCFAllocatorDefault);
NSString * uuid = (id)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, cfUuid));
CFRelease(cfUuid);
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
uuid = CFBridgingRelease(CFBridgingRetain(uuid));
#endif
uuid = uuid;
NSString *boundary = [NSString stringWithFormat:@"x-mime-boundary://%@", uuid];
//--
// Create the formData.
NSMutableData *formData = [NSMutableData data];
#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
for (NSString *key in [values allKeys]) {
#else
NSEnumerator *e = [[values allKeys] objectEnumerator];
NSString* key;
while ((key = [e nextObject]) != nil) {
#endif
[formData appendFormat:@"\r\n--%@\r\n", boundary];
// TODO escape keys with quotes in them.
[formData appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n", key];
id value = values[key];
if ([value isKindOfClass:[NSData class]]) {
[formData appendString:@"\r\n"];
[formData appendData:value];
} else if ([value isKindOfClass:[NSString class]]) {
[formData appendFormat:@"Content-Type: text/plain; charset=utf-8\r\n\r\n"];
[formData appendString:value];
} else {
NSAssert1(NO, @"unknown value class: %@", [value className]);
}
}
[formData appendFormat:@"\r\n--%@--\r\n", boundary];
//--
//
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] forHTTPHeaderField:@"Content-Type"];
[request setValue:[NSString stringWithFormat:@"%lu", [formData length]] forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:formData];
return request;
}
@end