",
85 | title, title, _EscapeHTMLString(message), error];
86 | if ((self = [self initWithHTML:html])) {
87 | self.statusCode = statusCode;
88 | }
89 | return self;
90 | }
91 |
92 | - (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... {
93 | GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
94 | va_list arguments;
95 | va_start(arguments, format);
96 | self = [self initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments];
97 | va_end(arguments);
98 | return self;
99 | }
100 |
101 | - (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... {
102 | GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
103 | va_list arguments;
104 | va_start(arguments, format);
105 | self = [self initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments];
106 | va_end(arguments);
107 | return self;
108 | }
109 |
110 | - (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... {
111 | GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
112 | va_list arguments;
113 | va_start(arguments, format);
114 | self = [self initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments];
115 | va_end(arguments);
116 | return self;
117 | }
118 |
119 | - (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... {
120 | GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
121 | va_list arguments;
122 | va_start(arguments, format);
123 | self = [self initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments];
124 | va_end(arguments);
125 | return self;
126 | }
127 |
128 | @end
129 |
--------------------------------------------------------------------------------
/CocoaLogToWebServer/Classes/DBClass/FMDatabaseQueue.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabaseQueue.h
3 | // fmdb
4 | //
5 | // Created by August Mueller on 6/22/11.
6 | // Copyright 2011 Flying Meat Inc. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class FMDatabase;
12 |
13 | /** To perform queries and updates on multiple threads, you'll want to use `FMDatabaseQueue`.
14 |
15 | Using a single instance of `` from multiple threads at once is a bad idea. It has always been OK to make a `` object *per thread*. Just don't share a single instance across threads, and definitely not across multiple threads at the same time.
16 |
17 | Instead, use `FMDatabaseQueue`. Here's how to use it:
18 |
19 | First, make your queue.
20 |
21 | FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];
22 |
23 | Then use it like so:
24 |
25 | [queue inDatabase:^(FMDatabase *db) {
26 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
27 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
28 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];
29 |
30 | FMResultSet *rs = [db executeQuery:@"select * from foo"];
31 | while ([rs next]) {
32 | //…
33 | }
34 | }];
35 |
36 | An easy way to wrap things up in a transaction can be done like this:
37 |
38 | [queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
39 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
40 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
41 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];
42 |
43 | if (whoopsSomethingWrongHappened) {
44 | *rollback = YES;
45 | return;
46 | }
47 | // etc…
48 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];
49 | }];
50 |
51 | `FMDatabaseQueue` will run the blocks on a serialized queue (hence the name of the class). So if you call `FMDatabaseQueue`'s methods from multiple threads at the same time, they will be executed in the order they are received. This way queries and updates won't step on each other's toes, and every one is happy.
52 |
53 | ### See also
54 |
55 | - ``
56 |
57 | @warning Do not instantiate a single `` object and use it across multiple threads. Use `FMDatabaseQueue` instead.
58 |
59 | @warning The calls to `FMDatabaseQueue`'s methods are blocking. So even though you are passing along blocks, they will **not** be run on another thread.
60 |
61 | */
62 |
63 | @interface FMDatabaseQueue : NSObject {
64 | NSString *_path;
65 | dispatch_queue_t _queue;
66 | FMDatabase *_db;
67 | int _openFlags;
68 | NSString *_vfsName;
69 | }
70 |
71 | /** Path of database */
72 |
73 | @property (atomic, retain) NSString *path;
74 |
75 | /** Open flags */
76 |
77 | @property (atomic, readonly) int openFlags;
78 |
79 | /** Custom virtual file system name */
80 |
81 | @property (atomic, copy) NSString *vfsName;
82 |
83 | ///----------------------------------------------------
84 | /// @name Initialization, opening, and closing of queue
85 | ///----------------------------------------------------
86 |
87 | /** Create queue using path.
88 |
89 | @param aPath The file path of the database.
90 |
91 | @return The `FMDatabaseQueue` object. `nil` on error.
92 | */
93 |
94 | + (instancetype)databaseQueueWithPath:(NSString*)aPath;
95 |
96 | /** Create queue using path and specified flags.
97 |
98 | @param aPath The file path of the database.
99 | @param openFlags Flags passed to the openWithFlags method of the database
100 |
101 | @return The `FMDatabaseQueue` object. `nil` on error.
102 | */
103 | + (instancetype)databaseQueueWithPath:(NSString*)aPath flags:(int)openFlags;
104 |
105 | /** Create queue using path.
106 |
107 | @param aPath The file path of the database.
108 |
109 | @return The `FMDatabaseQueue` object. `nil` on error.
110 | */
111 |
112 | - (instancetype)initWithPath:(NSString*)aPath;
113 |
114 | /** Create queue using path and specified flags.
115 |
116 | @param aPath The file path of the database.
117 | @param openFlags Flags passed to the openWithFlags method of the database
118 |
119 | @return The `FMDatabaseQueue` object. `nil` on error.
120 | */
121 |
122 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags;
123 |
124 | /** Create queue using path and specified flags.
125 |
126 | @param aPath The file path of the database.
127 | @param openFlags Flags passed to the openWithFlags method of the database
128 | @param vfsName The name of a custom virtual file system
129 |
130 | @return The `FMDatabaseQueue` object. `nil` on error.
131 | */
132 |
133 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags vfs:(NSString *)vfsName;
134 |
135 | /** Returns the Class of 'FMDatabase' subclass, that will be used to instantiate database object.
136 |
137 | Subclasses can override this method to return specified Class of 'FMDatabase' subclass.
138 |
139 | @return The Class of 'FMDatabase' subclass, that will be used to instantiate database object.
140 | */
141 |
142 | + (Class)databaseClass;
143 |
144 | /** Close database used by queue. */
145 |
146 | - (void)close;
147 |
148 | ///-----------------------------------------------
149 | /// @name Dispatching database operations to queue
150 | ///-----------------------------------------------
151 |
152 | /** Synchronously perform database operations on queue.
153 |
154 | @param block The code to be run on the queue of `FMDatabaseQueue`
155 | */
156 |
157 | - (void)inDatabase:(void (^)(FMDatabase *db))block;
158 |
159 | /** Synchronously perform database operations on queue, using transactions.
160 |
161 | @param block The code to be run on the queue of `FMDatabaseQueue`
162 | */
163 |
164 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
165 |
166 | /** Synchronously perform database operations on queue, using deferred transactions.
167 |
168 | @param block The code to be run on the queue of `FMDatabaseQueue`
169 | */
170 |
171 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
172 |
173 | ///-----------------------------------------------
174 | /// @name Dispatching database operations to queue
175 | ///-----------------------------------------------
176 |
177 | /** Synchronously perform database operations using save point.
178 |
179 | @param block The code to be run on the queue of `FMDatabaseQueue`
180 | */
181 |
182 | // NOTE: you can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock.
183 | // If you need to nest, use FMDatabase's startSavePointWithName:error: instead.
184 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block;
185 |
186 | @end
187 |
188 |
--------------------------------------------------------------------------------
/CocoaLogToWebServer/Classes/GCDWebServer/Core/GCDWebServerConnection.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2012-2015, Pierre-Olivier Latour
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | * The name of Pierre-Olivier Latour may not be used to endorse
13 | or promote products derived from this software without specific
14 | prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | #import "GCDWebServer.h"
29 |
30 | @class GCDWebServerHandler;
31 |
32 | /**
33 | * The GCDWebServerConnection class is instantiated by GCDWebServer to handle
34 | * each new HTTP connection. Each instance stays alive until the connection is
35 | * closed.
36 | *
37 | * You cannot use this class directly, but it is made public so you can
38 | * subclass it to override some hooks. Use the GCDWebServerOption_ConnectionClass
39 | * option for GCDWebServer to install your custom subclass.
40 | *
41 | * @warning The GCDWebServerConnection retains the GCDWebServer until the
42 | * connection is closed.
43 | */
44 | @interface GCDWebServerConnection : NSObject
45 |
46 | /**
47 | * Returns the GCDWebServer that owns the connection.
48 | */
49 | @property(nonatomic, readonly) GCDWebServer* server;
50 |
51 | /**
52 | * Returns YES if the connection is using IPv6.
53 | */
54 | @property(nonatomic, readonly, getter=isUsingIPv6) BOOL usingIPv6;
55 |
56 | /**
57 | * Returns the address of the local peer (i.e. server) of the connection
58 | * as a raw "struct sockaddr".
59 | */
60 | @property(nonatomic, readonly) NSData* localAddressData;
61 |
62 | /**
63 | * Returns the address of the local peer (i.e. server) of the connection
64 | * as a string.
65 | */
66 | @property(nonatomic, readonly) NSString* localAddressString;
67 |
68 | /**
69 | * Returns the address of the remote peer (i.e. client) of the connection
70 | * as a raw "struct sockaddr".
71 | */
72 | @property(nonatomic, readonly) NSData* remoteAddressData;
73 |
74 | /**
75 | * Returns the address of the remote peer (i.e. client) of the connection
76 | * as a string.
77 | */
78 | @property(nonatomic, readonly) NSString* remoteAddressString;
79 |
80 | /**
81 | * Returns the total number of bytes received from the remote peer (i.e. client)
82 | * so far.
83 | */
84 | @property(nonatomic, readonly) NSUInteger totalBytesRead;
85 |
86 | /**
87 | * Returns the total number of bytes sent to the remote peer (i.e. client) so far.
88 | */
89 | @property(nonatomic, readonly) NSUInteger totalBytesWritten;
90 |
91 | @end
92 |
93 | /**
94 | * Hooks to customize the behavior of GCDWebServer HTTP connections.
95 | *
96 | * @warning These methods can be called on any GCD thread.
97 | * Be sure to also call "super" when overriding them.
98 | */
99 | @interface GCDWebServerConnection (Subclassing)
100 |
101 | /**
102 | * This method is called when the connection is opened.
103 | *
104 | * Return NO to reject the connection e.g. after validating the local
105 | * or remote address.
106 | */
107 | - (BOOL)open;
108 |
109 | /**
110 | * This method is called whenever data has been received
111 | * from the remote peer (i.e. client).
112 | *
113 | * @warning Do not attempt to modify this data.
114 | */
115 | - (void)didReadBytes:(const void*)bytes length:(NSUInteger)length;
116 |
117 | /**
118 | * This method is called whenever data has been sent
119 | * to the remote peer (i.e. client).
120 | *
121 | * @warning Do not attempt to modify this data.
122 | */
123 | - (void)didWriteBytes:(const void*)bytes length:(NSUInteger)length;
124 |
125 | /**
126 | * This method is called after the HTTP headers have been received to
127 | * allow replacing the request URL by another one.
128 | *
129 | * The default implementation returns the original URL.
130 | */
131 | - (NSURL*)rewriteRequestURL:(NSURL*)url withMethod:(NSString*)method headers:(NSDictionary*)headers;
132 |
133 | /**
134 | * Assuming a valid HTTP request was received, this method is called before
135 | * the request is processed.
136 | *
137 | * Return a non-nil GCDWebServerResponse to bypass the request processing entirely.
138 | *
139 | * The default implementation checks for HTTP authentication if applicable
140 | * and returns a barebone 401 status code response if authentication failed.
141 | */
142 | - (GCDWebServerResponse*)preflightRequest:(GCDWebServerRequest*)request;
143 |
144 | /**
145 | * Assuming a valid HTTP request was received and -preflightRequest: returned nil,
146 | * this method is called to process the request by executing the handler's
147 | * process block.
148 | */
149 | - (void)processRequest:(GCDWebServerRequest*)request completion:(GCDWebServerCompletionBlock)completion;
150 |
151 | /**
152 | * Assuming a valid HTTP request was received and either -preflightRequest:
153 | * or -processRequest:completion: returned a non-nil GCDWebServerResponse,
154 | * this method is called to override the response.
155 | *
156 | * You can either modify the current response and return it, or return a
157 | * completely new one.
158 | *
159 | * The default implementation replaces any response matching the "ETag" or
160 | * "Last-Modified-Date" header of the request by a barebone "Not-Modified" (304)
161 | * one.
162 | */
163 | - (GCDWebServerResponse*)overrideResponse:(GCDWebServerResponse*)response forRequest:(GCDWebServerRequest*)request;
164 |
165 | /**
166 | * This method is called if any error happens while validing or processing
167 | * the request or if no GCDWebServerResponse was generated during processing.
168 | *
169 | * @warning If the request was invalid (e.g. the HTTP headers were malformed),
170 | * the "request" argument will be nil.
171 | */
172 | - (void)abortRequest:(GCDWebServerRequest*)request withStatusCode:(NSInteger)statusCode;
173 |
174 | /**
175 | * Called when the connection is closed.
176 | */
177 | - (void)close;
178 |
179 | @end
180 |
--------------------------------------------------------------------------------
/CocoaLogToWebServer/Classes/DDLogClass/DDTTYLogger.h:
--------------------------------------------------------------------------------
1 | // Software License Agreement (BSD License)
2 | //
3 | // Copyright (c) 2010-2016, Deusty, LLC
4 | // All rights reserved.
5 | //
6 | // Redistribution and use of this software in source and binary forms,
7 | // with or without modification, are permitted provided that the following conditions are met:
8 | //
9 | // * Redistributions of source code must retain the above copyright notice,
10 | // this list of conditions and the following disclaimer.
11 | //
12 | // * Neither the name of Deusty nor the names of its contributors may be used
13 | // to endorse or promote products derived from this software without specific
14 | // prior written permission of Deusty, LLC.
15 |
16 | // Disable legacy macros
17 | #ifndef DD_LEGACY_MACROS
18 | #define DD_LEGACY_MACROS 0
19 | #endif
20 |
21 | #import "DDLog.h"
22 |
23 | #define LOG_CONTEXT_ALL INT_MAX
24 |
25 | #pragma clang diagnostic push
26 | #pragma clang diagnostic ignored "-Wunused-function"
27 | #if TARGET_OS_IPHONE
28 | // iOS
29 | #import
30 | typedef UIColor DDColor;
31 | static inline DDColor* DDMakeColor(CGFloat r, CGFloat g, CGFloat b) {return [DDColor colorWithRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f];}
32 | #elif defined(DD_CLI) || !__has_include()
33 | // OS X CLI
34 | #import "CLIColor.h"
35 | typedef CLIColor DDColor;
36 | static inline DDColor* DDMakeColor(CGFloat r, CGFloat g, CGFloat b) {return [DDColor colorWithCalibratedRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f];}
37 | #else
38 | // OS X with AppKit
39 | #import
40 | typedef NSColor DDColor;
41 | static inline DDColor* DDMakeColor(CGFloat r, CGFloat g, CGFloat b) {return [DDColor colorWithCalibratedRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f];}
42 | #endif
43 | #pragma clang diagnostic pop
44 |
45 |
46 | /**
47 | * This class provides a logger for Terminal output or Xcode console output,
48 | * depending on where you are running your code.
49 | *
50 | * As described in the "Getting Started" page,
51 | * the traditional NSLog() function directs it's output to two places:
52 | *
53 | * - Apple System Log (so it shows up in Console.app)
54 | * - StdErr (if stderr is a TTY, so log statements show up in Xcode console)
55 | *
56 | * To duplicate NSLog() functionality you can simply add this logger and an asl logger.
57 | * However, if you instead choose to use file logging (for faster performance),
58 | * you may choose to use only a file logger and a tty logger.
59 | **/
60 | @interface DDTTYLogger : DDAbstractLogger
61 |
62 | /**
63 | * Singleton method
64 | */
65 | + (instancetype)sharedInstance;
66 |
67 | /* Inherited from the DDLogger protocol:
68 | *
69 | * Formatters may optionally be added to any logger.
70 | *
71 | * If no formatter is set, the logger simply logs the message as it is given in logMessage,
72 | * or it may use its own built in formatting style.
73 | *
74 | * More information about formatters can be found here:
75 | * Documentation/CustomFormatters.md
76 | *
77 | * The actual implementation of these methods is inherited from DDAbstractLogger.
78 |
79 | - (id )logFormatter;
80 | - (void)setLogFormatter:(id )formatter;
81 |
82 | */
83 |
84 | /**
85 | * Want to use different colors for different log levels?
86 | * Enable this property.
87 | *
88 | * If you run the application via the Terminal (not Xcode),
89 | * the logger will map colors to xterm-256color or xterm-color (if available).
90 | *
91 | * Xcode does NOT natively support colors in the Xcode debugging console.
92 | * You'll need to install the XcodeColors plugin to see colors in the Xcode console.
93 | * https://github.com/robbiehanson/XcodeColors
94 | *
95 | * The default value is NO.
96 | **/
97 | @property (readwrite, assign) BOOL colorsEnabled;
98 |
99 | /**
100 | * When using a custom formatter you can set the `logMessage` method not to append
101 | * `\n` character after each output. This allows for some greater flexibility with
102 | * custom formatters. Default value is YES.
103 | **/
104 | @property (nonatomic, readwrite, assign) BOOL automaticallyAppendNewlineForCustomFormatters;
105 |
106 | /**
107 | * The default color set (foregroundColor, backgroundColor) is:
108 | *
109 | * - DDLogFlagError = (red, nil)
110 | * - DDLogFlagWarning = (orange, nil)
111 | *
112 | * You can customize the colors however you see fit.
113 | * Please note that you are passing a flag, NOT a level.
114 | *
115 | * GOOD : [ttyLogger setForegroundColor:pink backgroundColor:nil forFlag:DDLogFlagInfo]; // <- Good :)
116 | * BAD : [ttyLogger setForegroundColor:pink backgroundColor:nil forFlag:DDLogLevelInfo]; // <- BAD! :(
117 | *
118 | * DDLogFlagInfo = 0...00100
119 | * DDLogLevelInfo = 0...00111 <- Would match DDLogFlagInfo and DDLogFlagWarning and DDLogFlagError
120 | *
121 | * If you run the application within Xcode, then the XcodeColors plugin is required.
122 | *
123 | * If you run the application from a shell, then DDTTYLogger will automatically map the given color to
124 | * the closest available color. (xterm-256color or xterm-color which have 256 and 16 supported colors respectively.)
125 | *
126 | * This method invokes setForegroundColor:backgroundColor:forFlag:context: and applies it to `LOG_CONTEXT_ALL`.
127 | **/
128 | - (void)setForegroundColor:(DDColor *)txtColor backgroundColor:(DDColor *)bgColor forFlag:(DDLogFlag)mask;
129 |
130 | /**
131 | * Just like setForegroundColor:backgroundColor:flag, but allows you to specify a particular logging context.
132 | *
133 | * A logging context is often used to identify log messages coming from a 3rd party framework,
134 | * although logging context's can be used for many different functions.
135 | *
136 | * Use LOG_CONTEXT_ALL to set the deafult color for all contexts that have no specific color set defined.
137 | *
138 | * Logging context's are explained in further detail here:
139 | * Documentation/CustomContext.md
140 | **/
141 | - (void)setForegroundColor:(DDColor *)txtColor backgroundColor:(DDColor *)bgColor forFlag:(DDLogFlag)mask context:(NSInteger)ctxt;
142 |
143 | /**
144 | * Similar to the methods above, but allows you to map DDLogMessage->tag to a particular color profile.
145 | * For example, you could do something like this:
146 | *
147 | * static NSString *const PurpleTag = @"PurpleTag";
148 | *
149 | * #define DDLogPurple(frmt, ...) LOG_OBJC_TAG_MACRO(NO, 0, 0, 0, PurpleTag, frmt, ##__VA_ARGS__)
150 | *
151 | * And then where you configure CocoaLumberjack:
152 | *
153 | * purple = DDMakeColor((64/255.0), (0/255.0), (128/255.0));
154 | *
155 | * or any UIColor/NSColor constructor.
156 | *
157 | * Note: For CLI OS X projects that don't link with AppKit use CLIColor objects instead
158 | *
159 | * [[DDTTYLogger sharedInstance] setForegroundColor:purple backgroundColor:nil forTag:PurpleTag];
160 | * [DDLog addLogger:[DDTTYLogger sharedInstance]];
161 | *
162 | * This would essentially give you a straight NSLog replacement that prints in purple:
163 | *
164 | * DDLogPurple(@"I'm a purple log message!");
165 | **/
166 | - (void)setForegroundColor:(DDColor *)txtColor backgroundColor:(DDColor *)bgColor forTag:(id )tag;
167 |
168 | /**
169 | * Clearing color profiles.
170 | **/
171 | - (void)clearColorsForFlag:(DDLogFlag)mask;
172 | - (void)clearColorsForFlag:(DDLogFlag)mask context:(NSInteger)context;
173 | - (void)clearColorsForTag:(id )tag;
174 | - (void)clearColorsForAllFlags;
175 | - (void)clearColorsForAllTags;
176 | - (void)clearAllColors;
177 |
178 | @end
179 |
--------------------------------------------------------------------------------
/CocoaLogToWebServer/Classes/GCDWebServer/Responses/GCDWebServerFileResponse.m:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2012-2015, Pierre-Olivier Latour
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | * The name of Pierre-Olivier Latour may not be used to endorse
13 | or promote products derived from this software without specific
14 | prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | #if !__has_feature(objc_arc)
29 | #error GCDWebServer requires ARC
30 | #endif
31 |
32 | #import
33 |
34 | #import "GCDWebServerPrivate.h"
35 |
36 | #define kFileReadBufferSize (32 * 1024)
37 |
38 | @interface GCDWebServerFileResponse () {
39 | @private
40 | NSString* _path;
41 | NSUInteger _offset;
42 | NSUInteger _size;
43 | int _file;
44 | }
45 | @end
46 |
47 | @implementation GCDWebServerFileResponse
48 |
49 | + (instancetype)responseWithFile:(NSString*)path {
50 | return [[[self class] alloc] initWithFile:path];
51 | }
52 |
53 | + (instancetype)responseWithFile:(NSString*)path isAttachment:(BOOL)attachment {
54 | return [[[self class] alloc] initWithFile:path isAttachment:attachment];
55 | }
56 |
57 | + (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range {
58 | return [[[self class] alloc] initWithFile:path byteRange:range];
59 | }
60 |
61 | + (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment {
62 | return [[[self class] alloc] initWithFile:path byteRange:range isAttachment:attachment];
63 | }
64 |
65 | - (instancetype)initWithFile:(NSString*)path {
66 | return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:NO];
67 | }
68 |
69 | - (instancetype)initWithFile:(NSString*)path isAttachment:(BOOL)attachment {
70 | return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:attachment];
71 | }
72 |
73 | - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range {
74 | return [self initWithFile:path byteRange:range isAttachment:NO];
75 | }
76 |
77 | static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) {
78 | return [NSDate dateWithTimeIntervalSince1970:((NSTimeInterval)t->tv_sec + (NSTimeInterval)t->tv_nsec / 1000000000.0)];
79 | }
80 |
81 | - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment {
82 | struct stat info;
83 | if (lstat([path fileSystemRepresentation], &info) || !(info.st_mode & S_IFREG)) {
84 | GWS_DNOT_REACHED();
85 | return nil;
86 | }
87 | #ifndef __LP64__
88 | if (info.st_size >= (off_t)4294967295) { // In 32 bit mode, we can't handle files greater than 4 GiBs (don't use "NSUIntegerMax" here to avoid potential unsigned to signed conversion issues)
89 | GWS_DNOT_REACHED();
90 | return nil;
91 | }
92 | #endif
93 | NSUInteger fileSize = (NSUInteger)info.st_size;
94 |
95 | BOOL hasByteRange = GCDWebServerIsValidByteRange(range);
96 | if (hasByteRange) {
97 | if (range.location != NSUIntegerMax) {
98 | range.location = MIN(range.location, fileSize);
99 | range.length = MIN(range.length, fileSize - range.location);
100 | } else {
101 | range.length = MIN(range.length, fileSize);
102 | range.location = fileSize - range.length;
103 | }
104 | if (range.length == 0) {
105 | return nil; // TODO: Return 416 status code and "Content-Range: bytes */{file length}" header
106 | }
107 | } else {
108 | range.location = 0;
109 | range.length = fileSize;
110 | }
111 |
112 | if ((self = [super init])) {
113 | _path = [path copy];
114 | _offset = range.location;
115 | _size = range.length;
116 | if (hasByteRange) {
117 | [self setStatusCode:kGCDWebServerHTTPStatusCode_PartialContent];
118 | [self setValue:[NSString stringWithFormat:@"bytes %lu-%lu/%lu", (unsigned long)_offset, (unsigned long)(_offset + _size - 1), (unsigned long)fileSize] forAdditionalHeader:@"Content-Range"];
119 | GWS_LOG_DEBUG(@"Using content bytes range [%lu-%lu] for file \"%@\"", (unsigned long)_offset, (unsigned long)(_offset + _size - 1), path);
120 | }
121 |
122 | if (attachment) {
123 | NSString* fileName = [path lastPathComponent];
124 | NSData* data = [[fileName stringByReplacingOccurrencesOfString:@"\"" withString:@""] dataUsingEncoding:NSISOLatin1StringEncoding allowLossyConversion:YES];
125 | NSString* lossyFileName = data ? [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding] : nil;
126 | if (lossyFileName) {
127 | NSString* value = [NSString stringWithFormat:@"attachment; filename=\"%@\"; filename*=UTF-8''%@", lossyFileName, GCDWebServerEscapeURLString(fileName)];
128 | [self setValue:value forAdditionalHeader:@"Content-Disposition"];
129 | } else {
130 | GWS_DNOT_REACHED();
131 | }
132 | }
133 |
134 | self.contentType = GCDWebServerGetMimeTypeForExtension([_path pathExtension]);
135 | self.contentLength = _size;
136 | self.lastModifiedDate = _NSDateFromTimeSpec(&info.st_mtimespec);
137 | self.eTag = [NSString stringWithFormat:@"%llu/%li/%li", info.st_ino, info.st_mtimespec.tv_sec, info.st_mtimespec.tv_nsec];
138 | }
139 | return self;
140 | }
141 |
142 | - (BOOL)open:(NSError**)error {
143 | _file = open([_path fileSystemRepresentation], O_NOFOLLOW | O_RDONLY);
144 | if (_file <= 0) {
145 | if (error) {
146 | *error = GCDWebServerMakePosixError(errno);
147 | }
148 | return NO;
149 | }
150 | if (lseek(_file, _offset, SEEK_SET) != (off_t)_offset) {
151 | if (error) {
152 | *error = GCDWebServerMakePosixError(errno);
153 | }
154 | close(_file);
155 | return NO;
156 | }
157 | return YES;
158 | }
159 |
160 | - (NSData*)readData:(NSError**)error {
161 | size_t length = MIN((NSUInteger)kFileReadBufferSize, _size);
162 | NSMutableData* data = [[NSMutableData alloc] initWithLength:length];
163 | ssize_t result = read(_file, data.mutableBytes, length);
164 | if (result < 0) {
165 | if (error) {
166 | *error = GCDWebServerMakePosixError(errno);
167 | }
168 | return nil;
169 | }
170 | if (result > 0) {
171 | [data setLength:result];
172 | _size -= result;
173 | }
174 | return data;
175 | }
176 |
177 | - (void)close {
178 | close(_file);
179 | }
180 |
181 | - (NSString*)description {
182 | NSMutableString* description = [NSMutableString stringWithString:[super description]];
183 | [description appendFormat:@"\n\n{%@}", _path];
184 | return description;
185 | }
186 |
187 | @end
188 |
--------------------------------------------------------------------------------
/CocoaLogToWebServer/Classes/GCDWebServer/Core/GCDWebServerResponse.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2012-2015, Pierre-Olivier Latour
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | * The name of Pierre-Olivier Latour may not be used to endorse
13 | or promote products derived from this software without specific
14 | prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | #import
29 |
30 | /**
31 | * The GCDWebServerBodyReaderCompletionBlock is passed by GCDWebServer to the
32 | * GCDWebServerBodyReader object when reading data from it asynchronously.
33 | */
34 | typedef void (^GCDWebServerBodyReaderCompletionBlock)(NSData* data, NSError* error);
35 |
36 | /**
37 | * This protocol is used by the GCDWebServerConnection to communicate with
38 | * the GCDWebServerResponse and read the HTTP body data to send.
39 | *
40 | * Note that multiple GCDWebServerBodyReader objects can be chained together
41 | * internally e.g. to automatically apply gzip encoding to the content before
42 | * passing it on to the GCDWebServerResponse.
43 | *
44 | * @warning These methods can be called on any GCD thread.
45 | */
46 | @protocol GCDWebServerBodyReader
47 |
48 | @required
49 |
50 | /**
51 | * This method is called before any body data is sent.
52 | *
53 | * It should return YES on success or NO on failure and set the "error" argument
54 | * which is guaranteed to be non-NULL.
55 | */
56 | - (BOOL)open:(NSError**)error;
57 |
58 | /**
59 | * This method is called whenever body data is sent.
60 | *
61 | * It should return a non-empty NSData if there is body data available,
62 | * or an empty NSData there is no more body data, or nil on error and set
63 | * the "error" argument which is guaranteed to be non-NULL.
64 | */
65 | - (NSData*)readData:(NSError**)error;
66 |
67 | /**
68 | * This method is called after all body data has been sent.
69 | */
70 | - (void)close;
71 |
72 | @optional
73 |
74 | /**
75 | * If this method is implemented, it will be preferred over -readData:.
76 | *
77 | * It must call the passed block when data is available, passing a non-empty
78 | * NSData if there is body data available, or an empty NSData there is no more
79 | * body data, or nil on error and pass an NSError along.
80 | */
81 | - (void)asyncReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block;
82 |
83 | @end
84 |
85 | /**
86 | * The GCDWebServerResponse class is used to wrap a single HTTP response.
87 | * It is instantiated by the handler of the GCDWebServer that handled the request.
88 | * If a body is present, the methods from the GCDWebServerBodyReader protocol
89 | * will be called by the GCDWebServerConnection to send it.
90 | *
91 | * The default implementation of the GCDWebServerBodyReader protocol
92 | * on the class simply returns an empty body.
93 | *
94 | * @warning GCDWebServerResponse instances can be created and used on any GCD thread.
95 | */
96 | @interface GCDWebServerResponse : NSObject
97 |
98 | /**
99 | * Sets the content type for the body of the response.
100 | *
101 | * The default value is nil i.e. the response has no body.
102 | *
103 | * @warning This property must be set if a body is present.
104 | */
105 | @property(nonatomic, copy) NSString* contentType;
106 |
107 | /**
108 | * Sets the content length for the body of the response. If a body is present
109 | * but this property is set to "NSUIntegerMax", this means the length of the body
110 | * cannot be known ahead of time. Chunked transfer encoding will be
111 | * automatically enabled by the GCDWebServerConnection to comply with HTTP/1.1
112 | * specifications.
113 | *
114 | * The default value is "NSUIntegerMax" i.e. the response has no body or its length
115 | * is undefined.
116 | */
117 | @property(nonatomic) NSUInteger contentLength;
118 |
119 | /**
120 | * Sets the HTTP status code for the response.
121 | *
122 | * The default value is 200 i.e. "OK".
123 | */
124 | @property(nonatomic) NSInteger statusCode;
125 |
126 | /**
127 | * Sets the caching hint for the response using the "Cache-Control" header.
128 | * This value is expressed in seconds.
129 | *
130 | * The default value is 0 i.e. "no-cache".
131 | */
132 | @property(nonatomic) NSUInteger cacheControlMaxAge;
133 |
134 | /**
135 | * Sets the last modified date for the response using the "Last-Modified" header.
136 | *
137 | * The default value is nil.
138 | */
139 | @property(nonatomic, retain) NSDate* lastModifiedDate;
140 |
141 | /**
142 | * Sets the ETag for the response using the "ETag" header.
143 | *
144 | * The default value is nil.
145 | */
146 | @property(nonatomic, copy) NSString* eTag;
147 |
148 | /**
149 | * Enables gzip encoding for the response body.
150 | *
151 | * The default value is NO.
152 | *
153 | * @warning Enabling gzip encoding will remove any "Content-Length" header
154 | * since the length of the body is not known anymore. The client will still
155 | * be able to determine the body length when connection is closed per
156 | * HTTP/1.1 specifications.
157 | */
158 | @property(nonatomic, getter=isGZipContentEncodingEnabled) BOOL gzipContentEncodingEnabled;
159 |
160 | /**
161 | * Creates an empty response.
162 | */
163 | + (instancetype)response;
164 |
165 | /**
166 | * This method is the designated initializer for the class.
167 | */
168 | - (instancetype)init;
169 |
170 | /**
171 | * Sets an additional HTTP header on the response.
172 | * Pass a nil value to remove an additional header.
173 | *
174 | * @warning Do not attempt to override the primary headers used
175 | * by GCDWebServerResponse like "Content-Type", "ETag", etc...
176 | */
177 | - (void)setValue:(NSString*)value forAdditionalHeader:(NSString*)header;
178 |
179 | /**
180 | * Convenience method that checks if the contentType property is defined.
181 | */
182 | - (BOOL)hasBody;
183 |
184 | @end
185 |
186 | @interface GCDWebServerResponse (Extensions)
187 |
188 | /**
189 | * Creates a empty response with a specific HTTP status code.
190 | */
191 | + (instancetype)responseWithStatusCode:(NSInteger)statusCode;
192 |
193 | /**
194 | * Creates an HTTP redirect response to a new URL.
195 | */
196 | + (instancetype)responseWithRedirect:(NSURL*)location permanent:(BOOL)permanent;
197 |
198 | /**
199 | * Initializes an empty response with a specific HTTP status code.
200 | */
201 | - (instancetype)initWithStatusCode:(NSInteger)statusCode;
202 |
203 | /**
204 | * Initializes an HTTP redirect response to a new URL.
205 | */
206 | - (instancetype)initWithRedirect:(NSURL*)location permanent:(BOOL)permanent;
207 |
208 | @end
209 |
--------------------------------------------------------------------------------
/CocoaLogToWebServer/Classes/GCDWebServer/Core/GCDWebServerRequest.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2012-2015, Pierre-Olivier Latour
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | * The name of Pierre-Olivier Latour may not be used to endorse
13 | or promote products derived from this software without specific
14 | prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | #import
29 |
30 | /**
31 | * Attribute key to retrieve an NSArray containing NSStrings from a GCDWebServerRequest
32 | * with the contents of any regular expression captures done on the request path.
33 | *
34 | * @warning This attribute will only be set on the request if adding a handler using
35 | * -addHandlerForMethod:pathRegex:requestClass:processBlock:.
36 | */
37 | extern NSString* const GCDWebServerRequestAttribute_RegexCaptures;
38 |
39 | /**
40 | * This protocol is used by the GCDWebServerConnection to communicate with
41 | * the GCDWebServerRequest and write the received HTTP body data.
42 | *
43 | * Note that multiple GCDWebServerBodyWriter objects can be chained together
44 | * internally e.g. to automatically decode gzip encoded content before
45 | * passing it on to the GCDWebServerRequest.
46 | *
47 | * @warning These methods can be called on any GCD thread.
48 | */
49 | @protocol GCDWebServerBodyWriter
50 |
51 | /**
52 | * This method is called before any body data is received.
53 | *
54 | * It should return YES on success or NO on failure and set the "error" argument
55 | * which is guaranteed to be non-NULL.
56 | */
57 | - (BOOL)open:(NSError**)error;
58 |
59 | /**
60 | * This method is called whenever body data has been received.
61 | *
62 | * It should return YES on success or NO on failure and set the "error" argument
63 | * which is guaranteed to be non-NULL.
64 | */
65 | - (BOOL)writeData:(NSData*)data error:(NSError**)error;
66 |
67 | /**
68 | * This method is called after all body data has been received.
69 | *
70 | * It should return YES on success or NO on failure and set the "error" argument
71 | * which is guaranteed to be non-NULL.
72 | */
73 | - (BOOL)close:(NSError**)error;
74 |
75 | @end
76 |
77 | /**
78 | * The GCDWebServerRequest class is instantiated by the GCDWebServerConnection
79 | * after the HTTP headers have been received. Each instance wraps a single HTTP
80 | * request. If a body is present, the methods from the GCDWebServerBodyWriter
81 | * protocol will be called by the GCDWebServerConnection to receive it.
82 | *
83 | * The default implementation of the GCDWebServerBodyWriter protocol on the class
84 | * simply ignores the body data.
85 | *
86 | * @warning GCDWebServerRequest instances can be created and used on any GCD thread.
87 | */
88 | @interface GCDWebServerRequest : NSObject
89 |
90 | /**
91 | * Returns the HTTP method for the request.
92 | */
93 | @property(nonatomic, readonly) NSString* method;
94 |
95 | /**
96 | * Returns the URL for the request.
97 | */
98 | @property(nonatomic, readonly) NSURL* URL;
99 |
100 | /**
101 | * Returns the HTTP headers for the request.
102 | */
103 | @property(nonatomic, readonly) NSDictionary* headers;
104 |
105 | /**
106 | * Returns the path component of the URL for the request.
107 | */
108 | @property(nonatomic, readonly) NSString* path;
109 |
110 | /**
111 | * Returns the parsed and unescaped query component of the URL for the request.
112 | *
113 | * @warning This property will be nil if there is no query in the URL.
114 | */
115 | @property(nonatomic, readonly) NSDictionary* query;
116 |
117 | /**
118 | * Returns the content type for the body of the request parsed from the
119 | * "Content-Type" header.
120 | *
121 | * This property will be nil if the request has no body or set to
122 | * "application/octet-stream" if a body is present but there was no
123 | * "Content-Type" header.
124 | */
125 | @property(nonatomic, readonly) NSString* contentType;
126 |
127 | /**
128 | * Returns the content length for the body of the request parsed from the
129 | * "Content-Length" header.
130 | *
131 | * This property will be set to "NSUIntegerMax" if the request has no body or
132 | * if there is a body but no "Content-Length" header, typically because
133 | * chunked transfer encoding is used.
134 | */
135 | @property(nonatomic, readonly) NSUInteger contentLength;
136 |
137 | /**
138 | * Returns the parsed "If-Modified-Since" header or nil if absent or malformed.
139 | */
140 | @property(nonatomic, readonly) NSDate* ifModifiedSince;
141 |
142 | /**
143 | * Returns the parsed "If-None-Match" header or nil if absent or malformed.
144 | */
145 | @property(nonatomic, readonly) NSString* ifNoneMatch;
146 |
147 | /**
148 | * Returns the parsed "Range" header or (NSUIntegerMax, 0) if absent or malformed.
149 | * The range will be set to (offset, length) if expressed from the beginning
150 | * of the entity body, or (NSUIntegerMax, length) if expressed from its end.
151 | */
152 | @property(nonatomic, readonly) NSRange byteRange;
153 |
154 | /**
155 | * Returns YES if the client supports gzip content encoding according to the
156 | * "Accept-Encoding" header.
157 | */
158 | @property(nonatomic, readonly) BOOL acceptsGzipContentEncoding;
159 |
160 | /**
161 | * Returns the address of the local peer (i.e. server) for the request
162 | * as a raw "struct sockaddr".
163 | */
164 | @property(nonatomic, readonly) NSData* localAddressData;
165 |
166 | /**
167 | * Returns the address of the local peer (i.e. server) for the request
168 | * as a string.
169 | */
170 | @property(nonatomic, readonly) NSString* localAddressString;
171 |
172 | /**
173 | * Returns the address of the remote peer (i.e. client) for the request
174 | * as a raw "struct sockaddr".
175 | */
176 | @property(nonatomic, readonly) NSData* remoteAddressData;
177 |
178 | /**
179 | * Returns the address of the remote peer (i.e. client) for the request
180 | * as a string.
181 | */
182 | @property(nonatomic, readonly) NSString* remoteAddressString;
183 |
184 | /**
185 | * This method is the designated initializer for the class.
186 | */
187 | - (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query;
188 |
189 | /**
190 | * Convenience method that checks if the contentType property is defined.
191 | */
192 | - (BOOL)hasBody;
193 |
194 | /**
195 | * Convenience method that checks if the byteRange property is defined.
196 | */
197 | - (BOOL)hasByteRange;
198 |
199 | /**
200 | * Retrieves an attribute associated with this request using the given key.
201 | *
202 | * @return The attribute value for the key.
203 | */
204 | - (id)attributeForKey:(NSString*)key;
205 |
206 | @end
207 |
--------------------------------------------------------------------------------
/CocoaLogToWebServer/Classes/DBClass/FMDatabaseQueue.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabaseQueue.m
3 | // fmdb
4 | //
5 | // Created by August Mueller on 6/22/11.
6 | // Copyright 2011 Flying Meat Inc. All rights reserved.
7 | //
8 |
9 | #import "FMDatabaseQueue.h"
10 | #import "FMDatabase.h"
11 |
12 | #if FMDB_SQLITE_STANDALONE
13 | #import
14 | #else
15 | #import
16 | #endif
17 |
18 | /*
19 |
20 | Note: we call [self retain]; before using dispatch_sync, just incase
21 | FMDatabaseQueue is released on another thread and we're in the middle of doing
22 | something in dispatch_sync
23 |
24 | */
25 |
26 | /*
27 | * A key used to associate the FMDatabaseQueue object with the dispatch_queue_t it uses.
28 | * This in turn is used for deadlock detection by seeing if inDatabase: is called on
29 | * the queue's dispatch queue, which should not happen and causes a deadlock.
30 | */
31 | static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey;
32 |
33 | @implementation FMDatabaseQueue
34 |
35 | @synthesize path = _path;
36 | @synthesize openFlags = _openFlags;
37 | @synthesize vfsName = _vfsName;
38 |
39 | + (instancetype)databaseQueueWithPath:(NSString*)aPath {
40 |
41 | FMDatabaseQueue *q = [[self alloc] initWithPath:aPath];
42 |
43 | FMDBAutorelease(q);
44 |
45 | return q;
46 | }
47 |
48 | + (instancetype)databaseQueueWithPath:(NSString*)aPath flags:(int)openFlags {
49 |
50 | FMDatabaseQueue *q = [[self alloc] initWithPath:aPath flags:openFlags];
51 |
52 | FMDBAutorelease(q);
53 |
54 | return q;
55 | }
56 |
57 | + (Class)databaseClass {
58 | return [FMDatabase class];
59 | }
60 |
61 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags vfs:(NSString *)vfsName {
62 |
63 | self = [super init];
64 |
65 | if (self != nil) {
66 |
67 | _db = [[[self class] databaseClass] databaseWithPath:aPath];
68 | FMDBRetain(_db);
69 |
70 | #if SQLITE_VERSION_NUMBER >= 3005000
71 | BOOL success = [_db openWithFlags:openFlags vfs:vfsName];
72 | #else
73 | BOOL success = [_db open];
74 | #endif
75 | if (!success) {
76 | NSLog(@"Could not create database queue for path %@", aPath);
77 | FMDBRelease(self);
78 | return 0x00;
79 | }
80 |
81 | _path = FMDBReturnRetained(aPath);
82 |
83 | _queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
84 | dispatch_queue_set_specific(_queue, kDispatchQueueSpecificKey, (__bridge void *)self, NULL);
85 | _openFlags = openFlags;
86 | _vfsName = [vfsName copy];
87 | }
88 |
89 | return self;
90 | }
91 |
92 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags {
93 | return [self initWithPath:aPath flags:openFlags vfs:nil];
94 | }
95 |
96 | - (instancetype)initWithPath:(NSString*)aPath {
97 |
98 | // default flags for sqlite3_open
99 | return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE vfs:nil];
100 | }
101 |
102 | - (instancetype)init {
103 | return [self initWithPath:nil];
104 | }
105 |
106 |
107 | - (void)dealloc {
108 |
109 | FMDBRelease(_db);
110 | FMDBRelease(_path);
111 |
112 | if (_queue) {
113 | FMDBDispatchQueueRelease(_queue);
114 | _queue = 0x00;
115 | }
116 | #if ! __has_feature(objc_arc)
117 | [super dealloc];
118 | #endif
119 | }
120 |
121 | - (void)close {
122 | FMDBRetain(self);
123 | dispatch_sync(_queue, ^() {
124 | [self->_db close];
125 | FMDBRelease(_db);
126 | self->_db = 0x00;
127 | });
128 | FMDBRelease(self);
129 | }
130 |
131 | - (FMDatabase*)database {
132 | if (!_db) {
133 | _db = FMDBReturnRetained([[[self class] databaseClass] databaseWithPath:_path]);
134 |
135 | #if SQLITE_VERSION_NUMBER >= 3005000
136 | BOOL success = [_db openWithFlags:_openFlags vfs:_vfsName];
137 | #else
138 | BOOL success = [_db open];
139 | #endif
140 | if (!success) {
141 | NSLog(@"FMDatabaseQueue could not reopen database for path %@", _path);
142 | FMDBRelease(_db);
143 | _db = 0x00;
144 | return 0x00;
145 | }
146 | }
147 |
148 | return _db;
149 | }
150 |
151 | - (void)inDatabase:(void (^)(FMDatabase *db))block {
152 | /* Get the currently executing queue (which should probably be nil, but in theory could be another DB queue
153 | * and then check it against self to make sure we're not about to deadlock. */
154 | FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey);
155 | assert(currentSyncQueue != self && "inDatabase: was called reentrantly on the same queue, which would lead to a deadlock");
156 |
157 | FMDBRetain(self);
158 |
159 | dispatch_sync(_queue, ^() {
160 |
161 | FMDatabase *db = [self database];
162 | block(db);
163 |
164 | if ([db hasOpenResultSets]) {
165 | NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]");
166 |
167 | #if defined(DEBUG) && DEBUG
168 | NSSet *openSetCopy = FMDBReturnAutoreleased([[db valueForKey:@"_openResultSets"] copy]);
169 | for (NSValue *rsInWrappedInATastyValueMeal in openSetCopy) {
170 | FMResultSet *rs = (FMResultSet *)[rsInWrappedInATastyValueMeal pointerValue];
171 | NSLog(@"query: '%@'", [rs query]);
172 | }
173 | #endif
174 | }
175 | });
176 |
177 | FMDBRelease(self);
178 | }
179 |
180 |
181 | - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block {
182 | FMDBRetain(self);
183 | dispatch_sync(_queue, ^() {
184 |
185 | BOOL shouldRollback = NO;
186 |
187 | if (useDeferred) {
188 | [[self database] beginDeferredTransaction];
189 | }
190 | else {
191 | [[self database] beginTransaction];
192 | }
193 |
194 | block([self database], &shouldRollback);
195 |
196 | if (shouldRollback) {
197 | [[self database] rollback];
198 | }
199 | else {
200 | [[self database] commit];
201 | }
202 | });
203 |
204 | FMDBRelease(self);
205 | }
206 |
207 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
208 | [self beginTransaction:YES withBlock:block];
209 | }
210 |
211 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
212 | [self beginTransaction:NO withBlock:block];
213 | }
214 |
215 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {
216 | #if SQLITE_VERSION_NUMBER >= 3007000
217 | static unsigned long savePointIdx = 0;
218 | __block NSError *err = 0x00;
219 | FMDBRetain(self);
220 | dispatch_sync(_queue, ^() {
221 |
222 | NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++];
223 |
224 | BOOL shouldRollback = NO;
225 |
226 | if ([[self database] startSavePointWithName:name error:&err]) {
227 |
228 | block([self database], &shouldRollback);
229 |
230 | if (shouldRollback) {
231 | // We need to rollback and release this savepoint to remove it
232 | [[self database] rollbackToSavePointWithName:name error:&err];
233 | }
234 | [[self database] releaseSavePointWithName:name error:&err];
235 |
236 | }
237 | });
238 | FMDBRelease(self);
239 | return err;
240 | #else
241 | NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil);
242 | if (self.logsErrors) NSLog(@"%@", errorMessage);
243 | return [NSError errorWithDomain:@"FMDatabase" code:0 userInfo:@{NSLocalizedDescriptionKey : errorMessage}];
244 | #endif
245 | }
246 |
247 | @end
248 |
--------------------------------------------------------------------------------
/CocoaLogToWebServer/Classes/DBClass/FMDatabaseAdditions.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabaseAdditions.m
3 | // fmdb
4 | //
5 | // Created by August Mueller on 10/30/05.
6 | // Copyright 2005 Flying Meat Inc.. All rights reserved.
7 | //
8 |
9 | #import "FMDatabase.h"
10 | #import "FMDatabaseAdditions.h"
11 | #import "TargetConditionals.h"
12 |
13 | #if FMDB_SQLITE_STANDALONE
14 | #import
15 | #else
16 | #import
17 | #endif
18 |
19 | @interface FMDatabase (PrivateStuff)
20 | - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args;
21 | @end
22 |
23 | @implementation FMDatabase (FMDatabaseAdditions)
24 |
25 | #define RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(type, sel) \
26 | va_list args; \
27 | va_start(args, query); \
28 | FMResultSet *resultSet = [self executeQuery:query withArgumentsInArray:0x00 orDictionary:0x00 orVAList:args]; \
29 | va_end(args); \
30 | if (![resultSet next]) { return (type)0; } \
31 | type ret = [resultSet sel:0]; \
32 | [resultSet close]; \
33 | [resultSet setParentDB:nil]; \
34 | return ret;
35 |
36 |
37 | - (NSString*)stringForQuery:(NSString*)query, ... {
38 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex);
39 | }
40 |
41 | - (int)intForQuery:(NSString*)query, ... {
42 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(int, intForColumnIndex);
43 | }
44 |
45 | - (long)longForQuery:(NSString*)query, ... {
46 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(long, longForColumnIndex);
47 | }
48 |
49 | - (BOOL)boolForQuery:(NSString*)query, ... {
50 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(BOOL, boolForColumnIndex);
51 | }
52 |
53 | - (double)doubleForQuery:(NSString*)query, ... {
54 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(double, doubleForColumnIndex);
55 | }
56 |
57 | - (NSData*)dataForQuery:(NSString*)query, ... {
58 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSData *, dataForColumnIndex);
59 | }
60 |
61 | - (NSDate*)dateForQuery:(NSString*)query, ... {
62 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSDate *, dateForColumnIndex);
63 | }
64 |
65 |
66 | - (BOOL)tableExists:(NSString*)tableName {
67 |
68 | tableName = [tableName lowercaseString];
69 |
70 | FMResultSet *rs = [self executeQuery:@"select [sql] from sqlite_master where [type] = 'table' and lower(name) = ?", tableName];
71 |
72 | //if at least one next exists, table exists
73 | BOOL returnBool = [rs next];
74 |
75 | //close and free object
76 | [rs close];
77 |
78 | return returnBool;
79 | }
80 |
81 | /*
82 | get table with list of tables: result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING]
83 | check if table exist in database (patch from OZLB)
84 | */
85 | - (FMResultSet*)getSchema {
86 |
87 | //result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING]
88 | FMResultSet *rs = [self executeQuery:@"SELECT type, name, tbl_name, rootpage, sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type != 'meta' AND name NOT LIKE 'sqlite_%' ORDER BY tbl_name, type DESC, name"];
89 |
90 | return rs;
91 | }
92 |
93 | /*
94 | get table schema: result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER]
95 | */
96 | - (FMResultSet*)getTableSchema:(NSString*)tableName {
97 |
98 | //result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER]
99 | FMResultSet *rs = [self executeQuery:[NSString stringWithFormat: @"pragma table_info('%@')", tableName]];
100 |
101 | return rs;
102 | }
103 |
104 | - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName {
105 |
106 | BOOL returnBool = NO;
107 |
108 | tableName = [tableName lowercaseString];
109 | columnName = [columnName lowercaseString];
110 |
111 | FMResultSet *rs = [self getTableSchema:tableName];
112 |
113 | //check if column is present in table schema
114 | while ([rs next]) {
115 | if ([[[rs stringForColumn:@"name"] lowercaseString] isEqualToString:columnName]) {
116 | returnBool = YES;
117 | break;
118 | }
119 | }
120 |
121 | //If this is not done FMDatabase instance stays out of pool
122 | [rs close];
123 |
124 | return returnBool;
125 | }
126 |
127 |
128 |
129 | - (uint32_t)applicationID {
130 | #if SQLITE_VERSION_NUMBER >= 3007017
131 | uint32_t r = 0;
132 |
133 | FMResultSet *rs = [self executeQuery:@"pragma application_id"];
134 |
135 | if ([rs next]) {
136 | r = (uint32_t)[rs longLongIntForColumnIndex:0];
137 | }
138 |
139 | [rs close];
140 |
141 | return r;
142 | #else
143 | NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil);
144 | if (self.logsErrors) NSLog(@"%@", errorMessage);
145 | return 0;
146 | #endif
147 | }
148 |
149 | - (void)setApplicationID:(uint32_t)appID {
150 | #if SQLITE_VERSION_NUMBER >= 3007017
151 | NSString *query = [NSString stringWithFormat:@"pragma application_id=%d", appID];
152 | FMResultSet *rs = [self executeQuery:query];
153 | [rs next];
154 | [rs close];
155 | #else
156 | NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil);
157 | if (self.logsErrors) NSLog(@"%@", errorMessage);
158 | #endif
159 | }
160 |
161 |
162 | #if TARGET_OS_MAC && !TARGET_OS_IPHONE
163 |
164 | - (NSString*)applicationIDString {
165 | #if SQLITE_VERSION_NUMBER >= 3007017
166 | NSString *s = NSFileTypeForHFSTypeCode([self applicationID]);
167 |
168 | assert([s length] == 6);
169 |
170 | s = [s substringWithRange:NSMakeRange(1, 4)];
171 |
172 |
173 | return s;
174 | #else
175 | NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil);
176 | if (self.logsErrors) NSLog(@"%@", errorMessage);
177 | return nil;
178 | #endif
179 | }
180 |
181 | - (void)setApplicationIDString:(NSString*)s {
182 | #if SQLITE_VERSION_NUMBER >= 3007017
183 | if ([s length] != 4) {
184 | NSLog(@"setApplicationIDString: string passed is not exactly 4 chars long. (was %ld)", [s length]);
185 | }
186 |
187 | [self setApplicationID:NSHFSTypeCodeFromFileType([NSString stringWithFormat:@"'%@'", s])];
188 | #else
189 | NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil);
190 | if (self.logsErrors) NSLog(@"%@", errorMessage);
191 | #endif
192 | }
193 |
194 | #endif
195 |
196 | - (uint32_t)userVersion {
197 | uint32_t r = 0;
198 |
199 | FMResultSet *rs = [self executeQuery:@"pragma user_version"];
200 |
201 | if ([rs next]) {
202 | r = (uint32_t)[rs longLongIntForColumnIndex:0];
203 | }
204 |
205 | [rs close];
206 | return r;
207 | }
208 |
209 | - (void)setUserVersion:(uint32_t)version {
210 | NSString *query = [NSString stringWithFormat:@"pragma user_version = %d", version];
211 | FMResultSet *rs = [self executeQuery:query];
212 | [rs next];
213 | [rs close];
214 | }
215 |
216 | #pragma clang diagnostic push
217 | #pragma clang diagnostic ignored "-Wdeprecated-implementations"
218 |
219 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated)) {
220 | return [self columnExists:columnName inTableWithName:tableName];
221 | }
222 |
223 | #pragma clang diagnostic pop
224 |
225 |
226 | - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error {
227 | sqlite3_stmt *pStmt = NULL;
228 | BOOL validationSucceeded = YES;
229 |
230 | int rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0);
231 | if (rc != SQLITE_OK) {
232 | validationSucceeded = NO;
233 | if (error) {
234 | *error = [NSError errorWithDomain:NSCocoaErrorDomain
235 | code:[self lastErrorCode]
236 | userInfo:[NSDictionary dictionaryWithObject:[self lastErrorMessage]
237 | forKey:NSLocalizedDescriptionKey]];
238 | }
239 | }
240 |
241 | sqlite3_finalize(pStmt);
242 |
243 | return validationSucceeded;
244 | }
245 |
246 | @end
247 |
--------------------------------------------------------------------------------
/CocoaLogToWebServer/Classes/DBClass/FMDatabaseAdditions.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabaseAdditions.h
3 | // fmdb
4 | //
5 | // Created by August Mueller on 10/30/05.
6 | // Copyright 2005 Flying Meat Inc.. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "FMDatabase.h"
11 |
12 |
13 | /** Category of additions for `` class.
14 |
15 | ### See also
16 |
17 | - ``
18 | */
19 |
20 | @interface FMDatabase (FMDatabaseAdditions)
21 |
22 | ///----------------------------------------
23 | /// @name Return results of SQL to variable
24 | ///----------------------------------------
25 |
26 | /** Return `int` value for query
27 |
28 | @param query The SQL query to be performed.
29 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
30 |
31 | @return `int` value.
32 |
33 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
34 | */
35 |
36 | - (int)intForQuery:(NSString*)query, ...;
37 |
38 | /** Return `long` value for query
39 |
40 | @param query The SQL query to be performed.
41 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
42 |
43 | @return `long` value.
44 |
45 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
46 | */
47 |
48 | - (long)longForQuery:(NSString*)query, ...;
49 |
50 | /** Return `BOOL` value for query
51 |
52 | @param query The SQL query to be performed.
53 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
54 |
55 | @return `BOOL` value.
56 |
57 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
58 | */
59 |
60 | - (BOOL)boolForQuery:(NSString*)query, ...;
61 |
62 | /** Return `double` value for query
63 |
64 | @param query The SQL query to be performed.
65 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
66 |
67 | @return `double` value.
68 |
69 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
70 | */
71 |
72 | - (double)doubleForQuery:(NSString*)query, ...;
73 |
74 | /** Return `NSString` value for query
75 |
76 | @param query The SQL query to be performed.
77 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
78 |
79 | @return `NSString` value.
80 |
81 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
82 | */
83 |
84 | - (NSString*)stringForQuery:(NSString*)query, ...;
85 |
86 | /** Return `NSData` value for query
87 |
88 | @param query The SQL query to be performed.
89 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
90 |
91 | @return `NSData` value.
92 |
93 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
94 | */
95 |
96 | - (NSData*)dataForQuery:(NSString*)query, ...;
97 |
98 | /** Return `NSDate` value for query
99 |
100 | @param query The SQL query to be performed.
101 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
102 |
103 | @return `NSDate` value.
104 |
105 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
106 | */
107 |
108 | - (NSDate*)dateForQuery:(NSString*)query, ...;
109 |
110 |
111 | // Notice that there's no dataNoCopyForQuery:.
112 | // That would be a bad idea, because we close out the result set, and then what
113 | // happens to the data that we just didn't copy? Who knows, not I.
114 |
115 |
116 | ///--------------------------------
117 | /// @name Schema related operations
118 | ///--------------------------------
119 |
120 | /** Does table exist in database?
121 |
122 | @param tableName The name of the table being looked for.
123 |
124 | @return `YES` if table found; `NO` if not found.
125 | */
126 |
127 | - (BOOL)tableExists:(NSString*)tableName;
128 |
129 | /** The schema of the database.
130 |
131 | This will be the schema for the entire database. For each entity, each row of the result set will include the following fields:
132 |
133 | - `type` - The type of entity (e.g. table, index, view, or trigger)
134 | - `name` - The name of the object
135 | - `tbl_name` - The name of the table to which the object references
136 | - `rootpage` - The page number of the root b-tree page for tables and indices
137 | - `sql` - The SQL that created the entity
138 |
139 | @return `FMResultSet` of schema; `nil` on error.
140 |
141 | @see [SQLite File Format](http://www.sqlite.org/fileformat.html)
142 | */
143 |
144 | - (FMResultSet*)getSchema;
145 |
146 | /** The schema of the database.
147 |
148 | This will be the schema for a particular table as report by SQLite `PRAGMA`, for example:
149 |
150 | PRAGMA table_info('employees')
151 |
152 | This will report:
153 |
154 | - `cid` - The column ID number
155 | - `name` - The name of the column
156 | - `type` - The data type specified for the column
157 | - `notnull` - whether the field is defined as NOT NULL (i.e. values required)
158 | - `dflt_value` - The default value for the column
159 | - `pk` - Whether the field is part of the primary key of the table
160 |
161 | @param tableName The name of the table for whom the schema will be returned.
162 |
163 | @return `FMResultSet` of schema; `nil` on error.
164 |
165 | @see [table_info](http://www.sqlite.org/pragma.html#pragma_table_info)
166 | */
167 |
168 | - (FMResultSet*)getTableSchema:(NSString*)tableName;
169 |
170 | /** Test to see if particular column exists for particular table in database
171 |
172 | @param columnName The name of the column.
173 |
174 | @param tableName The name of the table.
175 |
176 | @return `YES` if column exists in table in question; `NO` otherwise.
177 | */
178 |
179 | - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName;
180 |
181 | /** Test to see if particular column exists for particular table in database
182 |
183 | @param columnName The name of the column.
184 |
185 | @param tableName The name of the table.
186 |
187 | @return `YES` if column exists in table in question; `NO` otherwise.
188 |
189 | @see columnExists:inTableWithName:
190 |
191 | @warning Deprecated - use `` instead.
192 | */
193 |
194 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated));
195 |
196 |
197 | /** Validate SQL statement
198 |
199 | This validates SQL statement by performing `sqlite3_prepare_v2`, but not returning the results, but instead immediately calling `sqlite3_finalize`.
200 |
201 | @param sql The SQL statement being validated.
202 |
203 | @param error This is a pointer to a `NSError` object that will receive the autoreleased `NSError` object if there was any error. If this is `nil`, no `NSError` result will be returned.
204 |
205 | @return `YES` if validation succeeded without incident; `NO` otherwise.
206 |
207 | */
208 |
209 | - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error;
210 |
211 |
212 | ///-----------------------------------
213 | /// @name Application identifier tasks
214 | ///-----------------------------------
215 |
216 | /** Retrieve application ID
217 |
218 | @return The `uint32_t` numeric value of the application ID.
219 |
220 | @see setApplicationID:
221 | */
222 |
223 | - (uint32_t)applicationID;
224 |
225 | /** Set the application ID
226 |
227 | @param appID The `uint32_t` numeric value of the application ID.
228 |
229 | @see applicationID
230 | */
231 |
232 | - (void)setApplicationID:(uint32_t)appID;
233 |
234 | #if TARGET_OS_MAC && !TARGET_OS_IPHONE
235 | /** Retrieve application ID string
236 |
237 | @return The `NSString` value of the application ID.
238 |
239 | @see setApplicationIDString:
240 | */
241 |
242 |
243 | - (NSString*)applicationIDString;
244 |
245 | /** Set the application ID string
246 |
247 | @param string The `NSString` value of the application ID.
248 |
249 | @see applicationIDString
250 | */
251 |
252 | - (void)setApplicationIDString:(NSString*)string;
253 |
254 | #endif
255 |
256 | ///-----------------------------------
257 | /// @name user version identifier tasks
258 | ///-----------------------------------
259 |
260 | /** Retrieve user version
261 |
262 | @return The `uint32_t` numeric value of the user version.
263 |
264 | @see setUserVersion:
265 | */
266 |
267 | - (uint32_t)userVersion;
268 |
269 | /** Set the user-version
270 |
271 | @param version The `uint32_t` numeric value of the user version.
272 |
273 | @see userVersion
274 | */
275 |
276 | - (void)setUserVersion:(uint32_t)version;
277 |
278 | @end
279 |
--------------------------------------------------------------------------------
/CocoaLogToWebServer/Classes/DBClass/FMDatabasePool.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabasePool.m
3 | // fmdb
4 | //
5 | // Created by August Mueller on 6/22/11.
6 | // Copyright 2011 Flying Meat Inc. All rights reserved.
7 | //
8 |
9 | #if FMDB_SQLITE_STANDALONE
10 | #import
11 | #else
12 | #import
13 | #endif
14 |
15 | #import "FMDatabasePool.h"
16 | #import "FMDatabase.h"
17 |
18 | @interface FMDatabasePool()
19 |
20 | - (void)pushDatabaseBackInPool:(FMDatabase*)db;
21 | - (FMDatabase*)db;
22 |
23 | @end
24 |
25 |
26 | @implementation FMDatabasePool
27 | @synthesize path=_path;
28 | @synthesize delegate=_delegate;
29 | @synthesize maximumNumberOfDatabasesToCreate=_maximumNumberOfDatabasesToCreate;
30 | @synthesize openFlags=_openFlags;
31 |
32 |
33 | + (instancetype)databasePoolWithPath:(NSString*)aPath {
34 | return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]);
35 | }
36 |
37 | + (instancetype)databasePoolWithPath:(NSString*)aPath flags:(int)openFlags {
38 | return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath flags:openFlags]);
39 | }
40 |
41 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags vfs:(NSString *)vfsName {
42 |
43 | self = [super init];
44 |
45 | if (self != nil) {
46 | _path = [aPath copy];
47 | _lockQueue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
48 | _databaseInPool = FMDBReturnRetained([NSMutableArray array]);
49 | _databaseOutPool = FMDBReturnRetained([NSMutableArray array]);
50 | _openFlags = openFlags;
51 | _vfsName = [vfsName copy];
52 | }
53 |
54 | return self;
55 | }
56 |
57 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags {
58 | return [self initWithPath:aPath flags:openFlags vfs:nil];
59 | }
60 |
61 | - (instancetype)initWithPath:(NSString*)aPath
62 | {
63 | // default flags for sqlite3_open
64 | return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE];
65 | }
66 |
67 | - (instancetype)init {
68 | return [self initWithPath:nil];
69 | }
70 |
71 | + (Class)databaseClass {
72 | return [FMDatabase class];
73 | }
74 |
75 | - (void)dealloc {
76 |
77 | _delegate = 0x00;
78 | FMDBRelease(_path);
79 | FMDBRelease(_databaseInPool);
80 | FMDBRelease(_databaseOutPool);
81 |
82 | if (_lockQueue) {
83 | FMDBDispatchQueueRelease(_lockQueue);
84 | _lockQueue = 0x00;
85 | }
86 | #if ! __has_feature(objc_arc)
87 | [super dealloc];
88 | #endif
89 | }
90 |
91 |
92 | - (void)executeLocked:(void (^)(void))aBlock {
93 | dispatch_sync(_lockQueue, aBlock);
94 | }
95 |
96 | - (void)pushDatabaseBackInPool:(FMDatabase*)db {
97 |
98 | if (!db) { // db can be null if we set an upper bound on the # of databases to create.
99 | return;
100 | }
101 |
102 | [self executeLocked:^() {
103 |
104 | if ([self->_databaseInPool containsObject:db]) {
105 | [[NSException exceptionWithName:@"Database already in pool" reason:@"The FMDatabase being put back into the pool is already present in the pool" userInfo:nil] raise];
106 | }
107 |
108 | [self->_databaseInPool addObject:db];
109 | [self->_databaseOutPool removeObject:db];
110 |
111 | }];
112 | }
113 |
114 | - (FMDatabase*)db {
115 |
116 | __block FMDatabase *db;
117 |
118 |
119 | [self executeLocked:^() {
120 | db = [self->_databaseInPool lastObject];
121 |
122 | BOOL shouldNotifyDelegate = NO;
123 |
124 | if (db) {
125 | [self->_databaseOutPool addObject:db];
126 | [self->_databaseInPool removeLastObject];
127 | }
128 | else {
129 |
130 | if (self->_maximumNumberOfDatabasesToCreate) {
131 | NSUInteger currentCount = [self->_databaseOutPool count] + [self->_databaseInPool count];
132 |
133 | if (currentCount >= self->_maximumNumberOfDatabasesToCreate) {
134 | NSLog(@"Maximum number of databases (%ld) has already been reached!", (long)currentCount);
135 | return;
136 | }
137 | }
138 |
139 | db = [[[self class] databaseClass] databaseWithPath:self->_path];
140 | shouldNotifyDelegate = YES;
141 | }
142 |
143 | //This ensures that the db is opened before returning
144 | #if SQLITE_VERSION_NUMBER >= 3005000
145 | BOOL success = [db openWithFlags:self->_openFlags vfs:self->_vfsName];
146 | #else
147 | BOOL success = [db open];
148 | #endif
149 | if (success) {
150 | if ([self->_delegate respondsToSelector:@selector(databasePool:shouldAddDatabaseToPool:)] && ![self->_delegate databasePool:self shouldAddDatabaseToPool:db]) {
151 | [db close];
152 | db = 0x00;
153 | }
154 | else {
155 | //It should not get added in the pool twice if lastObject was found
156 | if (![self->_databaseOutPool containsObject:db]) {
157 | [self->_databaseOutPool addObject:db];
158 |
159 | if (shouldNotifyDelegate && [self->_delegate respondsToSelector:@selector(databasePool:didAddDatabase:)]) {
160 | [self->_delegate databasePool:self didAddDatabase:db];
161 | }
162 | }
163 | }
164 | }
165 | else {
166 | NSLog(@"Could not open up the database at path %@", self->_path);
167 | db = 0x00;
168 | }
169 | }];
170 |
171 | return db;
172 | }
173 |
174 | - (NSUInteger)countOfCheckedInDatabases {
175 |
176 | __block NSUInteger count;
177 |
178 | [self executeLocked:^() {
179 | count = [self->_databaseInPool count];
180 | }];
181 |
182 | return count;
183 | }
184 |
185 | - (NSUInteger)countOfCheckedOutDatabases {
186 |
187 | __block NSUInteger count;
188 |
189 | [self executeLocked:^() {
190 | count = [self->_databaseOutPool count];
191 | }];
192 |
193 | return count;
194 | }
195 |
196 | - (NSUInteger)countOfOpenDatabases {
197 | __block NSUInteger count;
198 |
199 | [self executeLocked:^() {
200 | count = [self->_databaseOutPool count] + [self->_databaseInPool count];
201 | }];
202 |
203 | return count;
204 | }
205 |
206 | - (void)releaseAllDatabases {
207 | [self executeLocked:^() {
208 | [self->_databaseOutPool removeAllObjects];
209 | [self->_databaseInPool removeAllObjects];
210 | }];
211 | }
212 |
213 | - (void)inDatabase:(void (^)(FMDatabase *db))block {
214 |
215 | FMDatabase *db = [self db];
216 |
217 | block(db);
218 |
219 | [self pushDatabaseBackInPool:db];
220 | }
221 |
222 | - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block {
223 |
224 | BOOL shouldRollback = NO;
225 |
226 | FMDatabase *db = [self db];
227 |
228 | if (useDeferred) {
229 | [db beginDeferredTransaction];
230 | }
231 | else {
232 | [db beginTransaction];
233 | }
234 |
235 |
236 | block(db, &shouldRollback);
237 |
238 | if (shouldRollback) {
239 | [db rollback];
240 | }
241 | else {
242 | [db commit];
243 | }
244 |
245 | [self pushDatabaseBackInPool:db];
246 | }
247 |
248 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
249 | [self beginTransaction:YES withBlock:block];
250 | }
251 |
252 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
253 | [self beginTransaction:NO withBlock:block];
254 | }
255 |
256 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {
257 | #if SQLITE_VERSION_NUMBER >= 3007000
258 | static unsigned long savePointIdx = 0;
259 |
260 | NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++];
261 |
262 | BOOL shouldRollback = NO;
263 |
264 | FMDatabase *db = [self db];
265 |
266 | NSError *err = 0x00;
267 |
268 | if (![db startSavePointWithName:name error:&err]) {
269 | [self pushDatabaseBackInPool:db];
270 | return err;
271 | }
272 |
273 | block(db, &shouldRollback);
274 |
275 | if (shouldRollback) {
276 | // We need to rollback and release this savepoint to remove it
277 | [db rollbackToSavePointWithName:name error:&err];
278 | }
279 | [db releaseSavePointWithName:name error:&err];
280 |
281 | [self pushDatabaseBackInPool:db];
282 |
283 | return err;
284 | #else
285 | NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil);
286 | if (self.logsErrors) NSLog(@"%@", errorMessage);
287 | return [NSError errorWithDomain:@"FMDatabase" code:0 userInfo:@{NSLocalizedDescriptionKey : errorMessage}];
288 | #endif
289 | }
290 |
291 | @end
292 |
--------------------------------------------------------------------------------
/CocoaLogToWebServer/Classes/GCDWebServer/Core/GCDWebServerPrivate.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2012-2015, Pierre-Olivier Latour
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | * The name of Pierre-Olivier Latour may not be used to endorse
13 | or promote products derived from this software without specific
14 | prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | #import
29 | #import
30 |
31 | /**
32 | * All GCDWebServer headers.
33 | */
34 |
35 | #import "GCDWebServerHTTPStatusCodes.h"
36 | #import "GCDWebServerFunctions.h"
37 |
38 | #import "GCDWebServer.h"
39 | #import "GCDWebServerConnection.h"
40 |
41 | #import "GCDWebServerDataRequest.h"
42 | #import "GCDWebServerFileRequest.h"
43 | #import "GCDWebServerMultiPartFormRequest.h"
44 | #import "GCDWebServerURLEncodedFormRequest.h"
45 |
46 | #import "GCDWebServerDataResponse.h"
47 | #import "GCDWebServerErrorResponse.h"
48 | #import "GCDWebServerFileResponse.h"
49 | #import "GCDWebServerStreamedResponse.h"
50 |
51 | /**
52 | * Check if a custom logging facility should be used instead.
53 | */
54 |
55 | #if defined(__GCDWEBSERVER_LOGGING_HEADER__)
56 |
57 | #define __GCDWEBSERVER_LOGGING_FACILITY_CUSTOM__
58 |
59 | #import __GCDWEBSERVER_LOGGING_HEADER__
60 |
61 | /**
62 | * Automatically detect if XLFacility is available and if so use it as a
63 | * logging facility.
64 | */
65 |
66 | #elif defined(__has_include) && __has_include("XLFacilityMacros.h")
67 |
68 | #define __GCDWEBSERVER_LOGGING_FACILITY_XLFACILITY__
69 |
70 | #undef XLOG_TAG
71 | #define XLOG_TAG @"gcdwebserver.internal"
72 |
73 | #import "XLFacilityMacros.h"
74 |
75 | #define GWS_LOG_DEBUG(...) XLOG_DEBUG(__VA_ARGS__)
76 | #define GWS_LOG_VERBOSE(...) XLOG_VERBOSE(__VA_ARGS__)
77 | #define GWS_LOG_INFO(...) XLOG_INFO(__VA_ARGS__)
78 | #define GWS_LOG_WARNING(...) XLOG_WARNING(__VA_ARGS__)
79 | #define GWS_LOG_ERROR(...) XLOG_ERROR(__VA_ARGS__)
80 | #define GWS_LOG_EXCEPTION(__EXCEPTION__) XLOG_EXCEPTION(__EXCEPTION__)
81 |
82 | #define GWS_DCHECK(__CONDITION__) XLOG_DEBUG_CHECK(__CONDITION__)
83 | #define GWS_DNOT_REACHED() XLOG_DEBUG_UNREACHABLE()
84 |
85 | /**
86 | * Automatically detect if CocoaLumberJack is available and if so use
87 | * it as a logging facility.
88 | */
89 |
90 | #elif defined(__has_include) && __has_include("CocoaLumberjack/CocoaLumberjack.h")
91 |
92 | #import
93 |
94 | #define __GCDWEBSERVER_LOGGING_FACILITY_COCOALUMBERJACK__
95 |
96 | #undef LOG_LEVEL_DEF
97 | #define LOG_LEVEL_DEF GCDWebServerLogLevel
98 | extern DDLogLevel GCDWebServerLogLevel;
99 |
100 | #define GWS_LOG_DEBUG(...) DDLogDebug(__VA_ARGS__)
101 | #define GWS_LOG_VERBOSE(...) DDLogVerbose(__VA_ARGS__)
102 | #define GWS_LOG_INFO(...) DDLogInfo(__VA_ARGS__)
103 | #define GWS_LOG_WARNING(...) DDLogWarn(__VA_ARGS__)
104 | #define GWS_LOG_ERROR(...) DDLogError(__VA_ARGS__)
105 | #define GWS_LOG_EXCEPTION(__EXCEPTION__) DDLogError(@"%@", __EXCEPTION__)
106 |
107 | /**
108 | * If all of the above fail, then use GCDWebServer built-in
109 | * logging facility.
110 | */
111 |
112 | #else
113 |
114 | #define __GCDWEBSERVER_LOGGING_FACILITY_BUILTIN__
115 |
116 | typedef NS_ENUM(int, GCDWebServerLoggingLevel) {
117 | kGCDWebServerLoggingLevel_Debug = 0,
118 | kGCDWebServerLoggingLevel_Verbose,
119 | kGCDWebServerLoggingLevel_Info,
120 | kGCDWebServerLoggingLevel_Warning,
121 | kGCDWebServerLoggingLevel_Error,
122 | kGCDWebServerLoggingLevel_Exception
123 | };
124 |
125 | extern GCDWebServerLoggingLevel GCDWebServerLogLevel;
126 | extern void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* format, ...) NS_FORMAT_FUNCTION(2, 3);
127 |
128 | #if DEBUG
129 | #define GWS_LOG_DEBUG(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Debug) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Debug, __VA_ARGS__); } while (0)
130 | #else
131 | #define GWS_LOG_DEBUG(...)
132 | #endif
133 | #define GWS_LOG_VERBOSE(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Verbose) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Verbose, __VA_ARGS__); } while (0)
134 | #define GWS_LOG_INFO(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Info) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Info, __VA_ARGS__); } while (0)
135 | #define GWS_LOG_WARNING(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Warning) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Warning, __VA_ARGS__); } while (0)
136 | #define GWS_LOG_ERROR(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Error) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Error, __VA_ARGS__); } while (0)
137 | #define GWS_LOG_EXCEPTION(__EXCEPTION__) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Exception) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Exception, @"%@", __EXCEPTION__); } while (0)
138 |
139 | #endif
140 |
141 | /**
142 | * Consistency check macros used when building Debug only.
143 | */
144 |
145 | #if !defined(GWS_DCHECK) || !defined(GWS_DNOT_REACHED)
146 |
147 | #if DEBUG
148 |
149 | #define GWS_DCHECK(__CONDITION__) \
150 | do { \
151 | if (!(__CONDITION__)) { \
152 | abort(); \
153 | } \
154 | } while (0)
155 | #define GWS_DNOT_REACHED() abort()
156 |
157 | #else
158 |
159 | #define GWS_DCHECK(__CONDITION__)
160 | #define GWS_DNOT_REACHED()
161 |
162 | #endif
163 |
164 | #endif
165 |
166 | /**
167 | * GCDWebServer internal constants and APIs.
168 | */
169 |
170 | #define kGCDWebServerDefaultMimeType @"application/octet-stream"
171 | #define kGCDWebServerErrorDomain @"GCDWebServerErrorDomain"
172 |
173 | static inline BOOL GCDWebServerIsValidByteRange(NSRange range) {
174 | return ((range.location != NSUIntegerMax) || (range.length > 0));
175 | }
176 |
177 | static inline NSError* GCDWebServerMakePosixError(int code) {
178 | return [NSError errorWithDomain:NSPOSIXErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithUTF8String:strerror(code)]}];
179 | }
180 |
181 | extern void GCDWebServerInitializeFunctions();
182 | extern NSString* GCDWebServerNormalizeHeaderValue(NSString* value);
183 | extern NSString* GCDWebServerTruncateHeaderValue(NSString* value);
184 | extern NSString* GCDWebServerExtractHeaderValueParameter(NSString* header, NSString* attribute);
185 | extern NSStringEncoding GCDWebServerStringEncodingFromCharset(NSString* charset);
186 | extern BOOL GCDWebServerIsTextContentType(NSString* type);
187 | extern NSString* GCDWebServerDescribeData(NSData* data, NSString* contentType);
188 | extern NSString* GCDWebServerComputeMD5Digest(NSString* format, ...) NS_FORMAT_FUNCTION(1,2);
189 | extern NSString* GCDWebServerStringFromSockAddr(const struct sockaddr* addr, BOOL includeService);
190 |
191 | @interface GCDWebServerConnection ()
192 | - (id)initWithServer:(GCDWebServer*)server localAddress:(NSData*)localAddress remoteAddress:(NSData*)remoteAddress socket:(CFSocketNativeHandle)socket;
193 | @end
194 |
195 | @interface GCDWebServer ()
196 | @property(nonatomic, readonly) NSArray* handlers;
197 | @property(nonatomic, readonly) NSString* serverName;
198 | @property(nonatomic, readonly) NSString* authenticationRealm;
199 | @property(nonatomic, readonly) NSDictionary* authenticationBasicAccounts;
200 | @property(nonatomic, readonly) NSDictionary* authenticationDigestAccounts;
201 | @property(nonatomic, readonly) BOOL shouldAutomaticallyMapHEADToGET;
202 | @property(nonatomic, readonly) dispatch_queue_priority_t dispatchQueuePriority;
203 | - (void)willStartConnection:(GCDWebServerConnection*)connection;
204 | - (void)didEndConnection:(GCDWebServerConnection*)connection;
205 | @end
206 |
207 | @interface GCDWebServerHandler : NSObject
208 | @property(nonatomic, readonly) GCDWebServerMatchBlock matchBlock;
209 | @property(nonatomic, readonly) GCDWebServerAsyncProcessBlock asyncProcessBlock;
210 | @end
211 |
212 | @interface GCDWebServerRequest ()
213 | @property(nonatomic, readonly) BOOL usesChunkedTransferEncoding;
214 | @property(nonatomic, readwrite) NSData* localAddressData;
215 | @property(nonatomic, readwrite) NSData* remoteAddressData;
216 | - (void)prepareForWriting;
217 | - (BOOL)performOpen:(NSError**)error;
218 | - (BOOL)performWriteData:(NSData*)data error:(NSError**)error;
219 | - (BOOL)performClose:(NSError**)error;
220 | - (void)setAttribute:(id)attribute forKey:(NSString*)key;
221 | @end
222 |
223 | @interface GCDWebServerResponse ()
224 | @property(nonatomic, readonly) NSDictionary* additionalHeaders;
225 | @property(nonatomic, readonly) BOOL usesChunkedTransferEncoding;
226 | - (void)prepareForReading;
227 | - (BOOL)performOpen:(NSError**)error;
228 | - (void)performReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block;
229 | - (void)performClose;
230 | @end
231 |
--------------------------------------------------------------------------------