cordova-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From shaz...@apache.org
Subject [52/57] [abbrv] cordova-plugins git commit: Merge commit '394cfb12f80de35255a506c0dcbf4a21910e849a'
Date Mon, 25 Jul 2016 07:57:38 GMT
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/36f1a43e/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerConnection.m
----------------------------------------------------------------------
diff --cc local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerConnection.m
index d4e3f39,0000000..d6c369e
mode 100644,000000..100644
--- a/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerConnection.m
+++ b/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerConnection.m
@@@ -1,845 -1,0 +1,851 @@@
 +/*
-  Copyright (c) 2012-2014, Pierre-Olivier Latour
++ Copyright (c) 2012-2015, Pierre-Olivier Latour
 + All rights reserved.
 + 
 + Redistribution and use in source and binary forms, with or without
 + modification, are permitted provided that the following conditions are met:
 + * Redistributions of source code must retain the above copyright
 + notice, this list of conditions and the following disclaimer.
 + * Redistributions in binary form must reproduce the above copyright
 + notice, this list of conditions and the following disclaimer in the
 + documentation and/or other materials provided with the distribution.
 + * The name of Pierre-Olivier Latour may not be used to endorse
 + or promote products derived from this software without specific
 + prior written permission.
 + 
 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 + DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
 + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 + */
 +
 +#if !__has_feature(objc_arc)
 +#error GCDWebServer requires ARC
 +#endif
 +
 +#import <TargetConditionals.h>
 +#import <netdb.h>
 +#ifdef __GCDWEBSERVER_ENABLE_TESTING__
 +#import <libkern/OSAtomic.h>
 +#endif
 +
 +#import "GCDWebServerPrivate.h"
 +
 +#define kHeadersReadCapacity (1 * 1024)
 +#define kBodyReadCapacity (256 * 1024)
 +
 +typedef void (^ReadDataCompletionBlock)(BOOL success);
 +typedef void (^ReadHeadersCompletionBlock)(NSData* extraData);
 +typedef void (^ReadBodyCompletionBlock)(BOOL success);
 +
 +typedef void (^WriteDataCompletionBlock)(BOOL success);
 +typedef void (^WriteHeadersCompletionBlock)(BOOL success);
 +typedef void (^WriteBodyCompletionBlock)(BOOL success);
 +
 +static NSData* _CRLFData = nil;
 +static NSData* _CRLFCRLFData = nil;
 +static NSData* _continueData = nil;
 +static NSData* _lastChunkData = nil;
 +static NSString* _digestAuthenticationNonce = nil;
 +#ifdef __GCDWEBSERVER_ENABLE_TESTING__
 +static int32_t _connectionCounter = 0;
 +#endif
 +
 +@interface GCDWebServerConnection () {
 +@private
 +  GCDWebServer* _server;
 +  NSData* _localAddress;
 +  NSData* _remoteAddress;
 +  CFSocketNativeHandle _socket;
 +  NSUInteger _bytesRead;
 +  NSUInteger _bytesWritten;
 +  BOOL _virtualHEAD;
 +  
 +  CFHTTPMessageRef _requestMessage;
 +  GCDWebServerRequest* _request;
 +  GCDWebServerHandler* _handler;
 +  CFHTTPMessageRef _responseMessage;
 +  GCDWebServerResponse* _response;
 +  NSInteger _statusCode;
 +  
 +  BOOL _opened;
 +#ifdef __GCDWEBSERVER_ENABLE_TESTING__
 +  NSUInteger _connectionIndex;
 +  NSString* _requestPath;
 +  int _requestFD;
 +  NSString* _responsePath;
 +  int _responseFD;
 +#endif
 +}
 +@end
 +
 +@implementation GCDWebServerConnection (Read)
 +
 +- (void)_readData:(NSMutableData*)data withLength:(NSUInteger)length completionBlock:(ReadDataCompletionBlock)block {
 +  dispatch_read(_socket, length, kGCDWebServerGCDQueue, ^(dispatch_data_t buffer, int error) {
 +    
 +    @autoreleasepool {
 +      if (error == 0) {
 +        size_t size = dispatch_data_get_size(buffer);
 +        if (size > 0) {
 +          NSUInteger originalLength = data.length;
 +          dispatch_data_apply(buffer, ^bool(dispatch_data_t region, size_t chunkOffset, const void* chunkBytes, size_t chunkSize) {
 +            [data appendBytes:chunkBytes length:chunkSize];
 +            return true;
 +          });
 +          [self didReadBytes:((char*)data.bytes + originalLength) length:(data.length - originalLength)];
 +          block(YES);
 +        } else {
 +          if (_bytesRead > 0) {
 +            GWS_LOG_ERROR(@"No more data available on socket %i", _socket);
 +          } else {
 +            GWS_LOG_WARNING(@"No data received from socket %i", _socket);
 +          }
 +          block(NO);
 +        }
 +      } else {
 +        GWS_LOG_ERROR(@"Error while reading from socket %i: %s (%i)", _socket, strerror(error), error);
 +        block(NO);
 +      }
 +    }
 +    
 +  });
 +}
 +
 +- (void)_readHeaders:(NSMutableData*)headersData withCompletionBlock:(ReadHeadersCompletionBlock)block {
 +  GWS_DCHECK(_requestMessage);
 +  [self _readData:headersData withLength:NSUIntegerMax completionBlock:^(BOOL success) {
 +    
 +    if (success) {
 +      NSRange range = [headersData rangeOfData:_CRLFCRLFData options:0 range:NSMakeRange(0, headersData.length)];
 +      if (range.location == NSNotFound) {
 +        [self _readHeaders:headersData withCompletionBlock:block];
 +      } else {
 +        NSUInteger length = range.location + range.length;
 +        if (CFHTTPMessageAppendBytes(_requestMessage, headersData.bytes, length)) {
 +          if (CFHTTPMessageIsHeaderComplete(_requestMessage)) {
 +            block([headersData subdataWithRange:NSMakeRange(length, headersData.length - length)]);
 +          } else {
 +            GWS_LOG_ERROR(@"Failed parsing request headers from socket %i", _socket);
 +            block(nil);
 +          }
 +        } else {
 +          GWS_LOG_ERROR(@"Failed appending request headers data from socket %i", _socket);
 +          block(nil);
 +        }
 +      }
 +    } else {
 +      block(nil);
 +    }
 +    
 +  }];
 +}
 +
 +- (void)_readBodyWithRemainingLength:(NSUInteger)length completionBlock:(ReadBodyCompletionBlock)block {
 +  GWS_DCHECK([_request hasBody] && ![_request usesChunkedTransferEncoding]);
 +  NSMutableData* bodyData = [[NSMutableData alloc] initWithCapacity:kBodyReadCapacity];
 +  [self _readData:bodyData withLength:length completionBlock:^(BOOL success) {
 +    
 +    if (success) {
 +      if (bodyData.length <= length) {
 +        NSError* error = nil;
 +        if ([_request performWriteData:bodyData error:&error]) {
 +          NSUInteger remainingLength = length - bodyData.length;
 +          if (remainingLength) {
 +            [self _readBodyWithRemainingLength:remainingLength completionBlock:block];
 +          } else {
 +            block(YES);
 +          }
 +        } else {
 +          GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error);
 +          block(NO);
 +        }
 +      } else {
 +        GWS_LOG_ERROR(@"Unexpected extra content reading request body on socket %i", _socket);
 +        block(NO);
 +        GWS_DNOT_REACHED();
 +      }
 +    } else {
 +      block(NO);
 +    }
 +    
 +  }];
 +}
 +
 +static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
 +  char buffer[size + 1];
 +  bcopy(bytes, buffer, size);
 +  buffer[size] = 0;
 +  char* end = NULL;
 +  long result = strtol(buffer, &end, 16);
 +  return ((end != NULL) && (*end == 0) && (result >= 0) ? result : NSNotFound);
 +}
 +
 +- (void)_readNextBodyChunk:(NSMutableData*)chunkData completionBlock:(ReadBodyCompletionBlock)block {
 +  GWS_DCHECK([_request hasBody] && [_request usesChunkedTransferEncoding]);
 +  
 +  while (1) {
 +    NSRange range = [chunkData rangeOfData:_CRLFData options:0 range:NSMakeRange(0, chunkData.length)];
 +    if (range.location == NSNotFound) {
 +      break;
 +    }
 +    NSRange extensionRange = [chunkData rangeOfData:[NSData dataWithBytes:";" length:1] options:0 range:NSMakeRange(0, range.location)];  // Ignore chunk extensions
 +    NSUInteger length = _ScanHexNumber((char*)chunkData.bytes, extensionRange.location != NSNotFound ? extensionRange.location : range.location);
 +    if (length != NSNotFound) {
 +      if (length) {
 +        if (chunkData.length < range.location + range.length + length + 2) {
 +          break;
 +        }
 +        const char* ptr = (char*)chunkData.bytes + range.location + range.length + length;
 +        if ((*ptr == '\r') && (*(ptr + 1) == '\n')) {
 +          NSError* error = nil;
 +          if ([_request performWriteData:[chunkData subdataWithRange:NSMakeRange(range.location + range.length, length)] error:&error]) {
 +            [chunkData replaceBytesInRange:NSMakeRange(0, range.location + range.length + length + 2) withBytes:NULL length:0];
 +          } else {
 +            GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error);
 +            block(NO);
 +            return;
 +          }
 +        } else {
 +          GWS_LOG_ERROR(@"Missing terminating CRLF sequence for chunk reading request body on socket %i", _socket);
 +          block(NO);
 +          return;
 +        }
 +      } else {
 +        NSRange trailerRange = [chunkData rangeOfData:_CRLFCRLFData options:0 range:NSMakeRange(range.location, chunkData.length - range.location)];  // Ignore trailers
 +        if (trailerRange.location != NSNotFound) {
 +          block(YES);
 +          return;
 +        }
 +      }
 +    } else {
 +      GWS_LOG_ERROR(@"Invalid chunk length reading request body on socket %i", _socket);
 +      block(NO);
 +      return;
 +    }
 +  }
 +  
 +  [self _readData:chunkData withLength:NSUIntegerMax completionBlock:^(BOOL success) {
 +    
 +    if (success) {
 +      [self _readNextBodyChunk:chunkData completionBlock:block];
 +    } else {
 +      block(NO);
 +    }
 +    
 +  }];
 +}
 +
 +@end
 +
 +@implementation GCDWebServerConnection (Write)
 +
 +- (void)_writeData:(NSData*)data withCompletionBlock:(WriteDataCompletionBlock)block {
 +  dispatch_data_t buffer = dispatch_data_create(data.bytes, data.length, kGCDWebServerGCDQueue, ^{
 +    [data self];  // Keeps ARC from releasing data too early
 +  });
 +  dispatch_write(_socket, buffer, kGCDWebServerGCDQueue, ^(dispatch_data_t remainingData, int error) {
 +    
 +    @autoreleasepool {
 +      if (error == 0) {
 +        GWS_DCHECK(remainingData == NULL);
 +        [self didWriteBytes:data.bytes length:data.length];
 +        block(YES);
 +      } else {
 +        GWS_LOG_ERROR(@"Error while writing to socket %i: %s (%i)", _socket, strerror(error), error);
 +        block(NO);
 +      }
 +    }
 +    
 +  });
 +#if !OS_OBJECT_USE_OBJC_RETAIN_RELEASE
 +  dispatch_release(buffer);
 +#endif
 +}
 +
 +- (void)_writeHeadersWithCompletionBlock:(WriteHeadersCompletionBlock)block {
 +  GWS_DCHECK(_responseMessage);
 +  CFDataRef data = CFHTTPMessageCopySerializedMessage(_responseMessage);
 +  [self _writeData:(__bridge NSData*)data withCompletionBlock:block];
 +  CFRelease(data);
 +}
 +
 +- (void)_writeBodyWithCompletionBlock:(WriteBodyCompletionBlock)block {
 +  GWS_DCHECK([_response hasBody]);
 +  [_response performReadDataWithCompletion:^(NSData* data, NSError* error) {
 +    
 +    if (data) {
 +      if (data.length) {
 +        if (_response.usesChunkedTransferEncoding) {
 +          const char* hexString = [[NSString stringWithFormat:@"%lx", (unsigned long)data.length] UTF8String];
 +          size_t hexLength = strlen(hexString);
 +          NSData* chunk = [NSMutableData dataWithLength:(hexLength + 2 + data.length + 2)];
 +          if (chunk == nil) {
 +            GWS_LOG_ERROR(@"Failed allocating memory for response body chunk for socket %i: %@", _socket, error);
 +            block(NO);
 +            return;
 +          }
 +          char* ptr = (char*)[(NSMutableData*)chunk mutableBytes];
 +          bcopy(hexString, ptr, hexLength);
 +          ptr += hexLength;
 +          *ptr++ = '\r';
 +          *ptr++ = '\n';
 +          bcopy(data.bytes, ptr, data.length);
 +          ptr += data.length;
 +          *ptr++ = '\r';
 +          *ptr = '\n';
 +          data = chunk;
 +        }
 +        [self _writeData:data withCompletionBlock:^(BOOL success) {
 +          
 +          if (success) {
 +            [self _writeBodyWithCompletionBlock:block];
 +          } else {
 +            block(NO);
 +          }
 +          
 +        }];
 +      } else {
 +        if (_response.usesChunkedTransferEncoding) {
 +          [self _writeData:_lastChunkData withCompletionBlock:^(BOOL success) {
 +            
 +            block(success);
 +            
 +          }];
 +        } else {
 +          block(YES);
 +        }
 +      }
 +    } else {
 +      GWS_LOG_ERROR(@"Failed reading response body for socket %i: %@", _socket, error);
 +      block(NO);
 +    }
 +    
 +  }];
 +}
 +
 +@end
 +
 +@implementation GCDWebServerConnection
 +
 +@synthesize server=_server, localAddressData=_localAddress, remoteAddressData=_remoteAddress, totalBytesRead=_bytesRead, totalBytesWritten=_bytesWritten;
 +
 ++ (void)initialize {
 +  if (_CRLFData == nil) {
 +    _CRLFData = [[NSData alloc] initWithBytes:"\r\n" length:2];
 +    GWS_DCHECK(_CRLFData);
 +  }
 +  if (_CRLFCRLFData == nil) {
 +    _CRLFCRLFData = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4];
 +    GWS_DCHECK(_CRLFCRLFData);
 +  }
 +  if (_continueData == nil) {
 +    CFHTTPMessageRef message = CFHTTPMessageCreateResponse(kCFAllocatorDefault, 100, NULL, kCFHTTPVersion1_1);
 +    _continueData = CFBridgingRelease(CFHTTPMessageCopySerializedMessage(message));
 +    CFRelease(message);
 +    GWS_DCHECK(_continueData);
 +  }
 +  if (_lastChunkData == nil) {
 +    _lastChunkData = [[NSData alloc] initWithBytes:"0\r\n\r\n" length:5];
 +  }
 +  if (_digestAuthenticationNonce == nil) {
 +    CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
 +    _digestAuthenticationNonce = GCDWebServerComputeMD5Digest(@"%@", CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuid)));
 +    CFRelease(uuid);
 +  }
 +}
 +
 +- (BOOL)isUsingIPv6 {
 +  const struct sockaddr* localSockAddr = _localAddress.bytes;
 +  return (localSockAddr->sa_family == AF_INET6);
 +}
 +
 +- (void)_initializeResponseHeadersWithStatusCode:(NSInteger)statusCode {
 +  _statusCode = statusCode;
 +  _responseMessage = CFHTTPMessageCreateResponse(kCFAllocatorDefault, statusCode, NULL, kCFHTTPVersion1_1);
 +  CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Connection"), CFSTR("Close"));
 +  CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Server"), (__bridge CFStringRef)_server.serverName);
 +  CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Date"), (__bridge CFStringRef)GCDWebServerFormatRFC822([NSDate date]));
 +}
 +
 +- (void)_startProcessingRequest {
 +  GWS_DCHECK(_responseMessage == NULL);
 +  
 +  GCDWebServerResponse* preflightResponse = [self preflightRequest:_request];
 +  if (preflightResponse) {
 +    [self _finishProcessingRequest:preflightResponse];
 +  } else {
 +    [self processRequest:_request completion:^(GCDWebServerResponse* processResponse) {
 +      [self _finishProcessingRequest:processResponse];
 +    }];
 +  }
 +}
 +
 +// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
 +- (void)_finishProcessingRequest:(GCDWebServerResponse*)response {
 +  GWS_DCHECK(_responseMessage == NULL);
 +  BOOL hasBody = NO;
 +  
 +  if (response) {
 +    response = [self overrideResponse:response forRequest:_request];
 +  }
 +  if (response) {
 +    if ([response hasBody]) {
 +      [response prepareForReading];
 +      hasBody = !_virtualHEAD;
 +    }
 +    NSError* error = nil;
 +    if (hasBody && ![response performOpen:&error]) {
 +      GWS_LOG_ERROR(@"Failed opening response body for socket %i: %@", _socket, error);
 +    } else {
 +      _response = response;
 +    }
 +  }
 +  
 +  if (_response) {
 +    [self _initializeResponseHeadersWithStatusCode:_response.statusCode];
 +    if (_response.lastModifiedDate) {
 +      CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Last-Modified"), (__bridge CFStringRef)GCDWebServerFormatRFC822(_response.lastModifiedDate));
 +    }
 +    if (_response.eTag) {
 +      CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("ETag"), (__bridge CFStringRef)_response.eTag);
 +    }
 +    if ((_response.statusCode >= 200) && (_response.statusCode < 300)) {
 +      if (_response.cacheControlMaxAge > 0) {
 +        CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Cache-Control"), (__bridge CFStringRef)[NSString stringWithFormat:@"max-age=%i, public", (int)_response.cacheControlMaxAge]);
 +      } else {
 +        CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Cache-Control"), CFSTR("no-cache"));
 +      }
 +    }
 +    if (_response.contentType != nil) {
 +      CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Content-Type"), (__bridge CFStringRef)GCDWebServerNormalizeHeaderValue(_response.contentType));
 +    }
 +    if (_response.contentLength != NSUIntegerMax) {
 +      CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Content-Length"), (__bridge CFStringRef)[NSString stringWithFormat:@"%lu", (unsigned long)_response.contentLength]);
 +    }
 +    if (_response.usesChunkedTransferEncoding) {
 +      CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Transfer-Encoding"), CFSTR("chunked"));
 +    }
 +    [_response.additionalHeaders enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL* stop) {
 +      CFHTTPMessageSetHeaderFieldValue(_responseMessage, (__bridge CFStringRef)key, (__bridge CFStringRef)obj);
 +    }];
 +    [self _writeHeadersWithCompletionBlock:^(BOOL success) {
 +      
 +      if (success) {
 +        if (hasBody) {
 +          [self _writeBodyWithCompletionBlock:^(BOOL successInner) {
 +            
 +            [_response performClose];  // TODO: There's nothing we can do on failure as headers have already been sent
 +            
 +          }];
 +        }
 +      } else if (hasBody) {
 +        [_response performClose];
 +      }
 +      
 +    }];
 +  } else {
 +    [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
 +  }
 +  
 +}
 +
 +- (void)_readBodyWithLength:(NSUInteger)length initialData:(NSData*)initialData {
 +  NSError* error = nil;
 +  if (![_request performOpen:&error]) {
 +    GWS_LOG_ERROR(@"Failed opening request body for socket %i: %@", _socket, error);
 +    [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
 +    return;
 +  }
 +  
 +  if (initialData.length) {
 +    if (![_request performWriteData:initialData error:&error]) {
 +      GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error);
 +      if (![_request performClose:&error]) {
 +        GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error);
 +      }
 +      [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
 +      return;
 +    }
 +    length -= initialData.length;
 +  }
 +  
 +  if (length) {
 +    [self _readBodyWithRemainingLength:length completionBlock:^(BOOL success) {
 +      
 +      NSError* localError = nil;
 +      if ([_request performClose:&localError]) {
 +        [self _startProcessingRequest];
 +      } else {
 +        GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error);
 +        [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
 +      }
 +      
 +    }];
 +  } else {
 +    if ([_request performClose:&error]) {
 +      [self _startProcessingRequest];
 +    } else {
 +      GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error);
 +      [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
 +    }
 +  }
 +}
 +
 +- (void)_readChunkedBodyWithInitialData:(NSData*)initialData {
 +  NSError* error = nil;
 +  if (![_request performOpen:&error]) {
 +    GWS_LOG_ERROR(@"Failed opening request body for socket %i: %@", _socket, error);
 +    [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
 +    return;
 +  }
 +  
 +  NSMutableData* chunkData = [[NSMutableData alloc] initWithData:initialData];
 +  [self _readNextBodyChunk:chunkData completionBlock:^(BOOL success) {
 +  
 +    NSError* localError = nil;
 +    if ([_request performClose:&localError]) {
 +      [self _startProcessingRequest];
 +    } else {
 +      GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error);
 +      [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
 +    }
 +    
 +  }];
 +}
 +
 +- (void)_readRequestHeaders {
 +  _requestMessage = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, true);
 +  NSMutableData* headersData = [[NSMutableData alloc] initWithCapacity:kHeadersReadCapacity];
 +  [self _readHeaders:headersData withCompletionBlock:^(NSData* extraData) {
 +    
 +    if (extraData) {
 +      NSString* requestMethod = CFBridgingRelease(CFHTTPMessageCopyRequestMethod(_requestMessage));  // Method verbs are case-sensitive and uppercase
 +      if (_server.shouldAutomaticallyMapHEADToGET && [requestMethod isEqualToString:@"HEAD"]) {
 +        requestMethod = @"GET";
 +        _virtualHEAD = YES;
 +      }
 +      NSDictionary* requestHeaders = CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(_requestMessage));  // Header names are case-insensitive but CFHTTPMessageCopyAllHeaderFields() will standardize the common ones
 +      NSURL* requestURL = CFBridgingRelease(CFHTTPMessageCopyRequestURL(_requestMessage));
 +      if (requestURL) {
 +        requestURL = [self rewriteRequestURL:requestURL withMethod:requestMethod headers:requestHeaders];
 +        GWS_DCHECK(requestURL);
 +      }
 +      NSString* requestPath = requestURL ? GCDWebServerUnescapeURLString(CFBridgingRelease(CFURLCopyPath((CFURLRef)requestURL))) : nil;  // Don't use -[NSURL path] which strips the ending slash
 +      NSString* queryString = requestURL ? CFBridgingRelease(CFURLCopyQueryString((CFURLRef)requestURL, NULL)) : nil;  // Don't use -[NSURL query] to make sure query is not unescaped;
 +      NSDictionary* requestQuery = queryString ? GCDWebServerParseURLEncodedForm(queryString) : @{};
 +      if (requestMethod && requestURL && requestHeaders && requestPath && requestQuery) {
 +        for (_handler in _server.handlers) {
 +          _request = _handler.matchBlock(requestMethod, requestURL, requestHeaders, requestPath, requestQuery);
 +          if (_request) {
 +            break;
 +          }
 +        }
 +        if (_request) {
++          _request.localAddressData = self.localAddressData;
++          _request.remoteAddressData = self.remoteAddressData;
 +          if ([_request hasBody]) {
 +            [_request prepareForWriting];
 +            if (_request.usesChunkedTransferEncoding || (extraData.length <= _request.contentLength)) {
 +              NSString* expectHeader = [requestHeaders objectForKey:@"Expect"];
 +              if (expectHeader) {
 +                if ([expectHeader caseInsensitiveCompare:@"100-continue"] == NSOrderedSame) {  // TODO: Actually validate request before continuing
 +                  [self _writeData:_continueData withCompletionBlock:^(BOOL success) {
 +                    
 +                    if (success) {
 +                      if (_request.usesChunkedTransferEncoding) {
 +                        [self _readChunkedBodyWithInitialData:extraData];
 +                      } else {
 +                        [self _readBodyWithLength:_request.contentLength initialData:extraData];
 +                      }
 +                    }
 +                    
 +                  }];
 +                } else {
 +                  GWS_LOG_ERROR(@"Unsupported 'Expect' / 'Content-Length' header combination on socket %i", _socket);
 +                  [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_ExpectationFailed];
 +                }
 +              } else {
 +                if (_request.usesChunkedTransferEncoding) {
 +                  [self _readChunkedBodyWithInitialData:extraData];
 +                } else {
 +                  [self _readBodyWithLength:_request.contentLength initialData:extraData];
 +                }
 +              }
 +            } else {
 +              GWS_LOG_ERROR(@"Unexpected 'Content-Length' header value on socket %i", _socket);
 +              [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_BadRequest];
 +            }
 +          } else {
 +            [self _startProcessingRequest];
 +          }
 +        } else {
 +          _request = [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:requestPath query:requestQuery];
 +          GWS_DCHECK(_request);
 +          [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_MethodNotAllowed];
 +        }
 +      } else {
 +        [self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
 +        GWS_DNOT_REACHED();
 +      }
 +    } else {
 +      [self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
 +    }
 +    
 +  }];
 +}
 +
 +- (id)initWithServer:(GCDWebServer*)server localAddress:(NSData*)localAddress remoteAddress:(NSData*)remoteAddress socket:(CFSocketNativeHandle)socket {
 +  if ((self = [super init])) {
 +    _server = server;
 +    _localAddress = localAddress;
 +    _remoteAddress = remoteAddress;
 +    _socket = socket;
 +    GWS_LOG_DEBUG(@"Did open connection on socket %i", _socket);
 +    
 +    [_server willStartConnection:self];
 +    
 +    if (![self open]) {
 +      close(_socket);
 +      return nil;
 +    }
 +    _opened = YES;
 +    
 +    [self _readRequestHeaders];
 +  }
 +  return self;
 +}
 +
 +- (NSString*)localAddressString {
 +  return GCDWebServerStringFromSockAddr(_localAddress.bytes, YES);
 +}
 +
 +- (NSString*)remoteAddressString {
 +  return GCDWebServerStringFromSockAddr(_remoteAddress.bytes, YES);
 +}
 +
 +- (void)dealloc {
 +  int result = close(_socket);
 +  if (result != 0) {
 +    GWS_LOG_ERROR(@"Failed closing socket %i for connection: %s (%i)", _socket, strerror(errno), errno);
 +  } else {
 +    GWS_LOG_DEBUG(@"Did close connection on socket %i", _socket);
 +  }
 +  
 +  if (_opened) {
 +    [self close];
 +  }
 +  
 +  [_server didEndConnection:self];
 +  
 +  if (_requestMessage) {
 +    CFRelease(_requestMessage);
 +  }
 +  
 +  if (_responseMessage) {
 +    CFRelease(_responseMessage);
 +  }
 +}
 +
 +@end
 +
 +@implementation GCDWebServerConnection (Subclassing)
 +
 +- (BOOL)open {
 +#ifdef __GCDWEBSERVER_ENABLE_TESTING__
 +  if (_server.recordingEnabled) {
 +    _connectionIndex = OSAtomicIncrement32(&_connectionCounter);
 +    
 +    _requestPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];
 +    _requestFD = open([_requestPath fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
 +    GWS_DCHECK(_requestFD > 0);
 +    
 +    _responsePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];
 +    _responseFD = open([_responsePath fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
 +    GWS_DCHECK(_responseFD > 0);
 +  }
 +#endif
 +  
 +  return YES;
 +}
 +
 +- (void)didReadBytes:(const void*)bytes length:(NSUInteger)length {
 +  GWS_LOG_DEBUG(@"Connection received %lu bytes on socket %i", (unsigned long)length, _socket);
 +  _bytesRead += length;
 +  
 +#ifdef __GCDWEBSERVER_ENABLE_TESTING__
 +  if ((_requestFD > 0) && (write(_requestFD, bytes, length) != (ssize_t)length)) {
 +    GWS_LOG_ERROR(@"Failed recording request data: %s (%i)", strerror(errno), errno);
 +    close(_requestFD);
 +    _requestFD = 0;
 +  }
 +#endif
 +}
 +
 +- (void)didWriteBytes:(const void*)bytes length:(NSUInteger)length {
 +  GWS_LOG_DEBUG(@"Connection sent %lu bytes on socket %i", (unsigned long)length, _socket);
 +  _bytesWritten += length;
 +  
 +#ifdef __GCDWEBSERVER_ENABLE_TESTING__
 +  if ((_responseFD > 0) && (write(_responseFD, bytes, length) != (ssize_t)length)) {
 +    GWS_LOG_ERROR(@"Failed recording response data: %s (%i)", strerror(errno), errno);
 +    close(_responseFD);
 +    _responseFD = 0;
 +  }
 +#endif
 +}
 +
 +- (NSURL*)rewriteRequestURL:(NSURL*)url withMethod:(NSString*)method headers:(NSDictionary*)headers {
 +  return url;
 +}
 +
 +// https://tools.ietf.org/html/rfc2617
 +- (GCDWebServerResponse*)preflightRequest:(GCDWebServerRequest*)request {
 +  GWS_LOG_DEBUG(@"Connection on socket %i preflighting request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead);
 +  GCDWebServerResponse* response = nil;
 +  if (_server.authenticationBasicAccounts) {
 +    __block BOOL authenticated = NO;
 +    NSString* authorizationHeader = [request.headers objectForKey:@"Authorization"];
 +    if ([authorizationHeader hasPrefix:@"Basic "]) {
 +      NSString* basicAccount = [authorizationHeader substringFromIndex:6];
 +      [_server.authenticationBasicAccounts enumerateKeysAndObjectsUsingBlock:^(NSString* username, NSString* digest, BOOL* stop) {
 +        if ([basicAccount isEqualToString:digest]) {
 +          authenticated = YES;
 +          *stop = YES;
 +        }
 +      }];
 +    }
 +    if (!authenticated) {
 +      response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_Unauthorized];
 +      [response setValue:[NSString stringWithFormat:@"Basic realm=\"%@\"", _server.authenticationRealm] forAdditionalHeader:@"WWW-Authenticate"];
 +    }
 +  } else if (_server.authenticationDigestAccounts) {
 +    BOOL authenticated = NO;
 +    BOOL isStaled = NO;
 +    NSString* authorizationHeader = [request.headers objectForKey:@"Authorization"];
 +    if ([authorizationHeader hasPrefix:@"Digest "]) {
 +      NSString* realm = GCDWebServerExtractHeaderValueParameter(authorizationHeader, @"realm");
 +      if ([realm isEqualToString:_server.authenticationRealm]) {
 +        NSString* nonce = GCDWebServerExtractHeaderValueParameter(authorizationHeader, @"nonce");
 +        if ([nonce isEqualToString:_digestAuthenticationNonce]) {
 +          NSString* username = GCDWebServerExtractHeaderValueParameter(authorizationHeader, @"username");
 +          NSString* uri = GCDWebServerExtractHeaderValueParameter(authorizationHeader, @"uri");
 +          NSString* actualResponse = GCDWebServerExtractHeaderValueParameter(authorizationHeader, @"response");
 +          NSString* ha1 = [_server.authenticationDigestAccounts objectForKey:username];
 +          NSString* ha2 = GCDWebServerComputeMD5Digest(@"%@:%@", request.method, uri);  // We cannot use "request.path" as the query string is required
 +          NSString* expectedResponse = GCDWebServerComputeMD5Digest(@"%@:%@:%@", ha1, _digestAuthenticationNonce, ha2);
 +          if ([actualResponse isEqualToString:expectedResponse]) {
 +            authenticated = YES;
 +          }
 +        } else if (nonce.length) {
 +          isStaled = YES;
 +        }
 +      }
 +    }
 +    if (!authenticated) {
 +      response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_Unauthorized];
 +      [response setValue:[NSString stringWithFormat:@"Digest realm=\"%@\", nonce=\"%@\"%@", _server.authenticationRealm, _digestAuthenticationNonce, isStaled ? @", stale=TRUE" : @""] forAdditionalHeader:@"WWW-Authenticate"];  // TODO: Support Quality of Protection ("qop")
 +    }
 +  }
 +  return response;
 +}
 +
 +- (void)processRequest:(GCDWebServerRequest*)request completion:(GCDWebServerCompletionBlock)completion {
 +  GWS_LOG_DEBUG(@"Connection on socket %i processing request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead);
 +  @try {
-     _handler.asyncProcessBlock(request, completion);
++    _handler.asyncProcessBlock(request, [completion copy]);
 +  }
 +  @catch (NSException* exception) {
 +    GWS_LOG_EXCEPTION(exception);
 +  }
 +}
 +
++// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25
 +// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26
 +static inline BOOL _CompareResources(NSString* responseETag, NSString* requestETag, NSDate* responseLastModified, NSDate* requestLastModified) {
-   if ([requestETag isEqualToString:@"*"] && (!responseLastModified || !requestLastModified || ([responseLastModified compare:requestLastModified] != NSOrderedDescending))) {
-     return YES;
-   } else {
-     if ([responseETag isEqualToString:requestETag]) {
++  if (requestLastModified && responseLastModified) {
++    if ([responseLastModified compare:requestLastModified] != NSOrderedDescending) {
++      return YES;
++    }
++  }
++  if (requestETag && responseETag) {  // Per the specs "If-None-Match" must be checked after "If-Modified-Since"
++    if ([requestETag isEqualToString:@"*"]) {
 +      return YES;
 +    }
-     if (responseLastModified && requestLastModified && ([responseLastModified compare:requestLastModified] != NSOrderedDescending)) {
++    if ([responseETag isEqualToString:requestETag]) {
 +      return YES;
 +    }
 +  }
 +  return NO;
 +}
 +
 +- (GCDWebServerResponse*)overrideResponse:(GCDWebServerResponse*)response forRequest:(GCDWebServerRequest*)request {
 +  if ((response.statusCode >= 200) && (response.statusCode < 300) && _CompareResources(response.eTag, request.ifNoneMatch, response.lastModifiedDate, request.ifModifiedSince)) {
 +    NSInteger code = [request.method isEqualToString:@"HEAD"] || [request.method isEqualToString:@"GET"] ? kGCDWebServerHTTPStatusCode_NotModified : kGCDWebServerHTTPStatusCode_PreconditionFailed;
 +    GCDWebServerResponse* newResponse = [GCDWebServerResponse responseWithStatusCode:code];
 +    newResponse.cacheControlMaxAge = response.cacheControlMaxAge;
 +    newResponse.lastModifiedDate = response.lastModifiedDate;
 +    newResponse.eTag = response.eTag;
 +    GWS_DCHECK(newResponse);
 +    return newResponse;
 +  }
 +  return response;
 +}
 +
 +- (void)abortRequest:(GCDWebServerRequest*)request withStatusCode:(NSInteger)statusCode {
 +  GWS_DCHECK(_responseMessage == NULL);
 +  GWS_DCHECK((statusCode >= 400) && (statusCode < 600));
 +  [self _initializeResponseHeadersWithStatusCode:statusCode];
 +  [self _writeHeadersWithCompletionBlock:^(BOOL success) {
 +    ;  // Nothing more to do
 +  }];
 +  GWS_LOG_DEBUG(@"Connection aborted with status code %i on socket %i", (int)statusCode, _socket);
 +}
 +
 +- (void)close {
 +#ifdef __GCDWEBSERVER_ENABLE_TESTING__
 +  if (_requestPath) {
 +    BOOL success = NO;
 +    NSError* error = nil;
 +    if (_requestFD > 0) {
 +      close(_requestFD);
 +      NSString* name = [NSString stringWithFormat:@"%03lu-%@.request", (unsigned long)_connectionIndex, _virtualHEAD ? @"HEAD" : _request.method];
 +      success = [[NSFileManager defaultManager] moveItemAtPath:_requestPath toPath:[[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:name] error:&error];
 +    }
 +    if (!success) {
 +      GWS_LOG_ERROR(@"Failed saving recorded request: %@", error);
 +      GWS_DNOT_REACHED();
 +    }
 +    unlink([_requestPath fileSystemRepresentation]);
 +  }
 +  
 +  if (_responsePath) {
 +    BOOL success = NO;
 +    NSError* error = nil;
 +    if (_responseFD > 0) {
 +      close(_responseFD);
 +      NSString* name = [NSString stringWithFormat:@"%03lu-%i.response", (unsigned long)_connectionIndex, (int)_statusCode];
 +      success = [[NSFileManager defaultManager] moveItemAtPath:_responsePath toPath:[[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:name] error:&error];
 +    }
 +    if (!success) {
 +      GWS_LOG_ERROR(@"Failed saving recorded response: %@", error);
 +      GWS_DNOT_REACHED();
 +    }
 +    unlink([_responsePath fileSystemRepresentation]);
 +  }
 +#endif
 +  
 +  if (_request) {
 +    GWS_LOG_VERBOSE(@"[%@] %@ %i \"%@ %@\" (%lu | %lu)", self.localAddressString, self.remoteAddressString, (int)_statusCode, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead, (unsigned long)_bytesWritten);
 +  } else {
 +    GWS_LOG_VERBOSE(@"[%@] %@ %i \"(invalid request)\" (%lu | %lu)", self.localAddressString, self.remoteAddressString, (int)_statusCode, (unsigned long)_bytesRead, (unsigned long)_bytesWritten);
 +  }
 +}
 +
 +@end

http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/36f1a43e/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.h
----------------------------------------------------------------------
diff --cc local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.h
index a8b2857,0000000..e5be05c
mode 100644,000000..100644
--- a/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.h
+++ b/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.h
@@@ -1,101 -1,0 +1,101 @@@
 +/*
-  Copyright (c) 2012-2014, Pierre-Olivier Latour
++ Copyright (c) 2012-2015, Pierre-Olivier Latour
 + All rights reserved.
 + 
 + Redistribution and use in source and binary forms, with or without
 + modification, are permitted provided that the following conditions are met:
 + * Redistributions of source code must retain the above copyright
 + notice, this list of conditions and the following disclaimer.
 + * Redistributions in binary form must reproduce the above copyright
 + notice, this list of conditions and the following disclaimer in the
 + documentation and/or other materials provided with the distribution.
 + * The name of Pierre-Olivier Latour may not be used to endorse
 + or promote products derived from this software without specific
 + prior written permission.
 + 
 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 + DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
 + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 + */
 +
 +#import <Foundation/Foundation.h>
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +
 +/**
 + *  Converts a file extension to the corresponding MIME type.
 + *  If there is no match, "application/octet-stream" is returned.
 + */
 +NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension);
 +
 +/**
 + *  Add percent-escapes to a string so it can be used in a URL.
 + *  The legal characters ":@/?&=+" are also escaped to ensure compatibility
 + *  with URL encoded forms and URL queries.
 + */
 +NSString* GCDWebServerEscapeURLString(NSString* string);
 +
 +/**
 + *  Unescapes a URL percent-encoded string.
 + */
 +NSString* GCDWebServerUnescapeURLString(NSString* string);
 +
 +/**
 + *  Extracts the unescaped names and values from an
 + *  "application/x-www-form-urlencoded" form.
 + *  http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
 + */
 +NSDictionary* GCDWebServerParseURLEncodedForm(NSString* form);
 +
 +/**
 + *  On OS X, returns the IPv4 or IPv6 address as a string of the primary
 + *  connected service or nil if not available.
 + *  
 + *  On iOS, returns the IPv4 or IPv6 address as a string of the WiFi
 + *  interface if connected or nil otherwise.
 + */
 +NSString* GCDWebServerGetPrimaryIPAddress(BOOL useIPv6);
 +
 +/**
 + *  Converts a date into a string using RFC822 formatting.
 + *  https://tools.ietf.org/html/rfc822#section-5
 + *  https://tools.ietf.org/html/rfc1123#section-5.2.14
 + */
 +NSString* GCDWebServerFormatRFC822(NSDate* date);
 +
 +/**
 + *  Converts a RFC822 formatted string into a date.
 + *  https://tools.ietf.org/html/rfc822#section-5
 + *  https://tools.ietf.org/html/rfc1123#section-5.2.14
 + *
 + *  @warning Timezones other than GMT are not supported by this function.
 + */
 +NSDate* GCDWebServerParseRFC822(NSString* string);
 +
 +/**
 + *  Converts a date into a string using IOS 8601 formatting.
 + *  http://tools.ietf.org/html/rfc3339#section-5.6
 + */
 +NSString* GCDWebServerFormatISO8601(NSDate* date);
 +
 +/**
 + *  Converts a ISO 8601 formatted string into a date.
 + *  http://tools.ietf.org/html/rfc3339#section-5.6
 + *
 + *  @warning Only "calendar" variant is supported at this time and timezones
 + *  other than GMT are not supported either.
 + */
 +NSDate* GCDWebServerParseISO8601(NSString* string);
 +
 +#ifdef __cplusplus
 +}
 +#endif

http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/36f1a43e/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.m
----------------------------------------------------------------------
diff --cc local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.m
index d81af0b,0000000..25e41ca
mode 100644,000000..100644
--- a/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.m
+++ b/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.m
@@@ -1,299 -1,0 +1,307 @@@
 +/*
-  Copyright (c) 2012-2014, Pierre-Olivier Latour
++ Copyright (c) 2012-2015, Pierre-Olivier Latour
 + All rights reserved.
 + 
 + Redistribution and use in source and binary forms, with or without
 + modification, are permitted provided that the following conditions are met:
 + * Redistributions of source code must retain the above copyright
 + notice, this list of conditions and the following disclaimer.
 + * Redistributions in binary form must reproduce the above copyright
 + notice, this list of conditions and the following disclaimer in the
 + documentation and/or other materials provided with the distribution.
 + * The name of Pierre-Olivier Latour may not be used to endorse
 + or promote products derived from this software without specific
 + prior written permission.
 + 
 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 + DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
 + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 + */
 +
 +#if !__has_feature(objc_arc)
 +#error GCDWebServer requires ARC
 +#endif
 +
 +#import <TargetConditionals.h>
 +#if TARGET_OS_IPHONE
 +#import <MobileCoreServices/MobileCoreServices.h>
 +#else
 +#import <SystemConfiguration/SystemConfiguration.h>
 +#endif
 +#import <CommonCrypto/CommonDigest.h>
 +
 +#import <ifaddrs.h>
 +#import <net/if.h>
 +#import <netdb.h>
 +
 +#import "GCDWebServerPrivate.h"
 +
 +static NSDateFormatter* _dateFormatterRFC822 = nil;
 +static NSDateFormatter* _dateFormatterISO8601 = nil;
 +static dispatch_queue_t _dateFormatterQueue = NULL;
 +
 +// TODO: Handle RFC 850 and ANSI C's asctime() format
 +void GCDWebServerInitializeFunctions() {
 +  GWS_DCHECK([NSThread isMainThread]);  // NSDateFormatter should be initialized on main thread
 +  if (_dateFormatterRFC822 == nil) {
 +    _dateFormatterRFC822 = [[NSDateFormatter alloc] init];
 +    _dateFormatterRFC822.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
 +    _dateFormatterRFC822.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'";
 +    _dateFormatterRFC822.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
 +    GWS_DCHECK(_dateFormatterRFC822);
 +  }
 +  if (_dateFormatterISO8601 == nil) {
 +    _dateFormatterISO8601 = [[NSDateFormatter alloc] init];
 +    _dateFormatterISO8601.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
 +    _dateFormatterISO8601.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss'+00:00'";
 +    _dateFormatterISO8601.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
 +    GWS_DCHECK(_dateFormatterISO8601);
 +  }
 +  if (_dateFormatterQueue == NULL) {
 +    _dateFormatterQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
 +    GWS_DCHECK(_dateFormatterQueue);
 +  }
 +}
 +
 +NSString* GCDWebServerNormalizeHeaderValue(NSString* value) {
 +  if (value) {
 +    NSRange range = [value rangeOfString:@";"];  // Assume part before ";" separator is case-insensitive
 +    if (range.location != NSNotFound) {
 +      value = [[[value substringToIndex:range.location] lowercaseString] stringByAppendingString:[value substringFromIndex:range.location]];
 +    } else {
 +      value = [value lowercaseString];
 +    }
 +  }
 +  return value;
 +}
 +
 +NSString* GCDWebServerTruncateHeaderValue(NSString* value) {
 +  NSRange range = [value rangeOfString:@";"];
 +  return range.location != NSNotFound ? [value substringToIndex:range.location] : value;
 +}
 +
 +NSString* GCDWebServerExtractHeaderValueParameter(NSString* value, NSString* name) {
 +  NSString* parameter = nil;
 +  NSScanner* scanner = [[NSScanner alloc] initWithString:value];
 +  [scanner setCaseSensitive:NO];  // Assume parameter names are case-insensitive
 +  NSString* string = [NSString stringWithFormat:@"%@=", name];
 +  if ([scanner scanUpToString:string intoString:NULL]) {
 +    [scanner scanString:string intoString:NULL];
 +    if ([scanner scanString:@"\"" intoString:NULL]) {
 +      [scanner scanUpToString:@"\"" intoString:&parameter];
 +    } else {
 +      [scanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:&parameter];
 +    }
 +  }
 +  return parameter;
 +}
 +
 +// http://www.w3schools.com/tags/ref_charactersets.asp
 +NSStringEncoding GCDWebServerStringEncodingFromCharset(NSString* charset) {
 +  NSStringEncoding encoding = kCFStringEncodingInvalidId;
 +  if (charset) {
 +    encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)charset));
 +  }
 +  return (encoding != kCFStringEncodingInvalidId ? encoding : NSUTF8StringEncoding);
 +}
 +
 +NSString* GCDWebServerFormatRFC822(NSDate* date) {
 +  __block NSString* string;
 +  dispatch_sync(_dateFormatterQueue, ^{
 +    string = [_dateFormatterRFC822 stringFromDate:date];
 +  });
 +  return string;
 +}
 +
 +NSDate* GCDWebServerParseRFC822(NSString* string) {
 +  __block NSDate* date;
 +  dispatch_sync(_dateFormatterQueue, ^{
 +    date = [_dateFormatterRFC822 dateFromString:string];
 +  });
 +  return date;
 +}
 +
 +NSString* GCDWebServerFormatISO8601(NSDate* date) {
 +  __block NSString* string;
 +  dispatch_sync(_dateFormatterQueue, ^{
 +    string = [_dateFormatterISO8601 stringFromDate:date];
 +  });
 +  return string;
 +}
 +
 +NSDate* GCDWebServerParseISO8601(NSString* string) {
 +  __block NSDate* date;
 +  dispatch_sync(_dateFormatterQueue, ^{
 +    date = [_dateFormatterISO8601 dateFromString:string];
 +  });
 +  return date;
 +}
 +
 +BOOL GCDWebServerIsTextContentType(NSString* type) {
 +  return ([type hasPrefix:@"text/"] || [type hasPrefix:@"application/json"] || [type hasPrefix:@"application/xml"]);
 +}
 +
 +NSString* GCDWebServerDescribeData(NSData* data, NSString* type) {
 +  if (GCDWebServerIsTextContentType(type)) {
 +    NSString* charset = GCDWebServerExtractHeaderValueParameter(type, @"charset");
 +    NSString* string = [[NSString alloc] initWithData:data encoding:GCDWebServerStringEncodingFromCharset(charset)];
 +    if (string) {
 +      return string;
 +    }
 +  }
 +  return [NSString stringWithFormat:@"<%lu bytes>", (unsigned long)data.length];
 +}
 +
 +NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension) {
 +  static NSDictionary* _overrides = nil;
 +  if (_overrides == nil) {
 +    _overrides = [[NSDictionary alloc] initWithObjectsAndKeys:
 +                  @"text/css", @"css",
 +                  nil];
 +  }
 +  NSString* mimeType = nil;
 +  extension = [extension lowercaseString];
 +  if (extension.length) {
 +    mimeType = [_overrides objectForKey:extension];
 +    if (mimeType == nil) {
 +      CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)extension, NULL);
 +      if (uti) {
 +        mimeType = CFBridgingRelease(UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType));
 +        CFRelease(uti);
 +      }
 +    }
 +  }
 +  return mimeType ? mimeType : kGCDWebServerDefaultMimeType;
 +}
 +
 +NSString* GCDWebServerEscapeURLString(NSString* string) {
++#pragma clang diagnostic push
++#pragma clang diagnostic ignored "-Wdeprecated-declarations"
 +  return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, CFSTR(":@/?&=+"), kCFStringEncodingUTF8));
++#pragma clang diagnostic pop
 +}
 +
 +NSString* GCDWebServerUnescapeURLString(NSString* string) {
++#pragma clang diagnostic push
++#pragma clang diagnostic ignored "-Wdeprecated-declarations"
 +  return CFBridgingRelease(CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, (CFStringRef)string, CFSTR(""), kCFStringEncodingUTF8));
++#pragma clang diagnostic pop
 +}
 +
 +NSDictionary* GCDWebServerParseURLEncodedForm(NSString* form) {
 +  NSMutableDictionary* parameters = [NSMutableDictionary dictionary];
 +  NSScanner* scanner = [[NSScanner alloc] initWithString:form];
 +  [scanner setCharactersToBeSkipped:nil];
 +  while (1) {
 +    NSString* key = nil;
 +    if (![scanner scanUpToString:@"=" intoString:&key] || [scanner isAtEnd]) {
 +      break;
 +    }
 +    [scanner setScanLocation:([scanner scanLocation] + 1)];
 +    
 +    NSString* value = nil;
 +    [scanner scanUpToString:@"&" intoString:&value];
 +    if (value == nil) {
 +      value = @"";
 +    }
 +    
 +    key = [key stringByReplacingOccurrencesOfString:@"+" withString:@" "];
 +    NSString* unescapedKey = key ? GCDWebServerUnescapeURLString(key) : nil;
 +    value = [value stringByReplacingOccurrencesOfString:@"+" withString:@" "];
 +    NSString* unescapedValue = value ? GCDWebServerUnescapeURLString(value) : nil;
 +    if (unescapedKey && unescapedValue) {
 +      [parameters setObject:unescapedValue forKey:unescapedKey];
 +    } else {
 +      GWS_LOG_WARNING(@"Failed parsing URL encoded form for key \"%@\" and value \"%@\"", key, value);
 +      GWS_DNOT_REACHED();
 +    }
 +    
 +    if ([scanner isAtEnd]) {
 +      break;
 +    }
 +    [scanner setScanLocation:([scanner scanLocation] + 1)];
 +  }
 +  return parameters;
 +}
 +
 +NSString* GCDWebServerStringFromSockAddr(const struct sockaddr* addr, BOOL includeService) {
 +  NSString* string = nil;
 +  char hostBuffer[NI_MAXHOST];
 +  char serviceBuffer[NI_MAXSERV];
 +  if (getnameinfo(addr, addr->sa_len, hostBuffer, sizeof(hostBuffer), serviceBuffer, sizeof(serviceBuffer), NI_NUMERICHOST | NI_NUMERICSERV | NI_NOFQDN) >= 0) {
 +    string = includeService ? [NSString stringWithFormat:@"%s:%s", hostBuffer, serviceBuffer] : [NSString stringWithUTF8String:hostBuffer];
 +  } else {
 +    GWS_DNOT_REACHED();
 +  }
 +  return string;
 +}
 +
 +NSString* GCDWebServerGetPrimaryIPAddress(BOOL useIPv6) {
 +  NSString* address = nil;
 +#if TARGET_OS_IPHONE
- #if !TARGET_IPHONE_SIMULATOR
++#if !TARGET_IPHONE_SIMULATOR && !TARGET_OS_TV
 +  const char* primaryInterface = "en0";  // WiFi interface on iOS
 +#endif
 +#else
 +  const char* primaryInterface = NULL;
 +  SCDynamicStoreRef store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("GCDWebServer"), NULL, NULL);
 +  if (store) {
 +    CFPropertyListRef info = SCDynamicStoreCopyValue(store, CFSTR("State:/Network/Global/IPv4"));  // There is no equivalent for IPv6 but the primary interface should be the same
 +    if (info) {
 +      primaryInterface = [[NSString stringWithString:[(__bridge NSDictionary*)info objectForKey:@"PrimaryInterface"]] UTF8String];
 +      CFRelease(info);
 +    }
 +    CFRelease(store);
 +  }
 +  if (primaryInterface == NULL) {
 +    primaryInterface = "lo0";
 +  }
 +#endif
 +  struct ifaddrs* list;
 +  if (getifaddrs(&list) >= 0) {
 +    for (struct ifaddrs* ifap = list; ifap; ifap = ifap->ifa_next) {
- #if TARGET_IPHONE_SIMULATOR
-       if (strcmp(ifap->ifa_name, "en0") && strcmp(ifap->ifa_name, "en1"))  // Assume en0 is Ethernet and en1 is WiFi since there is no way to use SystemConfiguration framework in iOS Simulator
++#if TARGET_IPHONE_SIMULATOR  || TARGET_OS_TV
++        // Assume en0 is Ethernet and en1 is WiFi since there is no way to use SystemConfiguration framework in iOS Simulator
++        // Assumption holds for Apple TV running tvOS
++      if (strcmp(ifap->ifa_name, "en0") && strcmp(ifap->ifa_name, "en1"))
 +#else
 +      if (strcmp(ifap->ifa_name, primaryInterface))
 +#endif
 +      {
 +        continue;
 +      }
 +      if ((ifap->ifa_flags & IFF_UP) && ((!useIPv6 && (ifap->ifa_addr->sa_family == AF_INET)) || (useIPv6 && (ifap->ifa_addr->sa_family == AF_INET6)))) {
 +        address = GCDWebServerStringFromSockAddr(ifap->ifa_addr, NO);
 +        break;
 +      }
 +    }
 +    freeifaddrs(list);
 +  }
 +  return address;
 +}
 +
 +NSString* GCDWebServerComputeMD5Digest(NSString* format, ...) {
 +  va_list arguments;
 +  va_start(arguments, format);
 +  const char* string = [[[NSString alloc] initWithFormat:format arguments:arguments] UTF8String];
 +  va_end(arguments);
 +  unsigned char md5[CC_MD5_DIGEST_LENGTH];
 +  CC_MD5(string, (CC_LONG)strlen(string), md5);
 +  char buffer[2 * CC_MD5_DIGEST_LENGTH + 1];
 +  for (int i = 0; i < CC_MD5_DIGEST_LENGTH; ++i) {
 +    unsigned char byte = md5[i];
 +    unsigned char byteHi = (byte & 0xF0) >> 4;
 +    buffer[2 * i + 0] = byteHi >= 10 ? 'a' + byteHi - 10 : '0' + byteHi;
 +    unsigned char byteLo = byte & 0x0F;
 +    buffer[2 * i + 1] = byteLo >= 10 ? 'a' + byteLo - 10 : '0' + byteLo;
 +  }
 +  buffer[2 * CC_MD5_DIGEST_LENGTH] = 0;
 +  return [NSString stringWithUTF8String:buffer];
 +}

http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/36f1a43e/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerHTTPStatusCodes.h
----------------------------------------------------------------------
diff --cc local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerHTTPStatusCodes.h
index 7af51a2,0000000..6e98381
mode 100644,000000..100644
--- a/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerHTTPStatusCodes.h
+++ b/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerHTTPStatusCodes.h
@@@ -1,116 -1,0 +1,116 @@@
 +/*
-  Copyright (c) 2012-2014, Pierre-Olivier Latour
++ Copyright (c) 2012-2015, Pierre-Olivier Latour
 + All rights reserved.
 + 
 + Redistribution and use in source and binary forms, with or without
 + modification, are permitted provided that the following conditions are met:
 + * Redistributions of source code must retain the above copyright
 + notice, this list of conditions and the following disclaimer.
 + * Redistributions in binary form must reproduce the above copyright
 + notice, this list of conditions and the following disclaimer in the
 + documentation and/or other materials provided with the distribution.
 + * The name of Pierre-Olivier Latour may not be used to endorse
 + or promote products derived from this software without specific
 + prior written permission.
 + 
 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 + DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
 + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 + */
 +
 +// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
 +// http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
 +
 +#import <Foundation/Foundation.h>
 +
 +/**
 + *  Convenience constants for "informational" HTTP status codes.
 + */
 +typedef NS_ENUM(NSInteger, GCDWebServerInformationalHTTPStatusCode) {
 +  kGCDWebServerHTTPStatusCode_Continue = 100,
 +  kGCDWebServerHTTPStatusCode_SwitchingProtocols = 101,
 +  kGCDWebServerHTTPStatusCode_Processing = 102
 +};
 +
 +/**
 + *  Convenience constants for "successful" HTTP status codes.
 + */
 +typedef NS_ENUM(NSInteger, GCDWebServerSuccessfulHTTPStatusCode) {
 +  kGCDWebServerHTTPStatusCode_OK = 200,
 +  kGCDWebServerHTTPStatusCode_Created = 201,
 +  kGCDWebServerHTTPStatusCode_Accepted = 202,
 +  kGCDWebServerHTTPStatusCode_NonAuthoritativeInformation = 203,
 +  kGCDWebServerHTTPStatusCode_NoContent = 204,
 +  kGCDWebServerHTTPStatusCode_ResetContent = 205,
 +  kGCDWebServerHTTPStatusCode_PartialContent = 206,
 +  kGCDWebServerHTTPStatusCode_MultiStatus = 207,
 +  kGCDWebServerHTTPStatusCode_AlreadyReported = 208
 +};
 +
 +/**
 + *  Convenience constants for "redirection" HTTP status codes.
 + */
 +typedef NS_ENUM(NSInteger, GCDWebServerRedirectionHTTPStatusCode) {
 +  kGCDWebServerHTTPStatusCode_MultipleChoices = 300,
 +  kGCDWebServerHTTPStatusCode_MovedPermanently = 301,
 +  kGCDWebServerHTTPStatusCode_Found = 302,
 +  kGCDWebServerHTTPStatusCode_SeeOther = 303,
 +  kGCDWebServerHTTPStatusCode_NotModified = 304,
 +  kGCDWebServerHTTPStatusCode_UseProxy = 305,
 +  kGCDWebServerHTTPStatusCode_TemporaryRedirect = 307,
 +  kGCDWebServerHTTPStatusCode_PermanentRedirect = 308
 +};
 +
 +/**
 + *  Convenience constants for "client error" HTTP status codes.
 + */
 +typedef NS_ENUM(NSInteger, GCDWebServerClientErrorHTTPStatusCode) {
 +  kGCDWebServerHTTPStatusCode_BadRequest = 400,
 +  kGCDWebServerHTTPStatusCode_Unauthorized = 401,
 +  kGCDWebServerHTTPStatusCode_PaymentRequired = 402,
 +  kGCDWebServerHTTPStatusCode_Forbidden = 403,
 +  kGCDWebServerHTTPStatusCode_NotFound = 404,
 +  kGCDWebServerHTTPStatusCode_MethodNotAllowed = 405,
 +  kGCDWebServerHTTPStatusCode_NotAcceptable = 406,
 +  kGCDWebServerHTTPStatusCode_ProxyAuthenticationRequired = 407,
 +  kGCDWebServerHTTPStatusCode_RequestTimeout = 408,
 +  kGCDWebServerHTTPStatusCode_Conflict = 409,
 +  kGCDWebServerHTTPStatusCode_Gone = 410,
 +  kGCDWebServerHTTPStatusCode_LengthRequired = 411,
 +  kGCDWebServerHTTPStatusCode_PreconditionFailed = 412,
 +  kGCDWebServerHTTPStatusCode_RequestEntityTooLarge = 413,
 +  kGCDWebServerHTTPStatusCode_RequestURITooLong = 414,
 +  kGCDWebServerHTTPStatusCode_UnsupportedMediaType = 415,
 +  kGCDWebServerHTTPStatusCode_RequestedRangeNotSatisfiable = 416,
 +  kGCDWebServerHTTPStatusCode_ExpectationFailed = 417,
 +  kGCDWebServerHTTPStatusCode_UnprocessableEntity = 422,
 +  kGCDWebServerHTTPStatusCode_Locked = 423,
 +  kGCDWebServerHTTPStatusCode_FailedDependency = 424,
 +  kGCDWebServerHTTPStatusCode_UpgradeRequired = 426,
 +  kGCDWebServerHTTPStatusCode_PreconditionRequired = 428,
 +  kGCDWebServerHTTPStatusCode_TooManyRequests = 429,
 +  kGCDWebServerHTTPStatusCode_RequestHeaderFieldsTooLarge = 431
 +};
 +
 +/**
 + *  Convenience constants for "server error" HTTP status codes.
 + */
 +typedef NS_ENUM(NSInteger, GCDWebServerServerErrorHTTPStatusCode) {
 +  kGCDWebServerHTTPStatusCode_InternalServerError = 500,
 +  kGCDWebServerHTTPStatusCode_NotImplemented = 501,
 +  kGCDWebServerHTTPStatusCode_BadGateway = 502,
 +  kGCDWebServerHTTPStatusCode_ServiceUnavailable = 503,
 +  kGCDWebServerHTTPStatusCode_GatewayTimeout = 504,
 +  kGCDWebServerHTTPStatusCode_HTTPVersionNotSupported = 505,
 +  kGCDWebServerHTTPStatusCode_InsufficientStorage = 507,
 +  kGCDWebServerHTTPStatusCode_LoopDetected = 508,
 +  kGCDWebServerHTTPStatusCode_NotExtended = 510,
 +  kGCDWebServerHTTPStatusCode_NetworkAuthenticationRequired = 511
 +};

http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/36f1a43e/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerPrivate.h
----------------------------------------------------------------------
diff --cc local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerPrivate.h
index 1ed54e8,0000000..c9c6868
mode 100644,000000..100644
--- a/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerPrivate.h
+++ b/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerPrivate.h
@@@ -1,228 -1,0 +1,230 @@@
 +/*
-  Copyright (c) 2012-2014, Pierre-Olivier Latour
++ Copyright (c) 2012-2015, Pierre-Olivier Latour
 + All rights reserved.
 + 
 + Redistribution and use in source and binary forms, with or without
 + modification, are permitted provided that the following conditions are met:
 + * Redistributions of source code must retain the above copyright
 + notice, this list of conditions and the following disclaimer.
 + * Redistributions in binary form must reproduce the above copyright
 + notice, this list of conditions and the following disclaimer in the
 + documentation and/or other materials provided with the distribution.
 + * The name of Pierre-Olivier Latour may not be used to endorse
 + or promote products derived from this software without specific
 + prior written permission.
 + 
 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 + DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
 + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 + */
 +
 +#import <os/object.h>
 +#import <sys/socket.h>
 +
 +/**
 + *  All GCDWebServer headers.
 + */
 +
 +#import "GCDWebServerHTTPStatusCodes.h"
 +#import "GCDWebServerFunctions.h"
 +
 +#import "GCDWebServer.h"
 +#import "GCDWebServerConnection.h"
 +
 +#import "GCDWebServerDataRequest.h"
 +#import "GCDWebServerFileRequest.h"
 +#import "GCDWebServerMultiPartFormRequest.h"
 +#import "GCDWebServerURLEncodedFormRequest.h"
 +
 +#import "GCDWebServerDataResponse.h"
 +#import "GCDWebServerErrorResponse.h"
 +#import "GCDWebServerFileResponse.h"
 +#import "GCDWebServerStreamedResponse.h"
 +
 +/**
++ *  Check if a custom logging facility should be used instead.
++ */
++
++#if defined(__GCDWEBSERVER_LOGGING_HEADER__)
++
++#define __GCDWEBSERVER_LOGGING_FACILITY_CUSTOM__
++
++#import __GCDWEBSERVER_LOGGING_HEADER__
++
++/**
 + *  Automatically detect if XLFacility is available and if so use it as a
 + *  logging facility.
 + */
 +
- #if defined(__has_include) && __has_include("XLFacilityMacros.h")
++#elif defined(__has_include) && __has_include("XLFacilityMacros.h")
 +
 +#define __GCDWEBSERVER_LOGGING_FACILITY_XLFACILITY__
 +
 +#undef XLOG_TAG
 +#define XLOG_TAG @"gcdwebserver.internal"
 +
 +#import "XLFacilityMacros.h"
 +
 +#define GWS_LOG_DEBUG(...) XLOG_DEBUG(__VA_ARGS__)
 +#define GWS_LOG_VERBOSE(...) XLOG_VERBOSE(__VA_ARGS__)
 +#define GWS_LOG_INFO(...) XLOG_INFO(__VA_ARGS__)
 +#define GWS_LOG_WARNING(...) XLOG_WARNING(__VA_ARGS__)
 +#define GWS_LOG_ERROR(...) XLOG_ERROR(__VA_ARGS__)
 +#define GWS_LOG_EXCEPTION(__EXCEPTION__) XLOG_EXCEPTION(__EXCEPTION__)
 +
 +#define GWS_DCHECK(__CONDITION__) XLOG_DEBUG_CHECK(__CONDITION__)
 +#define GWS_DNOT_REACHED() XLOG_DEBUG_UNREACHABLE()
 +
 +/**
 + *  Automatically detect if CocoaLumberJack is available and if so use
 + *  it as a logging facility.
 + */
 +
- #elif defined(__has_include) && __has_include("DDLogMacros.h")
++#elif defined(__has_include) && __has_include("CocoaLumberjack/CocoaLumberjack.h")
 +
- #import "DDLogMacros.h"
++#import <CocoaLumberjack/CocoaLumberjack.h>
 +
 +#define __GCDWEBSERVER_LOGGING_FACILITY_COCOALUMBERJACK__
 +
 +#undef LOG_LEVEL_DEF
 +#define LOG_LEVEL_DEF GCDWebServerLogLevel
- extern int GCDWebServerLogLevel;
++extern DDLogLevel GCDWebServerLogLevel;
 +
 +#define GWS_LOG_DEBUG(...) DDLogDebug(__VA_ARGS__)
 +#define GWS_LOG_VERBOSE(...) DDLogVerbose(__VA_ARGS__)
 +#define GWS_LOG_INFO(...) DDLogInfo(__VA_ARGS__)
 +#define GWS_LOG_WARNING(...) DDLogWarn(__VA_ARGS__)
 +#define GWS_LOG_ERROR(...) DDLogError(__VA_ARGS__)
 +#define GWS_LOG_EXCEPTION(__EXCEPTION__) DDLogError(@"%@", __EXCEPTION__)
 +
 +/**
-  *  Check if a custom logging facility should be used instead.
-  */
- 
- #elif defined(__GCDWEBSERVER_LOGGING_HEADER__)
- 
- #define __GCDWEBSERVER_LOGGING_FACILITY_CUSTOM__
- 
- #import __GCDWEBSERVER_LOGGING_HEADER__
- 
- /**
 + *  If all of the above fail, then use GCDWebServer built-in
 + *  logging facility.
 + */
 +
 +#else
 +
 +#define __GCDWEBSERVER_LOGGING_FACILITY_BUILTIN__
 +
 +typedef NS_ENUM(int, GCDWebServerLoggingLevel) {
 +  kGCDWebServerLoggingLevel_Debug = 0,
 +  kGCDWebServerLoggingLevel_Verbose,
 +  kGCDWebServerLoggingLevel_Info,
 +  kGCDWebServerLoggingLevel_Warning,
 +  kGCDWebServerLoggingLevel_Error,
-   kGCDWebServerLoggingLevel_Exception,
++  kGCDWebServerLoggingLevel_Exception
 +};
 +
 +extern GCDWebServerLoggingLevel GCDWebServerLogLevel;
 +extern void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* format, ...) NS_FORMAT_FUNCTION(2, 3);
 +
 +#if DEBUG
 +#define GWS_LOG_DEBUG(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Debug) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Debug, __VA_ARGS__); } while (0)
 +#else
 +#define GWS_LOG_DEBUG(...)
 +#endif
 +#define GWS_LOG_VERBOSE(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Verbose) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Verbose, __VA_ARGS__); } while (0)
 +#define GWS_LOG_INFO(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Info) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Info, __VA_ARGS__); } while (0)
 +#define GWS_LOG_WARNING(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Warning) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Warning, __VA_ARGS__); } while (0)
 +#define GWS_LOG_ERROR(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Error) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Error, __VA_ARGS__); } while (0)
 +#define GWS_LOG_EXCEPTION(__EXCEPTION__) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Exception) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Exception, @"%@", __EXCEPTION__); } while (0)
 +
 +#endif
 +
 +/**
 + *  Consistency check macros used when building Debug only.
 + */
 +
 +#if !defined(GWS_DCHECK) || !defined(GWS_DNOT_REACHED)
 +
 +#if DEBUG
 +
 +#define GWS_DCHECK(__CONDITION__) \
 +  do { \
 +    if (!(__CONDITION__)) { \
 +      abort(); \
 +    } \
 +  } while (0)
 +#define GWS_DNOT_REACHED() abort()
 +
 +#else
 +
 +#define GWS_DCHECK(__CONDITION__)
 +#define GWS_DNOT_REACHED()
 +
 +#endif
 +
 +#endif
 +
 +/**
 + *  GCDWebServer internal constants and APIs.
 + */
 +
 +#define kGCDWebServerDefaultMimeType @"application/octet-stream"
 +#define kGCDWebServerGCDQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
 +#define kGCDWebServerErrorDomain @"GCDWebServerErrorDomain"
 +
 +static inline BOOL GCDWebServerIsValidByteRange(NSRange range) {
 +  return ((range.location != NSUIntegerMax) || (range.length > 0));
 +}
 +
 +static inline NSError* GCDWebServerMakePosixError(int code) {
 +  return [NSError errorWithDomain:NSPOSIXErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithUTF8String:strerror(code)]}];
 +}
 +
 +extern void GCDWebServerInitializeFunctions();
 +extern NSString* GCDWebServerNormalizeHeaderValue(NSString* value);
 +extern NSString* GCDWebServerTruncateHeaderValue(NSString* value);
 +extern NSString* GCDWebServerExtractHeaderValueParameter(NSString* header, NSString* attribute);
 +extern NSStringEncoding GCDWebServerStringEncodingFromCharset(NSString* charset);
 +extern BOOL GCDWebServerIsTextContentType(NSString* type);
 +extern NSString* GCDWebServerDescribeData(NSData* data, NSString* contentType);
 +extern NSString* GCDWebServerComputeMD5Digest(NSString* format, ...) NS_FORMAT_FUNCTION(1,2);
 +extern NSString* GCDWebServerStringFromSockAddr(const struct sockaddr* addr, BOOL includeService);
 +
 +@interface GCDWebServerConnection ()
 +- (id)initWithServer:(GCDWebServer*)server localAddress:(NSData*)localAddress remoteAddress:(NSData*)remoteAddress socket:(CFSocketNativeHandle)socket;
 +@end
 +
 +@interface GCDWebServer ()
 +@property(nonatomic, readonly) NSArray* handlers;
 +@property(nonatomic, readonly) NSString* serverName;
 +@property(nonatomic, readonly) NSString* authenticationRealm;
 +@property(nonatomic, readonly) NSDictionary* authenticationBasicAccounts;
 +@property(nonatomic, readonly) NSDictionary* authenticationDigestAccounts;
 +@property(nonatomic, readonly) BOOL shouldAutomaticallyMapHEADToGET;
 +- (void)willStartConnection:(GCDWebServerConnection*)connection;
 +- (void)didEndConnection:(GCDWebServerConnection*)connection;
 +@end
 +
 +@interface GCDWebServerHandler : NSObject
 +@property(nonatomic, readonly) GCDWebServerMatchBlock matchBlock;
 +@property(nonatomic, readonly) GCDWebServerAsyncProcessBlock asyncProcessBlock;
 +@end
 +
 +@interface GCDWebServerRequest ()
 +@property(nonatomic, readonly) BOOL usesChunkedTransferEncoding;
++@property(nonatomic, readwrite) NSData* localAddressData;
++@property(nonatomic, readwrite) NSData* remoteAddressData;
 +- (void)prepareForWriting;
 +- (BOOL)performOpen:(NSError**)error;
 +- (BOOL)performWriteData:(NSData*)data error:(NSError**)error;
 +- (BOOL)performClose:(NSError**)error;
 +- (void)setAttribute:(id)attribute forKey:(NSString*)key;
 +@end
 +
 +@interface GCDWebServerResponse ()
 +@property(nonatomic, readonly) NSDictionary* additionalHeaders;
 +@property(nonatomic, readonly) BOOL usesChunkedTransferEncoding;
 +- (void)prepareForReading;
 +- (BOOL)performOpen:(NSError**)error;
 +- (void)performReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block;
 +- (void)performClose;
 +@end

http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/36f1a43e/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.h
----------------------------------------------------------------------
diff --cc local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.h
index 3b517b6,0000000..c7bc31b
mode 100644,000000..100644
--- a/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.h
+++ b/local-webserver/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.h
@@@ -1,182 -1,0 +1,206 @@@
 +/*
-  Copyright (c) 2012-2014, Pierre-Olivier Latour
++ Copyright (c) 2012-2015, Pierre-Olivier Latour
 + All rights reserved.
 + 
 + Redistribution and use in source and binary forms, with or without
 + modification, are permitted provided that the following conditions are met:
 + * Redistributions of source code must retain the above copyright
 + notice, this list of conditions and the following disclaimer.
 + * Redistributions in binary form must reproduce the above copyright
 + notice, this list of conditions and the following disclaimer in the
 + documentation and/or other materials provided with the distribution.
 + * The name of Pierre-Olivier Latour may not be used to endorse
 + or promote products derived from this software without specific
 + prior written permission.
 + 
 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 + DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
 + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 + */
 +
 +#import <Foundation/Foundation.h>
 +
 +/**
 + *  Attribute key to retrieve an NSArray containing NSStrings from a GCDWebServerRequest
 + *  with the contents of any regular expression captures done on the request path.
 + *
 + *  @warning This attribute will only be set on the request if adding a handler using 
 + *  -addHandlerForMethod:pathRegex:requestClass:processBlock:.
 + */
 +extern NSString* const GCDWebServerRequestAttribute_RegexCaptures;
 +
 +/**
 + *  This protocol is used by the GCDWebServerConnection to communicate with
 + *  the GCDWebServerRequest and write the received HTTP body data.
 + *
 + *  Note that multiple GCDWebServerBodyWriter objects can be chained together
 + *  internally e.g. to automatically decode gzip encoded content before
 + *  passing it on to the GCDWebServerRequest.
 + *
 + *  @warning These methods can be called on any GCD thread.
 + */
 +@protocol GCDWebServerBodyWriter <NSObject>
 +
 +/**
 + *  This method is called before any body data is received.
 + *
 + *  It should return YES on success or NO on failure and set the "error" argument
 + *  which is guaranteed to be non-NULL.
 + */
 +- (BOOL)open:(NSError**)error;
 +
 +/**
 + *  This method is called whenever body data has been received.
 + *
 + *  It should return YES on success or NO on failure and set the "error" argument
 + *  which is guaranteed to be non-NULL.
 + */
 +- (BOOL)writeData:(NSData*)data error:(NSError**)error;
 +
 +/**
 + *  This method is called after all body data has been received.
 + *
 + *  It should return YES on success or NO on failure and set the "error" argument
 + *  which is guaranteed to be non-NULL.
 + */
 +- (BOOL)close:(NSError**)error;
 +
 +@end
 +
 +/**
 + *  The GCDWebServerRequest class is instantiated by the GCDWebServerConnection
 + *  after the HTTP headers have been received. Each instance wraps a single HTTP
 + *  request. If a body is present, the methods from the GCDWebServerBodyWriter
 + *  protocol will be called by the GCDWebServerConnection to receive it.
 + *
 + *  The default implementation of the GCDWebServerBodyWriter protocol on the class
 + *  simply ignores the body data.
 + *
 + *  @warning GCDWebServerRequest instances can be created and used on any GCD thread.
 + */
 +@interface GCDWebServerRequest : NSObject <GCDWebServerBodyWriter>
 +
 +/**
 + *  Returns the HTTP method for the request.
 + */
 +@property(nonatomic, readonly) NSString* method;
 +
 +/**
 + *  Returns the URL for the request.
 + */
 +@property(nonatomic, readonly) NSURL* URL;
 +
 +/**
 + *  Returns the HTTP headers for the request.
 + */
 +@property(nonatomic, readonly) NSDictionary* headers;
 +
 +/**
 + *  Returns the path component of the URL for the request.
 + */
 +@property(nonatomic, readonly) NSString* path;
 +
 +/**
 + *  Returns the parsed and unescaped query component of the URL for the request.
 + *
 + *  @warning This property will be nil if there is no query in the URL.
 + */
 +@property(nonatomic, readonly) NSDictionary* query;
 +
 +/**
 + *  Returns the content type for the body of the request parsed from the
 + *  "Content-Type" header.
 + *
 + *  This property will be nil if the request has no body or set to
 + *  "application/octet-stream" if a body is present but there was no
 + *  "Content-Type" header.
 + */
 +@property(nonatomic, readonly) NSString* contentType;
 +
 +/**
 + *  Returns the content length for the body of the request parsed from the
 + *  "Content-Length" header.
 + *
 + *  This property will be set to "NSUIntegerMax" if the request has no body or
 + *  if there is a body but no "Content-Length" header, typically because
 + *  chunked transfer encoding is used.
 + */
 +@property(nonatomic, readonly) NSUInteger contentLength;
 +
 +/**
 + *  Returns the parsed "If-Modified-Since" header or nil if absent or malformed.
 + */
 +@property(nonatomic, readonly) NSDate* ifModifiedSince;
 +
 +/**
 + *  Returns the parsed "If-None-Match" header or nil if absent or malformed.
 + */
 +@property(nonatomic, readonly) NSString* ifNoneMatch;
 +
 +/**
 + *  Returns the parsed "Range" header or (NSUIntegerMax, 0) if absent or malformed.
 + *  The range will be set to (offset, length) if expressed from the beginning
 + *  of the entity body, or (NSUIntegerMax, length) if expressed from its end.
 + */
 +@property(nonatomic, readonly) NSRange byteRange;
 +
 +/**
 + *  Returns YES if the client supports gzip content encoding according to the
 + *  "Accept-Encoding" header.
 + */
 +@property(nonatomic, readonly) BOOL acceptsGzipContentEncoding;
 +
 +/**
++ *  Returns the address of the local peer (i.e. server) for the request
++ *  as a raw "struct sockaddr".
++ */
++@property(nonatomic, readonly) NSData* localAddressData;
++
++/**
++ *  Returns the address of the local peer (i.e. server) for the request
++ *  as a string.
++ */
++@property(nonatomic, readonly) NSString* localAddressString;
++
++/**
++ *  Returns the address of the remote peer (i.e. client) for the request
++ *  as a raw "struct sockaddr".
++ */
++@property(nonatomic, readonly) NSData* remoteAddressData;
++
++/**
++ *  Returns the address of the remote peer (i.e. client) for the request
++ *  as a string.
++ */
++@property(nonatomic, readonly) NSString* remoteAddressString;
++
++/**
 + *  This method is the designated initializer for the class.
 + */
 +- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query;
 +
 +/**
 + *  Convenience method that checks if the contentType property is defined.
 + */
 +- (BOOL)hasBody;
 +
 +/**
 + *  Convenience method that checks if the byteRange property is defined.
 + */
 +- (BOOL)hasByteRange;
 +
 +/**
 + *  Retrieves an attribute associated with this request using the given key.
 + *
 + *  @return The attribute value for the key.
 + */
 +- (id)attributeForKey:(NSString*)key;
 +
 +@end


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


Mime
View raw message