81 Commits
3.2.5 ... 3.3.3

Author SHA1 Message Date
Pierre-Olivier Latour
43555c6662 Merge pull request #272 from bizz84/master
Removed cs.default_subspec from subspecs as this is now disallowed
2016-07-15 11:46:05 -07:00
Andrea Bizzotto
7c08c54156 Removed cs.default_subspec from subspecs as this is now disallowed in Cocoapods 2016-07-15 19:23:27 +01:00
Pierre-Olivier Latour
5834770e08 Removed exception handling which was only partial anyway 2016-06-29 21:38:57 -07:00
Pierre-Olivier Latour
52406a12c2 Merge pull request #267 from hsin919/master
Fix the typo in swift samples
2016-06-29 09:15:10 -07:00
Pierre-Olivier Latour
e83814b0fa Merge pull request #269 from opsGavin/patch-1
Typo in GCDWebServerGZipDecoder:open
2016-06-29 09:11:43 -07:00
Gavin MacLean
fba593a602 Typo in GCDWebServerGZipDecoder:open
I haven't tested or dug into this, as I just happened to spot it while looking through a colleagues code.

It looks like `inflateInit2` is called and then `deflateEnd` on error. I'm wondering if this is a copy and paste issue from `GCDWebServerGZipEncoder` and really it should be `inflateEnd` here instead?
2016-06-29 15:36:40 +01:00
hsin
eec17d5c7b Fix the typo in swift samples 2016-06-08 09:25:04 +08:00
Pierre-Olivier Latour
32bc72113a Merge pull request #266 from DD-P/read-me-typo-fix
Minor documentation fix: "owns" -> "own"
2016-05-08 08:00:48 -07:00
David Davies-Payne
200d21c3fa Minor documentation fix: "owns" -> "own" 2016-05-08 19:32:34 +12:00
Pierre-Olivier Latour
3042b853bc Fix 2016-04-17 20:07:54 -07:00
Pierre-Olivier Latour
50eb0437c1 Updated for Xcode 7.3 2016-04-17 20:07:49 -07:00
Pierre-Olivier Latour
00cc560b8e Merge pull request #264 from AmpMe/refacor/add-queue-priorty-as-an-option
Add an option to set the priority of the dispatch queue
2016-04-03 17:53:13 -07:00
Martin Gagnon
fa41f26b30 Add an option to set the priority of the dispatch queue 2016-04-03 20:11:35 -04:00
Pierre-Olivier Latour
845969ec0d Merge pull request #262 from pra85/patch-1
Fix a typo in Readme
2016-03-24 06:36:57 -07:00
Prayag Verma
629df7895d Fix a typo in Readme
`asynchronously` → `asynchronously`
2016-02-18 13:32:09 +05:30
Pierre-Olivier Latour
55104e5b1e Update README.md 2016-02-08 01:00:25 -08:00
Pierre-Olivier Latour
fcc95fdc11 Merge pull request #260 from jjrscott/master
Added __kindof keyword where appropriate
2016-02-07 17:18:39 -08:00
John Scott
10a94e36fd Removed guards around __kindof usage as the project is Xcode 7 only. 2016-02-06 12:18:49 +00:00
John Scott
010ef9b8bc Added __kindof keyword where appropriate to avoid errors of the form "incompatible block pointer types sending 'GCDWebServerResponse *(^)(GCDWebServerDataRequest *__strong)' to parameter of type 'GCDWebServerProcessBlock' (aka 'GCDWebServerResponse *(^)(GCDWebServerRequest *__strong)')" 2016-02-05 20:45:46 +00:00
Pierre-Olivier Latour
5ca7c27a07 Bumped version 2016-01-20 07:24:59 -08:00
Pierre-Olivier Latour
c6632633f8 Disabled address sanitizer 2016-01-20 07:21:37 -08:00
Pierre-Olivier Latour
5b6eebbb9e Fixed build warning 2016-01-20 07:21:18 -08:00
Pierre-Olivier Latour
a4c61bd071 Bumped version 2016-01-16 06:29:35 -08:00
Pierre-Olivier Latour
2543279a6d Merge pull request #256 from anton-matosov/master
Fixed CocoaLumberjack deps
2016-01-15 10:19:28 -08:00
Anton Matosov
95231b1a66 Fixed CocoaLumberjack deps 2016-01-15 07:54:14 -08:00
Pierre-Olivier Latour
5f2877b85f Merge pull request #255 from iosphere/check-range-location
Fix NSRangeException by checking range of NSTextCheckingResult
2016-01-08 09:18:39 -08:00
Lukas Mollidor
47a51c3d42 Fix NSRangeException by checking range of NSTextCheckingResult 2016-01-08 18:06:55 +01:00
Pierre-Olivier Latour
3873dd1ad3 Merge pull request #248 from dcrawshay/master
Support WebDAV GET request byte ranges
2016-01-03 18:23:28 -08:00
David Crawshay
2ff10258e7 Fixed WebDAV test response files to correctly represent the requested byte-range response instead of the entire file. 2016-01-02 01:58:40 -06:00
David Crawshay
4360c4f7db Support WebDAV GET request byte ranges 2016-01-01 23:23:43 -06:00
Pierre-Olivier Latour
8a6a139687 Merge pull request #236 from maeldur/master
Fixed GCDWebServerGetPrimaryIPAddress() on tvOS devices
2015-12-15 17:03:52 -05:00
Pierre-Olivier Latour
4eba86f348 Merge pull request #238 from bendytree/master
Add libz instructions to readme
2015-12-14 23:02:34 -08:00
Pierre-Olivier Latour
ea973735c1 Also set CFBundleVersion in Info.plist 2015-12-14 22:38:53 -08:00
Pierre-Olivier Latour
5707076e8d Updated to Xcode 7.2 2015-12-14 22:31:53 -08:00
Pierre-Olivier Latour
e1fb807a93 Bumped version 2015-12-14 22:31:47 -08:00
Josh Wright
71575729e9 Added libz and header instructions to readme 2015-11-03 16:28:51 -06:00
Josh Wright
94e30f6442 Added libz and header instructions to readme 2015-11-03 16:23:05 -06:00
Pierre-Olivier Latour
c98941121a Use Xcode 7.1 in Travis CI 2015-11-01 13:14:42 -08:00
Pierre-Olivier Latour
4ee9c30911 Fixed build script 2015-11-01 13:12:57 -08:00
Pierre-Olivier Latour
48cf20bb55 Updated iOS app to latest best practices 2015-11-01 11:38:49 -08:00
Pierre-Olivier Latour
ac9b8a5f47 Added support for tvOS 2015-11-01 11:38:49 -08:00
Pierre-Olivier Latour
cad428ca6f Removed deprecation warnings on tvOS 2015-11-01 11:25:18 -08:00
Pierre-Olivier Latour
bb5c1a5195 No need to link explicitly to Foundation 2015-11-01 11:25:18 -08:00
Pierre-Olivier Latour
bef95231d2 Updated for Xcode 7.1 2015-11-01 11:25:18 -08:00
Pierre-Olivier Latour
0192c364b6 Fix 2015-11-01 11:25:11 -08:00
Nick Chang
062a0dcee4 allow serverURL to be assigned on tvOS with wifi connection 2015-10-30 12:31:27 -07:00
Pierre-Olivier Latour
21d9fc2f62 Merge pull request #228 from CrossWaterBridge/tvos
Enable support for tvOS
2015-10-17 12:48:07 -07:00
Hilton Campbell
614ff58be5 Enable support for tvOS. 2015-10-17 13:46:46 -06:00
Pierre-Olivier Latour
7b0477b1e0 Merge pull request #219 from macdrevx/pods-use-frameworks
Enable support for Podfiles with use_frameworks!
2015-09-28 11:40:16 -07:00
Andrew Hershberger
a674614713 Enable support for Podfiles with use_frameworks!
The previous implementation looked in the main
bundle for the GCDWebUploader resource bundle.
When using the use_frameworks! Podfile option, the
resource bundle will be in a framework bundle, not
in the main bundle.
2015-09-22 15:22:45 -04:00
Pierre-Olivier Latour
b549f1197d Merge pull request #218 from tifroz/master
Fixed async handler crash under Swift 2
2015-09-21 15:20:48 -07:00
tifroz
9d38bb4f94 Workaround for Swift2 which apparently fails to retain the completion blocks passed as parameters 2015-09-21 15:15:58 -07:00
Pierre-Olivier Latour
44c6a8adcf Update README.md
[ci skip]
2015-09-16 11:40:19 -07:00
Pierre-Olivier Latour
aaf8679308 Increased Bonjour resolution timeout to 5 seconds 2015-09-16 11:34:16 -07:00
Pierre-Olivier Latour
81d74b46b8 Fix 2015-09-16 11:26:00 -07:00
Pierre-Olivier Latour
f7de5cac09 Fix 2015-09-16 11:24:08 -07:00
Pierre-Olivier Latour
a1c68352a4 Bumped version to 3.3 2015-09-16 11:19:02 -07:00
Pierre-Olivier Latour
e70a3338a5 Added support for NAT port mapping 2015-09-16 11:16:41 -07:00
Pierre-Olivier Latour
3c33e9f056 Bumped version to 3.2.7 2015-09-10 09:02:07 -07:00
Pierre-Olivier Latour
d160e5ff91 Merge pull request #213 from 0xpablo/master
Turn 'buildForRunning' on for 'GCDWebServers' iOS and Mac Schemes
2015-09-10 09:01:04 -07:00
Pablo Carcelén
2d2343ab34 Turn 'buildForRunning' on for 'GCDWebServers' iOS and Mac Schemes
This fixes building the project using Carthage (See #212)
2015-09-10 17:14:59 +02:00
Pierre-Olivier Latour
f6783daadd Updated test script to run built-in tests 2015-09-09 09:41:00 -07:00
Pierre-Olivier Latour
99cae36644 Added minimal tests for Mac framework 2015-09-09 09:36:29 -07:00
Pierre-Olivier Latour
b292710102 Fix 2015-09-09 08:41:08 -07:00
Pierre-Olivier Latour
b8b4a35178 Add version to framework Info.plist 2015-09-09 08:37:51 -07:00
Pierre-Olivier Latour
ecc572a934 Bumped version to 3.2.6 2015-09-09 08:37:36 -07:00
Pierre-Olivier Latour
3a02341b0c Disable testing and running in shared schemes for frameworks 2015-09-09 08:31:18 -07:00
Pierre-Olivier Latour
e792fe8eb6 Fixes 2015-09-09 08:30:54 -07:00
Pierre-Olivier Latour
4c8ec1d685 Removed unnecessary files from Xcode project 2015-09-09 08:25:53 -07:00
Pierre-Olivier Latour
f7bb5babf8 Bumped copyright year 2015-09-09 08:24:47 -07:00
Pierre-Olivier Latour
ae88198f20 Update README.md 2015-08-13 20:29:26 -07:00
Pierre-Olivier Latour
d71c0d493f Update README.md 2015-08-03 08:46:44 -07:00
Pierre-Olivier Latour
d611ae0cbe Merge pull request #187 from lfaoro/patch-2
Update README.md
2015-07-06 16:07:02 -07:00
Leonard
93287edfd5 Update README.md
The previous code won't compile in Swift, it had a missing ')' and the 'println' statement is deprecated, replaced by 'print'.
The bridging-headers syntax was wrong, couldn't compile.
Swift still requires an 'import GCDWebServers' statement to use the API
2015-07-07 00:17:31 +02:00
Pierre-Olivier Latour
dc287906d6 Merge pull request #186 from lfaoro/patch-1
Update README.md
2015-07-06 10:44:57 -07:00
Leonard
ab9459a67a Update README.md
the version number should not have quotes, with the quotes carthage errors: 
Parse error: unexpected trailing characters in line: github "swisspol/GCDWebServer" ~> "3.2.5"
2015-07-06 19:26:07 +02:00
Pierre-Olivier Latour
aa8fc97b9b Fixed buffer overflow when retrieving socket addresses 2015-07-03 10:17:33 -07:00
Pierre-Olivier Latour
863febed62 Updated for Xcode 7 2015-07-03 09:55:46 -07:00
Pierre-Olivier Latour
2ff117dbf3 Merge pull request #183 from guidomb/patch-1
Fixes error in Carthage documentation
2015-07-03 09:44:00 -07:00
Guido Marucci Blas
4838d0def9 Fixes error in Carthage documentation
~> is like an operator and does not go inside the version string. https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile
2015-07-03 13:43:03 -03:00
Pierre-Olivier Latour
c394ae8bf5 Update README.md 2015-07-03 08:51:42 -07:00
85 changed files with 1910 additions and 344 deletions

View File

@@ -1,2 +1,3 @@
language: objective-c
script: ./Run-Tests.sh
osx_image: xcode7.1

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -25,21 +25,25 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// GCDWebServer
// GCDWebServer Core
#import <GCDWebServers/GCDWebServer.h>
#import <GCDWebServers/GCDWebServerHTTPStatusCodes.h>
#import <GCDWebServers/GCDWebServerRequest.h>
#import <GCDWebServers/GCDWebServerErrorResponse.h>
#import <GCDWebServers/GCDWebServerURLEncodedFormRequest.h>
#import <GCDWebServers/GCDWebServerResponse.h>
#import <GCDWebServers/GCDWebServerFileResponse.h>
#import <GCDWebServers/GCDWebServerMultiPartFormRequest.h>
#import <GCDWebServers/GCDWebServerStreamedResponse.h>
#import <GCDWebServers/GCDWebServerConnection.h>
#import <GCDWebServers/GCDWebServerDataRequest.h>
#import <GCDWebServers/GCDWebServerDataResponse.h>
#import <GCDWebServers/GCDWebServerFunctions.h>
#import <GCDWebServers/GCDWebServerHTTPStatusCodes.h>
#import <GCDWebServers/GCDWebServerResponse.h>
#import <GCDWebServers/GCDWebServerRequest.h>
// GCDWebServer Requests
#import <GCDWebServers/GCDWebServerDataRequest.h>
#import <GCDWebServers/GCDWebServerFileRequest.h>
#import <GCDWebServers/GCDWebServerMultiPartFormRequest.h>
#import <GCDWebServers/GCDWebServerURLEncodedFormRequest.h>
// GCDWebServer Responses
#import <GCDWebServers/GCDWebServerDataResponse.h>
#import <GCDWebServers/GCDWebServerErrorResponse.h>
#import <GCDWebServers/GCDWebServerFileResponse.h>
#import <GCDWebServers/GCDWebServerStreamedResponse.h>
// GCDWebUploader
#import <GCDWebServers/GCDWebUploader.h>

View File

@@ -7,12 +7,16 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>net.pol-online.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleVersion</key>
<string>${BUNDLE_VERSION_STRING}</string>
<key>CFBundleShortVersionString</key>
<string>${BUNDLE_VERSION_STRING}</string>
</dict>
</plist>

24
Frameworks/Tests.m Normal file
View File

@@ -0,0 +1,24 @@
#import <GCDWebServers/GCDWebServers.h>
#import <XCTest/XCTest.h>
@interface Tests : XCTestCase
@end
@implementation Tests
- (void)testWebServer {
GCDWebServer* server = [[GCDWebServer alloc] init];
XCTAssertNotNil(server);
}
- (void)testDAVServer {
GCDWebDAVServer* server = [[GCDWebDAVServer alloc] init];
XCTAssertNotNil(server);
}
- (void)testWebUploader {
GCDWebUploader* server = [[GCDWebUploader alloc] init];
XCTAssertNotNil(server);
}
@end

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -115,6 +115,11 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) {
[self.delegate davServer:self didDownloadFileAtPath:absolutePath];
});
}
if ([request hasByteRange]) {
return [GCDWebServerFileResponse responseWithFile:absolutePath byteRange:request.byteRange];
}
return [GCDWebServerFileResponse responseWithFile:absolutePath];
}
@@ -261,7 +266,10 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) {
if ((dstRelativePath == nil) || (range.location == NSNotFound)) {
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Malformed 'Destination' header: %@", dstRelativePath];
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
dstRelativePath = [[dstRelativePath substringFromIndex:(range.location + range.length)] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
#pragma clang diagnostic pop
NSString* dstAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:dstRelativePath];
if (![self _checkSandboxedPath:dstAbsolutePath]) {
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", srcRelativePath];
@@ -333,7 +341,10 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name
}
- (void)_addPropertyResponseForItem:(NSString*)itemPath resource:(NSString*)resourcePath properties:(DAVProperties)properties xmlString:(NSMutableString*)xmlString {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
CFStringRef escapedPath = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)resourcePath, NULL, CFSTR("<&>?+"), kCFStringEncodingUTF8);
#pragma clang diagnostic pop
if (escapedPath) {
NSDictionary* attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:itemPath error:NULL];
NSString* type = [attributes objectForKey:NSFileType];

View File

@@ -2,12 +2,12 @@
# http://guides.cocoapods.org/making/getting-setup-with-trunk.html
# $ sudo gem update cocoapods
# (optional) $ pod trunk register {email} {name} --description={computer}
# $ pod trunk push
# $ pod trunk --verbose push
# DELETE THIS SECTION BEFORE PROCEEDING!
Pod::Spec.new do |s|
s.name = 'GCDWebServer'
s.version = '3.2.5'
s.version = '3.3.3'
s.author = { 'Pierre-Olivier Latour' => 'info@pol-online.net' }
s.license = { :type => 'BSD', :file => 'LICENSE' }
s.homepage = 'https://github.com/swisspol/GCDWebServer'
@@ -15,6 +15,7 @@ Pod::Spec.new do |s|
s.source = { :git => 'https://github.com/swisspol/GCDWebServer.git', :tag => s.version.to_s }
s.ios.deployment_target = '5.0'
s.tvos.deployment_target = '9.0'
s.osx.deployment_target = '10.7'
s.requires_arc = true
@@ -26,24 +27,45 @@ Pod::Spec.new do |s|
cs.requires_arc = true
cs.ios.library = 'z'
cs.ios.frameworks = 'MobileCoreServices', 'CFNetwork'
cs.tvos.library = 'z'
cs.tvos.frameworks = 'MobileCoreServices', 'CFNetwork'
cs.osx.library = 'z'
cs.osx.framework = 'SystemConfiguration'
end
s.subspec 'WebDAV' do |cs|
s.subspec "CocoaLumberjack" do |cs|
cs.dependency 'GCDWebServer/Core'
cs.source_files = 'GCDWebDAVServer/*.{h,m}'
cs.requires_arc = true
cs.ios.library = 'xml2'
cs.osx.library = 'xml2'
cs.compiler_flags = '-I$(SDKROOT)/usr/include/libxml2'
cs.dependency 'CocoaLumberjack', '~> 2'
end
s.subspec 'WebDAV' do |cs|
cs.subspec "Core" do |ccs|
ccs.dependency 'GCDWebServer/Core'
ccs.source_files = 'GCDWebDAVServer/*.{h,m}'
ccs.requires_arc = true
ccs.ios.library = 'xml2'
ccs.tvos.library = 'xml2'
ccs.osx.library = 'xml2'
ccs.compiler_flags = '-I$(SDKROOT)/usr/include/libxml2'
end
cs.subspec "CocoaLumberjack" do |cscl|
cscl.dependency 'GCDWebServer/WebDAV/Core'
cscl.dependency 'GCDWebServer/CocoaLumberjack'
end
end
s.subspec 'WebUploader' do |cs|
cs.dependency 'GCDWebServer/Core'
cs.source_files = 'GCDWebUploader/*.{h,m}'
cs.requires_arc = true
cs.resource = "GCDWebUploader/GCDWebUploader.bundle"
end
cs.subspec "Core" do |ccs|
ccs.dependency 'GCDWebServer/Core'
ccs.source_files = 'GCDWebUploader/*.{h,m}'
ccs.requires_arc = true
ccs.resource = "GCDWebUploader/GCDWebUploader.bundle"
end
cs.subspec "CocoaLumberjack" do |cscl|
cscl.dependency 'GCDWebServer/WebUploader/Core'
cscl.dependency 'GCDWebServer/CocoaLumberjack'
end
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0630"
LastUpgradeVersion = "0730"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForTesting = "NO"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
@@ -23,21 +23,34 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E24039241BA09207000B7089"
BuildableName = "Tests.xctest"
BlueprintName = "Tests (Mac)"
ReferencedContainer = "container:GCDWebServer.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
@@ -52,10 +65,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference

View File

@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0630"
LastUpgradeVersion = "0730"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForTesting = "NO"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
@@ -23,21 +23,33 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "CEE28CEE1AE0051F00F4023C"
BuildableName = "GCDWebServers.framework"
BlueprintName = "GCDWebServers (iOS)"
ReferencedContainer = "container:GCDWebServer.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
@@ -52,10 +64,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference

View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0730"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "NO"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E2DDD18A1BE69404002CE867"
BuildableName = "GCDWebServers.framework"
BlueprintName = "GCDWebServers (tvOS)"
ReferencedContainer = "container:GCDWebServer.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E2DDD18A1BE69404002CE867"
BuildableName = "GCDWebServers.framework"
BlueprintName = "GCDWebServers (tvOS)"
ReferencedContainer = "container:GCDWebServer.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E2DDD18A1BE69404002CE867"
BuildableName = "GCDWebServers.framework"
BlueprintName = "GCDWebServers (tvOS)"
ReferencedContainer = "container:GCDWebServer.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E2DDD18A1BE69404002CE867"
BuildableName = "GCDWebServers.framework"
BlueprintName = "GCDWebServers (tvOS)"
ReferencedContainer = "container:GCDWebServer.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -52,7 +52,7 @@ typedef GCDWebServerRequest* (^GCDWebServerMatchBlock)(NSString* requestMethod,
* recommended to return a GCDWebServerErrorResponse on error so more useful
* information can be returned to the client.
*/
typedef GCDWebServerResponse* (^GCDWebServerProcessBlock)(GCDWebServerRequest* request);
typedef GCDWebServerResponse* (^GCDWebServerProcessBlock)(__kindof GCDWebServerRequest* request);
/**
* The GCDWebServerAsynchronousProcessBlock works like the GCDWebServerProcessBlock
@@ -65,7 +65,7 @@ typedef GCDWebServerResponse* (^GCDWebServerProcessBlock)(GCDWebServerRequest* r
* useful information can be returned to the client.
*/
typedef void (^GCDWebServerCompletionBlock)(GCDWebServerResponse* response);
typedef void (^GCDWebServerAsyncProcessBlock)(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock);
typedef void (^GCDWebServerAsyncProcessBlock)(__kindof GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock);
/**
* The port used by the GCDWebServer (NSNumber / NSUInteger).
@@ -90,14 +90,26 @@ extern NSString* const GCDWebServerOption_BonjourName;
*/
extern NSString* const GCDWebServerOption_BonjourType;
/**
* Request a port mapping in the NAT gateway (NSNumber / BOOL).
*
* This uses the DNSService API under the hood which supports IPv4 mappings only.
*
* The default value is NO.
*
* @warning The external port set up by the NAT gateway may be different than
* the one used by the GCDWebServer.
*/
extern NSString* const GCDWebServerOption_RequestNATPortMapping;
/**
* Only accept HTTP requests coming from localhost i.e. not from the outside
* network (NSNumber / BOOL).
*
* The default value is NO.
*
* @warning Bonjour should be disabled if using this option since the server
* will not be reachable from the outside network anyway.
* @warning Bonjour and NAT port mapping should be disabled if using this option
* since the server will not be reachable from the outside network anyway.
*/
extern NSString* const GCDWebServerOption_BindToLocalhost;
@@ -164,6 +176,15 @@ extern NSString* const GCDWebServerOption_AutomaticallyMapHEADToGET;
*/
extern NSString* const GCDWebServerOption_ConnectedStateCoalescingInterval;
/**
* Set the dispatch queue priority on which server connection will be
* run (NSNumber / long).
*
*
* The default value is DISPATCH_QUEUE_PRIORITY_DEFAULT.
*/
extern NSString* const GCDWebServerOption_DispatchQueuePriority;
#if TARGET_OS_IPHONE
/**
@@ -213,9 +234,21 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
/**
* This method is called after the Bonjour registration for the server has
* successfully completed.
*
* Use the "bonjourServerURL" property to retrieve the Bonjour address of the
* server.
*/
- (void)webServerDidCompleteBonjourRegistration:(GCDWebServer*)server;
/**
* This method is called after the NAT port mapping for the server has been
* updated.
*
* Use the "publicServerURL" property to retrieve the public address of the
* server.
*/
- (void)webServerDidUpdateNATPortMapping:(GCDWebServer*)server;
/**
* This method is called when the first GCDWebServerConnection is opened by the
* server to serve a series of HTTP requests.
@@ -362,6 +395,14 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
*/
@property(nonatomic, readonly) NSURL* bonjourServerURL;
/**
* Returns the server's public URL.
*
* @warning This property is only valid if the server is running and NAT port
* mapping is active.
*/
@property(nonatomic, readonly) NSURL* publicServerURL;
/**
* Starts the server on port 8080 (OS X & iOS Simulator) or port 80 (iOS)
* using the default Bonjour name.
@@ -505,12 +546,10 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
* GWS_LOG_INFO(...)
* GWS_LOG_WARNING(...)
* GWS_LOG_ERROR(...)
* GWS_LOG_EXCEPTION(__EXCEPTION__)
*
* IMPORTANT: Except for GWS_LOG_EXCEPTION() which gets passed an NSException,
* these macros must behave like NSLog(). Furthermore the GWS_LOG_DEBUG() macro
* should not do anything unless the preprocessor constant "DEBUG" evaluates to
* non-zero.
* IMPORTANT: These macros must behave like NSLog(). Furthermore the GWS_LOG_DEBUG()
* macro should not do anything unless the preprocessor constant "DEBUG" evaluates
* to non-zero.
*
* The logging methods below send log messages to the same logging facility
* used by GCDWebServer. They can be used for consistency wherever you interact
@@ -530,7 +569,6 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
* INFO = 2
* WARNING = 3
* ERROR = 4
* EXCEPTION = 5
*/
+ (void)setLogLevel:(int)level;
@@ -554,11 +592,6 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
*/
- (void)logError:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
/**
* Logs an exception to the logging facility at the EXCEPTION level.
*/
- (void)logException:(NSException*)exception;
@end
#ifdef __GCDWEBSERVER_ENABLE_TESTING__

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,7 @@
#endif
#endif
#import <netinet/in.h>
#import <dns_sd.h>
#import "GCDWebServerPrivate.h"
@@ -47,9 +48,12 @@
#define kDefaultPort 8080
#endif
#define kBonjourResolutionTimeout 5.0
NSString* const GCDWebServerOption_Port = @"Port";
NSString* const GCDWebServerOption_BonjourName = @"BonjourName";
NSString* const GCDWebServerOption_BonjourType = @"BonjourType";
NSString* const GCDWebServerOption_RequestNATPortMapping = @"RequestNATPortMapping";
NSString* const GCDWebServerOption_BindToLocalhost = @"BindToLocalhost";
NSString* const GCDWebServerOption_MaxPendingConnections = @"MaxPendingConnections";
NSString* const GCDWebServerOption_ServerName = @"ServerName";
@@ -59,6 +63,7 @@ NSString* const GCDWebServerOption_AuthenticationAccounts = @"AuthenticationAcco
NSString* const GCDWebServerOption_ConnectionClass = @"ConnectionClass";
NSString* const GCDWebServerOption_AutomaticallyMapHEADToGET = @"AutomaticallyMapHEADToGET";
NSString* const GCDWebServerOption_ConnectedStateCoalescingInterval = @"ConnectedStateCoalescingInterval";
NSString* const GCDWebServerOption_DispatchQueuePriority = @"DispatchQueuePriority";
#if TARGET_OS_IPHONE
NSString* const GCDWebServerOption_AutomaticallySuspendInBackground = @"AutomaticallySuspendInBackground";
#endif
@@ -87,7 +92,7 @@ static BOOL _run;
#ifdef __GCDWEBSERVER_LOGGING_FACILITY_BUILTIN__
void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* format, ...) {
static const char* levelNames[] = {"DEBUG", "VERBOSE", "INFO", "WARNING", "ERROR", "EXCEPTION"};
static const char* levelNames[] = {"DEBUG", "VERBOSE", "INFO", "WARNING", "ERROR"};
static int enableLogging = -1;
if (enableLogging < 0) {
enableLogging = (isatty(STDERR_FILENO) ? 1 : 0);
@@ -166,11 +171,17 @@ static void _ExecuteMainThreadRunLoopSources() {
Class _connectionClass;
BOOL _mapHEADToGET;
CFTimeInterval _disconnectDelay;
dispatch_queue_priority_t _dispatchQueuePriority;
NSUInteger _port;
dispatch_source_t _source4;
dispatch_source_t _source6;
CFNetServiceRef _registrationService;
CFNetServiceRef _resolutionService;
DNSServiceRef _dnsService;
CFSocketRef _dnsSocket;
CFRunLoopSourceRef _dnsSource;
NSString* _dnsAddress;
NSUInteger _dnsPort;
BOOL _bindToLocalhost;
#if TARGET_OS_IPHONE
BOOL _suspendInBackground;
@@ -186,7 +197,7 @@ static void _ExecuteMainThreadRunLoopSources() {
@synthesize delegate=_delegate, handlers=_handlers, port=_port, serverName=_serverName, authenticationRealm=_authenticationRealm,
authenticationBasicAccounts=_authenticationBasicAccounts, authenticationDigestAccounts=_authenticationDigestAccounts,
shouldAutomaticallyMapHEADToGET=_mapHEADToGET;
shouldAutomaticallyMapHEADToGET=_mapHEADToGET, dispatchQueuePriority=_dispatchQueuePriority;
+ (void)initialize {
GCDWebServerInitializeFunctions();
@@ -369,7 +380,10 @@ static void _NetServiceRegisterCallBack(CFNetServiceRef service, CFStreamError*
} else {
GCDWebServer* server = (__bridge GCDWebServer*)info;
GWS_LOG_VERBOSE(@"Bonjour registration complete for %@", [server class]);
CFNetServiceResolveWithTimeout(server->_resolutionService, 1.0, NULL);
if (!CFNetServiceResolveWithTimeout(server->_resolutionService, kBonjourResolutionTimeout, NULL)) {
GWS_LOG_ERROR(@"Failed starting Bonjour resolution");
GWS_DNOT_REACHED();
}
}
}
}
@@ -383,7 +397,7 @@ static void _NetServiceResolveCallBack(CFNetServiceRef service, CFStreamError* e
}
} else {
GCDWebServer* server = (__bridge GCDWebServer*)info;
GWS_LOG_INFO(@"%@ now reachable at %@", [server class], server.bonjourServerURL);
GWS_LOG_INFO(@"%@ now locally reachable at %@", [server class], server.bonjourServerURL);
if ([server.delegate respondsToSelector:@selector(webServerDidCompleteBonjourRegistration:)]) {
[server.delegate webServerDidCompleteBonjourRegistration:server];
}
@@ -391,6 +405,41 @@ static void _NetServiceResolveCallBack(CFNetServiceRef service, CFStreamError* e
}
}
static void _DNSServiceCallBack(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, uint32_t externalAddress, DNSServiceProtocol protocol, uint16_t internalPort, uint16_t externalPort, uint32_t ttl, void* context) {
GWS_DCHECK([NSThread isMainThread]);
@autoreleasepool {
GCDWebServer* server = (__bridge GCDWebServer*)context;
if ((errorCode == kDNSServiceErr_NoError) || (errorCode == kDNSServiceErr_DoubleNAT)) {
struct sockaddr_in addr4;
bzero(&addr4, sizeof(addr4));
addr4.sin_len = sizeof(addr4);
addr4.sin_family = AF_INET;
addr4.sin_addr.s_addr = externalAddress; // Already in network byte order
server->_dnsAddress = GCDWebServerStringFromSockAddr((const struct sockaddr*)&addr4, NO);
server->_dnsPort = ntohs(externalPort);
GWS_LOG_INFO(@"%@ now publicly reachable at %@", [server class], server.publicServerURL);
} else {
GWS_LOG_ERROR(@"DNS service error %i", errorCode);
server->_dnsAddress = nil;
server->_dnsPort = 0;
}
if ([server.delegate respondsToSelector:@selector(webServerDidUpdateNATPortMapping:)]) {
[server.delegate webServerDidUpdateNATPortMapping:server];
}
}
}
static void _SocketCallBack(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void* data, void* info) {
GWS_DCHECK([NSThread isMainThread]);
@autoreleasepool {
GCDWebServer* server = (__bridge GCDWebServer*)info;
DNSServiceErrorType status = DNSServiceProcessResult(server->_dnsService);
if (status != kDNSServiceErr_NoError) {
GWS_LOG_ERROR(@"DNS service error %i", status);
}
}
}
static inline id _GetOption(NSDictionary* options, NSString* key, id defaultValue) {
id value = [options objectForKey:key];
return value ? value : defaultValue;
@@ -446,7 +495,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
- (dispatch_source_t)_createDispatchSourceWithListeningSocket:(int)listeningSocket isIPv6:(BOOL)isIPv6 {
dispatch_group_enter(_sourceGroup);
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, listeningSocket, 0, kGCDWebServerGCDQueue);
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, listeningSocket, 0, dispatch_get_global_queue(_dispatchQueuePriority, 0));
dispatch_source_set_cancel_handler(source, ^{
@autoreleasepool {
@@ -463,18 +512,18 @@ static inline NSString* _EncodeBase64(NSString* string) {
dispatch_source_set_event_handler(source, ^{
@autoreleasepool {
struct sockaddr remoteSockAddr;
struct sockaddr_storage remoteSockAddr;
socklen_t remoteAddrLen = sizeof(remoteSockAddr);
int socket = accept(listeningSocket, &remoteSockAddr, &remoteAddrLen);
int socket = accept(listeningSocket, (struct sockaddr*)&remoteSockAddr, &remoteAddrLen);
if (socket > 0) {
NSData* remoteAddress = [NSData dataWithBytes:&remoteSockAddr length:remoteAddrLen];
struct sockaddr localSockAddr;
struct sockaddr_storage localSockAddr;
socklen_t localAddrLen = sizeof(localSockAddr);
NSData* localAddress = nil;
if (getsockname(socket, &localSockAddr, &localAddrLen) == 0) {
if (getsockname(socket, (struct sockaddr*)&localSockAddr, &localAddrLen) == 0) {
localAddress = [NSData dataWithBytes:&localSockAddr length:localAddrLen];
GWS_DCHECK((!isIPv6 && localSockAddr.sa_family == AF_INET) || (isIPv6 && localSockAddr.sa_family == AF_INET6));
GWS_DCHECK((!isIPv6 && localSockAddr.ss_family == AF_INET) || (isIPv6 && localSockAddr.ss_family == AF_INET6));
} else {
GWS_DNOT_REACHED();
}
@@ -511,11 +560,10 @@ static inline NSString* _EncodeBase64(NSString* string) {
return NO;
}
if (port == 0) {
struct sockaddr addr;
struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
if (getsockname(listeningSocket4, &addr, &addrlen) == 0) {
struct sockaddr_in* sockaddr = (struct sockaddr_in*)&addr;
port = ntohs(sockaddr->sin_port);
if (getsockname(listeningSocket4, (struct sockaddr*)&addr, &addrlen) == 0) {
port = ntohs(addr.sin_port);
} else {
GWS_LOG_ERROR(@"Failed retrieving socket address: %s (%i)", strerror(errno), errno);
}
@@ -553,6 +601,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
_connectionClass = _GetOption(_options, GCDWebServerOption_ConnectionClass, [GCDWebServerConnection class]);
_mapHEADToGET = [_GetOption(_options, GCDWebServerOption_AutomaticallyMapHEADToGET, @YES) boolValue];
_disconnectDelay = [_GetOption(_options, GCDWebServerOption_ConnectedStateCoalescingInterval, @1.0) doubleValue];
_dispatchQueuePriority = [_GetOption(_options, GCDWebServerOption_DispatchQueuePriority, @(DISPATCH_QUEUE_PRIORITY_DEFAULT)) longValue];
_source4 = [self _createDispatchSourceWithListeningSocket:listeningSocket4 isIPv6:NO];
_source6 = [self _createDispatchSourceWithListeningSocket:listeningSocket6 isIPv6:YES];
@@ -575,9 +624,34 @@ static inline NSString* _EncodeBase64(NSString* string) {
if (_resolutionService) {
CFNetServiceSetClient(_resolutionService, _NetServiceResolveCallBack, &context);
CFNetServiceScheduleWithRunLoop(_resolutionService, CFRunLoopGetMain(), kCFRunLoopCommonModes);
} else {
GWS_LOG_ERROR(@"Failed creating CFNetService for resolution");
}
} else {
GWS_LOG_ERROR(@"Failed creating CFNetService");
GWS_LOG_ERROR(@"Failed creating CFNetService for registration");
}
}
if ([_GetOption(_options, GCDWebServerOption_RequestNATPortMapping, @NO) boolValue]) {
DNSServiceErrorType status = DNSServiceNATPortMappingCreate(&_dnsService, 0, 0, kDNSServiceProtocol_TCP, htons(port), htons(port), 0, _DNSServiceCallBack, (__bridge void*)self);
if (status == kDNSServiceErr_NoError) {
CFSocketContext context = {0, (__bridge void*)self, NULL, NULL, NULL};
_dnsSocket = CFSocketCreateWithNative(kCFAllocatorDefault, DNSServiceRefSockFD(_dnsService), kCFSocketReadCallBack, _SocketCallBack, &context);
if (_dnsSocket) {
CFSocketSetSocketFlags(_dnsSocket, CFSocketGetSocketFlags(_dnsSocket) & ~kCFSocketCloseOnInvalidate);
_dnsSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _dnsSocket, 0);
if (_dnsSource) {
CFRunLoopAddSource(CFRunLoopGetMain(), _dnsSource, kCFRunLoopCommonModes);
} else {
GWS_LOG_ERROR(@"Failed creating CFRunLoopSource");
GWS_DNOT_REACHED();
}
} else {
GWS_LOG_ERROR(@"Failed creating CFSocket");
GWS_DNOT_REACHED();
}
} else {
GWS_LOG_ERROR(@"Failed creating NAT port mapping (%i)", status);
}
}
@@ -596,6 +670,22 @@ static inline NSString* _EncodeBase64(NSString* string) {
- (void)_stop {
GWS_DCHECK(_source4 != NULL);
if (_dnsService) {
_dnsAddress = nil;
_dnsPort = 0;
if (_dnsSource) {
CFRunLoopSourceInvalidate(_dnsSource);
CFRelease(_dnsSource);
_dnsSource = NULL;
}
if (_dnsSocket) {
CFRelease(_dnsSocket);
_dnsSocket = NULL;
}
DNSServiceRefDeallocate(_dnsService);
_dnsService = NULL;
}
if (_registrationService) {
if (_resolutionService) {
CFNetServiceUnscheduleFromRunLoop(_resolutionService, CFRunLoopGetMain(), kCFRunLoopCommonModes);
@@ -747,6 +837,17 @@ static inline NSString* _EncodeBase64(NSString* string) {
return nil;
}
- (NSURL*)publicServerURL {
if (_source4 && _dnsService && _dnsAddress && _dnsPort) {
if (_dnsPort != 80) {
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@:%i/", _dnsAddress, (int)_dnsPort]];
} else {
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/", _dnsAddress]];
}
}
return nil;
}
- (BOOL)start {
return [self startWithPort:kDefaultPort bonjourName:@""];
}
@@ -859,7 +960,12 @@ static inline NSString* _EncodeBase64(NSString* string) {
for (NSTextCheckingResult* result in matches) {
// Start at 1; index 0 is the whole string
for (NSUInteger i = 1; i < result.numberOfRanges; i++) {
[captures addObject:[urlPath substringWithRange:[result rangeAtIndex:i]]];
NSRange range = [result rangeAtIndex:i];
// range is {NSNotFound, 0} "if one of the capture groups did not participate in this particular match"
// see discussion in -[NSRegularExpression firstMatchInString:options:range:]
if (range.location != NSNotFound) {
[captures addObject:[urlPath substringWithRange:range]];
}
}
}
@@ -915,7 +1021,10 @@ static inline NSString* _EncodeBase64(NSString* string) {
for (NSString* file in enumerator) {
if (![file hasPrefix:@"."]) {
NSString* type = [[enumerator fileAttributes] objectForKey:NSFileType];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
NSString* escapedFile = [file stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
#pragma clang diagnostic pop
GWS_DCHECK(escapedFile);
if ([type isEqualToString:NSFileTypeRegular]) {
[html appendFormat:@"<li><a href=\"%@\">%@</a></li>\n", escapedFile, file];
@@ -1022,10 +1131,6 @@ static inline NSString* _EncodeBase64(NSString* string) {
va_end(arguments);
}
- (void)logException:(NSException*)exception {
GWS_LOG_EXCEPTION(exception);
}
@end
#ifdef __GCDWEBSERVER_ENABLE_TESTING__

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -88,7 +88,7 @@ static int32_t _connectionCounter = 0;
@implementation GCDWebServerConnection (Read)
- (void)_readData:(NSMutableData*)data withLength:(NSUInteger)length completionBlock:(ReadDataCompletionBlock)block {
dispatch_read(_socket, length, kGCDWebServerGCDQueue, ^(dispatch_data_t buffer, int error) {
dispatch_read(_socket, length, dispatch_get_global_queue(_server.dispatchQueuePriority, 0), ^(dispatch_data_t buffer, int error) {
@autoreleasepool {
if (error == 0) {
@@ -247,10 +247,10 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
@implementation GCDWebServerConnection (Write)
- (void)_writeData:(NSData*)data withCompletionBlock:(WriteDataCompletionBlock)block {
dispatch_data_t buffer = dispatch_data_create(data.bytes, data.length, kGCDWebServerGCDQueue, ^{
dispatch_data_t buffer = dispatch_data_create(data.bytes, data.length, dispatch_get_global_queue(_server.dispatchQueuePriority, 0), ^{
[data self]; // Keeps ARC from releasing data too early
});
dispatch_write(_socket, buffer, kGCDWebServerGCDQueue, ^(dispatch_data_t remainingData, int error) {
dispatch_write(_socket, buffer, dispatch_get_global_queue(_server.dispatchQueuePriority, 0), ^(dispatch_data_t remainingData, int error) {
@autoreleasepool {
if (error == 0) {
@@ -758,12 +758,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
- (void)processRequest:(GCDWebServerRequest*)request completion:(GCDWebServerCompletionBlock)completion {
GWS_LOG_DEBUG(@"Connection on socket %i processing request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead);
@try {
_handler.asyncProcessBlock(request, completion);
}
@catch (NSException* exception) {
GWS_LOG_EXCEPTION(exception);
}
_handler.asyncProcessBlock(request, [completion copy]);
}
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -182,11 +182,17 @@ NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension) {
}
NSString* GCDWebServerEscapeURLString(NSString* string) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, CFSTR(":@/?&=+"), kCFStringEncodingUTF8));
#pragma clang diagnostic pop
}
NSString* GCDWebServerUnescapeURLString(NSString* string) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
return CFBridgingRelease(CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, (CFStringRef)string, CFSTR(""), kCFStringEncodingUTF8));
#pragma clang diagnostic pop
}
NSDictionary* GCDWebServerParseURLEncodedForm(NSString* form) {
@@ -240,7 +246,7 @@ NSString* GCDWebServerStringFromSockAddr(const struct sockaddr* addr, BOOL inclu
NSString* GCDWebServerGetPrimaryIPAddress(BOOL useIPv6) {
NSString* address = nil;
#if TARGET_OS_IPHONE
#if !TARGET_IPHONE_SIMULATOR
#if !TARGET_IPHONE_SIMULATOR && !TARGET_OS_TV
const char* primaryInterface = "en0"; // WiFi interface on iOS
#endif
#else
@@ -261,8 +267,10 @@ NSString* GCDWebServerGetPrimaryIPAddress(BOOL useIPv6) {
struct ifaddrs* list;
if (getifaddrs(&list) >= 0) {
for (struct ifaddrs* ifap = list; ifap; ifap = ifap->ifa_next) {
#if TARGET_IPHONE_SIMULATOR
if (strcmp(ifap->ifa_name, "en0") && strcmp(ifap->ifa_name, "en1")) // Assume en0 is Ethernet and en1 is WiFi since there is no way to use SystemConfiguration framework in iOS Simulator
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_TV
// Assume en0 is Ethernet and en1 is WiFi since there is no way to use SystemConfiguration framework in iOS Simulator
// Assumption holds for Apple TV running tvOS
if (strcmp(ifap->ifa_name, "en0") && strcmp(ifap->ifa_name, "en1"))
#else
if (strcmp(ifap->ifa_name, primaryInterface))
#endif

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -77,7 +77,6 @@
#define GWS_LOG_INFO(...) XLOG_INFO(__VA_ARGS__)
#define GWS_LOG_WARNING(...) XLOG_WARNING(__VA_ARGS__)
#define GWS_LOG_ERROR(...) XLOG_ERROR(__VA_ARGS__)
#define GWS_LOG_EXCEPTION(__EXCEPTION__) XLOG_EXCEPTION(__EXCEPTION__)
#define GWS_DCHECK(__CONDITION__) XLOG_DEBUG_CHECK(__CONDITION__)
#define GWS_DNOT_REACHED() XLOG_DEBUG_UNREACHABLE()
@@ -102,7 +101,6 @@ extern DDLogLevel GCDWebServerLogLevel;
#define GWS_LOG_INFO(...) DDLogInfo(__VA_ARGS__)
#define GWS_LOG_WARNING(...) DDLogWarn(__VA_ARGS__)
#define GWS_LOG_ERROR(...) DDLogError(__VA_ARGS__)
#define GWS_LOG_EXCEPTION(__EXCEPTION__) DDLogError(@"%@", __EXCEPTION__)
/**
* If all of the above fail, then use GCDWebServer built-in
@@ -118,8 +116,7 @@ typedef NS_ENUM(int, GCDWebServerLoggingLevel) {
kGCDWebServerLoggingLevel_Verbose,
kGCDWebServerLoggingLevel_Info,
kGCDWebServerLoggingLevel_Warning,
kGCDWebServerLoggingLevel_Error,
kGCDWebServerLoggingLevel_Exception
kGCDWebServerLoggingLevel_Error
};
extern GCDWebServerLoggingLevel GCDWebServerLogLevel;
@@ -134,7 +131,6 @@ extern void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* for
#define GWS_LOG_INFO(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Info) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Info, __VA_ARGS__); } while (0)
#define GWS_LOG_WARNING(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Warning) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Warning, __VA_ARGS__); } while (0)
#define GWS_LOG_ERROR(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Error) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Error, __VA_ARGS__); } while (0)
#define GWS_LOG_EXCEPTION(__EXCEPTION__) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Exception) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Exception, @"%@", __EXCEPTION__); } while (0)
#endif
@@ -168,7 +164,6 @@ extern void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* for
*/
#define kGCDWebServerDefaultMimeType @"application/octet-stream"
#define kGCDWebServerGCDQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define kGCDWebServerErrorDomain @"GCDWebServerErrorDomain"
static inline BOOL GCDWebServerIsValidByteRange(NSRange range) {
@@ -200,6 +195,7 @@ extern NSString* GCDWebServerStringFromSockAddr(const struct sockaddr* addr, BOO
@property(nonatomic, readonly) NSDictionary* authenticationBasicAccounts;
@property(nonatomic, readonly) NSDictionary* authenticationDigestAccounts;
@property(nonatomic, readonly) BOOL shouldAutomaticallyMapHEADToGET;
@property(nonatomic, readonly) dispatch_queue_priority_t dispatchQueuePriority;
- (void)willStartConnection:(GCDWebServerConnection*)connection;
- (void)didEndConnection:(GCDWebServerConnection*)connection;
@end

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -94,7 +94,7 @@ NSString* const GCDWebServerRequestAttribute_RegexCaptures = @"GCDWebServerReque
return NO;
}
if (![super open:error]) {
deflateEnd(&_stream);
inflateEnd(&_stream);
return NO;
}
return YES;

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -241,8 +241,9 @@
}
- (void)performReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block {
GWS_DCHECK(_opened);
if ([_reader respondsToSelector:@selector(asyncReadDataWithCompletion:)]) {
[_reader asyncReadDataWithCompletion:block];
[_reader asyncReadDataWithCompletion:[block copy]];
} else {
NSError* error = nil;
NSData* data = [_reader readData:&error];

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
<!--
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -296,7 +296,7 @@
- (instancetype)initWithUploadDirectory:(NSString*)path {
if ((self = [super init])) {
NSBundle* siteBundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"GCDWebUploader" ofType:@"bundle"]];
NSBundle* siteBundle = [NSBundle bundleWithPath:[[NSBundle bundleForClass:[GCDWebUploader class]] pathForResource:@"GCDWebUploader" ofType:@"bundle"]];
if (siteBundle == nil) {
return nil;
}

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -72,6 +72,10 @@ typedef enum {
[self _logDelegateCall:_cmd];
}
- (void)webServerDidUpdateNATPortMapping:(GCDWebServer*)server {
[self _logDelegateCall:_cmd];
}
- (void)webServerDidConnect:(GCDWebServer*)server {
[self _logDelegateCall:_cmd];
}
@@ -142,6 +146,7 @@ int main(int argc, const char* argv[]) {
NSString* authenticationUser = nil;
NSString* authenticationPassword = nil;
BOOL bindToLocalhost = NO;
BOOL requestNATPortMapping = NO;
if (argc == 1) {
fprintf(stdout, "Usage: %s [-mode webServer | htmlPage | htmlForm | htmlFileUpload | webDAV | webUploader | streamingResponse | asyncResponse] [-record] [-root directory] [-tests directory] [-authenticationMethod Basic | Digest] [-authenticationRealm realm] [-authenticationUser user] [-authenticationPassword password] [--localhost]\n\n", basename((char*)argv[0]));
@@ -191,6 +196,8 @@ int main(int argc, const char* argv[]) {
authenticationPassword = [NSString stringWithUTF8String:argv[i]];
} else if (!strcmp(argv[i], "--localhost")) {
bindToLocalhost = YES;
} else if (!strcmp(argv[i], "--nat")) {
requestNATPortMapping = YES;
}
}
}
@@ -412,6 +419,7 @@ int main(int argc, const char* argv[]) {
fprintf(stdout, "\n");
NSMutableDictionary* options = [NSMutableDictionary dictionary];
[options setObject:@8080 forKey:GCDWebServerOption_Port];
[options setObject:@(requestNATPortMapping) forKey:GCDWebServerOption_RequestNATPortMapping];
[options setObject:@(bindToLocalhost) forKey:GCDWebServerOption_BindToLocalhost];
[options setObject:@"" forKey:GCDWebServerOption_BonjourName];
if (authenticationUser && authenticationPassword) {

View File

@@ -24,6 +24,7 @@ Extra built-in features:
* [Basic](https://en.wikipedia.org/wiki/Basic_access_authentication) and [Digest Access](https://en.wikipedia.org/wiki/Digest_access_authentication) authentications for password protection
* Automatically handle transitions between foreground, background and suspended modes in iOS apps
* Full support for both IPv4 and IPv6
* NAT port mapping (IPv4 only)
Included extensions:
* [GCDWebUploader](GCDWebUploader/GCDWebUploader.h): subclass of ```GCDWebServer``` that implements an interface for uploading and downloading files using a web browser
@@ -43,6 +44,8 @@ Getting Started
Download or check out the [latest release](https://github.com/swisspol/GCDWebServer/releases) of GCDWebServer then add the entire "GCDWebServer" subfolder to your Xcode project. If you intend to use one of the extensions like GCDWebDAVServer or GCDWebUploader, add these subfolders as well.
If you add the files directly then (1) link to `libz` (via Target > Build Phases > Link Binary With Libraries) and (2) add `$(SDKROOT)/usr/include/libxml2` to your header search paths (via Target > Build Settings > HEADER_SEARCH_PATHS).
Alternatively, you can install GCDWebServer using [CocoaPods](http://cocoapods.org/) by simply adding this line to your Podfile:
```
pod "GCDWebServer", "~> 3.0"
@@ -58,13 +61,20 @@ pod "GCDWebServer/WebDAV", "~> 3.0"
And finally run `$ pod install`.
You can also use [Carthage](https://github.com/Carthage/Carthage) by adding this line to your Cartfile:
You can also use [Carthage](https://github.com/Carthage/Carthage) by adding this line to your Cartfile (3.2.5 is the first release with Carthage support):
```
github "swisspol/GCDWebServer" "master"
github "swisspol/GCDWebServer" ~> 3.2.5
```
Then run `$ carthage update` and add the generated frameworks to your Xcode projects (see [Carthage instructions](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application)).
Help & Support
==============
For help with using GCDWebServer, it's best to ask your question on Stack Overflow with the [`gcdwebserver`](http://stackoverflow.com/questions/tagged/gcdwebserver) tag.
Be sure to read this entire README first though!
Hello World
===========
@@ -143,22 +153,27 @@ int main(int argc, const char* argv[]) {
***webServer.swift***
```swift
import Foundation
import GCDWebServer
let webServer = GCDWebServer()
func initWebServer() {
webServer.addDefaultHandlerForMethod("GET", requestClass: GCDWebServerRequest.self, processBlock: {request in
let webServer = GCDWebServer()
webServer.addDefaultHandlerForMethod("GET", requestClass: GCDWebServerRequest.self, processBlock: {request in
return GCDWebServerDataResponse(HTML:"<html><body><p>Hello World</p></body></html>")
})
webServer.runWithPort(8080, bonjourName: "GCD Web Server")
print("Visit \(webServer.serverURL) in your web browser")
}
webServer.runWithPort(8080, bonjourName: nil)
println("Visit \(webServer.serverURL) in your web browser")
```
***WebServer-Bridging-Header.h***
```objectivec
#import "GCDWebServer.h"
#import "GCDWebServerDataResponse.h"
#import <GCDWebServer/GCDWebServer.h>
#import <GCDWebServer/GCDWebServerDataResponse.h>
```
Web Based Uploads in iOS Apps
@@ -261,7 +276,7 @@ GCDWebServer's architecture consists of only 4 core classes:
Implementing Handlers
=====================
GCDWebServer relies on "handlers" to process incoming web requests and generating responses. Handlers are implemented with GCD blocks which makes it very easy to provide your owns. However, they are executed on arbitrary threads within GCD so __special attention must be paid to thread-safety and re-entrancy__.
GCDWebServer relies on "handlers" to process incoming web requests and generating responses. Handlers are implemented with GCD blocks which makes it very easy to provide your own. However, they are executed on arbitrary threads within GCD so __special attention must be paid to thread-safety and re-entrancy__.
Handlers require 2 GCD blocks:
* The ```GCDWebServerMatchBlock``` is called on every handler added to the ```GCDWebServer``` instance whenever a web request has started (i.e. HTTP headers have been received). It is passed the basic info for the web request (HTTP method, URL, headers...) and must decide if it wants to handle it or not. If yes, it must return a new ```GCDWebServerRequest``` instance (see above) created with this info. Otherwise, it simply returns nil.
@@ -272,7 +287,7 @@ Note that most methods on ```GCDWebServer``` to add handlers only require the ``
Asynchronous HTTP Responses
===========================
New in GCDWebServer 3.0 is the ability to process HTTP requests aysnchronously i.e. add handlers to the server which generate their ```GCDWebServerResponse``` asynchronously. This is achieved by adding handlers that use a ```GCDWebServerAsyncProcessBlock``` instead of a ```GCDWebServerProcessBlock```. Here's an example:
New in GCDWebServer 3.0 is the ability to process HTTP requests asynchronously i.e. add handlers to the server which generate their ```GCDWebServerResponse``` asynchronously. This is achieved by adding handlers that use a ```GCDWebServerAsyncProcessBlock``` instead of a ```GCDWebServerProcessBlock```. Here's an example:
**(Synchronous version)** The handler blocks while generating the HTTP response:
```objectivec

View File

@@ -1,16 +1,20 @@
#!/bin/bash -ex
OSX_SDK="macosx"
if [ -z "$TRAVIS" ]; then
IOS_SDK="iphoneos"
else
IOS_SDK="iphonesimulator"
fi
IOS_SDK="iphonesimulator"
TVOS_SDK="appletvsimulator"
OSX_SDK_VERSION=`xcodebuild -version -sdk | grep -A 1 '^MacOSX' | tail -n 1 | awk '{ print $2 }'`
IOS_SDK_VERSION=`xcodebuild -version -sdk | grep -A 1 '^iPhoneOS' | tail -n 1 | awk '{ print $2 }'`
TVOS_SDK_VERSION=`xcodebuild -version -sdk | grep -A 1 '^AppleTVOS' | tail -n 1 | awk '{ print $2 }'`
OSX_TARGET="GCDWebServer (Mac)"
IOS_TARGET="GCDWebServer (iOS)"
TVOS_TARGET="GCDWebServer (tvOS)"
CONFIGURATION="Release"
OSX_TEST_SCHEME="GCDWebServers (Mac)"
BUILD_DIR="/tmp/GCDWebServer-Build"
PRODUCT="$BUILD_DIR/$CONFIGURATION/GCDWebServer"
@@ -30,21 +34,13 @@ function runTests {
logLevel=2 $1 -mode "$2" -root "$PAYLOAD_DIR/Payload" -tests "$3"
}
# Build for iOS for oldest deployment target (TODO: run tests on iOS)
# Run built-in OS X tests
rm -rf "$BUILD_DIR"
xcodebuild -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$BUILD_DIR" "IPHONEOS_DEPLOYMENT_TARGET=5.1.1" > /dev/null
xcodebuild test -scheme "$OSX_TEST_SCHEME" "SYMROOT=$BUILD_DIR"
# Build for iOS for default deployment target (TODO: run tests on iOS)
# Build for OS X for oldest supported deployment target
rm -rf "$BUILD_DIR"
xcodebuild -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$BUILD_DIR" > /dev/null
# Build for OS X for oldest deployment target
rm -rf "$BUILD_DIR"
xcodebuild -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$BUILD_DIR" "MACOSX_DEPLOYMENT_TARGET=10.7" > /dev/null
# Build for OS X for default deployment target
rm -rf "$BUILD_DIR"
xcodebuild -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$BUILD_DIR" > /dev/null
xcodebuild build -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" "SYMROOT=$BUILD_DIR" "MACOSX_DEPLOYMENT_TARGET=10.7" > /dev/null
# Run tests
runTests $PRODUCT "htmlForm" "Tests/HTMLForm"
@@ -56,5 +52,21 @@ runTests $PRODUCT "webDAV" "Tests/WebDAV-Finder"
runTests $PRODUCT "webUploader" "Tests/WebUploader"
runTests $PRODUCT "webServer" "Tests/WebServer-Sample-Movie" "Tests/Sample-Movie.mp4"
# Build for OS X for current deployment target
rm -rf "$BUILD_DIR"
xcodebuild build -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" "SYMROOT=$BUILD_DIR" "MACOSX_DEPLOYMENT_TARGET=$OSX_SDK_VERSION" > /dev/null
# Build for iOS for oldest supported deployment target
rm -rf "$BUILD_DIR"
xcodebuild build -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" "SYMROOT=$BUILD_DIR" "IPHONEOS_DEPLOYMENT_TARGET=6.0" > /dev/null
# Build for iOS for current deployment target
rm -rf "$BUILD_DIR"
xcodebuild build -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" "SYMROOT=$BUILD_DIR" "IPHONEOS_DEPLOYMENT_TARGET=$IOS_SDK_VERSION" > /dev/null
# Build for tvOS for current deployment target
rm -rf "$BUILD_DIR"
xcodebuild build -sdk "$TVOS_SDK" -target "$TVOS_TARGET" -configuration "$CONFIGURATION" "SYMROOT=$BUILD_DIR" "TVOS_DEPLOYMENT_TARGET=$TVOS_SDK_VERSION" > /dev/null
# Done
echo "\nAll tests completed successfully!"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -28,5 +28,5 @@
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property(retain, nonatomic) UIWindow* window;
@property(strong, nonatomic) UIWindow* window;
@end

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -26,45 +26,11 @@
*/
#import "AppDelegate.h"
#import "GCDWebUploader.h"
@interface AppDelegate () <GCDWebUploaderDelegate> {
@private
GCDWebUploader* _webServer;
}
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
CGRect bounds = ([UIScreen instancesRespondToSelector:@selector(nativeBounds)] ? [[UIScreen mainScreen] nativeBounds] : [[UIScreen mainScreen] bounds]);
_window = [[UIWindow alloc] initWithFrame:bounds];
_window.backgroundColor = [UIColor whiteColor];
[_window makeKeyAndVisible];
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
_webServer = [[GCDWebUploader alloc] initWithUploadDirectory:documentsPath];
_webServer.delegate = self;
_webServer.allowHiddenItems = YES;
[_webServer start];
return YES;
}
- (void)webUploader:(GCDWebUploader*)uploader didUploadFileAtPath:(NSString*)path {
NSLog(@"[UPLOAD] %@", path);
}
- (void)webUploader:(GCDWebUploader*)uploader didMoveItemFromPath:(NSString*)fromPath toPath:(NSString*)toPath {
NSLog(@"[MOVE] %@ -> %@", fromPath, toPath);
}
- (void)webUploader:(GCDWebUploader*)uploader didDeleteItemAtPath:(NSString*)path {
NSLog(@"[DELETE] %@", path);
}
- (void)webUploader:(GCDWebUploader*)uploader didCreateDirectoryAtPath:(NSString*)path {
NSLog(@"[CREATE] %@", path);
}
@end

View File

@@ -0,0 +1,68 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9059" systemVersion="14F1021" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9059" systemVersion="14F1021" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fqi-2H-Bq5">
<rect key="frame" x="279" y="290" width="42" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="fqi-2H-Bq5" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="fQm-a5-p9Z"/>
<constraint firstItem="fqi-2H-Bq5" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="vB0-cp-Fhd"/>
</constraints>
</view>
<connections>
<outlet property="label" destination="fqi-2H-Bq5" id="maJ-eb-cCq"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View File

@@ -4,24 +4,26 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>net.pol-online.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>

31
iOS/ViewController.h Normal file
View File

@@ -0,0 +1,31 @@
/*
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* The name of Pierre-Olivier Latour may not be used to endorse
or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end

77
iOS/ViewController.m Normal file
View File

@@ -0,0 +1,77 @@
/*
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* The name of Pierre-Olivier Latour may not be used to endorse
or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ViewController.h"
#import "GCDWebUploader.h"
@interface ViewController () <GCDWebUploaderDelegate>
@property(weak, nonatomic) IBOutlet UILabel* label;
@end
@implementation ViewController {
@private
GCDWebUploader* _webServer;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
_webServer = [[GCDWebUploader alloc] initWithUploadDirectory:documentsPath];
_webServer.delegate = self;
_webServer.allowHiddenItems = YES;
if ([_webServer start]) {
_label.text = [NSString stringWithFormat:NSLocalizedString(@"GCDWebServer running locally on port %i", nil), (int)_webServer.port];
} else {
_label.text = NSLocalizedString(@"GCDWebServer not running!", nil);
}
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[_webServer stop];
_webServer = nil;
}
- (void)webUploader:(GCDWebUploader*)uploader didUploadFileAtPath:(NSString*)path {
NSLog(@"[UPLOAD] %@", path);
}
- (void)webUploader:(GCDWebUploader*)uploader didMoveItemFromPath:(NSString*)fromPath toPath:(NSString*)toPath {
NSLog(@"[MOVE] %@ -> %@", fromPath, toPath);
}
- (void)webUploader:(GCDWebUploader*)uploader didDeleteItemAtPath:(NSString*)path {
NSLog(@"[DELETE] %@", path);
}
- (void)webUploader:(GCDWebUploader*)uploader didCreateDirectoryAtPath:(NSString*)path {
NSLog(@"[CREATE] %@", path);
}
@end

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2012-2014, Pierre-Olivier Latour
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without

32
tvOS/AppDelegate.h Normal file
View File

@@ -0,0 +1,32 @@
/*
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* The name of Pierre-Olivier Latour may not be used to endorse
or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property(strong, nonatomic) UIWindow* window;
@end

36
tvOS/AppDelegate.m Normal file
View File

@@ -0,0 +1,36 @@
/*
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* The name of Pierre-Olivier Latour may not be used to endorse
or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "AppDelegate.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
return YES;
}
@end

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "tv",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,17 @@
{
"layers" : [
{
"filename" : "Front.imagestacklayer"
},
{
"filename" : "Middle.imagestacklayer"
},
{
"filename" : "Back.imagestacklayer"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "tv",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "tv",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "tv",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,17 @@
{
"layers" : [
{
"filename" : "Front.imagestacklayer"
},
{
"filename" : "Middle.imagestacklayer"
},
{
"filename" : "Back.imagestacklayer"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "tv",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "tv",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,26 @@
{
"assets" : [
{
"size" : "1280x768",
"idiom" : "tv",
"filename" : "App Icon - Large.imagestack",
"role" : "primary-app-icon"
},
{
"size" : "400x240",
"idiom" : "tv",
"filename" : "App Icon - Small.imagestack",
"role" : "primary-app-icon"
},
{
"size" : "1920x720",
"idiom" : "tv",
"filename" : "Top Shelf Image.imageset",
"role" : "top-shelf-image"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "tv",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,15 @@
{
"images" : [
{
"orientation" : "landscape",
"idiom" : "tv",
"extent" : "full-screen",
"minimum-system-version" : "9.0",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder.AppleTV.Storyboard" version="3.0" toolsVersion="9059" systemVersion="14F1021" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="1920" height="1080"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IHC-Pp-Jrx">
<rect key="frame" x="939" y="530" width="42" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="IHC-Pp-Jrx" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="BOG-hA-JgS"/>
<constraint firstItem="IHC-Pp-Jrx" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="a9B-4C-wVj"/>
</constraints>
</view>
<connections>
<outlet property="label" destination="IHC-Pp-Jrx" id="lnE-JP-l00"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

30
tvOS/Info.plist Normal file
View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>net.pol-online.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
</dict>
</plist>

31
tvOS/ViewController.h Normal file
View File

@@ -0,0 +1,31 @@
/*
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* The name of Pierre-Olivier Latour may not be used to endorse
or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end

77
tvOS/ViewController.m Normal file
View File

@@ -0,0 +1,77 @@
/*
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* The name of Pierre-Olivier Latour may not be used to endorse
or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ViewController.h"
#import "GCDWebUploader.h"
@interface ViewController () <GCDWebUploaderDelegate>
@property(weak, nonatomic) IBOutlet UILabel* label;
@end
@implementation ViewController {
@private
GCDWebUploader* _webServer;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
_webServer = [[GCDWebUploader alloc] initWithUploadDirectory:documentsPath];
_webServer.delegate = self;
_webServer.allowHiddenItems = YES;
if ([_webServer start]) {
_label.text = [NSString stringWithFormat:NSLocalizedString(@"GCDWebServer running locally on port %i", nil), (int)_webServer.port];
} else {
_label.text = NSLocalizedString(@"GCDWebServer not running!", nil);
}
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[_webServer stop];
_webServer = nil;
}
- (void)webUploader:(GCDWebUploader*)uploader didUploadFileAtPath:(NSString*)path {
NSLog(@"[UPLOAD] %@", path);
}
- (void)webUploader:(GCDWebUploader*)uploader didMoveItemFromPath:(NSString*)fromPath toPath:(NSString*)toPath {
NSLog(@"[MOVE] %@ -> %@", fromPath, toPath);
}
- (void)webUploader:(GCDWebUploader*)uploader didDeleteItemAtPath:(NSString*)path {
NSLog(@"[DELETE] %@", path);
}
- (void)webUploader:(GCDWebUploader*)uploader didCreateDirectoryAtPath:(NSString*)path {
NSLog(@"[CREATE] %@", path);
}
@end

34
tvOS/main.m Normal file
View File

@@ -0,0 +1,34 @@
/*
Copyright (c) 2012-2015, Pierre-Olivier Latour
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* The name of Pierre-Olivier Latour may not be used to endorse
or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "AppDelegate.h"
int main(int argc, char* argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}