├── .gitignore ├── Podfile ├── Podfile.lock ├── Pods ├── GCDWebServer │ ├── GCDWebServer │ │ ├── Core │ │ │ ├── GCDWebServer.h │ │ │ ├── GCDWebServer.m │ │ │ ├── GCDWebServerConnection.h │ │ │ ├── GCDWebServerConnection.m │ │ │ ├── GCDWebServerFunctions.h │ │ │ ├── GCDWebServerFunctions.m │ │ │ ├── GCDWebServerHTTPStatusCodes.h │ │ │ ├── GCDWebServerPrivate.h │ │ │ ├── GCDWebServerRequest.h │ │ │ ├── GCDWebServerRequest.m │ │ │ ├── GCDWebServerResponse.h │ │ │ └── GCDWebServerResponse.m │ │ ├── Requests │ │ │ ├── GCDWebServerDataRequest.h │ │ │ ├── GCDWebServerDataRequest.m │ │ │ ├── GCDWebServerFileRequest.h │ │ │ ├── GCDWebServerFileRequest.m │ │ │ ├── GCDWebServerMultiPartFormRequest.h │ │ │ ├── GCDWebServerMultiPartFormRequest.m │ │ │ ├── GCDWebServerURLEncodedFormRequest.h │ │ │ └── GCDWebServerURLEncodedFormRequest.m │ │ └── Responses │ │ │ ├── GCDWebServerDataResponse.h │ │ │ ├── GCDWebServerDataResponse.m │ │ │ ├── GCDWebServerErrorResponse.h │ │ │ ├── GCDWebServerErrorResponse.m │ │ │ ├── GCDWebServerFileResponse.h │ │ │ ├── GCDWebServerFileResponse.m │ │ │ ├── GCDWebServerStreamedResponse.h │ │ │ └── GCDWebServerStreamedResponse.m │ ├── LICENSE │ └── README.md ├── Headers │ ├── Private │ │ └── GCDWebServer │ │ │ ├── GCDWebServer.h │ │ │ ├── GCDWebServerConnection.h │ │ │ ├── GCDWebServerDataRequest.h │ │ │ ├── GCDWebServerDataResponse.h │ │ │ ├── GCDWebServerErrorResponse.h │ │ │ ├── GCDWebServerFileRequest.h │ │ │ ├── GCDWebServerFileResponse.h │ │ │ ├── GCDWebServerFunctions.h │ │ │ ├── GCDWebServerHTTPStatusCodes.h │ │ │ ├── GCDWebServerMultiPartFormRequest.h │ │ │ ├── GCDWebServerPrivate.h │ │ │ ├── GCDWebServerRequest.h │ │ │ ├── GCDWebServerResponse.h │ │ │ ├── GCDWebServerStreamedResponse.h │ │ │ └── GCDWebServerURLEncodedFormRequest.h │ └── Public │ │ └── GCDWebServer │ │ ├── GCDWebServer.h │ │ ├── GCDWebServerConnection.h │ │ ├── GCDWebServerDataRequest.h │ │ ├── GCDWebServerDataResponse.h │ │ ├── GCDWebServerErrorResponse.h │ │ ├── GCDWebServerFileRequest.h │ │ ├── GCDWebServerFileResponse.h │ │ ├── GCDWebServerFunctions.h │ │ ├── GCDWebServerHTTPStatusCodes.h │ │ ├── GCDWebServerMultiPartFormRequest.h │ │ ├── GCDWebServerRequest.h │ │ ├── GCDWebServerResponse.h │ │ ├── GCDWebServerStreamedResponse.h │ │ └── GCDWebServerURLEncodedFormRequest.h ├── Manifest.lock ├── Pods.xcodeproj │ └── project.pbxproj └── Target Support Files │ ├── GCDWebServer │ ├── GCDWebServer-dummy.m │ ├── GCDWebServer-prefix.pch │ └── GCDWebServer.xcconfig │ └── Pods-TestNSlog │ ├── Pods-TestNSlog-acknowledgements.markdown │ ├── Pods-TestNSlog-acknowledgements.plist │ ├── Pods-TestNSlog-dummy.m │ ├── Pods-TestNSlog-frameworks.sh │ ├── Pods-TestNSlog-resources.sh │ ├── Pods-TestNSlog.debug.xcconfig │ └── Pods-TestNSlog.release.xcconfig ├── README.md ├── TestNSlog.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── yohunl.xcuserdatad │ └── xcschemes │ ├── TestNSlog.xcscheme │ └── xcschememanagement.plist ├── TestNSlog.xcworkspace └── contents.xcworkspacedata └── TestNSlog ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets └── AppIcon.appiconset │ └── Contents.json ├── Base.lproj └── LaunchScreen.storyboard ├── HttpServerLogger.h ├── HttpServerLogger.m ├── Info.plist ├── SystemLogManager.h ├── SystemLogManager.m ├── SystemLogMessage.h ├── SystemLogMessage.m ├── ViewController.h ├── ViewController.m └── main.m /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Bundler 23 | .bundle 24 | 25 | #AppCode 26 | .idea/ 27 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | platform :ios, '8.0' 3 | # Uncomment this line if you're using Swift 4 | # use_frameworks! 5 | 6 | target 'TestNSlog' do 7 | pod "GCDWebServer", "~> 3.0" 8 | end 9 | 10 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - GCDWebServer (3.3.2): 3 | - GCDWebServer/Core (= 3.3.2) 4 | - GCDWebServer/Core (3.3.2) 5 | 6 | DEPENDENCIES: 7 | - GCDWebServer (~> 3.0) 8 | 9 | SPEC CHECKSUMS: 10 | GCDWebServer: 2a375ec42839a41d7187d04e5b688d32fa5c4cd5 11 | 12 | PODFILE CHECKSUM: 455efa81127280c58f42ca02e62e90533753e8ad 13 | 14 | COCOAPODS: 1.0.0.beta.8 15 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Core/GCDWebServerConnection.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServer.h" 29 | 30 | @class GCDWebServerHandler; 31 | 32 | /** 33 | * The GCDWebServerConnection class is instantiated by GCDWebServer to handle 34 | * each new HTTP connection. Each instance stays alive until the connection is 35 | * closed. 36 | * 37 | * You cannot use this class directly, but it is made public so you can 38 | * subclass it to override some hooks. Use the GCDWebServerOption_ConnectionClass 39 | * option for GCDWebServer to install your custom subclass. 40 | * 41 | * @warning The GCDWebServerConnection retains the GCDWebServer until the 42 | * connection is closed. 43 | */ 44 | @interface GCDWebServerConnection : NSObject 45 | 46 | /** 47 | * Returns the GCDWebServer that owns the connection. 48 | */ 49 | @property(nonatomic, readonly) GCDWebServer* server; 50 | 51 | /** 52 | * Returns YES if the connection is using IPv6. 53 | */ 54 | @property(nonatomic, readonly, getter=isUsingIPv6) BOOL usingIPv6; 55 | 56 | /** 57 | * Returns the address of the local peer (i.e. server) of the connection 58 | * as a raw "struct sockaddr". 59 | */ 60 | @property(nonatomic, readonly) NSData* localAddressData; 61 | 62 | /** 63 | * Returns the address of the local peer (i.e. server) of the connection 64 | * as a string. 65 | */ 66 | @property(nonatomic, readonly) NSString* localAddressString; 67 | 68 | /** 69 | * Returns the address of the remote peer (i.e. client) of the connection 70 | * as a raw "struct sockaddr". 71 | */ 72 | @property(nonatomic, readonly) NSData* remoteAddressData; 73 | 74 | /** 75 | * Returns the address of the remote peer (i.e. client) of the connection 76 | * as a string. 77 | */ 78 | @property(nonatomic, readonly) NSString* remoteAddressString; 79 | 80 | /** 81 | * Returns the total number of bytes received from the remote peer (i.e. client) 82 | * so far. 83 | */ 84 | @property(nonatomic, readonly) NSUInteger totalBytesRead; 85 | 86 | /** 87 | * Returns the total number of bytes sent to the remote peer (i.e. client) so far. 88 | */ 89 | @property(nonatomic, readonly) NSUInteger totalBytesWritten; 90 | 91 | @end 92 | 93 | /** 94 | * Hooks to customize the behavior of GCDWebServer HTTP connections. 95 | * 96 | * @warning These methods can be called on any GCD thread. 97 | * Be sure to also call "super" when overriding them. 98 | */ 99 | @interface GCDWebServerConnection (Subclassing) 100 | 101 | /** 102 | * This method is called when the connection is opened. 103 | * 104 | * Return NO to reject the connection e.g. after validating the local 105 | * or remote address. 106 | */ 107 | - (BOOL)open; 108 | 109 | /** 110 | * This method is called whenever data has been received 111 | * from the remote peer (i.e. client). 112 | * 113 | * @warning Do not attempt to modify this data. 114 | */ 115 | - (void)didReadBytes:(const void*)bytes length:(NSUInteger)length; 116 | 117 | /** 118 | * This method is called whenever data has been sent 119 | * to the remote peer (i.e. client). 120 | * 121 | * @warning Do not attempt to modify this data. 122 | */ 123 | - (void)didWriteBytes:(const void*)bytes length:(NSUInteger)length; 124 | 125 | /** 126 | * This method is called after the HTTP headers have been received to 127 | * allow replacing the request URL by another one. 128 | * 129 | * The default implementation returns the original URL. 130 | */ 131 | - (NSURL*)rewriteRequestURL:(NSURL*)url withMethod:(NSString*)method headers:(NSDictionary*)headers; 132 | 133 | /** 134 | * Assuming a valid HTTP request was received, this method is called before 135 | * the request is processed. 136 | * 137 | * Return a non-nil GCDWebServerResponse to bypass the request processing entirely. 138 | * 139 | * The default implementation checks for HTTP authentication if applicable 140 | * and returns a barebone 401 status code response if authentication failed. 141 | */ 142 | - (GCDWebServerResponse*)preflightRequest:(GCDWebServerRequest*)request; 143 | 144 | /** 145 | * Assuming a valid HTTP request was received and -preflightRequest: returned nil, 146 | * this method is called to process the request by executing the handler's 147 | * process block. 148 | */ 149 | - (void)processRequest:(GCDWebServerRequest*)request completion:(GCDWebServerCompletionBlock)completion; 150 | 151 | /** 152 | * Assuming a valid HTTP request was received and either -preflightRequest: 153 | * or -processRequest:completion: returned a non-nil GCDWebServerResponse, 154 | * this method is called to override the response. 155 | * 156 | * You can either modify the current response and return it, or return a 157 | * completely new one. 158 | * 159 | * The default implementation replaces any response matching the "ETag" or 160 | * "Last-Modified-Date" header of the request by a barebone "Not-Modified" (304) 161 | * one. 162 | */ 163 | - (GCDWebServerResponse*)overrideResponse:(GCDWebServerResponse*)response forRequest:(GCDWebServerRequest*)request; 164 | 165 | /** 166 | * This method is called if any error happens while validing or processing 167 | * the request or if no GCDWebServerResponse was generated during processing. 168 | * 169 | * @warning If the request was invalid (e.g. the HTTP headers were malformed), 170 | * the "request" argument will be nil. 171 | */ 172 | - (void)abortRequest:(GCDWebServerRequest*)request withStatusCode:(NSInteger)statusCode; 173 | 174 | /** 175 | * Called when the connection is closed. 176 | */ 177 | - (void)close; 178 | 179 | @end 180 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | /** 35 | * Converts a file extension to the corresponding MIME type. 36 | * If there is no match, "application/octet-stream" is returned. 37 | */ 38 | NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension); 39 | 40 | /** 41 | * Add percent-escapes to a string so it can be used in a URL. 42 | * The legal characters ":@/?&=+" are also escaped to ensure compatibility 43 | * with URL encoded forms and URL queries. 44 | */ 45 | NSString* GCDWebServerEscapeURLString(NSString* string); 46 | 47 | /** 48 | * Unescapes a URL percent-encoded string. 49 | */ 50 | NSString* GCDWebServerUnescapeURLString(NSString* string); 51 | 52 | /** 53 | * Extracts the unescaped names and values from an 54 | * "application/x-www-form-urlencoded" form. 55 | * http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1 56 | */ 57 | NSDictionary* GCDWebServerParseURLEncodedForm(NSString* form); 58 | 59 | /** 60 | * On OS X, returns the IPv4 or IPv6 address as a string of the primary 61 | * connected service or nil if not available. 62 | * 63 | * On iOS, returns the IPv4 or IPv6 address as a string of the WiFi 64 | * interface if connected or nil otherwise. 65 | */ 66 | NSString* GCDWebServerGetPrimaryIPAddress(BOOL useIPv6); 67 | 68 | /** 69 | * Converts a date into a string using RFC822 formatting. 70 | * https://tools.ietf.org/html/rfc822#section-5 71 | * https://tools.ietf.org/html/rfc1123#section-5.2.14 72 | */ 73 | NSString* GCDWebServerFormatRFC822(NSDate* date); 74 | 75 | /** 76 | * Converts a RFC822 formatted string into a date. 77 | * https://tools.ietf.org/html/rfc822#section-5 78 | * https://tools.ietf.org/html/rfc1123#section-5.2.14 79 | * 80 | * @warning Timezones other than GMT are not supported by this function. 81 | */ 82 | NSDate* GCDWebServerParseRFC822(NSString* string); 83 | 84 | /** 85 | * Converts a date into a string using IOS 8601 formatting. 86 | * http://tools.ietf.org/html/rfc3339#section-5.6 87 | */ 88 | NSString* GCDWebServerFormatISO8601(NSDate* date); 89 | 90 | /** 91 | * Converts a ISO 8601 formatted string into a date. 92 | * http://tools.ietf.org/html/rfc3339#section-5.6 93 | * 94 | * @warning Only "calendar" variant is supported at this time and timezones 95 | * other than GMT are not supported either. 96 | */ 97 | NSDate* GCDWebServerParseISO8601(NSString* string); 98 | 99 | #ifdef __cplusplus 100 | } 101 | #endif 102 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import 33 | #if TARGET_OS_IPHONE 34 | #import 35 | #else 36 | #import 37 | #endif 38 | #import 39 | 40 | #import 41 | #import 42 | #import 43 | 44 | #import "GCDWebServerPrivate.h" 45 | 46 | static NSDateFormatter* _dateFormatterRFC822 = nil; 47 | static NSDateFormatter* _dateFormatterISO8601 = nil; 48 | static dispatch_queue_t _dateFormatterQueue = NULL; 49 | 50 | // TODO: Handle RFC 850 and ANSI C's asctime() format 51 | void GCDWebServerInitializeFunctions() { 52 | GWS_DCHECK([NSThread isMainThread]); // NSDateFormatter should be initialized on main thread 53 | if (_dateFormatterRFC822 == nil) { 54 | _dateFormatterRFC822 = [[NSDateFormatter alloc] init]; 55 | _dateFormatterRFC822.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"]; 56 | _dateFormatterRFC822.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'"; 57 | _dateFormatterRFC822.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; 58 | GWS_DCHECK(_dateFormatterRFC822); 59 | } 60 | if (_dateFormatterISO8601 == nil) { 61 | _dateFormatterISO8601 = [[NSDateFormatter alloc] init]; 62 | _dateFormatterISO8601.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"]; 63 | _dateFormatterISO8601.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss'+00:00'"; 64 | _dateFormatterISO8601.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; 65 | GWS_DCHECK(_dateFormatterISO8601); 66 | } 67 | if (_dateFormatterQueue == NULL) { 68 | _dateFormatterQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); 69 | GWS_DCHECK(_dateFormatterQueue); 70 | } 71 | } 72 | 73 | NSString* GCDWebServerNormalizeHeaderValue(NSString* value) { 74 | if (value) { 75 | NSRange range = [value rangeOfString:@";"]; // Assume part before ";" separator is case-insensitive 76 | if (range.location != NSNotFound) { 77 | value = [[[value substringToIndex:range.location] lowercaseString] stringByAppendingString:[value substringFromIndex:range.location]]; 78 | } else { 79 | value = [value lowercaseString]; 80 | } 81 | } 82 | return value; 83 | } 84 | 85 | NSString* GCDWebServerTruncateHeaderValue(NSString* value) { 86 | NSRange range = [value rangeOfString:@";"]; 87 | return range.location != NSNotFound ? [value substringToIndex:range.location] : value; 88 | } 89 | 90 | NSString* GCDWebServerExtractHeaderValueParameter(NSString* value, NSString* name) { 91 | NSString* parameter = nil; 92 | NSScanner* scanner = [[NSScanner alloc] initWithString:value]; 93 | [scanner setCaseSensitive:NO]; // Assume parameter names are case-insensitive 94 | NSString* string = [NSString stringWithFormat:@"%@=", name]; 95 | if ([scanner scanUpToString:string intoString:NULL]) { 96 | [scanner scanString:string intoString:NULL]; 97 | if ([scanner scanString:@"\"" intoString:NULL]) { 98 | [scanner scanUpToString:@"\"" intoString:¶meter]; 99 | } else { 100 | [scanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:¶meter]; 101 | } 102 | } 103 | return parameter; 104 | } 105 | 106 | // http://www.w3schools.com/tags/ref_charactersets.asp 107 | NSStringEncoding GCDWebServerStringEncodingFromCharset(NSString* charset) { 108 | NSStringEncoding encoding = kCFStringEncodingInvalidId; 109 | if (charset) { 110 | encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)charset)); 111 | } 112 | return (encoding != kCFStringEncodingInvalidId ? encoding : NSUTF8StringEncoding); 113 | } 114 | 115 | NSString* GCDWebServerFormatRFC822(NSDate* date) { 116 | __block NSString* string; 117 | dispatch_sync(_dateFormatterQueue, ^{ 118 | string = [_dateFormatterRFC822 stringFromDate:date]; 119 | }); 120 | return string; 121 | } 122 | 123 | NSDate* GCDWebServerParseRFC822(NSString* string) { 124 | __block NSDate* date; 125 | dispatch_sync(_dateFormatterQueue, ^{ 126 | date = [_dateFormatterRFC822 dateFromString:string]; 127 | }); 128 | return date; 129 | } 130 | 131 | NSString* GCDWebServerFormatISO8601(NSDate* date) { 132 | __block NSString* string; 133 | dispatch_sync(_dateFormatterQueue, ^{ 134 | string = [_dateFormatterISO8601 stringFromDate:date]; 135 | }); 136 | return string; 137 | } 138 | 139 | NSDate* GCDWebServerParseISO8601(NSString* string) { 140 | __block NSDate* date; 141 | dispatch_sync(_dateFormatterQueue, ^{ 142 | date = [_dateFormatterISO8601 dateFromString:string]; 143 | }); 144 | return date; 145 | } 146 | 147 | BOOL GCDWebServerIsTextContentType(NSString* type) { 148 | return ([type hasPrefix:@"text/"] || [type hasPrefix:@"application/json"] || [type hasPrefix:@"application/xml"]); 149 | } 150 | 151 | NSString* GCDWebServerDescribeData(NSData* data, NSString* type) { 152 | if (GCDWebServerIsTextContentType(type)) { 153 | NSString* charset = GCDWebServerExtractHeaderValueParameter(type, @"charset"); 154 | NSString* string = [[NSString alloc] initWithData:data encoding:GCDWebServerStringEncodingFromCharset(charset)]; 155 | if (string) { 156 | return string; 157 | } 158 | } 159 | return [NSString stringWithFormat:@"<%lu bytes>", (unsigned long)data.length]; 160 | } 161 | 162 | NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension) { 163 | static NSDictionary* _overrides = nil; 164 | if (_overrides == nil) { 165 | _overrides = [[NSDictionary alloc] initWithObjectsAndKeys: 166 | @"text/css", @"css", 167 | nil]; 168 | } 169 | NSString* mimeType = nil; 170 | extension = [extension lowercaseString]; 171 | if (extension.length) { 172 | mimeType = [_overrides objectForKey:extension]; 173 | if (mimeType == nil) { 174 | CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)extension, NULL); 175 | if (uti) { 176 | mimeType = CFBridgingRelease(UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)); 177 | CFRelease(uti); 178 | } 179 | } 180 | } 181 | return mimeType ? mimeType : kGCDWebServerDefaultMimeType; 182 | } 183 | 184 | NSString* GCDWebServerEscapeURLString(NSString* string) { 185 | #pragma clang diagnostic push 186 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" 187 | return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, CFSTR(":@/?&=+"), kCFStringEncodingUTF8)); 188 | #pragma clang diagnostic pop 189 | } 190 | 191 | NSString* GCDWebServerUnescapeURLString(NSString* string) { 192 | #pragma clang diagnostic push 193 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" 194 | return CFBridgingRelease(CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, (CFStringRef)string, CFSTR(""), kCFStringEncodingUTF8)); 195 | #pragma clang diagnostic pop 196 | } 197 | 198 | NSDictionary* GCDWebServerParseURLEncodedForm(NSString* form) { 199 | NSMutableDictionary* parameters = [NSMutableDictionary dictionary]; 200 | NSScanner* scanner = [[NSScanner alloc] initWithString:form]; 201 | [scanner setCharactersToBeSkipped:nil]; 202 | while (1) { 203 | NSString* key = nil; 204 | if (![scanner scanUpToString:@"=" intoString:&key] || [scanner isAtEnd]) { 205 | break; 206 | } 207 | [scanner setScanLocation:([scanner scanLocation] + 1)]; 208 | 209 | NSString* value = nil; 210 | [scanner scanUpToString:@"&" intoString:&value]; 211 | if (value == nil) { 212 | value = @""; 213 | } 214 | 215 | key = [key stringByReplacingOccurrencesOfString:@"+" withString:@" "]; 216 | NSString* unescapedKey = key ? GCDWebServerUnescapeURLString(key) : nil; 217 | value = [value stringByReplacingOccurrencesOfString:@"+" withString:@" "]; 218 | NSString* unescapedValue = value ? GCDWebServerUnescapeURLString(value) : nil; 219 | if (unescapedKey && unescapedValue) { 220 | [parameters setObject:unescapedValue forKey:unescapedKey]; 221 | } else { 222 | GWS_LOG_WARNING(@"Failed parsing URL encoded form for key \"%@\" and value \"%@\"", key, value); 223 | GWS_DNOT_REACHED(); 224 | } 225 | 226 | if ([scanner isAtEnd]) { 227 | break; 228 | } 229 | [scanner setScanLocation:([scanner scanLocation] + 1)]; 230 | } 231 | return parameters; 232 | } 233 | 234 | NSString* GCDWebServerStringFromSockAddr(const struct sockaddr* addr, BOOL includeService) { 235 | NSString* string = nil; 236 | char hostBuffer[NI_MAXHOST]; 237 | char serviceBuffer[NI_MAXSERV]; 238 | if (getnameinfo(addr, addr->sa_len, hostBuffer, sizeof(hostBuffer), serviceBuffer, sizeof(serviceBuffer), NI_NUMERICHOST | NI_NUMERICSERV | NI_NOFQDN) >= 0) { 239 | string = includeService ? [NSString stringWithFormat:@"%s:%s", hostBuffer, serviceBuffer] : [NSString stringWithUTF8String:hostBuffer]; 240 | } else { 241 | GWS_DNOT_REACHED(); 242 | } 243 | return string; 244 | } 245 | 246 | NSString* GCDWebServerGetPrimaryIPAddress(BOOL useIPv6) { 247 | NSString* address = nil; 248 | #if TARGET_OS_IPHONE 249 | #if !TARGET_IPHONE_SIMULATOR && !TARGET_OS_TV 250 | const char* primaryInterface = "en0"; // WiFi interface on iOS 251 | #endif 252 | #else 253 | const char* primaryInterface = NULL; 254 | SCDynamicStoreRef store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("GCDWebServer"), NULL, NULL); 255 | if (store) { 256 | CFPropertyListRef info = SCDynamicStoreCopyValue(store, CFSTR("State:/Network/Global/IPv4")); // There is no equivalent for IPv6 but the primary interface should be the same 257 | if (info) { 258 | primaryInterface = [[NSString stringWithString:[(__bridge NSDictionary*)info objectForKey:@"PrimaryInterface"]] UTF8String]; 259 | CFRelease(info); 260 | } 261 | CFRelease(store); 262 | } 263 | if (primaryInterface == NULL) { 264 | primaryInterface = "lo0"; 265 | } 266 | #endif 267 | struct ifaddrs* list; 268 | if (getifaddrs(&list) >= 0) { 269 | for (struct ifaddrs* ifap = list; ifap; ifap = ifap->ifa_next) { 270 | #if TARGET_IPHONE_SIMULATOR || TARGET_OS_TV 271 | // Assume en0 is Ethernet and en1 is WiFi since there is no way to use SystemConfiguration framework in iOS Simulator 272 | // Assumption holds for Apple TV running tvOS 273 | if (strcmp(ifap->ifa_name, "en0") && strcmp(ifap->ifa_name, "en1")) 274 | #else 275 | if (strcmp(ifap->ifa_name, primaryInterface)) 276 | #endif 277 | { 278 | continue; 279 | } 280 | if ((ifap->ifa_flags & IFF_UP) && ((!useIPv6 && (ifap->ifa_addr->sa_family == AF_INET)) || (useIPv6 && (ifap->ifa_addr->sa_family == AF_INET6)))) { 281 | address = GCDWebServerStringFromSockAddr(ifap->ifa_addr, NO); 282 | break; 283 | } 284 | } 285 | freeifaddrs(list); 286 | } 287 | return address; 288 | } 289 | 290 | NSString* GCDWebServerComputeMD5Digest(NSString* format, ...) { 291 | va_list arguments; 292 | va_start(arguments, format); 293 | const char* string = [[[NSString alloc] initWithFormat:format arguments:arguments] UTF8String]; 294 | va_end(arguments); 295 | unsigned char md5[CC_MD5_DIGEST_LENGTH]; 296 | CC_MD5(string, (CC_LONG)strlen(string), md5); 297 | char buffer[2 * CC_MD5_DIGEST_LENGTH + 1]; 298 | for (int i = 0; i < CC_MD5_DIGEST_LENGTH; ++i) { 299 | unsigned char byte = md5[i]; 300 | unsigned char byteHi = (byte & 0xF0) >> 4; 301 | buffer[2 * i + 0] = byteHi >= 10 ? 'a' + byteHi - 10 : '0' + byteHi; 302 | unsigned char byteLo = byte & 0x0F; 303 | buffer[2 * i + 1] = byteLo >= 10 ? 'a' + byteLo - 10 : '0' + byteLo; 304 | } 305 | buffer[2 * CC_MD5_DIGEST_LENGTH] = 0; 306 | return [NSString stringWithUTF8String:buffer]; 307 | } 308 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Core/GCDWebServerHTTPStatusCodes.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 29 | // http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml 30 | 31 | #import 32 | 33 | /** 34 | * Convenience constants for "informational" HTTP status codes. 35 | */ 36 | typedef NS_ENUM(NSInteger, GCDWebServerInformationalHTTPStatusCode) { 37 | kGCDWebServerHTTPStatusCode_Continue = 100, 38 | kGCDWebServerHTTPStatusCode_SwitchingProtocols = 101, 39 | kGCDWebServerHTTPStatusCode_Processing = 102 40 | }; 41 | 42 | /** 43 | * Convenience constants for "successful" HTTP status codes. 44 | */ 45 | typedef NS_ENUM(NSInteger, GCDWebServerSuccessfulHTTPStatusCode) { 46 | kGCDWebServerHTTPStatusCode_OK = 200, 47 | kGCDWebServerHTTPStatusCode_Created = 201, 48 | kGCDWebServerHTTPStatusCode_Accepted = 202, 49 | kGCDWebServerHTTPStatusCode_NonAuthoritativeInformation = 203, 50 | kGCDWebServerHTTPStatusCode_NoContent = 204, 51 | kGCDWebServerHTTPStatusCode_ResetContent = 205, 52 | kGCDWebServerHTTPStatusCode_PartialContent = 206, 53 | kGCDWebServerHTTPStatusCode_MultiStatus = 207, 54 | kGCDWebServerHTTPStatusCode_AlreadyReported = 208 55 | }; 56 | 57 | /** 58 | * Convenience constants for "redirection" HTTP status codes. 59 | */ 60 | typedef NS_ENUM(NSInteger, GCDWebServerRedirectionHTTPStatusCode) { 61 | kGCDWebServerHTTPStatusCode_MultipleChoices = 300, 62 | kGCDWebServerHTTPStatusCode_MovedPermanently = 301, 63 | kGCDWebServerHTTPStatusCode_Found = 302, 64 | kGCDWebServerHTTPStatusCode_SeeOther = 303, 65 | kGCDWebServerHTTPStatusCode_NotModified = 304, 66 | kGCDWebServerHTTPStatusCode_UseProxy = 305, 67 | kGCDWebServerHTTPStatusCode_TemporaryRedirect = 307, 68 | kGCDWebServerHTTPStatusCode_PermanentRedirect = 308 69 | }; 70 | 71 | /** 72 | * Convenience constants for "client error" HTTP status codes. 73 | */ 74 | typedef NS_ENUM(NSInteger, GCDWebServerClientErrorHTTPStatusCode) { 75 | kGCDWebServerHTTPStatusCode_BadRequest = 400, 76 | kGCDWebServerHTTPStatusCode_Unauthorized = 401, 77 | kGCDWebServerHTTPStatusCode_PaymentRequired = 402, 78 | kGCDWebServerHTTPStatusCode_Forbidden = 403, 79 | kGCDWebServerHTTPStatusCode_NotFound = 404, 80 | kGCDWebServerHTTPStatusCode_MethodNotAllowed = 405, 81 | kGCDWebServerHTTPStatusCode_NotAcceptable = 406, 82 | kGCDWebServerHTTPStatusCode_ProxyAuthenticationRequired = 407, 83 | kGCDWebServerHTTPStatusCode_RequestTimeout = 408, 84 | kGCDWebServerHTTPStatusCode_Conflict = 409, 85 | kGCDWebServerHTTPStatusCode_Gone = 410, 86 | kGCDWebServerHTTPStatusCode_LengthRequired = 411, 87 | kGCDWebServerHTTPStatusCode_PreconditionFailed = 412, 88 | kGCDWebServerHTTPStatusCode_RequestEntityTooLarge = 413, 89 | kGCDWebServerHTTPStatusCode_RequestURITooLong = 414, 90 | kGCDWebServerHTTPStatusCode_UnsupportedMediaType = 415, 91 | kGCDWebServerHTTPStatusCode_RequestedRangeNotSatisfiable = 416, 92 | kGCDWebServerHTTPStatusCode_ExpectationFailed = 417, 93 | kGCDWebServerHTTPStatusCode_UnprocessableEntity = 422, 94 | kGCDWebServerHTTPStatusCode_Locked = 423, 95 | kGCDWebServerHTTPStatusCode_FailedDependency = 424, 96 | kGCDWebServerHTTPStatusCode_UpgradeRequired = 426, 97 | kGCDWebServerHTTPStatusCode_PreconditionRequired = 428, 98 | kGCDWebServerHTTPStatusCode_TooManyRequests = 429, 99 | kGCDWebServerHTTPStatusCode_RequestHeaderFieldsTooLarge = 431 100 | }; 101 | 102 | /** 103 | * Convenience constants for "server error" HTTP status codes. 104 | */ 105 | typedef NS_ENUM(NSInteger, GCDWebServerServerErrorHTTPStatusCode) { 106 | kGCDWebServerHTTPStatusCode_InternalServerError = 500, 107 | kGCDWebServerHTTPStatusCode_NotImplemented = 501, 108 | kGCDWebServerHTTPStatusCode_BadGateway = 502, 109 | kGCDWebServerHTTPStatusCode_ServiceUnavailable = 503, 110 | kGCDWebServerHTTPStatusCode_GatewayTimeout = 504, 111 | kGCDWebServerHTTPStatusCode_HTTPVersionNotSupported = 505, 112 | kGCDWebServerHTTPStatusCode_InsufficientStorage = 507, 113 | kGCDWebServerHTTPStatusCode_LoopDetected = 508, 114 | kGCDWebServerHTTPStatusCode_NotExtended = 510, 115 | kGCDWebServerHTTPStatusCode_NetworkAuthenticationRequired = 511 116 | }; 117 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Core/GCDWebServerPrivate.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import 29 | #import 30 | 31 | /** 32 | * All GCDWebServer headers. 33 | */ 34 | 35 | #import "GCDWebServerHTTPStatusCodes.h" 36 | #import "GCDWebServerFunctions.h" 37 | 38 | #import "GCDWebServer.h" 39 | #import "GCDWebServerConnection.h" 40 | 41 | #import "GCDWebServerDataRequest.h" 42 | #import "GCDWebServerFileRequest.h" 43 | #import "GCDWebServerMultiPartFormRequest.h" 44 | #import "GCDWebServerURLEncodedFormRequest.h" 45 | 46 | #import "GCDWebServerDataResponse.h" 47 | #import "GCDWebServerErrorResponse.h" 48 | #import "GCDWebServerFileResponse.h" 49 | #import "GCDWebServerStreamedResponse.h" 50 | 51 | /** 52 | * Check if a custom logging facility should be used instead. 53 | */ 54 | 55 | #if defined(__GCDWEBSERVER_LOGGING_HEADER__) 56 | 57 | #define __GCDWEBSERVER_LOGGING_FACILITY_CUSTOM__ 58 | 59 | #import __GCDWEBSERVER_LOGGING_HEADER__ 60 | 61 | /** 62 | * Automatically detect if XLFacility is available and if so use it as a 63 | * logging facility. 64 | */ 65 | 66 | #elif defined(__has_include) && __has_include("XLFacilityMacros.h") 67 | 68 | #define __GCDWEBSERVER_LOGGING_FACILITY_XLFACILITY__ 69 | 70 | #undef XLOG_TAG 71 | #define XLOG_TAG @"gcdwebserver.internal" 72 | 73 | #import "XLFacilityMacros.h" 74 | 75 | #define GWS_LOG_DEBUG(...) XLOG_DEBUG(__VA_ARGS__) 76 | #define GWS_LOG_VERBOSE(...) XLOG_VERBOSE(__VA_ARGS__) 77 | #define GWS_LOG_INFO(...) XLOG_INFO(__VA_ARGS__) 78 | #define GWS_LOG_WARNING(...) XLOG_WARNING(__VA_ARGS__) 79 | #define GWS_LOG_ERROR(...) XLOG_ERROR(__VA_ARGS__) 80 | #define GWS_LOG_EXCEPTION(__EXCEPTION__) XLOG_EXCEPTION(__EXCEPTION__) 81 | 82 | #define GWS_DCHECK(__CONDITION__) XLOG_DEBUG_CHECK(__CONDITION__) 83 | #define GWS_DNOT_REACHED() XLOG_DEBUG_UNREACHABLE() 84 | 85 | /** 86 | * Automatically detect if CocoaLumberJack is available and if so use 87 | * it as a logging facility. 88 | */ 89 | 90 | #elif defined(__has_include) && __has_include("CocoaLumberjack/CocoaLumberjack.h") 91 | 92 | #import 93 | 94 | #define __GCDWEBSERVER_LOGGING_FACILITY_COCOALUMBERJACK__ 95 | 96 | #undef LOG_LEVEL_DEF 97 | #define LOG_LEVEL_DEF GCDWebServerLogLevel 98 | extern DDLogLevel GCDWebServerLogLevel; 99 | 100 | #define GWS_LOG_DEBUG(...) DDLogDebug(__VA_ARGS__) 101 | #define GWS_LOG_VERBOSE(...) DDLogVerbose(__VA_ARGS__) 102 | #define GWS_LOG_INFO(...) DDLogInfo(__VA_ARGS__) 103 | #define GWS_LOG_WARNING(...) DDLogWarn(__VA_ARGS__) 104 | #define GWS_LOG_ERROR(...) DDLogError(__VA_ARGS__) 105 | #define GWS_LOG_EXCEPTION(__EXCEPTION__) DDLogError(@"%@", __EXCEPTION__) 106 | 107 | /** 108 | * If all of the above fail, then use GCDWebServer built-in 109 | * logging facility. 110 | */ 111 | 112 | #else 113 | 114 | #define __GCDWEBSERVER_LOGGING_FACILITY_BUILTIN__ 115 | 116 | typedef NS_ENUM(int, GCDWebServerLoggingLevel) { 117 | kGCDWebServerLoggingLevel_Debug = 0, 118 | kGCDWebServerLoggingLevel_Verbose, 119 | kGCDWebServerLoggingLevel_Info, 120 | kGCDWebServerLoggingLevel_Warning, 121 | kGCDWebServerLoggingLevel_Error, 122 | kGCDWebServerLoggingLevel_Exception 123 | }; 124 | 125 | extern GCDWebServerLoggingLevel GCDWebServerLogLevel; 126 | extern void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* format, ...) NS_FORMAT_FUNCTION(2, 3); 127 | 128 | #if DEBUG 129 | #define GWS_LOG_DEBUG(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Debug) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Debug, __VA_ARGS__); } while (0) 130 | #else 131 | #define GWS_LOG_DEBUG(...) 132 | #endif 133 | #define GWS_LOG_VERBOSE(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Verbose) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Verbose, __VA_ARGS__); } while (0) 134 | #define GWS_LOG_INFO(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Info) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Info, __VA_ARGS__); } while (0) 135 | #define GWS_LOG_WARNING(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Warning) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Warning, __VA_ARGS__); } while (0) 136 | #define GWS_LOG_ERROR(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Error) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Error, __VA_ARGS__); } while (0) 137 | #define GWS_LOG_EXCEPTION(__EXCEPTION__) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Exception) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Exception, @"%@", __EXCEPTION__); } while (0) 138 | 139 | #endif 140 | 141 | /** 142 | * Consistency check macros used when building Debug only. 143 | */ 144 | 145 | #if !defined(GWS_DCHECK) || !defined(GWS_DNOT_REACHED) 146 | 147 | #if DEBUG 148 | 149 | #define GWS_DCHECK(__CONDITION__) \ 150 | do { \ 151 | if (!(__CONDITION__)) { \ 152 | abort(); \ 153 | } \ 154 | } while (0) 155 | #define GWS_DNOT_REACHED() abort() 156 | 157 | #else 158 | 159 | #define GWS_DCHECK(__CONDITION__) 160 | #define GWS_DNOT_REACHED() 161 | 162 | #endif 163 | 164 | #endif 165 | 166 | /** 167 | * GCDWebServer internal constants and APIs. 168 | */ 169 | 170 | #define kGCDWebServerDefaultMimeType @"application/octet-stream" 171 | #define kGCDWebServerGCDQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 172 | #define kGCDWebServerErrorDomain @"GCDWebServerErrorDomain" 173 | 174 | static inline BOOL GCDWebServerIsValidByteRange(NSRange range) { 175 | return ((range.location != NSUIntegerMax) || (range.length > 0)); 176 | } 177 | 178 | static inline NSError* GCDWebServerMakePosixError(int code) { 179 | return [NSError errorWithDomain:NSPOSIXErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithUTF8String:strerror(code)]}]; 180 | } 181 | 182 | extern void GCDWebServerInitializeFunctions(); 183 | extern NSString* GCDWebServerNormalizeHeaderValue(NSString* value); 184 | extern NSString* GCDWebServerTruncateHeaderValue(NSString* value); 185 | extern NSString* GCDWebServerExtractHeaderValueParameter(NSString* header, NSString* attribute); 186 | extern NSStringEncoding GCDWebServerStringEncodingFromCharset(NSString* charset); 187 | extern BOOL GCDWebServerIsTextContentType(NSString* type); 188 | extern NSString* GCDWebServerDescribeData(NSData* data, NSString* contentType); 189 | extern NSString* GCDWebServerComputeMD5Digest(NSString* format, ...) NS_FORMAT_FUNCTION(1,2); 190 | extern NSString* GCDWebServerStringFromSockAddr(const struct sockaddr* addr, BOOL includeService); 191 | 192 | @interface GCDWebServerConnection () 193 | - (id)initWithServer:(GCDWebServer*)server localAddress:(NSData*)localAddress remoteAddress:(NSData*)remoteAddress socket:(CFSocketNativeHandle)socket; 194 | @end 195 | 196 | @interface GCDWebServer () 197 | @property(nonatomic, readonly) NSArray* handlers; 198 | @property(nonatomic, readonly) NSString* serverName; 199 | @property(nonatomic, readonly) NSString* authenticationRealm; 200 | @property(nonatomic, readonly) NSDictionary* authenticationBasicAccounts; 201 | @property(nonatomic, readonly) NSDictionary* authenticationDigestAccounts; 202 | @property(nonatomic, readonly) BOOL shouldAutomaticallyMapHEADToGET; 203 | - (void)willStartConnection:(GCDWebServerConnection*)connection; 204 | - (void)didEndConnection:(GCDWebServerConnection*)connection; 205 | @end 206 | 207 | @interface GCDWebServerHandler : NSObject 208 | @property(nonatomic, readonly) GCDWebServerMatchBlock matchBlock; 209 | @property(nonatomic, readonly) GCDWebServerAsyncProcessBlock asyncProcessBlock; 210 | @end 211 | 212 | @interface GCDWebServerRequest () 213 | @property(nonatomic, readonly) BOOL usesChunkedTransferEncoding; 214 | @property(nonatomic, readwrite) NSData* localAddressData; 215 | @property(nonatomic, readwrite) NSData* remoteAddressData; 216 | - (void)prepareForWriting; 217 | - (BOOL)performOpen:(NSError**)error; 218 | - (BOOL)performWriteData:(NSData*)data error:(NSError**)error; 219 | - (BOOL)performClose:(NSError**)error; 220 | - (void)setAttribute:(id)attribute forKey:(NSString*)key; 221 | @end 222 | 223 | @interface GCDWebServerResponse () 224 | @property(nonatomic, readonly) NSDictionary* additionalHeaders; 225 | @property(nonatomic, readonly) BOOL usesChunkedTransferEncoding; 226 | - (void)prepareForReading; 227 | - (BOOL)performOpen:(NSError**)error; 228 | - (void)performReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block; 229 | - (void)performClose; 230 | @end 231 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import 29 | 30 | /** 31 | * Attribute key to retrieve an NSArray containing NSStrings from a GCDWebServerRequest 32 | * with the contents of any regular expression captures done on the request path. 33 | * 34 | * @warning This attribute will only be set on the request if adding a handler using 35 | * -addHandlerForMethod:pathRegex:requestClass:processBlock:. 36 | */ 37 | extern NSString* const GCDWebServerRequestAttribute_RegexCaptures; 38 | 39 | /** 40 | * This protocol is used by the GCDWebServerConnection to communicate with 41 | * the GCDWebServerRequest and write the received HTTP body data. 42 | * 43 | * Note that multiple GCDWebServerBodyWriter objects can be chained together 44 | * internally e.g. to automatically decode gzip encoded content before 45 | * passing it on to the GCDWebServerRequest. 46 | * 47 | * @warning These methods can be called on any GCD thread. 48 | */ 49 | @protocol GCDWebServerBodyWriter 50 | 51 | /** 52 | * This method is called before any body data is received. 53 | * 54 | * It should return YES on success or NO on failure and set the "error" argument 55 | * which is guaranteed to be non-NULL. 56 | */ 57 | - (BOOL)open:(NSError**)error; 58 | 59 | /** 60 | * This method is called whenever body data has been received. 61 | * 62 | * It should return YES on success or NO on failure and set the "error" argument 63 | * which is guaranteed to be non-NULL. 64 | */ 65 | - (BOOL)writeData:(NSData*)data error:(NSError**)error; 66 | 67 | /** 68 | * This method is called after all body data has been received. 69 | * 70 | * It should return YES on success or NO on failure and set the "error" argument 71 | * which is guaranteed to be non-NULL. 72 | */ 73 | - (BOOL)close:(NSError**)error; 74 | 75 | @end 76 | 77 | /** 78 | * The GCDWebServerRequest class is instantiated by the GCDWebServerConnection 79 | * after the HTTP headers have been received. Each instance wraps a single HTTP 80 | * request. If a body is present, the methods from the GCDWebServerBodyWriter 81 | * protocol will be called by the GCDWebServerConnection to receive it. 82 | * 83 | * The default implementation of the GCDWebServerBodyWriter protocol on the class 84 | * simply ignores the body data. 85 | * 86 | * @warning GCDWebServerRequest instances can be created and used on any GCD thread. 87 | */ 88 | @interface GCDWebServerRequest : NSObject 89 | 90 | /** 91 | * Returns the HTTP method for the request. 92 | */ 93 | @property(nonatomic, readonly) NSString* method; 94 | 95 | /** 96 | * Returns the URL for the request. 97 | */ 98 | @property(nonatomic, readonly) NSURL* URL; 99 | 100 | /** 101 | * Returns the HTTP headers for the request. 102 | */ 103 | @property(nonatomic, readonly) NSDictionary* headers; 104 | 105 | /** 106 | * Returns the path component of the URL for the request. 107 | */ 108 | @property(nonatomic, readonly) NSString* path; 109 | 110 | /** 111 | * Returns the parsed and unescaped query component of the URL for the request. 112 | * 113 | * @warning This property will be nil if there is no query in the URL. 114 | */ 115 | @property(nonatomic, readonly) NSDictionary* query; 116 | 117 | /** 118 | * Returns the content type for the body of the request parsed from the 119 | * "Content-Type" header. 120 | * 121 | * This property will be nil if the request has no body or set to 122 | * "application/octet-stream" if a body is present but there was no 123 | * "Content-Type" header. 124 | */ 125 | @property(nonatomic, readonly) NSString* contentType; 126 | 127 | /** 128 | * Returns the content length for the body of the request parsed from the 129 | * "Content-Length" header. 130 | * 131 | * This property will be set to "NSUIntegerMax" if the request has no body or 132 | * if there is a body but no "Content-Length" header, typically because 133 | * chunked transfer encoding is used. 134 | */ 135 | @property(nonatomic, readonly) NSUInteger contentLength; 136 | 137 | /** 138 | * Returns the parsed "If-Modified-Since" header or nil if absent or malformed. 139 | */ 140 | @property(nonatomic, readonly) NSDate* ifModifiedSince; 141 | 142 | /** 143 | * Returns the parsed "If-None-Match" header or nil if absent or malformed. 144 | */ 145 | @property(nonatomic, readonly) NSString* ifNoneMatch; 146 | 147 | /** 148 | * Returns the parsed "Range" header or (NSUIntegerMax, 0) if absent or malformed. 149 | * The range will be set to (offset, length) if expressed from the beginning 150 | * of the entity body, or (NSUIntegerMax, length) if expressed from its end. 151 | */ 152 | @property(nonatomic, readonly) NSRange byteRange; 153 | 154 | /** 155 | * Returns YES if the client supports gzip content encoding according to the 156 | * "Accept-Encoding" header. 157 | */ 158 | @property(nonatomic, readonly) BOOL acceptsGzipContentEncoding; 159 | 160 | /** 161 | * Returns the address of the local peer (i.e. server) for the request 162 | * as a raw "struct sockaddr". 163 | */ 164 | @property(nonatomic, readonly) NSData* localAddressData; 165 | 166 | /** 167 | * Returns the address of the local peer (i.e. server) for the request 168 | * as a string. 169 | */ 170 | @property(nonatomic, readonly) NSString* localAddressString; 171 | 172 | /** 173 | * Returns the address of the remote peer (i.e. client) for the request 174 | * as a raw "struct sockaddr". 175 | */ 176 | @property(nonatomic, readonly) NSData* remoteAddressData; 177 | 178 | /** 179 | * Returns the address of the remote peer (i.e. client) for the request 180 | * as a string. 181 | */ 182 | @property(nonatomic, readonly) NSString* remoteAddressString; 183 | 184 | /** 185 | * This method is the designated initializer for the class. 186 | */ 187 | - (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query; 188 | 189 | /** 190 | * Convenience method that checks if the contentType property is defined. 191 | */ 192 | - (BOOL)hasBody; 193 | 194 | /** 195 | * Convenience method that checks if the byteRange property is defined. 196 | */ 197 | - (BOOL)hasByteRange; 198 | 199 | /** 200 | * Retrieves an attribute associated with this request using the given key. 201 | * 202 | * @return The attribute value for the key. 203 | */ 204 | - (id)attributeForKey:(NSString*)key; 205 | 206 | @end 207 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import 33 | 34 | #import "GCDWebServerPrivate.h" 35 | 36 | NSString* const GCDWebServerRequestAttribute_RegexCaptures = @"GCDWebServerRequestAttribute_RegexCaptures"; 37 | 38 | #define kZlibErrorDomain @"ZlibErrorDomain" 39 | #define kGZipInitialBufferSize (256 * 1024) 40 | 41 | @interface GCDWebServerBodyDecoder : NSObject 42 | - (id)initWithRequest:(GCDWebServerRequest*)request writer:(id)writer; 43 | @end 44 | 45 | @interface GCDWebServerGZipDecoder : GCDWebServerBodyDecoder 46 | @end 47 | 48 | @interface GCDWebServerBodyDecoder () { 49 | @private 50 | GCDWebServerRequest* __unsafe_unretained _request; 51 | id __unsafe_unretained _writer; 52 | } 53 | @end 54 | 55 | @implementation GCDWebServerBodyDecoder 56 | 57 | - (id)initWithRequest:(GCDWebServerRequest*)request writer:(id)writer { 58 | if ((self = [super init])) { 59 | _request = request; 60 | _writer = writer; 61 | } 62 | return self; 63 | } 64 | 65 | - (BOOL)open:(NSError**)error { 66 | return [_writer open:error]; 67 | } 68 | 69 | - (BOOL)writeData:(NSData*)data error:(NSError**)error { 70 | return [_writer writeData:data error:error]; 71 | } 72 | 73 | - (BOOL)close:(NSError**)error { 74 | return [_writer close:error]; 75 | } 76 | 77 | @end 78 | 79 | @interface GCDWebServerGZipDecoder () { 80 | @private 81 | z_stream _stream; 82 | BOOL _finished; 83 | } 84 | @end 85 | 86 | @implementation GCDWebServerGZipDecoder 87 | 88 | - (BOOL)open:(NSError**)error { 89 | int result = inflateInit2(&_stream, 15 + 16); 90 | if (result != Z_OK) { 91 | if (error) { 92 | *error = [NSError errorWithDomain:kZlibErrorDomain code:result userInfo:nil]; 93 | } 94 | return NO; 95 | } 96 | if (![super open:error]) { 97 | deflateEnd(&_stream); 98 | return NO; 99 | } 100 | return YES; 101 | } 102 | 103 | - (BOOL)writeData:(NSData*)data error:(NSError**)error { 104 | GWS_DCHECK(!_finished); 105 | _stream.next_in = (Bytef*)data.bytes; 106 | _stream.avail_in = (uInt)data.length; 107 | NSMutableData* decodedData = [[NSMutableData alloc] initWithLength:kGZipInitialBufferSize]; 108 | if (decodedData == nil) { 109 | GWS_DNOT_REACHED(); 110 | return NO; 111 | } 112 | NSUInteger length = 0; 113 | while (1) { 114 | NSUInteger maxLength = decodedData.length - length; 115 | _stream.next_out = (Bytef*)((char*)decodedData.mutableBytes + length); 116 | _stream.avail_out = (uInt)maxLength; 117 | int result = inflate(&_stream, Z_NO_FLUSH); 118 | if ((result != Z_OK) && (result != Z_STREAM_END)) { 119 | if (error) { 120 | *error = [NSError errorWithDomain:kZlibErrorDomain code:result userInfo:nil]; 121 | } 122 | return NO; 123 | } 124 | length += maxLength - _stream.avail_out; 125 | if (_stream.avail_out > 0) { 126 | if (result == Z_STREAM_END) { 127 | _finished = YES; 128 | } 129 | break; 130 | } 131 | decodedData.length = 2 * decodedData.length; // zlib has used all the output buffer so resize it and try again in case more data is available 132 | } 133 | decodedData.length = length; 134 | BOOL success = length ? [super writeData:decodedData error:error] : YES; // No need to call writer if we have no data yet 135 | return success; 136 | } 137 | 138 | - (BOOL)close:(NSError**)error { 139 | GWS_DCHECK(_finished); 140 | inflateEnd(&_stream); 141 | return [super close:error]; 142 | } 143 | 144 | @end 145 | 146 | @interface GCDWebServerRequest () { 147 | @private 148 | NSString* _method; 149 | NSURL* _url; 150 | NSDictionary* _headers; 151 | NSString* _path; 152 | NSDictionary* _query; 153 | NSString* _type; 154 | BOOL _chunked; 155 | NSUInteger _length; 156 | NSDate* _modifiedSince; 157 | NSString* _noneMatch; 158 | NSRange _range; 159 | BOOL _gzipAccepted; 160 | NSData* _localAddress; 161 | NSData* _remoteAddress; 162 | 163 | BOOL _opened; 164 | NSMutableArray* _decoders; 165 | NSMutableDictionary* _attributes; 166 | id __unsafe_unretained _writer; 167 | } 168 | @end 169 | 170 | @implementation GCDWebServerRequest : NSObject 171 | 172 | @synthesize method=_method, URL=_url, headers=_headers, path=_path, query=_query, contentType=_type, contentLength=_length, ifModifiedSince=_modifiedSince, ifNoneMatch=_noneMatch, 173 | byteRange=_range, acceptsGzipContentEncoding=_gzipAccepted, usesChunkedTransferEncoding=_chunked, localAddressData=_localAddress, remoteAddressData=_remoteAddress; 174 | 175 | - (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query { 176 | if ((self = [super init])) { 177 | _method = [method copy]; 178 | _url = url; 179 | _headers = headers; 180 | _path = [path copy]; 181 | _query = query; 182 | 183 | _type = GCDWebServerNormalizeHeaderValue([_headers objectForKey:@"Content-Type"]); 184 | _chunked = [GCDWebServerNormalizeHeaderValue([_headers objectForKey:@"Transfer-Encoding"]) isEqualToString:@"chunked"]; 185 | NSString* lengthHeader = [_headers objectForKey:@"Content-Length"]; 186 | if (lengthHeader) { 187 | NSInteger length = [lengthHeader integerValue]; 188 | if (_chunked || (length < 0)) { 189 | GWS_LOG_WARNING(@"Invalid 'Content-Length' header '%@' for '%@' request on \"%@\"", lengthHeader, _method, _url); 190 | GWS_DNOT_REACHED(); 191 | return nil; 192 | } 193 | _length = length; 194 | if (_type == nil) { 195 | _type = kGCDWebServerDefaultMimeType; 196 | } 197 | } else if (_chunked) { 198 | if (_type == nil) { 199 | _type = kGCDWebServerDefaultMimeType; 200 | } 201 | _length = NSUIntegerMax; 202 | } else { 203 | if (_type) { 204 | GWS_LOG_WARNING(@"Ignoring 'Content-Type' header for '%@' request on \"%@\"", _method, _url); 205 | _type = nil; // Content-Type without Content-Length or chunked-encoding doesn't make sense 206 | } 207 | _length = NSUIntegerMax; 208 | } 209 | 210 | NSString* modifiedHeader = [_headers objectForKey:@"If-Modified-Since"]; 211 | if (modifiedHeader) { 212 | _modifiedSince = [GCDWebServerParseRFC822(modifiedHeader) copy]; 213 | } 214 | _noneMatch = [_headers objectForKey:@"If-None-Match"]; 215 | 216 | _range = NSMakeRange(NSUIntegerMax, 0); 217 | NSString* rangeHeader = GCDWebServerNormalizeHeaderValue([_headers objectForKey:@"Range"]); 218 | if (rangeHeader) { 219 | if ([rangeHeader hasPrefix:@"bytes="]) { 220 | NSArray* components = [[rangeHeader substringFromIndex:6] componentsSeparatedByString:@","]; 221 | if (components.count == 1) { 222 | components = [[components firstObject] componentsSeparatedByString:@"-"]; 223 | if (components.count == 2) { 224 | NSString* startString = [components objectAtIndex:0]; 225 | NSInteger startValue = [startString integerValue]; 226 | NSString* endString = [components objectAtIndex:1]; 227 | NSInteger endValue = [endString integerValue]; 228 | if (startString.length && (startValue >= 0) && endString.length && (endValue >= startValue)) { // The second 500 bytes: "500-999" 229 | _range.location = startValue; 230 | _range.length = endValue - startValue + 1; 231 | } else if (startString.length && (startValue >= 0)) { // The bytes after 9500 bytes: "9500-" 232 | _range.location = startValue; 233 | _range.length = NSUIntegerMax; 234 | } else if (endString.length && (endValue > 0)) { // The final 500 bytes: "-500" 235 | _range.location = NSUIntegerMax; 236 | _range.length = endValue; 237 | } 238 | } 239 | } 240 | } 241 | if ((_range.location == NSUIntegerMax) && (_range.length == 0)) { // Ignore "Range" header if syntactically invalid 242 | GWS_LOG_WARNING(@"Failed to parse 'Range' header \"%@\" for url: %@", rangeHeader, url); 243 | } 244 | } 245 | 246 | if ([[_headers objectForKey:@"Accept-Encoding"] rangeOfString:@"gzip"].location != NSNotFound) { 247 | _gzipAccepted = YES; 248 | } 249 | 250 | _decoders = [[NSMutableArray alloc] init]; 251 | _attributes = [[NSMutableDictionary alloc] init]; 252 | } 253 | return self; 254 | } 255 | 256 | - (BOOL)hasBody { 257 | return _type ? YES : NO; 258 | } 259 | 260 | - (BOOL)hasByteRange { 261 | return GCDWebServerIsValidByteRange(_range); 262 | } 263 | 264 | - (id)attributeForKey:(NSString*)key { 265 | return [_attributes objectForKey:key]; 266 | } 267 | 268 | - (BOOL)open:(NSError**)error { 269 | return YES; 270 | } 271 | 272 | - (BOOL)writeData:(NSData*)data error:(NSError**)error { 273 | return YES; 274 | } 275 | 276 | - (BOOL)close:(NSError**)error { 277 | return YES; 278 | } 279 | 280 | - (void)prepareForWriting { 281 | _writer = self; 282 | if ([GCDWebServerNormalizeHeaderValue([self.headers objectForKey:@"Content-Encoding"]) isEqualToString:@"gzip"]) { 283 | GCDWebServerGZipDecoder* decoder = [[GCDWebServerGZipDecoder alloc] initWithRequest:self writer:_writer]; 284 | [_decoders addObject:decoder]; 285 | _writer = decoder; 286 | } 287 | } 288 | 289 | - (BOOL)performOpen:(NSError**)error { 290 | GWS_DCHECK(_type); 291 | GWS_DCHECK(_writer); 292 | if (_opened) { 293 | GWS_DNOT_REACHED(); 294 | return NO; 295 | } 296 | _opened = YES; 297 | return [_writer open:error]; 298 | } 299 | 300 | - (BOOL)performWriteData:(NSData*)data error:(NSError**)error { 301 | GWS_DCHECK(_opened); 302 | return [_writer writeData:data error:error]; 303 | } 304 | 305 | - (BOOL)performClose:(NSError**)error { 306 | GWS_DCHECK(_opened); 307 | return [_writer close:error]; 308 | } 309 | 310 | - (void)setAttribute:(id)attribute forKey:(NSString*)key { 311 | [_attributes setValue:attribute forKey:key]; 312 | } 313 | 314 | - (NSString*)localAddressString { 315 | return GCDWebServerStringFromSockAddr(_localAddress.bytes, YES); 316 | } 317 | 318 | - (NSString*)remoteAddressString { 319 | return GCDWebServerStringFromSockAddr(_remoteAddress.bytes, YES); 320 | } 321 | 322 | - (NSString*)description { 323 | NSMutableString* description = [NSMutableString stringWithFormat:@"%@ %@", _method, _path]; 324 | for (NSString* argument in [[_query allKeys] sortedArrayUsingSelector:@selector(compare:)]) { 325 | [description appendFormat:@"\n %@ = %@", argument, [_query objectForKey:argument]]; 326 | } 327 | [description appendString:@"\n"]; 328 | for (NSString* header in [[_headers allKeys] sortedArrayUsingSelector:@selector(compare:)]) { 329 | [description appendFormat:@"\n%@: %@", header, [_headers objectForKey:header]]; 330 | } 331 | return description; 332 | } 333 | 334 | @end 335 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Core/GCDWebServerResponse.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import 29 | 30 | /** 31 | * The GCDWebServerBodyReaderCompletionBlock is passed by GCDWebServer to the 32 | * GCDWebServerBodyReader object when reading data from it asynchronously. 33 | */ 34 | typedef void (^GCDWebServerBodyReaderCompletionBlock)(NSData* data, NSError* error); 35 | 36 | /** 37 | * This protocol is used by the GCDWebServerConnection to communicate with 38 | * the GCDWebServerResponse and read the HTTP body data to send. 39 | * 40 | * Note that multiple GCDWebServerBodyReader objects can be chained together 41 | * internally e.g. to automatically apply gzip encoding to the content before 42 | * passing it on to the GCDWebServerResponse. 43 | * 44 | * @warning These methods can be called on any GCD thread. 45 | */ 46 | @protocol GCDWebServerBodyReader 47 | 48 | @required 49 | 50 | /** 51 | * This method is called before any body data is sent. 52 | * 53 | * It should return YES on success or NO on failure and set the "error" argument 54 | * which is guaranteed to be non-NULL. 55 | */ 56 | - (BOOL)open:(NSError**)error; 57 | 58 | /** 59 | * This method is called whenever body data is sent. 60 | * 61 | * It should return a non-empty NSData if there is body data available, 62 | * or an empty NSData there is no more body data, or nil on error and set 63 | * the "error" argument which is guaranteed to be non-NULL. 64 | */ 65 | - (NSData*)readData:(NSError**)error; 66 | 67 | /** 68 | * This method is called after all body data has been sent. 69 | */ 70 | - (void)close; 71 | 72 | @optional 73 | 74 | /** 75 | * If this method is implemented, it will be preferred over -readData:. 76 | * 77 | * It must call the passed block when data is available, passing a non-empty 78 | * NSData if there is body data available, or an empty NSData there is no more 79 | * body data, or nil on error and pass an NSError along. 80 | */ 81 | - (void)asyncReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block; 82 | 83 | @end 84 | 85 | /** 86 | * The GCDWebServerResponse class is used to wrap a single HTTP response. 87 | * It is instantiated by the handler of the GCDWebServer that handled the request. 88 | * If a body is present, the methods from the GCDWebServerBodyReader protocol 89 | * will be called by the GCDWebServerConnection to send it. 90 | * 91 | * The default implementation of the GCDWebServerBodyReader protocol 92 | * on the class simply returns an empty body. 93 | * 94 | * @warning GCDWebServerResponse instances can be created and used on any GCD thread. 95 | */ 96 | @interface GCDWebServerResponse : NSObject 97 | 98 | /** 99 | * Sets the content type for the body of the response. 100 | * 101 | * The default value is nil i.e. the response has no body. 102 | * 103 | * @warning This property must be set if a body is present. 104 | */ 105 | @property(nonatomic, copy) NSString* contentType; 106 | 107 | /** 108 | * Sets the content length for the body of the response. If a body is present 109 | * but this property is set to "NSUIntegerMax", this means the length of the body 110 | * cannot be known ahead of time. Chunked transfer encoding will be 111 | * automatically enabled by the GCDWebServerConnection to comply with HTTP/1.1 112 | * specifications. 113 | * 114 | * The default value is "NSUIntegerMax" i.e. the response has no body or its length 115 | * is undefined. 116 | */ 117 | @property(nonatomic) NSUInteger contentLength; 118 | 119 | /** 120 | * Sets the HTTP status code for the response. 121 | * 122 | * The default value is 200 i.e. "OK". 123 | */ 124 | @property(nonatomic) NSInteger statusCode; 125 | 126 | /** 127 | * Sets the caching hint for the response using the "Cache-Control" header. 128 | * This value is expressed in seconds. 129 | * 130 | * The default value is 0 i.e. "no-cache". 131 | */ 132 | @property(nonatomic) NSUInteger cacheControlMaxAge; 133 | 134 | /** 135 | * Sets the last modified date for the response using the "Last-Modified" header. 136 | * 137 | * The default value is nil. 138 | */ 139 | @property(nonatomic, retain) NSDate* lastModifiedDate; 140 | 141 | /** 142 | * Sets the ETag for the response using the "ETag" header. 143 | * 144 | * The default value is nil. 145 | */ 146 | @property(nonatomic, copy) NSString* eTag; 147 | 148 | /** 149 | * Enables gzip encoding for the response body. 150 | * 151 | * The default value is NO. 152 | * 153 | * @warning Enabling gzip encoding will remove any "Content-Length" header 154 | * since the length of the body is not known anymore. The client will still 155 | * be able to determine the body length when connection is closed per 156 | * HTTP/1.1 specifications. 157 | */ 158 | @property(nonatomic, getter=isGZipContentEncodingEnabled) BOOL gzipContentEncodingEnabled; 159 | 160 | /** 161 | * Creates an empty response. 162 | */ 163 | + (instancetype)response; 164 | 165 | /** 166 | * This method is the designated initializer for the class. 167 | */ 168 | - (instancetype)init; 169 | 170 | /** 171 | * Sets an additional HTTP header on the response. 172 | * Pass a nil value to remove an additional header. 173 | * 174 | * @warning Do not attempt to override the primary headers used 175 | * by GCDWebServerResponse like "Content-Type", "ETag", etc... 176 | */ 177 | - (void)setValue:(NSString*)value forAdditionalHeader:(NSString*)header; 178 | 179 | /** 180 | * Convenience method that checks if the contentType property is defined. 181 | */ 182 | - (BOOL)hasBody; 183 | 184 | @end 185 | 186 | @interface GCDWebServerResponse (Extensions) 187 | 188 | /** 189 | * Creates a empty response with a specific HTTP status code. 190 | */ 191 | + (instancetype)responseWithStatusCode:(NSInteger)statusCode; 192 | 193 | /** 194 | * Creates an HTTP redirect response to a new URL. 195 | */ 196 | + (instancetype)responseWithRedirect:(NSURL*)location permanent:(BOOL)permanent; 197 | 198 | /** 199 | * Initializes an empty response with a specific HTTP status code. 200 | */ 201 | - (instancetype)initWithStatusCode:(NSInteger)statusCode; 202 | 203 | /** 204 | * Initializes an HTTP redirect response to a new URL. 205 | */ 206 | - (instancetype)initWithRedirect:(NSURL*)location permanent:(BOOL)permanent; 207 | 208 | @end 209 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Core/GCDWebServerResponse.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import 33 | 34 | #import "GCDWebServerPrivate.h" 35 | 36 | #define kZlibErrorDomain @"ZlibErrorDomain" 37 | #define kGZipInitialBufferSize (256 * 1024) 38 | 39 | @interface GCDWebServerBodyEncoder : NSObject 40 | - (id)initWithResponse:(GCDWebServerResponse*)response reader:(id)reader; 41 | @end 42 | 43 | @interface GCDWebServerGZipEncoder : GCDWebServerBodyEncoder 44 | @end 45 | 46 | @interface GCDWebServerBodyEncoder () { 47 | @private 48 | GCDWebServerResponse* __unsafe_unretained _response; 49 | id __unsafe_unretained _reader; 50 | } 51 | @end 52 | 53 | @implementation GCDWebServerBodyEncoder 54 | 55 | - (id)initWithResponse:(GCDWebServerResponse*)response reader:(id)reader { 56 | if ((self = [super init])) { 57 | _response = response; 58 | _reader = reader; 59 | } 60 | return self; 61 | } 62 | 63 | - (BOOL)open:(NSError**)error { 64 | return [_reader open:error]; 65 | } 66 | 67 | - (NSData*)readData:(NSError**)error { 68 | return [_reader readData:error]; 69 | } 70 | 71 | - (void)close { 72 | [_reader close]; 73 | } 74 | 75 | @end 76 | 77 | @interface GCDWebServerGZipEncoder () { 78 | @private 79 | z_stream _stream; 80 | BOOL _finished; 81 | } 82 | @end 83 | 84 | @implementation GCDWebServerGZipEncoder 85 | 86 | - (id)initWithResponse:(GCDWebServerResponse*)response reader:(id)reader { 87 | if ((self = [super initWithResponse:response reader:reader])) { 88 | response.contentLength = NSUIntegerMax; // Make sure "Content-Length" header is not set since we don't know it 89 | [response setValue:@"gzip" forAdditionalHeader:@"Content-Encoding"]; 90 | } 91 | return self; 92 | } 93 | 94 | - (BOOL)open:(NSError**)error { 95 | int result = deflateInit2(&_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY); 96 | if (result != Z_OK) { 97 | if (error) { 98 | *error = [NSError errorWithDomain:kZlibErrorDomain code:result userInfo:nil]; 99 | } 100 | return NO; 101 | } 102 | if (![super open:error]) { 103 | deflateEnd(&_stream); 104 | return NO; 105 | } 106 | return YES; 107 | } 108 | 109 | - (NSData*)readData:(NSError**)error { 110 | NSMutableData* encodedData; 111 | if (_finished) { 112 | encodedData = [[NSMutableData alloc] init]; 113 | } else { 114 | encodedData = [[NSMutableData alloc] initWithLength:kGZipInitialBufferSize]; 115 | if (encodedData == nil) { 116 | GWS_DNOT_REACHED(); 117 | return nil; 118 | } 119 | NSUInteger length = 0; 120 | do { 121 | NSData* data = [super readData:error]; 122 | if (data == nil) { 123 | return nil; 124 | } 125 | _stream.next_in = (Bytef*)data.bytes; 126 | _stream.avail_in = (uInt)data.length; 127 | while (1) { 128 | NSUInteger maxLength = encodedData.length - length; 129 | _stream.next_out = (Bytef*)((char*)encodedData.mutableBytes + length); 130 | _stream.avail_out = (uInt)maxLength; 131 | int result = deflate(&_stream, data.length ? Z_NO_FLUSH : Z_FINISH); 132 | if (result == Z_STREAM_END) { 133 | _finished = YES; 134 | } else if (result != Z_OK) { 135 | if (error) { 136 | *error = [NSError errorWithDomain:kZlibErrorDomain code:result userInfo:nil]; 137 | } 138 | return nil; 139 | } 140 | length += maxLength - _stream.avail_out; 141 | if (_stream.avail_out > 0) { 142 | break; 143 | } 144 | encodedData.length = 2 * encodedData.length; // zlib has used all the output buffer so resize it and try again in case more data is available 145 | } 146 | GWS_DCHECK(_stream.avail_in == 0); 147 | } while (length == 0); // Make sure we don't return an empty NSData if not in finished state 148 | encodedData.length = length; 149 | } 150 | return encodedData; 151 | } 152 | 153 | - (void)close { 154 | deflateEnd(&_stream); 155 | [super close]; 156 | } 157 | 158 | @end 159 | 160 | @interface GCDWebServerResponse () { 161 | @private 162 | NSString* _type; 163 | NSUInteger _length; 164 | NSInteger _status; 165 | NSUInteger _maxAge; 166 | NSDate* _lastModified; 167 | NSString* _eTag; 168 | NSMutableDictionary* _headers; 169 | BOOL _chunked; 170 | BOOL _gzipped; 171 | 172 | BOOL _opened; 173 | NSMutableArray* _encoders; 174 | id __unsafe_unretained _reader; 175 | } 176 | @end 177 | 178 | @implementation GCDWebServerResponse 179 | 180 | @synthesize contentType=_type, contentLength=_length, statusCode=_status, cacheControlMaxAge=_maxAge, lastModifiedDate=_lastModified, eTag=_eTag, 181 | gzipContentEncodingEnabled=_gzipped, additionalHeaders=_headers; 182 | 183 | + (instancetype)response { 184 | return [[[self class] alloc] init]; 185 | } 186 | 187 | - (instancetype)init { 188 | if ((self = [super init])) { 189 | _type = nil; 190 | _length = NSUIntegerMax; 191 | _status = kGCDWebServerHTTPStatusCode_OK; 192 | _maxAge = 0; 193 | _headers = [[NSMutableDictionary alloc] init]; 194 | _encoders = [[NSMutableArray alloc] init]; 195 | } 196 | return self; 197 | } 198 | 199 | - (void)setValue:(NSString*)value forAdditionalHeader:(NSString*)header { 200 | [_headers setValue:value forKey:header]; 201 | } 202 | 203 | - (BOOL)hasBody { 204 | return _type ? YES : NO; 205 | } 206 | 207 | - (BOOL)usesChunkedTransferEncoding { 208 | return (_type != nil) && (_length == NSUIntegerMax); 209 | } 210 | 211 | - (BOOL)open:(NSError**)error { 212 | return YES; 213 | } 214 | 215 | - (NSData*)readData:(NSError**)error { 216 | return [NSData data]; 217 | } 218 | 219 | - (void)close { 220 | ; 221 | } 222 | 223 | - (void)prepareForReading { 224 | _reader = self; 225 | if (_gzipped) { 226 | GCDWebServerGZipEncoder* encoder = [[GCDWebServerGZipEncoder alloc] initWithResponse:self reader:_reader]; 227 | [_encoders addObject:encoder]; 228 | _reader = encoder; 229 | } 230 | } 231 | 232 | - (BOOL)performOpen:(NSError**)error { 233 | GWS_DCHECK(_type); 234 | GWS_DCHECK(_reader); 235 | if (_opened) { 236 | GWS_DNOT_REACHED(); 237 | return NO; 238 | } 239 | _opened = YES; 240 | return [_reader open:error]; 241 | } 242 | 243 | - (void)performReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block { 244 | if ([_reader respondsToSelector:@selector(asyncReadDataWithCompletion:)]) { 245 | [_reader asyncReadDataWithCompletion:[block copy]]; 246 | } else { 247 | NSError* error = nil; 248 | NSData* data = [_reader readData:&error]; 249 | block(data, error); 250 | } 251 | } 252 | 253 | - (void)performClose { 254 | GWS_DCHECK(_opened); 255 | [_reader close]; 256 | } 257 | 258 | - (NSString*)description { 259 | NSMutableString* description = [NSMutableString stringWithFormat:@"Status Code = %i", (int)_status]; 260 | if (_type) { 261 | [description appendFormat:@"\nContent Type = %@", _type]; 262 | } 263 | if (_length != NSUIntegerMax) { 264 | [description appendFormat:@"\nContent Length = %lu", (unsigned long)_length]; 265 | } 266 | [description appendFormat:@"\nCache Control Max Age = %lu", (unsigned long)_maxAge]; 267 | if (_lastModified) { 268 | [description appendFormat:@"\nLast Modified Date = %@", _lastModified]; 269 | } 270 | if (_eTag) { 271 | [description appendFormat:@"\nETag = %@", _eTag]; 272 | } 273 | if (_headers.count) { 274 | [description appendString:@"\n"]; 275 | for (NSString* header in [[_headers allKeys] sortedArrayUsingSelector:@selector(compare:)]) { 276 | [description appendFormat:@"\n%@: %@", header, [_headers objectForKey:header]]; 277 | } 278 | } 279 | return description; 280 | } 281 | 282 | @end 283 | 284 | @implementation GCDWebServerResponse (Extensions) 285 | 286 | + (instancetype)responseWithStatusCode:(NSInteger)statusCode { 287 | return [[self alloc] initWithStatusCode:statusCode]; 288 | } 289 | 290 | + (instancetype)responseWithRedirect:(NSURL*)location permanent:(BOOL)permanent { 291 | return [[self alloc] initWithRedirect:location permanent:permanent]; 292 | } 293 | 294 | - (instancetype)initWithStatusCode:(NSInteger)statusCode { 295 | if ((self = [self init])) { 296 | self.statusCode = statusCode; 297 | } 298 | return self; 299 | } 300 | 301 | - (instancetype)initWithRedirect:(NSURL*)location permanent:(BOOL)permanent { 302 | if ((self = [self init])) { 303 | self.statusCode = permanent ? kGCDWebServerHTTPStatusCode_MovedPermanently : kGCDWebServerHTTPStatusCode_TemporaryRedirect; 304 | [self setValue:[location absoluteString] forAdditionalHeader:@"Location"]; 305 | } 306 | return self; 307 | } 308 | 309 | @end 310 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Requests/GCDWebServerDataRequest.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerRequest.h" 29 | 30 | /** 31 | * The GCDWebServerDataRequest subclass of GCDWebServerRequest stores the body 32 | * of the HTTP request in memory. 33 | */ 34 | @interface GCDWebServerDataRequest : GCDWebServerRequest 35 | 36 | /** 37 | * Returns the data for the request body. 38 | */ 39 | @property(nonatomic, readonly) NSData* data; 40 | 41 | @end 42 | 43 | @interface GCDWebServerDataRequest (Extensions) 44 | 45 | /** 46 | * Returns the data for the request body interpreted as text. If the content 47 | * type of the body is not a text one, or if an error occurs, nil is returned. 48 | * 49 | * The text encoding used to interpret the data is extracted from the 50 | * "Content-Type" header or defaults to UTF-8. 51 | */ 52 | @property(nonatomic, readonly) NSString* text; 53 | 54 | /** 55 | * Returns the data for the request body interpreted as a JSON object. If the 56 | * content type of the body is not JSON, or if an error occurs, nil is returned. 57 | */ 58 | @property(nonatomic, readonly) id jsonObject; 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Requests/GCDWebServerDataRequest.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import "GCDWebServerPrivate.h" 33 | 34 | @interface GCDWebServerDataRequest () { 35 | @private 36 | NSMutableData* _data; 37 | 38 | NSString* _text; 39 | id _jsonObject; 40 | } 41 | @end 42 | 43 | @implementation GCDWebServerDataRequest 44 | 45 | @synthesize data=_data; 46 | 47 | - (BOOL)open:(NSError**)error { 48 | if (self.contentLength != NSUIntegerMax) { 49 | _data = [[NSMutableData alloc] initWithCapacity:self.contentLength]; 50 | } else { 51 | _data = [[NSMutableData alloc] init]; 52 | } 53 | if (_data == nil) { 54 | if (error) { 55 | *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Failed allocating memory"}]; 56 | } 57 | return NO; 58 | } 59 | return YES; 60 | } 61 | 62 | - (BOOL)writeData:(NSData*)data error:(NSError**)error { 63 | [_data appendData:data]; 64 | return YES; 65 | } 66 | 67 | - (BOOL)close:(NSError**)error { 68 | return YES; 69 | } 70 | 71 | - (NSString*)description { 72 | NSMutableString* description = [NSMutableString stringWithString:[super description]]; 73 | if (_data) { 74 | [description appendString:@"\n\n"]; 75 | [description appendString:GCDWebServerDescribeData(_data, self.contentType)]; 76 | } 77 | return description; 78 | } 79 | 80 | @end 81 | 82 | @implementation GCDWebServerDataRequest (Extensions) 83 | 84 | - (NSString*)text { 85 | if (_text == nil) { 86 | if ([self.contentType hasPrefix:@"text/"]) { 87 | NSString* charset = GCDWebServerExtractHeaderValueParameter(self.contentType, @"charset"); 88 | _text = [[NSString alloc] initWithData:self.data encoding:GCDWebServerStringEncodingFromCharset(charset)]; 89 | } else { 90 | GWS_DNOT_REACHED(); 91 | } 92 | } 93 | return _text; 94 | } 95 | 96 | - (id)jsonObject { 97 | if (_jsonObject == nil) { 98 | NSString* mimeType = GCDWebServerTruncateHeaderValue(self.contentType); 99 | if ([mimeType isEqualToString:@"application/json"] || [mimeType isEqualToString:@"text/json"] || [mimeType isEqualToString:@"text/javascript"]) { 100 | _jsonObject = [NSJSONSerialization JSONObjectWithData:_data options:0 error:NULL]; 101 | } else { 102 | GWS_DNOT_REACHED(); 103 | } 104 | } 105 | return _jsonObject; 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Requests/GCDWebServerFileRequest.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerRequest.h" 29 | 30 | /** 31 | * The GCDWebServerFileRequest subclass of GCDWebServerRequest stores the body 32 | * of the HTTP request to a file on disk. 33 | */ 34 | @interface GCDWebServerFileRequest : GCDWebServerRequest 35 | 36 | /** 37 | * Returns the path to the temporary file containing the request body. 38 | * 39 | * @warning This temporary file will be automatically deleted when the 40 | * GCDWebServerFileRequest is deallocated. If you want to preserve this file, 41 | * you must move it to a different location beforehand. 42 | */ 43 | @property(nonatomic, readonly) NSString* temporaryPath; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Requests/GCDWebServerFileRequest.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import "GCDWebServerPrivate.h" 33 | 34 | @interface GCDWebServerFileRequest () { 35 | @private 36 | NSString* _temporaryPath; 37 | int _file; 38 | } 39 | @end 40 | 41 | @implementation GCDWebServerFileRequest 42 | 43 | @synthesize temporaryPath=_temporaryPath; 44 | 45 | - (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query { 46 | if ((self = [super initWithMethod:method url:url headers:headers path:path query:query])) { 47 | _temporaryPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]; 48 | } 49 | return self; 50 | } 51 | 52 | - (void)dealloc { 53 | unlink([_temporaryPath fileSystemRepresentation]); 54 | } 55 | 56 | - (BOOL)open:(NSError**)error { 57 | _file = open([_temporaryPath fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 58 | if (_file <= 0) { 59 | if (error) { 60 | *error = GCDWebServerMakePosixError(errno); 61 | } 62 | return NO; 63 | } 64 | return YES; 65 | } 66 | 67 | - (BOOL)writeData:(NSData*)data error:(NSError**)error { 68 | if (write(_file, data.bytes, data.length) != (ssize_t)data.length) { 69 | if (error) { 70 | *error = GCDWebServerMakePosixError(errno); 71 | } 72 | return NO; 73 | } 74 | return YES; 75 | } 76 | 77 | - (BOOL)close:(NSError**)error { 78 | if (close(_file) < 0) { 79 | if (error) { 80 | *error = GCDWebServerMakePosixError(errno); 81 | } 82 | return NO; 83 | } 84 | #ifdef __GCDWEBSERVER_ENABLE_TESTING__ 85 | NSString* creationDateHeader = [self.headers objectForKey:@"X-GCDWebServer-CreationDate"]; 86 | if (creationDateHeader) { 87 | NSDate* date = GCDWebServerParseISO8601(creationDateHeader); 88 | if (!date || ![[NSFileManager defaultManager] setAttributes:@{NSFileCreationDate: date} ofItemAtPath:_temporaryPath error:error]) { 89 | return NO; 90 | } 91 | } 92 | NSString* modifiedDateHeader = [self.headers objectForKey:@"X-GCDWebServer-ModifiedDate"]; 93 | if (modifiedDateHeader) { 94 | NSDate* date = GCDWebServerParseRFC822(modifiedDateHeader); 95 | if (!date || ![[NSFileManager defaultManager] setAttributes:@{NSFileModificationDate: date} ofItemAtPath:_temporaryPath error:error]) { 96 | return NO; 97 | } 98 | } 99 | #endif 100 | return YES; 101 | } 102 | 103 | - (NSString*)description { 104 | NSMutableString* description = [NSMutableString stringWithString:[super description]]; 105 | [description appendFormat:@"\n\n{%@}", _temporaryPath]; 106 | return description; 107 | } 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerRequest.h" 29 | 30 | /** 31 | * The GCDWebServerMultiPart class is an abstract class that wraps the content 32 | * of a part. 33 | */ 34 | @interface GCDWebServerMultiPart : NSObject 35 | 36 | /** 37 | * Returns the control name retrieved from the part headers. 38 | */ 39 | @property(nonatomic, readonly) NSString* controlName; 40 | 41 | /** 42 | * Returns the content type retrieved from the part headers or "text/plain" 43 | * if not available (per HTTP specifications). 44 | */ 45 | @property(nonatomic, readonly) NSString* contentType; 46 | 47 | /** 48 | * Returns the MIME type component of the content type for the part. 49 | */ 50 | @property(nonatomic, readonly) NSString* mimeType; 51 | 52 | @end 53 | 54 | /** 55 | * The GCDWebServerMultiPartArgument subclass of GCDWebServerMultiPart wraps 56 | * the content of a part as data in memory. 57 | */ 58 | @interface GCDWebServerMultiPartArgument : GCDWebServerMultiPart 59 | 60 | /** 61 | * Returns the data for the part. 62 | */ 63 | @property(nonatomic, readonly) NSData* data; 64 | 65 | /** 66 | * Returns the data for the part interpreted as text. If the content 67 | * type of the part is not a text one, or if an error occurs, nil is returned. 68 | * 69 | * The text encoding used to interpret the data is extracted from the 70 | * "Content-Type" header or defaults to UTF-8. 71 | */ 72 | @property(nonatomic, readonly) NSString* string; 73 | 74 | @end 75 | 76 | /** 77 | * The GCDWebServerMultiPartFile subclass of GCDWebServerMultiPart wraps 78 | * the content of a part as a file on disk. 79 | */ 80 | @interface GCDWebServerMultiPartFile : GCDWebServerMultiPart 81 | 82 | /** 83 | * Returns the file name retrieved from the part headers. 84 | */ 85 | @property(nonatomic, readonly) NSString* fileName; 86 | 87 | /** 88 | * Returns the path to the temporary file containing the part data. 89 | * 90 | * @warning This temporary file will be automatically deleted when the 91 | * GCDWebServerMultiPartFile is deallocated. If you want to preserve this file, 92 | * you must move it to a different location beforehand. 93 | */ 94 | @property(nonatomic, readonly) NSString* temporaryPath; 95 | 96 | @end 97 | 98 | /** 99 | * The GCDWebServerMultiPartFormRequest subclass of GCDWebServerRequest 100 | * parses the body of the HTTP request as a multipart encoded form. 101 | */ 102 | @interface GCDWebServerMultiPartFormRequest : GCDWebServerRequest 103 | 104 | /** 105 | * Returns the argument parts from the multipart encoded form as 106 | * name / GCDWebServerMultiPartArgument pairs. 107 | */ 108 | @property(nonatomic, readonly) NSArray* arguments; 109 | 110 | /** 111 | * Returns the files parts from the multipart encoded form as 112 | * name / GCDWebServerMultiPartFile pairs. 113 | */ 114 | @property(nonatomic, readonly) NSArray* files; 115 | 116 | /** 117 | * Returns the MIME type for multipart encoded forms 118 | * i.e. "multipart/form-data". 119 | */ 120 | + (NSString*)mimeType; 121 | 122 | /** 123 | * Returns the first argument for a given control name or nil if not found. 124 | */ 125 | - (GCDWebServerMultiPartArgument*)firstArgumentForControlName:(NSString*)name; 126 | 127 | /** 128 | * Returns the first file for a given control name or nil if not found. 129 | */ 130 | - (GCDWebServerMultiPartFile*)firstFileForControlName:(NSString*)name; 131 | 132 | @end 133 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import "GCDWebServerPrivate.h" 33 | 34 | #define kMultiPartBufferSize (256 * 1024) 35 | 36 | typedef enum { 37 | kParserState_Undefined = 0, 38 | kParserState_Start, 39 | kParserState_Headers, 40 | kParserState_Content, 41 | kParserState_End 42 | } ParserState; 43 | 44 | @interface GCDWebServerMIMEStreamParser : NSObject 45 | - (id)initWithBoundary:(NSString*)boundary defaultControlName:(NSString*)name arguments:(NSMutableArray*)arguments files:(NSMutableArray*)files; 46 | - (BOOL)appendBytes:(const void*)bytes length:(NSUInteger)length; 47 | - (BOOL)isAtEnd; 48 | @end 49 | 50 | static NSData* _newlineData = nil; 51 | static NSData* _newlinesData = nil; 52 | static NSData* _dashNewlineData = nil; 53 | 54 | @interface GCDWebServerMultiPart () { 55 | @private 56 | NSString* _controlName; 57 | NSString* _contentType; 58 | NSString* _mimeType; 59 | } 60 | @end 61 | 62 | @implementation GCDWebServerMultiPart 63 | 64 | @synthesize controlName=_controlName, contentType=_contentType, mimeType=_mimeType; 65 | 66 | - (id)initWithControlName:(NSString*)name contentType:(NSString*)type { 67 | if ((self = [super init])) { 68 | _controlName = [name copy]; 69 | _contentType = [type copy]; 70 | _mimeType = GCDWebServerTruncateHeaderValue(_contentType); 71 | } 72 | return self; 73 | } 74 | 75 | @end 76 | 77 | @interface GCDWebServerMultiPartArgument () { 78 | @private 79 | NSData* _data; 80 | NSString* _string; 81 | } 82 | @end 83 | 84 | @implementation GCDWebServerMultiPartArgument 85 | 86 | @synthesize data=_data, string=_string; 87 | 88 | - (id)initWithControlName:(NSString*)name contentType:(NSString*)type data:(NSData*)data { 89 | if ((self = [super initWithControlName:name contentType:type])) { 90 | _data = data; 91 | 92 | if ([self.contentType hasPrefix:@"text/"]) { 93 | NSString* charset = GCDWebServerExtractHeaderValueParameter(self.contentType, @"charset"); 94 | _string = [[NSString alloc] initWithData:_data encoding:GCDWebServerStringEncodingFromCharset(charset)]; 95 | } 96 | } 97 | return self; 98 | } 99 | 100 | - (NSString*)description { 101 | return [NSString stringWithFormat:@"<%@ | '%@' | %lu bytes>", [self class], self.mimeType, (unsigned long)_data.length]; 102 | } 103 | 104 | @end 105 | 106 | @interface GCDWebServerMultiPartFile () { 107 | @private 108 | NSString* _fileName; 109 | NSString* _temporaryPath; 110 | } 111 | @end 112 | 113 | @implementation GCDWebServerMultiPartFile 114 | 115 | @synthesize fileName=_fileName, temporaryPath=_temporaryPath; 116 | 117 | - (id)initWithControlName:(NSString*)name contentType:(NSString*)type fileName:(NSString*)fileName temporaryPath:(NSString*)temporaryPath { 118 | if ((self = [super initWithControlName:name contentType:type])) { 119 | _fileName = [fileName copy]; 120 | _temporaryPath = [temporaryPath copy]; 121 | } 122 | return self; 123 | } 124 | 125 | - (void)dealloc { 126 | unlink([_temporaryPath fileSystemRepresentation]); 127 | } 128 | 129 | - (NSString*)description { 130 | return [NSString stringWithFormat:@"<%@ | '%@' | '%@>'", [self class], self.mimeType, _fileName]; 131 | } 132 | 133 | @end 134 | 135 | @interface GCDWebServerMIMEStreamParser () { 136 | @private 137 | NSData* _boundary; 138 | NSString* _defaultcontrolName; 139 | ParserState _state; 140 | NSMutableData* _data; 141 | NSMutableArray* _arguments; 142 | NSMutableArray* _files; 143 | 144 | NSString* _controlName; 145 | NSString* _fileName; 146 | NSString* _contentType; 147 | NSString* _tmpPath; 148 | int _tmpFile; 149 | GCDWebServerMIMEStreamParser* _subParser; 150 | } 151 | @end 152 | 153 | @implementation GCDWebServerMIMEStreamParser 154 | 155 | + (void)initialize { 156 | if (_newlineData == nil) { 157 | _newlineData = [[NSData alloc] initWithBytes:"\r\n" length:2]; 158 | GWS_DCHECK(_newlineData); 159 | } 160 | if (_newlinesData == nil) { 161 | _newlinesData = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4]; 162 | GWS_DCHECK(_newlinesData); 163 | } 164 | if (_dashNewlineData == nil) { 165 | _dashNewlineData = [[NSData alloc] initWithBytes:"--\r\n" length:4]; 166 | GWS_DCHECK(_dashNewlineData); 167 | } 168 | } 169 | 170 | - (id)initWithBoundary:(NSString*)boundary defaultControlName:(NSString*)name arguments:(NSMutableArray*)arguments files:(NSMutableArray*)files { 171 | NSData* data = boundary.length ? [[NSString stringWithFormat:@"--%@", boundary] dataUsingEncoding:NSASCIIStringEncoding] : nil; 172 | if (data == nil) { 173 | GWS_DNOT_REACHED(); 174 | return nil; 175 | } 176 | if ((self = [super init])) { 177 | _boundary = data; 178 | _defaultcontrolName = name; 179 | _arguments = arguments; 180 | _files = files; 181 | _data = [[NSMutableData alloc] initWithCapacity:kMultiPartBufferSize]; 182 | _state = kParserState_Start; 183 | } 184 | return self; 185 | } 186 | 187 | - (void)dealloc { 188 | if (_tmpFile > 0) { 189 | close(_tmpFile); 190 | unlink([_tmpPath fileSystemRepresentation]); 191 | } 192 | } 193 | 194 | // http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 195 | - (BOOL)_parseData { 196 | BOOL success = YES; 197 | 198 | if (_state == kParserState_Headers) { 199 | NSRange range = [_data rangeOfData:_newlinesData options:0 range:NSMakeRange(0, _data.length)]; 200 | if (range.location != NSNotFound) { 201 | 202 | _controlName = nil; 203 | _fileName = nil; 204 | _contentType = nil; 205 | _tmpPath = nil; 206 | _subParser = nil; 207 | NSString* headers = [[NSString alloc] initWithData:[_data subdataWithRange:NSMakeRange(0, range.location)] encoding:NSUTF8StringEncoding]; 208 | if (headers) { 209 | for (NSString* header in [headers componentsSeparatedByString:@"\r\n"]) { 210 | NSRange subRange = [header rangeOfString:@":"]; 211 | if (subRange.location != NSNotFound) { 212 | NSString* name = [header substringToIndex:subRange.location]; 213 | NSString* value = [[header substringFromIndex:(subRange.location + subRange.length)] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; 214 | if ([name caseInsensitiveCompare:@"Content-Type"] == NSOrderedSame) { 215 | _contentType = GCDWebServerNormalizeHeaderValue(value); 216 | } else if ([name caseInsensitiveCompare:@"Content-Disposition"] == NSOrderedSame) { 217 | NSString* contentDisposition = GCDWebServerNormalizeHeaderValue(value); 218 | if ([GCDWebServerTruncateHeaderValue(contentDisposition) isEqualToString:@"form-data"]) { 219 | _controlName = GCDWebServerExtractHeaderValueParameter(contentDisposition, @"name"); 220 | _fileName = GCDWebServerExtractHeaderValueParameter(contentDisposition, @"filename"); 221 | } else if ([GCDWebServerTruncateHeaderValue(contentDisposition) isEqualToString:@"file"]) { 222 | _controlName = _defaultcontrolName; 223 | _fileName = GCDWebServerExtractHeaderValueParameter(contentDisposition, @"filename"); 224 | } 225 | } 226 | } else { 227 | GWS_DNOT_REACHED(); 228 | } 229 | } 230 | if (_contentType == nil) { 231 | _contentType = @"text/plain"; 232 | } 233 | } else { 234 | GWS_LOG_ERROR(@"Failed decoding headers in part of 'multipart/form-data'"); 235 | GWS_DNOT_REACHED(); 236 | } 237 | if (_controlName) { 238 | if ([GCDWebServerTruncateHeaderValue(_contentType) isEqualToString:@"multipart/mixed"]) { 239 | NSString* boundary = GCDWebServerExtractHeaderValueParameter(_contentType, @"boundary"); 240 | _subParser = [[GCDWebServerMIMEStreamParser alloc] initWithBoundary:boundary defaultControlName:_controlName arguments:_arguments files:_files]; 241 | if (_subParser == nil) { 242 | GWS_DNOT_REACHED(); 243 | success = NO; 244 | } 245 | } else if (_fileName) { 246 | NSString* path = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]; 247 | _tmpFile = open([path fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 248 | if (_tmpFile > 0) { 249 | _tmpPath = [path copy]; 250 | } else { 251 | GWS_DNOT_REACHED(); 252 | success = NO; 253 | } 254 | } 255 | } else { 256 | GWS_DNOT_REACHED(); 257 | success = NO; 258 | } 259 | 260 | [_data replaceBytesInRange:NSMakeRange(0, range.location + range.length) withBytes:NULL length:0]; 261 | _state = kParserState_Content; 262 | } 263 | } 264 | 265 | if ((_state == kParserState_Start) || (_state == kParserState_Content)) { 266 | NSRange range = [_data rangeOfData:_boundary options:0 range:NSMakeRange(0, _data.length)]; 267 | if (range.location != NSNotFound) { 268 | NSRange subRange = NSMakeRange(range.location + range.length, _data.length - range.location - range.length); 269 | NSRange subRange1 = [_data rangeOfData:_newlineData options:NSDataSearchAnchored range:subRange]; 270 | NSRange subRange2 = [_data rangeOfData:_dashNewlineData options:NSDataSearchAnchored range:subRange]; 271 | if ((subRange1.location != NSNotFound) || (subRange2.location != NSNotFound)) { 272 | 273 | if (_state == kParserState_Content) { 274 | const void* dataBytes = _data.bytes; 275 | NSUInteger dataLength = range.location - 2; 276 | if (_subParser) { 277 | if (![_subParser appendBytes:dataBytes length:(dataLength + 2)] || ![_subParser isAtEnd]) { 278 | GWS_DNOT_REACHED(); 279 | success = NO; 280 | } 281 | _subParser = nil; 282 | } else if (_tmpPath) { 283 | ssize_t result = write(_tmpFile, dataBytes, dataLength); 284 | if (result == (ssize_t)dataLength) { 285 | if (close(_tmpFile) == 0) { 286 | _tmpFile = 0; 287 | GCDWebServerMultiPartFile* file = [[GCDWebServerMultiPartFile alloc] initWithControlName:_controlName contentType:_contentType fileName:_fileName temporaryPath:_tmpPath]; 288 | [_files addObject:file]; 289 | } else { 290 | GWS_DNOT_REACHED(); 291 | success = NO; 292 | } 293 | } else { 294 | GWS_DNOT_REACHED(); 295 | success = NO; 296 | } 297 | _tmpPath = nil; 298 | } else { 299 | NSData* data = [[NSData alloc] initWithBytes:(void*)dataBytes length:dataLength]; 300 | GCDWebServerMultiPartArgument* argument = [[GCDWebServerMultiPartArgument alloc] initWithControlName:_controlName contentType:_contentType data:data]; 301 | [_arguments addObject:argument]; 302 | } 303 | } 304 | 305 | if (subRange1.location != NSNotFound) { 306 | [_data replaceBytesInRange:NSMakeRange(0, subRange1.location + subRange1.length) withBytes:NULL length:0]; 307 | _state = kParserState_Headers; 308 | success = [self _parseData]; 309 | } else { 310 | _state = kParserState_End; 311 | } 312 | } 313 | } else { 314 | NSUInteger margin = 2 * _boundary.length; 315 | if (_data.length > margin) { 316 | NSUInteger length = _data.length - margin; 317 | if (_subParser) { 318 | if ([_subParser appendBytes:_data.bytes length:length]) { 319 | [_data replaceBytesInRange:NSMakeRange(0, length) withBytes:NULL length:0]; 320 | } else { 321 | GWS_DNOT_REACHED(); 322 | success = NO; 323 | } 324 | } else if (_tmpPath) { 325 | ssize_t result = write(_tmpFile, _data.bytes, length); 326 | if (result == (ssize_t)length) { 327 | [_data replaceBytesInRange:NSMakeRange(0, length) withBytes:NULL length:0]; 328 | } else { 329 | GWS_DNOT_REACHED(); 330 | success = NO; 331 | } 332 | } 333 | } 334 | } 335 | } 336 | 337 | return success; 338 | } 339 | 340 | - (BOOL)appendBytes:(const void*)bytes length:(NSUInteger)length { 341 | [_data appendBytes:bytes length:length]; 342 | return [self _parseData]; 343 | } 344 | 345 | - (BOOL)isAtEnd { 346 | return (_state == kParserState_End); 347 | } 348 | 349 | @end 350 | 351 | @interface GCDWebServerMultiPartFormRequest () { 352 | @private 353 | GCDWebServerMIMEStreamParser* _parser; 354 | NSMutableArray* _arguments; 355 | NSMutableArray* _files; 356 | } 357 | @end 358 | 359 | @implementation GCDWebServerMultiPartFormRequest 360 | 361 | @synthesize arguments=_arguments, files=_files; 362 | 363 | + (NSString*)mimeType { 364 | return @"multipart/form-data"; 365 | } 366 | 367 | - (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query { 368 | if ((self = [super initWithMethod:method url:url headers:headers path:path query:query])) { 369 | _arguments = [[NSMutableArray alloc] init]; 370 | _files = [[NSMutableArray alloc] init]; 371 | } 372 | return self; 373 | } 374 | 375 | - (BOOL)open:(NSError**)error { 376 | NSString* boundary = GCDWebServerExtractHeaderValueParameter(self.contentType, @"boundary"); 377 | _parser = [[GCDWebServerMIMEStreamParser alloc] initWithBoundary:boundary defaultControlName:nil arguments:_arguments files:_files]; 378 | if (_parser == nil) { 379 | if (error) { 380 | *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Failed starting to parse multipart form data"}]; 381 | } 382 | return NO; 383 | } 384 | return YES; 385 | } 386 | 387 | - (BOOL)writeData:(NSData*)data error:(NSError**)error { 388 | if (![_parser appendBytes:data.bytes length:data.length]) { 389 | if (error) { 390 | *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Failed continuing to parse multipart form data"}]; 391 | } 392 | return NO; 393 | } 394 | return YES; 395 | } 396 | 397 | - (BOOL)close:(NSError**)error { 398 | BOOL atEnd = [_parser isAtEnd]; 399 | _parser = nil; 400 | if (!atEnd) { 401 | if (error) { 402 | *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Failed finishing to parse multipart form data"}]; 403 | } 404 | return NO; 405 | } 406 | return YES; 407 | } 408 | 409 | - (GCDWebServerMultiPartArgument*)firstArgumentForControlName:(NSString*)name { 410 | for (GCDWebServerMultiPartArgument* argument in _arguments) { 411 | if ([argument.controlName isEqualToString:name]) { 412 | return argument; 413 | } 414 | } 415 | return nil; 416 | } 417 | 418 | - (GCDWebServerMultiPartFile*)firstFileForControlName:(NSString*)name { 419 | for (GCDWebServerMultiPartFile* file in _files) { 420 | if ([file.controlName isEqualToString:name]) { 421 | return file; 422 | } 423 | } 424 | return nil; 425 | } 426 | 427 | - (NSString*)description { 428 | NSMutableString* description = [NSMutableString stringWithString:[super description]]; 429 | if (_arguments.count) { 430 | [description appendString:@"\n"]; 431 | for (GCDWebServerMultiPartArgument* argument in _arguments) { 432 | [description appendFormat:@"\n%@ (%@)\n", argument.controlName, argument.contentType]; 433 | [description appendString:GCDWebServerDescribeData(argument.data, argument.contentType)]; 434 | } 435 | } 436 | if (_files.count) { 437 | [description appendString:@"\n"]; 438 | for (GCDWebServerMultiPartFile* file in _files) { 439 | [description appendFormat:@"\n%@ (%@): %@\n{%@}", file.controlName, file.contentType, file.fileName, file.temporaryPath]; 440 | } 441 | } 442 | return description; 443 | } 444 | 445 | @end 446 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerDataRequest.h" 29 | 30 | /** 31 | * The GCDWebServerURLEncodedFormRequest subclass of GCDWebServerRequest 32 | * parses the body of the HTTP request as a URL encoded form using 33 | * GCDWebServerParseURLEncodedForm(). 34 | */ 35 | @interface GCDWebServerURLEncodedFormRequest : GCDWebServerDataRequest 36 | 37 | /** 38 | * Returns the unescaped control names and values for the URL encoded form. 39 | * 40 | * The text encoding used to interpret the data is extracted from the 41 | * "Content-Type" header or defaults to UTF-8. 42 | */ 43 | @property(nonatomic, readonly) NSDictionary* arguments; 44 | 45 | /** 46 | * Returns the MIME type for URL encoded forms 47 | * i.e. "application/x-www-form-urlencoded". 48 | */ 49 | + (NSString*)mimeType; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import "GCDWebServerPrivate.h" 33 | 34 | @interface GCDWebServerURLEncodedFormRequest () { 35 | @private 36 | NSDictionary* _arguments; 37 | } 38 | @end 39 | 40 | @implementation GCDWebServerURLEncodedFormRequest 41 | 42 | @synthesize arguments=_arguments; 43 | 44 | + (NSString*)mimeType { 45 | return @"application/x-www-form-urlencoded"; 46 | } 47 | 48 | - (BOOL)close:(NSError**)error { 49 | if (![super close:error]) { 50 | return NO; 51 | } 52 | 53 | NSString* charset = GCDWebServerExtractHeaderValueParameter(self.contentType, @"charset"); 54 | NSString* string = [[NSString alloc] initWithData:self.data encoding:GCDWebServerStringEncodingFromCharset(charset)]; 55 | _arguments = GCDWebServerParseURLEncodedForm(string); 56 | GWS_DCHECK(_arguments); 57 | 58 | return YES; 59 | } 60 | 61 | - (NSString*)description { 62 | NSMutableString* description = [NSMutableString stringWithString:[super description]]; 63 | [description appendString:@"\n"]; 64 | for (NSString* argument in [[_arguments allKeys] sortedArrayUsingSelector:@selector(compare:)]) { 65 | [description appendFormat:@"\n%@ = %@", argument, [_arguments objectForKey:argument]]; 66 | } 67 | return description; 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Responses/GCDWebServerDataResponse.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerResponse.h" 29 | 30 | /** 31 | * The GCDWebServerDataResponse subclass of GCDWebServerResponse reads the body 32 | * of the HTTP response from memory. 33 | */ 34 | @interface GCDWebServerDataResponse : GCDWebServerResponse 35 | 36 | /** 37 | * Creates a response with data in memory and a given content type. 38 | */ 39 | + (instancetype)responseWithData:(NSData*)data contentType:(NSString*)type; 40 | 41 | /** 42 | * This method is the designated initializer for the class. 43 | */ 44 | - (instancetype)initWithData:(NSData*)data contentType:(NSString*)type; 45 | 46 | @end 47 | 48 | @interface GCDWebServerDataResponse (Extensions) 49 | 50 | /** 51 | * Creates a data response from text encoded using UTF-8. 52 | */ 53 | + (instancetype)responseWithText:(NSString*)text; 54 | 55 | /** 56 | * Creates a data response from HTML encoded using UTF-8. 57 | */ 58 | + (instancetype)responseWithHTML:(NSString*)html; 59 | 60 | /** 61 | * Creates a data response from an HTML template encoded using UTF-8. 62 | * See -initWithHTMLTemplate:variables: for details. 63 | */ 64 | + (instancetype)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables; 65 | 66 | /** 67 | * Creates a data response from a serialized JSON object and the default 68 | * "application/json" content type. 69 | */ 70 | + (instancetype)responseWithJSONObject:(id)object; 71 | 72 | /** 73 | * Creates a data response from a serialized JSON object and a custom 74 | * content type. 75 | */ 76 | + (instancetype)responseWithJSONObject:(id)object contentType:(NSString*)type; 77 | 78 | /** 79 | * Initializes a data response from text encoded using UTF-8. 80 | */ 81 | - (instancetype)initWithText:(NSString*)text; 82 | 83 | /** 84 | * Initializes a data response from HTML encoded using UTF-8. 85 | */ 86 | - (instancetype)initWithHTML:(NSString*)html; 87 | 88 | /** 89 | * Initializes a data response from an HTML template encoded using UTF-8. 90 | * 91 | * All occurences of "%variable%" within the HTML template are replaced with 92 | * their corresponding values. 93 | */ 94 | - (instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables; 95 | 96 | /** 97 | * Initializes a data response from a serialized JSON object and the default 98 | * "application/json" content type. 99 | */ 100 | - (instancetype)initWithJSONObject:(id)object; 101 | 102 | /** 103 | * Initializes a data response from a serialized JSON object and a custom 104 | * content type. 105 | */ 106 | - (instancetype)initWithJSONObject:(id)object contentType:(NSString*)type; 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Responses/GCDWebServerDataResponse.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import "GCDWebServerPrivate.h" 33 | 34 | @interface GCDWebServerDataResponse () { 35 | @private 36 | NSData* _data; 37 | BOOL _done; 38 | } 39 | @end 40 | 41 | @implementation GCDWebServerDataResponse 42 | 43 | + (instancetype)responseWithData:(NSData*)data contentType:(NSString*)type { 44 | return [[[self class] alloc] initWithData:data contentType:type]; 45 | } 46 | 47 | - (instancetype)initWithData:(NSData*)data contentType:(NSString*)type { 48 | if (data == nil) { 49 | GWS_DNOT_REACHED(); 50 | return nil; 51 | } 52 | 53 | if ((self = [super init])) { 54 | _data = data; 55 | 56 | self.contentType = type; 57 | self.contentLength = data.length; 58 | } 59 | return self; 60 | } 61 | 62 | - (NSData*)readData:(NSError**)error { 63 | NSData* data; 64 | if (_done) { 65 | data = [NSData data]; 66 | } else { 67 | data = _data; 68 | _done = YES; 69 | } 70 | return data; 71 | } 72 | 73 | - (NSString*)description { 74 | NSMutableString* description = [NSMutableString stringWithString:[super description]]; 75 | [description appendString:@"\n\n"]; 76 | [description appendString:GCDWebServerDescribeData(_data, self.contentType)]; 77 | return description; 78 | } 79 | 80 | @end 81 | 82 | @implementation GCDWebServerDataResponse (Extensions) 83 | 84 | + (instancetype)responseWithText:(NSString*)text { 85 | return [[self alloc] initWithText:text]; 86 | } 87 | 88 | + (instancetype)responseWithHTML:(NSString*)html { 89 | return [[self alloc] initWithHTML:html]; 90 | } 91 | 92 | + (instancetype)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables { 93 | return [[self alloc] initWithHTMLTemplate:path variables:variables]; 94 | } 95 | 96 | + (instancetype)responseWithJSONObject:(id)object { 97 | return [[self alloc] initWithJSONObject:object]; 98 | } 99 | 100 | + (instancetype)responseWithJSONObject:(id)object contentType:(NSString*)type { 101 | return [[self alloc] initWithJSONObject:object contentType:type]; 102 | } 103 | 104 | - (instancetype)initWithText:(NSString*)text { 105 | NSData* data = [text dataUsingEncoding:NSUTF8StringEncoding]; 106 | if (data == nil) { 107 | GWS_DNOT_REACHED(); 108 | return nil; 109 | } 110 | return [self initWithData:data contentType:@"text/plain; charset=utf-8"]; 111 | } 112 | 113 | - (instancetype)initWithHTML:(NSString*)html { 114 | NSData* data = [html dataUsingEncoding:NSUTF8StringEncoding]; 115 | if (data == nil) { 116 | GWS_DNOT_REACHED(); 117 | return nil; 118 | } 119 | return [self initWithData:data contentType:@"text/html; charset=utf-8"]; 120 | } 121 | 122 | - (instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables { 123 | NSMutableString* html = [[NSMutableString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL]; 124 | [variables enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSString* value, BOOL* stop) { 125 | [html replaceOccurrencesOfString:[NSString stringWithFormat:@"%%%@%%", key] withString:value options:0 range:NSMakeRange(0, html.length)]; 126 | }]; 127 | id response = [self initWithHTML:html]; 128 | return response; 129 | } 130 | 131 | - (instancetype)initWithJSONObject:(id)object { 132 | return [self initWithJSONObject:object contentType:@"application/json"]; 133 | } 134 | 135 | - (instancetype)initWithJSONObject:(id)object contentType:(NSString*)type { 136 | NSData* data = [NSJSONSerialization dataWithJSONObject:object options:0 error:NULL]; 137 | if (data == nil) { 138 | return nil; 139 | } 140 | return [self initWithData:data contentType:type]; 141 | } 142 | 143 | @end 144 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Responses/GCDWebServerErrorResponse.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerDataResponse.h" 29 | #import "GCDWebServerHTTPStatusCodes.h" 30 | 31 | /** 32 | * The GCDWebServerDataResponse subclass of GCDWebServerDataResponse generates 33 | * an HTML body from an HTTP status code and an error message. 34 | */ 35 | @interface GCDWebServerErrorResponse : GCDWebServerDataResponse 36 | 37 | /** 38 | * Creates a client error response with the corresponding HTTP status code. 39 | */ 40 | + (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); 41 | 42 | /** 43 | * Creates a server error response with the corresponding HTTP status code. 44 | */ 45 | + (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); 46 | 47 | /** 48 | * Creates a client error response with the corresponding HTTP status code 49 | * and an underlying NSError. 50 | */ 51 | + (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); 52 | 53 | /** 54 | * Creates a server error response with the corresponding HTTP status code 55 | * and an underlying NSError. 56 | */ 57 | + (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); 58 | 59 | /** 60 | * Initializes a client error response with the corresponding HTTP status code. 61 | */ 62 | - (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); 63 | 64 | /** 65 | * Initializes a server error response with the corresponding HTTP status code. 66 | */ 67 | - (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); 68 | 69 | /** 70 | * Initializes a client error response with the corresponding HTTP status code 71 | * and an underlying NSError. 72 | */ 73 | - (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); 74 | 75 | /** 76 | * Initializes a server error response with the corresponding HTTP status code 77 | * and an underlying NSError. 78 | */ 79 | - (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Responses/GCDWebServerErrorResponse.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import "GCDWebServerPrivate.h" 33 | 34 | @interface GCDWebServerErrorResponse () 35 | - (instancetype)initWithStatusCode:(NSInteger)statusCode underlyingError:(NSError*)underlyingError messageFormat:(NSString*)format arguments:(va_list)arguments; 36 | @end 37 | 38 | @implementation GCDWebServerErrorResponse 39 | 40 | + (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... { 41 | GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500)); 42 | va_list arguments; 43 | va_start(arguments, format); 44 | GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments]; 45 | va_end(arguments); 46 | return response; 47 | } 48 | 49 | + (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... { 50 | GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600)); 51 | va_list arguments; 52 | va_start(arguments, format); 53 | GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments]; 54 | va_end(arguments); 55 | return response; 56 | } 57 | 58 | + (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... { 59 | GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500)); 60 | va_list arguments; 61 | va_start(arguments, format); 62 | GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments]; 63 | va_end(arguments); 64 | return response; 65 | } 66 | 67 | + (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... { 68 | GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600)); 69 | va_list arguments; 70 | va_start(arguments, format); 71 | GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments]; 72 | va_end(arguments); 73 | return response; 74 | } 75 | 76 | static inline NSString* _EscapeHTMLString(NSString* string) { 77 | return [string stringByReplacingOccurrencesOfString:@"\"" withString:@"""]; 78 | } 79 | 80 | - (instancetype)initWithStatusCode:(NSInteger)statusCode underlyingError:(NSError*)underlyingError messageFormat:(NSString*)format arguments:(va_list)arguments { 81 | NSString* message = [[NSString alloc] initWithFormat:format arguments:arguments]; 82 | NSString* title = [NSString stringWithFormat:@"HTTP Error %i", (int)statusCode]; 83 | NSString* error = underlyingError ? [NSString stringWithFormat:@"[%@] %@ (%li)", underlyingError.domain, _EscapeHTMLString(underlyingError.localizedDescription), (long)underlyingError.code] : @""; 84 | NSString* html = [NSString stringWithFormat:@"%@

%@: %@

%@

", 85 | title, title, _EscapeHTMLString(message), error]; 86 | if ((self = [self initWithHTML:html])) { 87 | self.statusCode = statusCode; 88 | } 89 | return self; 90 | } 91 | 92 | - (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... { 93 | GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500)); 94 | va_list arguments; 95 | va_start(arguments, format); 96 | self = [self initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments]; 97 | va_end(arguments); 98 | return self; 99 | } 100 | 101 | - (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... { 102 | GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600)); 103 | va_list arguments; 104 | va_start(arguments, format); 105 | self = [self initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments]; 106 | va_end(arguments); 107 | return self; 108 | } 109 | 110 | - (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... { 111 | GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500)); 112 | va_list arguments; 113 | va_start(arguments, format); 114 | self = [self initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments]; 115 | va_end(arguments); 116 | return self; 117 | } 118 | 119 | - (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... { 120 | GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600)); 121 | va_list arguments; 122 | va_start(arguments, format); 123 | self = [self initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments]; 124 | va_end(arguments); 125 | return self; 126 | } 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Responses/GCDWebServerFileResponse.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerResponse.h" 29 | 30 | /** 31 | * The GCDWebServerFileResponse subclass of GCDWebServerResponse reads the body 32 | * of the HTTP response from a file on disk. 33 | * 34 | * It will automatically set the contentType, lastModifiedDate and eTag 35 | * properties of the GCDWebServerResponse according to the file extension and 36 | * metadata. 37 | */ 38 | @interface GCDWebServerFileResponse : GCDWebServerResponse 39 | 40 | /** 41 | * Creates a response with the contents of a file. 42 | */ 43 | + (instancetype)responseWithFile:(NSString*)path; 44 | 45 | /** 46 | * Creates a response like +responseWithFile: and sets the "Content-Disposition" 47 | * HTTP header for a download if the "attachment" argument is YES. 48 | */ 49 | + (instancetype)responseWithFile:(NSString*)path isAttachment:(BOOL)attachment; 50 | 51 | /** 52 | * Creates a response like +responseWithFile: but restricts the file contents 53 | * to a specific byte range. 54 | * 55 | * See -initWithFile:byteRange: for details. 56 | */ 57 | + (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range; 58 | 59 | /** 60 | * Creates a response like +responseWithFile:byteRange: and sets the 61 | * "Content-Disposition" HTTP header for a download if the "attachment" 62 | * argument is YES. 63 | */ 64 | + (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment; 65 | 66 | /** 67 | * Initializes a response with the contents of a file. 68 | */ 69 | - (instancetype)initWithFile:(NSString*)path; 70 | 71 | /** 72 | * Initializes a response like +responseWithFile: and sets the 73 | * "Content-Disposition" HTTP header for a download if the "attachment" 74 | * argument is YES. 75 | */ 76 | - (instancetype)initWithFile:(NSString*)path isAttachment:(BOOL)attachment; 77 | 78 | /** 79 | * Initializes a response like -initWithFile: but restricts the file contents 80 | * to a specific byte range. This range should be set to (NSUIntegerMax, 0) for 81 | * the full file, (offset, length) if expressed from the beginning of the file, 82 | * or (NSUIntegerMax, length) if expressed from the end of the file. The "offset" 83 | * and "length" values will be automatically adjusted to be compatible with the 84 | * actual size of the file. 85 | * 86 | * This argument would typically be set to the value of the byteRange property 87 | * of the current GCDWebServerRequest. 88 | */ 89 | - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range; 90 | 91 | /** 92 | * This method is the designated initializer for the class. 93 | */ 94 | - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment; 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Responses/GCDWebServerFileResponse.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import 33 | 34 | #import "GCDWebServerPrivate.h" 35 | 36 | #define kFileReadBufferSize (32 * 1024) 37 | 38 | @interface GCDWebServerFileResponse () { 39 | @private 40 | NSString* _path; 41 | NSUInteger _offset; 42 | NSUInteger _size; 43 | int _file; 44 | } 45 | @end 46 | 47 | @implementation GCDWebServerFileResponse 48 | 49 | + (instancetype)responseWithFile:(NSString*)path { 50 | return [[[self class] alloc] initWithFile:path]; 51 | } 52 | 53 | + (instancetype)responseWithFile:(NSString*)path isAttachment:(BOOL)attachment { 54 | return [[[self class] alloc] initWithFile:path isAttachment:attachment]; 55 | } 56 | 57 | + (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range { 58 | return [[[self class] alloc] initWithFile:path byteRange:range]; 59 | } 60 | 61 | + (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment { 62 | return [[[self class] alloc] initWithFile:path byteRange:range isAttachment:attachment]; 63 | } 64 | 65 | - (instancetype)initWithFile:(NSString*)path { 66 | return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:NO]; 67 | } 68 | 69 | - (instancetype)initWithFile:(NSString*)path isAttachment:(BOOL)attachment { 70 | return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:attachment]; 71 | } 72 | 73 | - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range { 74 | return [self initWithFile:path byteRange:range isAttachment:NO]; 75 | } 76 | 77 | static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) { 78 | return [NSDate dateWithTimeIntervalSince1970:((NSTimeInterval)t->tv_sec + (NSTimeInterval)t->tv_nsec / 1000000000.0)]; 79 | } 80 | 81 | - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment { 82 | struct stat info; 83 | if (lstat([path fileSystemRepresentation], &info) || !(info.st_mode & S_IFREG)) { 84 | GWS_DNOT_REACHED(); 85 | return nil; 86 | } 87 | #ifndef __LP64__ 88 | if (info.st_size >= (off_t)4294967295) { // In 32 bit mode, we can't handle files greater than 4 GiBs (don't use "NSUIntegerMax" here to avoid potential unsigned to signed conversion issues) 89 | GWS_DNOT_REACHED(); 90 | return nil; 91 | } 92 | #endif 93 | NSUInteger fileSize = (NSUInteger)info.st_size; 94 | 95 | BOOL hasByteRange = GCDWebServerIsValidByteRange(range); 96 | if (hasByteRange) { 97 | if (range.location != NSUIntegerMax) { 98 | range.location = MIN(range.location, fileSize); 99 | range.length = MIN(range.length, fileSize - range.location); 100 | } else { 101 | range.length = MIN(range.length, fileSize); 102 | range.location = fileSize - range.length; 103 | } 104 | if (range.length == 0) { 105 | return nil; // TODO: Return 416 status code and "Content-Range: bytes */{file length}" header 106 | } 107 | } else { 108 | range.location = 0; 109 | range.length = fileSize; 110 | } 111 | 112 | if ((self = [super init])) { 113 | _path = [path copy]; 114 | _offset = range.location; 115 | _size = range.length; 116 | if (hasByteRange) { 117 | [self setStatusCode:kGCDWebServerHTTPStatusCode_PartialContent]; 118 | [self setValue:[NSString stringWithFormat:@"bytes %lu-%lu/%lu", (unsigned long)_offset, (unsigned long)(_offset + _size - 1), (unsigned long)fileSize] forAdditionalHeader:@"Content-Range"]; 119 | GWS_LOG_DEBUG(@"Using content bytes range [%lu-%lu] for file \"%@\"", (unsigned long)_offset, (unsigned long)(_offset + _size - 1), path); 120 | } 121 | 122 | if (attachment) { 123 | NSString* fileName = [path lastPathComponent]; 124 | NSData* data = [[fileName stringByReplacingOccurrencesOfString:@"\"" withString:@""] dataUsingEncoding:NSISOLatin1StringEncoding allowLossyConversion:YES]; 125 | NSString* lossyFileName = data ? [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding] : nil; 126 | if (lossyFileName) { 127 | NSString* value = [NSString stringWithFormat:@"attachment; filename=\"%@\"; filename*=UTF-8''%@", lossyFileName, GCDWebServerEscapeURLString(fileName)]; 128 | [self setValue:value forAdditionalHeader:@"Content-Disposition"]; 129 | } else { 130 | GWS_DNOT_REACHED(); 131 | } 132 | } 133 | 134 | self.contentType = GCDWebServerGetMimeTypeForExtension([_path pathExtension]); 135 | self.contentLength = _size; 136 | self.lastModifiedDate = _NSDateFromTimeSpec(&info.st_mtimespec); 137 | self.eTag = [NSString stringWithFormat:@"%llu/%li/%li", info.st_ino, info.st_mtimespec.tv_sec, info.st_mtimespec.tv_nsec]; 138 | } 139 | return self; 140 | } 141 | 142 | - (BOOL)open:(NSError**)error { 143 | _file = open([_path fileSystemRepresentation], O_NOFOLLOW | O_RDONLY); 144 | if (_file <= 0) { 145 | if (error) { 146 | *error = GCDWebServerMakePosixError(errno); 147 | } 148 | return NO; 149 | } 150 | if (lseek(_file, _offset, SEEK_SET) != (off_t)_offset) { 151 | if (error) { 152 | *error = GCDWebServerMakePosixError(errno); 153 | } 154 | close(_file); 155 | return NO; 156 | } 157 | return YES; 158 | } 159 | 160 | - (NSData*)readData:(NSError**)error { 161 | size_t length = MIN((NSUInteger)kFileReadBufferSize, _size); 162 | NSMutableData* data = [[NSMutableData alloc] initWithLength:length]; 163 | ssize_t result = read(_file, data.mutableBytes, length); 164 | if (result < 0) { 165 | if (error) { 166 | *error = GCDWebServerMakePosixError(errno); 167 | } 168 | return nil; 169 | } 170 | if (result > 0) { 171 | [data setLength:result]; 172 | _size -= result; 173 | } 174 | return data; 175 | } 176 | 177 | - (void)close { 178 | close(_file); 179 | } 180 | 181 | - (NSString*)description { 182 | NSMutableString* description = [NSMutableString stringWithString:[super description]]; 183 | [description appendFormat:@"\n\n{%@}", _path]; 184 | return description; 185 | } 186 | 187 | @end 188 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Responses/GCDWebServerStreamedResponse.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerResponse.h" 29 | 30 | /** 31 | * The GCDWebServerStreamBlock is called to stream the data for the HTTP body. 32 | * The block must return either a chunk of data, an empty NSData when done, or 33 | * nil on error and set the "error" argument which is guaranteed to be non-NULL. 34 | */ 35 | typedef NSData* (^GCDWebServerStreamBlock)(NSError** error); 36 | 37 | /** 38 | * The GCDWebServerAsyncStreamBlock works like the GCDWebServerStreamBlock 39 | * except the streamed data can be returned at a later time allowing for 40 | * truly asynchronous generation of the data. 41 | * 42 | * The block must call "completionBlock" passing the new chunk of data when ready, 43 | * an empty NSData when done, or nil on error and pass a NSError. 44 | * 45 | * The block cannot call "completionBlock" more than once per invocation. 46 | */ 47 | typedef void (^GCDWebServerAsyncStreamBlock)(GCDWebServerBodyReaderCompletionBlock completionBlock); 48 | 49 | /** 50 | * The GCDWebServerStreamedResponse subclass of GCDWebServerResponse streams 51 | * the body of the HTTP response using a GCD block. 52 | */ 53 | @interface GCDWebServerStreamedResponse : GCDWebServerResponse 54 | 55 | /** 56 | * Creates a response with streamed data and a given content type. 57 | */ 58 | + (instancetype)responseWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block; 59 | 60 | /** 61 | * Creates a response with async streamed data and a given content type. 62 | */ 63 | + (instancetype)responseWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block; 64 | 65 | /** 66 | * Initializes a response with streamed data and a given content type. 67 | */ 68 | - (instancetype)initWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block; 69 | 70 | /** 71 | * This method is the designated initializer for the class. 72 | */ 73 | - (instancetype)initWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block; 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/GCDWebServer/Responses/GCDWebServerStreamedResponse.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import "GCDWebServerPrivate.h" 33 | 34 | @interface GCDWebServerStreamedResponse () { 35 | @private 36 | GCDWebServerAsyncStreamBlock _block; 37 | } 38 | @end 39 | 40 | @implementation GCDWebServerStreamedResponse 41 | 42 | + (instancetype)responseWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block { 43 | return [[[self class] alloc] initWithContentType:type streamBlock:block]; 44 | } 45 | 46 | + (instancetype)responseWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block { 47 | return [[[self class] alloc] initWithContentType:type asyncStreamBlock:block]; 48 | } 49 | 50 | - (instancetype)initWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block { 51 | return [self initWithContentType:type asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock completionBlock) { 52 | 53 | NSError* error = nil; 54 | NSData* data = block(&error); 55 | completionBlock(data, error); 56 | 57 | }]; 58 | } 59 | 60 | - (instancetype)initWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block { 61 | if ((self = [super init])) { 62 | _block = [block copy]; 63 | 64 | self.contentType = type; 65 | } 66 | return self; 67 | } 68 | 69 | - (void)asyncReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block { 70 | _block(block); 71 | } 72 | 73 | - (NSString*)description { 74 | NSMutableString* description = [NSMutableString stringWithString:[super description]]; 75 | [description appendString:@"\n\n"]; 76 | return description; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /Pods/GCDWebServer/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2014, Pierre-Olivier Latour 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * The name of Pierre-Olivier Latour may not be used to endorse 12 | or promote products derived from this software without specific 13 | prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /Pods/Headers/Private/GCDWebServer/GCDWebServer.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Core/GCDWebServer.h -------------------------------------------------------------------------------- /Pods/Headers/Private/GCDWebServer/GCDWebServerConnection.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Core/GCDWebServerConnection.h -------------------------------------------------------------------------------- /Pods/Headers/Private/GCDWebServer/GCDWebServerDataRequest.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Requests/GCDWebServerDataRequest.h -------------------------------------------------------------------------------- /Pods/Headers/Private/GCDWebServer/GCDWebServerDataResponse.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Responses/GCDWebServerDataResponse.h -------------------------------------------------------------------------------- /Pods/Headers/Private/GCDWebServer/GCDWebServerErrorResponse.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Responses/GCDWebServerErrorResponse.h -------------------------------------------------------------------------------- /Pods/Headers/Private/GCDWebServer/GCDWebServerFileRequest.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Requests/GCDWebServerFileRequest.h -------------------------------------------------------------------------------- /Pods/Headers/Private/GCDWebServer/GCDWebServerFileResponse.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Responses/GCDWebServerFileResponse.h -------------------------------------------------------------------------------- /Pods/Headers/Private/GCDWebServer/GCDWebServerFunctions.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.h -------------------------------------------------------------------------------- /Pods/Headers/Private/GCDWebServer/GCDWebServerHTTPStatusCodes.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Core/GCDWebServerHTTPStatusCodes.h -------------------------------------------------------------------------------- /Pods/Headers/Private/GCDWebServer/GCDWebServerMultiPartFormRequest.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h -------------------------------------------------------------------------------- /Pods/Headers/Private/GCDWebServer/GCDWebServerPrivate.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Core/GCDWebServerPrivate.h -------------------------------------------------------------------------------- /Pods/Headers/Private/GCDWebServer/GCDWebServerRequest.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.h -------------------------------------------------------------------------------- /Pods/Headers/Private/GCDWebServer/GCDWebServerResponse.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Core/GCDWebServerResponse.h -------------------------------------------------------------------------------- /Pods/Headers/Private/GCDWebServer/GCDWebServerStreamedResponse.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Responses/GCDWebServerStreamedResponse.h -------------------------------------------------------------------------------- /Pods/Headers/Private/GCDWebServer/GCDWebServerURLEncodedFormRequest.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h -------------------------------------------------------------------------------- /Pods/Headers/Public/GCDWebServer/GCDWebServer.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Core/GCDWebServer.h -------------------------------------------------------------------------------- /Pods/Headers/Public/GCDWebServer/GCDWebServerConnection.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Core/GCDWebServerConnection.h -------------------------------------------------------------------------------- /Pods/Headers/Public/GCDWebServer/GCDWebServerDataRequest.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Requests/GCDWebServerDataRequest.h -------------------------------------------------------------------------------- /Pods/Headers/Public/GCDWebServer/GCDWebServerDataResponse.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Responses/GCDWebServerDataResponse.h -------------------------------------------------------------------------------- /Pods/Headers/Public/GCDWebServer/GCDWebServerErrorResponse.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Responses/GCDWebServerErrorResponse.h -------------------------------------------------------------------------------- /Pods/Headers/Public/GCDWebServer/GCDWebServerFileRequest.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Requests/GCDWebServerFileRequest.h -------------------------------------------------------------------------------- /Pods/Headers/Public/GCDWebServer/GCDWebServerFileResponse.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Responses/GCDWebServerFileResponse.h -------------------------------------------------------------------------------- /Pods/Headers/Public/GCDWebServer/GCDWebServerFunctions.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.h -------------------------------------------------------------------------------- /Pods/Headers/Public/GCDWebServer/GCDWebServerHTTPStatusCodes.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Core/GCDWebServerHTTPStatusCodes.h -------------------------------------------------------------------------------- /Pods/Headers/Public/GCDWebServer/GCDWebServerMultiPartFormRequest.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h -------------------------------------------------------------------------------- /Pods/Headers/Public/GCDWebServer/GCDWebServerRequest.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.h -------------------------------------------------------------------------------- /Pods/Headers/Public/GCDWebServer/GCDWebServerResponse.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Core/GCDWebServerResponse.h -------------------------------------------------------------------------------- /Pods/Headers/Public/GCDWebServer/GCDWebServerStreamedResponse.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Responses/GCDWebServerStreamedResponse.h -------------------------------------------------------------------------------- /Pods/Headers/Public/GCDWebServer/GCDWebServerURLEncodedFormRequest.h: -------------------------------------------------------------------------------- 1 | ../../../GCDWebServer/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - GCDWebServer (3.3.2): 3 | - GCDWebServer/Core (= 3.3.2) 4 | - GCDWebServer/Core (3.3.2) 5 | 6 | DEPENDENCIES: 7 | - GCDWebServer (~> 3.0) 8 | 9 | SPEC CHECKSUMS: 10 | GCDWebServer: 2a375ec42839a41d7187d04e5b688d32fa5c4cd5 11 | 12 | PODFILE CHECKSUM: 455efa81127280c58f42ca02e62e90533753e8ad 13 | 14 | COCOAPODS: 1.0.0.beta.8 15 | -------------------------------------------------------------------------------- /Pods/Target Support Files/GCDWebServer/GCDWebServer-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_GCDWebServer : NSObject 3 | @end 4 | @implementation PodsDummy_GCDWebServer 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/GCDWebServer/GCDWebServer-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Pods/Target Support Files/GCDWebServer/GCDWebServer.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_SHARED_BUILD_DIR/GCDWebServer 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/GCDWebServer" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GCDWebServer" 4 | OTHER_LDFLAGS = -l"z" -framework "CFNetwork" -framework "MobileCoreServices" 5 | PODS_ROOT = ${SRCROOT} 6 | PODS_SHARED_BUILD_DIR = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 8 | SKIP_INSTALL = YES 9 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-TestNSlog/Pods-TestNSlog-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## GCDWebServer 5 | 6 | Copyright (c) 2012-2014, Pierre-Olivier Latour 7 | All rights reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are met: 11 | * Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | * The name of Pierre-Olivier Latour may not be used to endorse 17 | or promote products derived from this software without specific 18 | prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 24 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | Generated by CocoaPods - https://cocoapods.org 32 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-TestNSlog/Pods-TestNSlog-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2012-2014, Pierre-Olivier Latour 18 | All rights reserved. 19 | 20 | Redistribution and use in source and binary forms, with or without 21 | modification, are permitted provided that the following conditions are met: 22 | * Redistributions of source code must retain the above copyright 23 | notice, this list of conditions and the following disclaimer. 24 | * Redistributions in binary form must reproduce the above copyright 25 | notice, this list of conditions and the following disclaimer in the 26 | documentation and/or other materials provided with the distribution. 27 | * The name of Pierre-Olivier Latour may not be used to endorse 28 | or promote products derived from this software without specific 29 | prior written permission. 30 | 31 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 32 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 33 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 34 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 35 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 36 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 37 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 38 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 39 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 40 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 | 42 | Title 43 | GCDWebServer 44 | Type 45 | PSGroupSpecifier 46 | 47 | 48 | FooterText 49 | Generated by CocoaPods - https://cocoapods.org 50 | Title 51 | 52 | Type 53 | PSGroupSpecifier 54 | 55 | 56 | StringsTable 57 | Acknowledgements 58 | Title 59 | Acknowledgements 60 | 61 | 62 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-TestNSlog/Pods-TestNSlog-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_TestNSlog : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_TestNSlog 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-TestNSlog/Pods-TestNSlog-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-TestNSlog/Pods-TestNSlog-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | *) 22 | TARGET_DEVICE_ARGS="--target-device mac" 23 | ;; 24 | esac 25 | 26 | realpath() { 27 | DIRECTORY="$(cd "${1%/*}" && pwd)" 28 | FILENAME="${1##*/}" 29 | echo "$DIRECTORY/$FILENAME" 30 | } 31 | 32 | install_resource() 33 | { 34 | if [[ "$1" = /* ]] ; then 35 | RESOURCE_PATH="$1" 36 | else 37 | RESOURCE_PATH="${PODS_ROOT}/$1" 38 | fi 39 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 40 | cat << EOM 41 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 42 | EOM 43 | exit 1 44 | fi 45 | case $RESOURCE_PATH in 46 | *.storyboard) 47 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 48 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 49 | ;; 50 | *.xib) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT}" 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" 53 | ;; 54 | *.framework) 55 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 56 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 57 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 58 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 59 | ;; 60 | *.xcdatamodel) 61 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 62 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 63 | ;; 64 | *.xcdatamodeld) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 67 | ;; 68 | *.xcmappingmodel) 69 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 70 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 71 | ;; 72 | *.xcassets) 73 | ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") 74 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 75 | ;; 76 | *) 77 | echo "$RESOURCE_PATH" 78 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 79 | ;; 80 | esac 81 | } 82 | 83 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 84 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 85 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 86 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 87 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | fi 89 | rm -f "$RESOURCES_TO_COPY" 90 | 91 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 92 | then 93 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 94 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 95 | while read line; do 96 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 97 | XCASSET_FILES+=("$line") 98 | fi 99 | done <<<"$OTHER_XCASSETS" 100 | 101 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 102 | fi 103 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-TestNSlog/Pods-TestNSlog.debug.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GCDWebServer" 3 | LIBRARY_SEARCH_PATHS = $(inherited) "$CONFIGURATION_BUILD_DIR/GCDWebServer" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/GCDWebServer" 5 | OTHER_LDFLAGS = $(inherited) -ObjC -l"GCDWebServer" -l"z" -framework "CFNetwork" -framework "MobileCoreServices" 6 | PODS_ROOT = ${SRCROOT}/Pods 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-TestNSlog/Pods-TestNSlog.release.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GCDWebServer" 3 | LIBRARY_SEARCH_PATHS = $(inherited) "$CONFIGURATION_BUILD_DIR/GCDWebServer" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/GCDWebServer" 5 | OTHER_LDFLAGS = $(inherited) -ObjC -l"GCDWebServer" -l"z" -framework "CFNetwork" -framework "MobileCoreServices" 6 | PODS_ROOT = ${SRCROOT}/Pods 7 | -------------------------------------------------------------------------------- /TestNSlog.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TestNSlog.xcodeproj/xcuserdata/yohunl.xcuserdatad/xcschemes/TestNSlog.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /TestNSlog.xcodeproj/xcuserdata/yohunl.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | TestNSlog.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 099A57A31D0E8E17007AFAFE 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /TestNSlog.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestNSlog/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // TestNSlog 4 | // 5 | // Created by lingyohunl on 16/6/13. 6 | // Copyright © 2016年 yohunl. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /TestNSlog/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // TestNSlog 4 | // 5 | // Created by lingyohunl on 16/6/13. 6 | // Copyright © 2016年 yohunl. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "ViewController.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; 21 | ViewController *controller = [[ViewController alloc] init]; 22 | UINavigationController *nava = [[UINavigationController alloc]initWithRootViewController:controller]; 23 | 24 | 25 | [self.window setRootViewController:nava]; 26 | [self.window makeKeyAndVisible]; 27 | return YES; 28 | } 29 | 30 | - (void)applicationWillResignActive:(UIApplication *)application { 31 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 32 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 33 | } 34 | 35 | - (void)applicationDidEnterBackground:(UIApplication *)application { 36 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 37 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 38 | } 39 | 40 | - (void)applicationWillEnterForeground:(UIApplication *)application { 41 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 42 | } 43 | 44 | - (void)applicationDidBecomeActive:(UIApplication *)application { 45 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 46 | } 47 | 48 | - (void)applicationWillTerminate:(UIApplication *)application { 49 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /TestNSlog/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /TestNSlog/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /TestNSlog/HttpServerLogger.h: -------------------------------------------------------------------------------- 1 | // 2 | // HttpServerLogger.h 3 | // TestNSlog 4 | // 5 | // Created by lingyohunl on 16/6/14. 6 | // Copyright © 2016年 yohunl. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HttpServerLogger : NSObject 12 | + (instancetype)shared; 13 | - (void)startServer; 14 | - (void)stopServer; 15 | @end 16 | -------------------------------------------------------------------------------- /TestNSlog/HttpServerLogger.m: -------------------------------------------------------------------------------- 1 | // 2 | // HttpServerLogger.m 3 | // TestNSlog 4 | // 5 | // Created by lingyohunl on 16/6/14. 6 | // Copyright © 2016年 yohunl. All rights reserved. 7 | // 8 | 9 | #import "HttpServerLogger.h" 10 | #import "GCDWebServer.h" 11 | #import "GCDWebServerDataResponse.h" 12 | #import "SystemLogManager.h" 13 | #define kMinRefreshDelay 500 // In milliseconds 14 | @interface HttpServerLogger () 15 | @property (nonatomic,strong) GCDWebServer* webServer; 16 | @end 17 | @implementation HttpServerLogger 18 | 19 | + (instancetype)shared { 20 | static dispatch_once_t onceToken; 21 | static HttpServerLogger *shared; 22 | dispatch_once(&onceToken, ^{ 23 | shared = [HttpServerLogger new]; 24 | }); 25 | return shared; 26 | } 27 | 28 | 29 | - (GCDWebServer *)webServer { 30 | if (!_webServer) { 31 | _webServer = [[GCDWebServer alloc] init]; 32 | __weak __typeof__(self) weakSelf = self; 33 | // Add a handler to respond to GET requests on any URL 34 | [_webServer addDefaultHandlerForMethod:@"GET" 35 | requestClass:[GCDWebServerRequest class] 36 | processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { 37 | return [weakSelf createResponseBody:request]; 38 | 39 | 40 | }]; 41 | 42 | 43 | NSLog(@"Visit %@ in your web browser", _webServer.serverURL); 44 | 45 | } 46 | return _webServer; 47 | } 48 | - (void)startServer{ 49 | // Use convenience method that runs server on port 8080 50 | // until SIGINT (Ctrl-C in Terminal) or SIGTERM is received 51 | [self.webServer startWithPort:8080 bonjourName:nil]; 52 | 53 | } 54 | 55 | - (void)stopServer { 56 | [_webServer stop]; 57 | _webServer = nil; 58 | } 59 | 60 | 61 | - (GCDWebServerDataResponse *)createResponseBody :(GCDWebServerRequest* )request{ 62 | GCDWebServerDataResponse *response = nil; 63 | 64 | NSString* path = request.path; 65 | NSDictionary* query = request.query; 66 | //NSLog(@"path = %@,query = %@",path,query); 67 | NSMutableString* string; 68 | if ([path isEqualToString:@"/"]) { 69 | string = [[NSMutableString alloc] init]; 70 | [string appendString:@""]; 71 | [string appendString:@""]; 72 | [string appendFormat:@"%s[%i]", getprogname(), getpid()]; 73 | [string appendString:@""]; 102 | [string appendFormat:@"", kMinRefreshDelay]; 136 | [string appendString:@""]; 137 | [string appendString:@""]; 138 | [string appendString:@""]; 139 | [self _appendLogRecordsToString:string afterAbsoluteTime:0.0]; 140 | 141 | [string appendString:@"
"]; 142 | [string appendString:@"
"]; 143 | [string appendString:@""]; 144 | [string appendString:@""]; 145 | 146 | 147 | } 148 | else if ([path isEqualToString:@"/log"] && query[@"after"]) { 149 | string = [[NSMutableString alloc] init]; 150 | double time = [query[@"after"] doubleValue]; 151 | [self _appendLogRecordsToString:string afterAbsoluteTime:time]; 152 | 153 | } 154 | else { 155 | string = [@"

无数据

" mutableCopy]; 156 | } 157 | if (string == nil) { 158 | string = [@"" mutableCopy]; 159 | } 160 | response = [GCDWebServerDataResponse responseWithHTML:string]; 161 | return response; 162 | } 163 | 164 | - (void)_appendLogRecordsToString:(NSMutableString*)string afterAbsoluteTime:(double)time { 165 | __block double maxTime = time; 166 | NSArray *allMsg = [SystemLogManager allLogAfterTime:time]; 167 | [allMsg enumerateObjectsUsingBlock:^(SystemLogMessage * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 168 | const char* style = "color: dimgray;"; 169 | NSString* formattedMessage = [self displayedTextForLogMessage:obj]; 170 | [string appendFormat:@"%@", style, formattedMessage]; 171 | if (obj.timeInterval > maxTime) { 172 | maxTime = obj.timeInterval ; 173 | } 174 | }]; 175 | [string appendFormat:@"", maxTime]; 176 | 177 | } 178 | 179 | 180 | - (NSString *)displayedTextForLogMessage:(SystemLogMessage *)msg{ 181 | NSMutableString *string = [[NSMutableString alloc] init]; 182 | [string appendFormat:@"%@ %@ %@",[SystemLogMessage logTimeStringFromDate:msg.date ],msg.sender, msg.messageText]; 183 | return string; 184 | 185 | 186 | } 187 | @end 188 | -------------------------------------------------------------------------------- /TestNSlog/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /TestNSlog/SystemLogManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // SystemLogManager.h 3 | // TestNSlog 4 | // 5 | // Created by lingyohunl on 16/6/14. 6 | // Copyright © 2016年 yohunl. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "SystemLogMessage.h" 12 | @interface SystemLogManager : NSObject 13 | 14 | /** 15 | * 利用ASL提供的接口获取日志 16 | * 17 | * @param time 指定的时间 18 | * 19 | * @return 获取到的日志 20 | */ 21 | + (NSArray *)allLogAfterTime:(CFAbsoluteTime) time; 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /TestNSlog/SystemLogManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // SystemLogManager.m 3 | // TestNSlog 4 | // 5 | // Created by lingyohunl on 16/6/14. 6 | // Copyright © 2016年 yohunl. All rights reserved. 7 | // 8 | 9 | #import "SystemLogManager.h" 10 | 11 | @implementation SystemLogManager 12 | + (NSMutableArray *)allLogMessagesForCurrentProcess 13 | { 14 | asl_object_t query = asl_new(ASL_TYPE_QUERY); 15 | 16 | // Filter for messages from the current process. Note that this appears to happen by default on device, but is required in the simulator. 17 | NSString *pidString = [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]]; 18 | asl_set_query(query, ASL_KEY_PID, [pidString UTF8String], ASL_QUERY_OP_EQUAL); 19 | 20 | aslresponse response = asl_search(NULL, query); 21 | aslmsg aslMessage = NULL; 22 | 23 | NSMutableArray *logMessages = [NSMutableArray array]; 24 | while ((aslMessage = asl_next(response))) { 25 | [logMessages addObject:[SystemLogMessage logMessageFromASLMessage:aslMessage]]; 26 | } 27 | asl_release(response); 28 | 29 | return logMessages; 30 | } 31 | 32 | + (NSArray *)allLogAfterTime:(double) time { 33 | NSMutableArray *allMsg = [self allLogMessagesForCurrentProcess]; 34 | NSArray *filteredLogMessages = [allMsg filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(SystemLogMessage *logMessage, NSDictionary *bindings) { 35 | if (logMessage.timeInterval > time) { 36 | return YES; 37 | } 38 | return NO; 39 | }]]; 40 | 41 | return filteredLogMessages; 42 | 43 | 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /TestNSlog/SystemLogMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // SystemLogMessage.h 3 | // TestNSlog 4 | // 5 | // Created by lingyohunl on 16/6/14. 6 | // Copyright © 2016年 yohunl. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | @interface SystemLogMessage : NSObject 12 | + (instancetype)logMessageFromASLMessage:(aslmsg)aslMessage; 13 | 14 | @property (nonatomic, strong) NSDate *date; 15 | @property (nonatomic, assign) NSTimeInterval timeInterval; 16 | @property (nonatomic, copy) NSString *sender; 17 | @property (nonatomic, copy) NSString *messageText; 18 | @property (nonatomic, assign) long long messageID; 19 | 20 | 21 | 22 | - (NSString *)displayedTextForLogMessage; 23 | + (NSString *)logTimeStringFromDate:(NSDate *)date; 24 | @end 25 | -------------------------------------------------------------------------------- /TestNSlog/SystemLogMessage.m: -------------------------------------------------------------------------------- 1 | // 2 | // SystemLogMessage.m 3 | // TestNSlog 4 | // 5 | // Created by lingyohunl on 16/6/14. 6 | // Copyright © 2016年 yohunl. All rights reserved. 7 | // 8 | 9 | #import "SystemLogMessage.h" 10 | 11 | @implementation SystemLogMessage 12 | +(instancetype)logMessageFromASLMessage:(aslmsg)aslMessage 13 | { 14 | SystemLogMessage *logMessage = [[SystemLogMessage alloc] init]; 15 | 16 | const char *timestamp = asl_get(aslMessage, ASL_KEY_TIME); 17 | if (timestamp) { 18 | NSTimeInterval timeInterval = [@(timestamp) integerValue]; 19 | const char *nanoseconds = asl_get(aslMessage, ASL_KEY_TIME_NSEC); 20 | if (nanoseconds) { 21 | timeInterval += [@(nanoseconds) doubleValue] / NSEC_PER_SEC; 22 | } 23 | logMessage.timeInterval = timeInterval; 24 | logMessage.date = [NSDate dateWithTimeIntervalSince1970:timeInterval]; 25 | } 26 | 27 | const char *sender = asl_get(aslMessage, ASL_KEY_SENDER); 28 | if (sender) { 29 | logMessage.sender = @(sender); 30 | } 31 | 32 | const char *messageText = asl_get(aslMessage, ASL_KEY_MSG); 33 | if (messageText) { 34 | logMessage.messageText = @(messageText); 35 | } 36 | 37 | const char *messageID = asl_get(aslMessage, ASL_KEY_MSG_ID); 38 | if (messageID) { 39 | logMessage.messageID = [@(messageID) longLongValue]; 40 | } 41 | 42 | return logMessage; 43 | } 44 | 45 | - (BOOL)isEqual:(id)object 46 | { 47 | return [object isKindOfClass:[SystemLogMessage class]] && self.messageID == [object messageID]; 48 | } 49 | 50 | - (NSUInteger)hash 51 | { 52 | return (NSUInteger)self.messageID; 53 | } 54 | 55 | 56 | - (NSString *)displayedTextForLogMessage 57 | { 58 | return [NSString stringWithFormat:@"%@: %@", [self.class logTimeStringFromDate:self.date], self.messageText]; 59 | } 60 | 61 | + (NSString *)logTimeStringFromDate:(NSDate *)date 62 | { 63 | static NSDateFormatter *formatter = nil; 64 | static dispatch_once_t onceToken; 65 | dispatch_once(&onceToken, ^{ 66 | formatter = [[NSDateFormatter alloc] init]; 67 | formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS"; 68 | }); 69 | 70 | return [formatter stringFromDate:date]; 71 | } 72 | 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /TestNSlog/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // TestNSlog 4 | // 5 | // Created by lingyohunl on 16/6/13. 6 | // Copyright © 2016年 yohunl. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UITableViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /TestNSlog/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // TestNSlog 4 | // 5 | // Created by lingyohunl on 16/6/13. 6 | // Copyright © 2016年 yohunl. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | #import "GCDWebServer.h" 12 | #import "GCDWebServerDataResponse.h" 13 | #import "HttpServerLogger.h" 14 | 15 | 16 | static NSData* _newlineData = nil; 17 | @interface ViewController () 18 | @property (nonatomic,strong) NSMutableArray *datas; 19 | @property (nonatomic,assign) int originalStderrHandle; 20 | @property (nonatomic,strong) NSString *myLogPath; 21 | @property (nonatomic,assign) int mylogHandle; 22 | @property (nonatomic,strong) dispatch_source_t sourt_t; 23 | @property (nonatomic,strong) dispatch_source_t sourt_t2; 24 | 25 | @property (nonatomic,strong) UIButton *rightItemBtn; 26 | @end 27 | 28 | @implementation ViewController 29 | 30 | - (void)viewDidLoad { 31 | [super viewDidLoad]; 32 | NSLog(@"ViewController viewDidLoad"); 33 | 34 | 35 | fprintf (stderr, "%s\n", "ViewController viewDidLoad222"); 36 | 37 | _rightItemBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 38 | [_rightItemBtn setTitle:@"开启服务" forState:UIControlStateNormal]; 39 | [_rightItemBtn addTarget:self action:@selector(rightItemBtnAction:) forControlEvents:UIControlEventTouchUpInside]; 40 | _rightItemBtn.frame = CGRectMake(0, 0, 60, 30); 41 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:_rightItemBtn]; 42 | 43 | 44 | NSLog(@"ViewController viewDidLoad222"); 45 | 46 | //[self observerSteerr]; 47 | _datas = [@[@"第1行",@"第2行",@"第3行",@"第4行",@"第5行",@"第6行",@"第7行",@"第8行",@"第9行",@"第10行",@"第11行",@"第12行"] mutableCopy]; 48 | [self.tableView registerClass:UITableViewCell.class forCellReuseIdentifier:@"myviewcell"]; 49 | 50 | } 51 | 52 | - (void)rightItemBtnAction :(UIButton *)sender { 53 | NSString *text = [sender titleForState:UIControlStateNormal]; 54 | if ([text isEqualToString:@"开启服务"]) { 55 | [[HttpServerLogger shared]startServer]; 56 | [sender setTitle:@"关闭服务" forState:UIControlStateNormal]; 57 | } 58 | else{ 59 | [[HttpServerLogger shared]stopServer]; 60 | [sender setTitle:@"开启服务" forState:UIControlStateNormal]; 61 | } 62 | } 63 | 64 | 65 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 66 | return self.datas.count; 67 | } 68 | 69 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 70 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"myviewcell"]; 71 | cell.textLabel.text = self.datas[indexPath.row]; 72 | return cell; 73 | } 74 | 75 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 76 | NSString *str = [NSString stringWithFormat:@"didSelectRowAtIndexPath index:%@",indexPath]; 77 | NSLog(@"didSelectRowAtIndexPath index:%@",indexPath); 78 | printf("didSelectRowAtIndexPath"); 79 | if (indexPath.row % 2 == 0) { 80 | 81 | } 82 | 83 | 84 | //需要写入的字符串 85 | // NSString *str= @"iPhoneDeveloper Tips\nhttp://iPhoneDevelopTips,com"; 86 | //写入文件 87 | //char *mystr = [str UTF8String]; 88 | //ssize_t size = write(_mylogHandle, mystr, strlen(mystr)); 89 | 90 | //[str writeToFile:_myLogPath atomically:YES encoding:NSUTF8StringEncoding error:nil]; 91 | } 92 | 93 | - (void)redirectNSLog { 94 | _originalStderrHandle = dup(STDERR_FILENO); 95 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 96 | NSString *documentsPath = [paths objectAtIndex:0]; 97 | NSString *loggingPath = [documentsPath stringByAppendingPathComponent:@"/mylog.log"]; 98 | _myLogPath = loggingPath; 99 | NSLog(@"loggingPath:%@",loggingPath); 100 | freopen([loggingPath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr); 101 | 102 | 103 | 104 | 105 | } 106 | 107 | - (void)restoreNSLog { 108 | 109 | dup2(_originalStderrHandle, STDERR_FILENO); 110 | } 111 | 112 | - (void)observerSteerr { 113 | 114 | 115 | 116 | NSFileHandle* fh = [NSFileHandle fileHandleForReadingAtPath:_myLogPath]; 117 | int filehandle = fh.fileDescriptor; 118 | //fcntl(filehandle, F_SETEL,0_NONBLOCK); 119 | dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 120 | //dispatch_source_t source =dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, STDERR_FILENO, 0, dispatch_get_main_queue()); 121 | dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, 122 | filehandle, 123 | 0, 124 | globalQueue); 125 | dispatch_source_set_event_handler(source,^{ 126 | //NSLog(@"监听函数:%lu",dispatch_source_get_data(source)); 127 | char buf[1024]; 128 | ssize_t len = read(filehandle, (void*)buf, (size_t)(sizeof(buf))); 129 | //NSString *string = [[NSString alloc]initWithUTF8String:buf]; 130 | if(len > 0) 131 | NSLog(@"Got data from stdin: %.*s", len, buf); 132 | }); 133 | dispatch_resume(source); 134 | 135 | } 136 | 137 | - (void)createFile{ 138 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 139 | NSString *documentsPath = [paths objectAtIndex:0]; 140 | NSString *loggingPath = [documentsPath stringByAppendingPathComponent:@"/mylog.log"]; 141 | _myLogPath = loggingPath; 142 | //查找文件,如果不存在,就创建一个文件 143 | NSFileManager *fileManager = [NSFileManager defaultManager]; 144 | if (![fileManager fileExistsAtPath:_myLogPath]) { 145 | 146 | [fileManager createFileAtPath:_myLogPath contents:nil attributes:nil]; 147 | 148 | 149 | } 150 | NSLog(@"loggingPath:%@",loggingPath); 151 | NSString *str = @"lingdaipinglingdaipingsjfljslajflksadjf jsafjlasdjfasdj jfasjflkjaslkjflsajljflsadjfiegjkdsljfkljalfjlsdajfj sdaljflksdajfjasdljflj"; 152 | [str writeToFile:_myLogPath atomically:YES encoding:NSUTF8StringEncoding error:nil]; 153 | //_mylogHandle = open([loggingPath UTF8String], O_RDWR); 154 | //write(_mylogHandle, "fdjfldjlfjldjfldjfl", 18); 155 | //_sourt_t2 = [self processContentsOfFile:[loggingPath UTF8String]]; 156 | _sourt_t2 = [self _startCapturingWritingToFD:_mylogHandle]; 157 | } 158 | 159 | //- (void)test11 { 160 | // dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue()); 161 | // 162 | //// dispatch_source_set_event_handler(source, ^{ 163 | //// [progressIndicator incrementBy:dispatch_source_get_data(source)]; 164 | //// }); 165 | //// dispatch_resume(source); 166 | //// 167 | //// dispatch_apply([array count], globalQueue, ^(size_t index) { 168 | //// [self doWorkOnItem:obj:[array objectAtIndex:index]]; 169 | //// dispatch_source_merge_data(source, 1); 170 | //// }); 171 | //} 172 | 173 | 174 | - (dispatch_source_t )processContentsOfFile:(const char* )filename 175 | { 176 | // Prepare the file for reading. 177 | int fd = open(filename, O_RDONLY); 178 | _mylogHandle = fd; 179 | if (fd == -1) 180 | return NULL; 181 | fcntl(fd, F_SETFL, O_NONBLOCK); // Avoid blocking the read operation 182 | dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 183 | dispatch_source_t readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, queue); 184 | if (!readSource) 185 | { 186 | close(fd); 187 | return NULL; 188 | } 189 | 190 | // Install the event handler 191 | dispatch_source_set_event_handler(readSource, ^{ 192 | size_t estimated = dispatch_source_get_data(readSource) + 1; 193 | // Read the data into a text buffer. 194 | char* buffer = (char*)malloc(estimated); 195 | if (buffer) 196 | { 197 | ssize_t actual = read(fd, buffer, (estimated)); 198 | //Boolean done = MyProcessFileData(buffer, actual); // Process the data. 199 | NSLog(@"Got data from stdin: %.*s", actual, buffer); 200 | // Release the buffer when done. 201 | free(buffer); 202 | // If there is no more data, cancel the source. 203 | //if (done) 204 | // dispatch_source_cancel(readSource); 205 | } 206 | }); 207 | 208 | // Install the cancellation handler 209 | dispatch_source_set_cancel_handler(readSource, ^{close(fd);}); 210 | // Start reading the file. 211 | dispatch_resume(readSource); 212 | return readSource; 213 | } 214 | 215 | 216 | - (dispatch_source_t)_startCapturingWritingToFD:(int)fd { 217 | 218 | int fildes[2]; 219 | pipe(fildes); // [0] is read end of pipe while [1] is write end 220 | dup2(fildes[1], fd); // Duplicate write end of pipe "onto" fd (this closes fd) 221 | close(fildes[1]); // Close original write end of pipe 222 | fd = fildes[0]; // We can now monitor the read end of the pipe 223 | 224 | char* buffer = malloc(1024); 225 | NSMutableData* data = [[NSMutableData alloc] init]; 226 | fcntl(fd, F_SETFL, O_NONBLOCK); 227 | dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)); 228 | dispatch_source_set_cancel_handler(source, ^{ 229 | free(buffer); 230 | }); 231 | dispatch_source_set_event_handler(source, ^{ 232 | @autoreleasepool { 233 | 234 | while (1) { 235 | ssize_t size = read(fd, buffer, 1024); 236 | if (size <= 0) { 237 | break; 238 | } 239 | [data appendBytes:buffer length:size]; 240 | if (size < 1024) { 241 | break; 242 | } 243 | } 244 | NSString *aString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 245 | //printf("aString = %s",[aString UTF8String]); 246 | //NSLog(@"aString = %@",aString); 247 | //读到了日志,可以进行我们需要的各种操作了 248 | 249 | } 250 | }); 251 | dispatch_resume(source); 252 | return source; 253 | } 254 | 255 | 256 | @end 257 | -------------------------------------------------------------------------------- /TestNSlog/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TestNSlog 4 | // 5 | // Created by lingyohunl on 16/6/13. 6 | // Copyright © 2016年 yohunl. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | --------------------------------------------------------------------------------