You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by sh...@apache.org on 2016/07/25 07:57:25 UTC
[39/57] [abbrv] cordova-plugins git commit: Squashed
'local-webserver/src/ios/GCDWebServer/' content from commit 15caa9c
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/1547b6bc/GCDWebServer/Core/GCDWebServerResponse.h
----------------------------------------------------------------------
diff --git a/GCDWebServer/Core/GCDWebServerResponse.h b/GCDWebServer/Core/GCDWebServerResponse.h
new file mode 100644
index 0000000..01ef2ab
--- /dev/null
+++ b/GCDWebServer/Core/GCDWebServerResponse.h
@@ -0,0 +1,208 @@
+/*
+ Copyright (c) 2012-2014, 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>
+
+/**
+ * The GCDWebServerBodyReaderCompletionBlock is passed by GCDWebServer to the
+ * GCDWebServerBodyReader object when reading data from it asynchronously.
+ */
+typedef void (^GCDWebServerBodyReaderCompletionBlock)(NSData* data, NSError* error);
+
+/**
+ * This protocol is used by the GCDWebServerConnection to communicate with
+ * the GCDWebServerResponse and read the HTTP body data to send.
+ *
+ * Note that multiple GCDWebServerBodyReader objects can be chained together
+ * internally e.g. to automatically apply gzip encoding to the content before
+ * passing it on to the GCDWebServerResponse.
+ *
+ * @warning These methods can be called on any GCD thread.
+ */
+@protocol GCDWebServerBodyReader <NSObject>
+
+@required
+
+/**
+ * This method is called before any body data is sent.
+ *
+ * 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 is sent.
+ *
+ * It should return a non-empty NSData if there is body data available,
+ * or an empty NSData there is no more body data, or nil on error and set
+ * the "error" argument which is guaranteed to be non-NULL.
+ */
+- (NSData*)readData:(NSError**)error;
+
+/**
+ * This method is called after all body data has been sent.
+ */
+- (void)close;
+
+@optional
+
+/**
+ * If this method is implemented, it will be preferred over -readData:.
+ *
+ * It must call the passed block when data is available, passing a non-empty
+ * NSData if there is body data available, or an empty NSData there is no more
+ * body data, or nil on error and pass an NSError along.
+ */
+- (void)asyncReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block;
+
+@end
+
+/**
+ * The GCDWebServerResponse class is used to wrap a single HTTP response.
+ * It is instantiated by the handler of the GCDWebServer that handled the request.
+ * If a body is present, the methods from the GCDWebServerBodyReader protocol
+ * will be called by the GCDWebServerConnection to send it.
+ *
+ * The default implementation of the GCDWebServerBodyReader protocol
+ * on the class simply returns an empty body.
+ *
+ * @warning GCDWebServerResponse instances can be created and used on any GCD thread.
+ */
+@interface GCDWebServerResponse : NSObject <GCDWebServerBodyReader>
+
+/**
+ * Sets the content type for the body of the response.
+ *
+ * The default value is nil i.e. the response has no body.
+ *
+ * @warning This property must be set if a body is present.
+ */
+@property(nonatomic, copy) NSString* contentType;
+
+/**
+ * Sets the content length for the body of the response. If a body is present
+ * but this property is set to "NSUIntegerMax", this means the length of the body
+ * cannot be known ahead of time. Chunked transfer encoding will be
+ * automatically enabled by the GCDWebServerConnection to comply with HTTP/1.1
+ * specifications.
+ *
+ * The default value is "NSUIntegerMax" i.e. the response has no body or its length
+ * is undefined.
+ */
+@property(nonatomic) NSUInteger contentLength;
+
+/**
+ * Sets the HTTP status code for the response.
+ *
+ * The default value is 200 i.e. "OK".
+ */
+@property(nonatomic) NSInteger statusCode;
+
+/**
+ * Sets the caching hint for the response using the "Cache-Control" header.
+ * This value is expressed in seconds.
+ *
+ * The default value is 0 i.e. "no-cache".
+ */
+@property(nonatomic) NSUInteger cacheControlMaxAge;
+
+/**
+ * Sets the last modified date for the response using the "Last-Modified" header.
+ *
+ * The default value is nil.
+ */
+@property(nonatomic, retain) NSDate* lastModifiedDate;
+
+/**
+ * Sets the ETag for the response using the "ETag" header.
+ *
+ * The default value is nil.
+ */
+@property(nonatomic, copy) NSString* eTag;
+
+/**
+ * Enables gzip encoding for the response body.
+ *
+ * The default value is NO.
+ *
+ * @warning Enabling gzip encoding will remove any "Content-Length" header
+ * since the length of the body is not known anymore. The client will still
+ * be able to determine the body length when connection is closed per
+ * HTTP/1.1 specifications.
+ */
+@property(nonatomic, getter=isGZipContentEncodingEnabled) BOOL gzipContentEncodingEnabled;
+
+/**
+ * Creates an empty response.
+ */
++ (instancetype)response;
+
+/**
+ * This method is the designated initializer for the class.
+ */
+- (instancetype)init;
+
+/**
+ * Sets an additional HTTP header on the response.
+ * Pass a nil value to remove an additional header.
+ *
+ * @warning Do not attempt to override the primary headers used
+ * by GCDWebServerResponse like "Content-Type", "ETag", etc...
+ */
+- (void)setValue:(NSString*)value forAdditionalHeader:(NSString*)header;
+
+/**
+ * Convenience method that checks if the contentType property is defined.
+ */
+- (BOOL)hasBody;
+
+@end
+
+@interface GCDWebServerResponse (Extensions)
+
+/**
+ * Creates a empty response with a specific HTTP status code.
+ */
++ (instancetype)responseWithStatusCode:(NSInteger)statusCode;
+
+/**
+ * Creates an HTTP redirect response to a new URL.
+ */
++ (instancetype)responseWithRedirect:(NSURL*)location permanent:(BOOL)permanent;
+
+/**
+ * Initializes an empty response with a specific HTTP status code.
+ */
+- (instancetype)initWithStatusCode:(NSInteger)statusCode;
+
+/**
+ * Initializes an HTTP redirect response to a new URL.
+ */
+- (instancetype)initWithRedirect:(NSURL*)location permanent:(BOOL)permanent;
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/1547b6bc/GCDWebServer/Core/GCDWebServerResponse.m
----------------------------------------------------------------------
diff --git a/GCDWebServer/Core/GCDWebServerResponse.m b/GCDWebServer/Core/GCDWebServerResponse.m
new file mode 100644
index 0000000..b0a220b
--- /dev/null
+++ b/GCDWebServer/Core/GCDWebServerResponse.m
@@ -0,0 +1,305 @@
+/*
+ Copyright (c) 2012-2014, 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 <zlib.h>
+
+#import "GCDWebServerPrivate.h"
+
+#define kZlibErrorDomain @"ZlibErrorDomain"
+#define kGZipInitialBufferSize (256 * 1024)
+
+@interface GCDWebServerBodyEncoder : NSObject <GCDWebServerBodyReader>
+- (id)initWithResponse:(GCDWebServerResponse*)response reader:(id<GCDWebServerBodyReader>)reader;
+@end
+
+@interface GCDWebServerGZipEncoder : GCDWebServerBodyEncoder
+@end
+
+@interface GCDWebServerBodyEncoder () {
+@private
+ GCDWebServerResponse* __unsafe_unretained _response;
+ id<GCDWebServerBodyReader> __unsafe_unretained _reader;
+}
+@end
+
+@implementation GCDWebServerBodyEncoder
+
+- (id)initWithResponse:(GCDWebServerResponse*)response reader:(id<GCDWebServerBodyReader>)reader {
+ if ((self = [super init])) {
+ _response = response;
+ _reader = reader;
+ }
+ return self;
+}
+
+- (BOOL)open:(NSError**)error {
+ return [_reader open:error];
+}
+
+- (NSData*)readData:(NSError**)error {
+ return [_reader readData:error];
+}
+
+- (void)close {
+ [_reader close];
+}
+
+@end
+
+@interface GCDWebServerGZipEncoder () {
+@private
+ z_stream _stream;
+ BOOL _finished;
+}
+@end
+
+@implementation GCDWebServerGZipEncoder
+
+- (id)initWithResponse:(GCDWebServerResponse*)response reader:(id<GCDWebServerBodyReader>)reader {
+ if ((self = [super initWithResponse:response reader:reader])) {
+ response.contentLength = NSUIntegerMax; // Make sure "Content-Length" header is not set since we don't know it
+ [response setValue:@"gzip" forAdditionalHeader:@"Content-Encoding"];
+ }
+ return self;
+}
+
+- (BOOL)open:(NSError**)error {
+ int result = deflateInit2(&_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
+ if (result != Z_OK) {
+ *error = [NSError errorWithDomain:kZlibErrorDomain code:result userInfo:nil];
+ return NO;
+ }
+ if (![super open:error]) {
+ deflateEnd(&_stream);
+ return NO;
+ }
+ return YES;
+}
+
+- (NSData*)readData:(NSError**)error {
+ NSMutableData* encodedData;
+ if (_finished) {
+ encodedData = [[NSMutableData alloc] init];
+ } else {
+ encodedData = [[NSMutableData alloc] initWithLength:kGZipInitialBufferSize];
+ if (encodedData == nil) {
+ GWS_DNOT_REACHED();
+ return nil;
+ }
+ NSUInteger length = 0;
+ do {
+ NSData* data = [super readData:error];
+ if (data == nil) {
+ return nil;
+ }
+ _stream.next_in = (Bytef*)data.bytes;
+ _stream.avail_in = (uInt)data.length;
+ while (1) {
+ NSUInteger maxLength = encodedData.length - length;
+ _stream.next_out = (Bytef*)((char*)encodedData.mutableBytes + length);
+ _stream.avail_out = (uInt)maxLength;
+ int result = deflate(&_stream, data.length ? Z_NO_FLUSH : Z_FINISH);
+ if (result == Z_STREAM_END) {
+ _finished = YES;
+ } else if (result != Z_OK) {
+ *error = [NSError errorWithDomain:kZlibErrorDomain code:result userInfo:nil];
+ return nil;
+ }
+ length += maxLength - _stream.avail_out;
+ if (_stream.avail_out > 0) {
+ break;
+ }
+ encodedData.length = 2 * encodedData.length; // zlib has used all the output buffer so resize it and try again in case more data is available
+ }
+ GWS_DCHECK(_stream.avail_in == 0);
+ } while (length == 0); // Make sure we don't return an empty NSData if not in finished state
+ encodedData.length = length;
+ }
+ return encodedData;
+}
+
+- (void)close {
+ deflateEnd(&_stream);
+ [super close];
+}
+
+@end
+
+@interface GCDWebServerResponse () {
+@private
+ NSString* _type;
+ NSUInteger _length;
+ NSInteger _status;
+ NSUInteger _maxAge;
+ NSDate* _lastModified;
+ NSString* _eTag;
+ NSMutableDictionary* _headers;
+ BOOL _chunked;
+ BOOL _gzipped;
+
+ BOOL _opened;
+ NSMutableArray* _encoders;
+ id<GCDWebServerBodyReader> __unsafe_unretained _reader;
+}
+@end
+
+@implementation GCDWebServerResponse
+
+@synthesize contentType=_type, contentLength=_length, statusCode=_status, cacheControlMaxAge=_maxAge, lastModifiedDate=_lastModified, eTag=_eTag,
+ gzipContentEncodingEnabled=_gzipped, additionalHeaders=_headers;
+
++ (instancetype)response {
+ return [[[self class] alloc] init];
+}
+
+- (instancetype)init {
+ if ((self = [super init])) {
+ _type = nil;
+ _length = NSUIntegerMax;
+ _status = kGCDWebServerHTTPStatusCode_OK;
+ _maxAge = 0;
+ _headers = [[NSMutableDictionary alloc] init];
+ _encoders = [[NSMutableArray alloc] init];
+ }
+ return self;
+}
+
+- (void)setValue:(NSString*)value forAdditionalHeader:(NSString*)header {
+ [_headers setValue:value forKey:header];
+}
+
+- (BOOL)hasBody {
+ return _type ? YES : NO;
+}
+
+- (BOOL)usesChunkedTransferEncoding {
+ return (_type != nil) && (_length == NSUIntegerMax);
+}
+
+- (BOOL)open:(NSError**)error {
+ return YES;
+}
+
+- (NSData*)readData:(NSError**)error {
+ return [NSData data];
+}
+
+- (void)close {
+ ;
+}
+
+- (void)prepareForReading {
+ _reader = self;
+ if (_gzipped) {
+ GCDWebServerGZipEncoder* encoder = [[GCDWebServerGZipEncoder alloc] initWithResponse:self reader:_reader];
+ [_encoders addObject:encoder];
+ _reader = encoder;
+ }
+}
+
+- (BOOL)performOpen:(NSError**)error {
+ GWS_DCHECK(_type);
+ GWS_DCHECK(_reader);
+ if (_opened) {
+ GWS_DNOT_REACHED();
+ return NO;
+ }
+ _opened = YES;
+ return [_reader open:error];
+}
+
+- (void)performReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block {
+ if ([_reader respondsToSelector:@selector(asyncReadDataWithCompletion:)]) {
+ [_reader asyncReadDataWithCompletion:block];
+ } else {
+ NSError* error = nil;
+ NSData* data = [_reader readData:&error];
+ block(data, error);
+ }
+}
+
+- (void)performClose {
+ GWS_DCHECK(_opened);
+ [_reader close];
+}
+
+- (NSString*)description {
+ NSMutableString* description = [NSMutableString stringWithFormat:@"Status Code = %i", (int)_status];
+ if (_type) {
+ [description appendFormat:@"\nContent Type = %@", _type];
+ }
+ if (_length != NSUIntegerMax) {
+ [description appendFormat:@"\nContent Length = %lu", (unsigned long)_length];
+ }
+ [description appendFormat:@"\nCache Control Max Age = %lu", (unsigned long)_maxAge];
+ if (_lastModified) {
+ [description appendFormat:@"\nLast Modified Date = %@", _lastModified];
+ }
+ if (_eTag) {
+ [description appendFormat:@"\nETag = %@", _eTag];
+ }
+ if (_headers.count) {
+ [description appendString:@"\n"];
+ for (NSString* header in [[_headers allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
+ [description appendFormat:@"\n%@: %@", header, [_headers objectForKey:header]];
+ }
+ }
+ return description;
+}
+
+@end
+
+@implementation GCDWebServerResponse (Extensions)
+
++ (instancetype)responseWithStatusCode:(NSInteger)statusCode {
+ return [[self alloc] initWithStatusCode:statusCode];
+}
+
++ (instancetype)responseWithRedirect:(NSURL*)location permanent:(BOOL)permanent {
+ return [[self alloc] initWithRedirect:location permanent:permanent];
+}
+
+- (instancetype)initWithStatusCode:(NSInteger)statusCode {
+ if ((self = [self init])) {
+ self.statusCode = statusCode;
+ }
+ return self;
+}
+
+- (instancetype)initWithRedirect:(NSURL*)location permanent:(BOOL)permanent {
+ if ((self = [self init])) {
+ self.statusCode = permanent ? kGCDWebServerHTTPStatusCode_MovedPermanently : kGCDWebServerHTTPStatusCode_TemporaryRedirect;
+ [self setValue:[location absoluteString] forAdditionalHeader:@"Location"];
+ }
+ return self;
+}
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/1547b6bc/GCDWebServer/Requests/GCDWebServerDataRequest.h
----------------------------------------------------------------------
diff --git a/GCDWebServer/Requests/GCDWebServerDataRequest.h b/GCDWebServer/Requests/GCDWebServerDataRequest.h
new file mode 100644
index 0000000..ef94b97
--- /dev/null
+++ b/GCDWebServer/Requests/GCDWebServerDataRequest.h
@@ -0,0 +1,60 @@
+/*
+ Copyright (c) 2012-2014, 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 "GCDWebServerRequest.h"
+
+/**
+ * The GCDWebServerDataRequest subclass of GCDWebServerRequest stores the body
+ * of the HTTP request in memory.
+ */
+@interface GCDWebServerDataRequest : GCDWebServerRequest
+
+/**
+ * Returns the data for the request body.
+ */
+@property(nonatomic, readonly) NSData* data;
+
+@end
+
+@interface GCDWebServerDataRequest (Extensions)
+
+/**
+ * Returns the data for the request body interpreted as text. If the content
+ * type of the body is not a text one, or if an error occurs, nil is returned.
+ *
+ * The text encoding used to interpret the data is extracted from the
+ * "Content-Type" header or defaults to UTF-8.
+ */
+@property(nonatomic, readonly) NSString* text;
+
+/**
+ * Returns the data for the request body interpreted as a JSON object. If the
+ * content type of the body is not JSON, or if an error occurs, nil is returned.
+ */
+@property(nonatomic, readonly) id jsonObject;
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/1547b6bc/GCDWebServer/Requests/GCDWebServerDataRequest.m
----------------------------------------------------------------------
diff --git a/GCDWebServer/Requests/GCDWebServerDataRequest.m b/GCDWebServer/Requests/GCDWebServerDataRequest.m
new file mode 100644
index 0000000..4f0ed75
--- /dev/null
+++ b/GCDWebServer/Requests/GCDWebServerDataRequest.m
@@ -0,0 +1,106 @@
+/*
+ Copyright (c) 2012-2014, 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 "GCDWebServerPrivate.h"
+
+@interface GCDWebServerDataRequest () {
+@private
+ NSMutableData* _data;
+
+ NSString* _text;
+ id _jsonObject;
+}
+@end
+
+@implementation GCDWebServerDataRequest
+
+@synthesize data=_data;
+
+- (BOOL)open:(NSError**)error {
+ if (self.contentLength != NSUIntegerMax) {
+ _data = [[NSMutableData alloc] initWithCapacity:self.contentLength];
+ } else {
+ _data = [[NSMutableData alloc] init];
+ }
+ if (_data == nil) {
+ *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Failed allocating memory"}];
+ return NO;
+ }
+ return YES;
+}
+
+- (BOOL)writeData:(NSData*)data error:(NSError**)error {
+ [_data appendData:data];
+ return YES;
+}
+
+- (BOOL)close:(NSError**)error {
+ return YES;
+}
+
+- (NSString*)description {
+ NSMutableString* description = [NSMutableString stringWithString:[super description]];
+ if (_data) {
+ [description appendString:@"\n\n"];
+ [description appendString:GCDWebServerDescribeData(_data, self.contentType)];
+ }
+ return description;
+}
+
+@end
+
+@implementation GCDWebServerDataRequest (Extensions)
+
+- (NSString*)text {
+ if (_text == nil) {
+ if ([self.contentType hasPrefix:@"text/"]) {
+ NSString* charset = GCDWebServerExtractHeaderValueParameter(self.contentType, @"charset");
+ _text = [[NSString alloc] initWithData:self.data encoding:GCDWebServerStringEncodingFromCharset(charset)];
+ } else {
+ GWS_DNOT_REACHED();
+ }
+ }
+ return _text;
+}
+
+- (id)jsonObject {
+ if (_jsonObject == nil) {
+ NSString* mimeType = GCDWebServerTruncateHeaderValue(self.contentType);
+ if ([mimeType isEqualToString:@"application/json"] || [mimeType isEqualToString:@"text/json"] || [mimeType isEqualToString:@"text/javascript"]) {
+ _jsonObject = [NSJSONSerialization JSONObjectWithData:_data options:0 error:NULL];
+ } else {
+ GWS_DNOT_REACHED();
+ }
+ }
+ return _jsonObject;
+}
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/1547b6bc/GCDWebServer/Requests/GCDWebServerFileRequest.h
----------------------------------------------------------------------
diff --git a/GCDWebServer/Requests/GCDWebServerFileRequest.h b/GCDWebServer/Requests/GCDWebServerFileRequest.h
new file mode 100644
index 0000000..427a800
--- /dev/null
+++ b/GCDWebServer/Requests/GCDWebServerFileRequest.h
@@ -0,0 +1,45 @@
+/*
+ Copyright (c) 2012-2014, 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 "GCDWebServerRequest.h"
+
+/**
+ * The GCDWebServerFileRequest subclass of GCDWebServerRequest stores the body
+ * of the HTTP request to a file on disk.
+ */
+@interface GCDWebServerFileRequest : GCDWebServerRequest
+
+/**
+ * Returns the path to the temporary file containing the request body.
+ *
+ * @warning This temporary file will be automatically deleted when the
+ * GCDWebServerFileRequest is deallocated. If you want to preserve this file,
+ * you must move it to a different location beforehand.
+ */
+@property(nonatomic, readonly) NSString* temporaryPath;
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/1547b6bc/GCDWebServer/Requests/GCDWebServerFileRequest.m
----------------------------------------------------------------------
diff --git a/GCDWebServer/Requests/GCDWebServerFileRequest.m b/GCDWebServer/Requests/GCDWebServerFileRequest.m
new file mode 100644
index 0000000..d0c2118
--- /dev/null
+++ b/GCDWebServer/Requests/GCDWebServerFileRequest.m
@@ -0,0 +1,103 @@
+/*
+ Copyright (c) 2012-2014, 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 "GCDWebServerPrivate.h"
+
+@interface GCDWebServerFileRequest () {
+@private
+ NSString* _temporaryPath;
+ int _file;
+}
+@end
+
+@implementation GCDWebServerFileRequest
+
+@synthesize temporaryPath=_temporaryPath;
+
+- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query {
+ if ((self = [super initWithMethod:method url:url headers:headers path:path query:query])) {
+ _temporaryPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ unlink([_temporaryPath fileSystemRepresentation]);
+}
+
+- (BOOL)open:(NSError**)error {
+ _file = open([_temporaryPath fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (_file <= 0) {
+ *error = GCDWebServerMakePosixError(errno);
+ return NO;
+ }
+ return YES;
+}
+
+- (BOOL)writeData:(NSData*)data error:(NSError**)error {
+ if (write(_file, data.bytes, data.length) != (ssize_t)data.length) {
+ *error = GCDWebServerMakePosixError(errno);
+ return NO;
+ }
+ return YES;
+}
+
+- (BOOL)close:(NSError**)error {
+ if (close(_file) < 0) {
+ *error = GCDWebServerMakePosixError(errno);
+ return NO;
+ }
+#ifdef __GCDWEBSERVER_ENABLE_TESTING__
+ NSString* creationDateHeader = [self.headers objectForKey:@"X-GCDWebServer-CreationDate"];
+ if (creationDateHeader) {
+ NSDate* date = GCDWebServerParseISO8601(creationDateHeader);
+ if (!date || ![[NSFileManager defaultManager] setAttributes:@{NSFileCreationDate: date} ofItemAtPath:_temporaryPath error:error]) {
+ return NO;
+ }
+ }
+ NSString* modifiedDateHeader = [self.headers objectForKey:@"X-GCDWebServer-ModifiedDate"];
+ if (modifiedDateHeader) {
+ NSDate* date = GCDWebServerParseRFC822(modifiedDateHeader);
+ if (!date || ![[NSFileManager defaultManager] setAttributes:@{NSFileModificationDate: date} ofItemAtPath:_temporaryPath error:error]) {
+ return NO;
+ }
+ }
+#endif
+ return YES;
+}
+
+- (NSString*)description {
+ NSMutableString* description = [NSMutableString stringWithString:[super description]];
+ [description appendFormat:@"\n\n{%@}", _temporaryPath];
+ return description;
+}
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/1547b6bc/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h
----------------------------------------------------------------------
diff --git a/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h b/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h
new file mode 100644
index 0000000..2463ca2
--- /dev/null
+++ b/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h
@@ -0,0 +1,132 @@
+/*
+ Copyright (c) 2012-2014, 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 "GCDWebServerRequest.h"
+
+/**
+ * The GCDWebServerMultiPart class is an abstract class that wraps the content
+ * of a part.
+ */
+@interface GCDWebServerMultiPart : NSObject
+
+/**
+ * Returns the control name retrieved from the part headers.
+ */
+@property(nonatomic, readonly) NSString* controlName;
+
+/**
+ * Returns the content type retrieved from the part headers or "text/plain"
+ * if not available (per HTTP specifications).
+ */
+@property(nonatomic, readonly) NSString* contentType;
+
+/**
+ * Returns the MIME type component of the content type for the part.
+ */
+@property(nonatomic, readonly) NSString* mimeType;
+
+@end
+
+/**
+ * The GCDWebServerMultiPartArgument subclass of GCDWebServerMultiPart wraps
+ * the content of a part as data in memory.
+ */
+@interface GCDWebServerMultiPartArgument : GCDWebServerMultiPart
+
+/**
+ * Returns the data for the part.
+ */
+@property(nonatomic, readonly) NSData* data;
+
+/**
+ * Returns the data for the part interpreted as text. If the content
+ * type of the part is not a text one, or if an error occurs, nil is returned.
+ *
+ * The text encoding used to interpret the data is extracted from the
+ * "Content-Type" header or defaults to UTF-8.
+ */
+@property(nonatomic, readonly) NSString* string;
+
+@end
+
+/**
+ * The GCDWebServerMultiPartFile subclass of GCDWebServerMultiPart wraps
+ * the content of a part as a file on disk.
+ */
+@interface GCDWebServerMultiPartFile : GCDWebServerMultiPart
+
+/**
+ * Returns the file name retrieved from the part headers.
+ */
+@property(nonatomic, readonly) NSString* fileName;
+
+/**
+ * Returns the path to the temporary file containing the part data.
+ *
+ * @warning This temporary file will be automatically deleted when the
+ * GCDWebServerMultiPartFile is deallocated. If you want to preserve this file,
+ * you must move it to a different location beforehand.
+ */
+@property(nonatomic, readonly) NSString* temporaryPath;
+
+@end
+
+/**
+ * The GCDWebServerMultiPartFormRequest subclass of GCDWebServerRequest
+ * parses the body of the HTTP request as a multipart encoded form.
+ */
+@interface GCDWebServerMultiPartFormRequest : GCDWebServerRequest
+
+/**
+ * Returns the argument parts from the multipart encoded form as
+ * name / GCDWebServerMultiPartArgument pairs.
+ */
+@property(nonatomic, readonly) NSArray* arguments;
+
+/**
+ * Returns the files parts from the multipart encoded form as
+ * name / GCDWebServerMultiPartFile pairs.
+ */
+@property(nonatomic, readonly) NSArray* files;
+
+/**
+ * Returns the MIME type for multipart encoded forms
+ * i.e. "multipart/form-data".
+ */
++ (NSString*)mimeType;
+
+/**
+ * Returns the first argument for a given control name or nil if not found.
+ */
+- (GCDWebServerMultiPartArgument*)firstArgumentForControlName:(NSString*)name;
+
+/**
+ * Returns the first file for a given control name or nil if not found.
+ */
+- (GCDWebServerMultiPartFile*)firstFileForControlName:(NSString*)name;
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/1547b6bc/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.m
----------------------------------------------------------------------
diff --git a/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.m b/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.m
new file mode 100644
index 0000000..e1c0015
--- /dev/null
+++ b/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.m
@@ -0,0 +1,439 @@
+/*
+ Copyright (c) 2012-2014, 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 "GCDWebServerPrivate.h"
+
+#define kMultiPartBufferSize (256 * 1024)
+
+typedef enum {
+ kParserState_Undefined = 0,
+ kParserState_Start,
+ kParserState_Headers,
+ kParserState_Content,
+ kParserState_End
+} ParserState;
+
+@interface GCDWebServerMIMEStreamParser : NSObject
+- (id)initWithBoundary:(NSString*)boundary defaultControlName:(NSString*)name arguments:(NSMutableArray*)arguments files:(NSMutableArray*)files;
+- (BOOL)appendBytes:(const void*)bytes length:(NSUInteger)length;
+- (BOOL)isAtEnd;
+@end
+
+static NSData* _newlineData = nil;
+static NSData* _newlinesData = nil;
+static NSData* _dashNewlineData = nil;
+
+@interface GCDWebServerMultiPart () {
+@private
+ NSString* _controlName;
+ NSString* _contentType;
+ NSString* _mimeType;
+}
+@end
+
+@implementation GCDWebServerMultiPart
+
+@synthesize controlName=_controlName, contentType=_contentType, mimeType=_mimeType;
+
+- (id)initWithControlName:(NSString*)name contentType:(NSString*)type {
+ if ((self = [super init])) {
+ _controlName = [name copy];
+ _contentType = [type copy];
+ _mimeType = GCDWebServerTruncateHeaderValue(_contentType);
+ }
+ return self;
+}
+
+@end
+
+@interface GCDWebServerMultiPartArgument () {
+@private
+ NSData* _data;
+ NSString* _string;
+}
+@end
+
+@implementation GCDWebServerMultiPartArgument
+
+@synthesize data=_data, string=_string;
+
+- (id)initWithControlName:(NSString*)name contentType:(NSString*)type data:(NSData*)data {
+ if ((self = [super initWithControlName:name contentType:type])) {
+ _data = data;
+
+ if ([self.contentType hasPrefix:@"text/"]) {
+ NSString* charset = GCDWebServerExtractHeaderValueParameter(self.contentType, @"charset");
+ _string = [[NSString alloc] initWithData:_data encoding:GCDWebServerStringEncodingFromCharset(charset)];
+ }
+ }
+ return self;
+}
+
+- (NSString*)description {
+ return [NSString stringWithFormat:@"<%@ | '%@' | %lu bytes>", [self class], self.mimeType, (unsigned long)_data.length];
+}
+
+@end
+
+@interface GCDWebServerMultiPartFile () {
+@private
+ NSString* _fileName;
+ NSString* _temporaryPath;
+}
+@end
+
+@implementation GCDWebServerMultiPartFile
+
+@synthesize fileName=_fileName, temporaryPath=_temporaryPath;
+
+- (id)initWithControlName:(NSString*)name contentType:(NSString*)type fileName:(NSString*)fileName temporaryPath:(NSString*)temporaryPath {
+ if ((self = [super initWithControlName:name contentType:type])) {
+ _fileName = [fileName copy];
+ _temporaryPath = [temporaryPath copy];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ unlink([_temporaryPath fileSystemRepresentation]);
+}
+
+- (NSString*)description {
+ return [NSString stringWithFormat:@"<%@ | '%@' | '%@>'", [self class], self.mimeType, _fileName];
+}
+
+@end
+
+@interface GCDWebServerMIMEStreamParser () {
+@private
+ NSData* _boundary;
+ NSString* _defaultcontrolName;
+ ParserState _state;
+ NSMutableData* _data;
+ NSMutableArray* _arguments;
+ NSMutableArray* _files;
+
+ NSString* _controlName;
+ NSString* _fileName;
+ NSString* _contentType;
+ NSString* _tmpPath;
+ int _tmpFile;
+ GCDWebServerMIMEStreamParser* _subParser;
+}
+@end
+
+@implementation GCDWebServerMIMEStreamParser
+
++ (void)initialize {
+ if (_newlineData == nil) {
+ _newlineData = [[NSData alloc] initWithBytes:"\r\n" length:2];
+ GWS_DCHECK(_newlineData);
+ }
+ if (_newlinesData == nil) {
+ _newlinesData = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4];
+ GWS_DCHECK(_newlinesData);
+ }
+ if (_dashNewlineData == nil) {
+ _dashNewlineData = [[NSData alloc] initWithBytes:"--\r\n" length:4];
+ GWS_DCHECK(_dashNewlineData);
+ }
+}
+
+- (id)initWithBoundary:(NSString*)boundary defaultControlName:(NSString*)name arguments:(NSMutableArray*)arguments files:(NSMutableArray*)files {
+ NSData* data = boundary.length ? [[NSString stringWithFormat:@"--%@", boundary] dataUsingEncoding:NSASCIIStringEncoding] : nil;
+ if (data == nil) {
+ GWS_DNOT_REACHED();
+ return nil;
+ }
+ if ((self = [super init])) {
+ _boundary = data;
+ _defaultcontrolName = name;
+ _arguments = arguments;
+ _files = files;
+ _data = [[NSMutableData alloc] initWithCapacity:kMultiPartBufferSize];
+ _state = kParserState_Start;
+ }
+ return self;
+}
+
+- (void)dealloc {
+ if (_tmpFile > 0) {
+ close(_tmpFile);
+ unlink([_tmpPath fileSystemRepresentation]);
+ }
+}
+
+// http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2
+- (BOOL)_parseData {
+ BOOL success = YES;
+
+ if (_state == kParserState_Headers) {
+ NSRange range = [_data rangeOfData:_newlinesData options:0 range:NSMakeRange(0, _data.length)];
+ if (range.location != NSNotFound) {
+
+ _controlName = nil;
+ _fileName = nil;
+ _contentType = nil;
+ _tmpPath = nil;
+ _subParser = nil;
+ NSString* headers = [[NSString alloc] initWithData:[_data subdataWithRange:NSMakeRange(0, range.location)] encoding:NSUTF8StringEncoding];
+ if (headers) {
+ for (NSString* header in [headers componentsSeparatedByString:@"\r\n"]) {
+ NSRange subRange = [header rangeOfString:@":"];
+ if (subRange.location != NSNotFound) {
+ NSString* name = [header substringToIndex:subRange.location];
+ NSString* value = [[header substringFromIndex:(subRange.location + subRange.length)] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
+ if ([name caseInsensitiveCompare:@"Content-Type"] == NSOrderedSame) {
+ _contentType = GCDWebServerNormalizeHeaderValue(value);
+ } else if ([name caseInsensitiveCompare:@"Content-Disposition"] == NSOrderedSame) {
+ NSString* contentDisposition = GCDWebServerNormalizeHeaderValue(value);
+ if ([GCDWebServerTruncateHeaderValue(contentDisposition) isEqualToString:@"form-data"]) {
+ _controlName = GCDWebServerExtractHeaderValueParameter(contentDisposition, @"name");
+ _fileName = GCDWebServerExtractHeaderValueParameter(contentDisposition, @"filename");
+ } else if ([GCDWebServerTruncateHeaderValue(contentDisposition) isEqualToString:@"file"]) {
+ _controlName = _defaultcontrolName;
+ _fileName = GCDWebServerExtractHeaderValueParameter(contentDisposition, @"filename");
+ }
+ }
+ } else {
+ GWS_DNOT_REACHED();
+ }
+ }
+ if (_contentType == nil) {
+ _contentType = @"text/plain";
+ }
+ } else {
+ GWS_LOG_ERROR(@"Failed decoding headers in part of 'multipart/form-data'");
+ GWS_DNOT_REACHED();
+ }
+ if (_controlName) {
+ if ([GCDWebServerTruncateHeaderValue(_contentType) isEqualToString:@"multipart/mixed"]) {
+ NSString* boundary = GCDWebServerExtractHeaderValueParameter(_contentType, @"boundary");
+ _subParser = [[GCDWebServerMIMEStreamParser alloc] initWithBoundary:boundary defaultControlName:_controlName arguments:_arguments files:_files];
+ if (_subParser == nil) {
+ GWS_DNOT_REACHED();
+ success = NO;
+ }
+ } else if (_fileName) {
+ NSString* path = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];
+ _tmpFile = open([path fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (_tmpFile > 0) {
+ _tmpPath = [path copy];
+ } else {
+ GWS_DNOT_REACHED();
+ success = NO;
+ }
+ }
+ } else {
+ GWS_DNOT_REACHED();
+ success = NO;
+ }
+
+ [_data replaceBytesInRange:NSMakeRange(0, range.location + range.length) withBytes:NULL length:0];
+ _state = kParserState_Content;
+ }
+ }
+
+ if ((_state == kParserState_Start) || (_state == kParserState_Content)) {
+ NSRange range = [_data rangeOfData:_boundary options:0 range:NSMakeRange(0, _data.length)];
+ if (range.location != NSNotFound) {
+ NSRange subRange = NSMakeRange(range.location + range.length, _data.length - range.location - range.length);
+ NSRange subRange1 = [_data rangeOfData:_newlineData options:NSDataSearchAnchored range:subRange];
+ NSRange subRange2 = [_data rangeOfData:_dashNewlineData options:NSDataSearchAnchored range:subRange];
+ if ((subRange1.location != NSNotFound) || (subRange2.location != NSNotFound)) {
+
+ if (_state == kParserState_Content) {
+ const void* dataBytes = _data.bytes;
+ NSUInteger dataLength = range.location - 2;
+ if (_subParser) {
+ if (![_subParser appendBytes:dataBytes length:(dataLength + 2)] || ![_subParser isAtEnd]) {
+ GWS_DNOT_REACHED();
+ success = NO;
+ }
+ _subParser = nil;
+ } else if (_tmpPath) {
+ ssize_t result = write(_tmpFile, dataBytes, dataLength);
+ if (result == (ssize_t)dataLength) {
+ if (close(_tmpFile) == 0) {
+ _tmpFile = 0;
+ GCDWebServerMultiPartFile* file = [[GCDWebServerMultiPartFile alloc] initWithControlName:_controlName contentType:_contentType fileName:_fileName temporaryPath:_tmpPath];
+ [_files addObject:file];
+ } else {
+ GWS_DNOT_REACHED();
+ success = NO;
+ }
+ } else {
+ GWS_DNOT_REACHED();
+ success = NO;
+ }
+ _tmpPath = nil;
+ } else {
+ NSData* data = [[NSData alloc] initWithBytes:(void*)dataBytes length:dataLength];
+ GCDWebServerMultiPartArgument* argument = [[GCDWebServerMultiPartArgument alloc] initWithControlName:_controlName contentType:_contentType data:data];
+ [_arguments addObject:argument];
+ }
+ }
+
+ if (subRange1.location != NSNotFound) {
+ [_data replaceBytesInRange:NSMakeRange(0, subRange1.location + subRange1.length) withBytes:NULL length:0];
+ _state = kParserState_Headers;
+ success = [self _parseData];
+ } else {
+ _state = kParserState_End;
+ }
+ }
+ } else {
+ NSUInteger margin = 2 * _boundary.length;
+ if (_data.length > margin) {
+ NSUInteger length = _data.length - margin;
+ if (_subParser) {
+ if ([_subParser appendBytes:_data.bytes length:length]) {
+ [_data replaceBytesInRange:NSMakeRange(0, length) withBytes:NULL length:0];
+ } else {
+ GWS_DNOT_REACHED();
+ success = NO;
+ }
+ } else if (_tmpPath) {
+ ssize_t result = write(_tmpFile, _data.bytes, length);
+ if (result == (ssize_t)length) {
+ [_data replaceBytesInRange:NSMakeRange(0, length) withBytes:NULL length:0];
+ } else {
+ GWS_DNOT_REACHED();
+ success = NO;
+ }
+ }
+ }
+ }
+ }
+
+ return success;
+}
+
+- (BOOL)appendBytes:(const void*)bytes length:(NSUInteger)length {
+ [_data appendBytes:bytes length:length];
+ return [self _parseData];
+}
+
+- (BOOL)isAtEnd {
+ return (_state == kParserState_End);
+}
+
+@end
+
+@interface GCDWebServerMultiPartFormRequest () {
+@private
+ GCDWebServerMIMEStreamParser* _parser;
+ NSMutableArray* _arguments;
+ NSMutableArray* _files;
+}
+@end
+
+@implementation GCDWebServerMultiPartFormRequest
+
+@synthesize arguments=_arguments, files=_files;
+
++ (NSString*)mimeType {
+ return @"multipart/form-data";
+}
+
+- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query {
+ if ((self = [super initWithMethod:method url:url headers:headers path:path query:query])) {
+ _arguments = [[NSMutableArray alloc] init];
+ _files = [[NSMutableArray alloc] init];
+ }
+ return self;
+}
+
+- (BOOL)open:(NSError**)error {
+ NSString* boundary = GCDWebServerExtractHeaderValueParameter(self.contentType, @"boundary");
+ _parser = [[GCDWebServerMIMEStreamParser alloc] initWithBoundary:boundary defaultControlName:nil arguments:_arguments files:_files];
+ if (_parser == nil) {
+ *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Failed starting to parse multipart form data"}];
+ return NO;
+ }
+ return YES;
+}
+
+- (BOOL)writeData:(NSData*)data error:(NSError**)error {
+ if (![_parser appendBytes:data.bytes length:data.length]) {
+ *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Failed continuing to parse multipart form data"}];
+ return NO;
+ }
+ return YES;
+}
+
+- (BOOL)close:(NSError**)error {
+ BOOL atEnd = [_parser isAtEnd];
+ _parser = nil;
+ if (!atEnd) {
+ *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Failed finishing to parse multipart form data"}];
+ return NO;
+ }
+ return YES;
+}
+
+- (GCDWebServerMultiPartArgument*)firstArgumentForControlName:(NSString*)name {
+ for (GCDWebServerMultiPartArgument* argument in _arguments) {
+ if ([argument.controlName isEqualToString:name]) {
+ return argument;
+ }
+ }
+ return nil;
+}
+
+- (GCDWebServerMultiPartFile*)firstFileForControlName:(NSString*)name {
+ for (GCDWebServerMultiPartFile* file in _files) {
+ if ([file.controlName isEqualToString:name]) {
+ return file;
+ }
+ }
+ return nil;
+}
+
+- (NSString*)description {
+ NSMutableString* description = [NSMutableString stringWithString:[super description]];
+ if (_arguments.count) {
+ [description appendString:@"\n"];
+ for (GCDWebServerMultiPartArgument* argument in _arguments) {
+ [description appendFormat:@"\n%@ (%@)\n", argument.controlName, argument.contentType];
+ [description appendString:GCDWebServerDescribeData(argument.data, argument.contentType)];
+ }
+ }
+ if (_files.count) {
+ [description appendString:@"\n"];
+ for (GCDWebServerMultiPartFile* file in _files) {
+ [description appendFormat:@"\n%@ (%@): %@\n{%@}", file.controlName, file.contentType, file.fileName, file.temporaryPath];
+ }
+ }
+ return description;
+}
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/1547b6bc/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h
----------------------------------------------------------------------
diff --git a/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h b/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h
new file mode 100644
index 0000000..e36eac3
--- /dev/null
+++ b/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h
@@ -0,0 +1,51 @@
+/*
+ Copyright (c) 2012-2014, 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 "GCDWebServerDataRequest.h"
+
+/**
+ * The GCDWebServerURLEncodedFormRequest subclass of GCDWebServerRequest
+ * parses the body of the HTTP request as a URL encoded form using
+ * GCDWebServerParseURLEncodedForm().
+ */
+@interface GCDWebServerURLEncodedFormRequest : GCDWebServerDataRequest
+
+/**
+ * Returns the unescaped control names and values for the URL encoded form.
+ *
+ * The text encoding used to interpret the data is extracted from the
+ * "Content-Type" header or defaults to UTF-8.
+ */
+@property(nonatomic, readonly) NSDictionary* arguments;
+
+/**
+ * Returns the MIME type for URL encoded forms
+ * i.e. "application/x-www-form-urlencoded".
+ */
++ (NSString*)mimeType;
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/1547b6bc/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.m
----------------------------------------------------------------------
diff --git a/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.m b/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.m
new file mode 100644
index 0000000..f210fa0
--- /dev/null
+++ b/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.m
@@ -0,0 +1,70 @@
+/*
+ Copyright (c) 2012-2014, 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 "GCDWebServerPrivate.h"
+
+@interface GCDWebServerURLEncodedFormRequest () {
+@private
+ NSDictionary* _arguments;
+}
+@end
+
+@implementation GCDWebServerURLEncodedFormRequest
+
+@synthesize arguments=_arguments;
+
++ (NSString*)mimeType {
+ return @"application/x-www-form-urlencoded";
+}
+
+- (BOOL)close:(NSError**)error {
+ if (![super close:error]) {
+ return NO;
+ }
+
+ NSString* charset = GCDWebServerExtractHeaderValueParameter(self.contentType, @"charset");
+ NSString* string = [[NSString alloc] initWithData:self.data encoding:GCDWebServerStringEncodingFromCharset(charset)];
+ _arguments = GCDWebServerParseURLEncodedForm(string);
+ GWS_DCHECK(_arguments);
+
+ return YES;
+}
+
+- (NSString*)description {
+ NSMutableString* description = [NSMutableString stringWithString:[super description]];
+ [description appendString:@"\n"];
+ for (NSString* argument in [[_arguments allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
+ [description appendFormat:@"\n%@ = %@", argument, [_arguments objectForKey:argument]];
+ }
+ return description;
+}
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/1547b6bc/GCDWebServer/Responses/GCDWebServerDataResponse.h
----------------------------------------------------------------------
diff --git a/GCDWebServer/Responses/GCDWebServerDataResponse.h b/GCDWebServer/Responses/GCDWebServerDataResponse.h
new file mode 100644
index 0000000..b0c6493
--- /dev/null
+++ b/GCDWebServer/Responses/GCDWebServerDataResponse.h
@@ -0,0 +1,108 @@
+/*
+ Copyright (c) 2012-2014, 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 "GCDWebServerResponse.h"
+
+/**
+ * The GCDWebServerDataResponse subclass of GCDWebServerResponse reads the body
+ * of the HTTP response from memory.
+ */
+@interface GCDWebServerDataResponse : GCDWebServerResponse
+
+/**
+ * Creates a response with data in memory and a given content type.
+ */
++ (instancetype)responseWithData:(NSData*)data contentType:(NSString*)type;
+
+/**
+ * This method is the designated initializer for the class.
+ */
+- (instancetype)initWithData:(NSData*)data contentType:(NSString*)type;
+
+@end
+
+@interface GCDWebServerDataResponse (Extensions)
+
+/**
+ * Creates a data response from text encoded using UTF-8.
+ */
++ (instancetype)responseWithText:(NSString*)text;
+
+/**
+ * Creates a data response from HTML encoded using UTF-8.
+ */
++ (instancetype)responseWithHTML:(NSString*)html;
+
+/**
+ * Creates a data response from an HTML template encoded using UTF-8.
+ * See -initWithHTMLTemplate:variables: for details.
+ */
++ (instancetype)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables;
+
+/**
+ * Creates a data response from a serialized JSON object and the default
+ * "application/json" content type.
+ */
++ (instancetype)responseWithJSONObject:(id)object;
+
+/**
+ * Creates a data response from a serialized JSON object and a custom
+ * content type.
+ */
++ (instancetype)responseWithJSONObject:(id)object contentType:(NSString*)type;
+
+/**
+ * Initializes a data response from text encoded using UTF-8.
+ */
+- (instancetype)initWithText:(NSString*)text;
+
+/**
+ * Initializes a data response from HTML encoded using UTF-8.
+ */
+- (instancetype)initWithHTML:(NSString*)html;
+
+/**
+ * Initializes a data response from an HTML template encoded using UTF-8.
+ *
+ * All occurences of "%variable%" within the HTML template are replaced with
+ * their corresponding values.
+ */
+- (instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables;
+
+/**
+ * Initializes a data response from a serialized JSON object and the default
+ * "application/json" content type.
+ */
+- (instancetype)initWithJSONObject:(id)object;
+
+/**
+ * Initializes a data response from a serialized JSON object and a custom
+ * content type.
+ */
+- (instancetype)initWithJSONObject:(id)object contentType:(NSString*)type;
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/1547b6bc/GCDWebServer/Responses/GCDWebServerDataResponse.m
----------------------------------------------------------------------
diff --git a/GCDWebServer/Responses/GCDWebServerDataResponse.m b/GCDWebServer/Responses/GCDWebServerDataResponse.m
new file mode 100644
index 0000000..ea02799
--- /dev/null
+++ b/GCDWebServer/Responses/GCDWebServerDataResponse.m
@@ -0,0 +1,143 @@
+/*
+ Copyright (c) 2012-2014, 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 "GCDWebServerPrivate.h"
+
+@interface GCDWebServerDataResponse () {
+@private
+ NSData* _data;
+ BOOL _done;
+}
+@end
+
+@implementation GCDWebServerDataResponse
+
++ (instancetype)responseWithData:(NSData*)data contentType:(NSString*)type {
+ return [[[self class] alloc] initWithData:data contentType:type];
+}
+
+- (instancetype)initWithData:(NSData*)data contentType:(NSString*)type {
+ if (data == nil) {
+ GWS_DNOT_REACHED();
+ return nil;
+ }
+
+ if ((self = [super init])) {
+ _data = data;
+
+ self.contentType = type;
+ self.contentLength = data.length;
+ }
+ return self;
+}
+
+- (NSData*)readData:(NSError**)error {
+ NSData* data;
+ if (_done) {
+ data = [NSData data];
+ } else {
+ data = _data;
+ _done = YES;
+ }
+ return data;
+}
+
+- (NSString*)description {
+ NSMutableString* description = [NSMutableString stringWithString:[super description]];
+ [description appendString:@"\n\n"];
+ [description appendString:GCDWebServerDescribeData(_data, self.contentType)];
+ return description;
+}
+
+@end
+
+@implementation GCDWebServerDataResponse (Extensions)
+
++ (instancetype)responseWithText:(NSString*)text {
+ return [[self alloc] initWithText:text];
+}
+
++ (instancetype)responseWithHTML:(NSString*)html {
+ return [[self alloc] initWithHTML:html];
+}
+
++ (instancetype)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables {
+ return [[self alloc] initWithHTMLTemplate:path variables:variables];
+}
+
++ (instancetype)responseWithJSONObject:(id)object {
+ return [[self alloc] initWithJSONObject:object];
+}
+
++ (instancetype)responseWithJSONObject:(id)object contentType:(NSString*)type {
+ return [[self alloc] initWithJSONObject:object contentType:type];
+}
+
+- (instancetype)initWithText:(NSString*)text {
+ NSData* data = [text dataUsingEncoding:NSUTF8StringEncoding];
+ if (data == nil) {
+ GWS_DNOT_REACHED();
+ return nil;
+ }
+ return [self initWithData:data contentType:@"text/plain; charset=utf-8"];
+}
+
+- (instancetype)initWithHTML:(NSString*)html {
+ NSData* data = [html dataUsingEncoding:NSUTF8StringEncoding];
+ if (data == nil) {
+ GWS_DNOT_REACHED();
+ return nil;
+ }
+ return [self initWithData:data contentType:@"text/html; charset=utf-8"];
+}
+
+- (instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables {
+ NSMutableString* html = [[NSMutableString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
+ [variables enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSString* value, BOOL* stop) {
+ [html replaceOccurrencesOfString:[NSString stringWithFormat:@"%%%@%%", key] withString:value options:0 range:NSMakeRange(0, html.length)];
+ }];
+ id response = [self initWithHTML:html];
+ return response;
+}
+
+- (instancetype)initWithJSONObject:(id)object {
+ return [self initWithJSONObject:object contentType:@"application/json"];
+}
+
+- (instancetype)initWithJSONObject:(id)object contentType:(NSString*)type {
+ NSData* data = [NSJSONSerialization dataWithJSONObject:object options:0 error:NULL];
+ if (data == nil) {
+ return nil;
+ }
+ return [self initWithData:data contentType:type];
+}
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/1547b6bc/GCDWebServer/Responses/GCDWebServerErrorResponse.h
----------------------------------------------------------------------
diff --git a/GCDWebServer/Responses/GCDWebServerErrorResponse.h b/GCDWebServer/Responses/GCDWebServerErrorResponse.h
new file mode 100644
index 0000000..381b122
--- /dev/null
+++ b/GCDWebServer/Responses/GCDWebServerErrorResponse.h
@@ -0,0 +1,81 @@
+/*
+ Copyright (c) 2012-2014, 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 "GCDWebServerDataResponse.h"
+#import "GCDWebServerHTTPStatusCodes.h"
+
+/**
+ * The GCDWebServerDataResponse subclass of GCDWebServerDataResponse generates
+ * an HTML body from an HTTP status code and an error message.
+ */
+@interface GCDWebServerErrorResponse : GCDWebServerDataResponse
+
+/**
+ * Creates a client error response with the corresponding HTTP status code.
+ */
++ (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3);
+
+/**
+ * Creates a server error response with the corresponding HTTP status code.
+ */
++ (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3);
+
+/**
+ * Creates a client error response with the corresponding HTTP status code
+ * and an underlying NSError.
+ */
++ (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4);
+
+/**
+ * Creates a server error response with the corresponding HTTP status code
+ * and an underlying NSError.
+ */
++ (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4);
+
+/**
+ * Initializes a client error response with the corresponding HTTP status code.
+ */
+- (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3);
+
+/**
+ * Initializes a server error response with the corresponding HTTP status code.
+ */
+- (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3);
+
+/**
+ * Initializes a client error response with the corresponding HTTP status code
+ * and an underlying NSError.
+ */
+- (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4);
+
+/**
+ * Initializes a server error response with the corresponding HTTP status code
+ * and an underlying NSError.
+ */
+- (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4);
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/1547b6bc/GCDWebServer/Responses/GCDWebServerErrorResponse.m
----------------------------------------------------------------------
diff --git a/GCDWebServer/Responses/GCDWebServerErrorResponse.m b/GCDWebServer/Responses/GCDWebServerErrorResponse.m
new file mode 100644
index 0000000..c2e4422
--- /dev/null
+++ b/GCDWebServer/Responses/GCDWebServerErrorResponse.m
@@ -0,0 +1,128 @@
+/*
+ Copyright (c) 2012-2014, 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 "GCDWebServerPrivate.h"
+
+@interface GCDWebServerErrorResponse ()
+- (instancetype)initWithStatusCode:(NSInteger)statusCode underlyingError:(NSError*)underlyingError messageFormat:(NSString*)format arguments:(va_list)arguments;
+@end
+
+@implementation GCDWebServerErrorResponse
+
++ (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... {
+ GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
+ va_list arguments;
+ va_start(arguments, format);
+ GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments];
+ va_end(arguments);
+ return response;
+}
+
++ (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... {
+ GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
+ va_list arguments;
+ va_start(arguments, format);
+ GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments];
+ va_end(arguments);
+ return response;
+}
+
++ (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... {
+ GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
+ va_list arguments;
+ va_start(arguments, format);
+ GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments];
+ va_end(arguments);
+ return response;
+}
+
++ (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... {
+ GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
+ va_list arguments;
+ va_start(arguments, format);
+ GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments];
+ va_end(arguments);
+ return response;
+}
+
+static inline NSString* _EscapeHTMLString(NSString* string) {
+ return [string stringByReplacingOccurrencesOfString:@"\"" withString:@"""];
+}
+
+- (instancetype)initWithStatusCode:(NSInteger)statusCode underlyingError:(NSError*)underlyingError messageFormat:(NSString*)format arguments:(va_list)arguments {
+ NSString* message = [[NSString alloc] initWithFormat:format arguments:arguments];
+ NSString* title = [NSString stringWithFormat:@"HTTP Error %i", (int)statusCode];
+ NSString* error = underlyingError ? [NSString stringWithFormat:@"[%@] %@ (%li)", underlyingError.domain, _EscapeHTMLString(underlyingError.localizedDescription), (long)underlyingError.code] : @"";
+ NSString* html = [NSString stringWithFormat:@"<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"utf-8\"><title>%@</title></head><body><h1>%@: %@</h1><h3>%@</h3></body></html>",
+ title, title, _EscapeHTMLString(message), error];
+ if ((self = [self initWithHTML:html])) {
+ self.statusCode = statusCode;
+ }
+ return self;
+}
+
+- (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... {
+ GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
+ va_list arguments;
+ va_start(arguments, format);
+ self = [self initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments];
+ va_end(arguments);
+ return self;
+}
+
+- (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... {
+ GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
+ va_list arguments;
+ va_start(arguments, format);
+ self = [self initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments];
+ va_end(arguments);
+ return self;
+}
+
+- (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... {
+ GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
+ va_list arguments;
+ va_start(arguments, format);
+ self = [self initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments];
+ va_end(arguments);
+ return self;
+}
+
+- (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... {
+ GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
+ va_list arguments;
+ va_start(arguments, format);
+ self = [self initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments];
+ va_end(arguments);
+ return self;
+}
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/1547b6bc/GCDWebServer/Responses/GCDWebServerFileResponse.h
----------------------------------------------------------------------
diff --git a/GCDWebServer/Responses/GCDWebServerFileResponse.h b/GCDWebServer/Responses/GCDWebServerFileResponse.h
new file mode 100644
index 0000000..19d284d
--- /dev/null
+++ b/GCDWebServer/Responses/GCDWebServerFileResponse.h
@@ -0,0 +1,96 @@
+/*
+ Copyright (c) 2012-2014, 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 "GCDWebServerResponse.h"
+
+/**
+ * The GCDWebServerFileResponse subclass of GCDWebServerResponse reads the body
+ * of the HTTP response from a file on disk.
+ *
+ * It will automatically set the contentType, lastModifiedDate and eTag
+ * properties of the GCDWebServerResponse according to the file extension and
+ * metadata.
+ */
+@interface GCDWebServerFileResponse : GCDWebServerResponse
+
+/**
+ * Creates a response with the contents of a file.
+ */
++ (instancetype)responseWithFile:(NSString*)path;
+
+/**
+ * Creates a response like +responseWithFile: and sets the "Content-Disposition"
+ * HTTP header for a download if the "attachment" argument is YES.
+ */
++ (instancetype)responseWithFile:(NSString*)path isAttachment:(BOOL)attachment;
+
+/**
+ * Creates a response like +responseWithFile: but restricts the file contents
+ * to a specific byte range.
+ *
+ * See -initWithFile:byteRange: for details.
+ */
++ (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range;
+
+/**
+ * Creates a response like +responseWithFile:byteRange: and sets the
+ * "Content-Disposition" HTTP header for a download if the "attachment"
+ * argument is YES.
+ */
++ (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment;
+
+/**
+ * Initializes a response with the contents of a file.
+ */
+- (instancetype)initWithFile:(NSString*)path;
+
+/**
+ * Initializes a response like +responseWithFile: and sets the
+ * "Content-Disposition" HTTP header for a download if the "attachment"
+ * argument is YES.
+ */
+- (instancetype)initWithFile:(NSString*)path isAttachment:(BOOL)attachment;
+
+/**
+ * Initializes a response like -initWithFile: but restricts the file contents
+ * to a specific byte range. This range should be set to (NSUIntegerMax, 0) for
+ * the full file, (offset, length) if expressed from the beginning of the file,
+ * or (NSUIntegerMax, length) if expressed from the end of the file. The "offset"
+ * and "length" values will be automatically adjusted to be compatible with the
+ * actual size of the file.
+ *
+ * This argument would typically be set to the value of the byteRange property
+ * of the current GCDWebServerRequest.
+ */
+- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range;
+
+/**
+ * This method is the designated initializer for the class.
+ */
+- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment;
+
+@end
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org