├── .gitignore ├── .hgignore ├── Samples ├── WebDAVServer │ ├── WebDAVServer_Prefix.pch │ ├── README.markdown │ ├── main.m │ ├── English.lproj │ │ └── MainMenu.nib │ │ │ └── keyedobjects.nib │ ├── AppDelegate.h │ ├── WebDAVServer.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── WebDAVServer.xcscheme │ ├── Info.plist │ └── AppDelegate.m ├── DynamicServer │ ├── English.lproj │ │ └── InfoPlist.strings │ ├── MyHTTPConnection.h │ ├── DynamicServer_Prefix.pch │ ├── DynamicServer.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── DynamicServer.xcscheme │ ├── main.m │ ├── DynamicServerAppDelegate.h │ ├── HTTPResponseTest.h │ ├── README.markdown │ ├── Web │ │ └── index.html │ ├── DynamicServer-Info.plist │ ├── DynamicServerAppDelegate.m │ ├── MyHTTPConnection.m │ └── HTTPResponseTest.m ├── SimpleWebSocketServer │ ├── English.lproj │ │ └── InfoPlist.strings │ ├── MyWebSocket.h │ ├── MyHTTPConnection.h │ ├── SimpleWebSocketServer_Prefix.pch │ ├── SimpleWebSocketServer.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── SimpleWebSocketServer.xcscheme │ ├── main.m │ ├── SimpleWebSocketServerAppDelegate.h │ ├── Web │ │ ├── index.html │ │ ├── WebSocketTest.js │ │ └── WebSocketTest2.js │ ├── MyWebSocket.m │ ├── README.markdown │ ├── SimpleWebSocketServer-Info.plist │ ├── SimpleWebSocketServerAppDelegate.m │ └── MyHTTPConnection.m ├── SecureHTTPServer │ ├── DDKeychain.m │ ├── English.lproj │ │ └── InfoPlist.strings │ ├── SecureHTTPServer.xcodeproj │ │ ├── TemplateIcon.icns │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── SecureHTTPServer.xcscheme │ ├── MyHTTPConnection.h │ ├── AppDelegate.h │ ├── SecureHTTPServer_Prefix.pch │ ├── main.m │ ├── DDKeychain.h │ ├── Info.plist │ ├── MyHTTPConnection.m │ ├── README.markdown │ └── AppDelegate.m ├── SecureWebSocketServer │ ├── SecureWebSocketServer │ │ ├── en.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── Credits.rtf │ │ ├── DDKeychain.m │ │ ├── MyWebSocket.h │ │ ├── MyHTTPConnection.h │ │ ├── SecureWebSocketServer-Prefix.pch │ │ ├── main.m │ │ ├── SecureWebSocketServerAppDelegate.h │ │ ├── Web │ │ │ ├── WebSocketTest.js │ │ │ ├── index.html │ │ │ └── WebSocketTest2.js │ │ ├── DDKeychain.h │ │ ├── MyWebSocket.m │ │ ├── SecureWebSocketServer-Info.plist │ │ ├── SecureWebSocketServerAppDelegate.m │ │ └── MyHTTPConnection.m │ ├── SecureWebSocketServer.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── SecureWebSocketServer.xcscheme │ └── README.markdown ├── SimpleFileUploadServer │ ├── SimpleFileUploadServer │ │ ├── en.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── Credits.rtf │ │ ├── AppDelegate.h │ │ ├── SimpleFileUploadServer-Prefix.pch │ │ ├── web │ │ │ ├── upload.html │ │ │ └── index.html │ │ ├── MyHTTPConnection.h │ │ ├── main.m │ │ ├── SimpleFileUploadServer-Info.plist │ │ └── AppDelegate.m │ ├── SimpleFileUploadServer.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── SimpleFileUploadServer.xcscheme │ └── README.markdown ├── Xcode-Configurations │ ├── Debug.xcconfig │ ├── Release.xcconfig │ ├── ReadMe.txt │ └── Base.xcconfig ├── iPhoneHTTPServer │ ├── Default-568h@2x.png │ ├── Classes │ │ ├── iPhoneHTTPServerViewController.m │ │ ├── iPhoneHTTPServerViewController.h │ │ ├── iPhoneHTTPServerAppDelegate.h │ │ └── iPhoneHTTPServerAppDelegate.m │ ├── iPhoneHTTPServer.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── iPhoneHTTPServer.xcscheme │ ├── iPhoneHTTPServer_Prefix.pch │ ├── Web │ │ └── index.html │ ├── main.m │ ├── iPhoneHTTPServer-Info.plist │ └── README.markdown ├── PostHTTPServer │ ├── English.lproj │ │ └── InfoPlist.strings │ ├── MyHTTPConnection.h │ ├── PostHTTPServer.xcodeproj │ │ ├── TemplateIcon.icns │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── PostHTTPServer.xcscheme │ ├── AppDelegate.h │ ├── PostHTTPServer_Prefix.pch │ ├── Web │ │ └── index.html │ ├── main.m │ ├── README.markdown │ ├── Info.plist │ ├── AppDelegate.m │ └── MyHTTPConnection.m ├── PasswdHTTPServer │ ├── English.lproj │ │ └── InfoPlist.strings │ ├── PasswdHTTPServer.xcodeproj │ │ ├── TemplateIcon.icns │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── PasswdHTTPServer.xcscheme │ ├── MyHTTPConnection.h │ ├── AppDelegate.h │ ├── PasswdHTTPServer_Prefix.pch │ ├── main.m │ ├── Info.plist │ ├── README.markdown │ ├── MyHTTPConnection.m │ └── AppDelegate.m ├── SimpleHTTPServer │ ├── English.lproj │ │ ├── InfoPlist.strings │ │ └── MainMenu.nib │ │ │ └── keyedobjects.nib │ ├── AppDelegate.h │ ├── SimpleHTTPServer_Prefix.pch │ ├── SimpleHTTPServer.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── SimpleHTTPServer.xcscheme │ ├── main.m │ ├── README.markdown │ ├── Info.plist │ └── AppDelegate.m └── README.markdown ├── Extensions └── WebDAV │ ├── DAVConnection.h │ ├── DELETEResponse.h │ ├── PUTResponse.h │ ├── DAVResponse.h │ ├── DELETEResponse.m │ └── PUTResponse.m ├── Core ├── Responses │ ├── HTTPErrorResponse.h │ ├── HTTPDataResponse.h │ ├── HTTPRedirectResponse.h │ ├── HTTPFileResponse.h │ ├── HTTPErrorResponse.m │ ├── HTTPRedirectResponse.m │ ├── HTTPDynamicFileResponse.h │ ├── HTTPDataResponse.m │ └── HTTPAsyncFileResponse.h ├── Categories │ ├── DDData.h │ ├── DDNumber.h │ ├── DDNumber.m │ ├── DDRange.h │ ├── DDRange.m │ └── DDData.m ├── Mime │ ├── MultipartMessageHeaderField.h │ ├── MultipartMessageHeader.h │ ├── MultipartFormDataParser.h │ └── MultipartMessageHeader.m ├── HTTPAuthenticationRequest.h ├── HTTPMessage.h ├── WebSocket.h ├── HTTPMessage.m └── HTTPConnection.h ├── Vendor ├── CocoaAsyncSocket │ └── About.txt └── CocoaLumberjack │ ├── Extensions │ ├── README.txt │ ├── ContextFilterLogFormatter.h │ ├── ContextFilterLogFormatter.m │ └── DispatchQueueLogFormatter.h │ ├── DDASLLogger.h │ ├── About.txt │ ├── DDASLLogger.m │ └── DDAbstractDatabaseLogger.h ├── CocoaHTTPServer.podspec.json ├── .travis.yml ├── LICENSE.txt └── README.markdown /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.pbxuser 3 | *.mode1v3 4 | *.mode2v3 5 | xcuserdata 6 | *~ 7 | -------------------------------------------------------------------------------- /.hgignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | 3 | Samples/*/build 4 | *.pbxuser 5 | *.mode1v3 6 | *.xcuserdatad 7 | -------------------------------------------------------------------------------- /Samples/WebDAVServer/WebDAVServer_Prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | -------------------------------------------------------------------------------- /Samples/DynamicServer/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Samples/SecureHTTPServer/DDKeychain.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Todo/CocoaHTTPServer/master/Samples/SecureHTTPServer/DDKeychain.m -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Samples/SimpleFileUploadServer/SimpleFileUploadServer/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Samples/WebDAVServer/README.markdown: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Todo/CocoaHTTPServer/master/Samples/WebDAVServer/README.markdown -------------------------------------------------------------------------------- /Samples/Xcode-Configurations/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Base" 2 | 3 | // Common 4 | ONLY_ACTIVE_ARCH = YES 5 | GCC_OPTIMIZATION_LEVEL = 0 6 | -------------------------------------------------------------------------------- /Samples/iPhoneHTTPServer/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Todo/CocoaHTTPServer/master/Samples/iPhoneHTTPServer/Default-568h@2x.png -------------------------------------------------------------------------------- /Samples/WebDAVServer/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | int main(int argc, char* argv[]) { 4 | return NSApplicationMain(argc, (const char**)argv); 5 | } 6 | -------------------------------------------------------------------------------- /Samples/PostHTTPServer/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Todo/CocoaHTTPServer/master/Samples/PostHTTPServer/English.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /Samples/PostHTTPServer/MyHTTPConnection.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPConnection.h" 3 | 4 | 5 | @interface MyHTTPConnection : HTTPConnection 6 | 7 | @end -------------------------------------------------------------------------------- /Samples/PasswdHTTPServer/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Todo/CocoaHTTPServer/master/Samples/PasswdHTTPServer/English.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /Samples/SecureHTTPServer/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Todo/CocoaHTTPServer/master/Samples/SecureHTTPServer/English.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /Samples/SimpleHTTPServer/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Todo/CocoaHTTPServer/master/Samples/SimpleHTTPServer/English.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /Samples/DynamicServer/MyHTTPConnection.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPConnection.h" 3 | 4 | 5 | @interface MyHTTPConnection : HTTPConnection 6 | 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /Samples/PostHTTPServer/PostHTTPServer.xcodeproj/TemplateIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Todo/CocoaHTTPServer/master/Samples/PostHTTPServer/PostHTTPServer.xcodeproj/TemplateIcon.icns -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/DDKeychain.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Todo/CocoaHTTPServer/master/Samples/SecureWebSocketServer/SecureWebSocketServer/DDKeychain.m -------------------------------------------------------------------------------- /Samples/SimpleHTTPServer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | @class HTTPServer; 3 | 4 | @interface AppDelegate : NSObject 5 | { 6 | HTTPServer *httpServer; 7 | } 8 | @end 9 | -------------------------------------------------------------------------------- /Samples/WebDAVServer/English.lproj/MainMenu.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Todo/CocoaHTTPServer/master/Samples/WebDAVServer/English.lproj/MainMenu.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Samples/iPhoneHTTPServer/Classes/iPhoneHTTPServerViewController.m: -------------------------------------------------------------------------------- 1 | #import "iPhoneHTTPServerViewController.h" 2 | 3 | 4 | @implementation iPhoneHTTPServerViewController 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /Samples/PasswdHTTPServer/PasswdHTTPServer.xcodeproj/TemplateIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Todo/CocoaHTTPServer/master/Samples/PasswdHTTPServer/PasswdHTTPServer.xcodeproj/TemplateIcon.icns -------------------------------------------------------------------------------- /Samples/SecureHTTPServer/SecureHTTPServer.xcodeproj/TemplateIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Todo/CocoaHTTPServer/master/Samples/SecureHTTPServer/SecureHTTPServer.xcodeproj/TemplateIcon.icns -------------------------------------------------------------------------------- /Samples/SimpleHTTPServer/English.lproj/MainMenu.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Todo/CocoaHTTPServer/master/Samples/SimpleHTTPServer/English.lproj/MainMenu.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Samples/PasswdHTTPServer/MyHTTPConnection.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPConnection.h" 3 | 4 | 5 | @interface MyHTTPConnection : HTTPConnection 6 | { 7 | 8 | } 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /Samples/SecureHTTPServer/MyHTTPConnection.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPConnection.h" 3 | 4 | 5 | @interface MyHTTPConnection : HTTPConnection 6 | { 7 | 8 | } 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/MyWebSocket.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "WebSocket.h" 3 | 4 | 5 | @interface MyWebSocket : WebSocket 6 | { 7 | 8 | } 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /Extensions/WebDAV/DAVConnection.h: -------------------------------------------------------------------------------- 1 | #import "HTTPConnection.h" 2 | 3 | @interface DAVConnection : HTTPConnection { 4 | id requestContentBody; 5 | NSOutputStream* requestContentStream; 6 | } 7 | @end 8 | -------------------------------------------------------------------------------- /Samples/PostHTTPServer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class HTTPServer; 4 | 5 | 6 | @interface AppDelegate : NSObject 7 | { 8 | HTTPServer *httpServer; 9 | } 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Samples/WebDAVServer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class HTTPServer; 4 | 5 | @interface AppDelegate : NSObject { 6 | @private 7 | HTTPServer* _httpServer; 8 | } 9 | @end 10 | -------------------------------------------------------------------------------- /Extensions/WebDAV/DELETEResponse.h: -------------------------------------------------------------------------------- 1 | #import "HTTPResponse.h" 2 | 3 | @interface DELETEResponse : NSObject { 4 | NSInteger _status; 5 | } 6 | - (id) initWithFilePath:(NSString*)path; 7 | @end 8 | -------------------------------------------------------------------------------- /Samples/PasswdHTTPServer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class HTTPServer; 4 | 5 | 6 | @interface AppDelegate : NSObject 7 | { 8 | HTTPServer *httpServer; 9 | } 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Samples/SecureHTTPServer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class HTTPServer; 4 | 5 | 6 | @interface AppDelegate : NSObject 7 | { 8 | HTTPServer *httpServer; 9 | } 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Samples/Xcode-Configurations/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Base" 2 | 3 | // Common 4 | GCC_TREAT_WARNINGS_AS_ERRORS = YES 5 | GCC_PREPROCESSOR_DEFINITIONS = NDEBUG NS_BLOCK_ASSERTIONS 6 | VALIDATE_PRODUCT = YES 7 | -------------------------------------------------------------------------------- /Samples/iPhoneHTTPServer/Classes/iPhoneHTTPServerViewController.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface iPhoneHTTPServerViewController : UIViewController { 5 | 6 | } 7 | 8 | @end 9 | 10 | -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/MyWebSocket.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "WebSocket.h" 3 | 4 | 5 | @interface MyWebSocket : WebSocket 6 | { 7 | 8 | } 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /Samples/DynamicServer/DynamicServer_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'DynamicServer' target in the 'DynamicServer' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Samples/PostHTTPServer/PostHTTPServer_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'PostHTTPServer' target in the 'PostHTTPServer' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Core/Responses/HTTPErrorResponse.h: -------------------------------------------------------------------------------- 1 | #import "HTTPResponse.h" 2 | 3 | @interface HTTPErrorResponse : NSObject { 4 | NSInteger _status; 5 | } 6 | 7 | - (id)initWithErrorCode:(int)httpErrorCode; 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /Samples/PasswdHTTPServer/PasswdHTTPServer_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'PasswdHTTPServer' target in the 'PasswdHTTPServer' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Samples/SecureHTTPServer/SecureHTTPServer_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'SecureHTTPServer' target in the 'SecureHTTPServer' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Samples/SimpleHTTPServer/SimpleHTTPServer_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'SimpleHTTPServer' target in the 'SimpleHTTPServer' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Vendor/CocoaAsyncSocket/About.txt: -------------------------------------------------------------------------------- 1 | The CocoaAsyncSocket project is under Public Domain license. 2 | http://code.google.com/p/cocoaasyncsocket/ 3 | 4 | The AsyncSocket project has been around since 2001 and is used in many applications and frameworks. -------------------------------------------------------------------------------- /Samples/PostHTTPServer/Web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | What is 5 + 5 ? :
5 | 6 |
7 | 8 | -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/MyHTTPConnection.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPConnection.h" 3 | 4 | @class MyWebSocket; 5 | 6 | @interface MyHTTPConnection : HTTPConnection 7 | { 8 | MyWebSocket *ws; 9 | } 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/SimpleWebSocketServer_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'SimpleWebSocketServer' target in the 'SimpleWebSocketServer' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Samples/SimpleFileUploadServer/SimpleFileUploadServer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | @class HTTPServer; 5 | 6 | @interface AppDelegate : NSObject { 7 | HTTPServer *httpServer; 8 | } 9 | 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Samples/WebDAVServer/WebDAVServer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Samples/DynamicServer/DynamicServer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Samples/PostHTTPServer/PostHTTPServer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/MyHTTPConnection.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPConnection.h" 3 | 4 | @class MyWebSocket; 5 | 6 | @interface MyHTTPConnection : HTTPConnection 7 | { 8 | MyWebSocket *ws; 9 | } 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/SecureWebSocketServer-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'SecureWebSocketServer' target in the 'SecureWebSocketServer' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Samples/PasswdHTTPServer/PasswdHTTPServer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Samples/SecureHTTPServer/SecureHTTPServer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Samples/SimpleHTTPServer/SimpleHTTPServer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Samples/iPhoneHTTPServer/iPhoneHTTPServer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Samples/iPhoneHTTPServer/iPhoneHTTPServer_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'iPhoneHTTPServer' target in the 'iPhoneHTTPServer' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import 8 | #endif 9 | -------------------------------------------------------------------------------- /Samples/SimpleFileUploadServer/SimpleFileUploadServer/SimpleFileUploadServer-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'SimpleFileUploadServer' target in the 'SimpleFileUploadServer' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Core/Responses/HTTPDataResponse.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPResponse.h" 3 | 4 | 5 | @interface HTTPDataResponse : NSObject 6 | { 7 | NSUInteger offset; 8 | NSData *data; 9 | } 10 | 11 | - (id)initWithData:(NSData *)data; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Core/Responses/HTTPRedirectResponse.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPResponse.h" 3 | 4 | 5 | @interface HTTPRedirectResponse : NSObject 6 | { 7 | NSString *redirectPath; 8 | } 9 | 10 | - (id)initWithPath:(NSString *)redirectPath; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Core/Categories/DDData.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface NSData (DDData) 4 | 5 | - (NSData *)md5Digest; 6 | 7 | - (NSData *)sha1Digest; 8 | 9 | - (NSString *)hexStringValue; 10 | 11 | - (NSString *)base64Encoded; 12 | - (NSData *)base64Decoded; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Samples/SimpleFileUploadServer/SimpleFileUploadServer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/SimpleWebSocketServer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Samples/SimpleFileUploadServer/SimpleFileUploadServer/web/upload.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %MyFiles% 8 | 9 | -------------------------------------------------------------------------------- /Samples/DynamicServer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // DynamicServer 4 | // 5 | // Created by Robbie Hanson on 11/20/10. 6 | // Copyright 2010 Voalte. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **) argv); 14 | } 15 | -------------------------------------------------------------------------------- /Extensions/WebDAV/PUTResponse.h: -------------------------------------------------------------------------------- 1 | #import "HTTPResponse.h" 2 | 3 | @interface PUTResponse : NSObject { 4 | NSInteger _status; 5 | } 6 | - (id) initWithFilePath:(NSString*)path headers:(NSDictionary*)headers bodyData:(NSData*)body; 7 | - (id) initWithFilePath:(NSString*)path headers:(NSDictionary*)headers bodyFile:(NSString*)body; 8 | @end 9 | -------------------------------------------------------------------------------- /Samples/PasswdHTTPServer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PasswdHTTPServer 4 | // 5 | // Created by Robbie Hanson on 5/19/09. 6 | // Copyright Deusty Designs, LLC. 2009. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **) argv); 14 | } 15 | -------------------------------------------------------------------------------- /Samples/PostHTTPServer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PostHTTPServer 4 | // 5 | // Created by Robbie Hanson on 11/20/08. 6 | // Copyright Deusty Designs, LLC. 2008. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **) argv); 14 | } 15 | -------------------------------------------------------------------------------- /Samples/SecureHTTPServer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SecureHTTPServer 4 | // 5 | // Created by Robbie Hanson on 5/19/09. 6 | // Copyright Deusty Designs, LLC. 2009. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **) argv); 14 | } 15 | -------------------------------------------------------------------------------- /Samples/SimpleFileUploadServer/SimpleFileUploadServer/MyHTTPConnection.h: -------------------------------------------------------------------------------- 1 | 2 | #import "HTTPConnection.h" 3 | 4 | @class MultipartFormDataParser; 5 | 6 | @interface MyHTTPConnection : HTTPConnection { 7 | MultipartFormDataParser* parser; 8 | NSFileHandle* storeFile; 9 | 10 | NSMutableArray* uploadedFiles; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Samples/SimpleHTTPServer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SimpleHTTPServer 4 | // 5 | // Created by Robert Hanson on 6/6/07. 6 | // Copyright Deusty Designs, LLC 2007. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **) argv); 14 | } 15 | -------------------------------------------------------------------------------- /Samples/DynamicServer/DynamicServerAppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class HTTPServer; 4 | 5 | 6 | @interface DynamicServerAppDelegate : NSObject 7 | { 8 | HTTPServer *httpServer; 9 | 10 | NSWindow *__unsafe_unretained window; 11 | } 12 | 13 | @property (unsafe_unretained) IBOutlet NSWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SimpleWebSocketServer 4 | // 5 | // Created by Robbie Hanson on 4/20/10. 6 | // Copyright 2010 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **) argv); 14 | } 15 | -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SecureWebSocketServer 4 | // 5 | // Created by Robbie Hanson on 6/3/11. 6 | // Copyright 2011 Voalte. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/SimpleWebSocketServerAppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class HTTPServer; 4 | 5 | 6 | @interface SimpleWebSocketServerAppDelegate : NSObject 7 | { 8 | HTTPServer *httpServer; 9 | NSWindow *__unsafe_unretained window; 10 | } 11 | 12 | @property (unsafe_unretained) IBOutlet NSWindow *window; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Vendor/CocoaLumberjack/Extensions/README.txt: -------------------------------------------------------------------------------- 1 | This folder contains some sample formatters that may be helpful. 2 | 3 | Feel free to change them, extend them, or use them as the basis for your own custom formatter(s). 4 | 5 | More information about creating your own custom formatters can be found on the wiki: 6 | https://github.com/robbiehanson/CocoaLumberjack/wiki/CustomFormatters 7 | 8 | -------------------------------------------------------------------------------- /Samples/DynamicServer/DynamicServer.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Samples/WebDAVServer/WebDAVServer.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Samples/PostHTTPServer/PostHTTPServer.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Samples/SimpleFileUploadServer/SimpleFileUploadServer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SimpleFileUploadServer 4 | // 5 | // Created by Валерий Гаврилов on 16.04.12. 6 | // Copyright (c) 2012 muhtau1@gmail.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /Samples/PasswdHTTPServer/PasswdHTTPServer.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Samples/SecureHTTPServer/SecureHTTPServer.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Samples/SimpleHTTPServer/SimpleHTTPServer.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Samples/iPhoneHTTPServer/iPhoneHTTPServer.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/SecureWebSocketServerAppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class HTTPServer; 4 | 5 | 6 | @interface SecureWebSocketServerAppDelegate : NSObject { 7 | @private 8 | HTTPServer *httpServer; 9 | NSWindow *__unsafe_unretained window; 10 | } 11 | 12 | @property (unsafe_unretained) IBOutlet NSWindow *window; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Samples/SimpleFileUploadServer/SimpleFileUploadServer.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/SimpleWebSocketServer.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Core/Categories/DDNumber.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface NSNumber (DDNumber) 5 | 6 | + (BOOL)parseString:(NSString *)str intoSInt64:(SInt64 *)pNum; 7 | + (BOOL)parseString:(NSString *)str intoUInt64:(UInt64 *)pNum; 8 | 9 | + (BOOL)parseString:(NSString *)str intoNSInteger:(NSInteger *)pNum; 10 | + (BOOL)parseString:(NSString *)str intoNSUInteger:(NSUInteger *)pNum; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Extensions/WebDAV/DAVResponse.h: -------------------------------------------------------------------------------- 1 | #import "HTTPResponse.h" 2 | 3 | @interface DAVResponse : NSObject { 4 | @private 5 | UInt64 _offset; 6 | NSMutableDictionary* _headers; 7 | NSData* _data; 8 | NSInteger _status; 9 | } 10 | - (id) initWithMethod:(NSString*)method headers:(NSDictionary*)headers bodyData:(NSData*)body resourcePath:(NSString*)resourcePath rootPath:(NSString*)rootPath; 11 | @end 12 | -------------------------------------------------------------------------------- /Samples/iPhoneHTTPServer/Web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | iPhone HTTP Server Example 4 | 5 | 6 |

Welcome to CocoaHTTPServer!

7 | 8 | You can customize this page for your app, make other pages, or even serve up dynamic content.
9 | 10 | CocoaHTTPServer Project Page
11 | 12 | 13 | -------------------------------------------------------------------------------- /Samples/iPhoneHTTPServer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // iPhoneHTTPServer 4 | // 5 | // Created by Robbie Hanson on 11/25/10. 6 | // Copyright 2010 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) { 12 | 13 | @autoreleasepool { 14 | int retVal = UIApplicationMain(argc, argv, nil, nil); 15 | return retVal; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Samples/SimpleFileUploadServer/README.markdown: -------------------------------------------------------------------------------- 1 | INFO: 2 | 3 | This example project demonstrates the ability of accepting a file upload. 4 | 5 | INSTRUCTIONS: 6 | 7 | Open the Xcode project, and build and go. 8 | 9 | On the Xcode console you'll see a message saying: 10 | "Started HTTP server on port 59123" 11 | 12 | Now open your browser and type in the URL: 13 | http://localhost:59123 14 | 15 | (Replace 59123 with whatever port the server is actually running on.) 16 | 17 | Enjoy. -------------------------------------------------------------------------------- /Samples/Xcode-Configurations/ReadMe.txt: -------------------------------------------------------------------------------- 1 | Since there are so many different sample Xcode projects, we use these Xcode config files to help simplify a lot configuring of the projects and targets, and ensuring they are all in sync. 2 | 3 | Please note: These settings are not required if you want to include the CocoaHTTPServer in your project. They mostly help the developers of the project by ensuring that many compiler warnings are turned on so we don't introduce compiler issues into the project. -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/Web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | SimpleWebSocketServer 4 | 5 | 6 | 7 | 8 | Does my browser support WebSockets?
9 |
10 | Open WebSocket and tell me what time it is. 11 | 12 | -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/Web/WebSocketTest.js: -------------------------------------------------------------------------------- 1 | function WebSocketTest() 2 | { 3 | if ("WebSocket" in window) 4 | { 5 | alert("WebSocket supported here! :)\r\n\r\nBrowser: " + navigator.appName + " " + navigator.appVersion + "\r\n\r\n(based on Google sample code)"); 6 | } 7 | else 8 | { 9 | // Browser doesn't support WebSocket 10 | alert("WebSocket NOT supported here! :(\r\n\r\nBrowser: " + navigator.appName + " " + navigator.appVersion + "\r\n\r\n(based on Google sample code)"); 11 | } 12 | } -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/Web/WebSocketTest.js: -------------------------------------------------------------------------------- 1 | function WebSocketTest() 2 | { 3 | if ("WebSocket" in window) 4 | { 5 | alert("WebSocket supported here! :)\r\n\r\nBrowser: " + navigator.appName + " " + navigator.appVersion + "\r\n\r\n(based on Google sample code)"); 6 | } 7 | else 8 | { 9 | // Browser doesn't support WebSocket 10 | alert("WebSocket NOT supported here! :(\r\n\r\nBrowser: " + navigator.appName + " " + navigator.appVersion + "\r\n\r\n(based on Google sample code)"); 11 | } 12 | } -------------------------------------------------------------------------------- /Samples/iPhoneHTTPServer/Classes/iPhoneHTTPServerAppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class iPhoneHTTPServerViewController; 4 | @class HTTPServer; 5 | 6 | @interface iPhoneHTTPServerAppDelegate : NSObject 7 | { 8 | HTTPServer *httpServer; 9 | 10 | UIWindow *window; 11 | iPhoneHTTPServerViewController *viewController; 12 | } 13 | 14 | @property (nonatomic) IBOutlet UIWindow *window; 15 | @property (nonatomic) IBOutlet iPhoneHTTPServerViewController *viewController; 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /Samples/SimpleHTTPServer/README.markdown: -------------------------------------------------------------------------------- 1 | INFO: 2 | 3 | This is a bare bones example of how to embed the CocoaHTTPServer in a desktop application. The document root of the server is set to the ~/Sites folder. 4 | 5 | INSTRUCTIONS: 6 | 7 | Open the Xcode project, and build and go. 8 | 9 | On the Xcode console you'll see a message saying: 10 | "Started HTTP server on port 59123" 11 | 12 | Now open your browser and type in the URL: 13 | http://localhost:59123 14 | 15 | (Replace 59123 with whatever port the server is actually running on.) 16 | 17 | Enjoy. -------------------------------------------------------------------------------- /Core/Responses/HTTPFileResponse.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPResponse.h" 3 | 4 | @class HTTPConnection; 5 | 6 | 7 | @interface HTTPFileResponse : NSObject 8 | { 9 | HTTPConnection *connection; 10 | 11 | NSString *filePath; 12 | UInt64 fileLength; 13 | UInt64 fileOffset; 14 | 15 | BOOL aborted; 16 | 17 | int fileFD; 18 | void *buffer; 19 | NSUInteger bufferSize; 20 | } 21 | 22 | - (id)initWithFilePath:(NSString *)filePath forConnection:(HTTPConnection *)connection; 23 | - (NSString *)filePath; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Samples/Xcode-Configurations/Base.xcconfig: -------------------------------------------------------------------------------- 1 | // Common Settings 2 | ALWAYS_SEARCH_USER_PATHS = NO 3 | GCC_PRECOMPILE_PREFIX_HEADER = YES 4 | GCC_C_LANGUAGE_STANDARD = c99 5 | GCC_ENABLE_CPP_EXCEPTIONS = NO 6 | GCC_ENABLE_CPP_RTTI = NO 7 | 8 | // Common Warnings 9 | GCC_WARN_SHADOW = YES 10 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES 11 | GCC_WARN_ABOUT_RETURN_TYPE = YES 12 | GCC_WARN_MISSING_PARENTHESES = YES 13 | GCC_WARN_UNUSED_VARIABLE = YES 14 | WARNING_CFLAGS = -Wall -Winline 15 | 16 | // iOS SDK 17 | CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer 18 | 19 | 20 | -------------------------------------------------------------------------------- /Samples/SimpleFileUploadServer/SimpleFileUploadServer/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |
9 |
10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/Web/WebSocketTest2.js: -------------------------------------------------------------------------------- 1 | function WebSocketTest2() 2 | { 3 | if ("WebSocket" in window) 4 | { 5 | var ws = new WebSocket("%%WEBSOCKET_URL%%"); 6 | ws.onopen = function() 7 | { 8 | // Web Socket is connected 9 | alert("websocket is open"); 10 | 11 | // You can send data now 12 | ws.send("Hey man, you got the time?"); 13 | }; 14 | ws.onmessage = function(evt) { alert("received: " + evt.data); }; 15 | ws.onclose = function() { alert("websocket is closed"); }; 16 | } 17 | else 18 | { 19 | alert("Browser doesn't support WebSocket!"); 20 | } 21 | } -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/Web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | SimpleWebSocketServer 4 | 5 | 6 | 7 | 8 | 9 | 10 | Does my browser support WebSockets?
11 |
12 |
13 | Server Time 14 | not updated yet 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Samples/DynamicServer/HTTPResponseTest.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPResponse.h" 3 | 4 | @class HTTPConnection; 5 | 6 | // 7 | // This class is a UnitTest for the delayResponseHeaders capability of HTTPConnection 8 | // 9 | 10 | @interface HTTPResponseTest : NSObject 11 | { 12 | // Parents retain children, children do NOT retain parents 13 | 14 | __unsafe_unretained HTTPConnection *connection; 15 | dispatch_queue_t responseQueue; 16 | 17 | BOOL readyToSendResponseHeaders; 18 | } 19 | 20 | - (id)initWithConnection:(HTTPConnection *)connection; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /Samples/SimpleFileUploadServer/SimpleFileUploadServer/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /Samples/SecureHTTPServer/DDKeychain.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface DDKeychain : NSObject 5 | { 6 | 7 | } 8 | 9 | + (NSString *)passwordForHTTPServer; 10 | + (BOOL)setPasswordForHTTPServer:(NSString *)password; 11 | 12 | + (void)createNewIdentity; 13 | + (NSArray *)SSLIdentityAndCertificates; 14 | 15 | + (NSString *)applicationTemporaryDirectory; 16 | + (NSString *)stringForSecExternalFormat:(SecExternalFormat)extFormat; 17 | + (NSString *)stringForSecExternalItemType:(SecExternalItemType)itemType; 18 | + (NSString *)stringForSecKeychainAttrType:(SecKeychainAttrType)attrType; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/DDKeychain.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface DDKeychain : NSObject 5 | { 6 | 7 | } 8 | 9 | + (NSString *)passwordForHTTPServer; 10 | + (BOOL)setPasswordForHTTPServer:(NSString *)password; 11 | 12 | + (void)createNewIdentity; 13 | + (NSArray *)SSLIdentityAndCertificates; 14 | 15 | + (NSString *)applicationTemporaryDirectory; 16 | + (NSString *)stringForSecExternalFormat:(SecExternalFormat)extFormat; 17 | + (NSString *)stringForSecExternalItemType:(SecExternalItemType)itemType; 18 | + (NSString *)stringForSecKeychainAttrType:(SecKeychainAttrType)attrType; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Core/Responses/HTTPErrorResponse.m: -------------------------------------------------------------------------------- 1 | #import "HTTPErrorResponse.h" 2 | 3 | @implementation HTTPErrorResponse 4 | 5 | -(id)initWithErrorCode:(int)httpErrorCode 6 | { 7 | if ((self = [super init])) 8 | { 9 | _status = httpErrorCode; 10 | } 11 | 12 | return self; 13 | } 14 | 15 | - (UInt64) contentLength { 16 | return 0; 17 | } 18 | 19 | - (UInt64) offset { 20 | return 0; 21 | } 22 | 23 | - (void)setOffset:(UInt64)offset { 24 | ; 25 | } 26 | 27 | - (NSData*) readDataOfLength:(NSUInteger)length { 28 | return nil; 29 | } 30 | 31 | - (BOOL) isDone { 32 | return YES; 33 | } 34 | 35 | - (NSInteger) status { 36 | return _status; 37 | } 38 | @end 39 | -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/MyWebSocket.m: -------------------------------------------------------------------------------- 1 | #import "MyWebSocket.h" 2 | #import "HTTPLogging.h" 3 | 4 | // Log levels: off, error, warn, info, verbose 5 | // Other flags : trace 6 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN | HTTP_LOG_FLAG_TRACE; 7 | 8 | 9 | @implementation MyWebSocket 10 | 11 | - (void)didOpen 12 | { 13 | HTTPLogTrace(); 14 | 15 | [super didOpen]; 16 | } 17 | 18 | - (void)didReceiveMessage:(NSString *)msg 19 | { 20 | HTTPLogTrace2(@"%@[%p]: didReceiveMessage: %@", THIS_FILE, self, msg); 21 | 22 | [self sendMessage:[NSString stringWithFormat:@"%@", [NSDate date]]]; 23 | } 24 | 25 | - (void)didClose 26 | { 27 | HTTPLogTrace(); 28 | 29 | [super didClose]; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/MyWebSocket.m: -------------------------------------------------------------------------------- 1 | #import "MyWebSocket.h" 2 | #import "HTTPLogging.h" 3 | 4 | // Log levels: off, error, warn, info, verbose 5 | // Other flags : trace 6 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN | HTTP_LOG_FLAG_TRACE; 7 | 8 | 9 | @implementation MyWebSocket 10 | 11 | - (void)didOpen 12 | { 13 | HTTPLogTrace(); 14 | 15 | [super didOpen]; 16 | 17 | [self sendMessage:@"Welcome to my WebSocket"]; 18 | } 19 | 20 | - (void)didReceiveMessage:(NSString *)msg 21 | { 22 | HTTPLogTrace2(@"%@[%p]: didReceiveMessage: %@", THIS_FILE, self, msg); 23 | 24 | [self sendMessage:[NSString stringWithFormat:@"%@", [NSDate date]]]; 25 | } 26 | 27 | - (void)didClose 28 | { 29 | HTTPLogTrace(); 30 | 31 | [super didClose]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Samples/DynamicServer/README.markdown: -------------------------------------------------------------------------------- 1 | INFO: 2 | 3 | This example project demonstrates the ability of the HTTPDynamicFileResponse to easily create dynamic content. 4 | 5 | Take a look at the Web/index.html file. You'll notice a bunch of "%%PLACEHOLDERS%%" meant to be replaced dynamically. With only a few lines of code, the HTTPDynamicFileResponse will replace these automatically, and asynchronously, as the file gets uploaded to the client! 6 | 7 | INSTRUCTIONS: 8 | 9 | Open the Xcode project, and build and go. 10 | 11 | On the Xcode console you'll see a message saying: 12 | "Started HTTP server on port 59123" 13 | 14 | Now open your browser and type in the URL: 15 | http://localhost:59123 16 | 17 | (Replace 59123 with whatever port the server is actually running on.) 18 | 19 | Enjoy. -------------------------------------------------------------------------------- /Core/Mime/MultipartMessageHeaderField.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | //----------------------------------------------------------------- 5 | // interface MultipartMessageHeaderField 6 | //----------------------------------------------------------------- 7 | 8 | @interface MultipartMessageHeaderField : NSObject { 9 | NSString* name; 10 | NSString* value; 11 | NSMutableDictionary* params; 12 | } 13 | 14 | @property (strong, readonly) NSString* value; 15 | @property (strong, readonly) NSDictionary* params; 16 | @property (strong, readonly) NSString* name; 17 | 18 | //- (id) initWithLine:(NSString*) line; 19 | //- (id) initWithName:(NSString*) paramName value:(NSString*) paramValue; 20 | 21 | - (id) initWithData:(NSData*) data contentEncoding:(NSStringEncoding) encoding; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Samples/PostHTTPServer/README.markdown: -------------------------------------------------------------------------------- 1 | INFO: 2 | 3 | This is an extremely simplified example of accepting a POST. 4 | 5 | The included Web folder is added to the project, copied into the applications resource bundle, and set as the document root of the http server. It only has a single index.html file which prompts you to answer a simple math question. Your answer is submitted as a post. 6 | 7 | The MyHTTPConnection class reads your response, and dynamically generates the response. 8 | 9 | INSTRUCTIONS: 10 | 11 | Open the Xcode project, and build and go. 12 | 13 | On the Xcode console you'll see a message saying: 14 | "Started HTTP server on port 59123" 15 | 16 | Now open your browser and type in the URL: 17 | http://localhost:59123 18 | 19 | (Replace 59123 with whatever port the server is actually running on.) 20 | 21 | Enjoy. -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/README.markdown: -------------------------------------------------------------------------------- 1 | INFO: 2 | 3 | This example project demonstrates support for WebSockets. 4 | 5 | The sample includes a Web folder which is added to the project, copied into the application's resources folder, and is set as the document root of the http server. It contains a simple index.html file and the client-side code (run in the web browser) for the websocket stuff. 6 | 7 | Take a look at the MyWebSocket class to see the related server code. 8 | 9 | INSTRUCTIONS: 10 | 11 | Open the Xcode project, and build and go. 12 | 13 | On the Xcode console you'll see a message saying: 14 | "Started HTTP server on port 59123" 15 | 16 | Now open a browser that supports WebSockets (e.g. Google Chrome or Safari) 17 | and type in the URL: 18 | http://localhost:59123 19 | 20 | (Replace 59123 with whatever port the server is actually running on.) 21 | 22 | Enjoy. -------------------------------------------------------------------------------- /Samples/WebDAVServer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.yourcompany.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | APPL 17 | CFBundleVersion 18 | 1.0 19 | NSMainNibFile 20 | MainMenu 21 | NSPrincipalClass 22 | NSApplication 23 | 24 | 25 | -------------------------------------------------------------------------------- /Core/HTTPAuthenticationRequest.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #if TARGET_OS_IPHONE 4 | // Note: You may need to add the CFNetwork Framework to your project 5 | #import 6 | #endif 7 | 8 | @class HTTPMessage; 9 | 10 | 11 | @interface HTTPAuthenticationRequest : NSObject 12 | { 13 | BOOL isBasic; 14 | BOOL isDigest; 15 | 16 | NSString *base64Credentials; 17 | 18 | NSString *username; 19 | NSString *realm; 20 | NSString *nonce; 21 | NSString *uri; 22 | NSString *qop; 23 | NSString *nc; 24 | NSString *cnonce; 25 | NSString *response; 26 | } 27 | - (id)initWithRequest:(HTTPMessage *)request; 28 | 29 | - (BOOL)isBasic; 30 | - (BOOL)isDigest; 31 | 32 | // Basic 33 | - (NSString *)base64Credentials; 34 | 35 | // Digest 36 | - (NSString *)username; 37 | - (NSString *)realm; 38 | - (NSString *)nonce; 39 | - (NSString *)uri; 40 | - (NSString *)qop; 41 | - (NSString *)nc; 42 | - (NSString *)cnonce; 43 | - (NSString *)response; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Samples/PasswdHTTPServer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.yourcompany.${PRODUCT_NAME:identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | NSMainNibFile 24 | MainMenu 25 | NSPrincipalClass 26 | NSApplication 27 | 28 | 29 | -------------------------------------------------------------------------------- /Samples/PostHTTPServer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.yourcompany.${PRODUCT_NAME:identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | NSMainNibFile 24 | MainMenu 25 | NSPrincipalClass 26 | NSApplication 27 | 28 | 29 | -------------------------------------------------------------------------------- /Samples/SecureHTTPServer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.yourcompany.${PRODUCT_NAME:identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | NSMainNibFile 24 | MainMenu 25 | NSPrincipalClass 26 | NSApplication 27 | 28 | 29 | -------------------------------------------------------------------------------- /Samples/SimpleHTTPServer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.yourcompany.SimpleHTTPServer 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | NSMainNibFile 24 | MainMenu 25 | NSPrincipalClass 26 | NSApplication 27 | 28 | 29 | -------------------------------------------------------------------------------- /Samples/iPhoneHTTPServer/iPhoneHTTPServer-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | com.yourcompany.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | NSMainNibFile 28 | MainWindow 29 | 30 | 31 | -------------------------------------------------------------------------------- /CocoaHTTPServer.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CocoaHTTPServer", 3 | "version": "2.3", 4 | "license": "BSD", 5 | "summary": "A small, lightweight, embeddable HTTP server for Mac OS X or iOS applications.", 6 | "homepage": "https://github.com/robbiehanson/CocoaHTTPServer", 7 | "authors": { 8 | "Robbie Hanson": "cocoahttpserver@googlegroups.com" 9 | }, 10 | "source": { 11 | "git": "https://github.com/robbiehanson/CocoaHTTPServer.git", 12 | "tag": "2.3" 13 | }, 14 | "source_files": "{Core,Extensions}/**/*.{h,m}", 15 | "requires_arc": true, 16 | "platforms": { 17 | "ios": "5.0", 18 | "osx": "10.7" 19 | }, 20 | "ios": { 21 | "frameworks": [ 22 | "CFNetwork", 23 | "Security" 24 | ] 25 | }, 26 | "osx": { 27 | "frameworks": [ 28 | "CoreServices", 29 | "Security" 30 | ] 31 | }, 32 | "libraries": "xml2", 33 | "xcconfig": { 34 | "HEADER_SEARCH_PATHS": "\"$(SDKROOT)/usr/include/libxml2\"" 35 | }, 36 | "dependencies": { 37 | "CocoaAsyncSocket": [ 38 | 39 | ], 40 | "CocoaLumberjack": [ 41 | 42 | ] 43 | } 44 | } -------------------------------------------------------------------------------- /Samples/DynamicServer/Web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dynamic Server Example 4 | 5 | 6 |

7 | Welcome to CocoaHTTPServer! 8 |

9 | 10 |

11 | Parts of this file are generated dynamically.
12 | This is done via the HTTPDynamicFileResponse class.
13 | It uses a replacement dictionary to automatically replace
14 | tagged strings in the included Web/index.html file.
15 |

16 | 17 |

18 | Computer name: %%COMPUTER_NAME%%
19 |
20 | 21 | 22 | The current time is: %%TIME%%
23 |
24 | Tell me a story: %%STORY%%
25 |
26 | 27 | 28 | The first letter of the english alphabet: %%ALPHABET%%
29 |
30 | 31 | 32 | The sound a duck makes: %%QUACK%%
33 |
34 |
35 | Thank you. Come again. 36 |

37 | 38 | 39 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | 3 | script: 4 | - xctool -project Samples/DynamicServer/DynamicServer.xcodeproj -scheme DynamicServer build 5 | - xctool -project Samples/iPhoneHTTPServer/iPhoneHTTPServer.xcodeproj -scheme iPhoneHTTPServer -sdk iphonesimulator build 6 | - xctool -project Samples/PasswdHTTPServer/PasswdHTTPServer.xcodeproj -scheme PasswdHTTPServer build 7 | - xctool -project Samples/PostHTTPServer/PostHTTPServer.xcodeproj -scheme PostHTTPServer build 8 | - xctool -project Samples/SecureHTTPServer/SecureHTTPServer.xcodeproj -scheme SecureHTTPServer build 9 | - xctool -project Samples/SecureWebSocketServer/SecureWebSocketServer.xcodeproj -scheme SecureWebSocketServer build 10 | - xctool -project Samples/SimpleFileUploadServer/SimpleFileUploadServer.xcodeproj -scheme SimpleFileUploadServer build 11 | - xctool -project Samples/SimpleHTTPServer/SimpleHTTPServer.xcodeproj -scheme SimpleHTTPServer build 12 | - xctool -project Samples/SimpleWebSocketServer/SimpleWebSocketServer.xcodeproj -scheme SimpleWebSocketServer build 13 | - xctool -project Samples/WebDAVServer/WebDAVServer.xcodeproj -scheme WebDAVServer build 14 | -------------------------------------------------------------------------------- /Samples/WebDAVServer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import "DDLog.h" 3 | #import "DDTTYLogger.h" 4 | #import "HTTPServer.h" 5 | #import "DAVConnection.h" 6 | 7 | static const int ddLogLevel = LOG_LEVEL_VERBOSE; 8 | 9 | @implementation AppDelegate 10 | 11 | - (void) applicationDidFinishLaunching:(NSNotification*)notification { 12 | // Configure logging system 13 | [DDLog addLogger:[DDTTYLogger sharedInstance]]; 14 | 15 | // Create DAV server 16 | _httpServer = [[HTTPServer alloc] init]; 17 | [_httpServer setConnectionClass:[DAVConnection class]]; 18 | [_httpServer setPort:8080]; 19 | 20 | // Enable Bonjour 21 | [_httpServer setType:@"_http._tcp."]; 22 | 23 | // Set document root 24 | [_httpServer setDocumentRoot:[@"~/Sites" stringByExpandingTildeInPath]]; 25 | 26 | // Start DAV server 27 | NSError* error = nil; 28 | if (![_httpServer start:&error]) { 29 | DDLogError(@"Error starting HTTP Server: %@", error); 30 | } 31 | } 32 | 33 | - (void) applicationWillTerminate:(NSNotification*)notification { 34 | // Stop DAV server 35 | [_httpServer stop]; 36 | _httpServer = nil; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Samples/DynamicServer/DynamicServer-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.yourcompany.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /Core/Mime/MultipartMessageHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // MultipartMessagePart.h 3 | // HttpServer 4 | // 5 | // Created by Валерий Гаврилов on 29.03.12. 6 | // Copyright (c) 2012 LLC "Online Publishing Partners" (onlinepp.ru). All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | //----------------------------------------------------------------- 13 | // interface MultipartMessageHeader 14 | //----------------------------------------------------------------- 15 | enum { 16 | contentTransferEncoding_unknown, 17 | contentTransferEncoding_7bit, 18 | contentTransferEncoding_8bit, 19 | contentTransferEncoding_binary, 20 | contentTransferEncoding_base64, 21 | contentTransferEncoding_quotedPrintable, 22 | }; 23 | 24 | @interface MultipartMessageHeader : NSObject { 25 | NSMutableDictionary* fields; 26 | int encoding; 27 | NSString* contentDispositionName; 28 | } 29 | @property (strong,readonly) NSDictionary* fields; 30 | @property (readonly) int encoding; 31 | 32 | - (id) initWithData:(NSData*) data formEncoding:(NSStringEncoding) encoding; 33 | @end 34 | -------------------------------------------------------------------------------- /Samples/SecureHTTPServer/MyHTTPConnection.m: -------------------------------------------------------------------------------- 1 | #import "MyHTTPConnection.h" 2 | #import "HTTPLogging.h" 3 | #import "DDKeychain.h" 4 | 5 | // Log levels: off, error, warn, info, verbose 6 | // Other flags: trace 7 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN; // | HTTP_LOG_FLAG_TRACE; 8 | 9 | 10 | @implementation MyHTTPConnection 11 | 12 | /** 13 | * Overrides HTTPConnection's method 14 | **/ 15 | - (BOOL)isSecureServer 16 | { 17 | HTTPLogTrace(); 18 | 19 | // Create an HTTPS server (all connections will be secured via SSL/TLS) 20 | return YES; 21 | } 22 | 23 | /** 24 | * Overrides HTTPConnection's method 25 | * 26 | * This method is expected to returns an array appropriate for use in kCFStreamSSLCertificates SSL Settings. 27 | * It should be an array of SecCertificateRefs except for the first element in the array, which is a SecIdentityRef. 28 | **/ 29 | - (NSArray *)sslIdentityAndCertificates 30 | { 31 | HTTPLogTrace(); 32 | 33 | NSArray *result = [DDKeychain SSLIdentityAndCertificates]; 34 | if([result count] == 0) 35 | { 36 | [DDKeychain createNewIdentity]; 37 | return [DDKeychain SSLIdentityAndCertificates]; 38 | } 39 | return result; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/SimpleWebSocketServer-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.yourcompany.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleSignature 20 | ???? 21 | CFBundleShortVersionString 22 | 1.0 23 | LSMinimumSystemVersion 24 | ${MACOSX_DEPLOYMENT_TARGET} 25 | CFBundleVersion 26 | 1 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/SecureWebSocketServer-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.deusty.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /Extensions/WebDAV/DELETEResponse.m: -------------------------------------------------------------------------------- 1 | #import "DELETEResponse.h" 2 | #import "HTTPLogging.h" 3 | 4 | // HTTP methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html 5 | // HTTP headers: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html 6 | // HTTP status codes: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 7 | 8 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN; 9 | 10 | @implementation DELETEResponse 11 | 12 | - (id) initWithFilePath:(NSString*)path { 13 | if ((self = [super init])) { 14 | BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path]; 15 | if ([[NSFileManager defaultManager] removeItemAtPath:path error:NULL]) { 16 | _status = exists ? 200 : 204; 17 | } else { 18 | HTTPLogError(@"Failed deleting \"%@\"", path); 19 | _status = 404; 20 | } 21 | } 22 | return self; 23 | } 24 | 25 | - (UInt64) contentLength { 26 | return 0; 27 | } 28 | 29 | - (UInt64) offset { 30 | return 0; 31 | } 32 | 33 | - (void)setOffset:(UInt64)offset { 34 | ; 35 | } 36 | 37 | - (NSData*) readDataOfLength:(NSUInteger)length { 38 | return nil; 39 | } 40 | 41 | - (BOOL) isDone { 42 | return YES; 43 | } 44 | 45 | - (NSInteger) status { 46 | return _status; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Samples/iPhoneHTTPServer/README.markdown: -------------------------------------------------------------------------------- 1 | INFO: 2 | 3 | This is a bare bones project demonstrating how to embed the CocoaHTTPServer in an iOS project. 4 | 5 | Notice the Web folder. This folder is added to the project as a resource, and the folder itself is copied into the iPhone app. The contents of the folder are set as the document root of the http server. 6 | 7 | Critical note: The server is running only while application is in foreground. As soon as you exit from the application (by switching to another app or locking a device) the server will be stopped. The server will be restarted when you enter the application again. 8 | Read this Apple technical note for the details: http://developer.apple.com/library/ios/#technotes/tn2277/_index.html 9 | 10 | INSTRUCTIONS: 11 | 12 | Open the Xcode project, and build and go. 13 | 14 | On the Xcode console you'll see a message saying: 15 | "Started HTTP server on port 59123" 16 | 17 | Now open your browser and type in the URL to access the server. 18 | If you're running it via the simulator, then you can use: 19 | http://localhost:59123 20 | 21 | If you're running it on your device, then you'll need to use: 22 | http://<local IP of device>:59123 23 | 24 | (Replace 59123 with whatever port the server is actually running on.) 25 | 26 | Enjoy. -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/Web/WebSocketTest2.js: -------------------------------------------------------------------------------- 1 | 2 | var ws; 3 | var t; 4 | 5 | function init() 6 | { 7 | document.getElementById('updateme').innerHTML = "connecting to websocket"; 8 | OpenWebSocket(); 9 | } 10 | 11 | function OpenWebSocket() 12 | { 13 | if ("WebSocket" in window) 14 | { 15 | ws = new WebSocket("%%WEBSOCKET_URL%%"); 16 | ws.onopen = function() 17 | { 18 | // Web Socket is connected 19 | 20 | document.getElementById('updateme').innerHTML = "websocket is open"; 21 | 22 | t=setTimeout("SendMessage()",1000); 23 | }; 24 | ws.onmessage = function(evt) 25 | { 26 | document.getElementById('updateme').innerHTML = evt.data; 27 | }; 28 | ws.onclose = function() 29 | { 30 | document.getElementById('updateme').innerHTML = "websocket is closed"; 31 | OpenWebSocket(); 32 | }; 33 | ws.onerror = function(evt) 34 | { 35 | alert("onerror: " + evt); 36 | }; 37 | } 38 | else 39 | { 40 | alert("Browser doesn't support WebSocket!"); 41 | } 42 | } 43 | 44 | function SendMessage() 45 | { 46 | if ("WebSocket" in window) 47 | { 48 | ws.send("time"); 49 | 50 | t=setTimeout("SendMessage()",1000); 51 | } 52 | else 53 | { 54 | alert("Browser doesn't support WebSocket!"); 55 | } 56 | } -------------------------------------------------------------------------------- /Core/HTTPMessage.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The HTTPMessage class is a simple Objective-C wrapper around Apple's CFHTTPMessage class. 3 | **/ 4 | 5 | #import 6 | 7 | #if TARGET_OS_IPHONE 8 | // Note: You may need to add the CFNetwork Framework to your project 9 | #import 10 | #endif 11 | 12 | #define HTTPVersion1_0 ((NSString *)kCFHTTPVersion1_0) 13 | #define HTTPVersion1_1 ((NSString *)kCFHTTPVersion1_1) 14 | 15 | 16 | @interface HTTPMessage : NSObject 17 | { 18 | CFHTTPMessageRef message; 19 | } 20 | 21 | - (id)initEmptyRequest; 22 | 23 | - (id)initRequestWithMethod:(NSString *)method URL:(NSURL *)url version:(NSString *)version; 24 | 25 | - (id)initResponseWithStatusCode:(NSInteger)code description:(NSString *)description version:(NSString *)version; 26 | 27 | - (BOOL)appendData:(NSData *)data; 28 | 29 | - (BOOL)isHeaderComplete; 30 | 31 | - (NSString *)version; 32 | 33 | - (NSString *)method; 34 | - (NSURL *)url; 35 | 36 | - (NSInteger)statusCode; 37 | 38 | - (NSDictionary *)allHeaderFields; 39 | - (NSString *)headerField:(NSString *)headerField; 40 | 41 | - (void)setHeaderField:(NSString *)headerField value:(NSString *)headerFieldValue; 42 | 43 | - (NSData *)messageData; 44 | 45 | - (NSData *)body; 46 | - (void)setBody:(NSData *)body; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Samples/PasswdHTTPServer/README.markdown: -------------------------------------------------------------------------------- 1 | INFO: 2 | 3 | This project demonstrates password protecting a specific resource. More specifically, the project allows unrestricted access to the ~/Sites folder, but requires a password for anything in the ~/Sites/secret/ subfolder. 4 | 5 | INSTRUCTIONS: 6 | 7 | Create the following folder: 8 | ~/Sites/secret 9 | 10 | And then add a file to it. For example: 11 | ~/Sites/secret/doc.txt 12 | 13 | Open the Xcode project, and build and go. 14 | 15 | On the Xcode console you'll see a message saying something like: 16 | "Started HTTP server on port 59123" 17 | 18 | _The actual port the server uses is not hard-coded. You can hard-code it if you want, but by default it will just allow the operating system to provide an available port._ 19 | 20 | Now open your browser and type the URL (replacing with the proper port):
21 | http://localhost:59123 22 | 23 | Notice that it displays your file without password prompt:
24 | ~/Sites/index.html 25 | 26 | Now type the URL (replacing with password prompt):
27 | http://localhost:59123/secret/doc.txt 28 | 29 | Notice that it prompts you for a username/password. 30 | The sample code accepts any username, and the password is "secret". 31 | 32 | (Replace 59123 with whatever port the server is actually running on.) 33 | 34 | Enjoy. -------------------------------------------------------------------------------- /Samples/SimpleFileUploadServer/SimpleFileUploadServer/SimpleFileUploadServer-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | mycompany.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2012 muhtau1@gmail.com. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Core/Responses/HTTPRedirectResponse.m: -------------------------------------------------------------------------------- 1 | #import "HTTPRedirectResponse.h" 2 | #import "HTTPLogging.h" 3 | 4 | #if ! __has_feature(objc_arc) 5 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 6 | #endif 7 | 8 | // Log levels : off, error, warn, info, verbose 9 | // Other flags: trace 10 | static const int httpLogLevel = HTTP_LOG_LEVEL_OFF; // | HTTP_LOG_FLAG_TRACE; 11 | 12 | 13 | @implementation HTTPRedirectResponse 14 | 15 | - (id)initWithPath:(NSString *)path 16 | { 17 | if ((self = [super init])) 18 | { 19 | HTTPLogTrace(); 20 | 21 | redirectPath = [path copy]; 22 | } 23 | return self; 24 | } 25 | 26 | - (UInt64)contentLength 27 | { 28 | return 0; 29 | } 30 | 31 | - (UInt64)offset 32 | { 33 | return 0; 34 | } 35 | 36 | - (void)setOffset:(UInt64)offset 37 | { 38 | // Nothing to do 39 | } 40 | 41 | - (NSData *)readDataOfLength:(NSUInteger)length 42 | { 43 | HTTPLogTrace(); 44 | 45 | return nil; 46 | } 47 | 48 | - (BOOL)isDone 49 | { 50 | return YES; 51 | } 52 | 53 | - (NSDictionary *)httpHeaders 54 | { 55 | HTTPLogTrace(); 56 | 57 | return [NSDictionary dictionaryWithObject:redirectPath forKey:@"Location"]; 58 | } 59 | 60 | - (NSInteger)status 61 | { 62 | HTTPLogTrace(); 63 | 64 | return 302; 65 | } 66 | 67 | - (void)dealloc 68 | { 69 | HTTPLogTrace(); 70 | 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /Vendor/CocoaLumberjack/DDASLLogger.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import "DDLog.h" 5 | 6 | /** 7 | * Welcome to Cocoa Lumberjack! 8 | * 9 | * The project page has a wealth of documentation if you have any questions. 10 | * https://github.com/robbiehanson/CocoaLumberjack 11 | * 12 | * If you're new to the project you may wish to read the "Getting Started" wiki. 13 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 14 | * 15 | * 16 | * This class provides a logger for the Apple System Log facility. 17 | * 18 | * As described in the "Getting Started" page, 19 | * the traditional NSLog() function directs it's output to two places: 20 | * 21 | * - Apple System Log 22 | * - StdErr (if stderr is a TTY) so log statements show up in Xcode console 23 | * 24 | * To duplicate NSLog() functionality you can simply add this logger and a tty logger. 25 | * However, if you instead choose to use file logging (for faster performance), 26 | * you may choose to use a file logger and a tty logger. 27 | **/ 28 | 29 | @interface DDASLLogger : DDAbstractLogger 30 | { 31 | aslclient client; 32 | } 33 | 34 | + (DDASLLogger *)sharedInstance; 35 | 36 | // Inherited from DDAbstractLogger 37 | 38 | // - (id )logFormatter; 39 | // - (void)setLogFormatter:(id )formatter; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Software License Agreement (BSD License) 2 | 3 | Copyright (c) 2011, 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 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Neither the name of Deusty nor the names of its 14 | contributors may be used to endorse or promote products 15 | derived from this software without specific prior 16 | written permission of Deusty, LLC. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Samples/PasswdHTTPServer/MyHTTPConnection.m: -------------------------------------------------------------------------------- 1 | #import "MyHTTPConnection.h" 2 | #import "HTTPLogging.h" 3 | 4 | // Log levels : off, error, warn, info, verbose 5 | // Other flags: trace 6 | static const int httpLogLevel = HTTP_LOG_LEVEL_VERBOSE | HTTP_LOG_FLAG_TRACE; 7 | 8 | 9 | @implementation MyHTTPConnection 10 | 11 | - (BOOL)isPasswordProtected:(NSString *)path 12 | { 13 | // We're only going to password protect the "secret" directory. 14 | 15 | BOOL result = [path hasPrefix:@"/secret"]; 16 | 17 | HTTPLogTrace2(@"%@[%p]: isPasswordProtected(%@) - %@", THIS_FILE, self, path, (result ? @"YES" : @"NO")); 18 | 19 | return result; 20 | } 21 | 22 | - (BOOL)useDigestAccessAuthentication 23 | { 24 | HTTPLogTrace(); 25 | 26 | // Digest access authentication is the default setting. 27 | // Notice in Safari that when you're prompted for your password, 28 | // Safari tells you "Your login information will be sent securely." 29 | // 30 | // If you return NO in this method, the HTTP server will use 31 | // basic authentication. Try it and you'll see that Safari 32 | // will tell you "Your password will be sent unencrypted", 33 | // which is strongly discouraged. 34 | 35 | return YES; 36 | } 37 | 38 | - (NSString *)passwordForUser:(NSString *)username 39 | { 40 | HTTPLogTrace(); 41 | 42 | // You can do all kinds of cool stuff here. 43 | // For simplicity, we're not going to check the username, only the password. 44 | 45 | return @"secret"; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Samples/SimpleHTTPServer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import "HTTPServer.h" 3 | #import "DDLog.h" 4 | #import "DDTTYLogger.h" 5 | 6 | // Log levels: off, error, warn, info, verbose 7 | static const int ddLogLevel = LOG_LEVEL_VERBOSE; 8 | 9 | 10 | @implementation AppDelegate 11 | 12 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 13 | { 14 | // Configure our logging framework. 15 | // To keep things simple and fast, we're just going to log to the Xcode console. 16 | [DDLog addLogger:[DDTTYLogger sharedInstance]]; 17 | 18 | // Initalize our http server 19 | httpServer = [[HTTPServer alloc] init]; 20 | 21 | // Tell the server to broadcast its presence via Bonjour. 22 | // This allows browsers such as Safari to automatically discover our service. 23 | [httpServer setType:@"_http._tcp."]; 24 | 25 | // Normally there's no need to run our server on any specific port. 26 | // Technologies like Bonjour allow clients to dynamically discover the server's port at runtime. 27 | // However, for easy testing you may want force a certain port so you can just hit the refresh button. 28 | // [httpServer setPort:12345]; 29 | 30 | // Serve files from the standard Sites folder 31 | NSString *docRoot = [@"~/Sites" stringByExpandingTildeInPath]; 32 | DDLogInfo(@"Setting document root: %@", docRoot); 33 | 34 | [httpServer setDocumentRoot:docRoot]; 35 | 36 | NSError *error = nil; 37 | if(![httpServer start:&error]) 38 | { 39 | DDLogError(@"Error starting HTTP Server: %@", error); 40 | } 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Core/Categories/DDNumber.m: -------------------------------------------------------------------------------- 1 | #import "DDNumber.h" 2 | 3 | 4 | @implementation NSNumber (DDNumber) 5 | 6 | + (BOOL)parseString:(NSString *)str intoSInt64:(SInt64 *)pNum 7 | { 8 | if(str == nil) 9 | { 10 | *pNum = 0; 11 | return NO; 12 | } 13 | 14 | errno = 0; 15 | 16 | // On both 32-bit and 64-bit machines, long long = 64 bit 17 | 18 | *pNum = strtoll([str UTF8String], NULL, 10); 19 | 20 | if(errno != 0) 21 | return NO; 22 | else 23 | return YES; 24 | } 25 | 26 | + (BOOL)parseString:(NSString *)str intoUInt64:(UInt64 *)pNum 27 | { 28 | if(str == nil) 29 | { 30 | *pNum = 0; 31 | return NO; 32 | } 33 | 34 | errno = 0; 35 | 36 | // On both 32-bit and 64-bit machines, unsigned long long = 64 bit 37 | 38 | *pNum = strtoull([str UTF8String], NULL, 10); 39 | 40 | if(errno != 0) 41 | return NO; 42 | else 43 | return YES; 44 | } 45 | 46 | + (BOOL)parseString:(NSString *)str intoNSInteger:(NSInteger *)pNum 47 | { 48 | if(str == nil) 49 | { 50 | *pNum = 0; 51 | return NO; 52 | } 53 | 54 | errno = 0; 55 | 56 | // On LP64, NSInteger = long = 64 bit 57 | // Otherwise, NSInteger = int = long = 32 bit 58 | 59 | *pNum = strtol([str UTF8String], NULL, 10); 60 | 61 | if(errno != 0) 62 | return NO; 63 | else 64 | return YES; 65 | } 66 | 67 | + (BOOL)parseString:(NSString *)str intoNSUInteger:(NSUInteger *)pNum 68 | { 69 | if(str == nil) 70 | { 71 | *pNum = 0; 72 | return NO; 73 | } 74 | 75 | errno = 0; 76 | 77 | // On LP64, NSUInteger = unsigned long = 64 bit 78 | // Otherwise, NSUInteger = unsigned int = unsigned long = 32 bit 79 | 80 | *pNum = strtoul([str UTF8String], NULL, 10); 81 | 82 | if(errno != 0) 83 | return NO; 84 | else 85 | return YES; 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /Samples/SimpleFileUploadServer/SimpleFileUploadServer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import "HTTPServer.h" 3 | #import "DDLog.h" 4 | #import "DDTTYLogger.h" 5 | #import "MyHTTPConnection.h" 6 | // Log levels: off, error, warn, info, verbose 7 | static const int ddLogLevel = LOG_LEVEL_VERBOSE; 8 | 9 | 10 | @implementation AppDelegate 11 | 12 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 13 | { 14 | // Configure our logging framework. 15 | // To keep things simple and fast, we're just going to log to the Xcode console. 16 | [DDLog addLogger:[DDTTYLogger sharedInstance]]; 17 | 18 | // Initalize our http server 19 | httpServer = [[HTTPServer alloc] init]; 20 | 21 | // Tell the server to broadcast its presence via Bonjour. 22 | // This allows browsers such as Safari to automatically discover our service. 23 | [httpServer setType:@"_http._tcp."]; 24 | 25 | // Normally there's no need to run our server on any specific port. 26 | // Technologies like Bonjour allow clients to dynamically discover the server's port at runtime. 27 | // However, for easy testing you may want force a certain port so you can just hit the refresh button. 28 | // [httpServer setPort:12345]; 29 | 30 | // Serve files from the standard Sites folder 31 | NSString *docRoot = [[[NSBundle mainBundle] pathForResource:@"index" ofType:@"html" inDirectory:@"web"] stringByDeletingLastPathComponent]; 32 | DDLogInfo(@"Setting document root: %@", docRoot); 33 | 34 | [httpServer setDocumentRoot:docRoot]; 35 | 36 | [httpServer setConnectionClass:[MyHTTPConnection class]]; 37 | 38 | NSError *error = nil; 39 | if(![httpServer start:&error]) 40 | { 41 | DDLogError(@"Error starting HTTP Server: %@", error); 42 | } 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Samples/SecureHTTPServer/README.markdown: -------------------------------------------------------------------------------- 1 | INFO: 2 | 3 | The SecureHTTPServer examples demonstrates creating a HTTPS server. 4 | 5 | In order to do this, all connections must be secured using SSL/TLS. 6 | And in order to do that, you need to have a X509 certificate. 7 | Normally you PAY MONEY for these. 8 | For example, you purchase them via Verisign. 9 | However, for our example we're going to create a self-signed certificate. 10 | 11 | This means that when you browse the server in Safari, it may present a warning saying the certificate is untrusted. (Which makes sense since you didn't pay money to a trusted 3rd party certificate agency.) To make things easier for testing, when Safari presents this warning, click the "show certificate" button. And then click the "always trust this certificate" button. 12 | 13 | Also, the first time you run the server, it will automatically create a self-signed certificate and add it to your keychain (under the name SecureHTTPServer). Now the SecureHTTPServer is authorized to access this keychain item - unless of course the binary changes. So if you make changes, or simply switch between debug/release builds, you'll keep getting prompted by the Keychain utility. To solve this problem, open the Keychain Access application. Find the "SecureHTTPServer" private key, and change it's Access Control to "Allow all applications to access this item". 14 | 15 | INSTRUCTIONS: 16 | 17 | Open the Xcode project, and build and go. 18 | 19 | On the Xcode console you'll see a message saying: 20 | "Started HTTP server on port 59123" 21 | 22 | Now open your browser and type in the URL: 23 | https://localhost:59123 24 | 25 | Notice that you're using "https" and not "http". 26 | 27 | (Replace 59123 with whatever port the server is actually running on.) 28 | 29 | Enjoy. -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # CocoaHTTPServer 2 | 3 | [![Build Status](https://travis-ci.org/robbiehanson/CocoaHTTPServer.svg)](https://travis-ci.org/robbiehanson/CocoaHTTPServer) 4 | [![Version](http://img.shields.io/cocoapods/v/CocoaHTTPServer.svg?style=flat)](http://cocoapods.org/?q=CocoaHTTPServer) 5 | [![Platform](http://img.shields.io/cocoapods/p/CocoaHTTPServer.svg?style=flat)]() 6 | [![License](http://img.shields.io/cocoapods/l/CocoaHTTPServer.svg?style=flat)](https://github.com/robbiehanson/CocoaHTTPServer/blob/master/LICENSE) 7 | 8 | CocoaHTTPServer is a small, lightweight, embeddable HTTP server for Mac OS X or iOS applications. 9 | 10 | Sometimes developers need an embedded HTTP server in their app. Perhaps it's a server application with remote monitoring. Or perhaps it's a desktop application using HTTP for the communication backend. Or perhaps it's an iOS app providing over-the-air access to documents. Whatever your reason, CocoaHTTPServer can get the job done. It provides: 11 | 12 | - Built in support for bonjour broadcasting 13 | - IPv4 and IPv6 support 14 | - Asynchronous networking using GCD and standard sockets 15 | - Password protection support 16 | - SSL/TLS encryption support 17 | - Extremely FAST and memory efficient 18 | - Extremely scalable (built entirely upon GCD) 19 | - Heavily commented code 20 | - Very easily extensible 21 | - WebDAV is supported too! 22 | 23 |
24 | Can't find the answer to your question in any of the [wiki](https://github.com/robbiehanson/CocoaHTTPServer/wiki) articles? Try the **[mailing list](http://groups.google.com/group/cocoahttpserver)**. 25 |
26 |
27 | Love the project? Wanna buy me a coffee? (or a beer :D) [![donation](http://www.paypal.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=BHF2DJRETGV5S) 28 | -------------------------------------------------------------------------------- /Samples/PasswdHTTPServer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import "HTTPServer.h" 3 | #import "MyHTTPConnection.h" 4 | #import "DDLog.h" 5 | #import "DDTTYLogger.h" 6 | 7 | // Log levels: off, error, warn, info, verbose 8 | static const int ddLogLevel = LOG_LEVEL_VERBOSE; 9 | 10 | 11 | @implementation AppDelegate 12 | 13 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 14 | { 15 | // Configure our logging framework. 16 | // To keep things simple and fast, we're just going to log to the Xcode console. 17 | [DDLog addLogger:[DDTTYLogger sharedInstance]]; 18 | 19 | // Initalize our http server 20 | httpServer = [[HTTPServer alloc] init]; 21 | 22 | // Tell the server to broadcast its presence via Bonjour. 23 | // This allows browsers such as Safari to automatically discover our service. 24 | [httpServer setType:@"_http._tcp."]; 25 | 26 | // Normally there's no need to run our server on any specific port. 27 | // Technologies like Bonjour allow clients to dynamically discover the server's port at runtime. 28 | // However, for easy testing you may want force a certain port so you can just hit the refresh button. 29 | // [httpServer setPort:12345]; 30 | 31 | // We're going to extend the base HTTPConnection class with our MyHTTPConnection class. 32 | // This allows us to do custom password protection on our sensitive directories. 33 | [httpServer setConnectionClass:[MyHTTPConnection class]]; 34 | 35 | // Serve files from the standard Sites folder 36 | NSString *docRoot = [@"~/Sites" stringByExpandingTildeInPath]; 37 | DDLogInfo(@"Setting document root: %@", docRoot); 38 | 39 | [httpServer setDocumentRoot:docRoot]; 40 | 41 | NSError *error = nil; 42 | if (![httpServer start:&error]) 43 | { 44 | DDLogError(@"Error starting HTTP Server: %@", error); 45 | } 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Samples/PostHTTPServer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import "HTTPServer.h" 3 | #import "MyHTTPConnection.h" 4 | #import "DDLog.h" 5 | #import "DDTTYLogger.h" 6 | 7 | // Log levels: off, error, warn, info, verbose 8 | static const int ddLogLevel = LOG_LEVEL_VERBOSE; 9 | 10 | 11 | @implementation AppDelegate 12 | 13 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 14 | { 15 | // Configure our logging framework. 16 | // To keep things simple and fast, we're just going to log to the Xcode console. 17 | [DDLog addLogger:[DDTTYLogger sharedInstance]]; 18 | 19 | // Initalize our http server 20 | httpServer = [[HTTPServer alloc] init]; 21 | 22 | // Tell the server to broadcast its presence via Bonjour. 23 | // This allows browsers such as Safari to automatically discover our service. 24 | [httpServer setType:@"_http._tcp."]; 25 | 26 | // Normally there's no need to run our server on any specific port. 27 | // Technologies like Bonjour allow clients to dynamically discover the server's port at runtime. 28 | // However, for easy testing you may want force a certain port so you can just hit the refresh button. 29 | // [httpServer setPort:12345]; 30 | 31 | // We're going to extend the base HTTPConnection class with our MyHTTPConnection class. 32 | // This allows us to do all kinds of customizations. 33 | [httpServer setConnectionClass:[MyHTTPConnection class]]; 34 | 35 | // Serve files from our embedded Web folder 36 | NSString *webPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Web"]; 37 | DDLogInfo(@"Setting document root: %@", webPath); 38 | 39 | [httpServer setDocumentRoot:webPath]; 40 | 41 | 42 | NSError *error = nil; 43 | if(![httpServer start:&error]) 44 | { 45 | DDLogError(@"Error starting HTTP Server: %@", error); 46 | } 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Samples/README.markdown: -------------------------------------------------------------------------------- 1 | Welcome to CocoaHTTPServer! 2 | 3 | This project provides you (the developer) with an embedded HTTP server. It was built using standard networking sockets and streams, and offers a wealth of features for your app: 4 | 5 | - Built in support for bonjour broadcasting 6 | - IPv4 and IPv6 support automatically 7 | - Asynchronous networking 8 | - Multithreading support 9 | - Password protection using either digest access or basic authentication 10 | - TLS/SSL encryption support 11 | - Range request support for partial downloads and pause/resume 12 | - Support for LARGE files (up to 16 exabytes) 13 | - Heavily commented code 14 | 15 | As is the nature of embedded servers, you probably want to do something cool with it. Perhaps you simply want to serve up files, but maybe you want to provide dynamic content or allow user uploads. No problem - you can use this code to do any/all of these tasks. 16 | 17 | The suggested way to implement your custom server is by extending the HTTPServer and/or HTTPConnection classes. You'll find several methods in these classes with documentation that says "override me to add support for..." For example, if you wanted to add password protection to various resources, simply override the "isPasswordProtected" and "passwordForUser" methods. 18 | 19 | If you have questions, you may email the mailing list: 20 | http://groups.google.com/group/cocoahttpserver 21 | 22 | PLEASE NOTE: 23 | 24 | All sample xcode projects are simple examples of how to accomplish some task using CocoaHTTPServer. 25 | 26 | Don't forget to use source control to stay up-to-date with the latest version of the code. 27 | 28 | If you've implemented your custom server by extending the HTTPServer and HTTPConnection classes, it should be relatively easy to merge the latest improvements from subversion into your project. 29 | 30 | -------------------------------------------------------------------------------- /Core/Responses/HTTPDynamicFileResponse.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPResponse.h" 3 | #import "HTTPAsyncFileResponse.h" 4 | 5 | /** 6 | * This class is designed to assist with dynamic content. 7 | * Imagine you have a file that you want to make dynamic: 8 | * 9 | * 10 | * 11 | *

ComputerName Control Panel

12 | * ... 13 | *
  • System Time: SysTime
  • 14 | * 15 | * 16 | * 17 | * Now you could generate the entire file in Objective-C, 18 | * but this would be a horribly tedious process. 19 | * Beside, you want to design the file with professional tools to make it look pretty. 20 | * 21 | * So all you have to do is escape your dynamic content like this: 22 | * 23 | * ... 24 | *

    %%ComputerName%% Control Panel

    25 | * ... 26 | *
  • System Time: %%SysTime%%
  • 27 | * 28 | * And then you create an instance of this class with: 29 | * 30 | * - separator = @"%%" 31 | * - replacementDictionary = { "ComputerName"="Black MacBook", "SysTime"="2010-04-30 03:18:24" } 32 | * 33 | * This class will then perform the replacements for you, on the fly, as it reads the file data. 34 | * This class is also asynchronous, so it will perform the file IO using its own GCD queue. 35 | * 36 | * All keys for the replacementDictionary must be NSString's. 37 | * Values for the replacementDictionary may be NSString's, or any object that 38 | * returns what you want when its description method is invoked. 39 | **/ 40 | 41 | @interface HTTPDynamicFileResponse : HTTPAsyncFileResponse 42 | { 43 | NSData *separator; 44 | NSDictionary *replacementDict; 45 | } 46 | 47 | - (id)initWithFilePath:(NSString *)filePath 48 | forConnection:(HTTPConnection *)connection 49 | separator:(NSString *)separatorStr 50 | replacementDictionary:(NSDictionary *)dictionary; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Core/Categories/DDRange.h: -------------------------------------------------------------------------------- 1 | /** 2 | * DDRange is the functional equivalent of a 64 bit NSRange. 3 | * The HTTP Server is designed to support very large files. 4 | * On 32 bit architectures (ppc, i386) NSRange uses unsigned 32 bit integers. 5 | * This only supports a range of up to 4 gigabytes. 6 | * By defining our own variant, we can support a range up to 16 exabytes. 7 | * 8 | * All effort is given such that DDRange functions EXACTLY the same as NSRange. 9 | **/ 10 | 11 | #import 12 | #import 13 | 14 | @class NSString; 15 | 16 | typedef struct _DDRange { 17 | UInt64 location; 18 | UInt64 length; 19 | } DDRange; 20 | 21 | typedef DDRange *DDRangePointer; 22 | 23 | NS_INLINE DDRange DDMakeRange(UInt64 loc, UInt64 len) { 24 | DDRange r; 25 | r.location = loc; 26 | r.length = len; 27 | return r; 28 | } 29 | 30 | NS_INLINE UInt64 DDMaxRange(DDRange range) { 31 | return (range.location + range.length); 32 | } 33 | 34 | NS_INLINE BOOL DDLocationInRange(UInt64 loc, DDRange range) { 35 | return (loc - range.location < range.length); 36 | } 37 | 38 | NS_INLINE BOOL DDEqualRanges(DDRange range1, DDRange range2) { 39 | return ((range1.location == range2.location) && (range1.length == range2.length)); 40 | } 41 | 42 | FOUNDATION_EXPORT DDRange DDUnionRange(DDRange range1, DDRange range2); 43 | FOUNDATION_EXPORT DDRange DDIntersectionRange(DDRange range1, DDRange range2); 44 | FOUNDATION_EXPORT NSString *DDStringFromRange(DDRange range); 45 | FOUNDATION_EXPORT DDRange DDRangeFromString(NSString *aString); 46 | 47 | NSInteger DDRangeCompare(DDRangePointer pDDRange1, DDRangePointer pDDRange2); 48 | 49 | @interface NSValue (NSValueDDRangeExtensions) 50 | 51 | + (NSValue *)valueWithDDRange:(DDRange)range; 52 | - (DDRange)ddrangeValue; 53 | 54 | - (NSInteger)ddrangeCompare:(NSValue *)ddrangeValue; 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /Samples/DynamicServer/DynamicServerAppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "DynamicServerAppDelegate.h" 2 | #import "HTTPServer.h" 3 | #import "MyHTTPConnection.h" 4 | #import "DDLog.h" 5 | #import "DDTTYLogger.h" 6 | 7 | // Log levels: off, error, warn, info, verbose 8 | static const int ddLogLevel = LOG_LEVEL_VERBOSE; 9 | 10 | 11 | @implementation DynamicServerAppDelegate 12 | 13 | @synthesize window; 14 | 15 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 16 | { 17 | // Configure our logging framework. 18 | // To keep things simple and fast, we're just going to log to the Xcode console. 19 | [DDLog addLogger:[DDTTYLogger sharedInstance]]; 20 | 21 | // Initalize our http server 22 | httpServer = [[HTTPServer alloc] init]; 23 | 24 | // Tell server to use our custom MyHTTPConnection class. 25 | [httpServer setConnectionClass:[MyHTTPConnection class]]; 26 | 27 | // Tell the server to broadcast its presence via Bonjour. 28 | // This allows browsers such as Safari to automatically discover our service. 29 | [httpServer setType:@"_http._tcp."]; 30 | 31 | // Normally there's no need to run our server on any specific port. 32 | // Technologies like Bonjour allow clients to dynamically discover the server's port at runtime. 33 | // However, for easy testing you may want force a certain port so you can just hit the refresh button. 34 | // [httpServer setPort:12345]; 35 | 36 | // Serve files from our embedded Web folder 37 | NSString *webPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Web"]; 38 | DDLogVerbose(@"Setting document root: %@", webPath); 39 | 40 | [httpServer setDocumentRoot:webPath]; 41 | 42 | // Start the server (and check for problems) 43 | 44 | NSError *error; 45 | BOOL success = [httpServer start:&error]; 46 | 47 | if(!success) 48 | { 49 | DDLogError(@"Error starting HTTP Server: %@", error); 50 | } 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /Core/Responses/HTTPDataResponse.m: -------------------------------------------------------------------------------- 1 | #import "HTTPDataResponse.h" 2 | #import "HTTPLogging.h" 3 | 4 | #if ! __has_feature(objc_arc) 5 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 6 | #endif 7 | 8 | // Log levels : off, error, warn, info, verbose 9 | // Other flags: trace 10 | static const int httpLogLevel = HTTP_LOG_LEVEL_OFF; // | HTTP_LOG_FLAG_TRACE; 11 | 12 | 13 | @implementation HTTPDataResponse 14 | 15 | - (id)initWithData:(NSData *)dataParam 16 | { 17 | if((self = [super init])) 18 | { 19 | HTTPLogTrace(); 20 | 21 | offset = 0; 22 | data = dataParam; 23 | } 24 | return self; 25 | } 26 | 27 | - (void)dealloc 28 | { 29 | HTTPLogTrace(); 30 | 31 | } 32 | 33 | - (UInt64)contentLength 34 | { 35 | UInt64 result = (UInt64)[data length]; 36 | 37 | HTTPLogTrace2(@"%@[%p]: contentLength - %llu", THIS_FILE, self, result); 38 | 39 | return result; 40 | } 41 | 42 | - (UInt64)offset 43 | { 44 | HTTPLogTrace(); 45 | 46 | return offset; 47 | } 48 | 49 | - (void)setOffset:(UInt64)offsetParam 50 | { 51 | HTTPLogTrace2(@"%@[%p]: setOffset:%lu", THIS_FILE, self, (unsigned long)offset); 52 | 53 | offset = (NSUInteger)offsetParam; 54 | } 55 | 56 | - (NSData *)readDataOfLength:(NSUInteger)lengthParameter 57 | { 58 | HTTPLogTrace2(@"%@[%p]: readDataOfLength:%lu", THIS_FILE, self, (unsigned long)lengthParameter); 59 | 60 | NSUInteger remaining = [data length] - offset; 61 | NSUInteger length = lengthParameter < remaining ? lengthParameter : remaining; 62 | 63 | void *bytes = (void *)([data bytes] + offset); 64 | 65 | offset += length; 66 | 67 | return [NSData dataWithBytesNoCopy:bytes length:length freeWhenDone:NO]; 68 | } 69 | 70 | - (BOOL)isDone 71 | { 72 | BOOL result = (offset == [data length]); 73 | 74 | HTTPLogTrace2(@"%@[%p]: isDone - %@", THIS_FILE, self, (result ? @"YES" : @"NO")); 75 | 76 | return result; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/SimpleWebSocketServerAppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "SimpleWebSocketServerAppDelegate.h" 2 | #import "HTTPServer.h" 3 | #import "MyHTTPConnection.h" 4 | #import "DDLog.h" 5 | #import "DDTTYLogger.h" 6 | 7 | // Log levels: off, error, warn, info, verbose 8 | static const int ddLogLevel = LOG_LEVEL_VERBOSE; 9 | 10 | 11 | @implementation SimpleWebSocketServerAppDelegate 12 | 13 | @synthesize window; 14 | 15 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 16 | { 17 | // Configure our logging framework. 18 | // To keep things simple and fast, we're just going to log to the Xcode console. 19 | [DDLog addLogger:[DDTTYLogger sharedInstance]]; 20 | 21 | // Create server using our custom MyHTTPServer class 22 | httpServer = [[HTTPServer alloc] init]; 23 | 24 | // Tell server to use our custom MyHTTPConnection class. 25 | [httpServer setConnectionClass:[MyHTTPConnection class]]; 26 | 27 | // Tell the server to broadcast its presence via Bonjour. 28 | // This allows browsers such as Safari to automatically discover our service. 29 | [httpServer setType:@"_http._tcp."]; 30 | 31 | // Normally there's no need to run our server on any specific port. 32 | // Technologies like Bonjour allow clients to dynamically discover the server's port at runtime. 33 | // However, for easy testing you may want force a certain port so you can just hit the refresh button. 34 | // [httpServer setPort:12345]; 35 | 36 | // Serve files from our embedded Web folder 37 | NSString *webPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Web"]; 38 | DDLogInfo(@"Setting document root: %@", webPath); 39 | 40 | [httpServer setDocumentRoot:webPath]; 41 | 42 | // Start the server (and check for problems) 43 | 44 | NSError *error; 45 | if(![httpServer start:&error]) 46 | { 47 | DDLogError(@"Error starting HTTP Server: %@", error); 48 | } 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/SecureWebSocketServerAppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "SecureWebSocketServerAppDelegate.h" 2 | #import "HTTPServer.h" 3 | #import "MyHTTPConnection.h" 4 | #import "DDLog.h" 5 | #import "DDTTYLogger.h" 6 | 7 | // Log levels: off, error, warn, info, verbose 8 | static const int ddLogLevel = LOG_LEVEL_VERBOSE; 9 | 10 | 11 | @implementation SecureWebSocketServerAppDelegate 12 | 13 | @synthesize window; 14 | 15 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 16 | { 17 | // Configure our logging framework. 18 | // To keep things simple and fast, we're just going to log to the Xcode console. 19 | [DDLog addLogger:[DDTTYLogger sharedInstance]]; 20 | 21 | // Create server using our custom MyHTTPServer class 22 | httpServer = [[HTTPServer alloc] init]; 23 | 24 | // Tell server to use our custom MyHTTPConnection class. 25 | [httpServer setConnectionClass:[MyHTTPConnection class]]; 26 | 27 | // Tell the server to broadcast its presence via Bonjour. 28 | // This allows browsers such as Safari to automatically discover our service. 29 | [httpServer setType:@"_http._tcp."]; 30 | 31 | // Normally there's no need to run our server on any specific port. 32 | // Technologies like Bonjour allow clients to dynamically discover the server's port at runtime. 33 | // However, for easy testing you may want force a certain port so you can just hit the refresh button. 34 | // [httpServer setPort:12345]; 35 | 36 | // Serve files from our embedded Web folder 37 | NSString *webPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Web"]; 38 | DDLogInfo(@"Setting document root: %@", webPath); 39 | 40 | [httpServer setDocumentRoot:webPath]; 41 | 42 | // Start the server (and check for problems) 43 | 44 | NSError *error; 45 | if(![httpServer start:&error]) 46 | { 47 | DDLogError(@"Error starting HTTP Server: %@", error); 48 | } 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Samples/SecureHTTPServer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import "HTTPServer.h" 3 | #import "MyHTTPConnection.h" 4 | #import "DDLog.h" 5 | #import "DDTTYLogger.h" 6 | 7 | // Log levels: off, error, warn, info, verbose 8 | static const int ddLogLevel = LOG_LEVEL_VERBOSE; 9 | 10 | 11 | @implementation AppDelegate 12 | 13 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 14 | { 15 | // Configure our logging framework. 16 | // To keep things simple and fast, we're just going to log to the Xcode console. 17 | [DDLog addLogger:[DDTTYLogger sharedInstance]]; 18 | 19 | // Initalize our http server 20 | httpServer = [[HTTPServer alloc] init]; 21 | 22 | // Tell the server to broadcast its presence via Bonjour. 23 | // This allows browsers such as Safari to automatically discover our service. 24 | // [httpServer setType:@"_http._tcp."]; 25 | 26 | // Note: Clicking the bonjour service in Safari won't work because Safari will use http and not https. 27 | // Just change the url to https for proper access. 28 | 29 | // Normally there's no need to run our server on any specific port. 30 | // Technologies like Bonjour allow clients to dynamically discover the server's port at runtime. 31 | // However, for easy testing you may want force a certain port so you can just hit the refresh button. 32 | // [httpServer setPort:12345]; 33 | 34 | // We're going to extend the base HTTPConnection class with our MyHTTPConnection class. 35 | // This allows us to customize the server for things such as SSL and password-protection. 36 | [httpServer setConnectionClass:[MyHTTPConnection class]]; 37 | 38 | // Serve files from the standard Sites folder 39 | NSString *docRoot = [@"~/Sites" stringByExpandingTildeInPath]; 40 | DDLogInfo(@"Setting document root: %@", docRoot); 41 | 42 | [httpServer setDocumentRoot:docRoot]; 43 | 44 | NSError *error = nil; 45 | if(![httpServer start:&error]) 46 | { 47 | DDLogError(@"Error starting HTTP Server: %@", error); 48 | } 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Extensions/WebDAV/PUTResponse.m: -------------------------------------------------------------------------------- 1 | #import "PUTResponse.h" 2 | #import "HTTPLogging.h" 3 | 4 | // HTTP methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html 5 | // HTTP headers: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html 6 | // HTTP status codes: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 7 | 8 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN; 9 | 10 | @implementation PUTResponse 11 | 12 | - (id) initWithFilePath:(NSString*)path headers:(NSDictionary*)headers body:(id)body { 13 | if ((self = [super init])) { 14 | if ([headers objectForKey:@"Content-Range"]) { 15 | HTTPLogError(@"Content-Range not supported for upload to \"%@\"", path); 16 | _status = 400; 17 | } else { 18 | BOOL overwrite = [[NSFileManager defaultManager] fileExistsAtPath:path]; 19 | BOOL success; 20 | if ([body isKindOfClass:[NSString class]]) { 21 | [[NSFileManager defaultManager] removeItemAtPath:path error:NULL]; 22 | success = [[NSFileManager defaultManager] moveItemAtPath:body toPath:path error:NULL]; 23 | } else { 24 | success = [body writeToFile:path atomically:YES]; 25 | } 26 | if (success) { 27 | _status = overwrite ? 200 : 201; 28 | } else { 29 | HTTPLogError(@"Failed writing upload to \"%@\"", path); 30 | _status = 403; 31 | } 32 | } 33 | } 34 | return self; 35 | } 36 | 37 | - (id) initWithFilePath:(NSString*)path headers:(NSDictionary*)headers bodyData:(NSData*)body { 38 | return [self initWithFilePath:path headers:headers body:body]; 39 | } 40 | 41 | - (id) initWithFilePath:(NSString*)path headers:(NSDictionary*)headers bodyFile:(NSString*)body { 42 | return [self initWithFilePath:path headers:headers body:body]; 43 | } 44 | 45 | - (UInt64) contentLength { 46 | return 0; 47 | } 48 | 49 | - (UInt64) offset { 50 | return 0; 51 | } 52 | 53 | - (void) setOffset:(UInt64)offset { 54 | ; 55 | } 56 | 57 | - (NSData*) readDataOfLength:(NSUInteger)length { 58 | return nil; 59 | } 60 | 61 | - (BOOL) isDone { 62 | return YES; 63 | } 64 | 65 | - (NSInteger) status { 66 | return _status; 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/README.markdown: -------------------------------------------------------------------------------- 1 | INFO: 2 | 3 | The SecureWebSocketServer examples demonstrates two technologies: 4 | - Creating a HTTPS server 5 | - WebSockets 6 | 7 | To create a secure HTTPS server, all connections must be secured using SSL/TLS. 8 | And in order to do that, you need to have a X509 certificate. 9 | Normally you PAY MONEY for these. 10 | For example, you purchase them via Verisign. 11 | However, for our example we're going to create a self-signed certificate. 12 | 13 | This means that when you browse the server in Safari, it may present a warning saying the certificate is untrusted. (Which makes sense since you didn't pay money to a trusted 3rd party certificate agency.) To make things easier for testing, when Safari presents this warning, click the "show certificate" button. And then click the "always trust this certificate" button. 14 | 15 | Also, the first time you run the server, it will automatically create a self-signed certificate and add it to your keychain (under the name SecureHTTPServer). Now the SecureHTTPServer is authorized to access this keychain item - unless of course the binary changes. So if you make changes, or simply switch between debug/release builds, you'll keep getting prompted by the Keychain utility. To solve this problem, open the Keychain Access application. Find the "SecureHTTPServer" private key, and change it's Access Control to "Allow all applications to access this item". 16 | 17 | The sample includes a Web folder which is added to the project, copied into the application's resources folder, and is set as the document root of the http server. It contains a simple index.html file and the client-side code (run in the web browser) for the websocket stuff. 18 | 19 | It is fairly straight-forward. It will query the server for the time every second, and present the result on the page. 20 | 21 | Take a look at the MyWebSocket class to see the related server code. 22 | 23 | INSTRUCTIONS: 24 | 25 | Open the Xcode project, and build and go. 26 | 27 | On the Xcode console you'll see a message saying: 28 | "Started HTTP server on port 59123" 29 | 30 | Now open a browser that supports WebSockets (e.g. Google Chrome or Safari) 31 | and type in the URL: 32 | https://localhost:59123 33 | 34 | Notice that you're using "https" and not "http". 35 | 36 | (Replace 59123 with whatever port the server is actually running on.) 37 | 38 | Enjoy. -------------------------------------------------------------------------------- /Vendor/CocoaLumberjack/About.txt: -------------------------------------------------------------------------------- 1 | CocoaLumberjack is under the New BSD License. 2 | https://github.com/robbiehanson/CocoaLumberjack 3 | 4 | Extensive documentation, tutorials, etc are available: 5 | https://github.com/robbiehanson/CocoaLumberjack/wiki 6 | 7 | Overview of the project (copied from google code homepage): 8 | 9 | 10 | 11 | The lumberjack framework is fast & simple, yet powerful & flexible. 12 | It is similar in concept to other popular logging frameworks such as log4j, yet is designed specifically for objective-c, and takes advantage of features such as multi-threading, grand central dispatch (if available), lockless atomic operations, and the dynamic nature of the objective-c runtime. 13 | 14 | Lumberjack is fast: 15 | In most cases it is an order of magnitude faster than NSLog. 16 | 17 | Lumberjack is simple: 18 | It takes as little as a single line of code to configure lumberjack when your application launches. Then simply replace your NSLog statements with DDLog statements and that's about it. (And the DDLog macros have the exact same format and syntax as NSLog, so it's super easy.) 19 | 20 | Lumberjack is powerful: 21 | One log statement can be sent to multiple loggers, meaning you can log to a file and the console simultaneously. Want more? Create your own loggers (it's easy) and send your log statements over the network. Or to a database or distributed file system. The sky is the limit. 22 | 23 | Lumberjack is flexible: 24 | Configure your logging however you want. Change log levels per file (perfect for debugging). Change log levels per logger (verbose console, but concise log file). Change log levels per xcode configuration (verbose debug, but concise release). Have your log statements compiled out of the release build. Customize the number of log levels for your application. Add your own fine-grained logging. Dynamically change log levels during runtime. Choose how & when you want your log files to be rolled. Upload your log files to a central server. Compress archived log files to save disk space... 25 | 26 | 27 | 28 | This framework is for you if: 29 | 30 | You're looking for a way to track down that impossible-to-reproduce bug that keeps popping up in the field. 31 | You're frustrated with the super short console log on the iPhone. 32 | You're looking to take your application to the next level in terms of support and stability. 33 | You're looking for an enterprise level logging solution for your application (Mac or iPhone). -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/MyHTTPConnection.m: -------------------------------------------------------------------------------- 1 | #import "MyHTTPConnection.h" 2 | #import "HTTPMessage.h" 3 | #import "HTTPResponse.h" 4 | #import "HTTPDynamicFileResponse.h" 5 | #import "GCDAsyncSocket.h" 6 | #import "MyWebSocket.h" 7 | #import "HTTPLogging.h" 8 | 9 | // Log levels: off, error, warn, info, verbose 10 | // Other flags: trace 11 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN; // | HTTP_LOG_FLAG_TRACE; 12 | 13 | 14 | @implementation MyHTTPConnection 15 | 16 | - (NSObject *)httpResponseForMethod:(NSString *)method URI:(NSString *)path 17 | { 18 | HTTPLogTrace(); 19 | 20 | if ([path isEqualToString:@"/WebSocketTest2.js"]) 21 | { 22 | // The socket.js file contains a URL template that needs to be completed: 23 | // 24 | // ws = new WebSocket("%%WEBSOCKET_URL%%"); 25 | // 26 | // We need to replace "%%WEBSOCKET_URL%%" with whatever URL the server is running on. 27 | // We can accomplish this easily with the HTTPDynamicFileResponse class, 28 | // which takes a dictionary of replacement key-value pairs, 29 | // and performs replacements on the fly as it uploads the file. 30 | 31 | NSString *wsLocation; 32 | 33 | NSString *wsHost = [request headerField:@"Host"]; 34 | if (wsHost == nil) 35 | { 36 | NSString *port = [NSString stringWithFormat:@"%hu", [asyncSocket localPort]]; 37 | wsLocation = [NSString stringWithFormat:@"ws://localhost:%@/service", port]; 38 | } 39 | else 40 | { 41 | wsLocation = [NSString stringWithFormat:@"ws://%@/service", wsHost]; 42 | } 43 | 44 | NSDictionary *replacementDict = [NSDictionary dictionaryWithObject:wsLocation forKey:@"WEBSOCKET_URL"]; 45 | 46 | return [[HTTPDynamicFileResponse alloc] initWithFilePath:[self filePathForURI:path] 47 | forConnection:self 48 | separator:@"%%" 49 | replacementDictionary:replacementDict]; 50 | } 51 | 52 | return [super httpResponseForMethod:method URI:path]; 53 | } 54 | 55 | - (WebSocket *)webSocketForURI:(NSString *)path 56 | { 57 | HTTPLogTrace2(@"%@[%p]: webSocketForURI: %@", THIS_FILE, self, path); 58 | 59 | if([path isEqualToString:@"/service"]) 60 | { 61 | HTTPLogInfo(@"MyHTTPConnection: Creating MyWebSocket..."); 62 | 63 | return [[MyWebSocket alloc] initWithRequest:request socket:asyncSocket]; 64 | } 65 | 66 | return [super webSocketForURI:path]; 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /Core/Mime/MultipartFormDataParser.h: -------------------------------------------------------------------------------- 1 | 2 | #import "MultipartMessageHeader.h" 3 | 4 | /* 5 | Part one: http://tools.ietf.org/html/rfc2045 (Format of Internet Message Bodies) 6 | Part two: http://tools.ietf.org/html/rfc2046 (Media Types) 7 | Part three: http://tools.ietf.org/html/rfc2047 (Message Header Extensions for Non-ASCII Text) 8 | Part four: http://tools.ietf.org/html/rfc4289 (Registration Procedures) 9 | Part five: http://tools.ietf.org/html/rfc2049 (Conformance Criteria and Examples) 10 | 11 | Internet message format: http://tools.ietf.org/html/rfc2822 12 | 13 | Multipart/form-data http://tools.ietf.org/html/rfc2388 14 | */ 15 | 16 | @class MultipartFormDataParser; 17 | 18 | //----------------------------------------------------------------- 19 | // protocol MultipartFormDataParser 20 | //----------------------------------------------------------------- 21 | 22 | @protocol MultipartFormDataParserDelegate 23 | @optional 24 | - (void) processContent:(NSData*) data WithHeader:(MultipartMessageHeader*) header; 25 | - (void) processEndOfPartWithHeader:(MultipartMessageHeader*) header; 26 | - (void) processPreambleData:(NSData*) data; 27 | - (void) processEpilogueData:(NSData*) data; 28 | - (void) processStartOfPartWithHeader:(MultipartMessageHeader*) header; 29 | @end 30 | 31 | //----------------------------------------------------------------- 32 | // interface MultipartFormDataParser 33 | //----------------------------------------------------------------- 34 | 35 | @interface MultipartFormDataParser : NSObject { 36 | NSMutableData* pendingData; 37 | NSData* boundaryData; 38 | MultipartMessageHeader* currentHeader; 39 | 40 | BOOL waitingForCRLF; 41 | BOOL reachedEpilogue; 42 | BOOL processedPreamble; 43 | BOOL checkForContentEnd; 44 | 45 | #if __has_feature(objc_arc_weak) 46 | __weak id delegate; 47 | #else 48 | __unsafe_unretained id delegate; 49 | #endif 50 | int currentEncoding; 51 | NSStringEncoding formEncoding; 52 | } 53 | 54 | - (BOOL) appendData:(NSData*) data; 55 | 56 | - (id) initWithBoundary:(NSString*) boundary formEncoding:(NSStringEncoding) formEncoding; 57 | 58 | #if __has_feature(objc_arc_weak) 59 | @property(weak, readwrite) id delegate; 60 | #else 61 | @property(unsafe_unretained, readwrite) id delegate; 62 | #endif 63 | @property(readwrite) NSStringEncoding formEncoding; 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Vendor/CocoaLumberjack/Extensions/ContextFilterLogFormatter.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "DDLog.h" 3 | 4 | @class ContextFilterLogFormatter; 5 | 6 | /** 7 | * Welcome to Cocoa Lumberjack! 8 | * 9 | * The project page has a wealth of documentation if you have any questions. 10 | * https://github.com/robbiehanson/CocoaLumberjack 11 | * 12 | * If you're new to the project you may wish to read the "Getting Started" page. 13 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 14 | * 15 | * 16 | * This class provides a log formatter that filters log statements from a logging context not on the whitelist. 17 | * 18 | * A log formatter can be added to any logger to format and/or filter its output. 19 | * You can learn more about log formatters here: 20 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/CustomFormatters 21 | * 22 | * You can learn more about logging context's here: 23 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/CustomContext 24 | * 25 | * But here's a quick overview / refresher: 26 | * 27 | * Every log statement has a logging context. 28 | * These come from the underlying logging macros defined in DDLog.h. 29 | * The default logging context is zero. 30 | * You can define multiple logging context's for use in your application. 31 | * For example, logically separate parts of your app each have a different logging context. 32 | * Also 3rd party frameworks that make use of Lumberjack generally use their own dedicated logging context. 33 | **/ 34 | @interface ContextWhitelistFilterLogFormatter : NSObject 35 | 36 | - (id)init; 37 | 38 | - (void)addToWhitelist:(int)loggingContext; 39 | - (void)removeFromWhitelist:(int)loggingContext; 40 | 41 | - (NSArray *)whitelist; 42 | 43 | - (BOOL)isOnWhitelist:(int)loggingContext; 44 | 45 | @end 46 | 47 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 48 | #pragma mark - 49 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 50 | 51 | /** 52 | * This class provides a log formatter that filters log statements from a logging context on the blacklist. 53 | **/ 54 | @interface ContextBlacklistFilterLogFormatter : NSObject 55 | 56 | - (id)init; 57 | 58 | - (void)addToBlacklist:(int)loggingContext; 59 | - (void)removeFromBlacklist:(int)loggingContext; 60 | 61 | - (NSArray *)blacklist; 62 | 63 | - (BOOL)isOnBlacklist:(int)loggingContext; 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Core/Mime/MultipartMessageHeader.m: -------------------------------------------------------------------------------- 1 | // 2 | // MultipartMessagePart.m 3 | // HttpServer 4 | // 5 | // Created by Валерий Гаврилов on 29.03.12. 6 | // Copyright (c) 2012 LLC "Online Publishing Partners" (onlinepp.ru). All rights reserved. 7 | 8 | #import "MultipartMessageHeader.h" 9 | #import "MultipartMessageHeaderField.h" 10 | 11 | #import "HTTPLogging.h" 12 | 13 | //----------------------------------------------------------------- 14 | #pragma mark log level 15 | 16 | #ifdef DEBUG 17 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN; 18 | #else 19 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN; 20 | #endif 21 | 22 | //----------------------------------------------------------------- 23 | // implementation MultipartMessageHeader 24 | //----------------------------------------------------------------- 25 | 26 | 27 | @implementation MultipartMessageHeader 28 | @synthesize fields,encoding; 29 | 30 | 31 | - (id) initWithData:(NSData *)data formEncoding:(NSStringEncoding) formEncoding { 32 | if( nil == (self = [super init]) ) { 33 | return self; 34 | } 35 | 36 | fields = [[NSMutableDictionary alloc] initWithCapacity:1]; 37 | 38 | // In case encoding is not mentioned, 39 | encoding = contentTransferEncoding_unknown; 40 | 41 | char* bytes = (char*)data.bytes; 42 | NSUInteger length = data.length; 43 | int offset = 0; 44 | 45 | // split header into header fields, separated by \r\n 46 | uint16_t fields_separator = 0x0A0D; // \r\n 47 | while( offset < length - 2 ) { 48 | 49 | // the !isspace condition is to support header unfolding 50 | if( (*(uint16_t*) (bytes+offset) == fields_separator) && ((offset == length - 2) || !(isspace(bytes[offset+2])) )) { 51 | NSData* fieldData = [NSData dataWithBytesNoCopy:bytes length:offset freeWhenDone:NO]; 52 | MultipartMessageHeaderField* field = [[MultipartMessageHeaderField alloc] initWithData: fieldData contentEncoding:formEncoding]; 53 | if( field ) { 54 | [fields setObject:field forKey:field.name]; 55 | HTTPLogVerbose(@"MultipartFormDataParser: Processed Header field '%@'",field.name); 56 | } 57 | else { 58 | NSString* fieldStr = [[NSString alloc] initWithData:fieldData encoding:NSASCIIStringEncoding]; 59 | HTTPLogWarn(@"MultipartFormDataParser: Failed to parse MIME header field. Input ASCII string:%@",fieldStr); 60 | } 61 | 62 | // move to the next header field 63 | bytes += offset + 2; 64 | length -= offset + 2; 65 | offset = 0; 66 | continue; 67 | } 68 | ++ offset; 69 | } 70 | 71 | if( !fields.count ) { 72 | // it was an empty header. 73 | // we have to set default values. 74 | // default header. 75 | [fields setObject:@"text/plain" forKey:@"Content-Type"]; 76 | } 77 | 78 | return self; 79 | } 80 | 81 | - (NSString *)description { 82 | return [NSString stringWithFormat:@"%@",fields]; 83 | } 84 | 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /Samples/iPhoneHTTPServer/Classes/iPhoneHTTPServerAppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "iPhoneHTTPServerAppDelegate.h" 2 | #import "iPhoneHTTPServerViewController.h" 3 | #import "HTTPServer.h" 4 | #import "DDLog.h" 5 | #import "DDTTYLogger.h" 6 | 7 | // Log levels: off, error, warn, info, verbose 8 | static const int ddLogLevel = LOG_LEVEL_VERBOSE; 9 | 10 | 11 | @implementation iPhoneHTTPServerAppDelegate 12 | 13 | @synthesize window; 14 | @synthesize viewController; 15 | 16 | - (void)startServer 17 | { 18 | // Start the server (and check for problems) 19 | 20 | NSError *error; 21 | if([httpServer start:&error]) 22 | { 23 | DDLogInfo(@"Started HTTP Server on port %hu", [httpServer listeningPort]); 24 | } 25 | else 26 | { 27 | DDLogError(@"Error starting HTTP Server: %@", error); 28 | } 29 | } 30 | 31 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 32 | { 33 | // Configure our logging framework. 34 | // To keep things simple and fast, we're just going to log to the Xcode console. 35 | [DDLog addLogger:[DDTTYLogger sharedInstance]]; 36 | 37 | // Create server using our custom MyHTTPServer class 38 | httpServer = [[HTTPServer alloc] init]; 39 | 40 | // Tell the server to broadcast its presence via Bonjour. 41 | // This allows browsers such as Safari to automatically discover our service. 42 | [httpServer setType:@"_http._tcp."]; 43 | 44 | // Normally there's no need to run our server on any specific port. 45 | // Technologies like Bonjour allow clients to dynamically discover the server's port at runtime. 46 | // However, for easy testing you may want force a certain port so you can just hit the refresh button. 47 | // [httpServer setPort:12345]; 48 | 49 | // Serve files from our embedded Web folder 50 | NSString *webPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Web"]; 51 | DDLogInfo(@"Setting document root: %@", webPath); 52 | 53 | [httpServer setDocumentRoot:webPath]; 54 | 55 | [self startServer]; 56 | 57 | // Add the view controller's view to the window and display. 58 | [window addSubview:viewController.view]; 59 | [window makeKeyAndVisible]; 60 | 61 | return YES; 62 | } 63 | 64 | - (void)applicationWillEnterForeground:(UIApplication *)application 65 | { 66 | [self startServer]; 67 | } 68 | 69 | - (void)applicationDidEnterBackground:(UIApplication *)application 70 | { 71 | // There is no public(allowed in AppStore) method for iOS to run continiously in the background for our purposes (serving HTTP). 72 | // So, we stop the server when the app is paused (if a users exits from the app or locks a device) and 73 | // restart the server when the app is resumed (based on this document: http://developer.apple.com/library/ios/#technotes/tn2277/_index.html ) 74 | 75 | [httpServer stop]; 76 | } 77 | 78 | 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /Vendor/CocoaLumberjack/DDASLLogger.m: -------------------------------------------------------------------------------- 1 | #import "DDASLLogger.h" 2 | 3 | #import 4 | 5 | /** 6 | * Welcome to Cocoa Lumberjack! 7 | * 8 | * The project page has a wealth of documentation if you have any questions. 9 | * https://github.com/robbiehanson/CocoaLumberjack 10 | * 11 | * If you're new to the project you may wish to read the "Getting Started" wiki. 12 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 13 | **/ 14 | 15 | #if ! __has_feature(objc_arc) 16 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 17 | #endif 18 | 19 | 20 | @implementation DDASLLogger 21 | 22 | static DDASLLogger *sharedInstance; 23 | 24 | /** 25 | * The runtime sends initialize to each class in a program exactly one time just before the class, 26 | * or any class that inherits from it, is sent its first message from within the program. (Thus the 27 | * method may never be invoked if the class is not used.) The runtime sends the initialize message to 28 | * classes in a thread-safe manner. Superclasses receive this message before their subclasses. 29 | * 30 | * This method may also be called directly (assumably by accident), hence the safety mechanism. 31 | **/ 32 | + (void)initialize 33 | { 34 | static BOOL initialized = NO; 35 | if (!initialized) 36 | { 37 | initialized = YES; 38 | 39 | sharedInstance = [[DDASLLogger alloc] init]; 40 | } 41 | } 42 | 43 | + (DDASLLogger *)sharedInstance 44 | { 45 | return sharedInstance; 46 | } 47 | 48 | - (id)init 49 | { 50 | if (sharedInstance != nil) 51 | { 52 | return nil; 53 | } 54 | 55 | if ((self = [super init])) 56 | { 57 | // A default asl client is provided for the main thread, 58 | // but background threads need to create their own client. 59 | 60 | client = asl_open(NULL, "com.apple.console", 0); 61 | } 62 | return self; 63 | } 64 | 65 | - (void)logMessage:(DDLogMessage *)logMessage 66 | { 67 | NSString *logMsg = logMessage->logMsg; 68 | 69 | if (formatter) 70 | { 71 | logMsg = [formatter formatLogMessage:logMessage]; 72 | } 73 | 74 | if (logMsg) 75 | { 76 | const char *msg = [logMsg UTF8String]; 77 | 78 | int aslLogLevel; 79 | switch (logMessage->logFlag) 80 | { 81 | // Note: By default ASL will filter anything above level 5 (Notice). 82 | // So our mappings shouldn't go above that level. 83 | 84 | case LOG_FLAG_ERROR : aslLogLevel = ASL_LEVEL_CRIT; break; 85 | case LOG_FLAG_WARN : aslLogLevel = ASL_LEVEL_ERR; break; 86 | case LOG_FLAG_INFO : aslLogLevel = ASL_LEVEL_WARNING; break; 87 | default : aslLogLevel = ASL_LEVEL_NOTICE; break; 88 | } 89 | 90 | asl_log(client, NULL, aslLogLevel, "%s", msg); 91 | } 92 | } 93 | 94 | - (NSString *)loggerName 95 | { 96 | return @"cocoa.lumberjack.aslLogger"; 97 | } 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /Core/Responses/HTTPAsyncFileResponse.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPResponse.h" 3 | 4 | @class HTTPConnection; 5 | 6 | /** 7 | * This is an asynchronous version of HTTPFileResponse. 8 | * It reads data from the given file asynchronously via GCD. 9 | * 10 | * It may be overriden to allow custom post-processing of the data that has been read from the file. 11 | * An example of this is the HTTPDynamicFileResponse class. 12 | **/ 13 | 14 | @interface HTTPAsyncFileResponse : NSObject 15 | { 16 | HTTPConnection *connection; 17 | 18 | NSString *filePath; 19 | UInt64 fileLength; 20 | UInt64 fileOffset; // File offset as pertains to data given to connection 21 | UInt64 readOffset; // File offset as pertains to data read from file (but maybe not returned to connection) 22 | 23 | BOOL aborted; 24 | 25 | NSData *data; 26 | 27 | int fileFD; 28 | void *readBuffer; 29 | NSUInteger readBufferSize; // Malloced size of readBuffer 30 | NSUInteger readBufferOffset; // Offset within readBuffer where the end of existing data is 31 | NSUInteger readRequestLength; 32 | dispatch_queue_t readQueue; 33 | dispatch_source_t readSource; 34 | BOOL readSourceSuspended; 35 | } 36 | 37 | - (id)initWithFilePath:(NSString *)filePath forConnection:(HTTPConnection *)connection; 38 | - (NSString *)filePath; 39 | 40 | @end 41 | 42 | /** 43 | * Explanation of Variables (excluding those that are obvious) 44 | * 45 | * fileOffset 46 | * This is the number of bytes that have been returned to the connection via the readDataOfLength method. 47 | * If 1KB of data has been read from the file, but none of that data has yet been returned to the connection, 48 | * then the fileOffset variable remains at zero. 49 | * This variable is used in the calculation of the isDone method. 50 | * Only after all data has been returned to the connection are we actually done. 51 | * 52 | * readOffset 53 | * Represents the offset of the file descriptor. 54 | * In other words, the file position indidcator for our read stream. 55 | * It might be easy to think of it as the total number of bytes that have been read from the file. 56 | * However, this isn't entirely accurate, as the setOffset: method may have caused us to 57 | * jump ahead in the file (lseek). 58 | * 59 | * readBuffer 60 | * Malloc'd buffer to hold data read from the file. 61 | * 62 | * readBufferSize 63 | * Total allocation size of malloc'd buffer. 64 | * 65 | * readBufferOffset 66 | * Represents the position in the readBuffer where we should store new bytes. 67 | * 68 | * readRequestLength 69 | * The total number of bytes that were requested from the connection. 70 | * It's OK if we return a lesser number of bytes to the connection. 71 | * It's NOT OK if we return a greater number of bytes to the connection. 72 | * Doing so would disrupt proper support for range requests. 73 | * If, however, the response is chunked then we don't need to worry about this. 74 | * Chunked responses inheritly don't support range requests. 75 | **/ 76 | -------------------------------------------------------------------------------- /Core/Categories/DDRange.m: -------------------------------------------------------------------------------- 1 | #import "DDRange.h" 2 | #import "DDNumber.h" 3 | 4 | DDRange DDUnionRange(DDRange range1, DDRange range2) 5 | { 6 | DDRange result; 7 | 8 | result.location = MIN(range1.location, range2.location); 9 | result.length = MAX(DDMaxRange(range1), DDMaxRange(range2)) - result.location; 10 | 11 | return result; 12 | } 13 | 14 | DDRange DDIntersectionRange(DDRange range1, DDRange range2) 15 | { 16 | DDRange result; 17 | 18 | if((DDMaxRange(range1) < range2.location) || (DDMaxRange(range2) < range1.location)) 19 | { 20 | return DDMakeRange(0, 0); 21 | } 22 | 23 | result.location = MAX(range1.location, range2.location); 24 | result.length = MIN(DDMaxRange(range1), DDMaxRange(range2)) - result.location; 25 | 26 | return result; 27 | } 28 | 29 | NSString *DDStringFromRange(DDRange range) 30 | { 31 | return [NSString stringWithFormat:@"{%qu, %qu}", range.location, range.length]; 32 | } 33 | 34 | DDRange DDRangeFromString(NSString *aString) 35 | { 36 | DDRange result = DDMakeRange(0, 0); 37 | 38 | // NSRange will ignore '-' characters, but not '+' characters 39 | NSCharacterSet *cset = [NSCharacterSet characterSetWithCharactersInString:@"+0123456789"]; 40 | 41 | NSScanner *scanner = [NSScanner scannerWithString:aString]; 42 | [scanner setCharactersToBeSkipped:[cset invertedSet]]; 43 | 44 | NSString *str1 = nil; 45 | NSString *str2 = nil; 46 | 47 | BOOL found1 = [scanner scanCharactersFromSet:cset intoString:&str1]; 48 | BOOL found2 = [scanner scanCharactersFromSet:cset intoString:&str2]; 49 | 50 | if(found1) [NSNumber parseString:str1 intoUInt64:&result.location]; 51 | if(found2) [NSNumber parseString:str2 intoUInt64:&result.length]; 52 | 53 | return result; 54 | } 55 | 56 | NSInteger DDRangeCompare(DDRangePointer pDDRange1, DDRangePointer pDDRange2) 57 | { 58 | // Comparison basis: 59 | // Which range would you encouter first if you started at zero, and began walking towards infinity. 60 | // If you encouter both ranges at the same time, which range would end first. 61 | 62 | if(pDDRange1->location < pDDRange2->location) 63 | { 64 | return NSOrderedAscending; 65 | } 66 | if(pDDRange1->location > pDDRange2->location) 67 | { 68 | return NSOrderedDescending; 69 | } 70 | if(pDDRange1->length < pDDRange2->length) 71 | { 72 | return NSOrderedAscending; 73 | } 74 | if(pDDRange1->length > pDDRange2->length) 75 | { 76 | return NSOrderedDescending; 77 | } 78 | 79 | return NSOrderedSame; 80 | } 81 | 82 | @implementation NSValue (NSValueDDRangeExtensions) 83 | 84 | + (NSValue *)valueWithDDRange:(DDRange)range 85 | { 86 | return [NSValue valueWithBytes:&range objCType:@encode(DDRange)]; 87 | } 88 | 89 | - (DDRange)ddrangeValue 90 | { 91 | DDRange result; 92 | [self getValue:&result]; 93 | return result; 94 | } 95 | 96 | - (NSInteger)ddrangeCompare:(NSValue *)other 97 | { 98 | DDRange r1 = [self ddrangeValue]; 99 | DDRange r2 = [other ddrangeValue]; 100 | 101 | return DDRangeCompare(&r1, &r2); 102 | } 103 | 104 | @end 105 | -------------------------------------------------------------------------------- /Core/WebSocket.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class HTTPMessage; 4 | @class GCDAsyncSocket; 5 | 6 | 7 | #define WebSocketDidDieNotification @"WebSocketDidDie" 8 | 9 | @interface WebSocket : NSObject 10 | { 11 | dispatch_queue_t websocketQueue; 12 | 13 | HTTPMessage *request; 14 | GCDAsyncSocket *asyncSocket; 15 | 16 | NSData *term; 17 | 18 | BOOL isStarted; 19 | BOOL isOpen; 20 | BOOL isVersion76; 21 | 22 | id __unsafe_unretained delegate; 23 | } 24 | 25 | + (BOOL)isWebSocketRequest:(HTTPMessage *)request; 26 | 27 | - (id)initWithRequest:(HTTPMessage *)request socket:(GCDAsyncSocket *)socket; 28 | 29 | /** 30 | * Delegate option. 31 | * 32 | * In most cases it will be easier to subclass WebSocket, 33 | * but some circumstances may lead one to prefer standard delegate callbacks instead. 34 | **/ 35 | @property (/* atomic */ unsafe_unretained) id delegate; 36 | 37 | /** 38 | * The WebSocket class is thread-safe, generally via it's GCD queue. 39 | * All public API methods are thread-safe, 40 | * and the subclass API methods are thread-safe as they are all invoked on the same GCD queue. 41 | **/ 42 | @property (nonatomic, readonly) dispatch_queue_t websocketQueue; 43 | 44 | /** 45 | * Public API 46 | * 47 | * These methods are automatically called by the HTTPServer. 48 | * You may invoke the stop method yourself to close the WebSocket manually. 49 | **/ 50 | - (void)start; 51 | - (void)stop; 52 | 53 | /** 54 | * Public API 55 | * 56 | * Sends a message over the WebSocket. 57 | * This method is thread-safe. 58 | **/ 59 | - (void)sendMessage:(NSString *)msg; 60 | 61 | /** 62 | * Public API 63 | * 64 | * Sends a message over the WebSocket. 65 | * This method is thread-safe. 66 | **/ 67 | - (void)sendData:(NSData *)msg; 68 | 69 | /** 70 | * Subclass API 71 | * 72 | * These methods are designed to be overriden by subclasses. 73 | **/ 74 | - (void)didOpen; 75 | - (void)didReceiveMessage:(NSString *)msg; 76 | - (void)didClose; 77 | 78 | @end 79 | 80 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 81 | #pragma mark - 82 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 83 | 84 | /** 85 | * There are two ways to create your own custom WebSocket: 86 | * 87 | * - Subclass it and override the methods you're interested in. 88 | * - Use traditional delegate paradigm along with your own custom class. 89 | * 90 | * They both exist to allow for maximum flexibility. 91 | * In most cases it will be easier to subclass WebSocket. 92 | * However some circumstances may lead one to prefer standard delegate callbacks instead. 93 | * One such example, you're already subclassing another class, so subclassing WebSocket isn't an option. 94 | **/ 95 | 96 | @protocol WebSocketDelegate 97 | @optional 98 | 99 | - (void)webSocketDidOpen:(WebSocket *)ws; 100 | 101 | - (void)webSocket:(WebSocket *)ws didReceiveMessage:(NSString *)msg; 102 | 103 | - (void)webSocketDidClose:(WebSocket *)ws; 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /Core/HTTPMessage.m: -------------------------------------------------------------------------------- 1 | #import "HTTPMessage.h" 2 | 3 | #if ! __has_feature(objc_arc) 4 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 5 | #endif 6 | 7 | 8 | @implementation HTTPMessage 9 | 10 | - (id)initEmptyRequest 11 | { 12 | if ((self = [super init])) 13 | { 14 | message = CFHTTPMessageCreateEmpty(NULL, YES); 15 | } 16 | return self; 17 | } 18 | 19 | - (id)initRequestWithMethod:(NSString *)method URL:(NSURL *)url version:(NSString *)version 20 | { 21 | if ((self = [super init])) 22 | { 23 | message = CFHTTPMessageCreateRequest(NULL, 24 | (__bridge CFStringRef)method, 25 | (__bridge CFURLRef)url, 26 | (__bridge CFStringRef)version); 27 | } 28 | return self; 29 | } 30 | 31 | - (id)initResponseWithStatusCode:(NSInteger)code description:(NSString *)description version:(NSString *)version 32 | { 33 | if ((self = [super init])) 34 | { 35 | message = CFHTTPMessageCreateResponse(NULL, 36 | (CFIndex)code, 37 | (__bridge CFStringRef)description, 38 | (__bridge CFStringRef)version); 39 | } 40 | return self; 41 | } 42 | 43 | - (void)dealloc 44 | { 45 | if (message) 46 | { 47 | CFRelease(message); 48 | } 49 | } 50 | 51 | - (BOOL)appendData:(NSData *)data 52 | { 53 | return CFHTTPMessageAppendBytes(message, [data bytes], [data length]); 54 | } 55 | 56 | - (BOOL)isHeaderComplete 57 | { 58 | return CFHTTPMessageIsHeaderComplete(message); 59 | } 60 | 61 | - (NSString *)version 62 | { 63 | return (__bridge_transfer NSString *)CFHTTPMessageCopyVersion(message); 64 | } 65 | 66 | - (NSString *)method 67 | { 68 | return (__bridge_transfer NSString *)CFHTTPMessageCopyRequestMethod(message); 69 | } 70 | 71 | - (NSURL *)url 72 | { 73 | return (__bridge_transfer NSURL *)CFHTTPMessageCopyRequestURL(message); 74 | } 75 | 76 | - (NSInteger)statusCode 77 | { 78 | return (NSInteger)CFHTTPMessageGetResponseStatusCode(message); 79 | } 80 | 81 | - (NSDictionary *)allHeaderFields 82 | { 83 | return (__bridge_transfer NSDictionary *)CFHTTPMessageCopyAllHeaderFields(message); 84 | } 85 | 86 | - (NSString *)headerField:(NSString *)headerField 87 | { 88 | return (__bridge_transfer NSString *)CFHTTPMessageCopyHeaderFieldValue(message, (__bridge CFStringRef)headerField); 89 | } 90 | 91 | - (void)setHeaderField:(NSString *)headerField value:(NSString *)headerFieldValue 92 | { 93 | CFHTTPMessageSetHeaderFieldValue(message, 94 | (__bridge CFStringRef)headerField, 95 | (__bridge CFStringRef)headerFieldValue); 96 | } 97 | 98 | - (NSData *)messageData 99 | { 100 | return (__bridge_transfer NSData *)CFHTTPMessageCopySerializedMessage(message); 101 | } 102 | 103 | - (NSData *)body 104 | { 105 | return (__bridge_transfer NSData *)CFHTTPMessageCopyBody(message); 106 | } 107 | 108 | - (void)setBody:(NSData *)body 109 | { 110 | CFHTTPMessageSetBody(message, (__bridge CFDataRef)body); 111 | } 112 | 113 | @end 114 | -------------------------------------------------------------------------------- /Samples/PostHTTPServer/MyHTTPConnection.m: -------------------------------------------------------------------------------- 1 | #import "MyHTTPConnection.h" 2 | #import "HTTPMessage.h" 3 | #import "HTTPDataResponse.h" 4 | #import "DDNumber.h" 5 | #import "HTTPLogging.h" 6 | 7 | // Log levels : off, error, warn, info, verbose 8 | // Other flags: trace 9 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN; // | HTTP_LOG_FLAG_TRACE; 10 | 11 | 12 | /** 13 | * All we have to do is override appropriate methods in HTTPConnection. 14 | **/ 15 | 16 | @implementation MyHTTPConnection 17 | 18 | - (BOOL)supportsMethod:(NSString *)method atPath:(NSString *)path 19 | { 20 | HTTPLogTrace(); 21 | 22 | // Add support for POST 23 | 24 | if ([method isEqualToString:@"POST"]) 25 | { 26 | if ([path isEqualToString:@"/post.html"]) 27 | { 28 | // Let's be extra cautious, and make sure the upload isn't 5 gigs 29 | 30 | return requestContentLength < 50; 31 | } 32 | } 33 | 34 | return [super supportsMethod:method atPath:path]; 35 | } 36 | 37 | - (BOOL)expectsRequestBodyFromMethod:(NSString *)method atPath:(NSString *)path 38 | { 39 | HTTPLogTrace(); 40 | 41 | // Inform HTTP server that we expect a body to accompany a POST request 42 | 43 | if([method isEqualToString:@"POST"]) 44 | return YES; 45 | 46 | return [super expectsRequestBodyFromMethod:method atPath:path]; 47 | } 48 | 49 | - (NSObject *)httpResponseForMethod:(NSString *)method URI:(NSString *)path 50 | { 51 | HTTPLogTrace(); 52 | 53 | if ([method isEqualToString:@"POST"] && [path isEqualToString:@"/post.html"]) 54 | { 55 | HTTPLogVerbose(@"%@[%p]: postContentLength: %qu", THIS_FILE, self, requestContentLength); 56 | 57 | NSString *postStr = nil; 58 | 59 | NSData *postData = [request body]; 60 | if (postData) 61 | { 62 | postStr = [[NSString alloc] initWithData:postData encoding:NSUTF8StringEncoding]; 63 | } 64 | 65 | HTTPLogVerbose(@"%@[%p]: postStr: %@", THIS_FILE, self, postStr); 66 | 67 | // Result will be of the form "answer=..." 68 | 69 | int answer = [[postStr substringFromIndex:7] intValue]; 70 | 71 | NSData *response = nil; 72 | if(answer == 10) 73 | { 74 | response = [@"Correct" dataUsingEncoding:NSUTF8StringEncoding]; 75 | } 76 | else 77 | { 78 | response = [@"Sorry - Try Again" dataUsingEncoding:NSUTF8StringEncoding]; 79 | } 80 | 81 | return [[HTTPDataResponse alloc] initWithData:response]; 82 | } 83 | 84 | return [super httpResponseForMethod:method URI:path]; 85 | } 86 | 87 | - (void)prepareForBodyWithSize:(UInt64)contentLength 88 | { 89 | HTTPLogTrace(); 90 | 91 | // If we supported large uploads, 92 | // we might use this method to create/open files, allocate memory, etc. 93 | } 94 | 95 | - (void)processBodyData:(NSData *)postDataChunk 96 | { 97 | HTTPLogTrace(); 98 | 99 | // Remember: In order to support LARGE POST uploads, the data is read in chunks. 100 | // This prevents a 50 MB upload from being stored in RAM. 101 | // The size of the chunks are limited by the POST_CHUNKSIZE definition. 102 | // Therefore, this method may be called multiple times for the same POST request. 103 | 104 | BOOL result = [request appendData:postDataChunk]; 105 | if (!result) 106 | { 107 | HTTPLogError(@"%@[%p]: %@ - Couldn't append bytes!", THIS_FILE, self, THIS_METHOD); 108 | } 109 | } 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /Samples/WebDAVServer/WebDAVServer.xcodeproj/xcshareddata/xcschemes/WebDAVServer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Samples/DynamicServer/DynamicServer.xcodeproj/xcshareddata/xcschemes/DynamicServer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer/MyHTTPConnection.m: -------------------------------------------------------------------------------- 1 | #import "MyHTTPConnection.h" 2 | #import "HTTPMessage.h" 3 | #import "HTTPResponse.h" 4 | #import "HTTPDynamicFileResponse.h" 5 | #import "GCDAsyncSocket.h" 6 | #import "MyWebSocket.h" 7 | #import "HTTPLogging.h" 8 | #import "DDKeychain.h" 9 | 10 | // Log levels: off, error, warn, info, verbose 11 | // Other flags: trace 12 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN; // | HTTP_LOG_FLAG_TRACE; 13 | 14 | 15 | @implementation MyHTTPConnection 16 | 17 | /** 18 | * Overrides HTTPConnection's method 19 | **/ 20 | - (BOOL)isSecureServer 21 | { 22 | HTTPLogTrace(); 23 | 24 | // Create an HTTPS server (all connections will be secured via SSL/TLS) 25 | return YES; 26 | } 27 | 28 | /** 29 | * Overrides HTTPConnection's method 30 | * 31 | * This method is expected to returns an array appropriate for use in kCFStreamSSLCertificates SSL Settings. 32 | * It should be an array of SecCertificateRefs except for the first element in the array, which is a SecIdentityRef. 33 | **/ 34 | - (NSArray *)sslIdentityAndCertificates 35 | { 36 | HTTPLogTrace(); 37 | 38 | NSArray *result = [DDKeychain SSLIdentityAndCertificates]; 39 | if([result count] == 0) 40 | { 41 | HTTPLogInfo(@"sslIdentityAndCertificates: Creating New Identity..."); 42 | [DDKeychain createNewIdentity]; 43 | return [DDKeychain SSLIdentityAndCertificates]; 44 | } 45 | return result; 46 | } 47 | 48 | - (NSObject *)httpResponseForMethod:(NSString *)method URI:(NSString *)path 49 | { 50 | HTTPLogTrace(); 51 | 52 | if ([path isEqualToString:@"/WebSocketTest2.js"]) 53 | { 54 | // The socket.js file contains a URL template that needs to be completed: 55 | // 56 | // ws = new WebSocket("%%WEBSOCKET_URL%%"); 57 | // 58 | // We need to replace "%%WEBSOCKET_URL%%" with whatever URL the server is running on. 59 | // We can accomplish this easily with the HTTPDynamicFileResponse class, 60 | // which takes a dictionary of replacement key-value pairs, 61 | // and performs replacements on the fly as it uploads the file. 62 | 63 | NSString *wsLocation; 64 | 65 | NSString *scheme = [asyncSocket isSecure] ? @"wss" : @"ws"; 66 | NSString *wsHost = [request headerField:@"Host"]; 67 | 68 | if (wsHost == nil) 69 | { 70 | NSString *port = [NSString stringWithFormat:@"%hu", [asyncSocket localPort]]; 71 | wsLocation = [NSString stringWithFormat:@"%@://localhost:%@/service", scheme, port]; 72 | } 73 | else 74 | { 75 | wsLocation = [NSString stringWithFormat:@"%@://%@/service", scheme, wsHost]; 76 | } 77 | 78 | NSDictionary *replacementDict = [NSDictionary dictionaryWithObject:wsLocation forKey:@"WEBSOCKET_URL"]; 79 | 80 | return [[HTTPDynamicFileResponse alloc] initWithFilePath:[self filePathForURI:path] 81 | forConnection:self 82 | separator:@"%%" 83 | replacementDictionary:replacementDict]; 84 | } 85 | 86 | return [super httpResponseForMethod:method URI:path]; 87 | } 88 | 89 | - (WebSocket *)webSocketForURI:(NSString *)path 90 | { 91 | HTTPLogTrace2(@"%@[%p]: webSocketForURI: %@", THIS_FILE, self, path); 92 | 93 | if([path isEqualToString:@"/service"]) 94 | { 95 | HTTPLogInfo(@"MyHTTPConnection: Creating MyWebSocket..."); 96 | 97 | return [[MyWebSocket alloc] initWithRequest:request socket:asyncSocket]; 98 | } 99 | 100 | return [super webSocketForURI:path]; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /Samples/PostHTTPServer/PostHTTPServer.xcodeproj/xcshareddata/xcschemes/PostHTTPServer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Samples/PasswdHTTPServer/PasswdHTTPServer.xcodeproj/xcshareddata/xcschemes/PasswdHTTPServer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Samples/SecureHTTPServer/SecureHTTPServer.xcodeproj/xcshareddata/xcschemes/SecureHTTPServer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Samples/SimpleHTTPServer/SimpleHTTPServer.xcodeproj/xcshareddata/xcschemes/SimpleHTTPServer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Samples/iPhoneHTTPServer/iPhoneHTTPServer.xcodeproj/xcshareddata/xcschemes/iPhoneHTTPServer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Samples/DynamicServer/MyHTTPConnection.m: -------------------------------------------------------------------------------- 1 | #import "MyHTTPConnection.h" 2 | #import "HTTPDynamicFileResponse.h" 3 | #import "HTTPResponseTest.h" 4 | #import "HTTPLogging.h" 5 | 6 | // Log levels: off, error, warn, info, verbose 7 | // Other flags: trace 8 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN; // | HTTP_LOG_FLAG_TRACE; 9 | 10 | 11 | @implementation MyHTTPConnection 12 | 13 | - (NSObject *)httpResponseForMethod:(NSString *)method URI:(NSString *)path 14 | { 15 | // Use HTTPConnection's filePathForURI method. 16 | // This method takes the given path (which comes directly from the HTTP request), 17 | // and converts it to a full path by combining it with the configured document root. 18 | // 19 | // It also does cool things for us like support for converting "/" to "/index.html", 20 | // and security restrictions (ensuring we don't serve documents outside configured document root folder). 21 | 22 | NSString *filePath = [self filePathForURI:path]; 23 | 24 | // Convert to relative path 25 | 26 | NSString *documentRoot = [config documentRoot]; 27 | 28 | if (![filePath hasPrefix:documentRoot]) 29 | { 30 | // Uh oh. 31 | // HTTPConnection's filePathForURI was supposed to take care of this for us. 32 | return nil; 33 | } 34 | 35 | NSString *relativePath = [filePath substringFromIndex:[documentRoot length]]; 36 | 37 | if ([relativePath isEqualToString:@"/index.html"]) 38 | { 39 | HTTPLogVerbose(@"%@[%p]: Serving up dynamic content", THIS_FILE, self); 40 | 41 | // The index.html file contains several dynamic fields that need to be completed. 42 | // For example: 43 | // 44 | // Computer name: %%COMPUTER_NAME%% 45 | // 46 | // We need to replace "%%COMPUTER_NAME%%" with whatever the computer name is. 47 | // We can accomplish this easily with the HTTPDynamicFileResponse class, 48 | // which takes a dictionary of replacement key-value pairs, 49 | // and performs replacements on the fly as it uploads the file. 50 | 51 | NSString *computerName = [[NSHost currentHost] localizedName]; 52 | NSString *currentTime = [[NSDate date] description]; 53 | 54 | NSString *story = @"

    " 55 | "I'll tell you a story
    " \ 56 | "About Jack a Nory;
    " \ 57 | "And now my story's begun;
    " \ 58 | "I'll tell you another
    " \ 59 | "Of Jack and his brother,
    " \ 60 | "And now my story is done.
    "; 61 | 62 | NSMutableDictionary *replacementDict = [NSMutableDictionary dictionaryWithCapacity:5]; 63 | 64 | [replacementDict setObject:computerName forKey:@"COMPUTER_NAME"]; 65 | [replacementDict setObject:currentTime forKey:@"TIME"]; 66 | [replacementDict setObject:story forKey:@"STORY"]; 67 | [replacementDict setObject:@"A" forKey:@"ALPHABET"]; 68 | [replacementDict setObject:@" QUACK " forKey:@"QUACK"]; 69 | 70 | HTTPLogVerbose(@"%@[%p]: replacementDict = \n%@", THIS_FILE, self, replacementDict); 71 | 72 | return [[HTTPDynamicFileResponse alloc] initWithFilePath:[self filePathForURI:path] 73 | forConnection:self 74 | separator:@"%%" 75 | replacementDictionary:replacementDict]; 76 | } 77 | else if ([relativePath isEqualToString:@"/unittest.html"]) 78 | { 79 | HTTPLogVerbose(@"%@[%p]: Serving up HTTPResponseTest (unit testing)", THIS_FILE, self); 80 | 81 | return [[HTTPResponseTest alloc] initWithConnection:self]; 82 | } 83 | 84 | return [super httpResponseForMethod:method URI:path]; 85 | } 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /Samples/SecureWebSocketServer/SecureWebSocketServer.xcodeproj/xcshareddata/xcschemes/SecureWebSocketServer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Samples/SimpleWebSocketServer/SimpleWebSocketServer.xcodeproj/xcshareddata/xcschemes/SimpleWebSocketServer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Samples/SimpleFileUploadServer/SimpleFileUploadServer.xcodeproj/xcshareddata/xcschemes/SimpleFileUploadServer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Core/HTTPConnection.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class GCDAsyncSocket; 4 | @class HTTPMessage; 5 | @class HTTPServer; 6 | @class WebSocket; 7 | @protocol HTTPResponse; 8 | 9 | 10 | #define HTTPConnectionDidDieNotification @"HTTPConnectionDidDie" 11 | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | #pragma mark - 14 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | 16 | @interface HTTPConfig : NSObject 17 | { 18 | HTTPServer __unsafe_unretained *server; 19 | NSString __strong *documentRoot; 20 | dispatch_queue_t queue; 21 | } 22 | 23 | - (id)initWithServer:(HTTPServer *)server documentRoot:(NSString *)documentRoot; 24 | - (id)initWithServer:(HTTPServer *)server documentRoot:(NSString *)documentRoot queue:(dispatch_queue_t)q; 25 | 26 | @property (nonatomic, unsafe_unretained, readonly) HTTPServer *server; 27 | @property (nonatomic, strong, readonly) NSString *documentRoot; 28 | @property (nonatomic, readonly) dispatch_queue_t queue; 29 | 30 | @end 31 | 32 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | #pragma mark - 34 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 35 | 36 | @interface HTTPConnection : NSObject 37 | { 38 | dispatch_queue_t connectionQueue; 39 | GCDAsyncSocket *asyncSocket; 40 | HTTPConfig *config; 41 | 42 | BOOL started; 43 | 44 | HTTPMessage *request; 45 | unsigned int numHeaderLines; 46 | 47 | BOOL sentResponseHeaders; 48 | 49 | NSString *nonce; 50 | long lastNC; 51 | 52 | NSObject *httpResponse; 53 | 54 | NSMutableArray *ranges; 55 | NSMutableArray *ranges_headers; 56 | NSString *ranges_boundry; 57 | int rangeIndex; 58 | 59 | UInt64 requestContentLength; 60 | UInt64 requestContentLengthReceived; 61 | UInt64 requestChunkSize; 62 | UInt64 requestChunkSizeReceived; 63 | 64 | NSMutableArray *responseDataSizes; 65 | } 66 | 67 | - (id)initWithAsyncSocket:(GCDAsyncSocket *)newSocket configuration:(HTTPConfig *)aConfig; 68 | 69 | - (void)start; 70 | - (void)stop; 71 | 72 | - (void)startConnection; 73 | 74 | - (BOOL)supportsMethod:(NSString *)method atPath:(NSString *)path; 75 | - (BOOL)expectsRequestBodyFromMethod:(NSString *)method atPath:(NSString *)path; 76 | 77 | - (BOOL)isSecureServer; 78 | - (NSArray *)sslIdentityAndCertificates; 79 | 80 | - (BOOL)isPasswordProtected:(NSString *)path; 81 | - (BOOL)useDigestAccessAuthentication; 82 | - (NSString *)realm; 83 | - (NSString *)passwordForUser:(NSString *)username; 84 | 85 | - (NSDictionary *)parseParams:(NSString *)query; 86 | - (NSDictionary *)parseGetParams; 87 | 88 | - (NSString *)requestURI; 89 | 90 | - (NSArray *)directoryIndexFileNames; 91 | - (NSString *)filePathForURI:(NSString *)path; 92 | - (NSString *)filePathForURI:(NSString *)path allowDirectory:(BOOL)allowDirectory; 93 | - (NSObject *)httpResponseForMethod:(NSString *)method URI:(NSString *)path; 94 | - (WebSocket *)webSocketForURI:(NSString *)path; 95 | 96 | - (void)prepareForBodyWithSize:(UInt64)contentLength; 97 | - (void)processBodyData:(NSData *)postDataChunk; 98 | - (void)finishBody; 99 | 100 | - (void)handleVersionNotSupported:(NSString *)version; 101 | - (void)handleAuthenticationFailed; 102 | - (void)handleResourceNotFound; 103 | - (void)handleInvalidRequest:(NSData *)data; 104 | - (void)handleUnknownMethod:(NSString *)method; 105 | 106 | - (NSData *)preprocessResponse:(HTTPMessage *)response; 107 | - (NSData *)preprocessErrorResponse:(HTTPMessage *)response; 108 | 109 | - (void)finishResponse; 110 | 111 | - (BOOL)shouldDie; 112 | - (void)die; 113 | 114 | @end 115 | 116 | @interface HTTPConnection (AsynchronousHTTPResponse) 117 | - (void)responseHasAvailableData:(NSObject *)sender; 118 | - (void)responseDidAbort:(NSObject *)sender; 119 | @end 120 | -------------------------------------------------------------------------------- /Vendor/CocoaLumberjack/DDAbstractDatabaseLogger.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "DDLog.h" 4 | 5 | /** 6 | * Welcome to Cocoa Lumberjack! 7 | * 8 | * The project page has a wealth of documentation if you have any questions. 9 | * https://github.com/robbiehanson/CocoaLumberjack 10 | * 11 | * If you're new to the project you may wish to read the "Getting Started" wiki. 12 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 13 | * 14 | * 15 | * This class provides an abstract implementation of a database logger. 16 | * 17 | * That is, it provides the base implementation for a database logger to build atop of. 18 | * All that is needed for a concrete database logger is to extend this class 19 | * and override the methods in the implementation file that are prefixed with "db_". 20 | **/ 21 | 22 | @interface DDAbstractDatabaseLogger : DDAbstractLogger { 23 | @protected 24 | NSUInteger saveThreshold; 25 | NSTimeInterval saveInterval; 26 | NSTimeInterval maxAge; 27 | NSTimeInterval deleteInterval; 28 | BOOL deleteOnEverySave; 29 | 30 | BOOL saveTimerSuspended; 31 | NSUInteger unsavedCount; 32 | dispatch_time_t unsavedTime; 33 | dispatch_source_t saveTimer; 34 | dispatch_time_t lastDeleteTime; 35 | dispatch_source_t deleteTimer; 36 | } 37 | 38 | /** 39 | * Specifies how often to save the data to disk. 40 | * Since saving is an expensive operation (disk io) it is not done after every log statement. 41 | * These properties allow you to configure how/when the logger saves to disk. 42 | * 43 | * A save is done when either (whichever happens first): 44 | * 45 | * - The number of unsaved log entries reaches saveThreshold 46 | * - The amount of time since the oldest unsaved log entry was created reaches saveInterval 47 | * 48 | * You can optionally disable the saveThreshold by setting it to zero. 49 | * If you disable the saveThreshold you are entirely dependent on the saveInterval. 50 | * 51 | * You can optionally disable the saveInterval by setting it to zero (or a negative value). 52 | * If you disable the saveInterval you are entirely dependent on the saveThreshold. 53 | * 54 | * It's not wise to disable both saveThreshold and saveInterval. 55 | * 56 | * The default saveThreshold is 500. 57 | * The default saveInterval is 60 seconds. 58 | **/ 59 | @property (assign, readwrite) NSUInteger saveThreshold; 60 | @property (assign, readwrite) NSTimeInterval saveInterval; 61 | 62 | /** 63 | * It is likely you don't want the log entries to persist forever. 64 | * Doing so would allow the database to grow infinitely large over time. 65 | * 66 | * The maxAge property provides a way to specify how old a log statement can get 67 | * before it should get deleted from the database. 68 | * 69 | * The deleteInterval specifies how often to sweep for old log entries. 70 | * Since deleting is an expensive operation (disk io) is is done on a fixed interval. 71 | * 72 | * An alternative to the deleteInterval is the deleteOnEverySave option. 73 | * This specifies that old log entries should be deleted during every save operation. 74 | * 75 | * You can optionally disable the maxAge by setting it to zero (or a negative value). 76 | * If you disable the maxAge then old log statements are not deleted. 77 | * 78 | * You can optionally disable the deleteInterval by setting it to zero (or a negative value). 79 | * 80 | * If you disable both deleteInterval and deleteOnEverySave then old log statements are not deleted. 81 | * 82 | * It's not wise to enable both deleteInterval and deleteOnEverySave. 83 | * 84 | * The default maxAge is 7 days. 85 | * The default deleteInterval is 5 minutes. 86 | * The default deleteOnEverySave is NO. 87 | **/ 88 | @property (assign, readwrite) NSTimeInterval maxAge; 89 | @property (assign, readwrite) NSTimeInterval deleteInterval; 90 | @property (assign, readwrite) BOOL deleteOnEverySave; 91 | 92 | /** 93 | * Forces a save of any pending log entries (flushes log entries to disk). 94 | **/ 95 | - (void)savePendingLogEntries; 96 | 97 | /** 98 | * Removes any log entries that are older than maxAge. 99 | **/ 100 | - (void)deleteOldLogEntries; 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /Core/Categories/DDData.m: -------------------------------------------------------------------------------- 1 | #import "DDData.h" 2 | #import 3 | 4 | 5 | @implementation NSData (DDData) 6 | 7 | static char encodingTable[64] = { 8 | 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 9 | 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', 10 | 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', 11 | 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' }; 12 | 13 | - (NSData *)md5Digest 14 | { 15 | unsigned char result[CC_MD5_DIGEST_LENGTH]; 16 | 17 | CC_MD5([self bytes], (CC_LONG)[self length], result); 18 | return [NSData dataWithBytes:result length:CC_MD5_DIGEST_LENGTH]; 19 | } 20 | 21 | - (NSData *)sha1Digest 22 | { 23 | unsigned char result[CC_SHA1_DIGEST_LENGTH]; 24 | 25 | CC_SHA1([self bytes], (CC_LONG)[self length], result); 26 | return [NSData dataWithBytes:result length:CC_SHA1_DIGEST_LENGTH]; 27 | } 28 | 29 | - (NSString *)hexStringValue 30 | { 31 | NSMutableString *stringBuffer = [NSMutableString stringWithCapacity:([self length] * 2)]; 32 | 33 | const unsigned char *dataBuffer = [self bytes]; 34 | int i; 35 | 36 | for (i = 0; i < [self length]; ++i) 37 | { 38 | [stringBuffer appendFormat:@"%02x", (unsigned int)dataBuffer[i]]; 39 | } 40 | 41 | return [stringBuffer copy]; 42 | } 43 | 44 | - (NSString *)base64Encoded 45 | { 46 | const unsigned char *bytes = [self bytes]; 47 | NSMutableString *result = [NSMutableString stringWithCapacity:[self length]]; 48 | unsigned long ixtext = 0; 49 | unsigned long lentext = [self length]; 50 | long ctremaining = 0; 51 | unsigned char inbuf[3], outbuf[4]; 52 | unsigned short i = 0; 53 | unsigned short charsonline = 0, ctcopy = 0; 54 | unsigned long ix = 0; 55 | 56 | while( YES ) 57 | { 58 | ctremaining = lentext - ixtext; 59 | if( ctremaining <= 0 ) break; 60 | 61 | for( i = 0; i < 3; i++ ) { 62 | ix = ixtext + i; 63 | if( ix < lentext ) inbuf[i] = bytes[ix]; 64 | else inbuf [i] = 0; 65 | } 66 | 67 | outbuf [0] = (inbuf [0] & 0xFC) >> 2; 68 | outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4); 69 | outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6); 70 | outbuf [3] = inbuf [2] & 0x3F; 71 | ctcopy = 4; 72 | 73 | switch( ctremaining ) 74 | { 75 | case 1: 76 | ctcopy = 2; 77 | break; 78 | case 2: 79 | ctcopy = 3; 80 | break; 81 | } 82 | 83 | for( i = 0; i < ctcopy; i++ ) 84 | [result appendFormat:@"%c", encodingTable[outbuf[i]]]; 85 | 86 | for( i = ctcopy; i < 4; i++ ) 87 | [result appendString:@"="]; 88 | 89 | ixtext += 3; 90 | charsonline += 4; 91 | } 92 | 93 | return [NSString stringWithString:result]; 94 | } 95 | 96 | - (NSData *)base64Decoded 97 | { 98 | const unsigned char *bytes = [self bytes]; 99 | NSMutableData *result = [NSMutableData dataWithCapacity:[self length]]; 100 | 101 | unsigned long ixtext = 0; 102 | unsigned long lentext = [self length]; 103 | unsigned char ch = 0; 104 | unsigned char inbuf[4] = {0, 0, 0, 0}; 105 | unsigned char outbuf[3] = {0, 0, 0}; 106 | short i = 0, ixinbuf = 0; 107 | BOOL flignore = NO; 108 | BOOL flendtext = NO; 109 | 110 | while( YES ) 111 | { 112 | if( ixtext >= lentext ) break; 113 | ch = bytes[ixtext++]; 114 | flignore = NO; 115 | 116 | if( ( ch >= 'A' ) && ( ch <= 'Z' ) ) ch = ch - 'A'; 117 | else if( ( ch >= 'a' ) && ( ch <= 'z' ) ) ch = ch - 'a' + 26; 118 | else if( ( ch >= '0' ) && ( ch <= '9' ) ) ch = ch - '0' + 52; 119 | else if( ch == '+' ) ch = 62; 120 | else if( ch == '=' ) flendtext = YES; 121 | else if( ch == '/' ) ch = 63; 122 | else flignore = YES; 123 | 124 | if( ! flignore ) 125 | { 126 | short ctcharsinbuf = 3; 127 | BOOL flbreak = NO; 128 | 129 | if( flendtext ) 130 | { 131 | if( ! ixinbuf ) break; 132 | if( ( ixinbuf == 1 ) || ( ixinbuf == 2 ) ) ctcharsinbuf = 1; 133 | else ctcharsinbuf = 2; 134 | ixinbuf = 3; 135 | flbreak = YES; 136 | } 137 | 138 | inbuf [ixinbuf++] = ch; 139 | 140 | if( ixinbuf == 4 ) 141 | { 142 | ixinbuf = 0; 143 | outbuf [0] = ( inbuf[0] << 2 ) | ( ( inbuf[1] & 0x30) >> 4 ); 144 | outbuf [1] = ( ( inbuf[1] & 0x0F ) << 4 ) | ( ( inbuf[2] & 0x3C ) >> 2 ); 145 | outbuf [2] = ( ( inbuf[2] & 0x03 ) << 6 ) | ( inbuf[3] & 0x3F ); 146 | 147 | for( i = 0; i < ctcharsinbuf; i++ ) 148 | [result appendBytes:&outbuf[i] length:1]; 149 | } 150 | 151 | if( flbreak ) break; 152 | } 153 | } 154 | 155 | return [NSData dataWithData:result]; 156 | } 157 | 158 | @end 159 | -------------------------------------------------------------------------------- /Vendor/CocoaLumberjack/Extensions/ContextFilterLogFormatter.m: -------------------------------------------------------------------------------- 1 | #import "ContextFilterLogFormatter.h" 2 | #import 3 | 4 | /** 5 | * Welcome to Cocoa Lumberjack! 6 | * 7 | * The project page has a wealth of documentation if you have any questions. 8 | * https://github.com/robbiehanson/CocoaLumberjack 9 | * 10 | * If you're new to the project you may wish to read the "Getting Started" wiki. 11 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 12 | **/ 13 | 14 | #if ! __has_feature(objc_arc) 15 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 16 | #endif 17 | 18 | @interface LoggingContextSet : NSObject 19 | 20 | - (void)addToSet:(int)loggingContext; 21 | - (void)removeFromSet:(int)loggingContext; 22 | 23 | - (NSArray *)currentSet; 24 | 25 | - (BOOL)isInSet:(int)loggingContext; 26 | 27 | @end 28 | 29 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 | #pragma mark - 31 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | @implementation ContextWhitelistFilterLogFormatter 34 | { 35 | LoggingContextSet *contextSet; 36 | } 37 | 38 | - (id)init 39 | { 40 | if ((self = [super init])) 41 | { 42 | contextSet = [[LoggingContextSet alloc] init]; 43 | } 44 | return self; 45 | } 46 | 47 | 48 | - (void)addToWhitelist:(int)loggingContext 49 | { 50 | [contextSet addToSet:loggingContext]; 51 | } 52 | 53 | - (void)removeFromWhitelist:(int)loggingContext 54 | { 55 | [contextSet removeFromSet:loggingContext]; 56 | } 57 | 58 | - (NSArray *)whitelist 59 | { 60 | return [contextSet currentSet]; 61 | } 62 | 63 | - (BOOL)isOnWhitelist:(int)loggingContext 64 | { 65 | return [contextSet isInSet:loggingContext]; 66 | } 67 | 68 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage 69 | { 70 | if ([self isOnWhitelist:logMessage->logContext]) 71 | return logMessage->logMsg; 72 | else 73 | return nil; 74 | } 75 | 76 | @end 77 | 78 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 79 | #pragma mark - 80 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 81 | 82 | @implementation ContextBlacklistFilterLogFormatter 83 | { 84 | LoggingContextSet *contextSet; 85 | } 86 | 87 | - (id)init 88 | { 89 | if ((self = [super init])) 90 | { 91 | contextSet = [[LoggingContextSet alloc] init]; 92 | } 93 | return self; 94 | } 95 | 96 | 97 | - (void)addToBlacklist:(int)loggingContext 98 | { 99 | [contextSet addToSet:loggingContext]; 100 | } 101 | 102 | - (void)removeFromBlacklist:(int)loggingContext 103 | { 104 | [contextSet removeFromSet:loggingContext]; 105 | } 106 | 107 | - (NSArray *)blacklist 108 | { 109 | return [contextSet currentSet]; 110 | } 111 | 112 | - (BOOL)isOnBlacklist:(int)loggingContext 113 | { 114 | return [contextSet isInSet:loggingContext]; 115 | } 116 | 117 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage 118 | { 119 | if ([self isOnBlacklist:logMessage->logContext]) 120 | return nil; 121 | else 122 | return logMessage->logMsg; 123 | } 124 | 125 | @end 126 | 127 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 128 | #pragma mark - 129 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 130 | 131 | @implementation LoggingContextSet 132 | { 133 | OSSpinLock lock; 134 | NSMutableSet *set; 135 | } 136 | 137 | - (id)init 138 | { 139 | if ((self = [super init])) 140 | { 141 | set = [[NSMutableSet alloc] init]; 142 | } 143 | return self; 144 | } 145 | 146 | 147 | - (void)addToSet:(int)loggingContext 148 | { 149 | OSSpinLockLock(&lock); 150 | { 151 | [set addObject:@(loggingContext)]; 152 | } 153 | OSSpinLockUnlock(&lock); 154 | } 155 | 156 | - (void)removeFromSet:(int)loggingContext 157 | { 158 | OSSpinLockLock(&lock); 159 | { 160 | [set removeObject:@(loggingContext)]; 161 | } 162 | OSSpinLockUnlock(&lock); 163 | } 164 | 165 | - (NSArray *)currentSet 166 | { 167 | NSArray *result = nil; 168 | 169 | OSSpinLockLock(&lock); 170 | { 171 | result = [set allObjects]; 172 | } 173 | OSSpinLockUnlock(&lock); 174 | 175 | return result; 176 | } 177 | 178 | - (BOOL)isInSet:(int)loggingContext 179 | { 180 | BOOL result = NO; 181 | 182 | OSSpinLockLock(&lock); 183 | { 184 | result = [set containsObject:@(loggingContext)]; 185 | } 186 | OSSpinLockUnlock(&lock); 187 | 188 | return result; 189 | } 190 | 191 | @end 192 | -------------------------------------------------------------------------------- /Samples/DynamicServer/HTTPResponseTest.m: -------------------------------------------------------------------------------- 1 | #import "HTTPResponseTest.h" 2 | #import "HTTPConnection.h" 3 | #import "HTTPLogging.h" 4 | 5 | // Does ARC support support GCD objects? 6 | // It does if the minimum deployment target is iOS 6+ or Mac OS X 8+ 7 | 8 | #if TARGET_OS_IPHONE 9 | 10 | // Compiling for iOS 11 | 12 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000 // iOS 6.0 or later 13 | #define NEEDS_DISPATCH_RETAIN_RELEASE 0 14 | #else // iOS 5.X or earlier 15 | #define NEEDS_DISPATCH_RETAIN_RELEASE 1 16 | #endif 17 | 18 | #else 19 | 20 | // Compiling for Mac OS X 21 | 22 | #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 // Mac OS X 10.8 or later 23 | #define NEEDS_DISPATCH_RETAIN_RELEASE 0 24 | #else 25 | #define NEEDS_DISPATCH_RETAIN_RELEASE 1 // Mac OS X 10.7 or earlier 26 | #endif 27 | 28 | #endif 29 | 30 | // Log levels: off, error, warn, info, verbose 31 | // Other flags: trace 32 | static const int httpLogLevel = HTTP_LOG_LEVEL_OFF; // | HTTP_LOG_FLAG_TRACE; 33 | 34 | // 35 | // This class is a UnitTest for the delayResponseHeaders capability of HTTPConnection 36 | // 37 | 38 | @interface HTTPResponseTest (PrivateAPI) 39 | - (void)doAsyncStuff; 40 | - (void)asyncStuffFinished; 41 | @end 42 | 43 | 44 | @implementation HTTPResponseTest 45 | 46 | - (id)initWithConnection:(HTTPConnection *)parent 47 | { 48 | if ((self = [super init])) 49 | { 50 | HTTPLogTrace(); 51 | 52 | connection = parent; 53 | responseQueue = dispatch_queue_create("HTTPResponseTest", NULL); 54 | 55 | readyToSendResponseHeaders = NO; 56 | 57 | [self doAsyncStuff]; 58 | } 59 | return self; 60 | } 61 | 62 | - (void)doAsyncStuff 63 | { 64 | HTTPLogTrace(); 65 | 66 | dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0); 67 | dispatch_async(concurrentQueue, ^{ @autoreleasepool { 68 | 69 | // Simulate a long-running asynchronous task... 70 | [NSThread sleepForTimeInterval:5.0]; 71 | 72 | // Simulate completion callback 73 | dispatch_async(responseQueue, ^{ @autoreleasepool { 74 | 75 | [self asyncStuffFinished]; 76 | }}); 77 | }}); 78 | } 79 | 80 | - (void)asyncStuffFinished 81 | { 82 | // This method is executed on the responseQueue 83 | 84 | HTTPLogTrace(); 85 | 86 | // Enable flag that indicates we have enough information to send the response headers. 87 | readyToSendResponseHeaders = YES; 88 | 89 | // Then notify the connection that "something has changed". 90 | // The 'responseHasAvailableData:' method is thread-safe. 91 | // It knows what state the connection is in, and will "do the right thing". 92 | // In this case, it will requery us via delayResponseHeaders to see if it can send the headers yet. 93 | [connection responseHasAvailableData:self]; 94 | } 95 | 96 | - (BOOL)delayResponseHeaders 97 | { 98 | HTTPLogTrace2(@"%@[%p] %@ -> %@", THIS_FILE, self, THIS_METHOD, (readyToSendResponseHeaders ? @"NO" : @"YES")); 99 | 100 | __block BOOL delayResponseHeaders = NO; 101 | 102 | dispatch_sync(responseQueue, ^{ 103 | 104 | delayResponseHeaders = !readyToSendResponseHeaders; 105 | }); 106 | 107 | return delayResponseHeaders; 108 | } 109 | 110 | - (void)connectionDidClose 111 | { 112 | HTTPLogTrace(); 113 | 114 | dispatch_sync(responseQueue, ^{ 115 | connection = nil; 116 | }); 117 | } 118 | 119 | - (UInt64)contentLength 120 | { 121 | HTTPLogTrace(); 122 | 123 | __block UInt64 contentLength = 0; 124 | 125 | dispatch_sync(responseQueue, ^{ 126 | 127 | // Normal code would go here 128 | contentLength = 0; 129 | }); 130 | 131 | return contentLength; 132 | } 133 | 134 | - (UInt64)offset 135 | { 136 | HTTPLogTrace(); 137 | 138 | __block UInt64 offset = 0; 139 | 140 | dispatch_sync(responseQueue, ^{ 141 | 142 | // Normal code would go here 143 | offset = 0; 144 | }); 145 | 146 | return offset; 147 | } 148 | 149 | - (void)setOffset:(UInt64)offset 150 | { 151 | HTTPLogTrace(); 152 | 153 | dispatch_sync(responseQueue, ^{ 154 | 155 | // Normal code would go here 156 | }); 157 | } 158 | 159 | - (NSData *)readDataOfLength:(NSUInteger)length 160 | { 161 | HTTPLogTrace(); 162 | 163 | __block NSData *data = nil; 164 | 165 | dispatch_sync(responseQueue, ^{ 166 | 167 | // Normal code would go here 168 | }); 169 | 170 | return data; 171 | } 172 | 173 | - (BOOL)isDone 174 | { 175 | HTTPLogTrace(); 176 | 177 | __block BOOL isDone = NO; 178 | 179 | dispatch_sync(responseQueue, ^{ 180 | 181 | // Normal code would go here 182 | isDone = YES; 183 | }); 184 | 185 | return isDone; 186 | } 187 | 188 | - (void)dealloc 189 | { 190 | HTTPLogTrace(); 191 | 192 | #if NEEDS_DISPATCH_RETAIN_RELEASE 193 | dispatch_release(responseQueue); 194 | #endif 195 | } 196 | 197 | @end 198 | -------------------------------------------------------------------------------- /Vendor/CocoaLumberjack/Extensions/DispatchQueueLogFormatter.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "DDLog.h" 4 | 5 | 6 | /** 7 | * Welcome to Cocoa Lumberjack! 8 | * 9 | * The project page has a wealth of documentation if you have any questions. 10 | * https://github.com/robbiehanson/CocoaLumberjack 11 | * 12 | * If you're new to the project you may wish to read the "Getting Started" page. 13 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 14 | * 15 | * 16 | * This class provides a log formatter that prints the dispatch_queue label instead of the mach_thread_id. 17 | * 18 | * A log formatter can be added to any logger to format and/or filter its output. 19 | * You can learn more about log formatters here: 20 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/CustomFormatters 21 | * 22 | * A typical NSLog (or DDTTYLogger) prints detailed info as [:]. 23 | * For example: 24 | * 25 | * 2011-10-17 20:21:45.435 AppName[19928:5207] Your log message here 26 | * 27 | * Where: 28 | * - 19928 = process id 29 | * - 5207 = thread id (mach_thread_id printed in hex) 30 | * 31 | * When using grand central dispatch (GCD), this information is less useful. 32 | * This is because a single serial dispatch queue may be run on any thread from an internally managed thread pool. 33 | * For example: 34 | * 35 | * 2011-10-17 20:32:31.111 AppName[19954:4d07] Message from my_serial_dispatch_queue 36 | * 2011-10-17 20:32:31.112 AppName[19954:5207] Message from my_serial_dispatch_queue 37 | * 2011-10-17 20:32:31.113 AppName[19954:2c55] Message from my_serial_dispatch_queue 38 | * 39 | * This formatter allows you to replace the standard [box:info] with the dispatch_queue name. 40 | * For example: 41 | * 42 | * 2011-10-17 20:32:31.111 AppName[img-scaling] Message from my_serial_dispatch_queue 43 | * 2011-10-17 20:32:31.112 AppName[img-scaling] Message from my_serial_dispatch_queue 44 | * 2011-10-17 20:32:31.113 AppName[img-scaling] Message from my_serial_dispatch_queue 45 | * 46 | * If the dispatch_queue doesn't have a set name, then it falls back to the thread name. 47 | * If the current thread doesn't have a set name, then it falls back to the mach_thread_id in hex (like normal). 48 | * 49 | * Note: If manually creating your own background threads (via NSThread/alloc/init or NSThread/detachNeThread), 50 | * you can use [[NSThread currentThread] setName:(NSString *)]. 51 | **/ 52 | @interface DispatchQueueLogFormatter : NSObject { 53 | @protected 54 | 55 | NSString *dateFormatString; 56 | } 57 | 58 | /** 59 | * Standard init method. 60 | * Configure using properties as desired. 61 | **/ 62 | - (id)init; 63 | 64 | /** 65 | * The minQueueLength restricts the minimum size of the [detail box]. 66 | * If the minQueueLength is set to 0, there is no restriction. 67 | * 68 | * For example, say a dispatch_queue has a label of "diskIO": 69 | * 70 | * If the minQueueLength is 0: [diskIO] 71 | * If the minQueueLength is 4: [diskIO] 72 | * If the minQueueLength is 5: [diskIO] 73 | * If the minQueueLength is 6: [diskIO] 74 | * If the minQueueLength is 7: [diskIO ] 75 | * If the minQueueLength is 8: [diskIO ] 76 | * 77 | * The default minQueueLength is 0 (no minimum, so [detail box] won't be padded). 78 | * 79 | * If you want every [detail box] to have the exact same width, 80 | * set both minQueueLength and maxQueueLength to the same value. 81 | **/ 82 | @property (assign) NSUInteger minQueueLength; 83 | 84 | /** 85 | * The maxQueueLength restricts the number of characters that will be inside the [detail box]. 86 | * If the maxQueueLength is 0, there is no restriction. 87 | * 88 | * For example, say a dispatch_queue has a label of "diskIO": 89 | * 90 | * If the maxQueueLength is 0: [diskIO] 91 | * If the maxQueueLength is 4: [disk] 92 | * If the maxQueueLength is 5: [diskI] 93 | * If the maxQueueLength is 6: [diskIO] 94 | * If the maxQueueLength is 7: [diskIO] 95 | * If the maxQueueLength is 8: [diskIO] 96 | * 97 | * The default maxQueueLength is 0 (no maximum, so [detail box] won't be truncated). 98 | * 99 | * If you want every [detail box] to have the exact same width, 100 | * set both minQueueLength and maxQueueLength to the same value. 101 | **/ 102 | @property (assign) NSUInteger maxQueueLength; 103 | 104 | /** 105 | * Sometimes queue labels have long names like "com.apple.main-queue", 106 | * but you'd prefer something shorter like simply "main". 107 | * 108 | * This method allows you to set such preferred replacements. 109 | * The above example is set by default. 110 | * 111 | * To remove/undo a previous replacement, invoke this method with nil for the 'shortLabel' parameter. 112 | **/ 113 | - (NSString *)replacementStringForQueueLabel:(NSString *)longLabel; 114 | - (void)setReplacementString:(NSString *)shortLabel forQueueLabel:(NSString *)longLabel; 115 | 116 | @end 117 | --------------------------------------------------------------------------------