├── CocoaLogToWebServer ├── CocoaLogToWebServer.xcodeproj │ ├── xcuserdata │ │ └── yanglele.xcuserdatad │ │ │ ├── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ │ └── xcschemes │ │ │ ├── xcschememanagement.plist │ │ │ └── CocoaLogToWebServer.xcscheme │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ └── yanglele.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── CocoaLogToWebServer │ ├── ViewController.h │ ├── AppDelegate.h │ ├── main.m │ ├── ViewController.m │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ └── AppDelegate.m └── Classes │ ├── DBClass │ ├── FMDB.h │ ├── DBConnect.h │ ├── DBConnect.m │ ├── FMDatabasePool.h │ ├── FMDatabaseQueue.h │ ├── FMDatabaseQueue.m │ ├── FMDatabaseAdditions.m │ ├── FMDatabaseAdditions.h │ └── FMDatabasePool.m │ ├── DDLogClass │ ├── DDDBLogFormatter.h │ ├── DDLogCrash.h │ ├── DDDBLogger.h │ ├── logSqlModel.h │ ├── logSqlModel.m │ ├── DDLogCrash.m │ ├── DDDBLogFormatter.m │ ├── CocoaLumberjack.h │ ├── DDLegacyMacros.h │ ├── DDDBLogger.m │ ├── DDAbstractDatabaseLogger.h │ ├── DDLogMacros.h │ └── DDTTYLogger.h │ ├── ExLogger │ ├── ExLogger.h │ └── ExLogger.m │ ├── template.html │ ├── Common.h │ └── GCDWebServer │ ├── Requests │ ├── GCDWebServerFileRequest.h │ ├── GCDWebServerURLEncodedFormRequest.h │ ├── GCDWebServerDataRequest.h │ ├── GCDWebServerURLEncodedFormRequest.m │ ├── GCDWebServerDataRequest.m │ ├── GCDWebServerFileRequest.m │ └── GCDWebServerMultiPartFormRequest.h │ ├── Responses │ ├── GCDWebServerStreamedResponse.m │ ├── GCDWebServerStreamedResponse.h │ ├── GCDWebServerErrorResponse.h │ ├── GCDWebServerDataResponse.h │ ├── GCDWebServerFileResponse.h │ ├── GCDWebServerDataResponse.m │ ├── GCDWebServerErrorResponse.m │ └── GCDWebServerFileResponse.m │ └── Core │ ├── GCDWebServerFunctions.h │ ├── GCDWebServerHTTPStatusCodes.h │ ├── GCDWebServerConnection.h │ ├── GCDWebServerResponse.h │ ├── GCDWebServerRequest.h │ └── GCDWebServerPrivate.h ├── LICENSE └── CocoaLogToWebServer.podspec /CocoaLogToWebServer/CocoaLogToWebServer.xcodeproj/xcuserdata/yanglele.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/CocoaLogToWebServer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/CocoaLogToWebServer.xcodeproj/project.xcworkspace/xcuserdata/yanglele.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexYangLe/CocoaLogToWebServer/HEAD/CocoaLogToWebServer/CocoaLogToWebServer.xcodeproj/project.xcworkspace/xcuserdata/yanglele.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /CocoaLogToWebServer/CocoaLogToWebServer/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // CocoaLogToWebServer 4 | // 5 | // Created by 杨乐乐 on 16/4/20. 6 | // Copyright © 2016年 alex. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DBClass/FMDB.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | FOUNDATION_EXPORT double FMDBVersionNumber; 4 | FOUNDATION_EXPORT const unsigned char FMDBVersionString[]; 5 | 6 | #import "FMDatabase.h" 7 | #import "FMResultSet.h" 8 | #import "FMDatabaseAdditions.h" 9 | #import "FMDatabaseQueue.h" 10 | #import "FMDatabasePool.h" 11 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DDLogClass/DDDBLogFormatter.h: -------------------------------------------------------------------------------- 1 | // 2 | // DDDBLogFormatter.h 3 | // myLogToDB 4 | // 5 | // Created by Gump on 16/4/14. 6 | // Copyright © 2016年 Gump. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DDLog.h" 11 | 12 | 13 | @interface DDDBLogFormatter : NSObject 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DDLogClass/DDLogCrash.h: -------------------------------------------------------------------------------- 1 | // 2 | // DDLogCrash.h 3 | // ExLogger 4 | // 5 | // Created by Gump on 16/4/18. 6 | // Copyright © 2016年 Gump. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DDLogCrash : NSObject 12 | 13 | void uncaughtExceptionHandler(NSException *exception); 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DDLogClass/DDDBLogger.h: -------------------------------------------------------------------------------- 1 | // 2 | // DDDBLogger.h 3 | // myLogToDB 4 | // 5 | // Created by Gump on 16/4/14. 6 | // Copyright © 2016年 Gump. All rights reserved. 7 | // 8 | 9 | #import "DDAbstractDatabaseLogger.h" 10 | 11 | @interface DDDBLogger : DDAbstractDatabaseLogger 12 | 13 | @property (readwrite, assign) NSInteger saveDBTotalNum; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/ExLogger/ExLogger.h: -------------------------------------------------------------------------------- 1 | // 2 | // ExLogger.h 3 | // ExLogger 4 | // 5 | // Created by Gump on 16/4/15. 6 | // Copyright © 2016年 Gump. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ExLogger : NSObject 12 | 13 | +(void)prepare; 14 | 15 | +(BOOL)startService; 16 | +(void)stopService; 17 | 18 | +(BOOL)isStarted; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/CocoaLogToWebServer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // CocoaLogToWebServer 4 | // 5 | // Created by 杨乐乐 on 16/4/20. 6 | // Copyright © 2016年 alex. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/CocoaLogToWebServer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CocoaLogToWebServer 4 | // 5 | // Created by 杨乐乐 on 16/4/20. 6 | // Copyright © 2016年 alex. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DDLogClass/logSqlModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // logSqlModel.h 3 | // myLogToDB 4 | // 5 | // Created by Gump on 16/4/15. 6 | // Copyright © 2016年 Gump. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface logSqlModel : NSObject 12 | 13 | //统计数量的sql语句 14 | @property (nonatomic, copy) NSString *countSqlStr; 15 | //插入数据的sql语句 16 | @property (nonatomic, copy) NSString *insertSqlStr; 17 | //更新数据的sql语句(更新删除) 18 | @property (nonatomic, copy) NSString *updateDataSqlStr; 19 | //查询数据的sql语句 20 | @property (nonatomic, copy) NSString *queryDataSqlStr; 21 | 22 | -(instancetype)init; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/CocoaLogToWebServer.xcodeproj/xcuserdata/yanglele.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CocoaLogToWebServer.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 7551535A1CC788690054AE72 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DDLogClass/logSqlModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // logSqlModel.m 3 | // myLogToDB 4 | // 5 | // Created by Gump on 16/4/15. 6 | // Copyright © 2016年 Gump. All rights reserved. 7 | // 8 | 9 | #import "logSqlModel.h" 10 | 11 | @implementation logSqlModel 12 | 13 | -(instancetype)init 14 | { 15 | if (self = [super init]) { 16 | _countSqlStr = @"SELECT count(*) FROM logMessageHistory"; 17 | _insertSqlStr = @"INSERT INTO logMessageHistory (logtime,filename,line,function,message, level,lastUpdateTime) VALUES (?, ?, ?, ?, ?, ?, ?)"; 18 | _updateDataSqlStr = @"UPDATE logMessageHistory SET logtime = ?, filename = ?, line = ?, function = ?, message = ?, level = ?, lastUpdateTime = ? order by lastUpdateTime limit 1"; 19 | _queryDataSqlStr = @"SELECT logtime,filename,line,function,message,level,lastUpdateTime FROM logMessageHistory"; 20 | } 21 | return self; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DDLogClass/DDLogCrash.m: -------------------------------------------------------------------------------- 1 | // 2 | // DDLogCrash.m 3 | // ExLogger 4 | // 5 | // Created by Gump on 16/4/18. 6 | // Copyright © 2016年 Gump. All rights reserved. 7 | // 8 | 9 | #import "DDLogCrash.h" 10 | #import "Common.h" 11 | 12 | @implementation DDLogCrash 13 | 14 | void uncaughtExceptionHandler(NSException *exception) 15 | { 16 | //异常的堆栈信息 17 | NSArray *stackArray = [exception callStackSymbols]; 18 | //出现异常的原因 19 | NSString *reason = [exception reason]; 20 | //异常名称 21 | NSString *name = [exception name]; 22 | 23 | NSString *exceptionInfo = [NSString stringWithFormat:@"Exception resaon: %@\n Exception name: %@\n Exception static: %@", name, reason, stackArray]; 24 | DDLogError(@"%@",exceptionInfo); 25 | 26 | [exceptionInfo writeToFile:[NSString stringWithFormat:@"%@/Documents/error.log",NSHomeDirectory()] atomically:YES encoding:NSUTF8StringEncoding error:nil]; 27 | 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DBClass/DBConnect.h: -------------------------------------------------------------------------------- 1 | // 2 | // DBConnect.h 3 | // Ershixiong 4 | // 5 | // Created by tw001 on 14-8-29. 6 | // Copyright (c) 2014年 wave. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FMDB.h" 11 | #import "FMResultSet.h" 12 | 13 | @interface DBConnect : NSObject 14 | 15 | @property (nonatomic, retain) FMDatabase *dataBase; // 数据库类 16 | @property (nonatomic, retain) FMDatabaseQueue *dbQueue; 17 | 18 | /// 通过单例的方式 19 | + (DBConnect *)shareConnect; 20 | 21 | /// 打开数据库 22 | - (void)openDatabase; 23 | 24 | /// 判断是否存在表 25 | - (BOOL)isTableOK:(NSString *)tableName; 26 | 27 | /// 创建表 28 | - (BOOL)createTableSql:(NSString *)sql; 29 | 30 | /// 获得数据 31 | - (NSArray *)getDBlist:(NSString *)sql; 32 | 33 | /// 获得单条数据 34 | - (NSDictionary *)getDBOneData:(NSString *)sql; 35 | 36 | /// 统计数量 37 | - (int)getDBDataCount:(NSString *)sql; 38 | 39 | /// 执行sql (主要用来执行插入操作) 40 | - (unsigned)executeInsertSql:(NSString *)sql; 41 | 42 | /// 更新操作,删除操作 43 | - (void)executeUpdateSql:(NSString *)sql; 44 | 45 | /// 关闭数据库 46 | - (void)closeDatabase; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 gitCommandProgectTest 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/CocoaLogToWebServer/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // CocoaLogToWebServer 4 | // 5 | // Created by 杨乐乐 on 16/4/20. 6 | // Copyright © 2016年 alex. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "Common.h" 11 | 12 | @interface ViewController () 13 | @property(weak, nonatomic) IBOutlet UILabel* label; 14 | @property(weak,nonatomic) IBOutlet UIButton *btn; 15 | @end 16 | 17 | @implementation ViewController 18 | 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | NSLog(@"viewDidLoad"); 23 | if ([ExLogger isStarted]) { 24 | _label.text = [NSString stringWithFormat:NSLocalizedString(@"GCDWebServer running locally on port %i", nil), 8089]; 25 | } else { 26 | _label.text = NSLocalizedString(@"GCDWebServer not running!", nil); 27 | } 28 | } 29 | 30 | -(void)viewWillAppear:(BOOL)animated{ 31 | 32 | } 33 | 34 | - (void)didReceiveMemoryWarning { 35 | [super didReceiveMemoryWarning]; 36 | // Dispose of any resources that can be recreated. 37 | } 38 | 39 | -(IBAction)generateLog:(id)sender{ 40 | NSLog(@"this is a new log! time:%@",[NSDate date]); 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 |
    13 |
  • 14 | {{ x.logtime }}   [{{x.level}}]-{{x.filename}}:{{x.line}}/{{x.function}}  => {{x.message}} 15 |
  • 16 |
17 | 18 |
19 | 20 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // Common.h 3 | // CocoaLogToWebServer 4 | // 5 | // Created by 杨乐乐 on 16/4/21. 6 | // Copyright © 2016年 alex. All rights reserved. 7 | // 8 | 9 | #ifndef Common_h 10 | #define Common_h 11 | 12 | #ifdef __OBJC__ 13 | #import "DDTTYLogger.h" 14 | #import "DDDBLogger.h" 15 | #import "DDDBLogFormatter.h" 16 | #import "DDLogMacros.h" 17 | #import "DDLog.h" 18 | #import "DBConnect.h" 19 | #import "logSqlModel.h" 20 | #import "DDLogCrash.h" 21 | #import "ExLogger.h" 22 | #endif 23 | 24 | #ifndef DEBUG 25 | static const int ddLogLevel = DDLogLevelDebug; 26 | #else 27 | static const int ddLogLevel = DDLogLevelInfo; 28 | #endif 29 | 30 | #ifndef DEBUG 31 | #define NSLog(format, ...) 32 | #else 33 | #define NSLog(format, ...) DDLogWarn(format, ##__VA_ARGS__) 34 | #endif 35 | 36 | #define DDAssert(condition, frmt, ...) \ 37 | if (!(condition)) { \ 38 | NSString *description = [NSString stringWithFormat:frmt, ## __VA_ARGS__]; \ 39 | DDLogError(@"%@", description); \ 40 | NSAssert(NO, description); \ 41 | } 42 | #define DDAssertCondition(condition) DDAssert(condition, @"Condition not satisfied: %s", #condition) 43 | 44 | 45 | 46 | #endif /* Common_h */ 47 | -------------------------------------------------------------------------------- /CocoaLogToWebServer.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "CocoaLogToWebServer" 4 | s.version = "1.0.0" 5 | s.summary = "通过使用CocoaLumberjack 和GCDWebServer实现日志NSLog打印的重定向,并且可以使用浏览器访问日志" 6 | s.description = <<-DESC 7 | 通过使用CocoaLumberjack 和GCDWebServer实现日志NSLog打印> 的重定向,并且可以使用浏览器访问日志 8 | DESC 9 | 10 | s.homepage = "https://github.com/yanduhantan563/CocoaLogToWebServer" 11 | 12 | s.license = "MIT" 13 | 14 | s.author = { "yanduhantan563" => "yanduhantan563@sina.com" } 15 | s.source = { :git => "https://github.com/yanduhantan563/CocoaLogToWebServer.git", :commit => "ebf02ee7068571b24453ede54a6d01ae02641c9b", :tag => "1.0.0" } 16 | s.requires_arc = true 17 | s.source_files = 'CocoaLogToWebServer/Classes/**/*' 18 | s.library = 'sqlite3', 'z', 'xml2' 19 | s.frameworks = "MobileCoreServices","CFNetwork" 20 | s.platform = :ios, "7.0" 21 | s.ios.deployment_target = "5.0" 22 | 23 | s.resource = "CocoaLogToWebServer/Classes/template.html" 24 | s.public_header_files = "CocoaLogToWebServer/Classes/Common.h" 25 | # s.prefix_header_contents = "CocoaLogToWebServer/Classes/CocoaLogToWebServerPrefix.pch" 26 | # s.prefix_header_contents = "CocoaLogToWebServer/Classes/*.pch" 27 | # s.framework = "SomeFramework" 28 | # s.frameworks = "SomeFramework", "AnotherFramework" 29 | end 30 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DDLogClass/DDDBLogFormatter.m: -------------------------------------------------------------------------------- 1 | // 2 | // DDDBLogFormatter.m 3 | // myLogToDB 4 | // 5 | // Created by Gump on 16/4/14. 6 | // Copyright © 2016年 Gump. All rights reserved. 7 | // 8 | 9 | #import "DDDBLogFormatter.h" 10 | 11 | @implementation DDDBLogFormatter 12 | 13 | //实现代理协议format方法 14 | -(NSString *)formatLogMessage:(DDLogMessage *)logMessage 15 | { 16 | NSMutableDictionary *logDic = [NSMutableDictionary dictionary]; 17 | 18 | NSString *locationString; 19 | NSArray *parts = [logMessage->_file componentsSeparatedByString:@"/"]; 20 | if (parts.count > 0) 21 | { 22 | locationString = [parts lastObject]; 23 | } 24 | if (parts.count == 0) 25 | { 26 | locationString = @"no file"; 27 | } 28 | 29 | logDic[@"gampTech"] = [NSString stringWithFormat:@"%@:%lu(%@):%@", locationString, (unsigned long)logMessage.line, logMessage.function, logMessage.message]; 30 | //NSMutableDictionary 转成 NSString 31 | NSError *error; 32 | NSData *outputJsonData = [NSJSONSerialization dataWithJSONObject:logDic options:0 error:&error]; 33 | if (error) { 34 | return @"{\"gampTech\":\"error\"}"; 35 | } 36 | NSString *outputJsonStr = [[NSString alloc] initWithData:outputJsonData encoding:NSUTF8StringEncoding]; 37 | if (outputJsonStr) { 38 | return outputJsonStr; 39 | } 40 | return @"{\"gampTech\":\"error\"}"; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/CocoaLogToWebServer/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /CocoaLogToWebServer/CocoaLogToWebServer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/CocoaLogToWebServer/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Requests/GCDWebServerFileRequest.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerRequest.h" 29 | 30 | /** 31 | * The GCDWebServerFileRequest subclass of GCDWebServerRequest stores the body 32 | * of the HTTP request to a file on disk. 33 | */ 34 | @interface GCDWebServerFileRequest : GCDWebServerRequest 35 | 36 | /** 37 | * Returns the path to the temporary file containing the request body. 38 | * 39 | * @warning This temporary file will be automatically deleted when the 40 | * GCDWebServerFileRequest is deallocated. If you want to preserve this file, 41 | * you must move it to a different location beforehand. 42 | */ 43 | @property(nonatomic, readonly) NSString* temporaryPath; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/ExLogger/ExLogger.m: -------------------------------------------------------------------------------- 1 | // 2 | // ExLogger.m 3 | // ExLogger 4 | // 5 | // Created by Gump on 16/4/15. 6 | // Copyright © 2016年 Gump. All rights reserved. 7 | // 8 | 9 | #import "GCDWebServer.h" 10 | #import "GCDWebServerDataResponse.h" 11 | #import "Common.h" 12 | 13 | @implementation ExLogger 14 | 15 | static BOOL isStarted; 16 | static GCDWebServer *_webServer; 17 | 18 | +(void)prepare{ 19 | //TODO 初始化DDLog 20 | [DDLog addLogger:[DDTTYLogger sharedInstance]]; 21 | 22 | DDDBLogger *logger = [[DDDBLogger alloc] init]; 23 | [logger setLogFormatter:[DDDBLogFormatter new]]; 24 | [logger setSaveDBTotalNum:2000]; 25 | [DDLog addLogger:logger]; 26 | 27 | NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler); 28 | } 29 | 30 | //从数据库查询日志 31 | +(NSArray*)logsFromDB{ 32 | logSqlModel *logSql = [[logSqlModel alloc] init]; 33 | return [[DBConnect shareConnect] getDBlist:logSql.queryDataSqlStr]; 34 | } 35 | 36 | +(BOOL)startService{ 37 | NSLog(@"start service! _webserver=%@",_webServer); 38 | if (isStarted) { 39 | return NO; 40 | } 41 | if(!_webServer) 42 | _webServer = [[GCDWebServer alloc] init]; 43 | 44 | //首页请求 45 | [_webServer addDefaultHandlerForMethod:@"GET" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse*(GCDWebServerRequest *request){ 46 | NSError *err; 47 | NSString *path = [[NSBundle mainBundle] pathForResource:@"template" ofType:@"html"]; 48 | NSLog(@"path:%@",path); 49 | GCDWebServerResponse *response = [GCDWebServerDataResponse responseWithHTML:[NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&err]]; 50 | return response; 51 | }]; 52 | //日志数据请求 53 | [_webServer addHandlerForMethod:@"GET" path:@"/logs" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse*(GCDWebServerRequest *request){ 54 | NSArray *array = [self logsFromDB]; 55 | 56 | return [GCDWebServerDataResponse responseWithJSONObject:array]; 57 | }]; 58 | 59 | isStarted = [_webServer startWithPort:8089 bonjourName:nil]; 60 | return isStarted; 61 | 62 | } 63 | 64 | +(void)stopService{ 65 | [_webServer stop]; 66 | isStarted= NO; 67 | _webServer = nil; 68 | 69 | } 70 | 71 | +(BOOL)isStarted{ 72 | return isStarted; 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerDataRequest.h" 29 | 30 | /** 31 | * The GCDWebServerURLEncodedFormRequest subclass of GCDWebServerRequest 32 | * parses the body of the HTTP request as a URL encoded form using 33 | * GCDWebServerParseURLEncodedForm(). 34 | */ 35 | @interface GCDWebServerURLEncodedFormRequest : GCDWebServerDataRequest 36 | 37 | /** 38 | * Returns the unescaped control names and values for the URL encoded form. 39 | * 40 | * The text encoding used to interpret the data is extracted from the 41 | * "Content-Type" header or defaults to UTF-8. 42 | */ 43 | @property(nonatomic, readonly) NSDictionary* arguments; 44 | 45 | /** 46 | * Returns the MIME type for URL encoded forms 47 | * i.e. "application/x-www-form-urlencoded". 48 | */ 49 | + (NSString*)mimeType; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/CocoaLogToWebServer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // CocoaLogToWebServer 4 | // 5 | // Created by 杨乐乐 on 16/4/20. 6 | // Copyright © 2016年 alex. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "Common.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | // Override point for customization after application launch. 21 | 22 | NSLog(@"didFinishLaunchingWithOptions"); 23 | [ExLogger startService]; 24 | [ExLogger prepare]; 25 | NSLog(@"exlogger startservice:%@",[ExLogger isStarted]?@"YES":@"NO"); 26 | 27 | 28 | return YES; 29 | } 30 | 31 | - (void)applicationWillResignActive:(UIApplication *)application { 32 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 33 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 34 | } 35 | 36 | - (void)applicationDidEnterBackground:(UIApplication *)application { 37 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 38 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 39 | } 40 | 41 | - (void)applicationWillEnterForeground:(UIApplication *)application { 42 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 43 | } 44 | 45 | - (void)applicationDidBecomeActive:(UIApplication *)application { 46 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 47 | } 48 | 49 | - (void)applicationWillTerminate:(UIApplication *)application { 50 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 51 | NSLog(@"applicationWillTerminate"); 52 | [ExLogger stopService]; 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Requests/GCDWebServerDataRequest.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerRequest.h" 29 | 30 | /** 31 | * The GCDWebServerDataRequest subclass of GCDWebServerRequest stores the body 32 | * of the HTTP request in memory. 33 | */ 34 | @interface GCDWebServerDataRequest : GCDWebServerRequest 35 | 36 | /** 37 | * Returns the data for the request body. 38 | */ 39 | @property(nonatomic, readonly) NSData* data; 40 | 41 | @end 42 | 43 | @interface GCDWebServerDataRequest (Extensions) 44 | 45 | /** 46 | * Returns the data for the request body interpreted as text. If the content 47 | * type of the body is not a text one, or if an error occurs, nil is returned. 48 | * 49 | * The text encoding used to interpret the data is extracted from the 50 | * "Content-Type" header or defaults to UTF-8. 51 | */ 52 | @property(nonatomic, readonly) NSString* text; 53 | 54 | /** 55 | * Returns the data for the request body interpreted as a JSON object. If the 56 | * content type of the body is not JSON, or if an error occurs, nil is returned. 57 | */ 58 | @property(nonatomic, readonly) id jsonObject; 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DDLogClass/CocoaLumberjack.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 | /** 17 | * Welcome to CocoaLumberjack! 18 | * 19 | * The project page has a wealth of documentation if you have any questions. 20 | * https://github.com/CocoaLumberjack/CocoaLumberjack 21 | * 22 | * If you're new to the project you may wish to read "Getting Started" at: 23 | * Documentation/GettingStarted.md 24 | * 25 | * Otherwise, here is a quick refresher. 26 | * There are three steps to using the macros: 27 | * 28 | * Step 1: 29 | * Import the header in your implementation or prefix file: 30 | * 31 | * #import 32 | * 33 | * Step 2: 34 | * Define your logging level in your implementation file: 35 | * 36 | * // Log levels: off, error, warn, info, verbose 37 | * static const DDLogLevel ddLogLevel = DDLogLevelVerbose; 38 | * 39 | * Step 2 [3rd party frameworks]: 40 | * 41 | * Define your LOG_LEVEL_DEF to a different variable/function than ddLogLevel: 42 | * 43 | * // #undef LOG_LEVEL_DEF // Undefine first only if needed 44 | * #define LOG_LEVEL_DEF myLibLogLevel 45 | * 46 | * Define your logging level in your implementation file: 47 | * 48 | * // Log levels: off, error, warn, info, verbose 49 | * static const DDLogLevel myLibLogLevel = DDLogLevelVerbose; 50 | * 51 | * Step 3: 52 | * Replace your NSLog statements with DDLog statements according to the severity of the message. 53 | * 54 | * NSLog(@"Fatal error, no dohickey found!"); -> DDLogError(@"Fatal error, no dohickey found!"); 55 | * 56 | * DDLog works exactly the same as NSLog. 57 | * This means you can pass it multiple variables just like NSLog. 58 | **/ 59 | 60 | #import 61 | 62 | // Disable legacy macros 63 | #ifndef DD_LEGACY_MACROS 64 | #define DD_LEGACY_MACROS 0 65 | #endif 66 | 67 | // Core 68 | #import "DDLog.h" 69 | 70 | // Main macros 71 | #import "DDLogMacros.h" 72 | #import "DDAssertMacros.h" 73 | 74 | // Capture ASL 75 | #import "DDASLLogCapture.h" 76 | 77 | // Loggers 78 | #import "DDTTYLogger.h" 79 | #import "DDASLLogger.h" 80 | #import "DDFileLogger.h" 81 | 82 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import "GCDWebServerPrivate.h" 33 | 34 | @interface GCDWebServerURLEncodedFormRequest () { 35 | @private 36 | NSDictionary* _arguments; 37 | } 38 | @end 39 | 40 | @implementation GCDWebServerURLEncodedFormRequest 41 | 42 | @synthesize arguments=_arguments; 43 | 44 | + (NSString*)mimeType { 45 | return @"application/x-www-form-urlencoded"; 46 | } 47 | 48 | - (BOOL)close:(NSError**)error { 49 | if (![super close:error]) { 50 | return NO; 51 | } 52 | 53 | NSString* charset = GCDWebServerExtractHeaderValueParameter(self.contentType, @"charset"); 54 | NSString* string = [[NSString alloc] initWithData:self.data encoding:GCDWebServerStringEncodingFromCharset(charset)]; 55 | _arguments = GCDWebServerParseURLEncodedForm(string); 56 | GWS_DCHECK(_arguments); 57 | 58 | return YES; 59 | } 60 | 61 | - (NSString*)description { 62 | NSMutableString* description = [NSMutableString stringWithString:[super description]]; 63 | [description appendString:@"\n"]; 64 | for (NSString* argument in [[_arguments allKeys] sortedArrayUsingSelector:@selector(compare:)]) { 65 | [description appendFormat:@"\n%@ = %@", argument, [_arguments objectForKey:argument]]; 66 | } 67 | return description; 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Responses/GCDWebServerStreamedResponse.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import "GCDWebServerPrivate.h" 33 | 34 | @interface GCDWebServerStreamedResponse () { 35 | @private 36 | GCDWebServerAsyncStreamBlock _block; 37 | } 38 | @end 39 | 40 | @implementation GCDWebServerStreamedResponse 41 | 42 | + (instancetype)responseWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block { 43 | return [[[self class] alloc] initWithContentType:type streamBlock:block]; 44 | } 45 | 46 | + (instancetype)responseWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block { 47 | return [[[self class] alloc] initWithContentType:type asyncStreamBlock:block]; 48 | } 49 | 50 | - (instancetype)initWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block { 51 | return [self initWithContentType:type asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock completionBlock) { 52 | 53 | NSError* error = nil; 54 | NSData* data = block(&error); 55 | completionBlock(data, error); 56 | 57 | }]; 58 | } 59 | 60 | - (instancetype)initWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block { 61 | if ((self = [super init])) { 62 | _block = [block copy]; 63 | 64 | self.contentType = type; 65 | } 66 | return self; 67 | } 68 | 69 | - (void)asyncReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block { 70 | _block(block); 71 | } 72 | 73 | - (NSString*)description { 74 | NSMutableString* description = [NSMutableString stringWithString:[super description]]; 75 | [description appendString:@"\n\n"]; 76 | return description; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Responses/GCDWebServerStreamedResponse.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerResponse.h" 29 | 30 | /** 31 | * The GCDWebServerStreamBlock is called to stream the data for the HTTP body. 32 | * The block must return either a chunk of data, an empty NSData when done, or 33 | * nil on error and set the "error" argument which is guaranteed to be non-NULL. 34 | */ 35 | typedef NSData* (^GCDWebServerStreamBlock)(NSError** error); 36 | 37 | /** 38 | * The GCDWebServerAsyncStreamBlock works like the GCDWebServerStreamBlock 39 | * except the streamed data can be returned at a later time allowing for 40 | * truly asynchronous generation of the data. 41 | * 42 | * The block must call "completionBlock" passing the new chunk of data when ready, 43 | * an empty NSData when done, or nil on error and pass a NSError. 44 | * 45 | * The block cannot call "completionBlock" more than once per invocation. 46 | */ 47 | typedef void (^GCDWebServerAsyncStreamBlock)(GCDWebServerBodyReaderCompletionBlock completionBlock); 48 | 49 | /** 50 | * The GCDWebServerStreamedResponse subclass of GCDWebServerResponse streams 51 | * the body of the HTTP response using a GCD block. 52 | */ 53 | @interface GCDWebServerStreamedResponse : GCDWebServerResponse 54 | 55 | /** 56 | * Creates a response with streamed data and a given content type. 57 | */ 58 | + (instancetype)responseWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block; 59 | 60 | /** 61 | * Creates a response with async streamed data and a given content type. 62 | */ 63 | + (instancetype)responseWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block; 64 | 65 | /** 66 | * Initializes a response with streamed data and a given content type. 67 | */ 68 | - (instancetype)initWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block; 69 | 70 | /** 71 | * This method is the designated initializer for the class. 72 | */ 73 | - (instancetype)initWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block; 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DDLogClass/DDLegacyMacros.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 | /** 17 | * Legacy macros used for 1.9.x backwards compatibility. 18 | * 19 | * Imported by default when importing a DDLog.h directly and DD_LEGACY_MACROS is not defined and set to 0. 20 | **/ 21 | #if DD_LEGACY_MACROS 22 | 23 | #ifndef LOG_LEVEL_DEF 24 | #define LOG_LEVEL_DEF ddLogLevel 25 | #endif 26 | 27 | #define LOG_FLAG_ERROR DDLogFlagError 28 | #define LOG_FLAG_WARN DDLogFlagWarning 29 | #define LOG_FLAG_INFO DDLogFlagInfo 30 | #define LOG_FLAG_DEBUG DDLogFlagDebug 31 | #define LOG_FLAG_VERBOSE DDLogFlagVerbose 32 | 33 | #define LOG_LEVEL_OFF DDLogLevelOff 34 | #define LOG_LEVEL_ERROR DDLogLevelError 35 | #define LOG_LEVEL_WARN DDLogLevelWarning 36 | #define LOG_LEVEL_INFO DDLogLevelInfo 37 | #define LOG_LEVEL_DEBUG DDLogLevelDebug 38 | #define LOG_LEVEL_VERBOSE DDLogLevelVerbose 39 | #define LOG_LEVEL_ALL DDLogLevelAll 40 | 41 | #define LOG_ASYNC_ENABLED YES 42 | 43 | #define LOG_ASYNC_ERROR ( NO && LOG_ASYNC_ENABLED) 44 | #define LOG_ASYNC_WARN (YES && LOG_ASYNC_ENABLED) 45 | #define LOG_ASYNC_INFO (YES && LOG_ASYNC_ENABLED) 46 | #define LOG_ASYNC_DEBUG (YES && LOG_ASYNC_ENABLED) 47 | #define LOG_ASYNC_VERBOSE (YES && LOG_ASYNC_ENABLED) 48 | 49 | #define LOG_MACRO(isAsynchronous, lvl, flg, ctx, atag, fnct, frmt, ...) \ 50 | [DDLog log : isAsynchronous \ 51 | level : lvl \ 52 | flag : flg \ 53 | context : ctx \ 54 | file : __FILE__ \ 55 | function : fnct \ 56 | line : __LINE__ \ 57 | tag : atag \ 58 | format : (frmt), ## __VA_ARGS__] 59 | 60 | #define LOG_MAYBE(async, lvl, flg, ctx, fnct, frmt, ...) \ 61 | do { if(lvl & flg) LOG_MACRO(async, lvl, flg, ctx, nil, fnct, frmt, ##__VA_ARGS__); } while(0) 62 | 63 | #define LOG_OBJC_MAYBE(async, lvl, flg, ctx, frmt, ...) \ 64 | LOG_MAYBE(async, lvl, flg, ctx, __PRETTY_FUNCTION__, frmt, ## __VA_ARGS__) 65 | 66 | #define DDLogError(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_ERROR, LOG_LEVEL_DEF, LOG_FLAG_ERROR, 0, frmt, ##__VA_ARGS__) 67 | #define DDLogWarn(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_WARN, LOG_LEVEL_DEF, LOG_FLAG_WARN, 0, frmt, ##__VA_ARGS__) 68 | #define DDLogInfo(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_INFO, LOG_LEVEL_DEF, LOG_FLAG_INFO, 0, frmt, ##__VA_ARGS__) 69 | #define DDLogDebug(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_DEBUG, LOG_LEVEL_DEF, LOG_FLAG_DEBUG, 0, frmt, ##__VA_ARGS__) 70 | #define DDLogVerbose(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_VERBOSE, LOG_LEVEL_DEF, LOG_FLAG_VERBOSE, 0, frmt, ##__VA_ARGS__) 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/CocoaLogToWebServer.xcodeproj/xcuserdata/yanglele.xcuserdatad/xcschemes/CocoaLogToWebServer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/CocoaLogToWebServer/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Requests/GCDWebServerDataRequest.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import "GCDWebServerPrivate.h" 33 | 34 | @interface GCDWebServerDataRequest () { 35 | @private 36 | NSMutableData* _data; 37 | 38 | NSString* _text; 39 | id _jsonObject; 40 | } 41 | @end 42 | 43 | @implementation GCDWebServerDataRequest 44 | 45 | @synthesize data=_data; 46 | 47 | - (BOOL)open:(NSError**)error { 48 | if (self.contentLength != NSUIntegerMax) { 49 | _data = [[NSMutableData alloc] initWithCapacity:self.contentLength]; 50 | } else { 51 | _data = [[NSMutableData alloc] init]; 52 | } 53 | if (_data == nil) { 54 | if (error) { 55 | *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Failed allocating memory"}]; 56 | } 57 | return NO; 58 | } 59 | return YES; 60 | } 61 | 62 | - (BOOL)writeData:(NSData*)data error:(NSError**)error { 63 | [_data appendData:data]; 64 | return YES; 65 | } 66 | 67 | - (BOOL)close:(NSError**)error { 68 | return YES; 69 | } 70 | 71 | - (NSString*)description { 72 | NSMutableString* description = [NSMutableString stringWithString:[super description]]; 73 | if (_data) { 74 | [description appendString:@"\n\n"]; 75 | [description appendString:GCDWebServerDescribeData(_data, self.contentType)]; 76 | } 77 | return description; 78 | } 79 | 80 | @end 81 | 82 | @implementation GCDWebServerDataRequest (Extensions) 83 | 84 | - (NSString*)text { 85 | if (_text == nil) { 86 | if ([self.contentType hasPrefix:@"text/"]) { 87 | NSString* charset = GCDWebServerExtractHeaderValueParameter(self.contentType, @"charset"); 88 | _text = [[NSString alloc] initWithData:self.data encoding:GCDWebServerStringEncodingFromCharset(charset)]; 89 | } else { 90 | GWS_DNOT_REACHED(); 91 | } 92 | } 93 | return _text; 94 | } 95 | 96 | - (id)jsonObject { 97 | if (_jsonObject == nil) { 98 | NSString* mimeType = GCDWebServerTruncateHeaderValue(self.contentType); 99 | if ([mimeType isEqualToString:@"application/json"] || [mimeType isEqualToString:@"text/json"] || [mimeType isEqualToString:@"text/javascript"]) { 100 | _jsonObject = [NSJSONSerialization JSONObjectWithData:_data options:0 error:NULL]; 101 | } else { 102 | GWS_DNOT_REACHED(); 103 | } 104 | } 105 | return _jsonObject; 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Core/GCDWebServerFunctions.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | /** 35 | * Converts a file extension to the corresponding MIME type. 36 | * If there is no match, "application/octet-stream" is returned. 37 | */ 38 | NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension); 39 | 40 | /** 41 | * Add percent-escapes to a string so it can be used in a URL. 42 | * The legal characters ":@/?&=+" are also escaped to ensure compatibility 43 | * with URL encoded forms and URL queries. 44 | */ 45 | NSString* GCDWebServerEscapeURLString(NSString* string); 46 | 47 | /** 48 | * Unescapes a URL percent-encoded string. 49 | */ 50 | NSString* GCDWebServerUnescapeURLString(NSString* string); 51 | 52 | /** 53 | * Extracts the unescaped names and values from an 54 | * "application/x-www-form-urlencoded" form. 55 | * http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1 56 | */ 57 | NSDictionary* GCDWebServerParseURLEncodedForm(NSString* form); 58 | 59 | /** 60 | * On OS X, returns the IPv4 or IPv6 address as a string of the primary 61 | * connected service or nil if not available. 62 | * 63 | * On iOS, returns the IPv4 or IPv6 address as a string of the WiFi 64 | * interface if connected or nil otherwise. 65 | */ 66 | NSString* GCDWebServerGetPrimaryIPAddress(BOOL useIPv6); 67 | 68 | /** 69 | * Converts a date into a string using RFC822 formatting. 70 | * https://tools.ietf.org/html/rfc822#section-5 71 | * https://tools.ietf.org/html/rfc1123#section-5.2.14 72 | */ 73 | NSString* GCDWebServerFormatRFC822(NSDate* date); 74 | 75 | /** 76 | * Converts a RFC822 formatted string into a date. 77 | * https://tools.ietf.org/html/rfc822#section-5 78 | * https://tools.ietf.org/html/rfc1123#section-5.2.14 79 | * 80 | * @warning Timezones other than GMT are not supported by this function. 81 | */ 82 | NSDate* GCDWebServerParseRFC822(NSString* string); 83 | 84 | /** 85 | * Converts a date into a string using IOS 8601 formatting. 86 | * http://tools.ietf.org/html/rfc3339#section-5.6 87 | */ 88 | NSString* GCDWebServerFormatISO8601(NSDate* date); 89 | 90 | /** 91 | * Converts a ISO 8601 formatted string into a date. 92 | * http://tools.ietf.org/html/rfc3339#section-5.6 93 | * 94 | * @warning Only "calendar" variant is supported at this time and timezones 95 | * other than GMT are not supported either. 96 | */ 97 | NSDate* GCDWebServerParseISO8601(NSString* string); 98 | 99 | #ifdef __cplusplus 100 | } 101 | #endif 102 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Responses/GCDWebServerErrorResponse.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerDataResponse.h" 29 | #import "GCDWebServerHTTPStatusCodes.h" 30 | 31 | /** 32 | * The GCDWebServerDataResponse subclass of GCDWebServerDataResponse generates 33 | * an HTML body from an HTTP status code and an error message. 34 | */ 35 | @interface GCDWebServerErrorResponse : GCDWebServerDataResponse 36 | 37 | /** 38 | * Creates a client error response with the corresponding HTTP status code. 39 | */ 40 | + (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); 41 | 42 | /** 43 | * Creates a server error response with the corresponding HTTP status code. 44 | */ 45 | + (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); 46 | 47 | /** 48 | * Creates a client error response with the corresponding HTTP status code 49 | * and an underlying NSError. 50 | */ 51 | + (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); 52 | 53 | /** 54 | * Creates a server error response with the corresponding HTTP status code 55 | * and an underlying NSError. 56 | */ 57 | + (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); 58 | 59 | /** 60 | * Initializes a client error response with the corresponding HTTP status code. 61 | */ 62 | - (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); 63 | 64 | /** 65 | * Initializes a server error response with the corresponding HTTP status code. 66 | */ 67 | - (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); 68 | 69 | /** 70 | * Initializes a client error response with the corresponding HTTP status code 71 | * and an underlying NSError. 72 | */ 73 | - (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); 74 | 75 | /** 76 | * Initializes a server error response with the corresponding HTTP status code 77 | * and an underlying NSError. 78 | */ 79 | - (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Responses/GCDWebServerDataResponse.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerResponse.h" 29 | 30 | /** 31 | * The GCDWebServerDataResponse subclass of GCDWebServerResponse reads the body 32 | * of the HTTP response from memory. 33 | */ 34 | @interface GCDWebServerDataResponse : GCDWebServerResponse 35 | 36 | /** 37 | * Creates a response with data in memory and a given content type. 38 | */ 39 | + (instancetype)responseWithData:(NSData*)data contentType:(NSString*)type; 40 | 41 | /** 42 | * This method is the designated initializer for the class. 43 | */ 44 | - (instancetype)initWithData:(NSData*)data contentType:(NSString*)type; 45 | 46 | @end 47 | 48 | @interface GCDWebServerDataResponse (Extensions) 49 | 50 | /** 51 | * Creates a data response from text encoded using UTF-8. 52 | */ 53 | + (instancetype)responseWithText:(NSString*)text; 54 | 55 | /** 56 | * Creates a data response from HTML encoded using UTF-8. 57 | */ 58 | + (instancetype)responseWithHTML:(NSString*)html; 59 | 60 | /** 61 | * Creates a data response from an HTML template encoded using UTF-8. 62 | * See -initWithHTMLTemplate:variables: for details. 63 | */ 64 | + (instancetype)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables; 65 | 66 | /** 67 | * Creates a data response from a serialized JSON object and the default 68 | * "application/json" content type. 69 | */ 70 | + (instancetype)responseWithJSONObject:(id)object; 71 | 72 | /** 73 | * Creates a data response from a serialized JSON object and a custom 74 | * content type. 75 | */ 76 | + (instancetype)responseWithJSONObject:(id)object contentType:(NSString*)type; 77 | 78 | /** 79 | * Initializes a data response from text encoded using UTF-8. 80 | */ 81 | - (instancetype)initWithText:(NSString*)text; 82 | 83 | /** 84 | * Initializes a data response from HTML encoded using UTF-8. 85 | */ 86 | - (instancetype)initWithHTML:(NSString*)html; 87 | 88 | /** 89 | * Initializes a data response from an HTML template encoded using UTF-8. 90 | * 91 | * All occurences of "%variable%" within the HTML template are replaced with 92 | * their corresponding values. 93 | */ 94 | - (instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables; 95 | 96 | /** 97 | * Initializes a data response from a serialized JSON object and the default 98 | * "application/json" content type. 99 | */ 100 | - (instancetype)initWithJSONObject:(id)object; 101 | 102 | /** 103 | * Initializes a data response from a serialized JSON object and a custom 104 | * content type. 105 | */ 106 | - (instancetype)initWithJSONObject:(id)object contentType:(NSString*)type; 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Responses/GCDWebServerFileResponse.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerResponse.h" 29 | 30 | /** 31 | * The GCDWebServerFileResponse subclass of GCDWebServerResponse reads the body 32 | * of the HTTP response from a file on disk. 33 | * 34 | * It will automatically set the contentType, lastModifiedDate and eTag 35 | * properties of the GCDWebServerResponse according to the file extension and 36 | * metadata. 37 | */ 38 | @interface GCDWebServerFileResponse : GCDWebServerResponse 39 | 40 | /** 41 | * Creates a response with the contents of a file. 42 | */ 43 | + (instancetype)responseWithFile:(NSString*)path; 44 | 45 | /** 46 | * Creates a response like +responseWithFile: and sets the "Content-Disposition" 47 | * HTTP header for a download if the "attachment" argument is YES. 48 | */ 49 | + (instancetype)responseWithFile:(NSString*)path isAttachment:(BOOL)attachment; 50 | 51 | /** 52 | * Creates a response like +responseWithFile: but restricts the file contents 53 | * to a specific byte range. 54 | * 55 | * See -initWithFile:byteRange: for details. 56 | */ 57 | + (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range; 58 | 59 | /** 60 | * Creates a response like +responseWithFile:byteRange: and sets the 61 | * "Content-Disposition" HTTP header for a download if the "attachment" 62 | * argument is YES. 63 | */ 64 | + (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment; 65 | 66 | /** 67 | * Initializes a response with the contents of a file. 68 | */ 69 | - (instancetype)initWithFile:(NSString*)path; 70 | 71 | /** 72 | * Initializes a response like +responseWithFile: and sets the 73 | * "Content-Disposition" HTTP header for a download if the "attachment" 74 | * argument is YES. 75 | */ 76 | - (instancetype)initWithFile:(NSString*)path isAttachment:(BOOL)attachment; 77 | 78 | /** 79 | * Initializes a response like -initWithFile: but restricts the file contents 80 | * to a specific byte range. This range should be set to (NSUIntegerMax, 0) for 81 | * the full file, (offset, length) if expressed from the beginning of the file, 82 | * or (NSUIntegerMax, length) if expressed from the end of the file. The "offset" 83 | * and "length" values will be automatically adjusted to be compatible with the 84 | * actual size of the file. 85 | * 86 | * This argument would typically be set to the value of the byteRange property 87 | * of the current GCDWebServerRequest. 88 | */ 89 | - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range; 90 | 91 | /** 92 | * This method is the designated initializer for the class. 93 | */ 94 | - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment; 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Requests/GCDWebServerFileRequest.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import "GCDWebServerPrivate.h" 33 | 34 | @interface GCDWebServerFileRequest () { 35 | @private 36 | NSString* _temporaryPath; 37 | int _file; 38 | } 39 | @end 40 | 41 | @implementation GCDWebServerFileRequest 42 | 43 | @synthesize temporaryPath=_temporaryPath; 44 | 45 | - (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query { 46 | if ((self = [super initWithMethod:method url:url headers:headers path:path query:query])) { 47 | _temporaryPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]; 48 | } 49 | return self; 50 | } 51 | 52 | - (void)dealloc { 53 | unlink([_temporaryPath fileSystemRepresentation]); 54 | } 55 | 56 | - (BOOL)open:(NSError**)error { 57 | _file = open([_temporaryPath fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 58 | if (_file <= 0) { 59 | if (error) { 60 | *error = GCDWebServerMakePosixError(errno); 61 | } 62 | return NO; 63 | } 64 | return YES; 65 | } 66 | 67 | - (BOOL)writeData:(NSData*)data error:(NSError**)error { 68 | if (write(_file, data.bytes, data.length) != (ssize_t)data.length) { 69 | if (error) { 70 | *error = GCDWebServerMakePosixError(errno); 71 | } 72 | return NO; 73 | } 74 | return YES; 75 | } 76 | 77 | - (BOOL)close:(NSError**)error { 78 | if (close(_file) < 0) { 79 | if (error) { 80 | *error = GCDWebServerMakePosixError(errno); 81 | } 82 | return NO; 83 | } 84 | #ifdef __GCDWEBSERVER_ENABLE_TESTING__ 85 | NSString* creationDateHeader = [self.headers objectForKey:@"X-GCDWebServer-CreationDate"]; 86 | if (creationDateHeader) { 87 | NSDate* date = GCDWebServerParseISO8601(creationDateHeader); 88 | if (!date || ![[NSFileManager defaultManager] setAttributes:@{NSFileCreationDate: date} ofItemAtPath:_temporaryPath error:error]) { 89 | return NO; 90 | } 91 | } 92 | NSString* modifiedDateHeader = [self.headers objectForKey:@"X-GCDWebServer-ModifiedDate"]; 93 | if (modifiedDateHeader) { 94 | NSDate* date = GCDWebServerParseRFC822(modifiedDateHeader); 95 | if (!date || ![[NSFileManager defaultManager] setAttributes:@{NSFileModificationDate: date} ofItemAtPath:_temporaryPath error:error]) { 96 | return NO; 97 | } 98 | } 99 | #endif 100 | return YES; 101 | } 102 | 103 | - (NSString*)description { 104 | NSMutableString* description = [NSMutableString stringWithString:[super description]]; 105 | [description appendFormat:@"\n\n{%@}", _temporaryPath]; 106 | return description; 107 | } 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DDLogClass/DDDBLogger.m: -------------------------------------------------------------------------------- 1 | // 2 | // DDDBLogger.m 3 | // myLogToDB 4 | // 5 | // Created by Gump on 16/4/14. 6 | // Copyright © 2016年 Gump. All rights reserved. 7 | // 8 | 9 | #import "DDDBLogger.h" 10 | #import "DBConnect.h" 11 | #import "logSqlModel.h" 12 | 13 | 14 | @interface DDDBLogger () 15 | 16 | @property (nonatomic, strong) DDLogMessage *saveDBLogMessage; 17 | 18 | 19 | @end 20 | 21 | 22 | @implementation DDDBLogger 23 | 24 | - (void)setsaveDBTotalNum:(NSUInteger)threshold { 25 | // dispatch_block_t block = ^{ 26 | // @autoreleasepool { 27 | // if (_saveDBTotalNum != threshold) { 28 | // _saveDBTotalNum = threshold; 29 | // } 30 | // } 31 | // }; 32 | if (_saveDBTotalNum != threshold) { 33 | _saveDBTotalNum = threshold; 34 | } 35 | } 36 | 37 | 38 | 39 | -(instancetype)init 40 | { 41 | self = [super init]; 42 | if (self) 43 | { 44 | self.deleteOnEverySave = NO; 45 | self.saveInterval = 1; //1 seconds,1秒发送一次 46 | self.saveThreshold = 1; //每一条就发送 47 | self.saveDBTotalNum = 2000; //数据库总共存2000 条 48 | 49 | } 50 | return self; 51 | }; 52 | 53 | 54 | - (BOOL)db_log:(DDLogMessage *)logMessage 55 | { 56 | //没有日志信息 57 | if(!_logFormatter) 58 | { 59 | return NO; 60 | } 61 | 62 | _saveDBLogMessage = logMessage; 63 | return YES; 64 | } 65 | 66 | - (void)db_save { 67 | if ([self isOnGlobalLoggingQueue]) { 68 | NSAssert(NO, @"db_saveAnddelete should only be executed on the internaLoggerQueue thread, if you are seeing this, your doing it wrong"); 69 | } 70 | 71 | [self saveLogEntries:self.saveDBLogMessage]; 72 | } 73 | 74 | 75 | -(void)saveLogEntries:(DDLogMessage *)logMessage 76 | { 77 | logSqlModel *logSql = [[logSqlModel alloc] init]; 78 | 79 | //获取当前的数据库中村的数据的条数 80 | //统计数据库数据条数的sql 81 | NSInteger saveDBNum = [[DBConnect shareConnect] getDBDataCount: logSql.countSqlStr]; 82 | NSString *logTimeStr = [self stringFromDate:logMessage.timestamp]; 83 | NSString *line = [NSString stringWithFormat:@"%lu", (unsigned long)logMessage.line]; 84 | NSString *level = [NSString stringWithFormat:@"%lu", (unsigned long)logMessage.level]; 85 | 86 | // [[DBConnect shareConnect].dbQueue inDatabase:^(FMDatabase *db) { 87 | // if (_saveDBTotalNum < saveDBNum) 88 | // { 89 | // //数据库中存储的数据条数 大于 要求存储的条数 90 | // //删除的数据条数 91 | // NSInteger deleteNum = saveDBNum - _saveDBTotalNum; 92 | // NSString *deleteDataSqlStr = [NSString stringWithFormat:@"DELETE FROM logMessageHistory order by lastUpdateTime limit %ld", (long)deleteNum]; 93 | // [[DBConnect shareConnect] executeUpdateSql:deleteDataSqlStr]; 94 | // }else if (_saveDBTotalNum > saveDBNum) { 95 | // //数据库能保存的数据多余现在的数据,就是直接插入数据库 96 | // [[DBConnect shareConnect].dataBase executeUpdate:logSql.insertSqlStr,logTimeStr, logMessage.fileName, line, logMessage.function, logMessage.message, level, logMessage.timestamp]; 97 | // } 98 | // else{ 99 | // //数据库已经存满,此时需要update时间最早的数据 100 | // [[DBConnect shareConnect].dataBase executeUpdate: logSql.updateDataSqlStr,logTimeStr, logMessage.fileName, line, logMessage.function, logMessage.message, level, logMessage.timestamp]; 101 | // } 102 | // 103 | // }]; 104 | if (_saveDBTotalNum < saveDBNum) 105 | { 106 | //数据库中存储的数据条数 大于 要求存储的条数 107 | //删除的数据条数 108 | NSInteger deleteNum = saveDBNum - _saveDBTotalNum; 109 | NSString *deleteDataSqlStr = [NSString stringWithFormat:@"DELETE FROM logMessageHistory order by lastUpdateTime limit %ld", (long)deleteNum]; 110 | [[DBConnect shareConnect] executeUpdateSql:deleteDataSqlStr]; 111 | }else if (_saveDBTotalNum > saveDBNum) { 112 | //数据库能保存的数据多余现在的数据,就是直接插入数据库 113 | [[DBConnect shareConnect].dataBase executeUpdate:logSql.insertSqlStr,logTimeStr, logMessage.fileName, line, logMessage.function, logMessage.message, level, logMessage.timestamp]; 114 | } 115 | else{ 116 | //数据库已经存满,此时需要update时间最早的数据 117 | [[DBConnect shareConnect].dataBase executeUpdate: logSql.updateDataSqlStr,logTimeStr, logMessage.fileName, line, logMessage.function, logMessage.message, level, logMessage.timestamp]; 118 | } 119 | 120 | } 121 | 122 | - (NSString *)stringFromDate:(NSDate *)date{ 123 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 124 | [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; 125 | NSString *destDateString = [dateFormatter stringFromDate:date]; 126 | return destDateString; 127 | } 128 | 129 | 130 | 131 | @end 132 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DDLogClass/DDAbstractDatabaseLogger.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 | /** 24 | * This class provides an abstract implementation of a database logger. 25 | * 26 | * That is, it provides the base implementation for a database logger to build atop of. 27 | * All that is needed for a concrete database logger is to extend this class 28 | * and override the methods in the implementation file that are prefixed with "db_". 29 | **/ 30 | @interface DDAbstractDatabaseLogger : DDAbstractLogger { 31 | 32 | @protected 33 | NSUInteger _saveThreshold; 34 | NSTimeInterval _saveInterval; 35 | NSTimeInterval _maxAge; 36 | NSTimeInterval _deleteInterval; 37 | BOOL _deleteOnEverySave; 38 | 39 | BOOL _saveTimerSuspended; 40 | NSUInteger _unsavedCount; 41 | dispatch_time_t _unsavedTime; 42 | dispatch_source_t _saveTimer; 43 | dispatch_time_t _lastDeleteTime; 44 | dispatch_source_t _deleteTimer; 45 | } 46 | 47 | /** 48 | * Specifies how often to save the data to disk. 49 | * Since saving is an expensive operation (disk io) it is not done after every log statement. 50 | * These properties allow you to configure how/when the logger saves to disk. 51 | * 52 | * A save is done when either (whichever happens first): 53 | * 54 | * - The number of unsaved log entries reaches saveThreshold 55 | * - The amount of time since the oldest unsaved log entry was created reaches saveInterval 56 | * 57 | * You can optionally disable the saveThreshold by setting it to zero. 58 | * If you disable the saveThreshold you are entirely dependent on the saveInterval. 59 | * 60 | * You can optionally disable the saveInterval by setting it to zero (or a negative value). 61 | * If you disable the saveInterval you are entirely dependent on the saveThreshold. 62 | * 63 | * It's not wise to disable both saveThreshold and saveInterval. 64 | * 65 | * The default saveThreshold is 500. 66 | * The default saveInterval is 60 seconds. 67 | **/ 68 | @property (assign, readwrite) NSUInteger saveThreshold; 69 | 70 | /** 71 | * See the description for the `saveThreshold` property 72 | */ 73 | @property (assign, readwrite) NSTimeInterval saveInterval; 74 | 75 | /** 76 | * It is likely you don't want the log entries to persist forever. 77 | * Doing so would allow the database to grow infinitely large over time. 78 | * 79 | * The maxAge property provides a way to specify how old a log statement can get 80 | * before it should get deleted from the database. 81 | * 82 | * The deleteInterval specifies how often to sweep for old log entries. 83 | * Since deleting is an expensive operation (disk io) is is done on a fixed interval. 84 | * 85 | * An alternative to the deleteInterval is the deleteOnEverySave option. 86 | * This specifies that old log entries should be deleted during every save operation. 87 | * 88 | * You can optionally disable the maxAge by setting it to zero (or a negative value). 89 | * If you disable the maxAge then old log statements are not deleted. 90 | * 91 | * You can optionally disable the deleteInterval by setting it to zero (or a negative value). 92 | * 93 | * If you disable both deleteInterval and deleteOnEverySave then old log statements are not deleted. 94 | * 95 | * It's not wise to enable both deleteInterval and deleteOnEverySave. 96 | * 97 | * The default maxAge is 7 days. 98 | * The default deleteInterval is 5 minutes. 99 | * The default deleteOnEverySave is NO. 100 | **/ 101 | @property (assign, readwrite) NSTimeInterval maxAge; 102 | 103 | /** 104 | * See the description for the `maxAge` property 105 | */ 106 | @property (assign, readwrite) NSTimeInterval deleteInterval; 107 | 108 | /** 109 | * See the description for the `maxAge` property 110 | */ 111 | @property (assign, readwrite) BOOL deleteOnEverySave; 112 | 113 | /** 114 | * Forces a save of any pending log entries (flushes log entries to disk). 115 | **/ 116 | - (void)savePendingLogEntries; 117 | 118 | /** 119 | * Removes any log entries that are older than maxAge. 120 | **/ 121 | - (void)deleteOldLogEntries; 122 | 123 | @end 124 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "GCDWebServerRequest.h" 29 | 30 | /** 31 | * The GCDWebServerMultiPart class is an abstract class that wraps the content 32 | * of a part. 33 | */ 34 | @interface GCDWebServerMultiPart : NSObject 35 | 36 | /** 37 | * Returns the control name retrieved from the part headers. 38 | */ 39 | @property(nonatomic, readonly) NSString* controlName; 40 | 41 | /** 42 | * Returns the content type retrieved from the part headers or "text/plain" 43 | * if not available (per HTTP specifications). 44 | */ 45 | @property(nonatomic, readonly) NSString* contentType; 46 | 47 | /** 48 | * Returns the MIME type component of the content type for the part. 49 | */ 50 | @property(nonatomic, readonly) NSString* mimeType; 51 | 52 | @end 53 | 54 | /** 55 | * The GCDWebServerMultiPartArgument subclass of GCDWebServerMultiPart wraps 56 | * the content of a part as data in memory. 57 | */ 58 | @interface GCDWebServerMultiPartArgument : GCDWebServerMultiPart 59 | 60 | /** 61 | * Returns the data for the part. 62 | */ 63 | @property(nonatomic, readonly) NSData* data; 64 | 65 | /** 66 | * Returns the data for the part interpreted as text. If the content 67 | * type of the part is not a text one, or if an error occurs, nil is returned. 68 | * 69 | * The text encoding used to interpret the data is extracted from the 70 | * "Content-Type" header or defaults to UTF-8. 71 | */ 72 | @property(nonatomic, readonly) NSString* string; 73 | 74 | @end 75 | 76 | /** 77 | * The GCDWebServerMultiPartFile subclass of GCDWebServerMultiPart wraps 78 | * the content of a part as a file on disk. 79 | */ 80 | @interface GCDWebServerMultiPartFile : GCDWebServerMultiPart 81 | 82 | /** 83 | * Returns the file name retrieved from the part headers. 84 | */ 85 | @property(nonatomic, readonly) NSString* fileName; 86 | 87 | /** 88 | * Returns the path to the temporary file containing the part data. 89 | * 90 | * @warning This temporary file will be automatically deleted when the 91 | * GCDWebServerMultiPartFile is deallocated. If you want to preserve this file, 92 | * you must move it to a different location beforehand. 93 | */ 94 | @property(nonatomic, readonly) NSString* temporaryPath; 95 | 96 | @end 97 | 98 | /** 99 | * The GCDWebServerMultiPartFormRequest subclass of GCDWebServerRequest 100 | * parses the body of the HTTP request as a multipart encoded form. 101 | */ 102 | @interface GCDWebServerMultiPartFormRequest : GCDWebServerRequest 103 | 104 | /** 105 | * Returns the argument parts from the multipart encoded form as 106 | * name / GCDWebServerMultiPartArgument pairs. 107 | */ 108 | @property(nonatomic, readonly) NSArray* arguments; 109 | 110 | /** 111 | * Returns the files parts from the multipart encoded form as 112 | * name / GCDWebServerMultiPartFile pairs. 113 | */ 114 | @property(nonatomic, readonly) NSArray* files; 115 | 116 | /** 117 | * Returns the MIME type for multipart encoded forms 118 | * i.e. "multipart/form-data". 119 | */ 120 | + (NSString*)mimeType; 121 | 122 | /** 123 | * Returns the first argument for a given control name or nil if not found. 124 | */ 125 | - (GCDWebServerMultiPartArgument*)firstArgumentForControlName:(NSString*)name; 126 | 127 | /** 128 | * Returns the first file for a given control name or nil if not found. 129 | */ 130 | - (GCDWebServerMultiPartFile*)firstFileForControlName:(NSString*)name; 131 | 132 | @end 133 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Responses/GCDWebServerDataResponse.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import "GCDWebServerPrivate.h" 33 | 34 | @interface GCDWebServerDataResponse () { 35 | @private 36 | NSData* _data; 37 | BOOL _done; 38 | } 39 | @end 40 | 41 | @implementation GCDWebServerDataResponse 42 | 43 | + (instancetype)responseWithData:(NSData*)data contentType:(NSString*)type { 44 | return [[[self class] alloc] initWithData:data contentType:type]; 45 | } 46 | 47 | - (instancetype)initWithData:(NSData*)data contentType:(NSString*)type { 48 | if (data == nil) { 49 | GWS_DNOT_REACHED(); 50 | return nil; 51 | } 52 | 53 | if ((self = [super init])) { 54 | _data = data; 55 | 56 | self.contentType = type; 57 | self.contentLength = data.length; 58 | } 59 | return self; 60 | } 61 | 62 | - (NSData*)readData:(NSError**)error { 63 | NSData* data; 64 | if (_done) { 65 | data = [NSData data]; 66 | } else { 67 | data = _data; 68 | _done = YES; 69 | } 70 | return data; 71 | } 72 | 73 | - (NSString*)description { 74 | NSMutableString* description = [NSMutableString stringWithString:[super description]]; 75 | [description appendString:@"\n\n"]; 76 | [description appendString:GCDWebServerDescribeData(_data, self.contentType)]; 77 | return description; 78 | } 79 | 80 | @end 81 | 82 | @implementation GCDWebServerDataResponse (Extensions) 83 | 84 | + (instancetype)responseWithText:(NSString*)text { 85 | return [[self alloc] initWithText:text]; 86 | } 87 | 88 | + (instancetype)responseWithHTML:(NSString*)html { 89 | return [[self alloc] initWithHTML:html]; 90 | } 91 | 92 | + (instancetype)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables { 93 | return [[self alloc] initWithHTMLTemplate:path variables:variables]; 94 | } 95 | 96 | + (instancetype)responseWithJSONObject:(id)object { 97 | return [[self alloc] initWithJSONObject:object]; 98 | } 99 | 100 | + (instancetype)responseWithJSONObject:(id)object contentType:(NSString*)type { 101 | return [[self alloc] initWithJSONObject:object contentType:type]; 102 | } 103 | 104 | - (instancetype)initWithText:(NSString*)text { 105 | NSData* data = [text dataUsingEncoding:NSUTF8StringEncoding]; 106 | if (data == nil) { 107 | GWS_DNOT_REACHED(); 108 | return nil; 109 | } 110 | return [self initWithData:data contentType:@"text/plain; charset=utf-8"]; 111 | } 112 | 113 | - (instancetype)initWithHTML:(NSString*)html { 114 | NSData* data = [html dataUsingEncoding:NSUTF8StringEncoding]; 115 | if (data == nil) { 116 | GWS_DNOT_REACHED(); 117 | return nil; 118 | } 119 | return [self initWithData:data contentType:@"text/html; charset=utf-8"]; 120 | } 121 | 122 | - (instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables { 123 | NSMutableString* html = [[NSMutableString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL]; 124 | [variables enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSString* value, BOOL* stop) { 125 | [html replaceOccurrencesOfString:[NSString stringWithFormat:@"%%%@%%", key] withString:value options:0 range:NSMakeRange(0, html.length)]; 126 | }]; 127 | id response = [self initWithHTML:html]; 128 | return response; 129 | } 130 | 131 | - (instancetype)initWithJSONObject:(id)object { 132 | return [self initWithJSONObject:object contentType:@"application/json"]; 133 | } 134 | 135 | - (instancetype)initWithJSONObject:(id)object contentType:(NSString*)type { 136 | NSData* data = [NSJSONSerialization dataWithJSONObject:object options:0 error:NULL]; 137 | if (data == nil) { 138 | return nil; 139 | } 140 | return [self initWithData:data contentType:type]; 141 | } 142 | 143 | @end 144 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DBClass/DBConnect.m: -------------------------------------------------------------------------------- 1 | // 2 | // DBConnect.m 3 | // Ershixiong 4 | // 5 | // Created by tw001 on 14-8-29. 6 | // Copyright (c) 2014年 wave. All rights reserved. 7 | // 8 | 9 | #import "DBConnect.h" 10 | #import 11 | #import "FMDB.h" 12 | #define SQLNAME @"gampTech.sqlite" 13 | 14 | @implementation DBConnect 15 | 16 | static DBConnect *dBHandle; 17 | 18 | + (DBConnect *)shareConnect 19 | { 20 | if (dBHandle == nil) { 21 | dBHandle = [[DBConnect alloc] init]; 22 | [dBHandle openDatabase]; 23 | } 24 | return dBHandle; 25 | } 26 | 27 | + (NSString *)bundleSQLPath 28 | { 29 | return [[NSBundle mainBundle] pathForResource:@"mytable" ofType:@"sqlite"]; 30 | } 31 | 32 | /// 打开数据库 33 | - (void)openDatabase { 34 | // NSString *userDataBaseName = [NSString stringWithFormat:@"%@info.sqlite", [UserInfo shareInstance].userID]; 35 | NSString *logDataBaseName = [NSString stringWithFormat:@"%@logInfo.sqlit",@"gampTech"]; 36 | NSString *sqlPath = [[self getDocumentPath] stringByAppendingPathComponent:logDataBaseName]; 37 | NSLog(@"%@", sqlPath); // 拼接字符串 38 | 39 | self.dataBase = [FMDatabase databaseWithPath:sqlPath]; 40 | self.dbQueue = [FMDatabaseQueue databaseQueueWithPath:sqlPath]; 41 | 42 | [_dataBase open]; 43 | if (![_dataBase open]) { 44 | NSLog(@"数据库打开失败"); 45 | }else{ 46 | NSLog(@"数据库打开成功"); 47 | [self CreateNeedTable]; 48 | } 49 | } 50 | 51 | /// 获得document文件的路径 52 | - (NSString *)getDocumentPath 53 | { 54 | NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; // 获取document文件的路径 55 | return documentPath; 56 | } 57 | 58 | /// 判断是否存在表 59 | - (BOOL)isTableOK:(NSString *)tableName 60 | { 61 | NSString *sql = [NSString stringWithFormat:@"SELECT count(*) as 'count' FROM sqlite_master WHERE type ='table' and name = '%@'", tableName]; 62 | int count = [self getDBDataCount:sql]; 63 | if (count > 0) { 64 | return YES; 65 | } 66 | 67 | return NO; 68 | } 69 | 70 | /// 创建表 71 | - (BOOL)createTableSql:(NSString *)sql 72 | { 73 | [self executeInsertSql:sql]; 74 | return YES; 75 | } 76 | 77 | /// 获得数据 78 | - (NSArray *)getDBlist:(NSString *)sql { 79 | __block NSMutableArray *list = [[NSMutableArray alloc] init]; 80 | [self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) { 81 | [db executeStatements:sql withResultBlock:^int(NSDictionary *dictionary) { 82 | [list addObject:dictionary]; 83 | return 0; 84 | }]; 85 | }]; 86 | 87 | return list; 88 | } 89 | 90 | /// 获得单条数据 91 | - (NSDictionary *)getDBOneData:(NSString *)sql 92 | { 93 | __block NSMutableArray *list = [[NSMutableArray alloc] init]; 94 | 95 | [self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) { 96 | [db executeStatements:sql withResultBlock:^int(NSDictionary *dictionary) { 97 | [list addObject:dictionary]; 98 | return 0; 99 | }]; 100 | }]; 101 | 102 | if (list.count == 1) { 103 | return [list objectAtIndex:0]; 104 | } 105 | 106 | return nil; 107 | } 108 | 109 | /// 统计数量 110 | - (int)getDBDataCount:(NSString *)sql 111 | { 112 | int count = 0; 113 | __block NSMutableArray *list = [[NSMutableArray alloc] init]; 114 | 115 | [self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) { 116 | [db executeStatements:sql withResultBlock:^int(NSDictionary *dictionary) { 117 | [list addObject:dictionary]; 118 | return 0; 119 | }]; 120 | }]; 121 | 122 | if (list.count == 1) { 123 | NSDictionary *dict = [list objectAtIndex:0]; 124 | if (dict) { 125 | count = [[dict objectForKey:@"count(*)"] intValue]; 126 | } 127 | } 128 | 129 | return count; 130 | } 131 | 132 | /// 执行sql(主要用来执行插入操作) 133 | - (unsigned)executeInsertSql:(NSString *)sql 134 | { 135 | __block unsigned mid = 0; 136 | [self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) { 137 | [db executeStatements:sql]; 138 | sqlite_int64 lastId = [db lastInsertRowId]; 139 | mid = (unsigned)lastId; 140 | }]; 141 | 142 | return mid; 143 | } 144 | 145 | /// 更新操作,删除操作 146 | - (void)executeUpdateSql:(NSString *)sql 147 | { 148 | [self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) { 149 | [db executeStatements:sql]; 150 | }]; 151 | } 152 | 153 | /// 关闭数据库 154 | - (void)closeDatabase 155 | { 156 | [self.dataBase close]; 157 | } 158 | 159 | /** 160 | * 创建表格 161 | */ 162 | /* Create Need table */ 163 | - (void)CreateNeedTable { 164 | // Create post table for storage post 165 | NSString *sql = [NSString stringWithFormat:@"create table if not exists logMessageHistory(" 166 | "logtime text default '', " //日志打印时间 167 | "filename text default '', " //日志打印的文件名 168 | "line integer , " //日志打印的行数 169 | "function text default '', " //日志打印的函数名 170 | "message text default '', " //日志打印的日志内容 171 | "level integer , " //日志打印的级别 172 | "lastUpdateTime DATETINE )"]; //日志记录更新的最后时间 173 | [dBHandle createTableSql:sql]; 174 | } 175 | 176 | 177 | @end 178 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Core/GCDWebServerHTTPStatusCodes.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 29 | // http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml 30 | 31 | #import 32 | 33 | /** 34 | * Convenience constants for "informational" HTTP status codes. 35 | */ 36 | typedef NS_ENUM(NSInteger, GCDWebServerInformationalHTTPStatusCode) { 37 | kGCDWebServerHTTPStatusCode_Continue = 100, 38 | kGCDWebServerHTTPStatusCode_SwitchingProtocols = 101, 39 | kGCDWebServerHTTPStatusCode_Processing = 102 40 | }; 41 | 42 | /** 43 | * Convenience constants for "successful" HTTP status codes. 44 | */ 45 | typedef NS_ENUM(NSInteger, GCDWebServerSuccessfulHTTPStatusCode) { 46 | kGCDWebServerHTTPStatusCode_OK = 200, 47 | kGCDWebServerHTTPStatusCode_Created = 201, 48 | kGCDWebServerHTTPStatusCode_Accepted = 202, 49 | kGCDWebServerHTTPStatusCode_NonAuthoritativeInformation = 203, 50 | kGCDWebServerHTTPStatusCode_NoContent = 204, 51 | kGCDWebServerHTTPStatusCode_ResetContent = 205, 52 | kGCDWebServerHTTPStatusCode_PartialContent = 206, 53 | kGCDWebServerHTTPStatusCode_MultiStatus = 207, 54 | kGCDWebServerHTTPStatusCode_AlreadyReported = 208 55 | }; 56 | 57 | /** 58 | * Convenience constants for "redirection" HTTP status codes. 59 | */ 60 | typedef NS_ENUM(NSInteger, GCDWebServerRedirectionHTTPStatusCode) { 61 | kGCDWebServerHTTPStatusCode_MultipleChoices = 300, 62 | kGCDWebServerHTTPStatusCode_MovedPermanently = 301, 63 | kGCDWebServerHTTPStatusCode_Found = 302, 64 | kGCDWebServerHTTPStatusCode_SeeOther = 303, 65 | kGCDWebServerHTTPStatusCode_NotModified = 304, 66 | kGCDWebServerHTTPStatusCode_UseProxy = 305, 67 | kGCDWebServerHTTPStatusCode_TemporaryRedirect = 307, 68 | kGCDWebServerHTTPStatusCode_PermanentRedirect = 308 69 | }; 70 | 71 | /** 72 | * Convenience constants for "client error" HTTP status codes. 73 | */ 74 | typedef NS_ENUM(NSInteger, GCDWebServerClientErrorHTTPStatusCode) { 75 | kGCDWebServerHTTPStatusCode_BadRequest = 400, 76 | kGCDWebServerHTTPStatusCode_Unauthorized = 401, 77 | kGCDWebServerHTTPStatusCode_PaymentRequired = 402, 78 | kGCDWebServerHTTPStatusCode_Forbidden = 403, 79 | kGCDWebServerHTTPStatusCode_NotFound = 404, 80 | kGCDWebServerHTTPStatusCode_MethodNotAllowed = 405, 81 | kGCDWebServerHTTPStatusCode_NotAcceptable = 406, 82 | kGCDWebServerHTTPStatusCode_ProxyAuthenticationRequired = 407, 83 | kGCDWebServerHTTPStatusCode_RequestTimeout = 408, 84 | kGCDWebServerHTTPStatusCode_Conflict = 409, 85 | kGCDWebServerHTTPStatusCode_Gone = 410, 86 | kGCDWebServerHTTPStatusCode_LengthRequired = 411, 87 | kGCDWebServerHTTPStatusCode_PreconditionFailed = 412, 88 | kGCDWebServerHTTPStatusCode_RequestEntityTooLarge = 413, 89 | kGCDWebServerHTTPStatusCode_RequestURITooLong = 414, 90 | kGCDWebServerHTTPStatusCode_UnsupportedMediaType = 415, 91 | kGCDWebServerHTTPStatusCode_RequestedRangeNotSatisfiable = 416, 92 | kGCDWebServerHTTPStatusCode_ExpectationFailed = 417, 93 | kGCDWebServerHTTPStatusCode_UnprocessableEntity = 422, 94 | kGCDWebServerHTTPStatusCode_Locked = 423, 95 | kGCDWebServerHTTPStatusCode_FailedDependency = 424, 96 | kGCDWebServerHTTPStatusCode_UpgradeRequired = 426, 97 | kGCDWebServerHTTPStatusCode_PreconditionRequired = 428, 98 | kGCDWebServerHTTPStatusCode_TooManyRequests = 429, 99 | kGCDWebServerHTTPStatusCode_RequestHeaderFieldsTooLarge = 431 100 | }; 101 | 102 | /** 103 | * Convenience constants for "server error" HTTP status codes. 104 | */ 105 | typedef NS_ENUM(NSInteger, GCDWebServerServerErrorHTTPStatusCode) { 106 | kGCDWebServerHTTPStatusCode_InternalServerError = 500, 107 | kGCDWebServerHTTPStatusCode_NotImplemented = 501, 108 | kGCDWebServerHTTPStatusCode_BadGateway = 502, 109 | kGCDWebServerHTTPStatusCode_ServiceUnavailable = 503, 110 | kGCDWebServerHTTPStatusCode_GatewayTimeout = 504, 111 | kGCDWebServerHTTPStatusCode_HTTPVersionNotSupported = 505, 112 | kGCDWebServerHTTPStatusCode_InsufficientStorage = 507, 113 | kGCDWebServerHTTPStatusCode_LoopDetected = 508, 114 | kGCDWebServerHTTPStatusCode_NotExtended = 510, 115 | kGCDWebServerHTTPStatusCode_NetworkAuthenticationRequired = 511 116 | }; 117 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DDLogClass/DDLogMacros.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 | /** 24 | * The constant/variable/method responsible for controlling the current log level. 25 | **/ 26 | #ifndef LOG_LEVEL_DEF 27 | #define LOG_LEVEL_DEF ddLogLevel 28 | #endif 29 | 30 | /** 31 | * Whether async should be used by log messages, excluding error messages that are always sent sync. 32 | **/ 33 | #ifndef LOG_ASYNC_ENABLED 34 | #define LOG_ASYNC_ENABLED YES 35 | #endif 36 | 37 | /** 38 | * These are the two macros that all other macros below compile into. 39 | * These big multiline macros makes all the other macros easier to read. 40 | **/ 41 | #define LOG_MACRO(isAsynchronous, lvl, flg, ctx, atag, fnct, frmt, ...) \ 42 | [DDLog log : isAsynchronous \ 43 | level : lvl \ 44 | flag : flg \ 45 | context : ctx \ 46 | file : __FILE__ \ 47 | function : fnct \ 48 | line : __LINE__ \ 49 | tag : atag \ 50 | format : (frmt), ## __VA_ARGS__] 51 | 52 | #define LOG_MACRO_TO_DDLOG(ddlog, isAsynchronous, lvl, flg, ctx, atag, fnct, frmt, ...) \ 53 | [ddlog log : isAsynchronous \ 54 | level : lvl \ 55 | flag : flg \ 56 | context : ctx \ 57 | file : __FILE__ \ 58 | function : fnct \ 59 | line : __LINE__ \ 60 | tag : atag \ 61 | format : (frmt), ## __VA_ARGS__] 62 | 63 | /** 64 | * Define version of the macro that only execute if the log level is above the threshold. 65 | * The compiled versions essentially look like this: 66 | * 67 | * if (logFlagForThisLogMsg & ddLogLevel) { execute log message } 68 | * 69 | * When LOG_LEVEL_DEF is defined as ddLogLevel. 70 | * 71 | * As shown further below, Lumberjack actually uses a bitmask as opposed to primitive log levels. 72 | * This allows for a great amount of flexibility and some pretty advanced fine grained logging techniques. 73 | * 74 | * Note that when compiler optimizations are enabled (as they are for your release builds), 75 | * the log messages above your logging threshold will automatically be compiled out. 76 | * 77 | * (If the compiler sees LOG_LEVEL_DEF/ddLogLevel declared as a constant, the compiler simply checks to see 78 | * if the 'if' statement would execute, and if not it strips it from the binary.) 79 | * 80 | * We also define shorthand versions for asynchronous and synchronous logging. 81 | **/ 82 | #define LOG_MAYBE(async, lvl, flg, ctx, tag, fnct, frmt, ...) \ 83 | do { if(lvl & flg) LOG_MACRO(async, lvl, flg, ctx, tag, fnct, frmt, ##__VA_ARGS__); } while(0) 84 | 85 | #define LOG_MAYBE_TO_DDLOG(ddlog, async, lvl, flg, ctx, tag, fnct, frmt, ...) \ 86 | do { if(lvl & flg) LOG_MACRO_TO_DDLOG(ddlog, async, lvl, flg, ctx, tag, fnct, frmt, ##__VA_ARGS__); } while(0) 87 | 88 | /** 89 | * Ready to use log macros with no context or tag. 90 | **/ 91 | #define DDLogError(frmt, ...) LOG_MAYBE(NO, LOG_LEVEL_DEF, DDLogFlagError, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 92 | #define DDLogWarn(frmt, ...) LOG_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagWarning, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 93 | #define DDLogInfo(frmt, ...) LOG_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagInfo, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 94 | #define DDLogDebug(frmt, ...) LOG_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagDebug, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 95 | #define DDLogVerbose(frmt, ...) LOG_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagVerbose, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 96 | 97 | #define DDLogErrorToDDLog(ddlog, frmt, ...) LOG_MAYBE_TO_DDLOG(ddlog, NO, LOG_LEVEL_DEF, DDLogFlagError, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 98 | #define DDLogWarnToDDLog(ddlog, frmt, ...) LOG_MAYBE_TO_DDLOG(ddlog, LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagWarning, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 99 | #define DDLogInfoToDDLog(ddlog, frmt, ...) LOG_MAYBE_TO_DDLOG(ddlog, LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagInfo, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 100 | #define DDLogDebugToDDLog(ddlog, frmt, ...) LOG_MAYBE_TO_DDLOG(ddlog, LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagDebug, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 101 | #define DDLogVerboseToDDLog(ddlog, frmt, ...) LOG_MAYBE_TO_DDLOG(ddlog, LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagVerbose, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 102 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/DBClass/FMDatabasePool.h: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabasePool.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 | /** Pool of `` objects. 14 | 15 | ### See also 16 | 17 | - `` 18 | - `` 19 | 20 | @warning Before using `FMDatabasePool`, please consider using `` instead. 21 | 22 | If you really really really know what you're doing and `FMDatabasePool` is what 23 | you really really need (ie, you're using a read only database), OK you can use 24 | it. But just be careful not to deadlock! 25 | 26 | For an example on deadlocking, search for: 27 | `ONLY_USE_THE_POOL_IF_YOU_ARE_DOING_READS_OTHERWISE_YOULL_DEADLOCK_USE_FMDATABASEQUEUE_INSTEAD` 28 | in the main.m file. 29 | */ 30 | 31 | @interface FMDatabasePool : NSObject { 32 | NSString *_path; 33 | 34 | dispatch_queue_t _lockQueue; 35 | 36 | NSMutableArray *_databaseInPool; 37 | NSMutableArray *_databaseOutPool; 38 | 39 | __unsafe_unretained id _delegate; 40 | 41 | NSUInteger _maximumNumberOfDatabasesToCreate; 42 | int _openFlags; 43 | NSString *_vfsName; 44 | } 45 | 46 | /** Database path */ 47 | 48 | @property (atomic, retain) NSString *path; 49 | 50 | /** Delegate object */ 51 | 52 | @property (atomic, assign) id delegate; 53 | 54 | /** Maximum number of databases to create */ 55 | 56 | @property (atomic, assign) NSUInteger maximumNumberOfDatabasesToCreate; 57 | 58 | /** Open flags */ 59 | 60 | @property (atomic, readonly) int openFlags; 61 | 62 | /** Custom virtual file system name */ 63 | 64 | @property (atomic, copy) NSString *vfsName; 65 | 66 | 67 | ///--------------------- 68 | /// @name Initialization 69 | ///--------------------- 70 | 71 | /** Create pool using path. 72 | 73 | @param aPath The file path of the database. 74 | 75 | @return The `FMDatabasePool` object. `nil` on error. 76 | */ 77 | 78 | + (instancetype)databasePoolWithPath:(NSString*)aPath; 79 | 80 | /** Create pool using path and specified flags 81 | 82 | @param aPath The file path of the database. 83 | @param openFlags Flags passed to the openWithFlags method of the database 84 | 85 | @return The `FMDatabasePool` object. `nil` on error. 86 | */ 87 | 88 | + (instancetype)databasePoolWithPath:(NSString*)aPath flags:(int)openFlags; 89 | 90 | /** Create pool using path. 91 | 92 | @param aPath The file path of the database. 93 | 94 | @return The `FMDatabasePool` object. `nil` on error. 95 | */ 96 | 97 | - (instancetype)initWithPath:(NSString*)aPath; 98 | 99 | /** Create pool using path and specified flags. 100 | 101 | @param aPath The file path of the database. 102 | @param openFlags Flags passed to the openWithFlags method of the database 103 | 104 | @return The `FMDatabasePool` object. `nil` on error. 105 | */ 106 | 107 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags; 108 | 109 | /** Create pool using path and specified flags. 110 | 111 | @param aPath The file path of the database. 112 | @param openFlags Flags passed to the openWithFlags method of the database 113 | @param vfsName The name of a custom virtual file system 114 | 115 | @return The `FMDatabasePool` object. `nil` on error. 116 | */ 117 | 118 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags vfs:(NSString *)vfsName; 119 | 120 | /** Returns the Class of 'FMDatabase' subclass, that will be used to instantiate database object. 121 | 122 | Subclasses can override this method to return specified Class of 'FMDatabase' subclass. 123 | 124 | @return The Class of 'FMDatabase' subclass, that will be used to instantiate database object. 125 | */ 126 | 127 | + (Class)databaseClass; 128 | 129 | ///------------------------------------------------ 130 | /// @name Keeping track of checked in/out databases 131 | ///------------------------------------------------ 132 | 133 | /** Number of checked-in databases in pool 134 | 135 | @returns Number of databases 136 | */ 137 | 138 | - (NSUInteger)countOfCheckedInDatabases; 139 | 140 | /** Number of checked-out databases in pool 141 | 142 | @returns Number of databases 143 | */ 144 | 145 | - (NSUInteger)countOfCheckedOutDatabases; 146 | 147 | /** Total number of databases in pool 148 | 149 | @returns Number of databases 150 | */ 151 | 152 | - (NSUInteger)countOfOpenDatabases; 153 | 154 | /** Release all databases in pool */ 155 | 156 | - (void)releaseAllDatabases; 157 | 158 | ///------------------------------------------ 159 | /// @name Perform database operations in pool 160 | ///------------------------------------------ 161 | 162 | /** Synchronously perform database operations in pool. 163 | 164 | @param block The code to be run on the `FMDatabasePool` pool. 165 | */ 166 | 167 | - (void)inDatabase:(void (^)(FMDatabase *db))block; 168 | 169 | /** Synchronously perform database operations in pool using transaction. 170 | 171 | @param block The code to be run on the `FMDatabasePool` pool. 172 | */ 173 | 174 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 175 | 176 | /** Synchronously perform database operations in pool using deferred transaction. 177 | 178 | @param block The code to be run on the `FMDatabasePool` pool. 179 | */ 180 | 181 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 182 | 183 | /** Synchronously perform database operations in pool using save point. 184 | 185 | @param block The code to be run on the `FMDatabasePool` pool. 186 | 187 | @return `NSError` object if error; `nil` if successful. 188 | 189 | @warning You can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock. If you need to nest, use `<[FMDatabase startSavePointWithName:error:]>` instead. 190 | */ 191 | 192 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block; 193 | 194 | @end 195 | 196 | 197 | /** FMDatabasePool delegate category 198 | 199 | This is a category that defines the protocol for the FMDatabasePool delegate 200 | */ 201 | 202 | @interface NSObject (FMDatabasePoolDelegate) 203 | 204 | /** Asks the delegate whether database should be added to the pool. 205 | 206 | @param pool The `FMDatabasePool` object. 207 | @param database The `FMDatabase` object. 208 | 209 | @return `YES` if it should add database to pool; `NO` if not. 210 | 211 | */ 212 | 213 | - (BOOL)databasePool:(FMDatabasePool*)pool shouldAddDatabaseToPool:(FMDatabase*)database; 214 | 215 | /** Tells the delegate that database was added to the pool. 216 | 217 | @param pool The `FMDatabasePool` object. 218 | @param database The `FMDatabase` object. 219 | 220 | */ 221 | 222 | - (void)databasePool:(FMDatabasePool*)pool didAddDatabase:(FMDatabase*)database; 223 | 224 | @end 225 | 226 | -------------------------------------------------------------------------------- /CocoaLogToWebServer/Classes/GCDWebServer/Responses/GCDWebServerErrorResponse.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012-2015, Pierre-Olivier Latour 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of Pierre-Olivier Latour may not be used to endorse 13 | or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #if !__has_feature(objc_arc) 29 | #error GCDWebServer requires ARC 30 | #endif 31 | 32 | #import "GCDWebServerPrivate.h" 33 | 34 | @interface GCDWebServerErrorResponse () 35 | - (instancetype)initWithStatusCode:(NSInteger)statusCode underlyingError:(NSError*)underlyingError messageFormat:(NSString*)format arguments:(va_list)arguments; 36 | @end 37 | 38 | @implementation GCDWebServerErrorResponse 39 | 40 | + (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... { 41 | GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500)); 42 | va_list arguments; 43 | va_start(arguments, format); 44 | GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments]; 45 | va_end(arguments); 46 | return response; 47 | } 48 | 49 | + (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... { 50 | GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600)); 51 | va_list arguments; 52 | va_start(arguments, format); 53 | GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments]; 54 | va_end(arguments); 55 | return response; 56 | } 57 | 58 | + (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... { 59 | GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500)); 60 | va_list arguments; 61 | va_start(arguments, format); 62 | GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments]; 63 | va_end(arguments); 64 | return response; 65 | } 66 | 67 | + (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... { 68 | GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600)); 69 | va_list arguments; 70 | va_start(arguments, format); 71 | GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments]; 72 | va_end(arguments); 73 | return response; 74 | } 75 | 76 | static inline NSString* _EscapeHTMLString(NSString* string) { 77 | return [string stringByReplacingOccurrencesOfString:@"\"" withString:@"""]; 78 | } 79 | 80 | - (instancetype)initWithStatusCode:(NSInteger)statusCode underlyingError:(NSError*)underlyingError messageFormat:(NSString*)format arguments:(va_list)arguments { 81 | NSString* message = [[NSString alloc] initWithFormat:format arguments:arguments]; 82 | NSString* title = [NSString stringWithFormat:@"HTTP Error %i", (int)statusCode]; 83 | NSString* error = underlyingError ? [NSString stringWithFormat:@"[%@] %@ (%li)", underlyingError.domain, _EscapeHTMLString(underlyingError.localizedDescription), (long)underlyingError.code] : @""; 84 | NSString* html = [NSString stringWithFormat:@"%@

%@: %@

%@

", 85 | title, title, _EscapeHTMLString(message), error]; 86 | if ((self = [self initWithHTML:html])) { 87 | self.statusCode = statusCode; 88 | } 89 | return self; 90 | } 91 | 92 | - (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... { 93 | GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500)); 94 | va_list arguments; 95 | va_start(arguments, format); 96 | self = [self initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments]; 97 | va_end(arguments); 98 | return self; 99 | } 100 | 101 | - (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... { 102 | GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600)); 103 | va_list arguments; 104 | va_start(arguments, format); 105 | self = [self initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments]; 106 | va_end(arguments); 107 | return self; 108 | } 109 | 110 | - (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... { 111 | GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500)); 112 | va_list arguments; 113 | va_start(arguments, format); 114 | self = [self initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments]; 115 | va_end(arguments); 116 | return self; 117 | } 118 | 119 | - (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... { 120 | GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600)); 121 | va_list arguments; 122 | va_start(arguments, format); 123 | self = [self initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments]; 124 | va_end(arguments); 125 | return self; 126 | } 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------