├── .gitignore ├── BBHTTP.podspec ├── BBHTTP ├── BBHTTP.h ├── BBHTTPExecutor.h ├── BBHTTPExecutor.m ├── BBHTTPRequest+Convenience.h ├── BBHTTPRequest+Convenience.m ├── BBHTTPRequest.h ├── BBHTTPRequest.m ├── BBHTTPResponse.h ├── BBHTTPResponse.m ├── Handlers │ ├── BBHTTPAccumulator.h │ ├── BBHTTPAccumulator.m │ ├── BBHTTPContentHandler.h │ ├── BBHTTPFileWriter.h │ ├── BBHTTPFileWriter.m │ ├── BBHTTPImageDecoder.h │ ├── BBHTTPImageDecoder.m │ ├── BBHTTPSelectiveDiscarder.h │ ├── BBHTTPSelectiveDiscarder.m │ ├── BBHTTPStreamWriter.h │ ├── BBHTTPStreamWriter.m │ ├── BBHTTPToStringConverter.h │ ├── BBHTTPToStringConverter.m │ ├── BBJSONParser.h │ └── BBJSONParser.m └── Internal │ ├── BBHTTPRequest+PrivateInterface.h │ ├── BBHTTPRequest+PrivateInterface.m │ ├── BBHTTPRequestContext.h │ ├── BBHTTPRequestContext.m │ ├── BBHTTPUtils.h │ ├── BBHTTPUtils.m │ ├── BBJSONDictionary.h │ └── BBJSONDictionary.m ├── CHANGES.md ├── Docs ├── generate └── index.md ├── Example ├── OSX Sample app │ ├── Classes │ │ ├── AppDelegate.h │ │ └── AppDelegate.m │ └── Supporting Files │ │ ├── OSX Sample app-Info.plist │ │ ├── OSX Sample app-Prefix.pch │ │ ├── en.lproj │ │ ├── InfoPlist.strings │ │ └── MainMenu.xib │ │ └── main.m └── iOS Sample app │ ├── Classes │ ├── AppDelegate.h │ └── AppDelegate.m │ ├── Resources │ ├── Default-568h@2x.png │ ├── Default.png │ └── Default@2x.png │ └── Supporting Files │ ├── en.lproj │ └── InfoPlist.strings │ ├── iOS Sample app-Info.plist │ ├── iOS Sample app-Prefix.pch │ └── main.m ├── External ├── libcurl.OSX │ ├── curl.h │ ├── curlbuild.h │ ├── curlrules.h │ ├── curlver.h │ ├── easy.h │ ├── libcurl.OSX.a │ ├── mprintf.h │ ├── multi.h │ ├── stdcheaders.h │ └── typecheck-gcc.h └── libcurl.iOS │ ├── curl.h │ ├── curlbuild.h │ ├── curlrules.h │ ├── curlver.h │ ├── easy.h │ ├── libcurl.iOS.appstore.a │ ├── libcurl.iOS.dev.a │ ├── mprintf.h │ ├── multi.h │ ├── stdcheaders.h │ └── typecheck-gcc.h ├── LICENSE ├── Project ├── BBHTTP.OSX-Prefix.pch ├── BBHTTP.iOS-Prefix.pch ├── BBHTTP.xcodeproj │ └── project.pbxproj ├── build-configuration.properties └── build.xml ├── README.md └── Unit Tests ├── BBHTTPRequestTests.m └── Supporting Files ├── Unit Tests-Info.plist ├── Unit Tests-Prefix.pch └── en.lproj └── InfoPlist.strings /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | xcuserdata 3 | project.xcworkspace 4 | .idea 5 | Docs/html 6 | -------------------------------------------------------------------------------- /BBHTTP.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "BBHTTP" 3 | s.version = "0.9.9" 4 | s.summary = "A modern HTTP client framework for iOS/OSX built on top of libcurl." 5 | s.homepage = "https://github.com/brunodecarvalho/BBHTTP" 6 | s.license = { :type => "Apache License, Version 2.0", :file => "LICENSE" } 7 | s.author = { "Bruno de Carvalho" => "bruno@biasedbit.com" } 8 | s.source = { :git => "https://github.com/brunodecarvalho/BBHTTP.git", :tag => "0.9.9" } 9 | 10 | s.requires_arc = true 11 | s.source_files = "BBHTTP/**/*.{h,m}" 12 | 13 | s.ios.deployment_target = "5.0" 14 | s.ios.preserve_paths = "External/libcurl.iOS" 15 | s.ios.frameworks = %w{ MobileCoreServices Security UIKit } 16 | s.ios.libraries = %w{ z curl.iOS.dev } 17 | s.ios.xcconfig = { 18 | "HEADER_SEARCH_PATHS" => '"${PODS_ROOT}/BBHTTP/External/libcurl.iOS"', 19 | "LIBRARY_SEARCH_PATHS" => '"${PODS_ROOT}/BBHTTP/External/libcurl.iOS"' 20 | } 21 | 22 | s.osx.deployment_target = "10.7" 23 | s.osx.preserve_paths = "External/libcurl.OSX" 24 | s.osx.frameworks = %w{ Security CoreServices AppKit } 25 | s.osx.libraries = %w{ z curl.OSX } 26 | s.osx.xcconfig = { 27 | "HEADER_SEARCH_PATHS" => '"${PODS_ROOT}/BBHTTP/External/libcurl.OSX"', 28 | "LIBRARY_SEARCH_PATHS" => '"${PODS_ROOT}/BBHTTP/External/libcurl.OSX"' 29 | } 30 | 31 | s.prefix_header_contents = <<-PREFIXHEADER 32 | #import 33 | 34 | #if __IPHONE_OS_VERSION_MIN_REQUIRED 35 | #import 36 | #else 37 | #import 38 | #endif 39 | PREFIXHEADER 40 | end 41 | -------------------------------------------------------------------------------- /BBHTTP/BBHTTP.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #ifndef __BBHTTP 23 | #define __BBHTTP 24 | 25 | #import "BBHTTPExecutor.h" 26 | #import "BBHTTPRequest+Convenience.h" 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /BBHTTP/BBHTTPExecutor.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | @class BBHTTPRequest; 23 | @class BBHTTPResponse; 24 | 25 | 26 | 27 | #pragma mark - 28 | 29 | /** 30 | The `BBHTTPExecutor` class is a request executor and queue manager that takes `` instances and translates 31 | them for execution on the underlying libcurl infrastructure. 32 | 33 | It can be seen as a `NSOperationQueue` on which you enqueue operations — or, in this case, http requests. 34 | 35 | Given that each executor instance has little configuration and that configuration can safely be changed, using the 36 | [singleton]() is perfectly reasonable — encouraged, even. 37 | 38 | ### Request queuing and execution 39 | 40 | Whenever you submit a request, it will either be immediately executed or queued, depending on the number of active 41 | requests at the instant of submission. 42 | 43 | Submitted requests are strongly held (retain semantics) until their execution is terminated — either normally or 44 | abnormally — and the appropriate delegate blocks are called. 45 | 46 | At any time you may cancel a request. A queued request that is cancelled while still in the queue will remain in the 47 | queue (with the `cancel` flag set to `YES`) until it is extracted for execution, at which point it is simply discarded. 48 | Assuming no other strong references to the request are kept, it will be `dealloc`'d at this time. 49 | 50 | ### libcurl handle pooling 51 | 52 | Each instance will create up to `` libcurl handles to execute requests, depending on number of 53 | parallel requests that may need to be performed. In other words, if you set the limit of libcurl handles to 3 but 54 | never execute more than one request at a time, the instance will only create and maintain a single handle. 55 | 56 | When all the handles are in use, request will be queued and executed later in time, in the first handle that frees up. 57 | 58 | ### libcurl handle setup 59 | 60 | Every time a request is executed, the handle is completely reconfigured and, upon termination, reset. This means that 61 | you can safely perform all sorts of requests to different hosts under the same `BBHTTPExecutor` instance. 62 | */ 63 | @interface BBHTTPExecutor : NSObject 64 | 65 | 66 | #pragma mark Creating an instance 67 | 68 | ///--------------------------- 69 | /// @name Creating an instance 70 | ///--------------------------- 71 | 72 | /** 73 | Creates a new instace with the given unique identifier. 74 | 75 | @param identifier Unique identifier. 76 | 77 | @return An initialized `BBHTTPExecutor` with a unique *identifier*. 78 | */ 79 | - (instancetype)initWithId:(NSString*)identifier; 80 | 81 | /** 82 | Returns a singleton `BBHTTPExecutor` 83 | 84 | @return A `BBHTTPExecutor` singleton. 85 | */ 86 | + (instancetype)sharedExecutor; 87 | 88 | 89 | #pragma mark Configuring behavior 90 | 91 | ///--------------------------- 92 | /// @name Configuring behavior 93 | ///--------------------------- 94 | 95 | /** 96 | Determines the maximum number of maximum parallel requests that can be executed. 97 | 98 | This value controls the number of libcurl handles that this instance can pool. All instances begin with zero handles 99 | and ramp them up, as required, until this number is hit. 100 | 101 | Defaults to 3, minimum allowed value is 1. 102 | */ 103 | @property(assign, nonatomic) NSUInteger maxParallelRequests; 104 | 105 | /** 106 | The maximum number of requests that can be queued until others finish. 107 | 108 | Defaults to 1024. 109 | */ 110 | @property(assign, nonatomic) NSUInteger maxQueueSize; 111 | 112 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 113 | @property(assign, nonatomic) BOOL manageNetworkActivityIndicator; 114 | #endif 115 | 116 | /** For debug/bug-reporting purposes only; this turns on verbose mode for the underlying libcurl handles. */ 117 | @property(assign, nonatomic) BOOL verbose; 118 | /** Opens and closes a connection for each request. */ 119 | @property(assign, nonatomic) BOOL dontReuseConnections; 120 | 121 | 122 | #pragma mark Executing requests 123 | 124 | ///------------------------- 125 | /// @name Executing requests 126 | ///------------------------- 127 | 128 | 129 | /** 130 | Executes or enqueues a request for execution. 131 | 132 | @param request The request to execute. 133 | 134 | @return `YES` if the request can be executed/enqueued, `NO` if the request was rejected. 135 | 136 | Requests may be rejected if the execution queue grows too large or if the request itself is invalid (`nil` or already 137 | cancelled). 138 | */ 139 | - (BOOL)executeRequest:(BBHTTPRequest*)request; 140 | 141 | 142 | #pragma mark Cleanup 143 | 144 | + (void)cleanup; 145 | 146 | @end 147 | -------------------------------------------------------------------------------- /BBHTTP/BBHTTPRequest+Convenience.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPRequest.h" 23 | 24 | 25 | 26 | #pragma mark - 27 | 28 | @interface BBHTTPRequest (Convenience) 29 | 30 | 31 | #pragma mark Creating common requests 32 | 33 | ///------------------------------- 34 | /// @name Creating common requests 35 | ///------------------------------- 36 | 37 | #pragma mark      Create (POST) 38 | 39 | /** 40 | Creates a `POST` request to the target url, with the contents of an in-memory buffer and a specified content-type. 41 | 42 | This method is a convenience shortcut to `` that takes a string as input and converts 43 | it to a `NSURL`. 44 | 45 | @see postDataToURL:data:contentType: 46 | */ 47 | + (instancetype)createResource:(NSString*)resourceUrl withData:(NSData*)data contentType:(NSString*)contentType; 48 | 49 | /** 50 | Creates a `POST` request to the target url, with the contents of an in-memory buffer and a specified content-type. 51 | 52 | This method is a convenience shortcut to creating a new request and then calling `setUploadData:withContentType:` on 53 | it. Be sure to refer to that method for further information. 54 | 55 | The generated request will respond `YES` to `isUpload` and `isUploadFromMemory`. 56 | 57 | @return A `POST` request to *url*, with the value of *contentType* set as the `Content-Type` header and the contents 58 | of data as the body. May return `nil` if *data* is invalid. 59 | 60 | @see initWithURL:andVerb: 61 | @see setUploadData:withContentType: 62 | */ 63 | + (instancetype)postToURL:(NSURL*)url data:(NSData*)data contentType:(NSString*)contentType; 64 | + (instancetype)createResource:(NSString*)resourceUrl withContentsOfFile:(NSString*)pathToFile; 65 | + (instancetype)postToURL:(NSURL*)url withContentsOfFile:(NSString*)pathToFile; 66 | 67 | #pragma mark      Read (GET) 68 | 69 | /** 70 | Creates a `GET` request to the target url. 71 | 72 | This method is a convenience shortcut to `getFromURL:` that takes a string as input and converts it to a `NSURL`. 73 | 74 | @see getFromURL: 75 | */ 76 | + (instancetype)readResource:(NSString*)resourceUrl; 77 | 78 | /** 79 | Creates a `GET` request to the target url. 80 | 81 | @param url The target URL. 82 | 83 | @return A `GET` request to *url*. 84 | */ 85 | + (instancetype)getFromURL:(NSURL*)url; 86 | 87 | #pragma mark      Update (PUT) 88 | 89 | + (instancetype)updateResource:(NSString*)resourceUrl withData:(NSData*)data contentType:(NSString*)contentType; 90 | + (instancetype)putToURL:(NSURL*)url data:(NSData*)data contentType:(NSString*)contentType; 91 | + (instancetype)updateResource:(NSString*)resourceUrl withContentsOfFile:(NSString*)pathToFile; 92 | + (instancetype)putToURL:(NSURL*)url withContentsOfFile:(NSString*)pathToFile; 93 | 94 | 95 | #pragma mark      Delete (DELETE) 96 | 97 | + (instancetype)deleteResource:(NSString*)resourceUrl; 98 | 99 | /** 100 | Creates a `DELETE` request to the target url. 101 | 102 | @param url The target URL. 103 | 104 | @return A `DELETE` request to *url*. 105 | */ 106 | + (instancetype)deleteAtURL:(NSURL*)url; 107 | 108 | 109 | #pragma mark Configuring response content handling 110 | 111 | /** 112 | Treat the reponse body as `NSData`. 113 | 114 | When a successful response is received, a `NSData` will be available at at the `content` property of the response. 115 | 116 | This method assigns a `` as the `` for this request. 117 | */ 118 | - (void)downloadContentAsData; 119 | 120 | /** 121 | Treat the reponse body as a `NSString` 122 | 123 | When a successful response is received, a `NSString` will be available at at the `content` property of the response. 124 | 125 | This method assigns a `` as the `` for this request. 126 | */ 127 | - (void)downloadContentAsString; 128 | 129 | /** 130 | Treat the reponse body as JSON. 131 | 132 | When a successful response is received, the parsed JSON object will be available at the `content` property of the 133 | response. 134 | 135 | This method assigns a `` as the `` for this request. 136 | */ 137 | - (void)downloadContentAsJSON; 138 | 139 | /** 140 | Treat the reponse body as an image. 141 | 142 | When a successful response is received, the decoded `NSImage`/`UIImage` will be available at the `content` property of 143 | the response. 144 | 145 | This method assigns a `` as the `` for this request. 146 | */ 147 | - (void)downloadContentAsImage; 148 | 149 | /** 150 | Download the response body directo to a file. 151 | 152 | The `content` property of the response will be nil. If the download fails, any partially downloaded file is deleted. 153 | 154 | This method assigns a `` as the `` for this request. 155 | 156 | @param pathToFile Path to the file to write to. 157 | */ 158 | - (void)downloadToFile:(NSString*)pathToFile; 159 | 160 | /** 161 | Download the response body directly to an output stream. 162 | 163 | The `content` property of the response will be nil. If the download fails, the stream will be closed. 164 | 165 | This method assigns a `` as the `` for this request. 166 | 167 | @param stream The output stream to write to. 168 | */ 169 | - (void)downloadToStream:(NSOutputStream*)stream; 170 | 171 | /** 172 | Completely discard any data received as the body of the response. 173 | 174 | Sets `` to `<[BBHTTPSelectiveDiscarder sharedDiscarder]>`. 175 | */ 176 | - (void)discardResponseContent; 177 | 178 | /** 179 | Fluent syntax shortcut for ``. 180 | 181 | @return The current instance. 182 | */ 183 | - (instancetype)asData; 184 | 185 | /** 186 | Fluent syntax shortcut for ``. 187 | 188 | @return The current instance. 189 | */ 190 | - (instancetype)asString; 191 | 192 | /** 193 | Fluent syntax shortcut for ``. 194 | 195 | @return The current instance. 196 | */ 197 | - (instancetype)asJSON; 198 | 199 | /** 200 | Fluent syntax shortcut for ``. 201 | 202 | @return The current instance. 203 | */ 204 | - (instancetype)asImage; 205 | 206 | 207 | #pragma mark Executing the request 208 | 209 | ///---------------------------- 210 | /// @name Executing the request 211 | ///---------------------------- 212 | 213 | - (BOOL)execute:(void (^)(BBHTTPRequest* request))finish; 214 | 215 | /** 216 | Convenience method that executes this request in the singleton instance of ``. 217 | 218 | @param finish The finish block that will be called when the request terminates normally. 219 | @param error The error block that will be called if the request terminates abnormally. 220 | 221 | @return `YES` if the request was accepted for execution by the executor, `NO` otherwise. 222 | 223 | @see BBHTTPExecutor 224 | */ 225 | - (BOOL)execute:(void (^)(BBHTTPResponse* response))completed error:(void (^)(NSError* error))error; 226 | 227 | - (BOOL)execute:(void (^)(BBHTTPResponse* response))completed error:(void (^)(NSError* error))error 228 | finally:(void (^)())finally; 229 | 230 | - (BOOL)execute:(void (^)(BBHTTPResponse* response))completed error:(void (^)(NSError* error))error 231 | cancelled:(void (^)())cancelled finally:(void (^)())finally; 232 | 233 | /** 234 | Convenience method allows for extra request preparation steps and executes this request in the singleton instance of 235 | ``. 236 | 237 | @param setup The setup block, will be called passing the current request as argument. Allows you to perform 238 | additional setup on the request before it is fired into the network. 239 | @param finish The finish block that will be called when the request terminates normally. 240 | @param error The error block that will be called if the request terminates abnormally. 241 | 242 | @return `YES` if the request was accepted for execution by the executor, `NO` otherwise. 243 | 244 | @see BBHTTPExecutor 245 | */ 246 | - (BOOL)setup:(void (^)(BBHTTPRequest* request))setup execute:(void (^)(BBHTTPResponse* response))completed 247 | error:(void (^)(NSError* error))error; 248 | 249 | - (BOOL)setup:(void (^)(BBHTTPRequest* request))setup execute:(void (^)(BBHTTPResponse* response))completed 250 | error:(void (^)(NSError* error))error finally:(void (^)())finally; 251 | 252 | - (BOOL)setup:(void (^)(BBHTTPRequest* request))setup execute:(void (^)(BBHTTPResponse* response))completed 253 | error:(void (^)(NSError* error))error cancelled:(void (^)())cancelled finally:(void (^)())finally; 254 | 255 | @end 256 | -------------------------------------------------------------------------------- /BBHTTP/BBHTTPRequest+Convenience.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPRequest+Convenience.h" 23 | 24 | #import "BBHTTPAccumulator.h" 25 | #import "BBHTTPToStringConverter.h" 26 | #import "BBJSONParser.h" 27 | #import "BBHTTPImageDecoder.h" 28 | #import "BBHTTPFileWriter.h" 29 | #import "BBHTTPStreamWriter.h" 30 | #import "BBHTTPExecutor.h" 31 | 32 | 33 | 34 | #pragma mark - 35 | 36 | @implementation BBHTTPRequest (Convenience) 37 | 38 | 39 | #pragma mark      Create (POST) 40 | 41 | + (instancetype)createResource:(NSString*)resourceUrl withData:(NSData*)data contentType:(NSString*)contentType 42 | { 43 | return [self postToURL:[NSURL URLWithString:resourceUrl] data:data contentType:contentType]; 44 | } 45 | 46 | + (instancetype)postToURL:(NSURL*)url data:(NSData*)data contentType:(NSString*)contentType 47 | { 48 | BBHTTPRequest* request = [[self alloc] initWithURL:url andVerb:@"POST"]; 49 | [request setUploadData:data withContentType:contentType]; 50 | 51 | return request; 52 | } 53 | 54 | + (instancetype)createResource:(NSString*)resourceUrl withContentsOfFile:(NSString*)pathToFile 55 | { 56 | return [self postToURL:[NSURL URLWithString:resourceUrl] withContentsOfFile:pathToFile]; 57 | } 58 | 59 | + (instancetype)postToURL:(NSURL*)url withContentsOfFile:(NSString*)pathToFile 60 | { 61 | BBHTTPRequest* request = [[BBHTTPRequest alloc] initWithURL:url andVerb:@"POST"]; 62 | if (![request setUploadFile:pathToFile error:nil]) return nil; 63 | 64 | return request; 65 | } 66 | 67 | #pragma mark      Read (GET) 68 | 69 | + (instancetype)readResource:(NSString*)resourceUrl 70 | { 71 | return [self getFromURL:[NSURL URLWithString:resourceUrl]]; 72 | } 73 | 74 | + (instancetype)getFromURL:(NSURL*)url 75 | { 76 | return [[self alloc] initWithURL:url andVerb:@"GET"]; 77 | } 78 | 79 | #pragma mark      Update (PUT) 80 | 81 | + (instancetype)updateResource:(NSString*)resourceUrl withData:(NSData*)data contentType:(NSString*)contentType 82 | { 83 | return [self putToURL:[NSURL URLWithString:resourceUrl] data:data contentType:contentType]; 84 | } 85 | 86 | + (instancetype)putToURL:(NSURL*)url data:(NSData*)data contentType:(NSString*)contentType 87 | { 88 | BBHTTPRequest* request = [[self alloc] initWithURL:url andVerb:@"PUT"]; 89 | [request setUploadData:data withContentType:contentType]; 90 | 91 | return request; 92 | } 93 | 94 | + (instancetype)updateResource:(NSString*)resourceUrl withContentsOfFile:(NSString*)pathToFile 95 | { 96 | return [self putToURL:[NSURL URLWithString:resourceUrl] withContentsOfFile:pathToFile]; 97 | } 98 | 99 | + (instancetype)putToURL:(NSURL*)url withContentsOfFile:(NSString*)pathToFile 100 | { 101 | BBHTTPRequest* request = [[BBHTTPRequest alloc] initWithURL:url andVerb:@"PUT"]; 102 | if (![request setUploadFile:pathToFile error:nil]) return nil; 103 | 104 | return request; 105 | } 106 | 107 | #pragma mark      Delete (DELETE) 108 | 109 | + (instancetype)deleteResource:(NSString*)resourceUrl 110 | { 111 | return [self deleteAtURL:[NSURL URLWithString:resourceUrl]]; 112 | } 113 | 114 | + (instancetype)deleteAtURL:(NSURL*)url 115 | { 116 | return [[self alloc] initWithURL:url andVerb:@"DELETE"]; 117 | } 118 | 119 | 120 | #pragma mark Configuring response content handling 121 | 122 | - (void)downloadContentAsData 123 | { 124 | self.responseContentHandler = [[BBHTTPAccumulator alloc] init]; 125 | } 126 | 127 | - (void)downloadContentAsString 128 | { 129 | self.responseContentHandler = [[BBHTTPToStringConverter alloc] init]; 130 | } 131 | 132 | - (void)downloadContentAsStringWithEncoding:(NSStringEncoding)encoding 133 | { 134 | self.responseContentHandler = [[BBHTTPToStringConverter alloc] initWithEncoding:encoding]; 135 | } 136 | 137 | - (void)downloadContentAsJSON 138 | { 139 | self.responseContentHandler = [[BBJSONParser alloc] init]; 140 | } 141 | 142 | - (void)downloadContentAsImage 143 | { 144 | self.responseContentHandler = [[BBHTTPImageDecoder alloc] init]; 145 | } 146 | 147 | - (void)downloadToFile:(NSString*)pathToFile 148 | { 149 | self.responseContentHandler = [[BBHTTPFileWriter alloc] initWithTargetFile:pathToFile]; 150 | } 151 | 152 | - (void)downloadToStream:(NSOutputStream*)stream 153 | { 154 | self.responseContentHandler = [[BBHTTPStreamWriter alloc] initWithOutputStream:stream]; 155 | } 156 | 157 | - (void)discardResponseContent 158 | { 159 | self.responseContentHandler = [BBHTTPSelectiveDiscarder sharedDiscarder]; 160 | } 161 | 162 | - (instancetype)asData 163 | { 164 | [self downloadContentAsData]; 165 | 166 | return self; 167 | } 168 | 169 | - (instancetype)asString 170 | { 171 | [self downloadContentAsString]; 172 | 173 | return self; 174 | } 175 | 176 | - (instancetype)asStringWithEncoding:(NSStringEncoding)encoding 177 | { 178 | [self downloadContentAsStringWithEncoding:encoding]; 179 | 180 | return self; 181 | } 182 | 183 | - (instancetype)asJSON 184 | { 185 | [self downloadContentAsJSON]; 186 | 187 | return self; 188 | } 189 | 190 | - (instancetype)asImage 191 | { 192 | [self downloadContentAsImage]; 193 | 194 | return self; 195 | } 196 | 197 | 198 | #pragma mark Executing the request 199 | 200 | - (BOOL)execute:(void (^)(BBHTTPRequest* request))finish 201 | { 202 | self.finishBlock = finish; 203 | 204 | return [[BBHTTPExecutor sharedExecutor] executeRequest:self]; 205 | } 206 | 207 | - (BOOL)execute:(void (^)(BBHTTPResponse* response))completed error:(void (^)(NSError* error))error 208 | { 209 | return [self execute:completed error:error cancelled:nil finally:nil]; 210 | } 211 | 212 | - (BOOL)execute:(void (^)(BBHTTPResponse* response))completed error:(void (^)(NSError* error))error 213 | finally:(void (^)())finally 214 | { 215 | return [self execute:completed error:error cancelled:nil finally:finally]; 216 | } 217 | 218 | - (BOOL)execute:(void (^)(BBHTTPResponse* response))completed error:(void (^)(NSError* error))error 219 | cancelled:(void (^)())cancelled finally:(void (^)())finally 220 | { 221 | // If nothing was specified, load body to memory -- perhaps an instance of BBHTTPDiscard would be better here? 222 | if (self.responseContentHandler == nil) [self downloadContentAsData]; 223 | 224 | self.finishBlock = ^(BBHTTPRequest* request) { 225 | if (request.error != nil) { 226 | if (error != nil) error(request.error); 227 | } else if ([request wasCancelled]) { 228 | if (cancelled != nil) cancelled(); 229 | } else { 230 | if (completed != nil) completed(request.response); 231 | } 232 | 233 | if (finally != nil) finally(); 234 | }; 235 | 236 | return [[BBHTTPExecutor sharedExecutor] executeRequest:self]; 237 | } 238 | 239 | - (BOOL)setup:(void (^)(BBHTTPRequest* request))setup execute:(void (^)(BBHTTPResponse* response))completed 240 | error:(void (^)(NSError* error))error 241 | { 242 | if (setup != nil) setup(self); 243 | 244 | return [self execute:completed error:error cancelled:nil finally:nil]; 245 | } 246 | 247 | - (BOOL)setup:(void (^)(BBHTTPRequest* request))setup execute:(void (^)(BBHTTPResponse* response))completed 248 | error:(void (^)(NSError* error))error finally:(void (^)())finally 249 | { 250 | if (setup != nil) setup(self); 251 | 252 | return [self execute:completed error:error cancelled:nil finally:finally]; 253 | } 254 | 255 | - (BOOL)setup:(void (^)(BBHTTPRequest* request))setup execute:(void (^)(BBHTTPResponse* response))completed 256 | error:(void (^)(NSError* error))error cancelled:(void (^)())cancelled finally:(void (^)())finally 257 | { 258 | if (setup != nil) setup(self); 259 | 260 | return [self execute:completed error:error cancelled:cancelled finally:finally]; 261 | } 262 | 263 | @end 264 | -------------------------------------------------------------------------------- /BBHTTP/BBHTTPRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPRequest.h" 23 | 24 | #import "BBHTTPUtils.h" 25 | 26 | 27 | 28 | #pragma mark - Utility Functions 29 | 30 | BBTransferSpeed BBTransferSpeedMake(NSUInteger bytesPerSecond, NSTimeInterval duration) 31 | { 32 | BBTransferSpeed transferSpeed; 33 | transferSpeed.bytesPerSecond = bytesPerSecond; 34 | transferSpeed.duration = duration; 35 | 36 | return transferSpeed; 37 | } 38 | 39 | NSString* NSStringFromBBTransferSpeed(BBTransferSpeed transferSpeed) 40 | { 41 | return [NSString stringWithFormat:@"%lu/s for %.0f seconds", 42 | (unsigned long)transferSpeed.bytesPerSecond, transferSpeed.duration]; 43 | } 44 | 45 | 46 | 47 | #pragma mark - 48 | 49 | @implementation BBHTTPRequest 50 | { 51 | NSUInteger _uploadSize; // Cached upload size, when available 52 | NSMutableDictionary* _headers; // Header storage; auto generated synthesizer for headers property will use this ivar 53 | } 54 | 55 | 56 | #pragma mark Creating a request 57 | 58 | - (instancetype)init 59 | { 60 | NSAssert(NO, @"please use initWithURL:andVerb: instead"); 61 | return [self initWithTarget:@"http://biasedbit.com" andVerb:@"GET"]; 62 | } 63 | 64 | - (instancetype)initWithTarget:(NSString*)url andVerb:(NSString*)verb 65 | { 66 | return [self initWithURL:[NSURL URLWithString:url] andVerb:verb]; 67 | } 68 | 69 | - (instancetype)initWithURL:(NSURL*)url andVerb:(NSString*)verb 70 | { 71 | return [self initWithURL:url verb:verb andProtocolVersion:BBHTTPProtocolVersion_1_1]; 72 | } 73 | 74 | - (instancetype)initWithURL:(NSURL*)url verb:(NSString*)verb andProtocolVersion:(BBHTTPProtocolVersion)version; 75 | { 76 | BBHTTPEnsureNotNil(url); 77 | BBHTTPEnsureNotNil(verb); 78 | NSParameterAssert(![url isFileReferenceURL]); 79 | NSAssert([url host] != nil, 80 | @"Host cannot be nil; make sure you provided a valid NSURL instance.\n\nOffending URL: '%@'", url); 81 | 82 | self = [super init]; 83 | if (self != nil) { 84 | _url = [url copy]; 85 | _verb = [verb copy]; 86 | _headers = [NSMutableDictionary dictionary]; 87 | 88 | _startTimestamp = -1; 89 | _endTimestamp = -1; 90 | _version = version; 91 | _maxRedirects = 0; 92 | _allowInvalidSSLCertificates = NO; 93 | _connectionTimeout = 10; 94 | _downloadTimeout = BBTransferSpeedMake(1024, 20); 95 | _uploadSpeedLimit = 0; 96 | _downloadSpeedLimit = 0; 97 | _callbackQueue = dispatch_get_main_queue(); 98 | 99 | NSString* hostHeaderValue = [_url host]; 100 | NSUInteger port = [self port]; 101 | if (port != 80) hostHeaderValue = [hostHeaderValue stringByAppendingFormat:@":%ld", (long)port]; 102 | 103 | [self setValue:hostHeaderValue forHeader:H(Host)]; 104 | [self setValue:@"*/*" forHeader:H(Accept)]; 105 | 106 | BBHTTPSingleton(NSString, appName, 107 | [[[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleExecutableKey] 108 | stringByReplacingOccurrencesOfString:@" " withString:@"-"]); 109 | BBHTTPSingleton(NSString, appVersion, 110 | [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]); 111 | 112 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 113 | BBHTTPSingletonString(userAgent, @"BBHTTP/%@ %@/%@ (%@; iOS %@; Scale/%0.2f)", 114 | BBHTTPVersion, appName, appVersion, 115 | [[UIDevice currentDevice] model], 116 | [[UIDevice currentDevice] systemVersion], 117 | [[UIScreen mainScreen] scale]); 118 | #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) 119 | BBHTTPSingletonString(userAgent, @"BBHTTP/%@ %@/%@ (Mac OS X %@)", 120 | BBHTTPVersion, appName, appVersion, 121 | [[NSProcessInfo processInfo] operatingSystemVersionString]); 122 | #endif 123 | [self setValue:userAgent forHeader:H(UserAgent)]; 124 | } 125 | 126 | return self; 127 | } 128 | 129 | 130 | #pragma mark Managing download behavior 131 | 132 | - (NSUInteger)downloadSize 133 | { 134 | return _response == nil ? 0 : _response.contentSize; 135 | } 136 | 137 | - (double)downloadProgress 138 | { 139 | // TODO this is not working because a _response is not set until the request ends. 140 | NSUInteger toReceive = self.downloadSize; 141 | if (toReceive == 0) return 0; 142 | 143 | return (self.receivedBytes / (double)self.downloadSize) * 100; 144 | } 145 | 146 | - (double)downloadTransferRate 147 | { 148 | if (![self hasStarted]) return 0; 149 | 150 | long long end = (self.endTimestamp > 0 ? self.endTimestamp : BBHTTPCurrentTimeMillis()); 151 | return (self.receivedBytes * 1000) / (double)(end - self.startTimestamp); 152 | } 153 | 154 | 155 | #pragma mark Managing upload behavior 156 | 157 | - (BOOL)setUploadStream:(NSInputStream*)stream withContentType:(NSString*)contentType andSize:(NSUInteger)size; 158 | { 159 | BBHTTPEnsureNotNil(stream); 160 | BBHTTPEnsureNotNil(contentType); 161 | 162 | if (_version != BBHTTPProtocolVersion_1_1) return NO; 163 | 164 | _uploadFile = nil; 165 | _uploadData = nil; 166 | 167 | _uploadStream = stream; 168 | _uploadSize = size; 169 | 170 | [self setValue:contentType forHeader:H(ContentType)]; 171 | if (size > 0) [self setValue:[NSString stringWithFormat:@"%lu", (long)size] forHeader:H(ContentLength)]; 172 | 173 | return YES; 174 | } 175 | 176 | - (BOOL)setUploadFile:(NSString*)path error:(NSError**)error 177 | { 178 | BBHTTPEnsureNotNil(path); 179 | 180 | NSError* err = nil; 181 | NSDictionary* attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:&err]; 182 | if (err != nil) { 183 | if (error != NULL) *error = err; 184 | BBHTTPLogError(@"Can't read file attributes: %@", [err localizedDescription]); 185 | return NO; 186 | } 187 | 188 | unsigned long long size = [attributes fileSize]; 189 | if (size == 0) { 190 | if (error != NULL) *error = BBHTTPError(-1, @"File is empty (0 bytes)"); 191 | BBHTTPLogError(@"File is empty (0 bytes)"); 192 | return NO; 193 | } else if (size > NSUIntegerMax) { 194 | // This can probably be relaxed... 195 | BBHTTPLogError(@"File is too large (>%lu bytes)", NSUIntegerMax); 196 | if (error != NULL) *error = BBHTTPErrorWithFormat(-2, @"File is too large (>%lu bytes)", NSUIntegerMax); 197 | return NO; 198 | } 199 | 200 | [self setValue:BBHTTPMimeType(path) forHeader:H(ContentType)]; 201 | [self setValue:[NSString stringWithFormat:@"%llu", size] forHeader:H(ContentLength)]; 202 | 203 | _uploadData = nil; 204 | _uploadStream = nil; 205 | 206 | _uploadSize = (NSUInteger)size; 207 | _uploadFile = [path copy]; 208 | 209 | return YES; 210 | } 211 | 212 | - (BOOL)setUploadData:(NSData*)data withContentType:(NSString*)contentType 213 | { 214 | BBHTTPEnsureNotNil(data); 215 | BBHTTPEnsureNotNil(contentType); 216 | 217 | if (data.length == 0) return NO; 218 | 219 | _uploadStream = nil; 220 | _uploadFile = nil; 221 | 222 | _uploadData = data; 223 | _uploadSize = [data length]; 224 | 225 | [self setValue:contentType forHeader:H(ContentType)]; 226 | [self setValue:[NSString stringWithFormat:@"%lu", (long)_uploadSize] forHeader:H(ContentLength)]; 227 | 228 | return YES; 229 | } 230 | 231 | - (BOOL)setUploadFormData:(NSDictionary*)formData 232 | { 233 | BBHTTPEnsureNotNil(formData); 234 | 235 | NSMutableArray* concatenatedKeyValuePairs = [NSMutableArray arrayWithCapacity:[formData count]]; 236 | [formData enumerateKeysAndObjectsUsingBlock:^(NSString* key, id obj, BOOL* stop) { 237 | NSString* formEncodedKey = BBHTTPURLEncode(key, NSASCIIStringEncoding); 238 | NSString* formEncodedValue; 239 | if (obj == nil) { 240 | formEncodedValue = @""; 241 | } else { 242 | formEncodedValue = BBHTTPURLEncode(obj, NSASCIIStringEncoding); 243 | } 244 | 245 | NSString* concatenatedKeyValuePair = [NSString stringWithFormat:@"%@=%@", formEncodedKey, formEncodedValue]; 246 | [concatenatedKeyValuePairs addObject:concatenatedKeyValuePair]; 247 | }]; 248 | 249 | NSString* formDataAsConcatenatedURLEncodedString = [concatenatedKeyValuePairs componentsJoinedByString:@"&"]; 250 | NSData* data = [formDataAsConcatenatedURLEncodedString dataUsingEncoding:NSASCIIStringEncoding]; 251 | 252 | return [self setUploadData:data withContentType:@"application/x-www-form-urlencoded"]; 253 | } 254 | 255 | - (BOOL)isUpload 256 | { 257 | return (_uploadData != nil) || (_uploadFile != nil) || (_uploadStream != nil); 258 | } 259 | 260 | - (BOOL)isUploadSizeKnown 261 | { 262 | if ((_uploadStream != nil) && (_uploadSize == 0)) return NO; 263 | if ((_uploadFile != nil) || (_uploadData != nil)) return YES; 264 | else return NO; 265 | } 266 | 267 | - (double)uploadProgress 268 | { 269 | NSUInteger toSend = self.uploadSize; 270 | if (toSend == 0) return 0; 271 | 272 | return (self.sentBytes / (double)toSend) * 100; 273 | } 274 | 275 | - (double)uploadTransferRate 276 | { 277 | if (![self hasStarted]) return 0; 278 | 279 | long long end = (self.endTimestamp > 0 ? self.endTimestamp : BBHTTPCurrentTimeMillis()); 280 | return (self.sentBytes * 1000) / (double)(end - self.startTimestamp); 281 | } 282 | 283 | 284 | #pragma mark Manipulating headers 285 | 286 | - (BOOL)hasHeader:(NSString*)header 287 | { 288 | return _headers[header] != nil; 289 | } 290 | 291 | - (BOOL)hasHeader:(NSString*)header withValue:(NSString*)value 292 | { 293 | NSString* headerValue = _headers[header]; 294 | if (headerValue == nil) return NO; 295 | 296 | return [headerValue isEqualToString:value]; 297 | } 298 | 299 | - (NSString*)headerWithName:(NSString*)header 300 | { 301 | return _headers[header]; 302 | } 303 | 304 | - (NSString*)objectForKeyedSubscript:(NSString*)header 305 | { 306 | return _headers[header]; 307 | } 308 | 309 | - (BOOL)setValue:(NSString*)value forHeader:(NSString*)header 310 | { 311 | BBHTTPEnsureNotNil(value); 312 | BBHTTPEnsureNotNil(header); 313 | 314 | _headers[header] = value; 315 | 316 | return YES; 317 | } 318 | 319 | - (void)setObject:(NSString*)value forKeyedSubscript:(NSString*)header 320 | { 321 | [self setValue:value forHeader:header]; 322 | } 323 | 324 | 325 | #pragma mark Querying request properties 326 | 327 | - (NSUInteger)port 328 | { 329 | NSNumber* port = [_url port]; 330 | BOOL isHttps = [[_url scheme] isEqualToString:@"https"]; 331 | 332 | if (port == nil) return isHttps ? 443 : 80; 333 | else return [port unsignedIntValue]; 334 | } 335 | 336 | 337 | #pragma mark Querying request state 338 | 339 | - (BOOL)hasStarted 340 | { 341 | return _startTimestamp > 0; 342 | } 343 | 344 | - (BOOL)hasFinished 345 | { 346 | return _endTimestamp > 0; 347 | } 348 | 349 | - (BOOL)isExecuting 350 | { 351 | return [self hasStarted] && ![self hasFinished]; 352 | } 353 | 354 | - (BOOL)wasSuccessfullyExecuted 355 | { 356 | return [self hasFinished] && (_response != nil); 357 | } 358 | 359 | - (NSUInteger)responseStatusCode 360 | { 361 | return _response == nil ? 0 : _response.code; 362 | } 363 | 364 | - (BOOL)hasSuccessfulResponse 365 | { 366 | return [self wasSuccessfullyExecuted] && [_response isSuccessful]; 367 | } 368 | 369 | 370 | #pragma mark Cancelling a request 371 | 372 | - (BOOL)cancel 373 | { 374 | if (_cancelled) return NO; 375 | 376 | _cancelled = YES; 377 | 378 | long long now = BBHTTPCurrentTimeMillis(); 379 | if (_startTimestamp < 0) _startTimestamp = now; 380 | _endTimestamp = now; 381 | 382 | if (_finishBlock != nil) { 383 | dispatch_async(_callbackQueue, ^{ 384 | _finishBlock(self); 385 | 386 | _uploadProgressBlock = nil; 387 | _downloadProgressBlock = nil; 388 | _finishBlock = nil; 389 | }); 390 | } 391 | 392 | return YES; 393 | } 394 | 395 | 396 | #pragma mark Debug 397 | 398 | - (NSString*)description 399 | { 400 | NSString* url = [_url absoluteString]; 401 | NSString* trimmedUrl = [url length] > 40 ? [[url substringToIndex:37] stringByAppendingString:@"…"] : url; 402 | return [NSString stringWithFormat:@"%@ %@", _verb, trimmedUrl]; 403 | } 404 | 405 | @end 406 | -------------------------------------------------------------------------------- /BBHTTP/BBHTTPResponse.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #pragma mark - Enums 23 | 24 | typedef NS_ENUM(NSUInteger, BBHTTPProtocolVersion) { 25 | BBHTTPProtocolVersion_1_0 = 0, 26 | BBHTTPProtocolVersion_1_1, 27 | }; 28 | 29 | 30 | 31 | #pragma mark - Utility functions 32 | 33 | NSString* NSStringFromBBHTTPProtocolVersion(BBHTTPProtocolVersion version); 34 | BBHTTPProtocolVersion BBHTTPProtocolVersionFromNSString(NSString* string); 35 | 36 | 37 | 38 | #pragma mark - 39 | 40 | @interface BBHTTPResponse : NSObject 41 | 42 | 43 | #pragma mark Properties 44 | 45 | @property(assign, nonatomic, readonly) BBHTTPProtocolVersion version; 46 | @property(assign, nonatomic, readonly) NSUInteger code; 47 | @property(strong, nonatomic, readonly) NSString* message; 48 | @property(strong, nonatomic, readonly) NSDictionary* headers; 49 | @property(assign, nonatomic, readonly, getter = isSuccessful) BOOL successful; 50 | @property(assign, nonatomic, readonly) NSUInteger contentSize; 51 | @property(strong, nonatomic, readonly) id content; 52 | 53 | 54 | #pragma mark Creation 55 | 56 | - (instancetype)initWithVersion:(BBHTTPProtocolVersion)version 57 | code:(NSUInteger)code 58 | andMessage:(NSString*)message; 59 | 60 | 61 | #pragma mark Public static methods 62 | 63 | + (BBHTTPResponse*)responseWithStatusLine:(NSString*)statusLine; 64 | 65 | 66 | #pragma mark Interface 67 | 68 | - (void)finishWithContent:(id)content size:(NSUInteger)size successful:(BOOL)successful; 69 | - (NSString*)headerWithName:(NSString*)header; 70 | - (void)setValue:(NSString*)value forHeader:(NSString*)header; 71 | - (NSString*)objectForKeyedSubscript:(NSString*)header; 72 | - (void)setObject:(NSString*)value forKeyedSubscript:(NSString*)header; 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /BBHTTP/BBHTTPResponse.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPResponse.h" 23 | 24 | 25 | 26 | #pragma mark - Utility functions 27 | 28 | NSString* NSStringFromBBHTTPProtocolVersion(BBHTTPProtocolVersion version) 29 | { 30 | switch (version) { 31 | case BBHTTPProtocolVersion_1_0: 32 | return @"HTTP/1.0"; 33 | 34 | default: 35 | return @"HTTP/1.1"; 36 | } 37 | } 38 | 39 | BBHTTPProtocolVersion BBHTTPProtocolVersionFromNSString(NSString* string) 40 | { 41 | if ([string isEqualToString:@"HTTP/1.0"]) { 42 | return BBHTTPProtocolVersion_1_0; 43 | } else { 44 | return BBHTTPProtocolVersion_1_1; 45 | } 46 | } 47 | 48 | 49 | 50 | #pragma mark - 51 | 52 | @implementation BBHTTPResponse 53 | { 54 | NSMutableDictionary* _headers; 55 | BOOL _successful; 56 | } 57 | 58 | 59 | #pragma mark Creation 60 | 61 | - (instancetype)initWithVersion:(BBHTTPProtocolVersion)version 62 | code:(NSUInteger)code 63 | andMessage:(NSString*)message 64 | { 65 | self = [super init]; 66 | if (self != nil) { 67 | _version = version; 68 | _code = code; 69 | _message = message; 70 | _headers = [NSMutableDictionary dictionary]; 71 | } 72 | 73 | return self; 74 | } 75 | 76 | 77 | #pragma mark Public static methods 78 | 79 | + (BBHTTPResponse*)responseWithStatusLine:(NSString*)statusLine 80 | { 81 | // TODO check size 82 | NSString* versionString = [statusLine substringToIndex:8]; 83 | NSRange statusCodeRange = NSMakeRange(9, 3); 84 | NSString* statusCodeString = [statusLine substringWithRange:statusCodeRange]; 85 | 86 | BBHTTPProtocolVersion version = BBHTTPProtocolVersionFromNSString(versionString); 87 | NSUInteger statusCode = (NSUInteger)[statusCodeString integerValue]; 88 | 89 | NSString* message = [statusLine substringFromIndex:NSMaxRange(statusCodeRange) + 1]; 90 | 91 | BBHTTPResponse* response = [[self alloc] initWithVersion:version code:statusCode andMessage:message]; 92 | 93 | return response; 94 | } 95 | 96 | 97 | #pragma mark Interface 98 | 99 | - (void)finishWithContent:(id)content size:(NSUInteger)size successful:(BOOL)successful 100 | { 101 | _content = content; 102 | _contentSize = size; 103 | _successful = successful; 104 | } 105 | 106 | - (NSString*)headerWithName:(NSString*)header 107 | { 108 | return _headers[header]; 109 | } 110 | 111 | - (NSString*)objectForKeyedSubscript:(NSString*)header 112 | { 113 | return _headers[header]; 114 | } 115 | 116 | - (void)setValue:(NSString*)value forHeader:(NSString*)header 117 | { 118 | _headers[header] = value; 119 | } 120 | 121 | - (void)setObject:(NSString*)value forKeyedSubscript:(NSString*)header 122 | { 123 | [self setValue:value forHeader:header]; 124 | } 125 | 126 | - (BOOL)isSuccessful 127 | { 128 | return _successful; 129 | } 130 | 131 | 132 | #pragma mark Debug 133 | 134 | - (NSString*)description 135 | { 136 | return [NSString stringWithFormat:@"%@{%lu, %@, %lu bytes of data}", 137 | NSStringFromClass([self class]), (unsigned long)_code, _message, (unsigned long)[self contentSize]]; 138 | } 139 | 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /BBHTTP/Handlers/BBHTTPAccumulator.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPSelectiveDiscarder.h" 23 | 24 | 25 | 26 | #pragma mark - 27 | 28 | /** 29 | Convert request body to `NSData`. 30 | */ 31 | @interface BBHTTPAccumulator : BBHTTPSelectiveDiscarder 32 | @end 33 | -------------------------------------------------------------------------------- /BBHTTP/Handlers/BBHTTPAccumulator.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPAccumulator.h" 23 | 24 | 25 | 26 | #pragma mark - 27 | 28 | @implementation BBHTTPAccumulator 29 | { 30 | NSOutputStream* _stream; 31 | } 32 | 33 | 34 | #pragma mark BBHTTPSelectiveDiscarder behavior overrides 35 | 36 | - (NSInteger)appendResponseBytes:(uint8_t*)bytes withLength:(NSUInteger)length error:(NSError**)error 37 | { 38 | if (_stream == nil) { 39 | _stream = [NSOutputStream outputStreamToMemory]; 40 | [_stream open]; 41 | } 42 | 43 | NSInteger written = [_stream write:bytes maxLength:length]; 44 | if (written <= 0) [_stream close]; 45 | if ((written < 0) && (error != NULL)) *error = [_stream streamError]; 46 | 47 | return written; 48 | } 49 | 50 | - (id)parseContent:(NSError**)error 51 | { 52 | if (_stream == nil) return nil; // No data received 53 | 54 | if ([_stream streamError] != nil) { 55 | if (error != NULL) *error = [_stream streamError]; 56 | return nil; 57 | } 58 | 59 | if ([_stream streamStatus] != NSStreamStatusClosed) [_stream close]; 60 | NSData* data = [_stream propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; 61 | 62 | _stream = nil; 63 | 64 | return data; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /BBHTTP/Handlers/BBHTTPContentHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #pragma mark - 23 | 24 | /** 25 | Defines the interface for a response content handler. 26 | 27 | When a request is performed, its response content may be handled differently according to the implementation of the 28 | content handler it is configured to use. 29 | 30 | For instance, to handle JSON, the response content bytes would be read to a buffer and, when complete, that buffer 31 | would be converted to a JSON object. 32 | 33 | For examples of implementations of this protocol, take a look at `` or ``. 34 | */ 35 | @protocol BBHTTPContentHandler 36 | 37 | 38 | @required 39 | 40 | /** 41 | Prepares the response content handler for a response. 42 | 43 | If after inspecting the status code, message and headers the handler decides it does not want to accept the response, 44 | it should return `NO`. 45 | 46 | @param statusCode The response status code. 47 | @param message The response message from the response line (e.g. the "OK" in "200 OK" or 48 | "The Bees They're In My Eyes" in "500 The Bees They're In My Eyes"). 49 | @param headers Dictionary with the response headers. 50 | @param error On input, a pointer to an error object. If an error occurs, this pointer is set to an actual error object 51 | containing the error information. You may specify nil for this parameter if you do not want the error information. 52 | 53 | @return `YES` if this content handler accepts the response, `NO` otherwise. 54 | */ 55 | - (BOOL)prepareForResponse:(NSUInteger)statusCode message:(NSString*)message headers:(NSDictionary*)headers 56 | error:(NSError**)error; 57 | /** 58 | Feed response body data to the handler. 59 | 60 | If this method does not return the same number as the one it receives with the `length` parameter, the executor will 61 | assume error and abort the request. 62 | 63 | @param bytes Array of bytes. 64 | @param length Length of the byte array. 65 | @param error On input, a pointer to an error object. If an error occurs, this pointer is set to an actual error object 66 | containing the error information. You may specify nil for this parameter if you do not want the error information. 67 | 68 | @return The number of bytes handled. If this number is inferior to `length`, the download will be aborted. 69 | */ 70 | - (NSInteger)appendResponseBytes:(uint8_t*)bytes withLength:(NSUInteger)length error:(NSError**)error; 71 | - (id)parseContent:(NSError**)error; 72 | 73 | 74 | @optional 75 | 76 | /** 77 | Perform additional cleanup, if needed. 78 | */ 79 | - (void)cleanup; 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /BBHTTP/Handlers/BBHTTPFileWriter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPSelectiveDiscarder.h" 23 | 24 | 25 | #pragma mark - 26 | 27 | /** 28 | Response parser that inherits selective behavior from `` and dumps all the data it 29 | receives through `` to a the file it was initialized with. 30 | 31 | If the file cannot be written to or there's not enough space left on device, the request will fail. 32 | 33 | If an error occurs while transferring data to the the file, the partial file will automatically be deleted. 34 | */ 35 | @interface BBHTTPFileWriter : BBHTTPSelectiveDiscarder 36 | 37 | 38 | #pragma mark Creating a new file writer 39 | 40 | - (instancetype)initWithTargetFile:(NSString*)pathToFile; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /BBHTTP/Handlers/BBHTTPFileWriter.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPFileWriter.h" 23 | 24 | #import "BBHTTPUtils.h" 25 | 26 | 27 | 28 | #pragma mark - 29 | 30 | @implementation BBHTTPFileWriter 31 | { 32 | NSString* _pathToFile; 33 | NSOutputStream* _stream; 34 | BOOL _needsCleanup; 35 | } 36 | 37 | 38 | #pragma mark Creating a new file writer 39 | 40 | - (instancetype)initWithTargetFile:(NSString*)pathToFile 41 | { 42 | self = [super init]; 43 | if (self != nil) { 44 | _pathToFile = pathToFile; 45 | _needsCleanup = NO; 46 | } 47 | 48 | return self; 49 | } 50 | 51 | 52 | #pragma mark BBHTTPContentHandler 53 | 54 | - (BOOL)prepareForResponse:(NSUInteger)statusCode message:(NSString*)message headers:(NSDictionary*)headers 55 | error:(NSError**)error 56 | { 57 | if (![super prepareForResponse:statusCode message:message headers:headers error:error]) return NO; 58 | 59 | _stream = [NSOutputStream outputStreamToFileAtPath:_pathToFile append:NO]; 60 | [_stream open]; 61 | _needsCleanup = YES; 62 | 63 | return YES; 64 | } 65 | 66 | - (NSInteger)appendResponseBytes:(uint8_t*)bytes withLength:(NSUInteger)length error:(NSError**)error 67 | { 68 | NSInteger written = [_stream write:bytes maxLength:length]; 69 | if (written <= 0) [self cleanup]; 70 | if ((written < 0) && (error != NULL)) *error = [_stream streamError]; 71 | 72 | return written; 73 | } 74 | 75 | - (id)parseContent:(NSError**)error 76 | { 77 | _needsCleanup = NO; 78 | if (([_stream streamError] != nil) && (error != NULL)) *error = [_stream streamError]; 79 | if ([_stream streamStatus] != NSStreamStatusClosed) [_stream close]; 80 | 81 | // There's never anything to return here, this parser merely pumps data to the output stream. 82 | return nil; 83 | } 84 | 85 | - (void)cleanup 86 | { 87 | if (!_needsCleanup) return; 88 | 89 | _needsCleanup = NO; 90 | [_stream close]; 91 | [self deleteFileInBackground]; 92 | } 93 | 94 | 95 | #pragma mark Private helpers 96 | 97 | - (void)deleteFileInBackground 98 | { 99 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 100 | NSError* error = nil; 101 | if (![[NSFileManager defaultManager] removeItemAtPath:_pathToFile error:&error]) { 102 | NSError* cause = [[error userInfo] objectForKey:NSUnderlyingErrorKey]; 103 | NSString* description = cause == nil ? [error localizedDescription] : [cause localizedDescription]; 104 | BBHTTPLogWarn(@"[%@] Deletion of partially downloaded file '%@' failed: %@", 105 | self, _pathToFile, description); 106 | } else { 107 | BBHTTPLogTrace(@"[%@] Deleted partially downloaded file '%@'.", self, _pathToFile); 108 | } 109 | }); 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /BBHTTP/Handlers/BBHTTPImageDecoder.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPAccumulator.h" 23 | 24 | 25 | 26 | #pragma mark - 27 | 28 | @interface BBHTTPImageDecoder : BBHTTPAccumulator 29 | @end 30 | -------------------------------------------------------------------------------- /BBHTTP/Handlers/BBHTTPImageDecoder.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 23 | #import 24 | #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) 25 | #import 26 | #endif 27 | 28 | #import "BBHTTPImageDecoder.h" 29 | 30 | #import "BBHTTPUtils.h" 31 | 32 | 33 | 34 | #pragma mark - 35 | 36 | @implementation BBHTTPImageDecoder 37 | 38 | 39 | #pragma mark Creation 40 | 41 | - (instancetype)init 42 | { 43 | self = [super init]; 44 | if (self != nil) { 45 | self.acceptableContentTypes = @[@"image/"]; // accept anything that begins with image/ 46 | } 47 | 48 | return self; 49 | } 50 | 51 | 52 | #pragma mark BBHTTPAccumulator behavior override 53 | 54 | - (id)parseContent:(NSError**)error 55 | { 56 | // super ensures we have a valid response code and a valid content type 57 | NSData* data = [super parseContent:error]; 58 | if (((error != NULL) && (*error != nil)) || (data == nil)) return nil; 59 | 60 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 61 | UIImage* image = [UIImage imageWithData:data]; 62 | #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) 63 | NSImage* image = [[NSImage alloc] initWithData:data]; 64 | #endif 65 | if (image == nil) { 66 | if (error != NULL) *error = BBHTTPError(BBHTTPErrorCodeImageDecodingFailed, @"Image decoding failed"); 67 | return data; 68 | } 69 | 70 | return image; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /BBHTTP/Handlers/BBHTTPSelectiveDiscarder.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPContentHandler.h" 23 | 24 | 25 | 26 | #pragma mark - 27 | 28 | /** 29 | Semi-abstract response content handler that includes logic to accept or reject requests, based on their response 30 | status code and content type headers. 31 | 32 | It is a completely stateless implementation so instead of creating new instances, the `` should be 33 | used to obtain the singleton. 34 | 35 | ### Subclassing notes 36 | 37 | The behavior of this class is to completely discard any bytes received. To avoid this, subclasses must override 38 | the following methods from the `` protocol: 39 | 40 | * `` 41 | * `` 42 | 43 | The method `` should only be overridden if the subclass needs to perform 44 | additional validations; this class already calls `` and ``. 45 | */ 46 | @interface BBHTTPSelectiveDiscarder : NSObject 47 | 48 | 49 | #pragma mark Defining response pre-conditions for content parsing 50 | 51 | ///----------------------------------------------------------- 52 | /// @name Defining response pre-conditions for content parsing 53 | ///----------------------------------------------------------- 54 | 55 | /** 56 | List of response codes considered acceptable for a response, in order for content parsing to be allowed. 57 | 58 | You must pass a `NSArray` containing only `NSNumber` instances: 59 | 60 | [request setAcceptableResponses:@[@200, @201, @202]]; 61 | 62 | Setting this property to `nil` or to an empty array will cause all response codes to be accepted. 63 | */ 64 | @property(copy, nonatomic) NSArray* acceptableResponses; 65 | 66 | /** 67 | List of MIME types considered acceptable for the `Content-Type` header of a response, in order for content parsing 68 | to be allowed. 69 | 70 | Each string you provide will be tested, in order, against the response's `Content-Type` — it is therefore a good 71 | idea to place common types first. 72 | 73 | For the time being, this implementation does a dumb substring search so if you want wildcard matching, just use parts 74 | of the string. 75 | 76 | Examples: 77 | 78 | * `application/json` would allow `application/json;encoding=utf-8` 79 | * `application/json;encoding=utf-8` would not allow `application/json` 80 | * `text/` would allow any content type beginning with "text/" 81 | * `json` would allow any content type containing "json" 82 | 83 | Setting this property to `nil` or to an empty array will cause any content type to be accepted. 84 | */ 85 | @property(copy, nonatomic) NSArray* acceptableContentTypes; 86 | 87 | 88 | #pragma mark Obtaining the singleton 89 | 90 | + (instancetype)sharedDiscarder; 91 | 92 | 93 | #pragma mark Determining eligibility for content parsing (for subclasses) 94 | 95 | - (BOOL)isAcceptableResponseCode:(NSUInteger)statusCode; 96 | - (BOOL)isAcceptableContentType:(NSString*)contentType; 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /BBHTTP/Handlers/BBHTTPSelectiveDiscarder.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPSelectiveDiscarder.h" 23 | 24 | #import "BBHTTPUtils.h" 25 | 26 | 27 | 28 | #pragma mark - 29 | 30 | @implementation BBHTTPSelectiveDiscarder 31 | 32 | 33 | #pragma mark Creation 34 | 35 | - (instancetype)init 36 | { 37 | self = [super init]; 38 | if (self != nil) { 39 | _acceptableResponses = @[@200, @201, @202, @203, @204]; 40 | _acceptableContentTypes = nil; // accept everything 41 | } 42 | 43 | return self; 44 | } 45 | 46 | 47 | #pragma mark BBHTTPContentHandler 48 | 49 | - (BOOL)prepareForResponse:(NSUInteger)statusCode message:(NSString*)message headers:(NSDictionary*)headers 50 | error:(NSError**)error 51 | { 52 | if (![self isAcceptableResponseCode:statusCode]) { 53 | if (error != NULL) { 54 | *error = BBHTTPErrorWithFormat(statusCode, @"Unnacceptable response: %lu %@", 55 | (unsigned long)statusCode, message); 56 | } 57 | return NO; 58 | } 59 | 60 | NSString* contentType = headers[H(ContentType)]; // might be nil 61 | if (![self isAcceptableContentType:contentType]) { 62 | if (error != NULL) { 63 | *error = BBHTTPErrorWithFormat(BBHTTPErrorCodeUnnacceptableContentType, 64 | @"Unnacceptable response content: %@", contentType); 65 | } 66 | return NO; 67 | } 68 | 69 | return YES; 70 | } 71 | 72 | - (NSInteger)appendResponseBytes:(uint8_t*)bytes withLength:(NSUInteger)length error:(NSError**)error 73 | { 74 | return length; 75 | } 76 | 77 | - (id)parseContent:(NSError**)error 78 | { 79 | return nil; 80 | } 81 | 82 | 83 | #pragma mark Obtaining the singleton 84 | 85 | + (instancetype)sharedDiscarder 86 | { 87 | BBHTTPSingleton(BBHTTPSelectiveDiscarder, instance, [[BBHTTPSelectiveDiscarder alloc] init]); 88 | return instance; 89 | } 90 | 91 | 92 | #pragma mark Determining eligibility for content parsing (for subclasses) 93 | 94 | - (BOOL)isAcceptableResponseCode:(NSUInteger)statusCode 95 | { 96 | // When no acceptable response codes are defined, accept everything 97 | if ((_acceptableResponses == nil) || ([_acceptableResponses count] == 0)) return YES; 98 | 99 | return [_acceptableResponses containsObject:@(statusCode)]; 100 | } 101 | 102 | - (BOOL)isAcceptableContentType:(NSString*)contentType 103 | { 104 | // When no acceptable response content types are defined, accept everything 105 | if ((_acceptableContentTypes == nil) || ([_acceptableContentTypes count] == 0)) return YES; 106 | 107 | if (contentType == nil) return NO; // Reject responses without content type header 108 | 109 | // Go through each of the acceptable content types and return when first is matched. 110 | // For the time being, parameterized content types are not supported. 111 | for (NSString* acceptableContentType in _acceptableContentTypes) { 112 | NSRange searchResult = [contentType rangeOfString:acceptableContentType options:NSCaseInsensitiveSearch]; 113 | if (searchResult.location != NSNotFound) return YES; 114 | } 115 | 116 | return NO; 117 | } 118 | 119 | 120 | #pragma mark Debug 121 | 122 | - (NSString *)description 123 | { 124 | return NSStringFromClass([self class]); 125 | } 126 | 127 | @end 128 | -------------------------------------------------------------------------------- /BBHTTP/Handlers/BBHTTPStreamWriter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPSelectiveDiscarder.h" 23 | 24 | 25 | 26 | #pragma mark - 27 | 28 | /** 29 | Response parser that inherits selective behavior from `` and pumps all the data it 30 | receives through `` to a `NSOutputStream`. 31 | 32 | If the output stream is not open when the request is accepted, it will be automatically opened. 33 | 34 | If an error occurs while transferring data to the output stream, the stream will be closed. 35 | When processing ends, the stream will be closed. 36 | 37 | If the stream does not have enough space available, the request will fail. 38 | */ 39 | @interface BBHTTPStreamWriter : BBHTTPSelectiveDiscarder 40 | 41 | 42 | #pragma mark Creating a new stream writer 43 | 44 | - (instancetype)initWithOutputStream:(NSOutputStream*)stream; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /BBHTTP/Handlers/BBHTTPStreamWriter.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPStreamWriter.h" 23 | 24 | 25 | 26 | #pragma mark - 27 | 28 | @implementation BBHTTPStreamWriter 29 | { 30 | NSOutputStream* _stream; 31 | } 32 | 33 | 34 | #pragma mark Creating a new stream writer 35 | 36 | - (instancetype)initWithOutputStream:(NSOutputStream*)stream 37 | { 38 | self = [super init]; 39 | if (self != nil) _stream = stream; 40 | 41 | return self; 42 | } 43 | 44 | 45 | #pragma mark BBHTTPContentHandler 46 | 47 | - (BOOL)prepareForResponse:(NSUInteger)statusCode message:(NSString*)message headers:(NSDictionary*)headers 48 | error:(NSError**)error 49 | { 50 | if (![super prepareForResponse:statusCode message:message headers:headers error:error]) return NO; 51 | 52 | if ([_stream streamStatus] != NSStreamStatusOpen) [_stream open]; 53 | 54 | return YES; 55 | } 56 | 57 | - (NSInteger)appendResponseBytes:(uint8_t*)bytes withLength:(NSUInteger)length error:(NSError**)error 58 | { 59 | NSInteger written = [_stream write:bytes maxLength:length]; 60 | if (written <= 0) [_stream close]; 61 | if ((written < 0) && (error != NULL)) *error = [_stream streamError]; 62 | 63 | return written; 64 | } 65 | 66 | - (id)parseContent:(NSError**)error 67 | { 68 | if (([_stream streamError] != nil) && (error != NULL)) *error = [_stream streamError]; 69 | if ([_stream streamStatus] != NSStreamStatusClosed) [_stream close]; 70 | 71 | // There's never anything to return here, this parser merely pumps data to the output stream. 72 | return nil; 73 | } 74 | 75 | - (void)cleanup 76 | { 77 | if ([_stream streamStatus] != NSStreamStatusClosed) [_stream close]; 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /BBHTTP/Handlers/BBHTTPToStringConverter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPAccumulator.h" 23 | 24 | /** 25 | Simple response parser that extends `` and converts the resulting `NSData` into a UTF-8 26 | encoded `NSString`. 27 | */ 28 | @interface BBHTTPToStringConverter : BBHTTPAccumulator 29 | 30 | 31 | #pragma mark Properties 32 | 33 | @property(assign, nonatomic) NSStringEncoding encoding; 34 | 35 | 36 | #pragma mark Creation 37 | 38 | - (instancetype)initWithEncoding:(NSStringEncoding)encoding; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /BBHTTP/Handlers/BBHTTPToStringConverter.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPToStringConverter.h" 23 | 24 | 25 | 26 | #pragma mark - 27 | 28 | @implementation BBHTTPToStringConverter 29 | 30 | 31 | #pragma mark Creation 32 | 33 | - (instancetype)init 34 | { 35 | return [self initWithEncoding:NSUTF8StringEncoding]; 36 | } 37 | 38 | - (instancetype)initWithEncoding:(NSStringEncoding)encoding 39 | { 40 | self = [super init]; 41 | if (self != nil) _encoding = encoding; 42 | 43 | return self; 44 | } 45 | 46 | 47 | #pragma mark BBHTTPAccumulator behavior override 48 | 49 | - (NSString*)parseContent:(NSError**)error 50 | { 51 | NSData* data = [super parseContent:error]; 52 | if (((error != NULL) && (*error != nil)) || (data == nil)) return nil; 53 | 54 | return [[NSString alloc] initWithData:data encoding:_encoding]; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /BBHTTP/Handlers/BBJSONParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPAccumulator.h" 23 | 24 | 25 | 26 | #pragma mark - 27 | 28 | @interface BBJSONParser : BBHTTPAccumulator 29 | 30 | 31 | #pragma mark Defining default response pre-conditions for JSON parsing 32 | 33 | /** 34 | Affects the `` property for every new instance of this class that is created. 35 | 36 | Use this method if the default acceptable response codes don't fit your needs, as to avoid having to set them up for 37 | every new request. 38 | 39 | @param acceptableResponses Array of numbers. 40 | 41 | @see acceptableResponses 42 | */ 43 | + (void)setDefaultAcceptableResponses:(NSArray*)acceptableResponses; 44 | 45 | /** 46 | Affects the `` property for every new instance of this class that is created. 47 | 48 | Use this method if the default acceptable content types don't fit your needs, as to avoid having to set them up for 49 | every new request. 50 | 51 | @param acceptableContentTypes Array of strings. 52 | 53 | @see acceptableContentTypes 54 | */ 55 | + (void)setDefaultAcceptableContentTypes:(NSArray*)acceptableContentTypes; 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /BBHTTP/Handlers/BBJSONParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBJSONParser.h" 23 | 24 | #import "BBJSONDictionary.h" 25 | 26 | 27 | 28 | #pragma mark - 29 | 30 | @implementation BBJSONParser 31 | 32 | static NSArray* _DefaultAcceptableResponses; 33 | static NSArray* _DefaultAcceptableContentTypes; 34 | 35 | 36 | #pragma mark Class creation 37 | 38 | + (void)initialize 39 | { 40 | _DefaultAcceptableResponses = @[@200, @201, @202, @203]; 41 | _DefaultAcceptableContentTypes = @[@"application/json"]; 42 | } 43 | 44 | 45 | #pragma mark Creation 46 | 47 | - (instancetype)init 48 | { 49 | self = [super init]; 50 | if (self != nil) { 51 | self.acceptableResponses = _DefaultAcceptableResponses; 52 | self.acceptableContentTypes = _DefaultAcceptableContentTypes; 53 | } 54 | 55 | return self; 56 | } 57 | 58 | 59 | #pragma mark Defining response pre-conditions for JSON parsing 60 | 61 | + (void)setDefaultAcceptableResponses:(NSArray*)acceptableResponseCodes 62 | { 63 | _DefaultAcceptableResponses = [acceptableResponseCodes copy]; 64 | } 65 | 66 | + (void)setDefaultAcceptableContentTypes:(NSArray*)acceptableContentTypes 67 | { 68 | _DefaultAcceptableContentTypes = [acceptableContentTypes copy]; 69 | } 70 | 71 | 72 | #pragma mark BBHTTPAccumulator behavior override 73 | 74 | - (id)parseContent:(NSError**)error 75 | { 76 | // super ensures we have a valid response code and a valid content type 77 | NSData* data = [super parseContent:error]; 78 | if (((error != NULL) && (*error != nil)) || (data == nil)) return nil; 79 | 80 | id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:error]; 81 | if (((error != NULL) && (*error != nil)) || (json == nil)) return data; 82 | 83 | // If it's a dictionary, wrap it in BBHTTPDictionary; allows keypath retrieval via subscript operators. 84 | if ([json isKindOfClass:[NSDictionary class]]) return [[BBJSONDictionary alloc] initWithDictionary:json]; 85 | else return json; 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /BBHTTP/Internal/BBHTTPRequest+PrivateInterface.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPRequest.h" 23 | 24 | 25 | 26 | #pragma mark - 27 | 28 | @interface BBHTTPRequest (PrivateInterface) 29 | 30 | 31 | #pragma mark Events 32 | 33 | - (BOOL)executionStarted; 34 | - (BOOL)executionFailedWithFinalResponse:(BBHTTPResponse*)response error:(NSError*)error; 35 | - (BOOL)uploadProgressedToCurrent:(NSUInteger)current ofTotal:(NSUInteger)total; 36 | - (BOOL)downloadProgressedToCurrent:(NSUInteger)current ofTotal:(NSUInteger)total; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /BBHTTP/Internal/BBHTTPRequest+PrivateInterface.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPRequest+PrivateInterface.h" 23 | 24 | #import "BBHTTPUtils.h" 25 | 26 | 27 | 28 | #pragma mark - 29 | 30 | @implementation BBHTTPRequest (PrivateInterface) 31 | 32 | 33 | #pragma mark Events 34 | 35 | - (BOOL)executionStarted 36 | { 37 | if ([self hasFinished]) return NO; 38 | 39 | _startTimestamp = BBHTTPCurrentTimeMillis(); 40 | if (self.startBlock != nil) { 41 | dispatch_async(self.callbackQueue, ^{ 42 | self.startBlock(); 43 | 44 | self.startBlock = nil; 45 | }); 46 | } 47 | 48 | return YES; 49 | } 50 | 51 | - (BOOL)executionFailedWithFinalResponse:(BBHTTPResponse*)response error:(NSError*)error 52 | { 53 | if ([self hasFinished]) return NO; 54 | 55 | _endTimestamp = BBHTTPCurrentTimeMillis(); 56 | _error = error; 57 | _response = response; 58 | 59 | if (self.finishBlock != nil) { 60 | dispatch_async(self.callbackQueue, ^{ 61 | self.finishBlock(self); 62 | 63 | self.uploadProgressBlock = nil; 64 | self.downloadProgressBlock = nil; 65 | self.finishBlock = nil; 66 | }); 67 | } 68 | 69 | return YES; 70 | } 71 | 72 | - (BOOL)uploadProgressedToCurrent:(NSUInteger)current ofTotal:(NSUInteger)total 73 | { 74 | if ([self hasFinished]) return NO; 75 | 76 | _sentBytes = current; 77 | 78 | if (self.uploadProgressBlock != nil) { 79 | dispatch_async(self.callbackQueue, ^{ 80 | self.uploadProgressBlock(current, total); 81 | }); 82 | } 83 | 84 | return YES; 85 | } 86 | 87 | - (BOOL)downloadProgressedToCurrent:(NSUInteger)current ofTotal:(NSUInteger)total 88 | { 89 | if ([self hasFinished]) return NO; 90 | 91 | _receivedBytes = current; 92 | 93 | if (self.downloadProgressBlock != nil) { 94 | dispatch_async(self.callbackQueue, ^{ 95 | self.downloadProgressBlock(current, total); 96 | }); 97 | } 98 | 99 | return YES; 100 | } 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /BBHTTP/Internal/BBHTTPRequestContext.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPRequest.h" 23 | #import "curl.h" 24 | 25 | 26 | 27 | #pragma mark - Enums 28 | 29 | typedef NS_ENUM(NSUInteger, BBHTTPResponseState) { 30 | BBHTTPResponseStateReady = 0, 31 | BBHTTPResponseStateSendingData, 32 | BBHTTPResponseStateReadingStatusLine, 33 | BBHTTPResponseStateReadingHeaders, 34 | BBHTTPResponseStateReadingData, 35 | BBHTTPResponseStateFinished 36 | }; 37 | 38 | 39 | 40 | #pragma mark - 41 | 42 | /** 43 | The `BBHTTPRequestContext` class holds the originating request and all the responses received in its context. 44 | 45 | It mainly serves the purpose of hiding away some of the logic present in transitioning between states in the lifecycle 46 | of an HTTP request/response flow, as well as factoring out some of the logic that `` requires. 47 | As such, has no value outside of it. 48 | */ 49 | @interface BBHTTPRequestContext : NSObject 50 | 51 | 52 | #pragma mark Creating a request context 53 | 54 | /// -------------------------------- 55 | /// @name Creating a request context 56 | /// -------------------------------- 57 | 58 | - (instancetype)initWithRequest:(BBHTTPRequest*)request andCurlHandle:(CURL*)handle; 59 | 60 | 61 | #pragma mark Managing state transitions 62 | 63 | /// -------------------------------- 64 | /// @name Managing state transitions 65 | /// -------------------------------- 66 | 67 | - (BOOL)finishCurrentResponse; 68 | - (BOOL)prepareToReceiveData; 69 | - (void)requestFinished; 70 | - (void)requestFinishedWithError:(NSError*)error; 71 | - (void)cleanup; 72 | 73 | 74 | #pragma mark Managing the upload 75 | 76 | /// ------------------------- 77 | /// @name Managing the upload 78 | /// ------------------------- 79 | 80 | @property(assign, nonatomic, readonly, getter = hasUploadBeenAccepted) BOOL uploadAccepted; 81 | @property(assign, nonatomic, readonly, getter = isUploadPaused) BOOL uploadPaused; 82 | @property(assign, nonatomic, readonly, getter = hasUploadBeenAborted) BOOL uploadAborted; 83 | @property(assign, nonatomic, readonly) NSUInteger uploadedBytes; 84 | @property(assign, nonatomic, readonly) NSUInteger downloadSize; 85 | @property(assign, nonatomic, readonly) NSUInteger downloadedBytes; 86 | 87 | - (void)waitFor100ContinueBeforeUploading; 88 | - (void)pauseUpload; 89 | - (void)unpauseUpload; 90 | - (BOOL)is100ContinueRequired; 91 | - (NSInteger)transferInputToBuffer:(uint8_t*)buffer limit:(NSUInteger)limit; 92 | 93 | 94 | #pragma mark Reading data from the server 95 | 96 | /// ---------------------------------- 97 | /// @name Reading data from the server 98 | /// ---------------------------------- 99 | 100 | - (BOOL)beginResponseWithLine:(NSString*)line; 101 | - (BOOL)addHeaderToCurrentResponse:(NSString*)headerLine; 102 | - (BOOL)appendDataToCurrentResponse:(uint8_t*)bytes withLength:(NSUInteger)length; 103 | 104 | 105 | #pragma mark Querying context information 106 | 107 | /// ---------------------------------- 108 | /// @name Querying context information 109 | /// ---------------------------------- 110 | 111 | @property(strong, nonatomic, readonly) BBHTTPRequest* request; 112 | @property(assign, nonatomic, readonly) CURL* handle; 113 | @property(strong, nonatomic, readonly) NSError* error; 114 | @property(strong, nonatomic, readonly) BBHTTPResponse* currentResponse; 115 | @property(strong, nonatomic, readonly) BBHTTPResponse* lastResponse; 116 | @property(assign, nonatomic, readonly) BBHTTPResponseState state; 117 | 118 | - (BOOL)isCurrentResponse100Continue; 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /BBHTTP/Internal/BBHTTPRequestContext.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBHTTPRequestContext.h" 23 | 24 | #import "BBHTTPRequest+PrivateInterface.h" 25 | #import "BBHTTPUtils.h" 26 | 27 | 28 | 29 | #pragma mark - 30 | 31 | @implementation BBHTTPRequestContext 32 | { 33 | NSMutableArray* _receivedResponses; 34 | NSInputStream* _uploadStream; 35 | BOOL _discardBodyForCurrentResponse; 36 | BOOL _uploadAccepted; 37 | BOOL _uploadPaused; 38 | BOOL _uploadAborted; 39 | } 40 | 41 | 42 | #pragma mark Creating a request context 43 | 44 | - (instancetype)init 45 | { 46 | NSAssert(NO, @"please use initWithRequest:andHandle: instead"); 47 | return nil; 48 | } 49 | 50 | - (instancetype)initWithRequest:(BBHTTPRequest*)request andCurlHandle:(CURL*)handle 51 | { 52 | self = [super init]; 53 | if (self != nil) { 54 | _request = request; 55 | _handle = handle; 56 | 57 | _uploadAborted = NO; 58 | _uploadAccepted = YES; 59 | _uploadPaused = NO; 60 | _receivedResponses = [NSMutableArray array]; 61 | } 62 | 63 | return self; 64 | } 65 | 66 | 67 | #pragma mark Managing state transitions 68 | 69 | - (BOOL)finishCurrentResponse 70 | { 71 | if (_currentResponse == nil) return NO; 72 | 73 | id parsedContent = nil; 74 | 75 | BBHTTPResponseState nextState = BBHTTPResponseStateFinished; // Mark request as finished... 76 | 77 | if ([self isCurrentResponse100Continue]) { 78 | nextState = BBHTTPResponseStateReadingStatusLine; // ... unless it's a 100-Continue; if so, go back to the start 79 | // TODO I'm assuming 100-Continue's never have data... 80 | _uploadAccepted = YES; 81 | } else if (!_discardBodyForCurrentResponse) { 82 | NSError* error = nil; 83 | parsedContent = [_request.responseContentHandler parseContent:&error]; 84 | 85 | if (error != nil) _error = error; 86 | } 87 | 88 | [self switchToState:nextState]; 89 | 90 | [_currentResponse finishWithContent:parsedContent size:_downloadedBytes successful:(_error == nil)]; 91 | BBHTTPResponse* response = _currentResponse; 92 | _currentResponse = nil; 93 | [_receivedResponses addObject:response]; 94 | 95 | if (_error != nil) { 96 | BBHTTPLogDebug(@"%@ | Response with status '%lu' (%@) finished with error parsing content: %@.", 97 | self, (unsigned long)response.code, response.message, [_error localizedDescription]); 98 | return NO; 99 | } else { 100 | BBHTTPLogDebug(@"%@ | Response with status '%lu' (%@) finished.", 101 | self, (unsigned long)response.code, response.message); 102 | return YES; 103 | } 104 | } 105 | 106 | - (BOOL)prepareToReceiveData 107 | { 108 | if (_request.responseContentHandler == nil) { 109 | _discardBodyForCurrentResponse = YES; 110 | BBHTTPLogDebug(@"%@ | Response %lu %@ accepted but content will be discarded (no content handler).", 111 | self, (unsigned long)_currentResponse.code, _currentResponse.message); 112 | } else { 113 | NSError* error = nil; 114 | BOOL parserAcceptsResponse = [_request.responseContentHandler 115 | prepareForResponse:_currentResponse.code message:_currentResponse.message 116 | headers:_currentResponse.headers error:&error]; 117 | 118 | if (!parserAcceptsResponse) { 119 | _discardBodyForCurrentResponse = YES; 120 | if (error != nil) _error = error; 121 | } 122 | 123 | if (_error != nil) { 124 | BBHTTPLogError(@"%@ | Request handler rejected %lu %@ response with error: %@", 125 | self, (unsigned long)_currentResponse.code, _currentResponse.message, 126 | [_error localizedDescription]); 127 | 128 | return NO; 129 | } 130 | 131 | BBHTTPLogDebug(@"%@ | Request handler accepted %lu %@ response.", 132 | self, (unsigned long)_currentResponse.code, _currentResponse.message); 133 | } 134 | 135 | [self switchToState:BBHTTPResponseStateReadingData]; 136 | return YES; 137 | } 138 | 139 | - (void)requestFinished 140 | { 141 | [self finishCurrentResponse]; 142 | [self cleanup]; 143 | 144 | [_request executionFailedWithFinalResponse:[self lastResponse] error:_error]; 145 | } 146 | 147 | - (void)requestFinishedWithError:(NSError*)error 148 | { 149 | if (_error == nil) _error = error; 150 | 151 | [self requestFinished]; 152 | } 153 | 154 | - (void)cleanup 155 | { 156 | if (_uploadStream != nil) [_uploadStream close]; 157 | 158 | if ((_request.responseContentHandler != nil) && 159 | [_request.responseContentHandler respondsToSelector:@selector(cleanup)]) { 160 | [_request.responseContentHandler cleanup]; 161 | } 162 | } 163 | 164 | 165 | #pragma mark Managing the upload 166 | 167 | - (void)waitFor100ContinueBeforeUploading 168 | { 169 | _uploadAccepted = NO; 170 | } 171 | 172 | - (BOOL)hasUploadBeenAccepted 173 | { 174 | return _uploadAccepted; 175 | } 176 | 177 | - (BOOL)isUploadPaused 178 | { 179 | return _uploadPaused; 180 | } 181 | 182 | - (void)pauseUpload 183 | { 184 | _uploadPaused = YES; 185 | } 186 | 187 | - (void)unpauseUpload 188 | { 189 | _uploadPaused = NO; 190 | } 191 | 192 | - (BOOL)hasUploadBeenAborted 193 | { 194 | return _uploadAborted; 195 | } 196 | 197 | - (BOOL)is100ContinueRequired 198 | { 199 | return [_request hasHeader:H(Expect) withValue:HV(100Continue)]; 200 | } 201 | 202 | - (NSInteger)transferInputToBuffer:(uint8_t*)buffer limit:(NSUInteger)limit 203 | { 204 | if (![_request isUpload]) return -1; 205 | 206 | if (_uploadStream == nil) { 207 | [self switchToState:BBHTTPResponseStateSendingData]; 208 | if (_request.uploadStream != nil) { 209 | _uploadStream = _request.uploadStream; 210 | 211 | } else if (_request.uploadFile != nil) { 212 | _uploadStream = [NSInputStream inputStreamWithFileAtPath:_request.uploadFile]; 213 | if (_uploadStream == nil) { 214 | _error = BBHTTPErrorWithReason(BBHTTPErrorCodeUploadFileStreamError, 215 | @"Couldn't upload file", 216 | @"File does not exist or cannot be read."); 217 | return -1; 218 | } 219 | BBHTTPLogTrace(@"%@ | Created input stream from file '%@' for upload.", self, _request.uploadFile); 220 | 221 | } else { 222 | _uploadStream = [NSInputStream inputStreamWithData:_request.uploadData]; 223 | if (_uploadStream == nil) { 224 | _error = BBHTTPErrorWithReason(BBHTTPErrorCodeUploadDataStreamError, 225 | @"Couldn't upload data", 226 | @"Upload data is not instance of NSData."); 227 | return -1; 228 | } 229 | BBHTTPLogTrace(@"%@ | Created input stream from in-memory NSData for upload.", self); 230 | } 231 | 232 | [_uploadStream open]; 233 | } 234 | 235 | NSInteger read = [_uploadStream read:buffer maxLength:limit]; 236 | if (read <= 0) { 237 | BBHTTPLogTrace(@"%@ | Upload stream read %@, closing stream...", self, read == 0 ? @"finished" : @"error"); 238 | [_uploadStream close]; 239 | _uploadStream = nil; 240 | } else { 241 | _uploadedBytes += read; 242 | [_request uploadProgressedToCurrent:_uploadedBytes ofTotal:_request.uploadSize]; 243 | BBHTTPLogTrace(@"%@ | Transferred %ldb to server.", self, (long)read); 244 | if (read < limit) { 245 | BBHTTPLogTrace(@"%@ | Upload finished.", self); 246 | [self uploadFinished]; 247 | } 248 | } 249 | 250 | return read; 251 | } 252 | 253 | 254 | #pragma mark Reading data from the server 255 | 256 | - (BOOL)beginResponseWithLine:(NSString*)line 257 | { 258 | if (_currentResponse != nil) [self finishCurrentResponse]; 259 | 260 | _uploadedBytes = 0; 261 | _downloadSize = 0; 262 | _downloadedBytes = 0; 263 | _discardBodyForCurrentResponse = NO; 264 | _currentResponse = [BBHTTPResponse responseWithStatusLine:line]; 265 | if (_currentResponse == nil) return NO; // May happen if line is not a valid status response line 266 | 267 | BBHTTPLogDebug(@"%@ | Receiving response with line '%@'.", self, line); 268 | if ([_request isUpload] && (_currentResponse.code >= 300)) { 269 | _uploadAborted = YES; 270 | BBHTTPLogTrace(@"%@ | ShouldAbortUpload flag set (final non-success response received)", self); 271 | } 272 | 273 | [self switchToState:BBHTTPResponseStateReadingHeaders]; 274 | return YES; 275 | } 276 | 277 | - (BOOL)addHeaderToCurrentResponse:(NSString*)line 278 | { 279 | if (_currentResponse == nil) return NO; 280 | 281 | return [self parseHeaderLine:line andAddToResponse:_currentResponse]; 282 | } 283 | 284 | - (BOOL)appendDataToCurrentResponse:(uint8_t*)bytes withLength:(NSUInteger)length 285 | { 286 | if (_currentResponse == nil) return NO; 287 | if (_discardBodyForCurrentResponse) return YES; 288 | 289 | if ([self transferBytes:bytes withLength:length toHandler:_request.responseContentHandler]) { 290 | _downloadedBytes += length; 291 | [_request downloadProgressedToCurrent:_downloadedBytes ofTotal:_downloadSize]; 292 | return YES; 293 | } 294 | 295 | return NO; 296 | } 297 | 298 | 299 | #pragma mark Querying context information 300 | 301 | - (BBHTTPResponse*)lastResponse 302 | { 303 | return [_receivedResponses lastObject]; 304 | } 305 | 306 | - (BOOL)isCurrentResponse100Continue 307 | { 308 | if (_currentResponse == nil) return NO; 309 | 310 | return _currentResponse.code == 100; 311 | } 312 | 313 | 314 | #pragma mark Private helpers 315 | 316 | - (void)uploadFinished 317 | { 318 | [self switchToState:BBHTTPResponseStateReadingStatusLine]; 319 | } 320 | 321 | - (BOOL)parseHeaderLine:(NSString*)headerLine andAddToResponse:(BBHTTPResponse*)response 322 | { 323 | if (headerLine == nil) return NO; 324 | 325 | NSRange range = [headerLine rangeOfString:@": "]; 326 | if (range.location == NSNotFound) return NO; 327 | 328 | NSString* headerName = [headerLine substringToIndex:range.location]; 329 | NSString* headerValue = [headerLine substringFromIndex:NSMaxRange(range)]; 330 | [response setValue:headerValue forHeader:headerName]; 331 | 332 | // If it's the Content-Length header, set our expected download size 333 | if ([headerName isEqualToString:H(ContentLength)]) _downloadSize = (NSUInteger)[headerValue integerValue]; 334 | 335 | BBHTTPLogTrace(@"%@ | Received header '%@: %@'.", self, headerName, headerValue); 336 | 337 | return YES; 338 | } 339 | 340 | - (BOOL)transferBytes:(uint8_t*)bytes withLength:(NSUInteger)length toHandler:(id)handler 341 | { 342 | NSError* error = nil; 343 | NSInteger written = [handler appendResponseBytes:bytes withLength:length error:&error]; 344 | if (error != nil) { 345 | _error = error; 346 | BBHTTPLogError(@"%@ | Error raised while attempting to transfer %lub to response content handler: %@", 347 | self, (unsigned long)length, [error localizedDescription]); 348 | return NO; 349 | } else if (written < length) { 350 | _error = BBHTTPErrorWithReason(BBHTTPErrorCodeDownloadCannotWriteToHandler, 351 | @"Error handling response content", 352 | @"Response handler capacity reached before content was fully read."); 353 | BBHTTPLogError(@"%@ | Could only write %ld bytes to response handler (expecting %lu)", 354 | self, (long)written, (unsigned long)length); 355 | return NO; 356 | } 357 | 358 | BBHTTPLogTrace(@"%@ | Transferred %lub to response content handler.", self, (unsigned long)length); 359 | return YES; 360 | } 361 | 362 | - (void)switchToState:(BBHTTPResponseState)state 363 | { 364 | BBHTTPResponseState oldState = _state; 365 | _state = state; 366 | BBHTTPLogTrace(@"%@ | Transitioned from state: '%@'", self, [self humanReadableState:oldState]); 367 | } 368 | 369 | 370 | #pragma mark Debug 371 | 372 | - (NSString*)humanReadableState:(BBHTTPResponseState)state 373 | { 374 | switch (state) { 375 | case BBHTTPResponseStateReady: 376 | if ([_request isUpload]) return @"wait send "; 377 | else return @"wait resp "; 378 | case BBHTTPResponseStateSendingData: 379 | return @"tx request"; 380 | case BBHTTPResponseStateReadingStatusLine: 381 | return @"wait resp "; 382 | case BBHTTPResponseStateReadingHeaders: 383 | return @"rx headers"; 384 | case BBHTTPResponseStateReadingData: 385 | return @"rx content"; 386 | default: 387 | return @"terminated"; 388 | } 389 | } 390 | 391 | - (NSString*)description 392 | { 393 | return [NSString stringWithFormat:@"%@ | %@", _request, [self humanReadableState:_state]]; 394 | } 395 | 396 | @end 397 | -------------------------------------------------------------------------------- /BBHTTP/Internal/BBHTTPUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #pragma mark - Constants 23 | 24 | #define BBHTTPVersion @"0.9.9" 25 | 26 | 27 | 28 | #pragma mark - Error codes 29 | 30 | #define BBHTTPErrorCodeCancelled 1000 31 | #define BBHTTPErrorCodeUploadFileStreamError 1001 32 | #define BBHTTPErrorCodeUploadDataStreamError 1002 33 | #define BBHTTPErrorCodeDownloadCannotWriteToHandler 1003 34 | #define BBHTTPErrorCodeUnnacceptableContentType 1004 35 | #define BBHTTPErrorCodeImageDecodingFailed 1005 36 | 37 | 38 | 39 | #pragma mark - Logging 40 | 41 | #define BBHTTPLogLevelOff 0 42 | #define BBHTTPLogLevelError 1 43 | #define BBHTTPLogLevelWarn 2 44 | #define BBHTTPLogLevelInfo 3 45 | #define BBHTTPLogLevelDebug 4 46 | #define BBHTTPLogLevelTrace 5 47 | 48 | extern NSUInteger BBHTTPLogLevel; 49 | 50 | extern void BBHTTPLog(NSUInteger level, NSString* prefix, NSString* (^statement)()); 51 | 52 | #define BBHTTPLogError(fmt, ...) BBHTTPLog(1, @"ERROR", ^{ return [NSString stringWithFormat:fmt, ##__VA_ARGS__]; }); 53 | #define BBHTTPLogWarn(fmt, ...) BBHTTPLog(2, @" WARN", ^{ return [NSString stringWithFormat:fmt, ##__VA_ARGS__]; }); 54 | #define BBHTTPLogInfo(fmt, ...) BBHTTPLog(3, @" INFO", ^{ return [NSString stringWithFormat:fmt, ##__VA_ARGS__]; }); 55 | #define BBHTTPLogDebug(fmt, ...) BBHTTPLog(4, @"DEBUG", ^{ return [NSString stringWithFormat:fmt, ##__VA_ARGS__]; }); 56 | #define BBHTTPLogTrace(fmt, ...) BBHTTPLog(5, @"TRACE", ^{ return [NSString stringWithFormat:fmt, ##__VA_ARGS__]; }); 57 | #define BBHTTPCurlDebug(fmt, ...) BBHTTPLog(1, @" CURL", ^{ return [NSString stringWithFormat:fmt, ##__VA_ARGS__]; }); 58 | 59 | 60 | 61 | #pragma mark - DRY macros 62 | 63 | #define BBHTTPErrorWithFormat(c, fmt, ...) \ 64 | [NSError errorWithDomain:@"com.biasedbit.http" code:c \ 65 | userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:fmt, ##__VA_ARGS__]}] 66 | 67 | // We need this variant because passing a non-statically initialized NSString* instance as fmt raises a warning 68 | #define BBHTTPError(c, description) \ 69 | [NSError errorWithDomain:@"com.biasedbit.http" code:c \ 70 | userInfo:@{NSLocalizedDescriptionKey: description}] 71 | 72 | #define BBHTTPErrorWithReason(c, description, reason) \ 73 | [NSError errorWithDomain:@"com.biasedbit.http" code:c \ 74 | userInfo:@{NSLocalizedDescriptionKey: description, NSLocalizedFailureReasonErrorKey: reason}] 75 | 76 | #define BBHTTPEnsureNotNil(value) NSAssert((value) != nil, @"%s cannot be nil", #value) 77 | 78 | #define BBHTTPEnsureSuccessOrReturn0(condition) do { if (!(condition)) return 0; } while(0) 79 | 80 | #define BBHTTPSingleton(class, name, value) \ 81 | static class* name = nil; \ 82 | if (name == nil) { \ 83 | static dispatch_once_t name ## _token; \ 84 | dispatch_once(&name##_token, ^{ name = value; }); \ 85 | } 86 | 87 | #define BBHTTPSingletonString(name, fmt, ...) \ 88 | static NSString* name = nil; \ 89 | if (name == nil) { \ 90 | static dispatch_once_t name ## _token; \ 91 | dispatch_once(&name##_token, ^{ name = [NSString stringWithFormat:fmt, ##__VA_ARGS__]; }); \ 92 | } 93 | 94 | #define BBHTTPSingletonBlock(class, name, block) \ 95 | static class* name = nil; \ 96 | if (name == nil) { \ 97 | static dispatch_once_t name ## _token; \ 98 | dispatch_once(&name##_token, block); \ 99 | } 100 | 101 | #define BBHTTPDefineHeaderName(name, override) static NSString* const BBHTTPHeaderName_##name = (override); 102 | #define BBHTTPDefineHeaderValue(value, override) static NSString* const BBHTTPHeaderValue_##value = (override); 103 | #define H(name) BBHTTPHeaderName_##name 104 | #define HV(value) BBHTTPHeaderValue_##value 105 | 106 | 107 | 108 | #pragma mark - Headers names 109 | 110 | BBHTTPDefineHeaderName(Host, @"Host") // Will create BBHTTPHeaderName_Host 111 | BBHTTPDefineHeaderName(UserAgent, @"User-Agent") 112 | BBHTTPDefineHeaderName(ContentType, @"Content-Type") 113 | BBHTTPDefineHeaderName(ContentLength, @"Content-Length") 114 | BBHTTPDefineHeaderName(Accept, @"Accept") 115 | BBHTTPDefineHeaderName(AcceptLanguage, @"Accept-Language") 116 | BBHTTPDefineHeaderName(Expect, @"Expect") 117 | BBHTTPDefineHeaderName(TransferEncoding, @"Transfer-Encoding") 118 | BBHTTPDefineHeaderName(Date, @"Date") 119 | BBHTTPDefineHeaderName(Authorization, @"Authorization") 120 | 121 | 122 | 123 | #pragma mark - Header values 124 | 125 | BBHTTPDefineHeaderValue(100Continue, @"100-Continue") // Will create BBHTTPHeaderValue_100Continue 126 | BBHTTPDefineHeaderValue(Chunked, @"chunked") 127 | 128 | 129 | 130 | #pragma mark - Utility functions 131 | 132 | extern NSString* BBHTTPMimeType(NSString* file); 133 | extern long long BBHTTPCurrentTimeMillis(void); 134 | extern NSString* BBHTTPURLEncode(NSString* string, NSStringEncoding encoding); 135 | -------------------------------------------------------------------------------- /BBHTTP/Internal/BBHTTPUtils.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #include "BBHTTPUtils.h" 23 | 24 | #import 25 | 26 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 27 | #import 28 | #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) 29 | #import 30 | #endif 31 | 32 | 33 | 34 | #pragma mark - Logging 35 | 36 | NSUInteger BBHTTPLogLevel = BBHTTPLogLevelWarn; 37 | 38 | void BBHTTPLog(NSUInteger level, NSString* prefix, NSString* (^statement)()) 39 | { 40 | // The block logging approach does incur some overhead but since default log level is WARN, the number of 41 | // statements supressed (trace, debug & info) is so high that it compensates to not evaluate the formatted 42 | // expression for these cases. 43 | if (level <= BBHTTPLogLevel) NSLog(@"BBHTTP | %@ | %@", prefix, statement()); 44 | } 45 | 46 | 47 | 48 | #pragma mark - Utility functions 49 | 50 | NSString* BBHTTPMimeType(NSString* file) 51 | { 52 | #ifndef __UTTYPE__ 53 | return @"application/octet-stream"; 54 | #else 55 | NSString* ext = [file pathExtension]; 56 | if (ext == nil) return @"application/octet-stream"; 57 | 58 | CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, 59 | (__bridge CFStringRef)ext, NULL); 60 | if (!UTI) return nil; 61 | 62 | CFStringRef registeredType = UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType); 63 | CFRelease(UTI); 64 | 65 | if (!registeredType) return @"application/octet-stream"; 66 | else return CFBridgingRelease(registeredType); 67 | #endif 68 | } 69 | 70 | long long BBHTTPCurrentTimeMillis() 71 | { 72 | struct timeval t; 73 | gettimeofday(&t, NULL); 74 | 75 | return (((int64_t) t.tv_sec) * 1000) + (((int64_t) t.tv_usec) / 1000); 76 | } 77 | 78 | NSString* BBHTTPURLEncode(NSString* string, NSStringEncoding encoding) 79 | { 80 | return (__bridge_transfer NSString*) 81 | CFURLCreateStringByAddingPercentEscapes(NULL, 82 | (__bridge CFStringRef)string, 83 | NULL, 84 | (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", 85 | CFStringConvertNSStringEncodingToEncoding(encoding)); 86 | } 87 | -------------------------------------------------------------------------------- /BBHTTP/Internal/BBJSONDictionary.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #pragma mark - 23 | 24 | /** 25 | Surrogate for `NSDictionary` that makes the subscript operator call `valueForKeyPath:` on the wrapped dictionary 26 | — instead of the default behavior, which is to call `valueForKey:` — and forwards every other invocation. 27 | */ 28 | @interface BBJSONDictionary : NSObject 29 | 30 | 31 | #pragma mark Creating a surrogate 32 | 33 | ///--------------------------- 34 | /// @name Creating a surrogate 35 | ///--------------------------- 36 | 37 | /** 38 | Creates a new dictionary surrogate for the given dictionary. 39 | 40 | @param dictionary Dictionary to wrap. 41 | 42 | @return A surrogate for the dictionary. 43 | */ 44 | - (instancetype)initWithDictionary:(NSDictionary*)dictionary; 45 | 46 | 47 | #pragma mark NSDictionary behavior override 48 | 49 | ///------------------------------------- 50 | /// @name NSDictionary behavior override 51 | ///------------------------------------- 52 | 53 | /** 54 | Calls `valueForKeyPath:` on the underlying dictionary. 55 | 56 | @param key Keypath expression to apply to the underlying dictionary. 57 | 58 | @return Value for the given keypath expression. 59 | */ 60 | - (id)objectForKeyedSubscript:(NSString*)key; 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /BBHTTP/Internal/BBJSONDictionary.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "BBJSONDictionary.h" 23 | 24 | 25 | 26 | #pragma mark - 27 | 28 | @implementation BBJSONDictionary 29 | { 30 | NSDictionary* _dictionary; 31 | } 32 | 33 | #pragma mark Creating a surrogate 34 | 35 | - (instancetype)initWithDictionary:(NSDictionary*)dictionary 36 | { 37 | self = [super init]; 38 | if (self != nil) _dictionary = dictionary; 39 | 40 | return self; 41 | } 42 | 43 | 44 | #pragma mark NSDictionary behavior override 45 | 46 | - (id)objectForKeyedSubscript:(NSString*)key 47 | { 48 | return [_dictionary valueForKeyPath:key]; 49 | } 50 | 51 | - (id)forwardingTargetForSelector:(SEL)selector 52 | { 53 | // Docs state that forwardingTargetForSelector "(...) can be an order of magnitude faster than regular forwarding." 54 | if ([_dictionary respondsToSelector:selector]) return _dictionary; 55 | return nil; 56 | } 57 | 58 | - (NSString*)description 59 | { 60 | return [_dictionary description]; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | ## 0.9.9 2 | 3 | #### September 26th, 2013 4 | 5 | * Add form encoded POST 6 | * Update to libcurl 7.32.0 7 | * Update project file for Xcode 5 8 | 9 | ## 0.9.5 10 | 11 | #### March 30th, 2013 12 | 13 | * Add configurable upload and download speed limits (issue #3) 14 | * Add configurable download timeout condition (issue #13) 15 | * Change all init methods to return `instancetype` instead of `id` 16 | * Remove unnecessary (and wrong) condition on upload and download transfer speeds query methods (`BBHTTPRequest`) that caused it to always report 0b/s until the request finished. 17 | 18 | 19 | ## 0.9.4 20 | 21 | #### March 21st, 2013 22 | 23 | * Ensure that the last `BBHTTPResponse` is always preserved as part of the `BBHTTPRequest`, even if the response content parser rejects the response. 24 | 25 | Previously only the error message (status code and status message) were being preserved, which led to `wasSuccessfullyExecuted` incorrectly reporting `NO`. 26 | 27 | 28 | ## 0.9.3 29 | 30 | #### March 19th, 2013 31 | 32 | * Added support to specify custom encoding when decoding response contents to NSString (issue #10) 33 | * Add cancel handling block when using convenience executors 34 | * Add missing interface declaration for `asImage` on convenience executors 35 | * Renamed from BBHotpotato to BBHTTP 36 | -------------------------------------------------------------------------------- /Docs/generate: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" 3 | 4 | rm -rf ${SCRIPT_DIR}/html 5 | rm -rf ${SCRIPT_DIR}/docset 6 | rm -rf ${SCRIPT_DIR}/publish 7 | 8 | appledoc \ 9 | \ 10 | --keep-intermediate-files \ 11 | --no-create-docset \ 12 | --no-install-docset \ 13 | --keep-undocumented-objects \ 14 | --keep-undocumented-members \ 15 | --no-repeat-first-par \ 16 | --no-warn-undocumented-object \ 17 | --no-warn-undocumented-member \ 18 | --explicit-crossref \ 19 | --keep-merged-sections \ 20 | \ 21 | --project-name BBHTTP \ 22 | --project-company BiasedBit \ 23 | --company-id com.biasedbit \ 24 | --ignore .m \ 25 | --index-desc ${SCRIPT_DIR}/index.md \ 26 | --output ${SCRIPT_DIR} \ 27 | \ 28 | ${SCRIPT_DIR}/../BBHTTP 29 | -------------------------------------------------------------------------------- /Docs/index.md: -------------------------------------------------------------------------------- 1 | BBHTTP is a rich wrapper for libcurl written in Objective-C. 2 | 3 | It is an ARC-only library that uses features introduced by Clang 3.1. Thus, it is only suitable for iOS 5+ and OSX 10.7+. 4 | 5 | ## Useful links: 6 | 7 | * [Project page](https://github.com/brunodecarvalho/BBHTTP) 8 | * [Issue tracker](https://github.com/brunodecarvalho/BBHTTP/issues) 9 | * [Wiki](https://github.com/brunodecarvalho/BBHTTP/wiki) 10 | * [Build your own curl binaries](https://github.com/brunodecarvalho/curl-ios-build-scripts) 11 | 12 | You can also shoot me an email to *bruno at biasedbit.com* or ping me on twitter [@biasedbit](http://twitter.com/biasedbit). 13 | -------------------------------------------------------------------------------- /Example/OSX Sample app/Classes/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #pragma mark - 23 | 24 | @interface AppDelegate : NSObject 25 | 26 | 27 | #pragma mark Properties 28 | 29 | @property(weak, nonatomic) IBOutlet NSWindow* window; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Example/OSX Sample app/Classes/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "AppDelegate.h" 23 | 24 | #import "BBHTTP.h" 25 | 26 | 27 | 28 | #pragma mark - 29 | 30 | @implementation AppDelegate 31 | 32 | 33 | #pragma mark NSApplicationDelegate 34 | 35 | - (void)applicationDidFinishLaunching:(NSNotification*)notification 36 | { 37 | [self getImageExample]; 38 | // [self getExample]; 39 | } 40 | 41 | - (void)getImageExample 42 | { 43 | [[BBHTTPRequest readResource:@"http://biasedbit.com/images/badge_dark.png"] setup:^(id request) { 44 | [request downloadContentAsImage]; // alternative to 'asImage' fluent syntax 45 | } execute:^(BBHTTPResponse* response) { 46 | NSImage* image = response.content; 47 | NSLog(@"image size: %@", NSStringFromSize(image.size)); 48 | } error:^(NSError* error) { 49 | NSLog(@"Error: %@", [error localizedDescription]); 50 | }]; 51 | } 52 | 53 | - (void)getExample 54 | { 55 | [[BBHTTPRequest readResource:@"http://biasedbit.com"] execute:^(BBHTTPResponse* response) { 56 | NSLog(@"Finished: %lu %@ -- received %lu bytes of '%@' %@", 57 | response.code, response.message, response.contentSize, 58 | response[@"Content-Type"], response.headers); 59 | } error:^(NSError* error) { 60 | NSLog(@"Error: %@", [error localizedDescription]); 61 | }]; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /Example/OSX Sample app/Supporting Files/OSX Sample app-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.biasedbit.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /Example/OSX Sample app/Supporting Files/OSX Sample app-Prefix.pch: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | -------------------------------------------------------------------------------- /Example/OSX Sample app/Supporting Files/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/OSX Sample app/Supporting Files/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // OSX Sample app 4 | // 5 | // Created by Bruno de Carvalho on 2/24/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /Example/iOS Sample app/Classes/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #pragma mark - 23 | 24 | @interface AppDelegate : UIResponder 25 | @end 26 | -------------------------------------------------------------------------------- /Example/iOS Sample app/Classes/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import "AppDelegate.h" 23 | 24 | #import "BBHTTP.h" 25 | 26 | 27 | 28 | #pragma mark - 29 | 30 | @implementation AppDelegate 31 | 32 | 33 | #pragma mark UIApplicationDelegate 34 | 35 | - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions 36 | { 37 | [self getImageExample]; 38 | // [self getJsonExample]; 39 | // [self getExample]; 40 | // [self postExample]; 41 | 42 | return YES; 43 | } 44 | 45 | - (void)getImageExample 46 | { 47 | [[BBHTTPRequest readResource:@"http://biasedbit.com/images/badge_dark.png"] setup:^(id request) { 48 | [request downloadContentAsImage]; // alternative to 'asImage' fluent syntax 49 | } execute:^(BBHTTPResponse* response) { 50 | UIImage* image = response.content; 51 | NSLog(@"image size: %@", NSStringFromCGSize(image.size)); 52 | } error:^(NSError* error) { 53 | NSLog(@"Error: %@", [error localizedDescription]); 54 | }]; 55 | } 56 | 57 | - (void)getJsonExample 58 | { 59 | NSString* yahooWeather = @"http://query.yahooapis.com/v1/public/yql?format=json&q=" 60 | "select%20*%20from%20weather.forecast%20where%20woeid%3D2502265"; 61 | 62 | [[[BBHTTPRequest readResource:yahooWeather] asJSON] execute:^(BBHTTPResponse* response) { 63 | NSLog(@"%@: %@", 64 | response.content[@"query.results.channel.description"], 65 | response.content[@"query.results.channel.item.condition.text"]); 66 | // DOBJ(response.content); // dump the whole JSON response 67 | 68 | } error:^(NSError* error) { 69 | NSLog(@"Error: %@", [error localizedDescription]); 70 | }]; 71 | } 72 | 73 | - (void)getExample 74 | { 75 | [[BBHTTPRequest readResource:@"http://biasedbit.com"] execute:^(BBHTTPResponse* response) { 76 | NSLog(@"Finished: %u %@ -- received %u bytes of '%@' %@", 77 | response.code, response.message, response.contentSize, 78 | response[@"Content-Type"], response.headers); 79 | 80 | } error:^(NSError* error) { 81 | NSLog(@"Error: %@", [error localizedDescription]); 82 | }]; 83 | } 84 | 85 | - (void)postExample 86 | { 87 | BBHTTPRequest* upload = [BBHTTPRequest createResource:@"http://target.api/" withContentsOfFile:@"/path/to/file"]; 88 | upload.uploadProgressBlock = ^(NSUInteger current, NSUInteger total) { 89 | NSLog(@"--> %u/%u", current, total); 90 | }; 91 | upload.downloadProgressBlock = ^(NSUInteger current, NSUInteger total) { 92 | NSLog(@"<== %u/%u%@", current, total, total == 0 ? @" (chunked download, total size unknown)" : @""); 93 | }; 94 | 95 | [upload setup:^(BBHTTPRequest* request) { 96 | request[@"User-Agent"] = @"<3 subscript operators"; 97 | } execute:^(BBHTTPResponse* response) { 98 | NSLog(@"%@ %u %@ %@", NSStringFromBBHTTPProtocolVersion(response.version), 99 | response.code, response.message, response.headers); 100 | } error:^(NSError* error) { 101 | NSLog(@"Error: %@", [error localizedDescription]); 102 | }]; 103 | } 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /Example/iOS Sample app/Resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/biasedbit/BBHTTP/c5cfe0f5d5d5ac75a873ca9fba77aaa2756ac463/Example/iOS Sample app/Resources/Default-568h@2x.png -------------------------------------------------------------------------------- /Example/iOS Sample app/Resources/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/biasedbit/BBHTTP/c5cfe0f5d5d5ac75a873ca9fba77aaa2756ac463/Example/iOS Sample app/Resources/Default.png -------------------------------------------------------------------------------- /Example/iOS Sample app/Resources/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/biasedbit/BBHTTP/c5cfe0f5d5d5ac75a873ca9fba77aaa2756ac463/Example/iOS Sample app/Resources/Default@2x.png -------------------------------------------------------------------------------- /Example/iOS Sample app/Supporting Files/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/iOS Sample app/Supporting Files/iOS Sample app-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.biasedbit.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Example/iOS Sample app/Supporting Files/iOS Sample app-Prefix.pch: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | -------------------------------------------------------------------------------- /Example/iOS Sample app/Supporting Files/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // iOS Sample app 4 | // 5 | // Created by Bruno de Carvalho on 2/24/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /External/libcurl.OSX/curlbuild.h: -------------------------------------------------------------------------------- 1 | /* include/curl/curlbuild.h. Generated from curlbuild.h.in by configure. */ 2 | #ifndef __CURL_CURLBUILD_H 3 | #define __CURL_CURLBUILD_H 4 | /*************************************************************************** 5 | * _ _ ____ _ 6 | * Project ___| | | | _ \| | 7 | * / __| | | | |_) | | 8 | * | (__| |_| | _ <| |___ 9 | * \___|\___/|_| \_\_____| 10 | * 11 | * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. 12 | * 13 | * This software is licensed as described in the file COPYING, which 14 | * you should have received as part of this distribution. The terms 15 | * are also available at http://curl.haxx.se/docs/copyright.html. 16 | * 17 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell 18 | * copies of the Software, and permit persons to whom the Software is 19 | * furnished to do so, under the terms of the COPYING file. 20 | * 21 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 22 | * KIND, either express or implied. 23 | * 24 | ***************************************************************************/ 25 | 26 | /* ================================================================ */ 27 | /* NOTES FOR CONFIGURE CAPABLE SYSTEMS */ 28 | /* ================================================================ */ 29 | 30 | /* 31 | * NOTE 1: 32 | * ------- 33 | * 34 | * Nothing in this file is intended to be modified or adjusted by the 35 | * curl library user nor by the curl library builder. 36 | * 37 | * If you think that something actually needs to be changed, adjusted 38 | * or fixed in this file, then, report it on the libcurl development 39 | * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/ 40 | * 41 | * This header file shall only export symbols which are 'curl' or 'CURL' 42 | * prefixed, otherwise public name space would be polluted. 43 | * 44 | * NOTE 2: 45 | * ------- 46 | * 47 | * Right now you might be staring at file include/curl/curlbuild.h.in or 48 | * at file include/curl/curlbuild.h, this is due to the following reason: 49 | * 50 | * On systems capable of running the configure script, the configure process 51 | * will overwrite the distributed include/curl/curlbuild.h file with one that 52 | * is suitable and specific to the library being configured and built, which 53 | * is generated from the include/curl/curlbuild.h.in template file. 54 | * 55 | */ 56 | 57 | /* ================================================================ */ 58 | /* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */ 59 | /* ================================================================ */ 60 | 61 | #ifdef CURL_SIZEOF_LONG 62 | #error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" 63 | Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined 64 | #endif 65 | 66 | #ifdef CURL_TYPEOF_CURL_SOCKLEN_T 67 | #error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" 68 | Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined 69 | #endif 70 | 71 | #ifdef CURL_SIZEOF_CURL_SOCKLEN_T 72 | #error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" 73 | Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined 74 | #endif 75 | 76 | #ifdef CURL_TYPEOF_CURL_OFF_T 77 | #error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" 78 | Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined 79 | #endif 80 | 81 | #ifdef CURL_FORMAT_CURL_OFF_T 82 | #error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" 83 | Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined 84 | #endif 85 | 86 | #ifdef CURL_FORMAT_CURL_OFF_TU 87 | #error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" 88 | Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined 89 | #endif 90 | 91 | #ifdef CURL_FORMAT_OFF_T 92 | #error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" 93 | Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined 94 | #endif 95 | 96 | #ifdef CURL_SIZEOF_CURL_OFF_T 97 | #error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" 98 | Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined 99 | #endif 100 | 101 | #ifdef CURL_SUFFIX_CURL_OFF_T 102 | #error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" 103 | Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined 104 | #endif 105 | 106 | #ifdef CURL_SUFFIX_CURL_OFF_TU 107 | #error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" 108 | Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined 109 | #endif 110 | 111 | /* ================================================================ */ 112 | /* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */ 113 | /* ================================================================ */ 114 | 115 | /* Configure process defines this to 1 when it finds out that system */ 116 | /* header file ws2tcpip.h must be included by the external interface. */ 117 | /* #undef CURL_PULL_WS2TCPIP_H */ 118 | #ifdef CURL_PULL_WS2TCPIP_H 119 | # ifndef WIN32_LEAN_AND_MEAN 120 | # define WIN32_LEAN_AND_MEAN 121 | # endif 122 | # include 123 | # include 124 | # include 125 | #endif 126 | 127 | /* Configure process defines this to 1 when it finds out that system */ 128 | /* header file sys/types.h must be included by the external interface. */ 129 | #define CURL_PULL_SYS_TYPES_H 1 130 | #ifdef CURL_PULL_SYS_TYPES_H 131 | # include 132 | #endif 133 | 134 | /* Configure process defines this to 1 when it finds out that system */ 135 | /* header file stdint.h must be included by the external interface. */ 136 | /* #undef CURL_PULL_STDINT_H */ 137 | #ifdef CURL_PULL_STDINT_H 138 | # include 139 | #endif 140 | 141 | /* Configure process defines this to 1 when it finds out that system */ 142 | /* header file inttypes.h must be included by the external interface. */ 143 | /* #undef CURL_PULL_INTTYPES_H */ 144 | #ifdef CURL_PULL_INTTYPES_H 145 | # include 146 | #endif 147 | 148 | /* Configure process defines this to 1 when it finds out that system */ 149 | /* header file sys/socket.h must be included by the external interface. */ 150 | #define CURL_PULL_SYS_SOCKET_H 1 151 | #ifdef CURL_PULL_SYS_SOCKET_H 152 | # include 153 | #endif 154 | 155 | /* Configure process defines this to 1 when it finds out that system */ 156 | /* header file sys/poll.h must be included by the external interface. */ 157 | /* #undef CURL_PULL_SYS_POLL_H */ 158 | #ifdef CURL_PULL_SYS_POLL_H 159 | # include 160 | #endif 161 | 162 | /* The size of `long', as computed by sizeof. */ 163 | #define CURL_SIZEOF_LONG 8 164 | 165 | /* Integral data type used for curl_socklen_t. */ 166 | #define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t 167 | 168 | /* The size of `curl_socklen_t', as computed by sizeof. */ 169 | #define CURL_SIZEOF_CURL_SOCKLEN_T 4 170 | 171 | /* Data type definition of curl_socklen_t. */ 172 | typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; 173 | 174 | /* Signed integral data type used for curl_off_t. */ 175 | #define CURL_TYPEOF_CURL_OFF_T long 176 | 177 | /* Data type definition of curl_off_t. */ 178 | typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; 179 | 180 | /* curl_off_t formatting string directive without "%" conversion specifier. */ 181 | #define CURL_FORMAT_CURL_OFF_T "ld" 182 | 183 | /* unsigned curl_off_t formatting string without "%" conversion specifier. */ 184 | #define CURL_FORMAT_CURL_OFF_TU "lu" 185 | 186 | /* curl_off_t formatting string directive with "%" conversion specifier. */ 187 | #define CURL_FORMAT_OFF_T "%ld" 188 | 189 | /* The size of `curl_off_t', as computed by sizeof. */ 190 | #define CURL_SIZEOF_CURL_OFF_T 8 191 | 192 | /* curl_off_t constant suffix. */ 193 | #define CURL_SUFFIX_CURL_OFF_T L 194 | 195 | /* unsigned curl_off_t constant suffix. */ 196 | #define CURL_SUFFIX_CURL_OFF_TU UL 197 | 198 | #endif /* __CURL_CURLBUILD_H */ 199 | -------------------------------------------------------------------------------- /External/libcurl.OSX/curlrules.h: -------------------------------------------------------------------------------- 1 | #ifndef __CURL_CURLRULES_H 2 | #define __CURL_CURLRULES_H 3 | /*************************************************************************** 4 | * _ _ ____ _ 5 | * Project ___| | | | _ \| | 6 | * / __| | | | |_) | | 7 | * | (__| |_| | _ <| |___ 8 | * \___|\___/|_| \_\_____| 9 | * 10 | * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. 11 | * 12 | * This software is licensed as described in the file COPYING, which 13 | * you should have received as part of this distribution. The terms 14 | * are also available at http://curl.haxx.se/docs/copyright.html. 15 | * 16 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell 17 | * copies of the Software, and permit persons to whom the Software is 18 | * furnished to do so, under the terms of the COPYING file. 19 | * 20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21 | * KIND, either express or implied. 22 | * 23 | ***************************************************************************/ 24 | 25 | /* ================================================================ */ 26 | /* COMPILE TIME SANITY CHECKS */ 27 | /* ================================================================ */ 28 | 29 | /* 30 | * NOTE 1: 31 | * ------- 32 | * 33 | * All checks done in this file are intentionally placed in a public 34 | * header file which is pulled by curl/curl.h when an application is 35 | * being built using an already built libcurl library. Additionally 36 | * this file is also included and used when building the library. 37 | * 38 | * If compilation fails on this file it is certainly sure that the 39 | * problem is elsewhere. It could be a problem in the curlbuild.h 40 | * header file, or simply that you are using different compilation 41 | * settings than those used to build the library. 42 | * 43 | * Nothing in this file is intended to be modified or adjusted by the 44 | * curl library user nor by the curl library builder. 45 | * 46 | * Do not deactivate any check, these are done to make sure that the 47 | * library is properly built and used. 48 | * 49 | * You can find further help on the libcurl development mailing list: 50 | * http://cool.haxx.se/mailman/listinfo/curl-library/ 51 | * 52 | * NOTE 2 53 | * ------ 54 | * 55 | * Some of the following compile time checks are based on the fact 56 | * that the dimension of a constant array can not be a negative one. 57 | * In this way if the compile time verification fails, the compilation 58 | * will fail issuing an error. The error description wording is compiler 59 | * dependent but it will be quite similar to one of the following: 60 | * 61 | * "negative subscript or subscript is too large" 62 | * "array must have at least one element" 63 | * "-1 is an illegal array size" 64 | * "size of array is negative" 65 | * 66 | * If you are building an application which tries to use an already 67 | * built libcurl library and you are getting this kind of errors on 68 | * this file, it is a clear indication that there is a mismatch between 69 | * how the library was built and how you are trying to use it for your 70 | * application. Your already compiled or binary library provider is the 71 | * only one who can give you the details you need to properly use it. 72 | */ 73 | 74 | /* 75 | * Verify that some macros are actually defined. 76 | */ 77 | 78 | #ifndef CURL_SIZEOF_LONG 79 | # error "CURL_SIZEOF_LONG definition is missing!" 80 | Error Compilation_aborted_CURL_SIZEOF_LONG_is_missing 81 | #endif 82 | 83 | #ifndef CURL_TYPEOF_CURL_SOCKLEN_T 84 | # error "CURL_TYPEOF_CURL_SOCKLEN_T definition is missing!" 85 | Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_is_missing 86 | #endif 87 | 88 | #ifndef CURL_SIZEOF_CURL_SOCKLEN_T 89 | # error "CURL_SIZEOF_CURL_SOCKLEN_T definition is missing!" 90 | Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_is_missing 91 | #endif 92 | 93 | #ifndef CURL_TYPEOF_CURL_OFF_T 94 | # error "CURL_TYPEOF_CURL_OFF_T definition is missing!" 95 | Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_is_missing 96 | #endif 97 | 98 | #ifndef CURL_FORMAT_CURL_OFF_T 99 | # error "CURL_FORMAT_CURL_OFF_T definition is missing!" 100 | Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_is_missing 101 | #endif 102 | 103 | #ifndef CURL_FORMAT_CURL_OFF_TU 104 | # error "CURL_FORMAT_CURL_OFF_TU definition is missing!" 105 | Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing 106 | #endif 107 | 108 | #ifndef CURL_FORMAT_OFF_T 109 | # error "CURL_FORMAT_OFF_T definition is missing!" 110 | Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing 111 | #endif 112 | 113 | #ifndef CURL_SIZEOF_CURL_OFF_T 114 | # error "CURL_SIZEOF_CURL_OFF_T definition is missing!" 115 | Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing 116 | #endif 117 | 118 | #ifndef CURL_SUFFIX_CURL_OFF_T 119 | # error "CURL_SUFFIX_CURL_OFF_T definition is missing!" 120 | Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_is_missing 121 | #endif 122 | 123 | #ifndef CURL_SUFFIX_CURL_OFF_TU 124 | # error "CURL_SUFFIX_CURL_OFF_TU definition is missing!" 125 | Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_is_missing 126 | #endif 127 | 128 | /* 129 | * Macros private to this header file. 130 | */ 131 | 132 | #define CurlchkszEQ(t, s) sizeof(t) == s ? 1 : -1 133 | 134 | #define CurlchkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1 135 | 136 | /* 137 | * Verify that the size previously defined and expected for long 138 | * is the same as the one reported by sizeof() at compile time. 139 | */ 140 | 141 | typedef char 142 | __curl_rule_01__ 143 | [CurlchkszEQ(long, CURL_SIZEOF_LONG)]; 144 | 145 | /* 146 | * Verify that the size previously defined and expected for 147 | * curl_off_t is actually the the same as the one reported 148 | * by sizeof() at compile time. 149 | */ 150 | 151 | typedef char 152 | __curl_rule_02__ 153 | [CurlchkszEQ(curl_off_t, CURL_SIZEOF_CURL_OFF_T)]; 154 | 155 | /* 156 | * Verify at compile time that the size of curl_off_t as reported 157 | * by sizeof() is greater or equal than the one reported for long 158 | * for the current compilation. 159 | */ 160 | 161 | typedef char 162 | __curl_rule_03__ 163 | [CurlchkszGE(curl_off_t, long)]; 164 | 165 | /* 166 | * Verify that the size previously defined and expected for 167 | * curl_socklen_t is actually the the same as the one reported 168 | * by sizeof() at compile time. 169 | */ 170 | 171 | typedef char 172 | __curl_rule_04__ 173 | [CurlchkszEQ(curl_socklen_t, CURL_SIZEOF_CURL_SOCKLEN_T)]; 174 | 175 | /* 176 | * Verify at compile time that the size of curl_socklen_t as reported 177 | * by sizeof() is greater or equal than the one reported for int for 178 | * the current compilation. 179 | */ 180 | 181 | typedef char 182 | __curl_rule_05__ 183 | [CurlchkszGE(curl_socklen_t, int)]; 184 | 185 | /* ================================================================ */ 186 | /* EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS */ 187 | /* ================================================================ */ 188 | 189 | /* 190 | * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow 191 | * these to be visible and exported by the external libcurl interface API, 192 | * while also making them visible to the library internals, simply including 193 | * curl_setup.h, without actually needing to include curl.h internally. 194 | * If some day this section would grow big enough, all this should be moved 195 | * to its own header file. 196 | */ 197 | 198 | /* 199 | * Figure out if we can use the ## preprocessor operator, which is supported 200 | * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__ 201 | * or __cplusplus so we need to carefully check for them too. 202 | */ 203 | 204 | #if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \ 205 | defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \ 206 | defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \ 207 | defined(__ILEC400__) 208 | /* This compiler is believed to have an ISO compatible preprocessor */ 209 | #define CURL_ISOCPP 210 | #else 211 | /* This compiler is believed NOT to have an ISO compatible preprocessor */ 212 | #undef CURL_ISOCPP 213 | #endif 214 | 215 | /* 216 | * Macros for minimum-width signed and unsigned curl_off_t integer constants. 217 | */ 218 | 219 | #if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551) 220 | # define __CURL_OFF_T_C_HLPR2(x) x 221 | # define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x) 222 | # define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ 223 | __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T) 224 | # define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ 225 | __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU) 226 | #else 227 | # ifdef CURL_ISOCPP 228 | # define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix 229 | # else 230 | # define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix 231 | # endif 232 | # define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix) 233 | # define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T) 234 | # define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU) 235 | #endif 236 | 237 | /* 238 | * Get rid of macros private to this header file. 239 | */ 240 | 241 | #undef CurlchkszEQ 242 | #undef CurlchkszGE 243 | 244 | /* 245 | * Get rid of macros not intended to exist beyond this point. 246 | */ 247 | 248 | #undef CURL_PULL_WS2TCPIP_H 249 | #undef CURL_PULL_SYS_TYPES_H 250 | #undef CURL_PULL_SYS_SOCKET_H 251 | #undef CURL_PULL_SYS_POLL_H 252 | #undef CURL_PULL_STDINT_H 253 | #undef CURL_PULL_INTTYPES_H 254 | 255 | #undef CURL_TYPEOF_CURL_SOCKLEN_T 256 | #undef CURL_TYPEOF_CURL_OFF_T 257 | 258 | #ifdef CURL_NO_OLDIES 259 | #undef CURL_FORMAT_OFF_T /* not required since 7.19.0 - obsoleted in 7.20.0 */ 260 | #endif 261 | 262 | #endif /* __CURL_CURLRULES_H */ 263 | -------------------------------------------------------------------------------- /External/libcurl.OSX/curlver.h: -------------------------------------------------------------------------------- 1 | #ifndef __CURL_CURLVER_H 2 | #define __CURL_CURLVER_H 3 | /*************************************************************************** 4 | * _ _ ____ _ 5 | * Project ___| | | | _ \| | 6 | * / __| | | | |_) | | 7 | * | (__| |_| | _ <| |___ 8 | * \___|\___/|_| \_\_____| 9 | * 10 | * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. 11 | * 12 | * This software is licensed as described in the file COPYING, which 13 | * you should have received as part of this distribution. The terms 14 | * are also available at http://curl.haxx.se/docs/copyright.html. 15 | * 16 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell 17 | * copies of the Software, and permit persons to whom the Software is 18 | * furnished to do so, under the terms of the COPYING file. 19 | * 20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21 | * KIND, either express or implied. 22 | * 23 | ***************************************************************************/ 24 | 25 | /* This header file contains nothing but libcurl version info, generated by 26 | a script at release-time. This was made its own header file in 7.11.2 */ 27 | 28 | /* This is the global package copyright */ 29 | #define LIBCURL_COPYRIGHT "1996 - 2013 Daniel Stenberg, ." 30 | 31 | /* This is the version number of the libcurl package from which this header 32 | file origins: */ 33 | #define LIBCURL_VERSION "7.32.0" 34 | 35 | /* The numeric version number is also available "in parts" by using these 36 | defines: */ 37 | #define LIBCURL_VERSION_MAJOR 7 38 | #define LIBCURL_VERSION_MINOR 32 39 | #define LIBCURL_VERSION_PATCH 0 40 | 41 | /* This is the numeric version of the libcurl version number, meant for easier 42 | parsing and comparions by programs. The LIBCURL_VERSION_NUM define will 43 | always follow this syntax: 44 | 45 | 0xXXYYZZ 46 | 47 | Where XX, YY and ZZ are the main version, release and patch numbers in 48 | hexadecimal (using 8 bits each). All three numbers are always represented 49 | using two digits. 1.2 would appear as "0x010200" while version 9.11.7 50 | appears as "0x090b07". 51 | 52 | This 6-digit (24 bits) hexadecimal number does not show pre-release number, 53 | and it is always a greater number in a more recent release. It makes 54 | comparisons with greater than and less than work. 55 | */ 56 | #define LIBCURL_VERSION_NUM 0x072000 57 | 58 | /* 59 | * This is the date and time when the full source package was created. The 60 | * timestamp is not stored in git, as the timestamp is properly set in the 61 | * tarballs by the maketgz script. 62 | * 63 | * The format of the date should follow this template: 64 | * 65 | * "Mon Feb 12 11:35:33 UTC 2007" 66 | */ 67 | #define LIBCURL_TIMESTAMP "Sun Aug 11 22:15:54 UTC 2013" 68 | 69 | #endif /* __CURL_CURLVER_H */ 70 | -------------------------------------------------------------------------------- /External/libcurl.OSX/easy.h: -------------------------------------------------------------------------------- 1 | #ifndef __CURL_EASY_H 2 | #define __CURL_EASY_H 3 | /*************************************************************************** 4 | * _ _ ____ _ 5 | * Project ___| | | | _ \| | 6 | * / __| | | | |_) | | 7 | * | (__| |_| | _ <| |___ 8 | * \___|\___/|_| \_\_____| 9 | * 10 | * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. 11 | * 12 | * This software is licensed as described in the file COPYING, which 13 | * you should have received as part of this distribution. The terms 14 | * are also available at http://curl.haxx.se/docs/copyright.html. 15 | * 16 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell 17 | * copies of the Software, and permit persons to whom the Software is 18 | * furnished to do so, under the terms of the COPYING file. 19 | * 20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21 | * KIND, either express or implied. 22 | * 23 | ***************************************************************************/ 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | CURL_EXTERN CURL *curl_easy_init(void); 29 | CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); 30 | CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); 31 | CURL_EXTERN void curl_easy_cleanup(CURL *curl); 32 | 33 | /* 34 | * NAME curl_easy_getinfo() 35 | * 36 | * DESCRIPTION 37 | * 38 | * Request internal information from the curl session with this function. The 39 | * third argument MUST be a pointer to a long, a pointer to a char * or a 40 | * pointer to a double (as the documentation describes elsewhere). The data 41 | * pointed to will be filled in accordingly and can be relied upon only if the 42 | * function returns CURLE_OK. This function is intended to get used *AFTER* a 43 | * performed transfer, all results from this function are undefined until the 44 | * transfer is completed. 45 | */ 46 | CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); 47 | 48 | 49 | /* 50 | * NAME curl_easy_duphandle() 51 | * 52 | * DESCRIPTION 53 | * 54 | * Creates a new curl session handle with the same options set for the handle 55 | * passed in. Duplicating a handle could only be a matter of cloning data and 56 | * options, internal state info and things like persistent connections cannot 57 | * be transferred. It is useful in multithreaded applications when you can run 58 | * curl_easy_duphandle() for each new thread to avoid a series of identical 59 | * curl_easy_setopt() invokes in every thread. 60 | */ 61 | CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl); 62 | 63 | /* 64 | * NAME curl_easy_reset() 65 | * 66 | * DESCRIPTION 67 | * 68 | * Re-initializes a CURL handle to the default values. This puts back the 69 | * handle to the same state as it was in when it was just created. 70 | * 71 | * It does keep: live connections, the Session ID cache, the DNS cache and the 72 | * cookies. 73 | */ 74 | CURL_EXTERN void curl_easy_reset(CURL *curl); 75 | 76 | /* 77 | * NAME curl_easy_recv() 78 | * 79 | * DESCRIPTION 80 | * 81 | * Receives data from the connected socket. Use after successful 82 | * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. 83 | */ 84 | CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, 85 | size_t *n); 86 | 87 | /* 88 | * NAME curl_easy_send() 89 | * 90 | * DESCRIPTION 91 | * 92 | * Sends data over the connected socket. Use after successful 93 | * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. 94 | */ 95 | CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, 96 | size_t buflen, size_t *n); 97 | 98 | #ifdef __cplusplus 99 | } 100 | #endif 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /External/libcurl.OSX/libcurl.OSX.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/biasedbit/BBHTTP/c5cfe0f5d5d5ac75a873ca9fba77aaa2756ac463/External/libcurl.OSX/libcurl.OSX.a -------------------------------------------------------------------------------- /External/libcurl.OSX/mprintf.h: -------------------------------------------------------------------------------- 1 | #ifndef __CURL_MPRINTF_H 2 | #define __CURL_MPRINTF_H 3 | /*************************************************************************** 4 | * _ _ ____ _ 5 | * Project ___| | | | _ \| | 6 | * / __| | | | |_) | | 7 | * | (__| |_| | _ <| |___ 8 | * \___|\___/|_| \_\_____| 9 | * 10 | * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. 11 | * 12 | * This software is licensed as described in the file COPYING, which 13 | * you should have received as part of this distribution. The terms 14 | * are also available at http://curl.haxx.se/docs/copyright.html. 15 | * 16 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell 17 | * copies of the Software, and permit persons to whom the Software is 18 | * furnished to do so, under the terms of the COPYING file. 19 | * 20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21 | * KIND, either express or implied. 22 | * 23 | ***************************************************************************/ 24 | 25 | #include 26 | #include /* needed for FILE */ 27 | 28 | #include "curl.h" 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | CURL_EXTERN int curl_mprintf(const char *format, ...); 35 | CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...); 36 | CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...); 37 | CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, 38 | const char *format, ...); 39 | CURL_EXTERN int curl_mvprintf(const char *format, va_list args); 40 | CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args); 41 | CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args); 42 | CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, 43 | const char *format, va_list args); 44 | CURL_EXTERN char *curl_maprintf(const char *format, ...); 45 | CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args); 46 | 47 | #ifdef _MPRINTF_REPLACE 48 | # undef printf 49 | # undef fprintf 50 | # undef sprintf 51 | # undef vsprintf 52 | # undef snprintf 53 | # undef vprintf 54 | # undef vfprintf 55 | # undef vsnprintf 56 | # undef aprintf 57 | # undef vaprintf 58 | # define printf curl_mprintf 59 | # define fprintf curl_mfprintf 60 | #ifdef CURLDEBUG 61 | /* When built with CURLDEBUG we define away the sprintf functions since we 62 | don't want internal code to be using them */ 63 | # define sprintf sprintf_was_used 64 | # define vsprintf vsprintf_was_used 65 | #else 66 | # define sprintf curl_msprintf 67 | # define vsprintf curl_mvsprintf 68 | #endif 69 | # define snprintf curl_msnprintf 70 | # define vprintf curl_mvprintf 71 | # define vfprintf curl_mvfprintf 72 | # define vsnprintf curl_mvsnprintf 73 | # define aprintf curl_maprintf 74 | # define vaprintf curl_mvaprintf 75 | #endif 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | 81 | #endif /* __CURL_MPRINTF_H */ 82 | -------------------------------------------------------------------------------- /External/libcurl.OSX/stdcheaders.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDC_HEADERS_H 2 | #define __STDC_HEADERS_H 3 | /*************************************************************************** 4 | * _ _ ____ _ 5 | * Project ___| | | | _ \| | 6 | * / __| | | | |_) | | 7 | * | (__| |_| | _ <| |___ 8 | * \___|\___/|_| \_\_____| 9 | * 10 | * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. 11 | * 12 | * This software is licensed as described in the file COPYING, which 13 | * you should have received as part of this distribution. The terms 14 | * are also available at http://curl.haxx.se/docs/copyright.html. 15 | * 16 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell 17 | * copies of the Software, and permit persons to whom the Software is 18 | * furnished to do so, under the terms of the COPYING file. 19 | * 20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21 | * KIND, either express or implied. 22 | * 23 | ***************************************************************************/ 24 | 25 | #include 26 | 27 | size_t fread (void *, size_t, size_t, FILE *); 28 | size_t fwrite (const void *, size_t, size_t, FILE *); 29 | 30 | int strcasecmp(const char *, const char *); 31 | int strncasecmp(const char *, const char *, size_t); 32 | 33 | #endif /* __STDC_HEADERS_H */ 34 | -------------------------------------------------------------------------------- /External/libcurl.iOS/curlbuild.h: -------------------------------------------------------------------------------- 1 | /* include/curl/curlbuild.h. Generated from curlbuild.h.in by configure. */ 2 | #ifndef __CURL_CURLBUILD_H 3 | #define __CURL_CURLBUILD_H 4 | /*************************************************************************** 5 | * _ _ ____ _ 6 | * Project ___| | | | _ \| | 7 | * / __| | | | |_) | | 8 | * | (__| |_| | _ <| |___ 9 | * \___|\___/|_| \_\_____| 10 | * 11 | * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. 12 | * 13 | * This software is licensed as described in the file COPYING, which 14 | * you should have received as part of this distribution. The terms 15 | * are also available at http://curl.haxx.se/docs/copyright.html. 16 | * 17 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell 18 | * copies of the Software, and permit persons to whom the Software is 19 | * furnished to do so, under the terms of the COPYING file. 20 | * 21 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 22 | * KIND, either express or implied. 23 | * 24 | ***************************************************************************/ 25 | 26 | /* ================================================================ */ 27 | /* NOTES FOR CONFIGURE CAPABLE SYSTEMS */ 28 | /* ================================================================ */ 29 | 30 | /* 31 | * NOTE 1: 32 | * ------- 33 | * 34 | * Nothing in this file is intended to be modified or adjusted by the 35 | * curl library user nor by the curl library builder. 36 | * 37 | * If you think that something actually needs to be changed, adjusted 38 | * or fixed in this file, then, report it on the libcurl development 39 | * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/ 40 | * 41 | * This header file shall only export symbols which are 'curl' or 'CURL' 42 | * prefixed, otherwise public name space would be polluted. 43 | * 44 | * NOTE 2: 45 | * ------- 46 | * 47 | * Right now you might be staring at file include/curl/curlbuild.h.in or 48 | * at file include/curl/curlbuild.h, this is due to the following reason: 49 | * 50 | * On systems capable of running the configure script, the configure process 51 | * will overwrite the distributed include/curl/curlbuild.h file with one that 52 | * is suitable and specific to the library being configured and built, which 53 | * is generated from the include/curl/curlbuild.h.in template file. 54 | * 55 | */ 56 | 57 | /* ================================================================ */ 58 | /* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */ 59 | /* ================================================================ */ 60 | 61 | #ifdef CURL_SIZEOF_LONG 62 | #error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" 63 | Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined 64 | #endif 65 | 66 | #ifdef CURL_TYPEOF_CURL_SOCKLEN_T 67 | #error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" 68 | Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined 69 | #endif 70 | 71 | #ifdef CURL_SIZEOF_CURL_SOCKLEN_T 72 | #error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" 73 | Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined 74 | #endif 75 | 76 | #ifdef CURL_TYPEOF_CURL_OFF_T 77 | #error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" 78 | Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined 79 | #endif 80 | 81 | #ifdef CURL_FORMAT_CURL_OFF_T 82 | #error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" 83 | Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined 84 | #endif 85 | 86 | #ifdef CURL_FORMAT_CURL_OFF_TU 87 | #error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" 88 | Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined 89 | #endif 90 | 91 | #ifdef CURL_FORMAT_OFF_T 92 | #error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" 93 | Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined 94 | #endif 95 | 96 | #ifdef CURL_SIZEOF_CURL_OFF_T 97 | #error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" 98 | Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined 99 | #endif 100 | 101 | #ifdef CURL_SUFFIX_CURL_OFF_T 102 | #error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" 103 | Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined 104 | #endif 105 | 106 | #ifdef CURL_SUFFIX_CURL_OFF_TU 107 | #error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" 108 | Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined 109 | #endif 110 | 111 | /* ================================================================ */ 112 | /* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */ 113 | /* ================================================================ */ 114 | 115 | /* Configure process defines this to 1 when it finds out that system */ 116 | /* header file ws2tcpip.h must be included by the external interface. */ 117 | /* #undef CURL_PULL_WS2TCPIP_H */ 118 | #ifdef CURL_PULL_WS2TCPIP_H 119 | # ifndef WIN32_LEAN_AND_MEAN 120 | # define WIN32_LEAN_AND_MEAN 121 | # endif 122 | # include 123 | # include 124 | # include 125 | #endif 126 | 127 | /* Configure process defines this to 1 when it finds out that system */ 128 | /* header file sys/types.h must be included by the external interface. */ 129 | #define CURL_PULL_SYS_TYPES_H 1 130 | #ifdef CURL_PULL_SYS_TYPES_H 131 | # include 132 | #endif 133 | 134 | /* Configure process defines this to 1 when it finds out that system */ 135 | /* header file stdint.h must be included by the external interface. */ 136 | #define CURL_PULL_STDINT_H 1 137 | #ifdef CURL_PULL_STDINT_H 138 | # include 139 | #endif 140 | 141 | /* Configure process defines this to 1 when it finds out that system */ 142 | /* header file inttypes.h must be included by the external interface. */ 143 | #define CURL_PULL_INTTYPES_H 1 144 | #ifdef CURL_PULL_INTTYPES_H 145 | # include 146 | #endif 147 | 148 | /* Configure process defines this to 1 when it finds out that system */ 149 | /* header file sys/socket.h must be included by the external interface. */ 150 | #define CURL_PULL_SYS_SOCKET_H 1 151 | #ifdef CURL_PULL_SYS_SOCKET_H 152 | # include 153 | #endif 154 | 155 | /* Configure process defines this to 1 when it finds out that system */ 156 | /* header file sys/poll.h must be included by the external interface. */ 157 | /* #undef CURL_PULL_SYS_POLL_H */ 158 | #ifdef CURL_PULL_SYS_POLL_H 159 | # include 160 | #endif 161 | 162 | /* The size of `long', as computed by sizeof. */ 163 | #define CURL_SIZEOF_LONG 4 164 | 165 | /* Integral data type used for curl_socklen_t. */ 166 | #define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t 167 | 168 | /* The size of `curl_socklen_t', as computed by sizeof. */ 169 | #define CURL_SIZEOF_CURL_SOCKLEN_T 4 170 | 171 | /* Data type definition of curl_socklen_t. */ 172 | typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; 173 | 174 | /* Signed integral data type used for curl_off_t. */ 175 | #define CURL_TYPEOF_CURL_OFF_T int64_t 176 | 177 | /* Data type definition of curl_off_t. */ 178 | typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; 179 | 180 | /* curl_off_t formatting string directive without "%" conversion specifier. */ 181 | #define CURL_FORMAT_CURL_OFF_T "lld" 182 | 183 | /* unsigned curl_off_t formatting string without "%" conversion specifier. */ 184 | #define CURL_FORMAT_CURL_OFF_TU "llu" 185 | 186 | /* curl_off_t formatting string directive with "%" conversion specifier. */ 187 | #define CURL_FORMAT_OFF_T "%lld" 188 | 189 | /* The size of `curl_off_t', as computed by sizeof. */ 190 | #define CURL_SIZEOF_CURL_OFF_T 8 191 | 192 | /* curl_off_t constant suffix. */ 193 | #define CURL_SUFFIX_CURL_OFF_T LL 194 | 195 | /* unsigned curl_off_t constant suffix. */ 196 | #define CURL_SUFFIX_CURL_OFF_TU ULL 197 | 198 | #endif /* __CURL_CURLBUILD_H */ 199 | -------------------------------------------------------------------------------- /External/libcurl.iOS/curlrules.h: -------------------------------------------------------------------------------- 1 | #ifndef __CURL_CURLRULES_H 2 | #define __CURL_CURLRULES_H 3 | /*************************************************************************** 4 | * _ _ ____ _ 5 | * Project ___| | | | _ \| | 6 | * / __| | | | |_) | | 7 | * | (__| |_| | _ <| |___ 8 | * \___|\___/|_| \_\_____| 9 | * 10 | * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. 11 | * 12 | * This software is licensed as described in the file COPYING, which 13 | * you should have received as part of this distribution. The terms 14 | * are also available at http://curl.haxx.se/docs/copyright.html. 15 | * 16 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell 17 | * copies of the Software, and permit persons to whom the Software is 18 | * furnished to do so, under the terms of the COPYING file. 19 | * 20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21 | * KIND, either express or implied. 22 | * 23 | ***************************************************************************/ 24 | 25 | /* ================================================================ */ 26 | /* COMPILE TIME SANITY CHECKS */ 27 | /* ================================================================ */ 28 | 29 | /* 30 | * NOTE 1: 31 | * ------- 32 | * 33 | * All checks done in this file are intentionally placed in a public 34 | * header file which is pulled by curl/curl.h when an application is 35 | * being built using an already built libcurl library. Additionally 36 | * this file is also included and used when building the library. 37 | * 38 | * If compilation fails on this file it is certainly sure that the 39 | * problem is elsewhere. It could be a problem in the curlbuild.h 40 | * header file, or simply that you are using different compilation 41 | * settings than those used to build the library. 42 | * 43 | * Nothing in this file is intended to be modified or adjusted by the 44 | * curl library user nor by the curl library builder. 45 | * 46 | * Do not deactivate any check, these are done to make sure that the 47 | * library is properly built and used. 48 | * 49 | * You can find further help on the libcurl development mailing list: 50 | * http://cool.haxx.se/mailman/listinfo/curl-library/ 51 | * 52 | * NOTE 2 53 | * ------ 54 | * 55 | * Some of the following compile time checks are based on the fact 56 | * that the dimension of a constant array can not be a negative one. 57 | * In this way if the compile time verification fails, the compilation 58 | * will fail issuing an error. The error description wording is compiler 59 | * dependent but it will be quite similar to one of the following: 60 | * 61 | * "negative subscript or subscript is too large" 62 | * "array must have at least one element" 63 | * "-1 is an illegal array size" 64 | * "size of array is negative" 65 | * 66 | * If you are building an application which tries to use an already 67 | * built libcurl library and you are getting this kind of errors on 68 | * this file, it is a clear indication that there is a mismatch between 69 | * how the library was built and how you are trying to use it for your 70 | * application. Your already compiled or binary library provider is the 71 | * only one who can give you the details you need to properly use it. 72 | */ 73 | 74 | /* 75 | * Verify that some macros are actually defined. 76 | */ 77 | 78 | #ifndef CURL_SIZEOF_LONG 79 | # error "CURL_SIZEOF_LONG definition is missing!" 80 | Error Compilation_aborted_CURL_SIZEOF_LONG_is_missing 81 | #endif 82 | 83 | #ifndef CURL_TYPEOF_CURL_SOCKLEN_T 84 | # error "CURL_TYPEOF_CURL_SOCKLEN_T definition is missing!" 85 | Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_is_missing 86 | #endif 87 | 88 | #ifndef CURL_SIZEOF_CURL_SOCKLEN_T 89 | # error "CURL_SIZEOF_CURL_SOCKLEN_T definition is missing!" 90 | Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_is_missing 91 | #endif 92 | 93 | #ifndef CURL_TYPEOF_CURL_OFF_T 94 | # error "CURL_TYPEOF_CURL_OFF_T definition is missing!" 95 | Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_is_missing 96 | #endif 97 | 98 | #ifndef CURL_FORMAT_CURL_OFF_T 99 | # error "CURL_FORMAT_CURL_OFF_T definition is missing!" 100 | Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_is_missing 101 | #endif 102 | 103 | #ifndef CURL_FORMAT_CURL_OFF_TU 104 | # error "CURL_FORMAT_CURL_OFF_TU definition is missing!" 105 | Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing 106 | #endif 107 | 108 | #ifndef CURL_FORMAT_OFF_T 109 | # error "CURL_FORMAT_OFF_T definition is missing!" 110 | Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing 111 | #endif 112 | 113 | #ifndef CURL_SIZEOF_CURL_OFF_T 114 | # error "CURL_SIZEOF_CURL_OFF_T definition is missing!" 115 | Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing 116 | #endif 117 | 118 | #ifndef CURL_SUFFIX_CURL_OFF_T 119 | # error "CURL_SUFFIX_CURL_OFF_T definition is missing!" 120 | Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_is_missing 121 | #endif 122 | 123 | #ifndef CURL_SUFFIX_CURL_OFF_TU 124 | # error "CURL_SUFFIX_CURL_OFF_TU definition is missing!" 125 | Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_is_missing 126 | #endif 127 | 128 | /* 129 | * Macros private to this header file. 130 | */ 131 | 132 | #define CurlchkszEQ(t, s) sizeof(t) == s ? 1 : -1 133 | 134 | #define CurlchkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1 135 | 136 | /* 137 | * Verify that the size previously defined and expected for long 138 | * is the same as the one reported by sizeof() at compile time. 139 | */ 140 | 141 | typedef char 142 | __curl_rule_01__ 143 | [CurlchkszEQ(long, CURL_SIZEOF_LONG)]; 144 | 145 | /* 146 | * Verify that the size previously defined and expected for 147 | * curl_off_t is actually the the same as the one reported 148 | * by sizeof() at compile time. 149 | */ 150 | 151 | typedef char 152 | __curl_rule_02__ 153 | [CurlchkszEQ(curl_off_t, CURL_SIZEOF_CURL_OFF_T)]; 154 | 155 | /* 156 | * Verify at compile time that the size of curl_off_t as reported 157 | * by sizeof() is greater or equal than the one reported for long 158 | * for the current compilation. 159 | */ 160 | 161 | typedef char 162 | __curl_rule_03__ 163 | [CurlchkszGE(curl_off_t, long)]; 164 | 165 | /* 166 | * Verify that the size previously defined and expected for 167 | * curl_socklen_t is actually the the same as the one reported 168 | * by sizeof() at compile time. 169 | */ 170 | 171 | typedef char 172 | __curl_rule_04__ 173 | [CurlchkszEQ(curl_socklen_t, CURL_SIZEOF_CURL_SOCKLEN_T)]; 174 | 175 | /* 176 | * Verify at compile time that the size of curl_socklen_t as reported 177 | * by sizeof() is greater or equal than the one reported for int for 178 | * the current compilation. 179 | */ 180 | 181 | typedef char 182 | __curl_rule_05__ 183 | [CurlchkszGE(curl_socklen_t, int)]; 184 | 185 | /* ================================================================ */ 186 | /* EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS */ 187 | /* ================================================================ */ 188 | 189 | /* 190 | * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow 191 | * these to be visible and exported by the external libcurl interface API, 192 | * while also making them visible to the library internals, simply including 193 | * curl_setup.h, without actually needing to include curl.h internally. 194 | * If some day this section would grow big enough, all this should be moved 195 | * to its own header file. 196 | */ 197 | 198 | /* 199 | * Figure out if we can use the ## preprocessor operator, which is supported 200 | * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__ 201 | * or __cplusplus so we need to carefully check for them too. 202 | */ 203 | 204 | #if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \ 205 | defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \ 206 | defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \ 207 | defined(__ILEC400__) 208 | /* This compiler is believed to have an ISO compatible preprocessor */ 209 | #define CURL_ISOCPP 210 | #else 211 | /* This compiler is believed NOT to have an ISO compatible preprocessor */ 212 | #undef CURL_ISOCPP 213 | #endif 214 | 215 | /* 216 | * Macros for minimum-width signed and unsigned curl_off_t integer constants. 217 | */ 218 | 219 | #if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551) 220 | # define __CURL_OFF_T_C_HLPR2(x) x 221 | # define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x) 222 | # define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ 223 | __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T) 224 | # define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ 225 | __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU) 226 | #else 227 | # ifdef CURL_ISOCPP 228 | # define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix 229 | # else 230 | # define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix 231 | # endif 232 | # define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix) 233 | # define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T) 234 | # define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU) 235 | #endif 236 | 237 | /* 238 | * Get rid of macros private to this header file. 239 | */ 240 | 241 | #undef CurlchkszEQ 242 | #undef CurlchkszGE 243 | 244 | /* 245 | * Get rid of macros not intended to exist beyond this point. 246 | */ 247 | 248 | #undef CURL_PULL_WS2TCPIP_H 249 | #undef CURL_PULL_SYS_TYPES_H 250 | #undef CURL_PULL_SYS_SOCKET_H 251 | #undef CURL_PULL_SYS_POLL_H 252 | #undef CURL_PULL_STDINT_H 253 | #undef CURL_PULL_INTTYPES_H 254 | 255 | #undef CURL_TYPEOF_CURL_SOCKLEN_T 256 | #undef CURL_TYPEOF_CURL_OFF_T 257 | 258 | #ifdef CURL_NO_OLDIES 259 | #undef CURL_FORMAT_OFF_T /* not required since 7.19.0 - obsoleted in 7.20.0 */ 260 | #endif 261 | 262 | #endif /* __CURL_CURLRULES_H */ 263 | -------------------------------------------------------------------------------- /External/libcurl.iOS/curlver.h: -------------------------------------------------------------------------------- 1 | #ifndef __CURL_CURLVER_H 2 | #define __CURL_CURLVER_H 3 | /*************************************************************************** 4 | * _ _ ____ _ 5 | * Project ___| | | | _ \| | 6 | * / __| | | | |_) | | 7 | * | (__| |_| | _ <| |___ 8 | * \___|\___/|_| \_\_____| 9 | * 10 | * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. 11 | * 12 | * This software is licensed as described in the file COPYING, which 13 | * you should have received as part of this distribution. The terms 14 | * are also available at http://curl.haxx.se/docs/copyright.html. 15 | * 16 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell 17 | * copies of the Software, and permit persons to whom the Software is 18 | * furnished to do so, under the terms of the COPYING file. 19 | * 20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21 | * KIND, either express or implied. 22 | * 23 | ***************************************************************************/ 24 | 25 | /* This header file contains nothing but libcurl version info, generated by 26 | a script at release-time. This was made its own header file in 7.11.2 */ 27 | 28 | /* This is the global package copyright */ 29 | #define LIBCURL_COPYRIGHT "1996 - 2013 Daniel Stenberg, ." 30 | 31 | /* This is the version number of the libcurl package from which this header 32 | file origins: */ 33 | #define LIBCURL_VERSION "7.32.0" 34 | 35 | /* The numeric version number is also available "in parts" by using these 36 | defines: */ 37 | #define LIBCURL_VERSION_MAJOR 7 38 | #define LIBCURL_VERSION_MINOR 32 39 | #define LIBCURL_VERSION_PATCH 0 40 | 41 | /* This is the numeric version of the libcurl version number, meant for easier 42 | parsing and comparions by programs. The LIBCURL_VERSION_NUM define will 43 | always follow this syntax: 44 | 45 | 0xXXYYZZ 46 | 47 | Where XX, YY and ZZ are the main version, release and patch numbers in 48 | hexadecimal (using 8 bits each). All three numbers are always represented 49 | using two digits. 1.2 would appear as "0x010200" while version 9.11.7 50 | appears as "0x090b07". 51 | 52 | This 6-digit (24 bits) hexadecimal number does not show pre-release number, 53 | and it is always a greater number in a more recent release. It makes 54 | comparisons with greater than and less than work. 55 | */ 56 | #define LIBCURL_VERSION_NUM 0x072000 57 | 58 | /* 59 | * This is the date and time when the full source package was created. The 60 | * timestamp is not stored in git, as the timestamp is properly set in the 61 | * tarballs by the maketgz script. 62 | * 63 | * The format of the date should follow this template: 64 | * 65 | * "Mon Feb 12 11:35:33 UTC 2007" 66 | */ 67 | #define LIBCURL_TIMESTAMP "Sun Aug 11 22:15:54 UTC 2013" 68 | 69 | #endif /* __CURL_CURLVER_H */ 70 | -------------------------------------------------------------------------------- /External/libcurl.iOS/easy.h: -------------------------------------------------------------------------------- 1 | #ifndef __CURL_EASY_H 2 | #define __CURL_EASY_H 3 | /*************************************************************************** 4 | * _ _ ____ _ 5 | * Project ___| | | | _ \| | 6 | * / __| | | | |_) | | 7 | * | (__| |_| | _ <| |___ 8 | * \___|\___/|_| \_\_____| 9 | * 10 | * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. 11 | * 12 | * This software is licensed as described in the file COPYING, which 13 | * you should have received as part of this distribution. The terms 14 | * are also available at http://curl.haxx.se/docs/copyright.html. 15 | * 16 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell 17 | * copies of the Software, and permit persons to whom the Software is 18 | * furnished to do so, under the terms of the COPYING file. 19 | * 20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21 | * KIND, either express or implied. 22 | * 23 | ***************************************************************************/ 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | CURL_EXTERN CURL *curl_easy_init(void); 29 | CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); 30 | CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); 31 | CURL_EXTERN void curl_easy_cleanup(CURL *curl); 32 | 33 | /* 34 | * NAME curl_easy_getinfo() 35 | * 36 | * DESCRIPTION 37 | * 38 | * Request internal information from the curl session with this function. The 39 | * third argument MUST be a pointer to a long, a pointer to a char * or a 40 | * pointer to a double (as the documentation describes elsewhere). The data 41 | * pointed to will be filled in accordingly and can be relied upon only if the 42 | * function returns CURLE_OK. This function is intended to get used *AFTER* a 43 | * performed transfer, all results from this function are undefined until the 44 | * transfer is completed. 45 | */ 46 | CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); 47 | 48 | 49 | /* 50 | * NAME curl_easy_duphandle() 51 | * 52 | * DESCRIPTION 53 | * 54 | * Creates a new curl session handle with the same options set for the handle 55 | * passed in. Duplicating a handle could only be a matter of cloning data and 56 | * options, internal state info and things like persistent connections cannot 57 | * be transferred. It is useful in multithreaded applications when you can run 58 | * curl_easy_duphandle() for each new thread to avoid a series of identical 59 | * curl_easy_setopt() invokes in every thread. 60 | */ 61 | CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl); 62 | 63 | /* 64 | * NAME curl_easy_reset() 65 | * 66 | * DESCRIPTION 67 | * 68 | * Re-initializes a CURL handle to the default values. This puts back the 69 | * handle to the same state as it was in when it was just created. 70 | * 71 | * It does keep: live connections, the Session ID cache, the DNS cache and the 72 | * cookies. 73 | */ 74 | CURL_EXTERN void curl_easy_reset(CURL *curl); 75 | 76 | /* 77 | * NAME curl_easy_recv() 78 | * 79 | * DESCRIPTION 80 | * 81 | * Receives data from the connected socket. Use after successful 82 | * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. 83 | */ 84 | CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, 85 | size_t *n); 86 | 87 | /* 88 | * NAME curl_easy_send() 89 | * 90 | * DESCRIPTION 91 | * 92 | * Sends data over the connected socket. Use after successful 93 | * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. 94 | */ 95 | CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, 96 | size_t buflen, size_t *n); 97 | 98 | #ifdef __cplusplus 99 | } 100 | #endif 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /External/libcurl.iOS/libcurl.iOS.appstore.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/biasedbit/BBHTTP/c5cfe0f5d5d5ac75a873ca9fba77aaa2756ac463/External/libcurl.iOS/libcurl.iOS.appstore.a -------------------------------------------------------------------------------- /External/libcurl.iOS/libcurl.iOS.dev.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/biasedbit/BBHTTP/c5cfe0f5d5d5ac75a873ca9fba77aaa2756ac463/External/libcurl.iOS/libcurl.iOS.dev.a -------------------------------------------------------------------------------- /External/libcurl.iOS/mprintf.h: -------------------------------------------------------------------------------- 1 | #ifndef __CURL_MPRINTF_H 2 | #define __CURL_MPRINTF_H 3 | /*************************************************************************** 4 | * _ _ ____ _ 5 | * Project ___| | | | _ \| | 6 | * / __| | | | |_) | | 7 | * | (__| |_| | _ <| |___ 8 | * \___|\___/|_| \_\_____| 9 | * 10 | * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. 11 | * 12 | * This software is licensed as described in the file COPYING, which 13 | * you should have received as part of this distribution. The terms 14 | * are also available at http://curl.haxx.se/docs/copyright.html. 15 | * 16 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell 17 | * copies of the Software, and permit persons to whom the Software is 18 | * furnished to do so, under the terms of the COPYING file. 19 | * 20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21 | * KIND, either express or implied. 22 | * 23 | ***************************************************************************/ 24 | 25 | #include 26 | #include /* needed for FILE */ 27 | 28 | #include "curl.h" 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | CURL_EXTERN int curl_mprintf(const char *format, ...); 35 | CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...); 36 | CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...); 37 | CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, 38 | const char *format, ...); 39 | CURL_EXTERN int curl_mvprintf(const char *format, va_list args); 40 | CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args); 41 | CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args); 42 | CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, 43 | const char *format, va_list args); 44 | CURL_EXTERN char *curl_maprintf(const char *format, ...); 45 | CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args); 46 | 47 | #ifdef _MPRINTF_REPLACE 48 | # undef printf 49 | # undef fprintf 50 | # undef sprintf 51 | # undef vsprintf 52 | # undef snprintf 53 | # undef vprintf 54 | # undef vfprintf 55 | # undef vsnprintf 56 | # undef aprintf 57 | # undef vaprintf 58 | # define printf curl_mprintf 59 | # define fprintf curl_mfprintf 60 | #ifdef CURLDEBUG 61 | /* When built with CURLDEBUG we define away the sprintf functions since we 62 | don't want internal code to be using them */ 63 | # define sprintf sprintf_was_used 64 | # define vsprintf vsprintf_was_used 65 | #else 66 | # define sprintf curl_msprintf 67 | # define vsprintf curl_mvsprintf 68 | #endif 69 | # define snprintf curl_msnprintf 70 | # define vprintf curl_mvprintf 71 | # define vfprintf curl_mvfprintf 72 | # define vsnprintf curl_mvsnprintf 73 | # define aprintf curl_maprintf 74 | # define vaprintf curl_mvaprintf 75 | #endif 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | 81 | #endif /* __CURL_MPRINTF_H */ 82 | -------------------------------------------------------------------------------- /External/libcurl.iOS/stdcheaders.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDC_HEADERS_H 2 | #define __STDC_HEADERS_H 3 | /*************************************************************************** 4 | * _ _ ____ _ 5 | * Project ___| | | | _ \| | 6 | * / __| | | | |_) | | 7 | * | (__| |_| | _ <| |___ 8 | * \___|\___/|_| \_\_____| 9 | * 10 | * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. 11 | * 12 | * This software is licensed as described in the file COPYING, which 13 | * you should have received as part of this distribution. The terms 14 | * are also available at http://curl.haxx.se/docs/copyright.html. 15 | * 16 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell 17 | * copies of the Software, and permit persons to whom the Software is 18 | * furnished to do so, under the terms of the COPYING file. 19 | * 20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21 | * KIND, either express or implied. 22 | * 23 | ***************************************************************************/ 24 | 25 | #include 26 | 27 | size_t fread (void *, size_t, size_t, FILE *); 28 | size_t fwrite (const void *, size_t, size_t, FILE *); 29 | 30 | int strcasecmp(const char *, const char *); 31 | int strncasecmp(const char *, const char *, size_t); 32 | 33 | #endif /* __STDC_HEADERS_H */ 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013 BiasedBit 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /Project/BBHTTP.OSX-Prefix.pch: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import -------------------------------------------------------------------------------- /Project/BBHTTP.iOS-Prefix.pch: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | -------------------------------------------------------------------------------- /Project/build-configuration.properties: -------------------------------------------------------------------------------- 1 | #----------------------------------------------- Release Configuration ------------------------------------------------# 2 | module.name=BBHTTP 3 | module.company=BBHTTP 4 | module.sdk.version=6.1 5 | 6 | #-------------------------------------------------- Base Directories --------------------------------------------------# 7 | target.dir=${basedir}/build 8 | temp.dir=${target.dir}/temp 9 | reports.dir=${target.dir}/reports 10 | scripts.dir=${basedir}/Scripts 11 | 12 | #------------------------------------------------- Source Directories -------------------------------------------------# 13 | source.main.dir=${basedir}/BBHTTP 14 | 15 | #------------------------------------------------ iOS Device Simulator ------------------------------------------------# 16 | simulator.version=6.1 17 | simulator.path=Platforms/iPhoneSimulator.platform/Developer/Applications/iPhone Simulator.app 18 | 19 | #--------------------------------------------------- Test Execution ---------------------------------------------------# 20 | tests.target.name=Tests 21 | 22 | #----------------------------------------------------- API Report -----------------------------------------------------# 23 | appledoc.bin=/usr/local/bin/appledoc 24 | xcodebuild=/usr/bin/xcodebuild 25 | 26 | #----------------------------------------------------- Publishing -----------------------------------------------------# 27 | github.repo=git@github.com:jasperblues/BBHotpotato.git -------------------------------------------------------------------------------- /Project/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | Xcode path is not set. Please use run xcode-select from the cmd-line, to specify location of Xcode tools. 37 | ${line.separator}Example: sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer 38 | 39 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | tell application "${xcode.path}/${simulator.path}" to quit 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 | 98 | 99 | 100 | 101 | 102 | #!/bin/sh 103 | cd ${basedir} 104 | git remote add origin ${github.repo} 105 | git remote set-url origin ${github.repo} 106 | git fetch origin gh-pages:gh-pages 107 | git fetch origin gh-pages 108 | git checkout gh-pages 109 | git pull 110 | 111 | rm -fr ./api 112 | cp -fr ${reports.dir}/api ./api 113 | git add api 114 | 115 | git commit -a -m "publish reports to gh-pages" 116 | git push -u origin gh-pages 117 | git checkout master 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | BBHTTP 2 | ====== 3 | 4 | BBHTTP is a rich wrapper for **libcurl** written in Objective-C. 5 | 6 | It is an ARC-only library that uses [features](http://clang.llvm.org/docs/ObjectiveCLiterals.html) introduced by Clang 3.1. Thus, it is only suitable for iOS 5+ and OSX 10.7+. 7 | 8 | It boasts an extremely simple and compact interface that allows you to reduce your code to fire off HTTP requests down to a couple of clean lines, while preserving full flexibility should you ever need it. 9 | 10 | ```objc 11 | [[BBHTTPRequest readResource:@"http://foo.bar/baz"] execute:^(BBHTTPResponse* r) { 12 | NSLog(@"Finished: %u %@ -- received %u bytes of '%@'.", 13 | r.code, r.message, r.contentSize, r[@"Content-Type"]); 14 | } error:^(NSError* e) { 15 | NSLog(@"Request failed: %@", [e localizedDescription]); 16 | }]; 17 | 18 | // Finished: 200 OK -- received 68364 bytes of 'text/html'. 19 | ``` 20 | 21 | At this stage there are still a lot of rough edges to polish, bugs to fix and features missing to bring it up-to-par with other similar projects. I want to add those over time but help is always more than welcome so be sure to open issues for the features you'd love to see or drop me a mention [@biasedbit](http://twitter.com/biasedbit) on Twitter. 22 | 23 | The API is **very** likely to keep mutating until this reaches 1.0. 24 | 25 | 26 | ## Highlights 27 | 28 | * Concise asynchronous-driven usage: 29 | 30 | ```objc 31 | [[BBHTTPRequest deleteResource:@"http://foo.bar/baz/1"] execute:^(BBHTTPResponse* r) { 32 | // handle response 33 | } error:nil]]; 34 | ``` 35 | 36 | > You don't even need to keep references to the requests, just fire and forget. 37 | 38 | 39 | * Handy common usage patterns: 40 | 41 | ```objc 42 | [[BBHTTPRequest readResource:@"http://foo.bar/baz/1"] setup:^(id request) { 43 | // Prepare request... 44 | } execute:^(BBHTTPResponse* response) { 45 | // Handle response... 46 | } error:^(NSError* error) { 47 | // Handle error... 48 | } finally:^{ 49 | // Do after error OR success. 50 | }]; 51 | 52 | 53 | * Get JSON effortlessly: 54 | 55 | ```objc 56 | [[[BBHTTPRequest readResource:@"http://foo.bar/baz.json"] asJSON] execute:^(BBHTTPResponse* r) { 57 | NSLog(@"User email: %@", r.content[@"user.email"]); 58 | NSLog(@"# of followers: %@", r.content[@"user.followers.@count"]); 59 | } error:^(NSError* error) { 60 | // Handle request *or* JSON decoding error 61 | }]; 62 | ``` 63 | 64 | > Notice the keyed subscript operator behaves as `valueForKeyPath:` rather than `valueForKey:`. That's because JSON responses that would yield a `NSDictionary` get wrapped by `BBJSONDictionary`. 65 | > Read more about the collection operators [here](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/CollectionOperators.html). 66 | 67 | * Images too: 68 | 69 | ```objc 70 | [[BBHTTPRequest readResource:@"http://foo.bar/baz.png"] setup:^(id request) { 71 | [request downloadContentAsImage]; 72 | } execute:^(BBHTTPResponse* response) { 73 | UIImage* image = response.content; // NSImage on OSX 74 | NSLog(@"image size: %@", NSStringFromCGSize(image.size)); 75 | } error:nil]; 76 | ``` 77 | 78 | > This example uses `downloadContentAsImage` on the `setup` block to setup the image download & conversion but you could also use the fluent syntax alternative (`asImage`), just like on the JSON example above. 79 | 80 | * Stream uploads from a `NSInputStream` or directly from a file: 81 | 82 | ```objc 83 | [[BBHTTPRequest createResource:@"http://foo.bar/baz" withContentsOfFile:@"/path/to/file"] 84 | setup:^(BBHTTPRequest* request) { 85 | request[@"Extra-Header"] = @"something else"; 86 | } execute:^(BBHTTPResponse* response) { 87 | // handle response 88 | } error:nil]; 89 | ``` 90 | 91 | > The request's content type and content length headers will be automatically set based on the file's properties. 92 | 93 | 94 | * Download to memory buffers or stream directly to file/`NSOutputStream`: 95 | 96 | ```objc 97 | [[BBHTTPRequest readResource:@"http://foo.bar/baz"] setup:^(BBHTTPRequest* request) { 98 | [request downloadToFile:@"/path/to/file"]; 99 | } execute:^(BBHTTPResponse* response) { 100 | // handle response 101 | } error:nil]; 102 | ``` 103 | 104 | > No need to delete the file if the download fails midway; BBHTTP will take care of keeping everything clean. 105 | 106 | 107 | * A *power-dev* API when you need that extra bit of control: 108 | 109 | ```objc 110 | BBHTTPExecutor* twitterExecutor = [BBHTTPExecutor initWithId:@"twitter.com"]; 111 | BBHTTPExecutor* facebookExecutor = [BBHTTPExecutor initWithId:@"facebook.com"]; 112 | twitterExecutor.maxParallelRequests = 10; 113 | facebookExecutor.maxParallelRequests = 2; 114 | ... 115 | BBHTTPRequest* request = [[BBHTTPRequest alloc] 116 | initWithURL:[NSURL URLWithString:@"http://twitter.com/resource"] 117 | andVerb:@"GET"]; 118 | 119 | request[@"Accept-Language"] = @"en-us"; 120 | request.downloadProgressBlock = ^(NSUInteger current, NSUInteger total) { /* ... */ }; 121 | request.finishBlock = ^(BBHTTPRequest* request) { /* ... */ }; 122 | 123 | [twitterExecutor executeRequest:request]; 124 | ``` 125 | 126 | There are other built-in ways to handle content from responses. Be sure to read up the [In-depth guide to response content handling](https://github.com/brunodecarvalho/BBHTTP/wiki/Response-content-handling). 127 | 128 | 129 | # Documentation 130 | 131 | * Guides and tutorials available on the [wiki pages](https://github.com/brunodecarvalho/BBHTTP/wiki). 132 | * API available at [CocoaDocs](http://cocoadocs.org/docsets/BBHTTP). 133 | 134 | 135 | ## Likely TODO list 136 | 137 | * Multipart upload helpers 138 | * Follow redirects 139 | * Use curl's multi handles 140 | * *Your bright idea here* 141 | 142 | For a comprehensive list, be sure to visit the [Roadmap](https://github.com/brunodecarvalho/BBHTTP/wiki/Roadmap) wiki page. 143 | 144 | 145 | ## Why? 146 | 147 | You mean other than its sleek API or the fact that it uses libcurl underneath? 148 | 149 | Well, unlike `NSURLConnection` and, consequently, any lib that relies on it, BBHTTP... 150 | 151 | * is strictly compliant with [section 8.2.3](http://tools.ietf.org/html/rfc2616#section-8.2.3) of RFC 2616, a.k.a. the misbeloved `Expect: 100-Continue` header; 152 | * can receive server error responses midway through upload — as opposed to continuing to pump data into socket eden, and eventually reporting connection timeout instead of the actual error response sent by the server. 153 | 154 | *"But my uploads work just fine..."* 155 | 156 | * If you only wrote code that uploads to a server, you've probably never noticed either of the above; 157 | * If you wrote both client *and* server-side code to handle uploads, chances are that you never ran into either of the above either; 158 | * If you're hardcore and wrote your own server *and* client *and* noticed `NSURLConnection` ignores errors until it finishes its upload, then this is the HTTP framework for you. Also, fistbump for writing your server and client. And paying attention to the specs. 159 | 160 | On a more serious tone, the motivation for this libcurl wrapper was that during development of [Droplr](http://droplr.com)'s API server, we noticed that whenever the API rejected an upload and immediately closed the connection — which is a perfectly legal & reasonable behavior — the Cocoa-based clients would keep reporting upload progress (even though I **knew** the socket was closed) and eventually fail with "Request timeout", instead of the response the server had sent down the pipes. 161 | 162 | This meant that: 163 | 164 | 1. `NSURLConnection` wasn't waiting for the `100-Continue` provisional response before sending along the request body; 165 | 2. `NSURLConnection` wasn't realizing that a response was already sent and the connection was dying until it finished uploading what it had to upload. *stubborn bastard, eh?* 166 | 167 | I did file a bug report but after a year of waiting for a response, I decided to come up with a working alternative. Coincidentally, the same day I let this library out in the open, I got a reply from Apple — closing the bug as a duplicate of some other I don't have access to. 168 | 169 | A couple of quick tests with command line version of curl proved that curl knew how to properly handle these edge cases so it was time to build a new HTTP framework for Cocoa. 170 | 171 | > During that process, [this handy build script](https://github.com/brunodecarvalho/curl-ios-build-scripts) was produced, so even if you don't want to use this library but are still interested in getting curl running on iOS, do check it out! 172 | 173 | 174 | ## Dependencies 175 | 176 | * `libcurl` (read below) 177 | * `libz.dylib` 178 | * `Security.framework` 179 | * `CoreServices.framework` on OSX, `MobileCoreServices.framework` on iOS 180 | * `AppKit.framework` on OSX, `UIKit.framework` on iOS 181 | 182 | > **Note:** You can find libcurl 7.30.0 binaries and headers under `Build/iOS/Static lib/libcurl` and `Build/OSX/Static lib/libcurl`. There are two versions for iOS, compiled against 6.1 SDK. `libcurl.iOS.dev.a` has support for for i386 (simulator), armv7 and armv7s (iPhone 3GS and newer) while `libcurl.iOS.appstore.a` only has support for arm architectures — making it smaller in size and thus optimized for releases. The OSX version was compiled against 10.8 SDK with support for x86_64 (64 bit Intel). If you'd like to build your own custom version, try [this](https://github.com/brunodecarvalho/curl-ios-build-scripts). 183 | > All binaries are compiled with debug symbols so even though they appear large, they'll end up with 400~600KB. 184 | 185 | 186 | ## Documentation 187 | 188 | For guides on how to setup and start working with this lib, check out [the wiki pages](https://github.com/brunodecarvalho/BBHTTP/wiki). 189 | 190 | The project also includes comprehensive class-level documentation. If you happen to have [appledoc](https://github.com/tomaz/appledoc) installed, just run the `generate` script on the `Docs` folder and it'll create html documentation for you under `Docs/html`. 191 | 192 | 193 | ## Acknowledgements 194 | 195 | * Daniel Stenberg and everyone else involved in making cURL and libcurl 196 | * Nick Zitzmann for the Secure Transport TLS/SSL curl plugin 197 | * Ben Copsey for ASIHTTPRequest, which has been my HTTP workhorse on iOS since day 0 198 | 199 | 200 | ## License 201 | 202 | BBHTTP is licensed under the Apache Software License version 2.0 203 | 204 | 205 | ## Get in touch 206 | 207 | I'm on twitter as [@biasedbit](https://twitter.com/biasedbit). 208 | I also [write](http://biasedbit.com/) every now and then. 209 | -------------------------------------------------------------------------------- /Unit Tests/BBHTTPRequestTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 BiasedBit 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // 18 | // Created by Bruno de Carvalho - @biasedbit / http://biasedbit.com 19 | // Copyright (c) 2013 BiasedBit. All rights reserved. 20 | // 21 | 22 | #import 23 | 24 | #import "BBHTTPRequest.h" 25 | 26 | 27 | 28 | #pragma mark - 29 | 30 | @interface BBHTTPRequestTests : SenTestCase 31 | @end 32 | 33 | @implementation BBHTTPRequestTests 34 | 35 | - (void)testFormData 36 | { 37 | BBHTTPRequest* post = [[BBHTTPRequest alloc] initWithTarget:@"http://biasedbit.com" andVerb:@"POST"]; 38 | 39 | NSDictionary* uploadFormData = @{@"foo": @"bar", @"baz": @"2"}; 40 | STAssertTrue([post setUploadFormData:uploadFormData], 41 | @"setUploadFormData: returned NO"); 42 | 43 | NSString* expectedFormDataString = @"foo=bar&baz=2"; 44 | NSData* expectedFormData = [expectedFormDataString dataUsingEncoding:NSASCIIStringEncoding]; 45 | 46 | STAssertNotNil(post[@"Content-Type"], 47 | @"Content-Type header is nil"); 48 | STAssertNotNil(post[@"Content-Length"], 49 | @"Content-Length header is nil"); 50 | STAssertTrue([post[@"Content-Type"] isEqualToString:@"application/x-www-form-urlencoded"], 51 | @"Content-Type header doesn't match expected value"); 52 | STAssertEquals(post.uploadSize, [expectedFormDataString length], 53 | @"upload size doesn't match expected value"); 54 | STAssertTrue([expectedFormData isEqualToData:post.uploadData], 55 | @"request upload data doesn't match expected value"); 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Unit Tests/Supporting Files/Unit Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.biasedbit.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Unit Tests/Supporting Files/Unit Tests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Unit Tests' target in the 'Unit Tests' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Unit Tests/Supporting Files/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | --------------------------------------------------------------------------------