10 Commits
2.5 ... 2.5.2

Author SHA1 Message Date
Pierre-Olivier Latour
a5d83abdd0 Bumped version to 2.5.2 2014-09-21 10:35:46 -07:00
Pierre-Olivier Latour
f1e9f1a37c Improved handling of symbolic links in -addGETHandlerForBasePath:directoryPath:indexFilename:cacheAge:allowRangeRequests: 2014-09-19 08:19:49 -07:00
Pierre-Olivier Latour
00b5ec87ba #76 Fixed -bonjourServerURL to correctly return hostname instead of service name 2014-09-15 09:00:39 -07:00
Pierre-Olivier Latour
cf94e70a42 Fall back to CFBundleName if CFBundleDisplayName is not available 2014-09-15 08:05:07 -07:00
Pierre-Olivier Latour
d47409c776 Updated for Xcode6 2014-09-15 08:05:00 -07:00
Pierre-Olivier Latour
a9db13475b Bumped version 2014-08-24 12:28:51 -07:00
Pierre-Olivier Latour
17fad0f1b9 Improved automatic detection of when to use dispatch_retain() and dispatch_release() depending on compiler settings 2014-08-24 12:24:16 -07:00
Pierre-Olivier Latour
5493d9e803 Run test against default and oldest supported deployment targets 2014-08-24 12:20:55 -07:00
Pierre-Olivier Latour
12b1edb958 #70 Ensure -isRunning works as expected even if GCDWebServerOption_AutomaticallySuspendInBackground is enabled 2014-07-23 07:40:37 -07:00
Pierre-Olivier Latour
7544a6dc4e Update 2014-07-12 17:11:26 -07:00
7 changed files with 104 additions and 52 deletions

View File

@@ -1,19 +1,19 @@
# http://guides.cocoapods.org/syntax/podspec.html
# Verify Podspec with:
# sudo gem update cocoapods
# pod spec lint GCDWebServer.podspec --verbose
# Add to source line:
# :tag => s.version.to_s
# 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
# DELETE THIS SECTION BEFORE PROCEEDING!
Pod::Spec.new do |s|
s.name = 'GCDWebServer'
s.version = '2.5'
s.version = '2.5.2'
s.author = { 'Pierre-Olivier Latour' => 'info@pol-online.net' }
s.license = { :type => 'BSD', :file => 'LICENSE' }
s.homepage = 'https://github.com/swisspol/GCDWebServer'
s.summary = 'Lightweight GCD based HTTP server for OS X & iOS (includes web based uploader & WebDAV server)'
s.source = { :git => 'https://github.com/swisspol/GCDWebServer.git' }
s.source = { :git => 'https://github.com/swisspol/GCDWebServer.git', :tag => s.version.to_s }
s.ios.deployment_target = '5.0'
s.osx.deployment_target = '10.7'
s.requires_arc = true

View File

@@ -370,7 +370,7 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0510;
LastUpgradeCheck = 0600;
};
buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "GCDWebServer" */;
compatibilityVersion = "Xcode 3.2";
@@ -491,7 +491,6 @@
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD)";
MACOSX_DEPLOYMENT_TARGET = 10.7;
PRODUCT_NAME = GCDWebServer;
SDKROOT = macosx;
};
@@ -501,7 +500,6 @@
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD)";
MACOSX_DEPLOYMENT_TARGET = 10.7;
PRODUCT_NAME = GCDWebServer;
SDKROOT = macosx;
};
@@ -553,7 +551,6 @@
ARCHS = "$(ARCHS_STANDARD)";
CODE_SIGN_IDENTITY = "iPhone Developer";
INFOPLIST_FILE = iOS/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 5.1.1;
PRODUCT_NAME = GCDWebServer;
PROVISIONING_PROFILE = "";
SDKROOT = iphoneos;
@@ -567,7 +564,6 @@
ARCHS = "$(ARCHS_STANDARD)";
CODE_SIGN_IDENTITY = "iPhone Developer";
INFOPLIST_FILE = iOS/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 5.1.1;
PRODUCT_NAME = GCDWebServer;
PROVISIONING_PROFILE = "";
SDKROOT = iphoneos;

View File

@@ -77,16 +77,18 @@ typedef GCDWebServerResponse* (^GCDWebServerProcessBlock)(GCDWebServerRequest* r
extern NSString* const GCDWebServerOption_Port;
/**
* The Bonjour name used by the GCDWebServer (NSString).
* The Bonjour name used by the GCDWebServer (NSString). If set to an empty string,
* the name will automatically take the value of the GCDWebServerOption_ServerName
* option. If this option is set to nil, Bonjour will be disabled.
*
* The default value is an empty string i.e. use the computer / device name.
* The default value is an empty string.
*/
extern NSString* const GCDWebServerOption_BonjourName;
/**
* The Bonjour service type used by the GCDWebServer (NSString).
*
* The default value is "_http._tcp", standard HTTP web server.
* The default value is "_http._tcp", the service type for HTTP web servers.
*/
extern NSString* const GCDWebServerOption_BonjourType;
@@ -336,12 +338,14 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
*
* @warning This property is only valid if the server is running and Bonjour
* registration has successfully completed, which can take up to a few seconds.
* Also be aware this property will not automatically update if the Bonjour hostname
* has been dynamically changed after the server started running (this should be rare).
*/
@property(nonatomic, readonly) NSURL* bonjourServerURL;
/**
* Starts the server on port 8080 (OS X & iOS Simulator) or port 80 (iOS)
* using the computer / device name for as the Bonjour name.
* using the default Bonjour name.
*
* Returns NO if the server failed to start.
*/
@@ -350,7 +354,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
/**
* Starts the server on a given port and with a specific Bonjour name.
* Pass a nil Bonjour name to disable Bonjour entirely or an empty string to
* use the computer / device name.
* use the default name.
*
* Returns NO if the server failed to start.
*/

View File

@@ -160,7 +160,8 @@ static void _ExecuteMainThreadRunLoopSources() {
CFTimeInterval _disconnectDelay;
NSUInteger _port;
dispatch_source_t _source;
CFNetServiceRef _service;
CFNetServiceRef _registrationService;
CFNetServiceRef _resolutionService;
#if TARGET_OS_IPHONE
BOOL _suspendInBackground;
UIBackgroundTaskIdentifier _backgroundTask;
@@ -339,12 +340,12 @@ static void _DisconnectTimerCallBack(CFRunLoopTimerRef timer, void* info) {
}
- (NSString*)bonjourName {
CFStringRef name = _service ? CFNetServiceGetName(_service) : NULL;
CFStringRef name = _resolutionService ? CFNetServiceGetName(_resolutionService) : NULL;
return name && CFStringGetLength(name) ? ARC_BRIDGE_RELEASE(CFStringCreateCopy(kCFAllocatorDefault, name)) : nil;
}
- (NSString*)bonjourType {
CFStringRef type = _service ? CFNetServiceGetType(_service) : NULL;
CFStringRef type = _resolutionService ? CFNetServiceGetType(_resolutionService) : NULL;
return type && CFStringGetLength(type) ? ARC_BRIDGE_RELEASE(CFStringCreateCopy(kCFAllocatorDefault, type)) : nil;
}
@@ -360,11 +361,26 @@ static void _DisconnectTimerCallBack(CFRunLoopTimerRef timer, void* info) {
[_handlers removeAllObjects];
}
static void _NetServiceClientCallBack(CFNetServiceRef service, CFStreamError* error, void* info) {
static void _NetServiceRegisterCallBack(CFNetServiceRef service, CFStreamError* error, void* info) {
DCHECK([NSThread isMainThread]);
@autoreleasepool {
if (error->error) {
LOG_ERROR(@"Bonjour error %i (domain %i)", (int)error->error, (int)error->domain);
LOG_ERROR(@"Bonjour registration error %i (domain %i)", (int)error->error, (int)error->domain);
} else {
GCDWebServer* server = (ARC_BRIDGE GCDWebServer*)info;
LOG_VERBOSE(@"Bonjour registration complete for %@", [server class]);
CFNetServiceResolveWithTimeout(server->_resolutionService, 1.0, NULL);
}
}
}
static void _NetServiceResolveCallBack(CFNetServiceRef service, CFStreamError* error, void* info) {
DCHECK([NSThread isMainThread]);
@autoreleasepool {
if (error->error) {
if ((error->domain != kCFStreamErrorDomainNetServices) && (error->error != kCFNetServicesErrorTimeout)) {
LOG_ERROR(@"Bonjour resolution error %i (domain %i)", (int)error->error, (int)error->domain);
}
} else {
GCDWebServer* server = (ARC_BRIDGE GCDWebServer*)info;
LOG_INFO(@"%@ now reachable at %@", [server class], server.bonjourServerURL);
@@ -392,8 +408,9 @@ static inline NSString* _EncodeBase64(NSString* string) {
- (BOOL)_start:(NSError**)error {
DCHECK(_source == NULL);
NSUInteger port = [_GetOption(_options, GCDWebServerOption_Port, @0) unsignedIntegerValue];
NSString* name = _GetOption(_options, GCDWebServerOption_BonjourName, @"");
NSString* bonjourName = _GetOption(_options, GCDWebServerOption_BonjourName, @"");
NSString* bonjourType = _GetOption(_options, GCDWebServerOption_BonjourType, @"_http._tcp");
NSUInteger maxPendingConnections = [_GetOption(_options, GCDWebServerOption_MaxPendingConnections, @16) unsignedIntegerValue];
int listeningSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
@@ -491,14 +508,21 @@ static inline NSString* _EncodeBase64(NSString* string) {
_port = port;
}
if (name) {
_service = CFNetServiceCreate(kCFAllocatorDefault, CFSTR("local."), (ARC_BRIDGE CFStringRef)bonjourType, (ARC_BRIDGE CFStringRef)name, (SInt32)_port);
if (_service) {
if (bonjourName) {
_registrationService = CFNetServiceCreate(kCFAllocatorDefault, CFSTR("local."), (ARC_BRIDGE CFStringRef)bonjourType, (ARC_BRIDGE CFStringRef)(bonjourName.length ? bonjourName : _serverName), (SInt32)_port);
if (_registrationService) {
CFNetServiceClientContext context = {0, (ARC_BRIDGE void*)self, NULL, NULL, NULL};
CFNetServiceSetClient(_service, _NetServiceClientCallBack, &context);
CFNetServiceScheduleWithRunLoop(_service, CFRunLoopGetMain(), kCFRunLoopCommonModes);
CFNetServiceSetClient(_registrationService, _NetServiceRegisterCallBack, &context);
CFNetServiceScheduleWithRunLoop(_registrationService, CFRunLoopGetMain(), kCFRunLoopCommonModes);
CFStreamError streamError = {0};
CFNetServiceRegisterWithOptions(_service, 0, &streamError);
CFNetServiceRegisterWithOptions(_registrationService, 0, &streamError);
_resolutionService = CFNetServiceCreateCopy(kCFAllocatorDefault, _registrationService);
if (_resolutionService) {
CFNetServiceSetClient(_resolutionService, _NetServiceResolveCallBack, &context);
CFNetServiceScheduleWithRunLoop(_resolutionService, CFRunLoopGetMain(), kCFRunLoopCommonModes);
}
} else {
LOG_ERROR(@"Failed creating CFNetService");
}
@@ -537,11 +561,19 @@ static inline NSString* _EncodeBase64(NSString* string) {
- (void)_stop {
DCHECK(_source != NULL);
if (_service) {
CFNetServiceUnscheduleFromRunLoop(_service, CFRunLoopGetMain(), kCFRunLoopCommonModes);
CFNetServiceSetClient(_service, NULL, NULL);
CFRelease(_service);
_service = NULL;
if (_registrationService) {
if (_resolutionService) {
CFNetServiceUnscheduleFromRunLoop(_resolutionService, CFRunLoopGetMain(), kCFRunLoopCommonModes);
CFNetServiceSetClient(_resolutionService, NULL, NULL);
CFNetServiceCancel(_resolutionService);
CFRelease(_resolutionService);
_resolutionService = NULL;
}
CFNetServiceUnscheduleFromRunLoop(_registrationService, CFRunLoopGetMain(), kCFRunLoopCommonModes);
CFNetServiceSetClient(_registrationService, NULL, NULL);
CFNetServiceCancel(_registrationService);
CFRelease(_registrationService);
_registrationService = NULL;
}
dispatch_source_cancel(_source);
@@ -623,7 +655,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
}
- (BOOL)isRunning {
return (_source ? YES : NO);
return (_options ? YES : NO);
}
- (void)stop {
@@ -663,13 +695,14 @@ static inline NSString* _EncodeBase64(NSString* string) {
}
- (NSURL*)bonjourServerURL {
if (_source && _service) {
CFStringRef name = CFNetServiceGetName(_service);
if (name && CFStringGetLength(name)) {
if (_source && _resolutionService) {
NSString* name = (ARC_BRIDGE NSString*)CFNetServiceGetTargetHost(_resolutionService);
if (name.length) {
name = [name substringToIndex:(name.length - 1)]; // Strip trailing period at end of domain
if (_port != 80) {
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@.local:%i/", name, (int)_port]];
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@:%i/", name, (int)_port]];
} else {
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@.local/", name]];
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/", name]];
}
}
}
@@ -849,17 +882,18 @@ static inline NSString* _EncodeBase64(NSString* string) {
GCDWebServerResponse* response = nil;
NSString* filePath = [directoryPath stringByAppendingPathComponent:[request.path substringFromIndex:basePath.length]];
BOOL isDirectory;
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDirectory]) {
if (isDirectory) {
NSString* fileType = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:NULL] fileType];
if (fileType) {
if ([fileType isEqualToString:NSFileTypeDirectory]) {
if (indexFilename) {
NSString* indexPath = [filePath stringByAppendingPathComponent:indexFilename];
if ([[NSFileManager defaultManager] fileExistsAtPath:indexPath isDirectory:&isDirectory] && !isDirectory) {
NSString* indexType = [[[NSFileManager defaultManager] attributesOfItemAtPath:indexPath error:NULL] fileType];
if ([indexType isEqualToString:NSFileTypeRegular]) {
return [GCDWebServerFileResponse responseWithFile:indexPath];
}
}
response = [server _responseWithContentsOfDirectory:filePath];
} else {
} else if ([fileType isEqualToString:NSFileTypeRegular]) {
if (allowRangeRequests) {
response = [GCDWebServerFileResponse responseWithFile:filePath byteRange:request.byteRange];
[response setValue:@"bytes" forAdditionalHeader:@"Accept-Ranges"];

View File

@@ -25,8 +25,7 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <TargetConditionals.h>
#import <AvailabilityMacros.h>
#import <os/object.h>
#if __has_feature(objc_arc)
#define ARC_BRIDGE __bridge
@@ -35,7 +34,7 @@
#define ARC_RELEASE(__OBJECT__)
#define ARC_AUTORELEASE(__OBJECT__) __OBJECT__
#define ARC_DEALLOC(__OBJECT__)
#if (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0)) || (!TARGET_OS_IPHONE && (__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_8))
#if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
#define ARC_DISPATCH_RETAIN(__OBJECT__)
#define ARC_DISPATCH_RELEASE(__OBJECT__)
#else

View File

@@ -322,6 +322,9 @@
NSString* title = server.title;
if (title == nil) {
title = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
if (title == nil) {
title = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
}
#if !TARGET_OS_IPHONE
if (title == nil) {
title = [[NSProcessInfo processInfo] processName];

View File

@@ -32,19 +32,35 @@ function runTests {
logLevel=2 $1 -mode "$2" -root "$PAYLOAD_DIR/Payload" -tests "$3"
}
# Build for iOS in manual memory management mode (TODO: run tests on iOS)
# Build for iOS in manual memory management mode and for oldest deployment target (TODO: run tests on iOS)
rm -rf "$MRC_BUILD_DIR"
xcodebuild -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$MRC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=NO" "IPHONEOS_DEPLOYMENT_TARGET=5.1.1" > /dev/null
# Build for iOS in manual memory management mode and for default deployment target (TODO: run tests on iOS)
rm -rf "$MRC_BUILD_DIR"
xcodebuild -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$MRC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=NO" > /dev/null
# Build for iOS in ARC mode (TODO: run tests on iOS)
# Build for iOS in ARC mode and for oldest deployment target (TODO: run tests on iOS)
rm -rf "$ARC_BUILD_DIR"
xcodebuild -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$ARC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=YES" "IPHONEOS_DEPLOYMENT_TARGET=5.1.1" > /dev/null
# Build for iOS in ARC mode and for default deployment target (TODO: run tests on iOS)
rm -rf "$ARC_BUILD_DIR"
xcodebuild -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$ARC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=YES" > /dev/null
# Build for OS X in manual memory management mode
# Build for OS X in manual memory management mode and for oldest deployment target
rm -rf "$MRC_BUILD_DIR"
xcodebuild -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$MRC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=NO" "MACOSX_DEPLOYMENT_TARGET=10.7" > /dev/null
# Build for OS X in manual memory management mode and for default deployment target
rm -rf "$MRC_BUILD_DIR"
xcodebuild -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$MRC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=NO" > /dev/null
# Build for OS X in ARC mode
# Build for OS X in ARC mode and for oldest deployment target
rm -rf "$ARC_BUILD_DIR"
xcodebuild -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$ARC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=YES" "MACOSX_DEPLOYMENT_TARGET=10.7" > /dev/null
# Build for OS X in ARC mode and for default deployment target
rm -rf "$ARC_BUILD_DIR"
xcodebuild -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$ARC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=YES" > /dev/null