OLD | NEW |
1 // Copyright (c) 2006, Google Inc. | 1 // Copyright (c) 2006, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 12 matching lines...) Expand all Loading... |
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | 29 |
30 #import "HTTPMultipartUpload.h" | 30 #import "HTTPMultipartUpload.h" |
31 #import "GTMDefines.h" | 31 #import "GTMDefines.h" |
32 | 32 |
33 #include <Availability.h> | |
34 #include <AvailabilityMacros.h> | |
35 | |
36 // As -[NSString stringByAddingPercentEscapesUsingEncoding:] has been | |
37 // deprecated with iOS 9.0 / OS X 10.11 SDKs, this function re-implements it | |
38 // using -[NSString stringByAddingPercentEncodingWithAllowedCharacters:] when | |
39 // using those SDKs. | |
40 static NSString *PercentEncodeNSString(NSString *key) { | |
41 #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_9_0) && \ | |
42 __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_9_0) || \ | |
43 (defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \ | |
44 defined(MAC_OS_X_VERSION_10_11) && \ | |
45 MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11) | |
46 return [key stringByAddingPercentEncodingWithAllowedCharacters: | |
47 [NSCharacterSet alphanumericCharacterSet]]; | |
48 #else | |
49 return [key stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; | |
50 #endif | |
51 } | |
52 | |
53 // As -[NSURLConnection sendSynchronousRequest:returningResponse:error:] has | |
54 // been deprecated with iOS 9.0 / OS X 10.11 SDKs, this function re-implements | |
55 // it using -[NSURLSession dataTaskWithRequest:completionHandler:] when using | |
56 // those SDKs. | |
57 static NSData *SendSynchronousNSURLRequest(NSURLRequest *req, | |
58 NSURLResponse **response, | |
59 NSError **error) { | |
60 #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_9_0) && \ | |
61 __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_9_0) || \ | |
62 (defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \ | |
63 defined(MAC_OS_X_VERSION_10_11) && \ | |
64 MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11) | |
65 __block NSData* result = nil; | |
66 dispatch_semaphore_t wait_semaphone = dispatch_semaphore_create(0); | |
67 [[[NSURLSession sharedSession] | |
68 dataTaskWithRequest:req | |
69 completionHandler:^(NSData *data, NSURLResponse *resp, | |
70 NSError *err) { | |
71 if (error) | |
72 *error = err; | |
73 if (response) | |
74 *response = resp; | |
75 if (err == nil) | |
76 result = data; | |
77 dispatch_semaphore_signal(wait_semaphone); | |
78 }] resume]; | |
79 dispatch_semaphore_wait(wait_semaphone, DISPATCH_TIME_FOREVER); | |
80 dispatch_release(wait_semaphone); | |
81 return result; | |
82 #else | |
83 return [NSURLConnection sendSynchronousRequest:req | |
84 returningResponse:response | |
85 error:error]; | |
86 #endif | |
87 } | |
88 | |
89 @interface HTTPMultipartUpload(PrivateMethods) | 33 @interface HTTPMultipartUpload(PrivateMethods) |
90 - (NSString *)multipartBoundary; | 34 - (NSString *)multipartBoundary; |
91 // Each of the following methods will append the starting multipart boundary, | 35 // Each of the following methods will append the starting multipart boundary, |
92 // but not the ending one. | 36 // but not the ending one. |
93 - (NSData *)formDataForKey:(NSString *)key value:(NSString *)value; | 37 - (NSData *)formDataForKey:(NSString *)key value:(NSString *)value; |
94 - (NSData *)formDataForFileContents:(NSData *)contents name:(NSString *)name; | 38 - (NSData *)formDataForFileContents:(NSData *)contents name:(NSString *)name; |
95 - (NSData *)formDataForFile:(NSString *)file name:(NSString *)name; | 39 - (NSData *)formDataForFile:(NSString *)file name:(NSString *)name; |
96 @end | 40 @end |
97 | 41 |
98 @implementation HTTPMultipartUpload | 42 @implementation HTTPMultipartUpload |
99 //============================================================================= | 43 //============================================================================= |
100 #pragma mark - | 44 #pragma mark - |
101 #pragma mark || Private || | 45 #pragma mark || Private || |
102 //============================================================================= | 46 //============================================================================= |
103 - (NSString *)multipartBoundary { | 47 - (NSString *)multipartBoundary { |
104 // The boundary has 27 '-' characters followed by 16 hex digits | 48 // The boundary has 27 '-' characters followed by 16 hex digits |
105 return [NSString stringWithFormat:@"---------------------------%08X%08X", | 49 return [NSString stringWithFormat:@"---------------------------%08X%08X", |
106 rand(), rand()]; | 50 rand(), rand()]; |
107 } | 51 } |
108 | 52 |
109 //============================================================================= | 53 //============================================================================= |
110 - (NSData *)formDataForKey:(NSString *)key value:(NSString *)value { | 54 - (NSData *)formDataForKey:(NSString *)key value:(NSString *)value { |
111 NSString *escaped = PercentEncodeNSString(key); | 55 NSString *escaped = |
| 56 [key stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; |
112 NSString *fmt = | 57 NSString *fmt = |
113 @"--%@\r\nContent-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n"; | 58 @"--%@\r\nContent-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n"; |
114 NSString *form = [NSString stringWithFormat:fmt, boundary_, escaped, value]; | 59 NSString *form = [NSString stringWithFormat:fmt, boundary_, escaped, value]; |
115 | 60 |
116 return [form dataUsingEncoding:NSUTF8StringEncoding]; | 61 return [form dataUsingEncoding:NSUTF8StringEncoding]; |
117 } | 62 } |
118 | 63 |
119 //============================================================================= | 64 //============================================================================= |
120 - (NSData *)formDataForFileContents:(NSData *)contents name:(NSString *)name { | 65 - (NSData *)formDataForFileContents:(NSData *)contents name:(NSString *)name { |
121 NSMutableData *data = [NSMutableData data]; | 66 NSMutableData *data = [NSMutableData data]; |
122 NSString *escaped = PercentEncodeNSString(name); | 67 NSString *escaped = |
| 68 [name stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; |
123 NSString *fmt = @"--%@\r\nContent-Disposition: form-data; name=\"%@\"; " | 69 NSString *fmt = @"--%@\r\nContent-Disposition: form-data; name=\"%@\"; " |
124 "filename=\"minidump.dmp\"\r\nContent-Type: application/octet-stream\r\n\r\n
"; | 70 "filename=\"minidump.dmp\"\r\nContent-Type: application/octet-stream\r\n\r\n
"; |
125 NSString *pre = [NSString stringWithFormat:fmt, boundary_, escaped]; | 71 NSString *pre = [NSString stringWithFormat:fmt, boundary_, escaped]; |
126 | 72 |
127 [data appendData:[pre dataUsingEncoding:NSUTF8StringEncoding]]; | 73 [data appendData:[pre dataUsingEncoding:NSUTF8StringEncoding]]; |
128 [data appendData:contents]; | 74 [data appendData:contents]; |
129 | 75 |
130 return data; | 76 return data; |
131 } | 77 } |
132 | 78 |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 [req setHTTPMethod:@"POST"]; | 189 [req setHTTPMethod:@"POST"]; |
244 | 190 |
245 [response_ release]; | 191 [response_ release]; |
246 response_ = nil; | 192 response_ = nil; |
247 | 193 |
248 NSData *data = nil; | 194 NSData *data = nil; |
249 if ([[req URL] isFileURL]) { | 195 if ([[req URL] isFileURL]) { |
250 [[req HTTPBody] writeToURL:[req URL] options:0 error:error]; | 196 [[req HTTPBody] writeToURL:[req URL] options:0 error:error]; |
251 } else { | 197 } else { |
252 NSURLResponse *response = nil; | 198 NSURLResponse *response = nil; |
253 data = SendSynchronousNSURLRequest(req, &response, error); | 199 data = [NSURLConnection sendSynchronousRequest:req |
| 200 returningResponse:&response |
| 201 error:error]; |
254 response_ = (NSHTTPURLResponse *)[response retain]; | 202 response_ = (NSHTTPURLResponse *)[response retain]; |
255 } | 203 } |
256 [req release]; | 204 [req release]; |
257 | 205 |
258 return data; | 206 return data; |
259 } | 207 } |
260 | 208 |
261 //============================================================================= | 209 //============================================================================= |
262 - (NSHTTPURLResponse *)response { | 210 - (NSHTTPURLResponse *)response { |
263 return response_; | 211 return response_; |
264 } | 212 } |
265 | 213 |
266 @end | 214 @end |
OLD | NEW |