mirror of
https://github.com/swisspol/GCDWebServer.git
synced 2026-02-11 00:00:07 +08:00
Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6d118f4ec | ||
|
|
0da9ee6afe | ||
|
|
6c93927e12 | ||
|
|
f4cf591e50 | ||
|
|
5c737549fc | ||
|
|
1c36bf07c8 | ||
|
|
df8d66f6c8 | ||
|
|
45432e6563 | ||
|
|
7720b1363d | ||
|
|
a7a6cfdbc7 | ||
|
|
70f687e34b | ||
|
|
11967061a1 | ||
|
|
2d8dc8775d | ||
|
|
9cb7caacbd | ||
|
|
ac10c0c5b0 | ||
|
|
acdb5c9262 | ||
|
|
f54cc20bd6 | ||
|
|
02738433bf | ||
|
|
c9563db0a6 | ||
|
|
cd1eea5612 | ||
|
|
f7c1c4eff5 | ||
|
|
fdc0feddf0 | ||
|
|
25dbee032d | ||
|
|
c3c7aaad00 | ||
|
|
2c53064f5d | ||
|
|
8d0a3599ee | ||
|
|
653dfb727b | ||
|
|
7e4dd53c98 | ||
|
|
4739d208c0 | ||
|
|
f57c307e7d | ||
|
|
466b1f8444 | ||
|
|
fd565421dc | ||
|
|
8811d2233e | ||
|
|
e561389d33 | ||
|
|
32cf20a1d8 | ||
|
|
3c6c2a2b5d | ||
|
|
2bf2dc72c5 | ||
|
|
0001648879 | ||
|
|
cbbf5483e8 | ||
|
|
edd1f2850b | ||
|
|
5eb5e14b70 | ||
|
|
3e46e12648 | ||
|
|
ee4395e67d | ||
|
|
34884f273a | ||
|
|
87745c0fde | ||
|
|
ec800b43d5 | ||
|
|
79d9fb389c | ||
|
|
33d14f22e0 | ||
|
|
b060305d6d | ||
|
|
561f56e7fb | ||
|
|
e9fdd19830 | ||
|
|
03fae468d1 | ||
|
|
0a7d185417 | ||
|
|
1e29a0195b | ||
|
|
4e29da53a2 | ||
|
|
acc54ceac3 | ||
|
|
c46a2ddb22 | ||
|
|
71e972084c | ||
|
|
e8c872b286 | ||
|
|
fc928d0e2b | ||
|
|
e65f0eeaf1 | ||
|
|
79ae63a4c0 | ||
|
|
21cc6bfb35 | ||
|
|
faf28fe0f9 | ||
|
|
bac5b680df | ||
|
|
7df465336e | ||
|
|
11254331d1 | ||
|
|
9f345c6858 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,6 +1,5 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
xcuserdata
|
xcuserdata
|
||||||
project.xcworkspace
|
project.xcworkspace
|
||||||
|
/build
|
||||||
Tests/Payload
|
/Carthage/Build
|
||||||
Carthage/Build
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
language: objective-c
|
language: objective-c
|
||||||
script: ./Run-Tests.sh
|
script: ./Run-Tests.sh
|
||||||
osx_image: xcode8.2
|
osx_image: xcode11.3
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -26,27 +26,27 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// GCDWebServer Core
|
// GCDWebServer Core
|
||||||
#import <GCDWebServers/GCDWebServer.h>
|
#import "GCDWebServer.h"
|
||||||
#import <GCDWebServers/GCDWebServerConnection.h>
|
#import "GCDWebServerConnection.h"
|
||||||
#import <GCDWebServers/GCDWebServerFunctions.h>
|
#import "GCDWebServerFunctions.h"
|
||||||
#import <GCDWebServers/GCDWebServerHTTPStatusCodes.h>
|
#import "GCDWebServerHTTPStatusCodes.h"
|
||||||
#import <GCDWebServers/GCDWebServerResponse.h>
|
#import "GCDWebServerResponse.h"
|
||||||
#import <GCDWebServers/GCDWebServerRequest.h>
|
#import "GCDWebServerRequest.h"
|
||||||
|
|
||||||
// GCDWebServer Requests
|
// GCDWebServer Requests
|
||||||
#import <GCDWebServers/GCDWebServerDataRequest.h>
|
#import "GCDWebServerDataRequest.h"
|
||||||
#import <GCDWebServers/GCDWebServerFileRequest.h>
|
#import "GCDWebServerFileRequest.h"
|
||||||
#import <GCDWebServers/GCDWebServerMultiPartFormRequest.h>
|
#import "GCDWebServerMultiPartFormRequest.h"
|
||||||
#import <GCDWebServers/GCDWebServerURLEncodedFormRequest.h>
|
#import "GCDWebServerURLEncodedFormRequest.h"
|
||||||
|
|
||||||
// GCDWebServer Responses
|
// GCDWebServer Responses
|
||||||
#import <GCDWebServers/GCDWebServerDataResponse.h>
|
#import "GCDWebServerDataResponse.h"
|
||||||
#import <GCDWebServers/GCDWebServerErrorResponse.h>
|
#import "GCDWebServerErrorResponse.h"
|
||||||
#import <GCDWebServers/GCDWebServerFileResponse.h>
|
#import "GCDWebServerFileResponse.h"
|
||||||
#import <GCDWebServers/GCDWebServerStreamedResponse.h>
|
#import "GCDWebServerStreamedResponse.h"
|
||||||
|
|
||||||
// GCDWebUploader
|
// GCDWebUploader
|
||||||
#import <GCDWebServers/GCDWebUploader.h>
|
#import "GCDWebUploader.h"
|
||||||
|
|
||||||
// GCDWebDAVServer
|
// GCDWebDAVServer
|
||||||
#import <GCDWebServers/GCDWebDAVServer.h>
|
#import "GCDWebDAVServer.h"
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#import <GCDWebServers/GCDWebServers.h>
|
#import <GCDWebServers/GCDWebServers.h>
|
||||||
#import <XCTest/XCTest.h>
|
#import <XCTest/XCTest.h>
|
||||||
|
|
||||||
|
#pragma clang diagnostic ignored "-Weverything" // Prevent "messaging to unqualified id" warnings
|
||||||
|
|
||||||
@interface Tests : XCTestCase
|
@interface Tests : XCTestCase
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -21,4 +23,21 @@
|
|||||||
XCTAssertNotNil(server);
|
XCTAssertNotNil(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)testPaths {
|
||||||
|
XCTAssertEqualObjects(GCDWebServerNormalizePath(@""), @"");
|
||||||
|
XCTAssertEqualObjects(GCDWebServerNormalizePath(@"/foo/"), @"/foo");
|
||||||
|
XCTAssertEqualObjects(GCDWebServerNormalizePath(@"foo/bar"), @"foo/bar");
|
||||||
|
XCTAssertEqualObjects(GCDWebServerNormalizePath(@"foo//bar"), @"foo/bar");
|
||||||
|
XCTAssertEqualObjects(GCDWebServerNormalizePath(@"foo/bar//"), @"foo/bar");
|
||||||
|
XCTAssertEqualObjects(GCDWebServerNormalizePath(@"foo/./bar"), @"foo/bar");
|
||||||
|
XCTAssertEqualObjects(GCDWebServerNormalizePath(@"foo/bar/."), @"foo/bar");
|
||||||
|
XCTAssertEqualObjects(GCDWebServerNormalizePath(@"foo/../bar"), @"bar");
|
||||||
|
XCTAssertEqualObjects(GCDWebServerNormalizePath(@"/foo/../bar"), @"/bar");
|
||||||
|
XCTAssertEqualObjects(GCDWebServerNormalizePath(@"/foo/.."), @"/");
|
||||||
|
XCTAssertEqualObjects(GCDWebServerNormalizePath(@"/.."), @"/");
|
||||||
|
XCTAssertEqualObjects(GCDWebServerNormalizePath(@"."), @"");
|
||||||
|
XCTAssertEqualObjects(GCDWebServerNormalizePath(@".."), @"");
|
||||||
|
XCTAssertEqualObjects(GCDWebServerNormalizePath(@"../.."), @"");
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
3
Frameworks/module.modulemap
Normal file
3
Frameworks/module.modulemap
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
framework module GCDWebServers {
|
||||||
|
umbrella header "GCDWebServers.h"
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -95,7 +95,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
*
|
*
|
||||||
* The default value is nil i.e. all file extensions are allowed.
|
* The default value is nil i.e. all file extensions are allowed.
|
||||||
*/
|
*/
|
||||||
@property(nonatomic, copy) NSArray* allowedFileExtensions;
|
@property(nonatomic, copy) NSArray<NSString*>* allowedFileExtensions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets if files and directories whose name start with a period are allowed to
|
* Sets if files and directories whose name start with a period are allowed to
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -77,7 +77,7 @@ NS_ASSUME_NONNULL_END
|
|||||||
|
|
||||||
- (instancetype)initWithUploadDirectory:(NSString*)path {
|
- (instancetype)initWithUploadDirectory:(NSString*)path {
|
||||||
if ((self = [super init])) {
|
if ((self = [super init])) {
|
||||||
_uploadDirectory = [[path stringByStandardizingPath] copy];
|
_uploadDirectory = [path copy];
|
||||||
GCDWebDAVServer* __unsafe_unretained server = self;
|
GCDWebDAVServer* __unsafe_unretained server = self;
|
||||||
|
|
||||||
// 9.1 PROPFIND method
|
// 9.1 PROPFIND method
|
||||||
@@ -157,11 +157,6 @@ NS_ASSUME_NONNULL_END
|
|||||||
|
|
||||||
@implementation GCDWebDAVServer (Methods)
|
@implementation GCDWebDAVServer (Methods)
|
||||||
|
|
||||||
// Must match implementation in GCDWebUploader
|
|
||||||
- (BOOL)_checkSandboxedPath:(NSString*)path {
|
|
||||||
return [[path stringByStandardizingPath] hasPrefix:_uploadDirectory];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)_checkFileExtension:(NSString*)fileName {
|
- (BOOL)_checkFileExtension:(NSString*)fileName {
|
||||||
if (_allowedFileExtensions && ![_allowedFileExtensions containsObject:[[fileName pathExtension] lowercaseString]]) {
|
if (_allowedFileExtensions && ![_allowedFileExtensions containsObject:[[fileName pathExtension] lowercaseString]]) {
|
||||||
return NO;
|
return NO;
|
||||||
@@ -186,9 +181,9 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) {
|
|||||||
|
|
||||||
- (GCDWebServerResponse*)performGET:(GCDWebServerRequest*)request {
|
- (GCDWebServerResponse*)performGET:(GCDWebServerRequest*)request {
|
||||||
NSString* relativePath = request.path;
|
NSString* relativePath = request.path;
|
||||||
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
|
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)];
|
||||||
BOOL isDirectory = NO;
|
BOOL isDirectory = NO;
|
||||||
if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,10 +216,7 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NSString* relativePath = request.path;
|
NSString* relativePath = request.path;
|
||||||
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
|
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)];
|
||||||
if (![self _checkSandboxedPath:absolutePath]) {
|
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
|
||||||
}
|
|
||||||
BOOL isDirectory;
|
BOOL isDirectory;
|
||||||
if (![[NSFileManager defaultManager] fileExistsAtPath:[absolutePath stringByDeletingLastPathComponent] isDirectory:&isDirectory] || !isDirectory) {
|
if (![[NSFileManager defaultManager] fileExistsAtPath:[absolutePath stringByDeletingLastPathComponent] isDirectory:&isDirectory] || !isDirectory) {
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Conflict message:@"Missing intermediate collection(s) for \"%@\"", relativePath];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Conflict message:@"Missing intermediate collection(s) for \"%@\"", relativePath];
|
||||||
@@ -265,9 +257,9 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NSString* relativePath = request.path;
|
NSString* relativePath = request.path;
|
||||||
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
|
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)];
|
||||||
BOOL isDirectory = NO;
|
BOOL isDirectory = NO;
|
||||||
if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,10 +291,7 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NSString* relativePath = request.path;
|
NSString* relativePath = request.path;
|
||||||
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
|
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)];
|
||||||
if (![self _checkSandboxedPath:absolutePath]) {
|
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
|
||||||
}
|
|
||||||
BOOL isDirectory;
|
BOOL isDirectory;
|
||||||
if (![[NSFileManager defaultManager] fileExistsAtPath:[absolutePath stringByDeletingLastPathComponent] isDirectory:&isDirectory] || !isDirectory) {
|
if (![[NSFileManager defaultManager] fileExistsAtPath:[absolutePath stringByDeletingLastPathComponent] isDirectory:&isDirectory] || !isDirectory) {
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Conflict message:@"Missing intermediate collection(s) for \"%@\"", relativePath];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Conflict message:@"Missing intermediate collection(s) for \"%@\"", relativePath];
|
||||||
@@ -348,10 +337,7 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NSString* srcRelativePath = request.path;
|
NSString* srcRelativePath = request.path;
|
||||||
NSString* srcAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:srcRelativePath];
|
NSString* srcAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(srcRelativePath)];
|
||||||
if (![self _checkSandboxedPath:srcAbsolutePath]) {
|
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", srcRelativePath];
|
|
||||||
}
|
|
||||||
|
|
||||||
NSString* dstRelativePath = [request.headers objectForKey:@"Destination"];
|
NSString* dstRelativePath = [request.headers objectForKey:@"Destination"];
|
||||||
NSRange range = [dstRelativePath rangeOfString:(NSString*)[request.headers objectForKey:@"Host"]];
|
NSRange range = [dstRelativePath rangeOfString:(NSString*)[request.headers objectForKey:@"Host"]];
|
||||||
@@ -362,8 +348,8 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) {
|
|||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
dstRelativePath = [[dstRelativePath substringFromIndex:(range.location + range.length)] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
dstRelativePath = [[dstRelativePath substringFromIndex:(range.location + range.length)] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
NSString* dstAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:dstRelativePath];
|
NSString* dstAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(dstRelativePath)];
|
||||||
if (![self _checkSandboxedPath:dstAbsolutePath]) {
|
if (!dstAbsolutePath) {
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", srcRelativePath];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", srcRelativePath];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,9 +358,14 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) {
|
|||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Conflict message:@"Invalid destination \"%@\"", dstRelativePath];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Conflict message:@"Invalid destination \"%@\"", dstRelativePath];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString* itemName = [dstAbsolutePath lastPathComponent];
|
NSString* srcName = [srcAbsolutePath lastPathComponent];
|
||||||
if ((!_allowHiddenItems && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) {
|
if ((!_allowHiddenItems && [srcName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:srcName])) {
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"%@ to item name \"%@\" is not allowed", isMove ? @"Moving" : @"Copying", itemName];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"%@ from item name \"%@\" is not allowed", isMove ? @"Moving" : @"Copying", srcName];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString* dstName = [dstAbsolutePath lastPathComponent];
|
||||||
|
if ((!_allowHiddenItems && [dstName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:dstName])) {
|
||||||
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"%@ to item name \"%@\" is not allowed", isMove ? @"Moving" : @"Copying", dstName];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString* overwriteHeader = [request.headers objectForKey:@"Overwrite"];
|
NSString* overwriteHeader = [request.headers objectForKey:@"Overwrite"];
|
||||||
@@ -532,9 +523,9 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name
|
|||||||
}
|
}
|
||||||
|
|
||||||
NSString* relativePath = request.path;
|
NSString* relativePath = request.path;
|
||||||
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
|
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)];
|
||||||
BOOL isDirectory = NO;
|
BOOL isDirectory = NO;
|
||||||
if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,7 +537,7 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name
|
|||||||
NSArray* items = nil;
|
NSArray* items = nil;
|
||||||
if (isDirectory) {
|
if (isDirectory) {
|
||||||
NSError* error = nil;
|
NSError* error = nil;
|
||||||
items = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:absolutePath error:&error];
|
items = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:absolutePath error:&error] sortedArrayUsingSelector:@selector(localizedStandardCompare:)];
|
||||||
if (items == nil) {
|
if (items == nil) {
|
||||||
return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed listing directory \"%@\"", relativePath];
|
return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed listing directory \"%@\"", relativePath];
|
||||||
}
|
}
|
||||||
@@ -582,9 +573,9 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name
|
|||||||
}
|
}
|
||||||
|
|
||||||
NSString* relativePath = request.path;
|
NSString* relativePath = request.path;
|
||||||
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
|
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)];
|
||||||
BOOL isDirectory = NO;
|
BOOL isDirectory = NO;
|
||||||
if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -679,9 +670,9 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name
|
|||||||
}
|
}
|
||||||
|
|
||||||
NSString* relativePath = request.path;
|
NSString* relativePath = request.path;
|
||||||
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
|
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)];
|
||||||
BOOL isDirectory = NO;
|
BOOL isDirectory = NO;
|
||||||
if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = 'GCDWebServer'
|
s.name = 'GCDWebServer'
|
||||||
s.version = '3.4.2'
|
s.version = '3.5.4'
|
||||||
s.author = { 'Pierre-Olivier Latour' => 'info@pol-online.net' }
|
s.author = { 'Pierre-Olivier Latour' => 'info@pol-online.net' }
|
||||||
s.license = { :type => 'BSD', :file => 'LICENSE' }
|
s.license = { :type => 'BSD', :file => 'LICENSE' }
|
||||||
s.homepage = 'https://github.com/swisspol/GCDWebServer'
|
s.homepage = 'https://github.com/swisspol/GCDWebServer'
|
||||||
@@ -26,9 +26,9 @@ Pod::Spec.new do |s|
|
|||||||
cs.private_header_files = "GCDWebServer/Core/GCDWebServerPrivate.h"
|
cs.private_header_files = "GCDWebServer/Core/GCDWebServerPrivate.h"
|
||||||
cs.requires_arc = true
|
cs.requires_arc = true
|
||||||
cs.ios.library = 'z'
|
cs.ios.library = 'z'
|
||||||
cs.ios.frameworks = 'MobileCoreServices', 'CFNetwork'
|
cs.ios.frameworks = 'CoreServices', 'CFNetwork'
|
||||||
cs.tvos.library = 'z'
|
cs.tvos.library = 'z'
|
||||||
cs.tvos.frameworks = 'MobileCoreServices', 'CFNetwork'
|
cs.tvos.frameworks = 'CoreServices', 'CFNetwork'
|
||||||
cs.osx.library = 'z'
|
cs.osx.library = 'z'
|
||||||
cs.osx.framework = 'SystemConfiguration'
|
cs.osx.framework = 'SystemConfiguration'
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -96,7 +96,7 @@
|
|||||||
CEE28D501AE0098600F4023C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2BE851018E79DAF0061360B /* SystemConfiguration.framework */; };
|
CEE28D501AE0098600F4023C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2BE851018E79DAF0061360B /* SystemConfiguration.framework */; };
|
||||||
CEE28D511AE0098C00F4023C /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E208D1B2167BB17E00500836 /* CoreServices.framework */; };
|
CEE28D511AE0098C00F4023C /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E208D1B2167BB17E00500836 /* CoreServices.framework */; };
|
||||||
CEE28D521AE00A7A00F4023C /* GCDWebServers.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE28CF31AE0051F00F4023C /* GCDWebServers.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
CEE28D521AE00A7A00F4023C /* GCDWebServers.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE28CF31AE0051F00F4023C /* GCDWebServers.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
CEE28D571AE00AFE00F4023C /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E221129C1690B7BA0048D2B2 /* MobileCoreServices.framework */; };
|
CEE28D571AE00AFE00F4023C /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E221129C1690B7BA0048D2B2 /* CoreServices.framework */; };
|
||||||
CEE28D591AE00AFE00F4023C /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E22112981690B7AA0048D2B2 /* CFNetwork.framework */; };
|
CEE28D591AE00AFE00F4023C /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E22112981690B7AA0048D2B2 /* CFNetwork.framework */; };
|
||||||
CEE28D6A1AE1ABAA00F4023C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE28D691AE1ABAA00F4023C /* UIKit.framework */; };
|
CEE28D6A1AE1ABAA00F4023C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE28D691AE1ABAA00F4023C /* UIKit.framework */; };
|
||||||
E208D149167B76B700500836 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E208D148167B76B700500836 /* CFNetwork.framework */; };
|
E208D149167B76B700500836 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E208D148167B76B700500836 /* CFNetwork.framework */; };
|
||||||
@@ -104,6 +104,10 @@
|
|||||||
E221128F1690B6470048D2B2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E221128E1690B6470048D2B2 /* main.m */; };
|
E221128F1690B6470048D2B2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E221128E1690B6470048D2B2 /* main.m */; };
|
||||||
E240392B1BA09207000B7089 /* GCDWebServers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE28CD11AE004D800F4023C /* GCDWebServers.framework */; };
|
E240392B1BA09207000B7089 /* GCDWebServers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE28CD11AE004D800F4023C /* GCDWebServers.framework */; };
|
||||||
E24039321BA092B7000B7089 /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = E24039311BA092B7000B7089 /* Tests.m */; };
|
E24039321BA092B7000B7089 /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = E24039311BA092B7000B7089 /* Tests.m */; };
|
||||||
|
E24A3C0721E2879F00C58878 /* GCDWebServers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE28CEF1AE0051F00F4023C /* GCDWebServers.framework */; };
|
||||||
|
E24A3C0821E287A300C58878 /* GCDWebServers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD18B1BE69404002CE867 /* GCDWebServers.framework */; };
|
||||||
|
E24A3C0E21E28D3C00C58878 /* GCDWebServers.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = CEE28CEF1AE0051F00F4023C /* GCDWebServers.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
|
E24A3C0F21E28EFB00C58878 /* GCDWebServers.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD18B1BE69404002CE867 /* GCDWebServers.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
E28BAE3418F99C810095C089 /* GCDWebServer.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE1718F99C810095C089 /* GCDWebServer.m */; };
|
E28BAE3418F99C810095C089 /* GCDWebServer.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE1718F99C810095C089 /* GCDWebServer.m */; };
|
||||||
E28BAE3618F99C810095C089 /* GCDWebServerConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE1918F99C810095C089 /* GCDWebServerConnection.m */; };
|
E28BAE3618F99C810095C089 /* GCDWebServerConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE1918F99C810095C089 /* GCDWebServerConnection.m */; };
|
||||||
E28BAE3818F99C810095C089 /* GCDWebServerFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE1B18F99C810095C089 /* GCDWebServerFunctions.m */; };
|
E28BAE3818F99C810095C089 /* GCDWebServerFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE1B18F99C810095C089 /* GCDWebServerFunctions.m */; };
|
||||||
@@ -157,63 +161,19 @@
|
|||||||
E2DDD1B71BE6951A002CE867 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD1B61BE6951A002CE867 /* CFNetwork.framework */; };
|
E2DDD1B71BE6951A002CE867 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD1B61BE6951A002CE867 /* CFNetwork.framework */; };
|
||||||
E2DDD1BA1BE69545002CE867 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD1B91BE69545002CE867 /* libz.tbd */; };
|
E2DDD1BA1BE69545002CE867 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD1B91BE69545002CE867 /* libz.tbd */; };
|
||||||
E2DDD1BC1BE69551002CE867 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD1BB1BE69551002CE867 /* libxml2.tbd */; };
|
E2DDD1BC1BE69551002CE867 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD1BB1BE69551002CE867 /* libxml2.tbd */; };
|
||||||
E2DDD1BE1BE6956F002CE867 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD1BD1BE6956F002CE867 /* MobileCoreServices.framework */; };
|
E2DDD1BE1BE6956F002CE867 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD1BD1BE6956F002CE867 /* CoreServices.framework */; };
|
||||||
E2DDD1C01BE69576002CE867 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD1BF1BE69576002CE867 /* UIKit.framework */; };
|
E2DDD1C01BE69576002CE867 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD1BF1BE69576002CE867 /* UIKit.framework */; };
|
||||||
E2DDD1CB1BE698A8002CE867 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E2DDD1CA1BE698A8002CE867 /* main.m */; };
|
E2DDD1CE1BE698A8002CE867 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2DDD1CD1BE698A8002CE867 /* AppDelegate.swift */; };
|
||||||
E2DDD1CE1BE698A8002CE867 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E2DDD1CD1BE698A8002CE867 /* AppDelegate.m */; };
|
E2DDD1D11BE698A8002CE867 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2DDD1D01BE698A8002CE867 /* ViewController.swift */; };
|
||||||
E2DDD1D11BE698A8002CE867 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E2DDD1D01BE698A8002CE867 /* ViewController.m */; };
|
|
||||||
E2DDD1D41BE698A8002CE867 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E2DDD1D21BE698A8002CE867 /* Main.storyboard */; };
|
E2DDD1D41BE698A8002CE867 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E2DDD1D21BE698A8002CE867 /* Main.storyboard */; };
|
||||||
E2DDD1D61BE698A8002CE867 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E2DDD1D51BE698A8002CE867 /* Assets.xcassets */; };
|
E2DDD1D61BE698A8002CE867 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E2DDD1D51BE698A8002CE867 /* Assets.xcassets */; };
|
||||||
E2DDD1DD1BE69B1C002CE867 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD1BF1BE69576002CE867 /* UIKit.framework */; };
|
E2DDD1FD1BE69EE5002CE867 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2DDD1FC1BE69EE5002CE867 /* AppDelegate.swift */; };
|
||||||
E2DDD1DE1BE69BB7002CE867 /* GCDWebServer.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE1718F99C810095C089 /* GCDWebServer.m */; };
|
E2DDD2001BE69EE5002CE867 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2DDD1FF1BE69EE5002CE867 /* ViewController.swift */; };
|
||||||
E2DDD1DF1BE69BB7002CE867 /* GCDWebServerConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE1918F99C810095C089 /* GCDWebServerConnection.m */; };
|
|
||||||
E2DDD1E01BE69BB7002CE867 /* GCDWebServerFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE1B18F99C810095C089 /* GCDWebServerFunctions.m */; };
|
|
||||||
E2DDD1E11BE69BB7002CE867 /* GCDWebServerRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE1F18F99C810095C089 /* GCDWebServerRequest.m */; };
|
|
||||||
E2DDD1E21BE69BB7002CE867 /* GCDWebServerResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE2118F99C810095C089 /* GCDWebServerResponse.m */; };
|
|
||||||
E2DDD1E31BE69BB7002CE867 /* GCDWebServerDataRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE2418F99C810095C089 /* GCDWebServerDataRequest.m */; };
|
|
||||||
E2DDD1E41BE69BB7002CE867 /* GCDWebServerFileRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE2618F99C810095C089 /* GCDWebServerFileRequest.m */; };
|
|
||||||
E2DDD1E51BE69BB7002CE867 /* GCDWebServerMultiPartFormRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE2818F99C810095C089 /* GCDWebServerMultiPartFormRequest.m */; };
|
|
||||||
E2DDD1E61BE69BB7002CE867 /* GCDWebServerURLEncodedFormRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE2A18F99C810095C089 /* GCDWebServerURLEncodedFormRequest.m */; };
|
|
||||||
E2DDD1E71BE69BB7002CE867 /* GCDWebServerDataResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE2D18F99C810095C089 /* GCDWebServerDataResponse.m */; };
|
|
||||||
E2DDD1E81BE69BB7002CE867 /* GCDWebServerErrorResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE2F18F99C810095C089 /* GCDWebServerErrorResponse.m */; };
|
|
||||||
E2DDD1E91BE69BB7002CE867 /* GCDWebServerFileResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE3118F99C810095C089 /* GCDWebServerFileResponse.m */; };
|
|
||||||
E2DDD1EA1BE69BB7002CE867 /* GCDWebServerStreamedResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE3318F99C810095C089 /* GCDWebServerStreamedResponse.m */; };
|
|
||||||
E2DDD1EB1BE69BB7002CE867 /* GCDWebDAVServer.m in Sources */ = {isa = PBXBuildFile; fileRef = E2A0E80918F3432600C580B1 /* GCDWebDAVServer.m */; };
|
|
||||||
E2DDD1EC1BE69BB7002CE867 /* GCDWebUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = E2BE850918E77ECA0061360B /* GCDWebUploader.m */; };
|
|
||||||
E2DDD1ED1BE69BC5002CE867 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD1BD1BE6956F002CE867 /* MobileCoreServices.framework */; };
|
|
||||||
E2DDD1EE1BE69BC5002CE867 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD1B61BE6951A002CE867 /* CFNetwork.framework */; };
|
|
||||||
E2DDD1EF1BE69BC5002CE867 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD1BB1BE69551002CE867 /* libxml2.tbd */; };
|
|
||||||
E2DDD1F01BE69BC5002CE867 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD1B91BE69545002CE867 /* libz.tbd */; };
|
|
||||||
E2DDD1F11BE69BE9002CE867 /* GCDWebUploader.bundle in Resources */ = {isa = PBXBuildFile; fileRef = E2BE850718E77ECA0061360B /* GCDWebUploader.bundle */; };
|
|
||||||
E2DDD1FA1BE69EE5002CE867 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E2DDD1F91BE69EE5002CE867 /* main.m */; };
|
|
||||||
E2DDD1FD1BE69EE5002CE867 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E2DDD1FC1BE69EE5002CE867 /* AppDelegate.m */; };
|
|
||||||
E2DDD2001BE69EE5002CE867 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E2DDD1FF1BE69EE5002CE867 /* ViewController.m */; };
|
|
||||||
E2DDD2031BE69EE5002CE867 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E2DDD2011BE69EE5002CE867 /* Main.storyboard */; };
|
E2DDD2031BE69EE5002CE867 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E2DDD2011BE69EE5002CE867 /* Main.storyboard */; };
|
||||||
E2DDD2051BE69EE5002CE867 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E2DDD2041BE69EE5002CE867 /* Assets.xcassets */; };
|
E2DDD2051BE69EE5002CE867 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E2DDD2041BE69EE5002CE867 /* Assets.xcassets */; };
|
||||||
E2DDD2081BE69EE5002CE867 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E2DDD2061BE69EE5002CE867 /* LaunchScreen.storyboard */; };
|
E2DDD2081BE69EE5002CE867 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E2DDD2061BE69EE5002CE867 /* LaunchScreen.storyboard */; };
|
||||||
E2DDD20F1BE69F03002CE867 /* GCDWebUploader.bundle in Resources */ = {isa = PBXBuildFile; fileRef = E2BE850718E77ECA0061360B /* GCDWebUploader.bundle */; };
|
|
||||||
E2DDD2101BE69F17002CE867 /* GCDWebServer.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE1718F99C810095C089 /* GCDWebServer.m */; };
|
|
||||||
E2DDD2111BE69F17002CE867 /* GCDWebServerConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE1918F99C810095C089 /* GCDWebServerConnection.m */; };
|
|
||||||
E2DDD2121BE69F17002CE867 /* GCDWebServerFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE1B18F99C810095C089 /* GCDWebServerFunctions.m */; };
|
|
||||||
E2DDD2131BE69F17002CE867 /* GCDWebServerRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE1F18F99C810095C089 /* GCDWebServerRequest.m */; };
|
|
||||||
E2DDD2141BE69F17002CE867 /* GCDWebServerResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE2118F99C810095C089 /* GCDWebServerResponse.m */; };
|
|
||||||
E2DDD2151BE69F17002CE867 /* GCDWebServerDataRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE2418F99C810095C089 /* GCDWebServerDataRequest.m */; };
|
|
||||||
E2DDD2161BE69F17002CE867 /* GCDWebServerFileRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE2618F99C810095C089 /* GCDWebServerFileRequest.m */; };
|
|
||||||
E2DDD2171BE69F17002CE867 /* GCDWebServerMultiPartFormRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE2818F99C810095C089 /* GCDWebServerMultiPartFormRequest.m */; };
|
|
||||||
E2DDD2181BE69F17002CE867 /* GCDWebServerURLEncodedFormRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE2A18F99C810095C089 /* GCDWebServerURLEncodedFormRequest.m */; };
|
|
||||||
E2DDD2191BE69F17002CE867 /* GCDWebServerDataResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE2D18F99C810095C089 /* GCDWebServerDataResponse.m */; };
|
|
||||||
E2DDD21A1BE69F17002CE867 /* GCDWebServerErrorResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE2F18F99C810095C089 /* GCDWebServerErrorResponse.m */; };
|
|
||||||
E2DDD21B1BE69F17002CE867 /* GCDWebServerFileResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE3118F99C810095C089 /* GCDWebServerFileResponse.m */; };
|
|
||||||
E2DDD21C1BE69F17002CE867 /* GCDWebServerStreamedResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = E28BAE3318F99C810095C089 /* GCDWebServerStreamedResponse.m */; };
|
|
||||||
E2DDD21D1BE69F25002CE867 /* GCDWebDAVServer.m in Sources */ = {isa = PBXBuildFile; fileRef = E2A0E80918F3432600C580B1 /* GCDWebDAVServer.m */; };
|
|
||||||
E2DDD21E1BE69F25002CE867 /* GCDWebUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = E2BE850918E77ECA0061360B /* GCDWebUploader.m */; };
|
|
||||||
E2DDD21F1BE6A061002CE867 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE28D691AE1ABAA00F4023C /* UIKit.framework */; };
|
|
||||||
E2DDD2201BE6A067002CE867 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E221129C1690B7BA0048D2B2 /* MobileCoreServices.framework */; };
|
|
||||||
E2DDD2211BE6A06E002CE867 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E22112981690B7AA0048D2B2 /* CFNetwork.framework */; };
|
|
||||||
E2DDD2251BE6A0AE002CE867 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD2241BE6A0AE002CE867 /* libxml2.tbd */; };
|
E2DDD2251BE6A0AE002CE867 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD2241BE6A0AE002CE867 /* libxml2.tbd */; };
|
||||||
E2DDD2271BE6A0B4002CE867 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD2261BE6A0B4002CE867 /* libz.tbd */; };
|
E2DDD2271BE6A0B4002CE867 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD2261BE6A0B4002CE867 /* libz.tbd */; };
|
||||||
E2DDD2281BE6A0D8002CE867 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD2241BE6A0AE002CE867 /* libxml2.tbd */; };
|
|
||||||
E2DDD2291BE6A0D8002CE867 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD2261BE6A0B4002CE867 /* libz.tbd */; };
|
|
||||||
E2DDD22B1BE6A0EB002CE867 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD22A1BE6A0EB002CE867 /* libxml2.tbd */; };
|
E2DDD22B1BE6A0EB002CE867 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD22A1BE6A0EB002CE867 /* libxml2.tbd */; };
|
||||||
E2DDD22D1BE6A0EF002CE867 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD22C1BE6A0EF002CE867 /* libz.tbd */; };
|
E2DDD22D1BE6A0EF002CE867 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD22C1BE6A0EF002CE867 /* libz.tbd */; };
|
||||||
E2DDD22E1BE6A106002CE867 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD22A1BE6A0EB002CE867 /* libxml2.tbd */; };
|
E2DDD22E1BE6A106002CE867 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E2DDD22A1BE6A0EB002CE867 /* libxml2.tbd */; };
|
||||||
@@ -242,6 +202,20 @@
|
|||||||
remoteGlobalIDString = CEE28CD01AE004D800F4023C;
|
remoteGlobalIDString = CEE28CD01AE004D800F4023C;
|
||||||
remoteInfo = "GCDWebServers (Mac)";
|
remoteInfo = "GCDWebServers (Mac)";
|
||||||
};
|
};
|
||||||
|
E24A3C0321E2879000C58878 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = CEE28CEE1AE0051F00F4023C;
|
||||||
|
remoteInfo = "GCDWebServers (iOS)";
|
||||||
|
};
|
||||||
|
E24A3C0521E2879700C58878 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = E2DDD18A1BE69404002CE867;
|
||||||
|
remoteInfo = "GCDWebServers (tvOS)";
|
||||||
|
};
|
||||||
E274F87A187E77E3009E0582 /* PBXContainerItemProxy */ = {
|
E274F87A187E77E3009E0582 /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||||
@@ -273,6 +247,28 @@
|
|||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
E24A3C0C21E28D1E00C58878 /* Copy Frameworks */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 10;
|
||||||
|
files = (
|
||||||
|
E24A3C0E21E28D3C00C58878 /* GCDWebServers.framework in Copy Frameworks */,
|
||||||
|
);
|
||||||
|
name = "Copy Frameworks";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
E24A3C0D21E28D2300C58878 /* Copy Frameworks */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 10;
|
||||||
|
files = (
|
||||||
|
E24A3C0F21E28EFB00C58878 /* GCDWebServers.framework in Copy Frameworks */,
|
||||||
|
);
|
||||||
|
name = "Copy Frameworks";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
E2BE850E18E788910061360B /* CopyFiles */ = {
|
E2BE850E18E788910061360B /* CopyFiles */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -297,9 +293,10 @@
|
|||||||
E208D1B2167BB17E00500836 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
|
E208D1B2167BB17E00500836 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
|
||||||
E221128E1690B6470048D2B2 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
E221128E1690B6470048D2B2 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||||
E22112981690B7AA0048D2B2 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/System/Library/Frameworks/CFNetwork.framework; sourceTree = DEVELOPER_DIR; };
|
E22112981690B7AA0048D2B2 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/System/Library/Frameworks/CFNetwork.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
E221129C1690B7BA0048D2B2 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/System/Library/Frameworks/MobileCoreServices.framework; sourceTree = DEVELOPER_DIR; };
|
E221129C1690B7BA0048D2B2 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/System/Library/Frameworks/CoreServices.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
E24039251BA09207000B7089 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
E24039251BA09207000B7089 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
E24039311BA092B7000B7089 /* Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = "<group>"; };
|
E24039311BA092B7000B7089 /* Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = "<group>"; };
|
||||||
|
E24A3C4021E2940600C58878 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
|
||||||
E28BAE1618F99C810095C089 /* GCDWebServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDWebServer.h; sourceTree = "<group>"; };
|
E28BAE1618F99C810095C089 /* GCDWebServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDWebServer.h; sourceTree = "<group>"; };
|
||||||
E28BAE1718F99C810095C089 /* GCDWebServer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDWebServer.m; sourceTree = "<group>"; };
|
E28BAE1718F99C810095C089 /* GCDWebServer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDWebServer.m; sourceTree = "<group>"; };
|
||||||
E28BAE1818F99C810095C089 /* GCDWebServerConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDWebServerConnection.h; sourceTree = "<group>"; };
|
E28BAE1818F99C810095C089 /* GCDWebServerConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDWebServerConnection.h; sourceTree = "<group>"; };
|
||||||
@@ -338,23 +335,17 @@
|
|||||||
E2DDD1B61BE6951A002CE867 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/CFNetwork.framework; sourceTree = DEVELOPER_DIR; };
|
E2DDD1B61BE6951A002CE867 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/CFNetwork.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
E2DDD1B91BE69545002CE867 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/usr/lib/libz.tbd; sourceTree = DEVELOPER_DIR; };
|
E2DDD1B91BE69545002CE867 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/usr/lib/libz.tbd; sourceTree = DEVELOPER_DIR; };
|
||||||
E2DDD1BB1BE69551002CE867 /* libxml2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/usr/lib/libxml2.tbd; sourceTree = DEVELOPER_DIR; };
|
E2DDD1BB1BE69551002CE867 /* libxml2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/usr/lib/libxml2.tbd; sourceTree = DEVELOPER_DIR; };
|
||||||
E2DDD1BD1BE6956F002CE867 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/MobileCoreServices.framework; sourceTree = DEVELOPER_DIR; };
|
E2DDD1BD1BE6956F002CE867 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/CoreServices.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
E2DDD1BF1BE69576002CE867 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
|
E2DDD1BF1BE69576002CE867 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
E2DDD1C71BE698A8002CE867 /* GCDWebServer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GCDWebServer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
E2DDD1C71BE698A8002CE867 /* GCDWebServer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GCDWebServer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
E2DDD1CA1BE698A8002CE867 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
E2DDD1CD1BE698A8002CE867 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
E2DDD1CC1BE698A8002CE867 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
E2DDD1D01BE698A8002CE867 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||||
E2DDD1CD1BE698A8002CE867 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
|
||||||
E2DDD1CF1BE698A8002CE867 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
|
|
||||||
E2DDD1D01BE698A8002CE867 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
|
|
||||||
E2DDD1D31BE698A8002CE867 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
E2DDD1D31BE698A8002CE867 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||||
E2DDD1D51BE698A8002CE867 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
E2DDD1D51BE698A8002CE867 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
E2DDD1D71BE698A8002CE867 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
E2DDD1D71BE698A8002CE867 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
E2DDD1F61BE69EE4002CE867 /* GCDWebServer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GCDWebServer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
E2DDD1F61BE69EE4002CE867 /* GCDWebServer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GCDWebServer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
E2DDD1F91BE69EE5002CE867 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
E2DDD1FC1BE69EE5002CE867 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
E2DDD1FB1BE69EE5002CE867 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
E2DDD1FF1BE69EE5002CE867 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||||
E2DDD1FC1BE69EE5002CE867 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
|
||||||
E2DDD1FE1BE69EE5002CE867 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
|
|
||||||
E2DDD1FF1BE69EE5002CE867 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
|
|
||||||
E2DDD2021BE69EE5002CE867 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
E2DDD2021BE69EE5002CE867 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||||
E2DDD2041BE69EE5002CE867 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
E2DDD2041BE69EE5002CE867 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
E2DDD2071BE69EE5002CE867 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
E2DDD2071BE69EE5002CE867 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
@@ -396,7 +387,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
CEE28D6A1AE1ABAA00F4023C /* UIKit.framework in Frameworks */,
|
CEE28D6A1AE1ABAA00F4023C /* UIKit.framework in Frameworks */,
|
||||||
CEE28D571AE00AFE00F4023C /* MobileCoreServices.framework in Frameworks */,
|
CEE28D571AE00AFE00F4023C /* CoreServices.framework in Frameworks */,
|
||||||
CEE28D591AE00AFE00F4023C /* CFNetwork.framework in Frameworks */,
|
CEE28D591AE00AFE00F4023C /* CFNetwork.framework in Frameworks */,
|
||||||
E2DDD2251BE6A0AE002CE867 /* libxml2.tbd in Frameworks */,
|
E2DDD2251BE6A0AE002CE867 /* libxml2.tbd in Frameworks */,
|
||||||
E2DDD2271BE6A0B4002CE867 /* libz.tbd in Frameworks */,
|
E2DDD2271BE6A0B4002CE867 /* libz.tbd in Frameworks */,
|
||||||
@@ -416,7 +407,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
E2DDD1C01BE69576002CE867 /* UIKit.framework in Frameworks */,
|
E2DDD1C01BE69576002CE867 /* UIKit.framework in Frameworks */,
|
||||||
E2DDD1BE1BE6956F002CE867 /* MobileCoreServices.framework in Frameworks */,
|
E2DDD1BE1BE6956F002CE867 /* CoreServices.framework in Frameworks */,
|
||||||
E2DDD1B71BE6951A002CE867 /* CFNetwork.framework in Frameworks */,
|
E2DDD1B71BE6951A002CE867 /* CFNetwork.framework in Frameworks */,
|
||||||
E2DDD1BC1BE69551002CE867 /* libxml2.tbd in Frameworks */,
|
E2DDD1BC1BE69551002CE867 /* libxml2.tbd in Frameworks */,
|
||||||
E2DDD1BA1BE69545002CE867 /* libz.tbd in Frameworks */,
|
E2DDD1BA1BE69545002CE867 /* libz.tbd in Frameworks */,
|
||||||
@@ -427,11 +418,7 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
E2DDD1DD1BE69B1C002CE867 /* UIKit.framework in Frameworks */,
|
E24A3C0821E287A300C58878 /* GCDWebServers.framework in Frameworks */,
|
||||||
E2DDD1ED1BE69BC5002CE867 /* MobileCoreServices.framework in Frameworks */,
|
|
||||||
E2DDD1EE1BE69BC5002CE867 /* CFNetwork.framework in Frameworks */,
|
|
||||||
E2DDD1EF1BE69BC5002CE867 /* libxml2.tbd in Frameworks */,
|
|
||||||
E2DDD1F01BE69BC5002CE867 /* libz.tbd in Frameworks */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -439,11 +426,7 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
E2DDD21F1BE6A061002CE867 /* UIKit.framework in Frameworks */,
|
E24A3C0721E2879F00C58878 /* GCDWebServers.framework in Frameworks */,
|
||||||
E2DDD2201BE6A067002CE867 /* MobileCoreServices.framework in Frameworks */,
|
|
||||||
E2DDD2211BE6A06E002CE867 /* CFNetwork.framework in Frameworks */,
|
|
||||||
E2DDD2281BE6A0D8002CE867 /* libxml2.tbd in Frameworks */,
|
|
||||||
E2DDD2291BE6A0D8002CE867 /* libz.tbd in Frameworks */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -487,6 +470,7 @@
|
|||||||
CEE28D081AE0053E00F4023C /* Frameworks */ = {
|
CEE28D081AE0053E00F4023C /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
E24A3C4021E2940600C58878 /* module.modulemap */,
|
||||||
CEE28CF31AE0051F00F4023C /* GCDWebServers.h */,
|
CEE28CF31AE0051F00F4023C /* GCDWebServers.h */,
|
||||||
CEE28CF21AE0051F00F4023C /* Info.plist */,
|
CEE28CF21AE0051F00F4023C /* Info.plist */,
|
||||||
E24039311BA092B7000B7089 /* Tests.m */,
|
E24039311BA092B7000B7089 /* Tests.m */,
|
||||||
@@ -506,7 +490,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
CEE28D691AE1ABAA00F4023C /* UIKit.framework */,
|
CEE28D691AE1ABAA00F4023C /* UIKit.framework */,
|
||||||
E221129C1690B7BA0048D2B2 /* MobileCoreServices.framework */,
|
E221129C1690B7BA0048D2B2 /* CoreServices.framework */,
|
||||||
E22112981690B7AA0048D2B2 /* CFNetwork.framework */,
|
E22112981690B7AA0048D2B2 /* CFNetwork.framework */,
|
||||||
E2DDD2241BE6A0AE002CE867 /* libxml2.tbd */,
|
E2DDD2241BE6A0AE002CE867 /* libxml2.tbd */,
|
||||||
E2DDD2261BE6A0B4002CE867 /* libz.tbd */,
|
E2DDD2261BE6A0B4002CE867 /* libz.tbd */,
|
||||||
@@ -609,7 +593,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E2DDD1BF1BE69576002CE867 /* UIKit.framework */,
|
E2DDD1BF1BE69576002CE867 /* UIKit.framework */,
|
||||||
E2DDD1BD1BE6956F002CE867 /* MobileCoreServices.framework */,
|
E2DDD1BD1BE6956F002CE867 /* CoreServices.framework */,
|
||||||
E2DDD1B61BE6951A002CE867 /* CFNetwork.framework */,
|
E2DDD1B61BE6951A002CE867 /* CFNetwork.framework */,
|
||||||
E2DDD1BB1BE69551002CE867 /* libxml2.tbd */,
|
E2DDD1BB1BE69551002CE867 /* libxml2.tbd */,
|
||||||
E2DDD1B91BE69545002CE867 /* libz.tbd */,
|
E2DDD1B91BE69545002CE867 /* libz.tbd */,
|
||||||
@@ -620,14 +604,11 @@
|
|||||||
E2DDD1C81BE698A8002CE867 /* tvOS */ = {
|
E2DDD1C81BE698A8002CE867 /* tvOS */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E2DDD1CC1BE698A8002CE867 /* AppDelegate.h */,
|
E2DDD1CD1BE698A8002CE867 /* AppDelegate.swift */,
|
||||||
E2DDD1CD1BE698A8002CE867 /* AppDelegate.m */,
|
E2DDD1D01BE698A8002CE867 /* ViewController.swift */,
|
||||||
E2DDD1CF1BE698A8002CE867 /* ViewController.h */,
|
|
||||||
E2DDD1D01BE698A8002CE867 /* ViewController.m */,
|
|
||||||
E2DDD1D21BE698A8002CE867 /* Main.storyboard */,
|
E2DDD1D21BE698A8002CE867 /* Main.storyboard */,
|
||||||
E2DDD1D51BE698A8002CE867 /* Assets.xcassets */,
|
E2DDD1D51BE698A8002CE867 /* Assets.xcassets */,
|
||||||
E2DDD1D71BE698A8002CE867 /* Info.plist */,
|
E2DDD1D71BE698A8002CE867 /* Info.plist */,
|
||||||
E2DDD1CA1BE698A8002CE867 /* main.m */,
|
|
||||||
);
|
);
|
||||||
path = tvOS;
|
path = tvOS;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -635,15 +616,12 @@
|
|||||||
E2DDD1F71BE69EE5002CE867 /* iOS */ = {
|
E2DDD1F71BE69EE5002CE867 /* iOS */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E2DDD1FB1BE69EE5002CE867 /* AppDelegate.h */,
|
E2DDD1FC1BE69EE5002CE867 /* AppDelegate.swift */,
|
||||||
E2DDD1FC1BE69EE5002CE867 /* AppDelegate.m */,
|
E2DDD1FF1BE69EE5002CE867 /* ViewController.swift */,
|
||||||
E2DDD1FE1BE69EE5002CE867 /* ViewController.h */,
|
|
||||||
E2DDD1FF1BE69EE5002CE867 /* ViewController.m */,
|
|
||||||
E2DDD2011BE69EE5002CE867 /* Main.storyboard */,
|
E2DDD2011BE69EE5002CE867 /* Main.storyboard */,
|
||||||
E2DDD2041BE69EE5002CE867 /* Assets.xcassets */,
|
E2DDD2041BE69EE5002CE867 /* Assets.xcassets */,
|
||||||
E2DDD2061BE69EE5002CE867 /* LaunchScreen.storyboard */,
|
E2DDD2061BE69EE5002CE867 /* LaunchScreen.storyboard */,
|
||||||
E2DDD2091BE69EE5002CE867 /* Info.plist */,
|
E2DDD2091BE69EE5002CE867 /* Info.plist */,
|
||||||
E2DDD1F91BE69EE5002CE867 /* main.m */,
|
|
||||||
);
|
);
|
||||||
path = iOS;
|
path = iOS;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -821,12 +799,14 @@
|
|||||||
buildConfigurationList = E2DDD1D81BE698A8002CE867 /* Build configuration list for PBXNativeTarget "GCDWebServer (tvOS)" */;
|
buildConfigurationList = E2DDD1D81BE698A8002CE867 /* Build configuration list for PBXNativeTarget "GCDWebServer (tvOS)" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
E2DDD1C51BE698A8002CE867 /* Resources */,
|
E2DDD1C51BE698A8002CE867 /* Resources */,
|
||||||
|
E24A3C0D21E28D2300C58878 /* Copy Frameworks */,
|
||||||
E2DDD1C31BE698A8002CE867 /* Sources */,
|
E2DDD1C31BE698A8002CE867 /* Sources */,
|
||||||
E2DDD1C41BE698A8002CE867 /* Frameworks */,
|
E2DDD1C41BE698A8002CE867 /* Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
|
E24A3C0621E2879700C58878 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = "GCDWebServer (tvOS)";
|
name = "GCDWebServer (tvOS)";
|
||||||
productName = tvOS;
|
productName = tvOS;
|
||||||
@@ -838,12 +818,14 @@
|
|||||||
buildConfigurationList = E2DDD20A1BE69EE5002CE867 /* Build configuration list for PBXNativeTarget "GCDWebServer (iOS)" */;
|
buildConfigurationList = E2DDD20A1BE69EE5002CE867 /* Build configuration list for PBXNativeTarget "GCDWebServer (iOS)" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
E2DDD1F41BE69EE4002CE867 /* Resources */,
|
E2DDD1F41BE69EE4002CE867 /* Resources */,
|
||||||
|
E24A3C0C21E28D1E00C58878 /* Copy Frameworks */,
|
||||||
E2DDD1F21BE69EE4002CE867 /* Sources */,
|
E2DDD1F21BE69EE4002CE867 /* Sources */,
|
||||||
E2DDD1F31BE69EE4002CE867 /* Frameworks */,
|
E2DDD1F31BE69EE4002CE867 /* Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
|
E24A3C0421E2879000C58878 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = "GCDWebServer (iOS)";
|
name = "GCDWebServer (iOS)";
|
||||||
productName = "GCDWebServer (iOS)";
|
productName = "GCDWebServer (iOS)";
|
||||||
@@ -856,7 +838,7 @@
|
|||||||
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 0910;
|
LastUpgradeCheck = 1130;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
CEE28CD01AE004D800F4023C = {
|
CEE28CD01AE004D800F4023C = {
|
||||||
CreatedOnToolsVersion = 6.3;
|
CreatedOnToolsVersion = 6.3;
|
||||||
@@ -869,9 +851,11 @@
|
|||||||
};
|
};
|
||||||
E2DDD18A1BE69404002CE867 = {
|
E2DDD18A1BE69404002CE867 = {
|
||||||
CreatedOnToolsVersion = 7.1;
|
CreatedOnToolsVersion = 7.1;
|
||||||
|
ProvisioningStyle = Manual;
|
||||||
};
|
};
|
||||||
E2DDD1C61BE698A8002CE867 = {
|
E2DDD1C61BE698A8002CE867 = {
|
||||||
CreatedOnToolsVersion = 7.1;
|
CreatedOnToolsVersion = 7.1;
|
||||||
|
ProvisioningStyle = Manual;
|
||||||
};
|
};
|
||||||
E2DDD1F51BE69EE4002CE867 = {
|
E2DDD1F51BE69EE4002CE867 = {
|
||||||
CreatedOnToolsVersion = 7.1;
|
CreatedOnToolsVersion = 7.1;
|
||||||
@@ -880,13 +864,9 @@
|
|||||||
};
|
};
|
||||||
buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "GCDWebServer" */;
|
buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "GCDWebServer" */;
|
||||||
compatibilityVersion = "Xcode 8.0";
|
compatibilityVersion = "Xcode 8.0";
|
||||||
developmentRegion = English;
|
developmentRegion = en;
|
||||||
hasScannedForEncodings = 1;
|
hasScannedForEncodings = 1;
|
||||||
knownRegions = (
|
knownRegions = (
|
||||||
English,
|
|
||||||
Japanese,
|
|
||||||
French,
|
|
||||||
German,
|
|
||||||
en,
|
en,
|
||||||
Base,
|
Base,
|
||||||
);
|
);
|
||||||
@@ -935,7 +915,6 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
E2DDD1F11BE69BE9002CE867 /* GCDWebUploader.bundle in Resources */,
|
|
||||||
E2DDD1D61BE698A8002CE867 /* Assets.xcassets in Resources */,
|
E2DDD1D61BE698A8002CE867 /* Assets.xcassets in Resources */,
|
||||||
E2DDD1D41BE698A8002CE867 /* Main.storyboard in Resources */,
|
E2DDD1D41BE698A8002CE867 /* Main.storyboard in Resources */,
|
||||||
);
|
);
|
||||||
@@ -945,7 +924,6 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
E2DDD20F1BE69F03002CE867 /* GCDWebUploader.bundle in Resources */,
|
|
||||||
E2DDD2081BE69EE5002CE867 /* LaunchScreen.storyboard in Resources */,
|
E2DDD2081BE69EE5002CE867 /* LaunchScreen.storyboard in Resources */,
|
||||||
E2DDD2051BE69EE5002CE867 /* Assets.xcassets in Resources */,
|
E2DDD2051BE69EE5002CE867 /* Assets.xcassets in Resources */,
|
||||||
E2DDD2031BE69EE5002CE867 /* Main.storyboard in Resources */,
|
E2DDD2031BE69EE5002CE867 /* Main.storyboard in Resources */,
|
||||||
@@ -1073,24 +1051,8 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
E2DDD1DE1BE69BB7002CE867 /* GCDWebServer.m in Sources */,
|
E2DDD1D11BE698A8002CE867 /* ViewController.swift in Sources */,
|
||||||
E2DDD1DF1BE69BB7002CE867 /* GCDWebServerConnection.m in Sources */,
|
E2DDD1CE1BE698A8002CE867 /* AppDelegate.swift in Sources */,
|
||||||
E2DDD1E01BE69BB7002CE867 /* GCDWebServerFunctions.m in Sources */,
|
|
||||||
E2DDD1E11BE69BB7002CE867 /* GCDWebServerRequest.m in Sources */,
|
|
||||||
E2DDD1E21BE69BB7002CE867 /* GCDWebServerResponse.m in Sources */,
|
|
||||||
E2DDD1E31BE69BB7002CE867 /* GCDWebServerDataRequest.m in Sources */,
|
|
||||||
E2DDD1E41BE69BB7002CE867 /* GCDWebServerFileRequest.m in Sources */,
|
|
||||||
E2DDD1E51BE69BB7002CE867 /* GCDWebServerMultiPartFormRequest.m in Sources */,
|
|
||||||
E2DDD1E61BE69BB7002CE867 /* GCDWebServerURLEncodedFormRequest.m in Sources */,
|
|
||||||
E2DDD1E71BE69BB7002CE867 /* GCDWebServerDataResponse.m in Sources */,
|
|
||||||
E2DDD1E81BE69BB7002CE867 /* GCDWebServerErrorResponse.m in Sources */,
|
|
||||||
E2DDD1E91BE69BB7002CE867 /* GCDWebServerFileResponse.m in Sources */,
|
|
||||||
E2DDD1EA1BE69BB7002CE867 /* GCDWebServerStreamedResponse.m in Sources */,
|
|
||||||
E2DDD1EB1BE69BB7002CE867 /* GCDWebDAVServer.m in Sources */,
|
|
||||||
E2DDD1EC1BE69BB7002CE867 /* GCDWebUploader.m in Sources */,
|
|
||||||
E2DDD1D11BE698A8002CE867 /* ViewController.m in Sources */,
|
|
||||||
E2DDD1CE1BE698A8002CE867 /* AppDelegate.m in Sources */,
|
|
||||||
E2DDD1CB1BE698A8002CE867 /* main.m in Sources */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -1098,24 +1060,8 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
E2DDD2101BE69F17002CE867 /* GCDWebServer.m in Sources */,
|
E2DDD2001BE69EE5002CE867 /* ViewController.swift in Sources */,
|
||||||
E2DDD2111BE69F17002CE867 /* GCDWebServerConnection.m in Sources */,
|
E2DDD1FD1BE69EE5002CE867 /* AppDelegate.swift in Sources */,
|
||||||
E2DDD2121BE69F17002CE867 /* GCDWebServerFunctions.m in Sources */,
|
|
||||||
E2DDD2131BE69F17002CE867 /* GCDWebServerRequest.m in Sources */,
|
|
||||||
E2DDD2141BE69F17002CE867 /* GCDWebServerResponse.m in Sources */,
|
|
||||||
E2DDD2151BE69F17002CE867 /* GCDWebServerDataRequest.m in Sources */,
|
|
||||||
E2DDD2161BE69F17002CE867 /* GCDWebServerFileRequest.m in Sources */,
|
|
||||||
E2DDD2171BE69F17002CE867 /* GCDWebServerMultiPartFormRequest.m in Sources */,
|
|
||||||
E2DDD2181BE69F17002CE867 /* GCDWebServerURLEncodedFormRequest.m in Sources */,
|
|
||||||
E2DDD2191BE69F17002CE867 /* GCDWebServerDataResponse.m in Sources */,
|
|
||||||
E2DDD21A1BE69F17002CE867 /* GCDWebServerErrorResponse.m in Sources */,
|
|
||||||
E2DDD21B1BE69F17002CE867 /* GCDWebServerFileResponse.m in Sources */,
|
|
||||||
E2DDD21C1BE69F17002CE867 /* GCDWebServerStreamedResponse.m in Sources */,
|
|
||||||
E2DDD21D1BE69F25002CE867 /* GCDWebDAVServer.m in Sources */,
|
|
||||||
E2DDD21E1BE69F25002CE867 /* GCDWebUploader.m in Sources */,
|
|
||||||
E2DDD2001BE69EE5002CE867 /* ViewController.m in Sources */,
|
|
||||||
E2DDD1FD1BE69EE5002CE867 /* AppDelegate.m in Sources */,
|
|
||||||
E2DDD1FA1BE69EE5002CE867 /* main.m in Sources */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -1137,6 +1083,16 @@
|
|||||||
target = CEE28CD01AE004D800F4023C /* GCDWebServers (Mac) */;
|
target = CEE28CD01AE004D800F4023C /* GCDWebServers (Mac) */;
|
||||||
targetProxy = E240392C1BA09207000B7089 /* PBXContainerItemProxy */;
|
targetProxy = E240392C1BA09207000B7089 /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
|
E24A3C0421E2879000C58878 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = CEE28CEE1AE0051F00F4023C /* GCDWebServers (iOS) */;
|
||||||
|
targetProxy = E24A3C0321E2879000C58878 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
E24A3C0621E2879700C58878 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = E2DDD18A1BE69404002CE867 /* GCDWebServers (tvOS) */;
|
||||||
|
targetProxy = E24A3C0521E2879700C58878 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
E274F87B187E77E3009E0582 /* PBXTargetDependency */ = {
|
E274F87B187E77E3009E0582 /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
target = 8DD76FA90486AB0100D96B5E /* GCDWebServer (Mac) */;
|
target = 8DD76FA90486AB0100D96B5E /* GCDWebServer (Mac) */;
|
||||||
@@ -1208,7 +1164,8 @@
|
|||||||
1DEB928A08733DD80010E9CD /* Debug */ = {
|
1DEB928A08733DD80010E9CD /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_VERSION_STRING = 3.3.4;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
BUNDLE_VERSION_STRING = 3.5.4;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
GCC_OPTIMIZATION_LEVEL = 0;
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
@@ -1217,16 +1174,20 @@
|
|||||||
HEADER_SEARCH_PATHS = "$(SDKROOT)/usr/include/libxml2";
|
HEADER_SEARCH_PATHS = "$(SDKROOT)/usr/include/libxml2";
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "net.pol-online.GCDWebServers";
|
PRODUCT_BUNDLE_IDENTIFIER = "net.pol-online.GCDWebServers";
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
WARNING_CFLAGS = (
|
WARNING_CFLAGS = (
|
||||||
"-Wall",
|
"-Wall",
|
||||||
"-Weverything",
|
"-Weverything",
|
||||||
"-Wshadow",
|
"-Wshadow",
|
||||||
"-Wshorten-64-to-32",
|
"-Wshorten-64-to-32",
|
||||||
|
"-Wstrict-prototypes",
|
||||||
|
"-Wdeprecated-declarations",
|
||||||
"-Wno-vla",
|
"-Wno-vla",
|
||||||
"-Wno-explicit-ownership-type",
|
"-Wno-explicit-ownership-type",
|
||||||
"-Wno-gnu-statement-expression",
|
"-Wno-gnu-statement-expression",
|
||||||
"-Wno-direct-ivar-access",
|
"-Wno-direct-ivar-access",
|
||||||
"-Wno-implicit-retain-self",
|
|
||||||
"-Wno-assign-enum",
|
"-Wno-assign-enum",
|
||||||
"-Wno-format-nonliteral",
|
"-Wno-format-nonliteral",
|
||||||
"-Wno-cast-align",
|
"-Wno-cast-align",
|
||||||
@@ -1237,7 +1198,6 @@
|
|||||||
"-Wno-cstring-format-directive",
|
"-Wno-cstring-format-directive",
|
||||||
"-Wno-reserved-id-macro",
|
"-Wno-reserved-id-macro",
|
||||||
"-Wno-cast-qual",
|
"-Wno-cast-qual",
|
||||||
"-Wno-partial-availability",
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
@@ -1245,13 +1205,17 @@
|
|||||||
1DEB928B08733DD80010E9CD /* Release */ = {
|
1DEB928B08733DD80010E9CD /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_VERSION_STRING = 3.3.4;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
BUNDLE_VERSION_STRING = 3.5.4;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = __GCDWEBSERVER_ENABLE_TESTING__;
|
GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = __GCDWEBSERVER_ENABLE_TESTING__;
|
||||||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||||
HEADER_SEARCH_PATHS = "$(SDKROOT)/usr/include/libxml2";
|
HEADER_SEARCH_PATHS = "$(SDKROOT)/usr/include/libxml2";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "net.pol-online.GCDWebServers";
|
PRODUCT_BUNDLE_IDENTIFIER = "net.pol-online.GCDWebServers";
|
||||||
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
|
SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
WARNING_CFLAGS = "-Wall";
|
WARNING_CFLAGS = "-Wall";
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
@@ -1298,9 +1262,11 @@
|
|||||||
INFOPLIST_FILE = Frameworks/Info.plist;
|
INFOPLIST_FILE = Frameworks/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
|
MODULEMAP_FILE = Frameworks/module.modulemap;
|
||||||
PRODUCT_NAME = GCDWebServers;
|
PRODUCT_NAME = GCDWebServers;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@@ -1314,9 +1280,11 @@
|
|||||||
INFOPLIST_FILE = Frameworks/Info.plist;
|
INFOPLIST_FILE = Frameworks/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
|
MODULEMAP_FILE = Frameworks/module.modulemap;
|
||||||
PRODUCT_NAME = GCDWebServers;
|
PRODUCT_NAME = GCDWebServers;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
@@ -1373,13 +1341,16 @@
|
|||||||
E2DDD1901BE69404002CE867 /* Debug */ = {
|
E2DDD1901BE69404002CE867 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Manual;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
|
DEVELOPMENT_TEAM = "";
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 1;
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
INFOPLIST_FILE = Frameworks/Info.plist;
|
INFOPLIST_FILE = Frameworks/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
PRODUCT_NAME = GCDWebServers;
|
PRODUCT_NAME = GCDWebServers;
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SDKROOT = appletvos;
|
SDKROOT = appletvos;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||||
@@ -1389,13 +1360,16 @@
|
|||||||
E2DDD1911BE69404002CE867 /* Release */ = {
|
E2DDD1911BE69404002CE867 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Manual;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
|
DEVELOPMENT_TEAM = "";
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 1;
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
INFOPLIST_FILE = Frameworks/Info.plist;
|
INFOPLIST_FILE = Frameworks/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
PRODUCT_NAME = GCDWebServers;
|
PRODUCT_NAME = GCDWebServers;
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SDKROOT = appletvos;
|
SDKROOT = appletvos;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||||
@@ -1405,9 +1379,13 @@
|
|||||||
E2DDD1D91BE698A8002CE867 /* Debug */ = {
|
E2DDD1D91BE698A8002CE867 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Manual;
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEVELOPMENT_TEAM = "";
|
||||||
INFOPLIST_FILE = tvOS/Info.plist;
|
INFOPLIST_FILE = tvOS/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
PRODUCT_NAME = GCDWebServer;
|
PRODUCT_NAME = GCDWebServer;
|
||||||
PROVISIONING_PROFILE = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SDKROOT = appletvos;
|
SDKROOT = appletvos;
|
||||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||||
};
|
};
|
||||||
@@ -1416,9 +1394,13 @@
|
|||||||
E2DDD1DA1BE698A8002CE867 /* Release */ = {
|
E2DDD1DA1BE698A8002CE867 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Manual;
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEVELOPMENT_TEAM = "";
|
||||||
INFOPLIST_FILE = tvOS/Info.plist;
|
INFOPLIST_FILE = tvOS/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
PRODUCT_NAME = GCDWebServer;
|
PRODUCT_NAME = GCDWebServer;
|
||||||
PROVISIONING_PROFILE = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SDKROOT = appletvos;
|
SDKROOT = appletvos;
|
||||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||||
};
|
};
|
||||||
@@ -1427,11 +1409,12 @@
|
|||||||
E2DDD20B1BE69EE5002CE867 /* Debug */ = {
|
E2DDD20B1BE69EE5002CE867 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
ENABLE_BITCODE = YES;
|
ENABLE_BITCODE = YES;
|
||||||
INFOPLIST_FILE = iOS/Info.plist;
|
INFOPLIST_FILE = iOS/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
PRODUCT_NAME = GCDWebServer;
|
PRODUCT_NAME = GCDWebServer;
|
||||||
PROVISIONING_PROFILE = "";
|
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
@@ -1440,11 +1423,12 @@
|
|||||||
E2DDD20C1BE69EE5002CE867 /* Release */ = {
|
E2DDD20C1BE69EE5002CE867 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
ENABLE_BITCODE = YES;
|
ENABLE_BITCODE = YES;
|
||||||
INFOPLIST_FILE = iOS/Info.plist;
|
INFOPLIST_FILE = iOS/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
PRODUCT_NAME = GCDWebServer;
|
PRODUCT_NAME = GCDWebServer;
|
||||||
PROVISIONING_PROFILE = "";
|
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0910"
|
LastUpgradeVersion = "1130"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
@@ -26,9 +26,8 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
enableAddressSanitizer = "YES"
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
language = ""
|
enableAddressSanitizer = "YES">
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
|
||||||
<Testables>
|
<Testables>
|
||||||
<TestableReference
|
<TestableReference
|
||||||
skipped = "NO">
|
skipped = "NO">
|
||||||
@@ -41,14 +40,11 @@
|
|||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</TestableReference>
|
</TestableReference>
|
||||||
</Testables>
|
</Testables>
|
||||||
<AdditionalOptions>
|
|
||||||
</AdditionalOptions>
|
|
||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
language = ""
|
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
@@ -64,8 +60,6 @@
|
|||||||
ReferencedContainer = "container:GCDWebServer.xcodeproj">
|
ReferencedContainer = "container:GCDWebServer.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</MacroExpansion>
|
</MacroExpansion>
|
||||||
<AdditionalOptions>
|
|
||||||
</AdditionalOptions>
|
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Release"
|
buildConfiguration = "Release"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0910"
|
LastUpgradeVersion = "1130"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
@@ -26,10 +26,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
language = ""
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<Testables>
|
|
||||||
</Testables>
|
|
||||||
<MacroExpansion>
|
<MacroExpansion>
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
@@ -39,14 +36,13 @@
|
|||||||
ReferencedContainer = "container:GCDWebServer.xcodeproj">
|
ReferencedContainer = "container:GCDWebServer.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</MacroExpansion>
|
</MacroExpansion>
|
||||||
<AdditionalOptions>
|
<Testables>
|
||||||
</AdditionalOptions>
|
</Testables>
|
||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
language = ""
|
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
@@ -62,8 +58,6 @@
|
|||||||
ReferencedContainer = "container:GCDWebServer.xcodeproj">
|
ReferencedContainer = "container:GCDWebServer.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</MacroExpansion>
|
</MacroExpansion>
|
||||||
<AdditionalOptions>
|
|
||||||
</AdditionalOptions>
|
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Release"
|
buildConfiguration = "Release"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0910"
|
LastUpgradeVersion = "1130"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
@@ -26,10 +26,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
language = ""
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<Testables>
|
|
||||||
</Testables>
|
|
||||||
<MacroExpansion>
|
<MacroExpansion>
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
@@ -39,14 +36,13 @@
|
|||||||
ReferencedContainer = "container:GCDWebServer.xcodeproj">
|
ReferencedContainer = "container:GCDWebServer.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</MacroExpansion>
|
</MacroExpansion>
|
||||||
<AdditionalOptions>
|
<Testables>
|
||||||
</AdditionalOptions>
|
</Testables>
|
||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
language = ""
|
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
@@ -62,8 +58,6 @@
|
|||||||
ReferencedContainer = "container:GCDWebServer.xcodeproj">
|
ReferencedContainer = "container:GCDWebServer.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</MacroExpansion>
|
</MacroExpansion>
|
||||||
<AdditionalOptions>
|
|
||||||
</AdditionalOptions>
|
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Release"
|
buildConfiguration = "Release"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -42,7 +42,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
* GCDWebServerRequest instance created with the same basic info.
|
* GCDWebServerRequest instance created with the same basic info.
|
||||||
* Otherwise, it simply returns nil.
|
* Otherwise, it simply returns nil.
|
||||||
*/
|
*/
|
||||||
typedef GCDWebServerRequest* _Nullable (^GCDWebServerMatchBlock)(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery);
|
typedef GCDWebServerRequest* _Nullable (^GCDWebServerMatchBlock)(NSString* requestMethod, NSURL* requestURL, NSDictionary<NSString*, NSString*>* requestHeaders, NSString* urlPath, NSDictionary<NSString*, NSString*>* urlQuery);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The GCDWebServerProcessBlock is called after the HTTP request has been fully
|
* The GCDWebServerProcessBlock is called after the HTTP request has been fully
|
||||||
@@ -69,6 +69,13 @@ typedef GCDWebServerResponse* _Nullable (^GCDWebServerProcessBlock)(__kindof GCD
|
|||||||
typedef void (^GCDWebServerCompletionBlock)(GCDWebServerResponse* _Nullable response);
|
typedef void (^GCDWebServerCompletionBlock)(GCDWebServerResponse* _Nullable response);
|
||||||
typedef void (^GCDWebServerAsyncProcessBlock)(__kindof GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock);
|
typedef void (^GCDWebServerAsyncProcessBlock)(__kindof GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GCDWebServerBuiltInLoggerBlock is used to override the built-in logger at runtime.
|
||||||
|
* The block will be passed the log level and the log message, see setLogLevel for
|
||||||
|
* documentation of the log levels for the built-in logger.
|
||||||
|
*/
|
||||||
|
typedef void (^GCDWebServerBuiltInLoggerBlock)(int level, NSString* _Nonnull message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The port used by the GCDWebServer (NSNumber / NSUInteger).
|
* The port used by the GCDWebServer (NSNumber / NSUInteger).
|
||||||
*
|
*
|
||||||
@@ -85,6 +92,13 @@ extern NSString* const GCDWebServerOption_Port;
|
|||||||
*/
|
*/
|
||||||
extern NSString* const GCDWebServerOption_BonjourName;
|
extern NSString* const GCDWebServerOption_BonjourName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Bonjour TXT Data used by the GCDWebServer (NSDictionary<NSString, NSString>).
|
||||||
|
*
|
||||||
|
* The default value is nil.
|
||||||
|
*/
|
||||||
|
extern NSString* const GCDWebServerOption_BonjourTXTData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Bonjour service type used by the GCDWebServer (NSString).
|
* The Bonjour service type used by the GCDWebServer (NSString).
|
||||||
*
|
*
|
||||||
@@ -365,7 +379,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
|
|||||||
*
|
*
|
||||||
* Returns NO if the server failed to start and sets "error" argument if not NULL.
|
* Returns NO if the server failed to start and sets "error" argument if not NULL.
|
||||||
*/
|
*/
|
||||||
- (BOOL)startWithOptions:(nullable NSDictionary*)options error:(NSError** _Nullable)error;
|
- (BOOL)startWithOptions:(nullable NSDictionary<NSString*, id>*)options error:(NSError** _Nullable)error;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the server and prevents it to accepts new HTTP requests.
|
* Stops the server and prevents it to accepts new HTTP requests.
|
||||||
@@ -444,7 +458,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
|
|||||||
*
|
*
|
||||||
* @warning This method must be used from the main thread only.
|
* @warning This method must be used from the main thread only.
|
||||||
*/
|
*/
|
||||||
- (BOOL)runWithOptions:(nullable NSDictionary*)options error:(NSError** _Nullable)error;
|
- (BOOL)runWithOptions:(nullable NSDictionary<NSString*, id>*)options error:(NSError** _Nullable)error;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -573,6 +587,14 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
|
|||||||
*/
|
*/
|
||||||
+ (void)setLogLevel:(int)level;
|
+ (void)setLogLevel:(int)level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a logger to be used instead of the built-in logger which logs to stderr.
|
||||||
|
*
|
||||||
|
* IMPORTANT: In order for this override to work, you should not be specifying
|
||||||
|
* a custom logger at compile time with "__GCDWEBSERVER_LOGGING_HEADER__".
|
||||||
|
*/
|
||||||
|
+ (void)setBuiltInLogger:(GCDWebServerBuiltInLoggerBlock)block;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs a message to the logging facility at the VERBOSE level.
|
* Logs a message to the logging facility at the VERBOSE level.
|
||||||
*/
|
*/
|
||||||
@@ -613,7 +635,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
|
|||||||
*
|
*
|
||||||
* Returns the number of failed tests or -1 if server failed to start.
|
* Returns the number of failed tests or -1 if server failed to start.
|
||||||
*/
|
*/
|
||||||
- (NSInteger)runTestsWithOptions:(nullable NSDictionary*)options inDirectory:(NSString*)path;
|
- (NSInteger)runTestsWithOptions:(nullable NSDictionary<NSString*, id>*)options inDirectory:(NSString*)path;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -53,6 +53,7 @@
|
|||||||
NSString* const GCDWebServerOption_Port = @"Port";
|
NSString* const GCDWebServerOption_Port = @"Port";
|
||||||
NSString* const GCDWebServerOption_BonjourName = @"BonjourName";
|
NSString* const GCDWebServerOption_BonjourName = @"BonjourName";
|
||||||
NSString* const GCDWebServerOption_BonjourType = @"BonjourType";
|
NSString* const GCDWebServerOption_BonjourType = @"BonjourType";
|
||||||
|
NSString* const GCDWebServerOption_BonjourTXTData = @"BonjourTXTData";
|
||||||
NSString* const GCDWebServerOption_RequestNATPortMapping = @"RequestNATPortMapping";
|
NSString* const GCDWebServerOption_RequestNATPortMapping = @"RequestNATPortMapping";
|
||||||
NSString* const GCDWebServerOption_BindToLocalhost = @"BindToLocalhost";
|
NSString* const GCDWebServerOption_BindToLocalhost = @"BindToLocalhost";
|
||||||
NSString* const GCDWebServerOption_MaxPendingConnections = @"MaxPendingConnections";
|
NSString* const GCDWebServerOption_MaxPendingConnections = @"MaxPendingConnections";
|
||||||
@@ -85,18 +86,24 @@ static BOOL _run;
|
|||||||
|
|
||||||
#ifdef __GCDWEBSERVER_LOGGING_FACILITY_BUILTIN__
|
#ifdef __GCDWEBSERVER_LOGGING_FACILITY_BUILTIN__
|
||||||
|
|
||||||
|
static GCDWebServerBuiltInLoggerBlock _builtInLoggerBlock;
|
||||||
|
|
||||||
void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* format, ...) {
|
void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* format, ...) {
|
||||||
static const char* levelNames[] = {"DEBUG", "VERBOSE", "INFO", "WARNING", "ERROR"};
|
static const char* levelNames[] = {"DEBUG", "VERBOSE", "INFO", "WARNING", "ERROR"};
|
||||||
static int enableLogging = -1;
|
static int enableLogging = -1;
|
||||||
if (enableLogging < 0) {
|
if (enableLogging < 0) {
|
||||||
enableLogging = (isatty(STDERR_FILENO) ? 1 : 0);
|
enableLogging = (isatty(STDERR_FILENO) ? 1 : 0);
|
||||||
}
|
}
|
||||||
if (enableLogging) {
|
if (_builtInLoggerBlock || enableLogging) {
|
||||||
va_list arguments;
|
va_list arguments;
|
||||||
va_start(arguments, format);
|
va_start(arguments, format);
|
||||||
NSString* message = [[NSString alloc] initWithFormat:format arguments:arguments];
|
NSString* message = [[NSString alloc] initWithFormat:format arguments:arguments];
|
||||||
va_end(arguments);
|
va_end(arguments);
|
||||||
fprintf(stderr, "[%s] %s\n", levelNames[level], [message UTF8String]);
|
if (_builtInLoggerBlock) {
|
||||||
|
_builtInLoggerBlock(level, message);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "[%s] %s\n", levelNames[level], [message UTF8String]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,14 +148,14 @@ static void _ExecuteMainThreadRunLoopSources() {
|
|||||||
@implementation GCDWebServer {
|
@implementation GCDWebServer {
|
||||||
dispatch_queue_t _syncQueue;
|
dispatch_queue_t _syncQueue;
|
||||||
dispatch_group_t _sourceGroup;
|
dispatch_group_t _sourceGroup;
|
||||||
NSMutableArray* _handlers;
|
NSMutableArray<GCDWebServerHandler*>* _handlers;
|
||||||
NSInteger _activeConnections; // Accessed through _syncQueue only
|
NSInteger _activeConnections; // Accessed through _syncQueue only
|
||||||
BOOL _connected; // Accessed on main thread only
|
BOOL _connected; // Accessed on main thread only
|
||||||
CFRunLoopTimerRef _disconnectTimer; // Accessed on main thread only
|
CFRunLoopTimerRef _disconnectTimer; // Accessed on main thread only
|
||||||
|
|
||||||
NSDictionary* _options;
|
NSDictionary<NSString*, id>* _options;
|
||||||
NSMutableDictionary* _authenticationBasicAccounts;
|
NSMutableDictionary<NSString*, NSString*>* _authenticationBasicAccounts;
|
||||||
NSMutableDictionary* _authenticationDigestAccounts;
|
NSMutableDictionary<NSString*, NSString*>* _authenticationDigestAccounts;
|
||||||
Class _connectionClass;
|
Class _connectionClass;
|
||||||
CFTimeInterval _disconnectDelay;
|
CFTimeInterval _disconnectDelay;
|
||||||
dispatch_source_t _source4;
|
dispatch_source_t _source4;
|
||||||
@@ -206,10 +213,8 @@ static void _ExecuteMainThreadRunLoopSources() {
|
|||||||
if (_backgroundTask == UIBackgroundTaskInvalid) {
|
if (_backgroundTask == UIBackgroundTaskInvalid) {
|
||||||
GWS_LOG_DEBUG(@"Did start background task");
|
GWS_LOG_DEBUG(@"Did start background task");
|
||||||
_backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
|
_backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
|
||||||
|
|
||||||
GWS_LOG_WARNING(@"Application is being suspended while %@ is still connected", [self class]);
|
GWS_LOG_WARNING(@"Application is being suspended while %@ is still connected", [self class]);
|
||||||
[self _endBackgroundTask];
|
[self _endBackgroundTask];
|
||||||
|
|
||||||
}];
|
}];
|
||||||
} else {
|
} else {
|
||||||
GWS_DNOT_REACHED();
|
GWS_DNOT_REACHED();
|
||||||
@@ -238,22 +243,20 @@ static void _ExecuteMainThreadRunLoopSources() {
|
|||||||
|
|
||||||
- (void)willStartConnection:(GCDWebServerConnection*)connection {
|
- (void)willStartConnection:(GCDWebServerConnection*)connection {
|
||||||
dispatch_sync(_syncQueue, ^{
|
dispatch_sync(_syncQueue, ^{
|
||||||
|
GWS_DCHECK(self->_activeConnections >= 0);
|
||||||
GWS_DCHECK(_activeConnections >= 0);
|
if (self->_activeConnections == 0) {
|
||||||
if (_activeConnections == 0) {
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
if (_disconnectTimer) {
|
if (self->_disconnectTimer) {
|
||||||
CFRunLoopTimerInvalidate(_disconnectTimer);
|
CFRunLoopTimerInvalidate(self->_disconnectTimer);
|
||||||
CFRelease(_disconnectTimer);
|
CFRelease(self->_disconnectTimer);
|
||||||
_disconnectTimer = NULL;
|
self->_disconnectTimer = NULL;
|
||||||
}
|
}
|
||||||
if (_connected == NO) {
|
if (self->_connected == NO) {
|
||||||
[self _didConnect];
|
[self _didConnect];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_activeConnections += 1;
|
self->_activeConnections += 1;
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,22 +295,22 @@ static void _ExecuteMainThreadRunLoopSources() {
|
|||||||
|
|
||||||
- (void)didEndConnection:(GCDWebServerConnection*)connection {
|
- (void)didEndConnection:(GCDWebServerConnection*)connection {
|
||||||
dispatch_sync(_syncQueue, ^{
|
dispatch_sync(_syncQueue, ^{
|
||||||
GWS_DCHECK(_activeConnections > 0);
|
GWS_DCHECK(self->_activeConnections > 0);
|
||||||
_activeConnections -= 1;
|
self->_activeConnections -= 1;
|
||||||
if (_activeConnections == 0) {
|
if (self->_activeConnections == 0) {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
if ((_disconnectDelay > 0.0) && (_source4 != NULL)) {
|
if ((self->_disconnectDelay > 0.0) && (self->_source4 != NULL)) {
|
||||||
if (_disconnectTimer) {
|
if (self->_disconnectTimer) {
|
||||||
CFRunLoopTimerInvalidate(_disconnectTimer);
|
CFRunLoopTimerInvalidate(self->_disconnectTimer);
|
||||||
CFRelease(_disconnectTimer);
|
CFRelease(self->_disconnectTimer);
|
||||||
}
|
}
|
||||||
_disconnectTimer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + _disconnectDelay, 0.0, 0, 0, ^(CFRunLoopTimerRef timer) {
|
self->_disconnectTimer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + self->_disconnectDelay, 0.0, 0, 0, ^(CFRunLoopTimerRef timer) {
|
||||||
GWS_DCHECK([NSThread isMainThread]);
|
GWS_DCHECK([NSThread isMainThread]);
|
||||||
[self _didDisconnect];
|
[self _didDisconnect];
|
||||||
CFRelease(_disconnectTimer);
|
CFRelease(self->_disconnectTimer);
|
||||||
_disconnectTimer = NULL;
|
self->_disconnectTimer = NULL;
|
||||||
});
|
});
|
||||||
CFRunLoopAddTimer(CFRunLoopGetMain(), _disconnectTimer, kCFRunLoopCommonModes);
|
CFRunLoopAddTimer(CFRunLoopGetMain(), self->_disconnectTimer, kCFRunLoopCommonModes);
|
||||||
} else {
|
} else {
|
||||||
[self _didDisconnect];
|
[self _didDisconnect];
|
||||||
}
|
}
|
||||||
@@ -412,19 +415,21 @@ static void _SocketCallBack(CFSocketRef s, CFSocketCallBackType type, CFDataRef
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline id _GetOption(NSDictionary* options, NSString* key, id defaultValue) {
|
static inline id _GetOption(NSDictionary<NSString*, id>* options, NSString* key, id defaultValue) {
|
||||||
id value = [options objectForKey:key];
|
id value = [options objectForKey:key];
|
||||||
return value ? value : defaultValue;
|
return value ? value : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline NSString* _EncodeBase64(NSString* string) {
|
static inline NSString* _EncodeBase64(NSString* string) {
|
||||||
NSData* data = [string dataUsingEncoding:NSUTF8StringEncoding];
|
NSData* data = [string dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
#if (TARGET_OS_IPHONE && !(__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0)) || (!TARGET_OS_IPHONE && !(__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_9))
|
#if TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_9)
|
||||||
if (![data respondsToSelector:@selector(base64EncodedDataWithOptions:)]) {
|
|
||||||
return [data base64Encoding];
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return [[NSString alloc] initWithData:[data base64EncodedDataWithOptions:0] encoding:NSASCIIStringEncoding];
|
return [[NSString alloc] initWithData:[data base64EncodedDataWithOptions:0] encoding:NSASCIIStringEncoding];
|
||||||
|
#else
|
||||||
|
if (@available(macOS 10.9, *)) {
|
||||||
|
return [[NSString alloc] initWithData:[data base64EncodedDataWithOptions:0] encoding:NSASCIIStringEncoding];
|
||||||
|
}
|
||||||
|
return [data base64Encoding];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int)_createListeningSocket:(BOOL)useIPv6
|
- (int)_createListeningSocket:(BOOL)useIPv6
|
||||||
@@ -469,7 +474,6 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
dispatch_group_enter(_sourceGroup);
|
dispatch_group_enter(_sourceGroup);
|
||||||
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, listeningSocket, 0, dispatch_get_global_queue(_dispatchQueuePriority, 0));
|
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, ^{
|
dispatch_source_set_cancel_handler(source, ^{
|
||||||
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
int result = close(listeningSocket);
|
int result = close(listeningSocket);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
@@ -478,11 +482,9 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
GWS_LOG_DEBUG(@"Did close %s listening socket %i", isIPv6 ? "IPv6" : "IPv4", listeningSocket);
|
GWS_LOG_DEBUG(@"Did close %s listening socket %i", isIPv6 ? "IPv6" : "IPv4", listeningSocket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dispatch_group_leave(_sourceGroup);
|
dispatch_group_leave(self->_sourceGroup);
|
||||||
|
|
||||||
});
|
});
|
||||||
dispatch_source_set_event_handler(source, ^{
|
dispatch_source_set_event_handler(source, ^{
|
||||||
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
struct sockaddr_storage remoteSockAddr;
|
struct sockaddr_storage remoteSockAddr;
|
||||||
socklen_t remoteAddrLen = sizeof(remoteSockAddr);
|
socklen_t remoteAddrLen = sizeof(remoteSockAddr);
|
||||||
@@ -503,13 +505,12 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
int noSigPipe = 1;
|
int noSigPipe = 1;
|
||||||
setsockopt(socket, SOL_SOCKET, SO_NOSIGPIPE, &noSigPipe, sizeof(noSigPipe)); // Make sure this socket cannot generate SIG_PIPE
|
setsockopt(socket, SOL_SOCKET, SO_NOSIGPIPE, &noSigPipe, sizeof(noSigPipe)); // Make sure this socket cannot generate SIG_PIPE
|
||||||
|
|
||||||
GCDWebServerConnection* connection = [[_connectionClass alloc] initWithServer:self localAddress:localAddress remoteAddress:remoteAddress socket:socket]; // Connection will automatically retain itself while opened
|
GCDWebServerConnection* connection = [(GCDWebServerConnection*)[self->_connectionClass alloc] initWithServer:self localAddress:localAddress remoteAddress:remoteAddress socket:socket]; // Connection will automatically retain itself while opened
|
||||||
[connection self]; // Prevent compiler from complaining about unused variable / useless statement
|
[connection self]; // Prevent compiler from complaining about unused variable / useless statement
|
||||||
} else {
|
} else {
|
||||||
GWS_LOG_ERROR(@"Failed accepting %s socket: %s (%i)", isIPv6 ? "IPv6" : "IPv4", strerror(errno), errno);
|
GWS_LOG_ERROR(@"Failed accepting %s socket: %s (%i)", isIPv6 ? "IPv6" : "IPv4", strerror(errno), errno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
@@ -517,9 +518,9 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
- (BOOL)_start:(NSError**)error {
|
- (BOOL)_start:(NSError**)error {
|
||||||
GWS_DCHECK(_source4 == NULL);
|
GWS_DCHECK(_source4 == NULL);
|
||||||
|
|
||||||
NSUInteger port = [_GetOption(_options, GCDWebServerOption_Port, @0) unsignedIntegerValue];
|
NSUInteger port = [(NSNumber*)_GetOption(_options, GCDWebServerOption_Port, @0) unsignedIntegerValue];
|
||||||
BOOL bindToLocalhost = [_GetOption(_options, GCDWebServerOption_BindToLocalhost, @NO) boolValue];
|
BOOL bindToLocalhost = [(NSNumber*)_GetOption(_options, GCDWebServerOption_BindToLocalhost, @NO) boolValue];
|
||||||
NSUInteger maxPendingConnections = [_GetOption(_options, GCDWebServerOption_MaxPendingConnections, @16) unsignedIntegerValue];
|
NSUInteger maxPendingConnections = [(NSNumber*)_GetOption(_options, GCDWebServerOption_MaxPendingConnections, @16) unsignedIntegerValue];
|
||||||
|
|
||||||
struct sockaddr_in addr4;
|
struct sockaddr_in addr4;
|
||||||
bzero(&addr4, sizeof(addr4));
|
bzero(&addr4, sizeof(addr4));
|
||||||
@@ -553,27 +554,27 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
_serverName = [_GetOption(_options, GCDWebServerOption_ServerName, NSStringFromClass([self class])) copy];
|
_serverName = [(NSString*)_GetOption(_options, GCDWebServerOption_ServerName, NSStringFromClass([self class])) copy];
|
||||||
NSString* authenticationMethod = _GetOption(_options, GCDWebServerOption_AuthenticationMethod, nil);
|
NSString* authenticationMethod = _GetOption(_options, GCDWebServerOption_AuthenticationMethod, nil);
|
||||||
if ([authenticationMethod isEqualToString:GCDWebServerAuthenticationMethod_Basic]) {
|
if ([authenticationMethod isEqualToString:GCDWebServerAuthenticationMethod_Basic]) {
|
||||||
_authenticationRealm = [_GetOption(_options, GCDWebServerOption_AuthenticationRealm, _serverName) copy];
|
_authenticationRealm = [(NSString*)_GetOption(_options, GCDWebServerOption_AuthenticationRealm, _serverName) copy];
|
||||||
_authenticationBasicAccounts = [[NSMutableDictionary alloc] init];
|
_authenticationBasicAccounts = [[NSMutableDictionary alloc] init];
|
||||||
NSDictionary* accounts = _GetOption(_options, GCDWebServerOption_AuthenticationAccounts, @{});
|
NSDictionary* accounts = _GetOption(_options, GCDWebServerOption_AuthenticationAccounts, @{});
|
||||||
[accounts enumerateKeysAndObjectsUsingBlock:^(NSString* username, NSString* password, BOOL* stop) {
|
[accounts enumerateKeysAndObjectsUsingBlock:^(NSString* username, NSString* password, BOOL* stop) {
|
||||||
[_authenticationBasicAccounts setObject:_EncodeBase64([NSString stringWithFormat:@"%@:%@", username, password]) forKey:username];
|
[self->_authenticationBasicAccounts setObject:_EncodeBase64([NSString stringWithFormat:@"%@:%@", username, password]) forKey:username];
|
||||||
}];
|
}];
|
||||||
} else if ([authenticationMethod isEqualToString:GCDWebServerAuthenticationMethod_DigestAccess]) {
|
} else if ([authenticationMethod isEqualToString:GCDWebServerAuthenticationMethod_DigestAccess]) {
|
||||||
_authenticationRealm = [_GetOption(_options, GCDWebServerOption_AuthenticationRealm, _serverName) copy];
|
_authenticationRealm = [(NSString*)_GetOption(_options, GCDWebServerOption_AuthenticationRealm, _serverName) copy];
|
||||||
_authenticationDigestAccounts = [[NSMutableDictionary alloc] init];
|
_authenticationDigestAccounts = [[NSMutableDictionary alloc] init];
|
||||||
NSDictionary* accounts = _GetOption(_options, GCDWebServerOption_AuthenticationAccounts, @{});
|
NSDictionary* accounts = _GetOption(_options, GCDWebServerOption_AuthenticationAccounts, @{});
|
||||||
[accounts enumerateKeysAndObjectsUsingBlock:^(NSString* username, NSString* password, BOOL* stop) {
|
[accounts enumerateKeysAndObjectsUsingBlock:^(NSString* username, NSString* password, BOOL* stop) {
|
||||||
[_authenticationDigestAccounts setObject:GCDWebServerComputeMD5Digest(@"%@:%@:%@", username, _authenticationRealm, password) forKey:username];
|
[self->_authenticationDigestAccounts setObject:GCDWebServerComputeMD5Digest(@"%@:%@:%@", username, self->_authenticationRealm, password) forKey:username];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
_connectionClass = _GetOption(_options, GCDWebServerOption_ConnectionClass, [GCDWebServerConnection class]);
|
_connectionClass = _GetOption(_options, GCDWebServerOption_ConnectionClass, [GCDWebServerConnection class]);
|
||||||
_shouldAutomaticallyMapHEADToGET = [_GetOption(_options, GCDWebServerOption_AutomaticallyMapHEADToGET, @YES) boolValue];
|
_shouldAutomaticallyMapHEADToGET = [(NSNumber*)_GetOption(_options, GCDWebServerOption_AutomaticallyMapHEADToGET, @YES) boolValue];
|
||||||
_disconnectDelay = [_GetOption(_options, GCDWebServerOption_ConnectedStateCoalescingInterval, @1.0) doubleValue];
|
_disconnectDelay = [(NSNumber*)_GetOption(_options, GCDWebServerOption_ConnectedStateCoalescingInterval, @1.0) doubleValue];
|
||||||
_dispatchQueuePriority = [_GetOption(_options, GCDWebServerOption_DispatchQueuePriority, @(DISPATCH_QUEUE_PRIORITY_DEFAULT)) longValue];
|
_dispatchQueuePriority = [(NSNumber*)_GetOption(_options, GCDWebServerOption_DispatchQueuePriority, @(DISPATCH_QUEUE_PRIORITY_DEFAULT)) longValue];
|
||||||
|
|
||||||
_source4 = [self _createDispatchSourceWithListeningSocket:listeningSocket4 isIPv6:NO];
|
_source4 = [self _createDispatchSourceWithListeningSocket:listeningSocket4 isIPv6:NO];
|
||||||
_source6 = [self _createDispatchSourceWithListeningSocket:listeningSocket6 isIPv6:YES];
|
_source6 = [self _createDispatchSourceWithListeningSocket:listeningSocket6 isIPv6:YES];
|
||||||
@@ -590,6 +591,29 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
CFNetServiceSetClient(_registrationService, _NetServiceRegisterCallBack, &context);
|
CFNetServiceSetClient(_registrationService, _NetServiceRegisterCallBack, &context);
|
||||||
CFNetServiceScheduleWithRunLoop(_registrationService, CFRunLoopGetMain(), kCFRunLoopCommonModes);
|
CFNetServiceScheduleWithRunLoop(_registrationService, CFRunLoopGetMain(), kCFRunLoopCommonModes);
|
||||||
CFStreamError streamError = {0};
|
CFStreamError streamError = {0};
|
||||||
|
|
||||||
|
NSDictionary* txtDataDictionary = _GetOption(_options, GCDWebServerOption_BonjourTXTData, nil);
|
||||||
|
if (txtDataDictionary != nil) {
|
||||||
|
NSUInteger count = txtDataDictionary.count;
|
||||||
|
CFStringRef keys[count];
|
||||||
|
CFStringRef values[count];
|
||||||
|
NSUInteger index = 0;
|
||||||
|
for (NSString *key in txtDataDictionary) {
|
||||||
|
NSString *value = txtDataDictionary[key];
|
||||||
|
keys[index] = (__bridge CFStringRef)(key);
|
||||||
|
values[index] = (__bridge CFStringRef)(value);
|
||||||
|
index ++;
|
||||||
|
}
|
||||||
|
CFDictionaryRef txtDictionary = CFDictionaryCreate(CFAllocatorGetDefault(), (void *)keys, (void *)values, count, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||||
|
if (txtDictionary != NULL) {
|
||||||
|
CFDataRef txtData = CFNetServiceCreateTXTDataWithDictionary(nil, txtDictionary);
|
||||||
|
Boolean setTXTDataResult = CFNetServiceSetTXTData(_registrationService, txtData);
|
||||||
|
if (!setTXTDataResult) {
|
||||||
|
GWS_LOG_ERROR(@"Failed setting TXTData");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CFNetServiceRegisterWithOptions(_registrationService, 0, &streamError);
|
CFNetServiceRegisterWithOptions(_registrationService, 0, &streamError);
|
||||||
|
|
||||||
_resolutionService = CFNetServiceCreateCopy(kCFAllocatorDefault, _registrationService);
|
_resolutionService = CFNetServiceCreateCopy(kCFAllocatorDefault, _registrationService);
|
||||||
@@ -604,7 +628,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([_GetOption(_options, GCDWebServerOption_RequestNATPortMapping, @NO) boolValue]) {
|
if ([(NSNumber*)_GetOption(_options, GCDWebServerOption_RequestNATPortMapping, @NO) boolValue]) {
|
||||||
DNSServiceErrorType status = DNSServiceNATPortMappingCreate(&_dnsService, 0, 0, kDNSServiceProtocol_TCP, htons(port), htons(port), 0, _DNSServiceCallBack, (__bridge void*)self);
|
DNSServiceErrorType status = DNSServiceNATPortMappingCreate(&_dnsService, 0, 0, kDNSServiceProtocol_TCP, htons(port), htons(port), 0, _DNSServiceCallBack, (__bridge void*)self);
|
||||||
if (status == kDNSServiceErr_NoError) {
|
if (status == kDNSServiceErr_NoError) {
|
||||||
CFSocketContext context = {0, (__bridge void*)self, NULL, NULL, NULL};
|
CFSocketContext context = {0, (__bridge void*)self, NULL, NULL, NULL};
|
||||||
@@ -632,7 +656,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
GWS_LOG_INFO(@"%@ started on port %i and reachable at %@", [self class], (int)_port, self.serverURL);
|
GWS_LOG_INFO(@"%@ started on port %i and reachable at %@", [self class], (int)_port, self.serverURL);
|
||||||
if ([_delegate respondsToSelector:@selector(webServerDidStart:)]) {
|
if ([_delegate respondsToSelector:@selector(webServerDidStart:)]) {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[_delegate webServerDidStart:self];
|
[self->_delegate webServerDidStart:self];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -693,10 +717,10 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
_authenticationDigestAccounts = nil;
|
_authenticationDigestAccounts = nil;
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
if (_disconnectTimer) {
|
if (self->_disconnectTimer) {
|
||||||
CFRunLoopTimerInvalidate(_disconnectTimer);
|
CFRunLoopTimerInvalidate(self->_disconnectTimer);
|
||||||
CFRelease(_disconnectTimer);
|
CFRelease(self->_disconnectTimer);
|
||||||
_disconnectTimer = NULL;
|
self->_disconnectTimer = NULL;
|
||||||
[self _didDisconnect];
|
[self _didDisconnect];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -704,7 +728,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
GWS_LOG_INFO(@"%@ stopped", [self class]);
|
GWS_LOG_INFO(@"%@ stopped", [self class]);
|
||||||
if ([_delegate respondsToSelector:@selector(webServerDidStop:)]) {
|
if ([_delegate respondsToSelector:@selector(webServerDidStop:)]) {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[_delegate webServerDidStop:self];
|
[self->_delegate webServerDidStop:self];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -729,11 +753,11 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
- (BOOL)startWithOptions:(NSDictionary*)options error:(NSError**)error {
|
- (BOOL)startWithOptions:(NSDictionary<NSString*, id>*)options error:(NSError**)error {
|
||||||
if (_options == nil) {
|
if (_options == nil) {
|
||||||
_options = options ? [options copy] : @{};
|
_options = options ? [options copy] : @{};
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
_suspendInBackground = [_GetOption(_options, GCDWebServerOption_AutomaticallySuspendInBackground, @YES) boolValue];
|
_suspendInBackground = [(NSNumber*)_GetOption(_options, GCDWebServerOption_AutomaticallySuspendInBackground, @YES) boolValue];
|
||||||
if (((_suspendInBackground == NO) || ([[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground)) && ![self _start:error])
|
if (((_suspendInBackground == NO) || ([[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground)) && ![self _start:error])
|
||||||
#else
|
#else
|
||||||
if (![self _start:error])
|
if (![self _start:error])
|
||||||
@@ -840,7 +864,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
return [self runWithOptions:options error:NULL];
|
return [self runWithOptions:options error:NULL];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)runWithOptions:(NSDictionary*)options error:(NSError**)error {
|
- (BOOL)runWithOptions:(NSDictionary<NSString*, id>*)options error:(NSError**)error {
|
||||||
GWS_DCHECK([NSThread isMainThread]);
|
GWS_DCHECK([NSThread isMainThread]);
|
||||||
BOOL success = NO;
|
BOOL success = NO;
|
||||||
_run = YES;
|
_run = YES;
|
||||||
@@ -876,15 +900,14 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)addDefaultHandlerForMethod:(NSString*)method requestClass:(Class)aClass asyncProcessBlock:(GCDWebServerAsyncProcessBlock)block {
|
- (void)addDefaultHandlerForMethod:(NSString*)method requestClass:(Class)aClass asyncProcessBlock:(GCDWebServerAsyncProcessBlock)block {
|
||||||
[self addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) {
|
[self
|
||||||
|
addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary<NSString*, NSString*>* requestHeaders, NSString* urlPath, NSDictionary<NSString*, NSString*>* urlQuery) {
|
||||||
if (![requestMethod isEqualToString:method]) {
|
if (![requestMethod isEqualToString:method]) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
return [[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery];
|
return [(GCDWebServerRequest*)[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery];
|
||||||
|
}
|
||||||
}
|
asyncProcessBlock:block];
|
||||||
asyncProcessBlock:block];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)addHandlerForMethod:(NSString*)method path:(NSString*)path requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block {
|
- (void)addHandlerForMethod:(NSString*)method path:(NSString*)path requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block {
|
||||||
@@ -898,18 +921,17 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
|
|
||||||
- (void)addHandlerForMethod:(NSString*)method path:(NSString*)path requestClass:(Class)aClass asyncProcessBlock:(GCDWebServerAsyncProcessBlock)block {
|
- (void)addHandlerForMethod:(NSString*)method path:(NSString*)path requestClass:(Class)aClass asyncProcessBlock:(GCDWebServerAsyncProcessBlock)block {
|
||||||
if ([path hasPrefix:@"/"] && [aClass isSubclassOfClass:[GCDWebServerRequest class]]) {
|
if ([path hasPrefix:@"/"] && [aClass isSubclassOfClass:[GCDWebServerRequest class]]) {
|
||||||
[self addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) {
|
[self
|
||||||
|
addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary<NSString*, NSString*>* requestHeaders, NSString* urlPath, NSDictionary<NSString*, NSString*>* urlQuery) {
|
||||||
if (![requestMethod isEqualToString:method]) {
|
if (![requestMethod isEqualToString:method]) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
if ([urlPath caseInsensitiveCompare:path] != NSOrderedSame) {
|
if ([urlPath caseInsensitiveCompare:path] != NSOrderedSame) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
return [[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery];
|
return [(GCDWebServerRequest*)[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery];
|
||||||
|
}
|
||||||
}
|
asyncProcessBlock:block];
|
||||||
asyncProcessBlock:block];
|
|
||||||
} else {
|
} else {
|
||||||
GWS_DNOT_REACHED();
|
GWS_DNOT_REACHED();
|
||||||
}
|
}
|
||||||
@@ -927,36 +949,35 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
- (void)addHandlerForMethod:(NSString*)method pathRegex:(NSString*)regex requestClass:(Class)aClass asyncProcessBlock:(GCDWebServerAsyncProcessBlock)block {
|
- (void)addHandlerForMethod:(NSString*)method pathRegex:(NSString*)regex requestClass:(Class)aClass asyncProcessBlock:(GCDWebServerAsyncProcessBlock)block {
|
||||||
NSRegularExpression* expression = [NSRegularExpression regularExpressionWithPattern:regex options:NSRegularExpressionCaseInsensitive error:NULL];
|
NSRegularExpression* expression = [NSRegularExpression regularExpressionWithPattern:regex options:NSRegularExpressionCaseInsensitive error:NULL];
|
||||||
if (expression && [aClass isSubclassOfClass:[GCDWebServerRequest class]]) {
|
if (expression && [aClass isSubclassOfClass:[GCDWebServerRequest class]]) {
|
||||||
[self addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) {
|
[self
|
||||||
|
addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary<NSString*, NSString*>* requestHeaders, NSString* urlPath, NSDictionary<NSString*, NSString*>* urlQuery) {
|
||||||
if (![requestMethod isEqualToString:method]) {
|
if (![requestMethod isEqualToString:method]) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
|
||||||
|
|
||||||
NSArray* matches = [expression matchesInString:urlPath options:0 range:NSMakeRange(0, urlPath.length)];
|
|
||||||
if (matches.count == 0) {
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSMutableArray* captures = [NSMutableArray array];
|
|
||||||
for (NSTextCheckingResult* result in matches) {
|
|
||||||
// Start at 1; index 0 is the whole string
|
|
||||||
for (NSUInteger i = 1; i < result.numberOfRanges; 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]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NSArray* matches = [expression matchesInString:urlPath options:0 range:NSMakeRange(0, urlPath.length)];
|
||||||
|
if (matches.count == 0) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMutableArray* captures = [NSMutableArray array];
|
||||||
|
for (NSTextCheckingResult* result in matches) {
|
||||||
|
// Start at 1; index 0 is the whole string
|
||||||
|
for (NSUInteger i = 1; i < result.numberOfRanges; 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]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GCDWebServerRequest* request = [(GCDWebServerRequest*)[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery];
|
||||||
|
[request setAttribute:captures forKey:GCDWebServerRequestAttribute_RegexCaptures];
|
||||||
|
return request;
|
||||||
}
|
}
|
||||||
}
|
asyncProcessBlock:block];
|
||||||
|
|
||||||
GCDWebServerRequest* request = [[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery];
|
|
||||||
[request setAttribute:captures forKey:GCDWebServerRequestAttribute_RegexCaptures];
|
|
||||||
return request;
|
|
||||||
|
|
||||||
}
|
|
||||||
asyncProcessBlock:block];
|
|
||||||
} else {
|
} else {
|
||||||
GWS_DNOT_REACHED();
|
GWS_DNOT_REACHED();
|
||||||
}
|
}
|
||||||
@@ -971,11 +992,9 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
path:path
|
path:path
|
||||||
requestClass:[GCDWebServerRequest class]
|
requestClass:[GCDWebServerRequest class]
|
||||||
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
||||||
|
|
||||||
GCDWebServerResponse* response = [GCDWebServerDataResponse responseWithData:staticData contentType:contentType];
|
GCDWebServerResponse* response = [GCDWebServerDataResponse responseWithData:staticData contentType:contentType];
|
||||||
response.cacheControlMaxAge = cacheAge;
|
response.cacheControlMaxAge = cacheAge;
|
||||||
return response;
|
return response;
|
||||||
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -984,7 +1003,6 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
path:path
|
path:path
|
||||||
requestClass:[GCDWebServerRequest class]
|
requestClass:[GCDWebServerRequest class]
|
||||||
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
||||||
|
|
||||||
GCDWebServerResponse* response = nil;
|
GCDWebServerResponse* response = nil;
|
||||||
if (allowRangeRequests) {
|
if (allowRangeRequests) {
|
||||||
response = [GCDWebServerFileResponse responseWithFile:filePath byteRange:request.byteRange isAttachment:isAttachment];
|
response = [GCDWebServerFileResponse responseWithFile:filePath byteRange:request.byteRange isAttachment:isAttachment];
|
||||||
@@ -994,34 +1012,33 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
}
|
}
|
||||||
response.cacheControlMaxAge = cacheAge;
|
response.cacheControlMaxAge = cacheAge;
|
||||||
return response;
|
return response;
|
||||||
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (GCDWebServerResponse*)_responseWithContentsOfDirectory:(NSString*)path {
|
- (GCDWebServerResponse*)_responseWithContentsOfDirectory:(NSString*)path {
|
||||||
NSDirectoryEnumerator* enumerator = [[NSFileManager defaultManager] enumeratorAtPath:path];
|
NSArray* contents = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL] sortedArrayUsingSelector:@selector(localizedStandardCompare:)];
|
||||||
if (enumerator == nil) {
|
if (contents == nil) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
NSMutableString* html = [NSMutableString string];
|
NSMutableString* html = [NSMutableString string];
|
||||||
[html appendString:@"<!DOCTYPE html>\n"];
|
[html appendString:@"<!DOCTYPE html>\n"];
|
||||||
[html appendString:@"<html><head><meta charset=\"utf-8\"></head><body>\n"];
|
[html appendString:@"<html><head><meta charset=\"utf-8\"></head><body>\n"];
|
||||||
[html appendString:@"<ul>\n"];
|
[html appendString:@"<ul>\n"];
|
||||||
for (NSString* file in enumerator) {
|
for (NSString* entry in contents) {
|
||||||
if (![file hasPrefix:@"."]) {
|
if (![entry hasPrefix:@"."]) {
|
||||||
NSString* type = [[enumerator fileAttributes] objectForKey:NSFileType];
|
NSString* type = [[[NSFileManager defaultManager] attributesOfItemAtPath:[path stringByAppendingPathComponent:entry] error:NULL] objectForKey:NSFileType];
|
||||||
|
GWS_DCHECK(type);
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
NSString* escapedFile = [file stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
NSString* escapedFile = [entry stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
GWS_DCHECK(escapedFile);
|
GWS_DCHECK(escapedFile);
|
||||||
if ([type isEqualToString:NSFileTypeRegular]) {
|
if ([type isEqualToString:NSFileTypeRegular]) {
|
||||||
[html appendFormat:@"<li><a href=\"%@\">%@</a></li>\n", escapedFile, file];
|
[html appendFormat:@"<li><a href=\"%@\">%@</a></li>\n", escapedFile, entry];
|
||||||
} else if ([type isEqualToString:NSFileTypeDirectory]) {
|
} else if ([type isEqualToString:NSFileTypeDirectory]) {
|
||||||
[html appendFormat:@"<li><a href=\"%@/\">%@/</a></li>\n", escapedFile, file];
|
[html appendFormat:@"<li><a href=\"%@/\">%@/</a></li>\n", escapedFile, entry];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[enumerator skipDescendents];
|
|
||||||
}
|
}
|
||||||
[html appendString:@"</ul>\n"];
|
[html appendString:@"</ul>\n"];
|
||||||
[html appendString:@"</body></html>\n"];
|
[html appendString:@"</body></html>\n"];
|
||||||
@@ -1031,21 +1048,19 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
- (void)addGETHandlerForBasePath:(NSString*)basePath directoryPath:(NSString*)directoryPath indexFilename:(NSString*)indexFilename cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests {
|
- (void)addGETHandlerForBasePath:(NSString*)basePath directoryPath:(NSString*)directoryPath indexFilename:(NSString*)indexFilename cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests {
|
||||||
if ([basePath hasPrefix:@"/"] && [basePath hasSuffix:@"/"]) {
|
if ([basePath hasPrefix:@"/"] && [basePath hasSuffix:@"/"]) {
|
||||||
GCDWebServer* __unsafe_unretained server = self;
|
GCDWebServer* __unsafe_unretained server = self;
|
||||||
[self addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) {
|
[self
|
||||||
|
addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary<NSString*, NSString*>* requestHeaders, NSString* urlPath, NSDictionary<NSString*, NSString*>* urlQuery) {
|
||||||
if (![requestMethod isEqualToString:@"GET"]) {
|
if (![requestMethod isEqualToString:@"GET"]) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
if (![urlPath hasPrefix:basePath]) {
|
if (![urlPath hasPrefix:basePath]) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
return [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery];
|
return [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery];
|
||||||
|
}
|
||||||
}
|
|
||||||
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
||||||
|
|
||||||
GCDWebServerResponse* response = nil;
|
GCDWebServerResponse* response = nil;
|
||||||
NSString* filePath = [directoryPath stringByAppendingPathComponent:[request.path substringFromIndex:basePath.length]];
|
NSString* filePath = [directoryPath stringByAppendingPathComponent:GCDWebServerNormalizePath([request.path substringFromIndex:basePath.length])];
|
||||||
NSString* fileType = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:NULL] fileType];
|
NSString* fileType = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:NULL] fileType];
|
||||||
if (fileType) {
|
if (fileType) {
|
||||||
if ([fileType isEqualToString:NSFileTypeDirectory]) {
|
if ([fileType isEqualToString:NSFileTypeDirectory]) {
|
||||||
@@ -1072,7 +1087,6 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_NotFound];
|
response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_NotFound];
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
|
|
||||||
}];
|
}];
|
||||||
} else {
|
} else {
|
||||||
GWS_DNOT_REACHED();
|
GWS_DNOT_REACHED();
|
||||||
@@ -1091,6 +1105,14 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (void)setBuiltInLogger:(GCDWebServerBuiltInLoggerBlock)block {
|
||||||
|
#if defined(__GCDWEBSERVER_LOGGING_FACILITY_BUILTIN__)
|
||||||
|
_builtInLoggerBlock = block;
|
||||||
|
#else
|
||||||
|
GWS_DNOT_REACHED(); // Built-in logger must be enabled in order to override
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
- (void)logVerbose:(NSString*)format, ... {
|
- (void)logVerbose:(NSString*)format, ... {
|
||||||
va_list arguments;
|
va_list arguments;
|
||||||
va_start(arguments, format);
|
va_start(arguments, format);
|
||||||
@@ -1148,9 +1170,9 @@ static CFHTTPMessageRef _CreateHTTPMessageFromPerformingRequest(NSData* inData,
|
|||||||
if (httpSocket > 0) {
|
if (httpSocket > 0) {
|
||||||
struct sockaddr_in addr4;
|
struct sockaddr_in addr4;
|
||||||
bzero(&addr4, sizeof(addr4));
|
bzero(&addr4, sizeof(addr4));
|
||||||
addr4.sin_len = sizeof(port);
|
addr4.sin_len = sizeof(addr4);
|
||||||
addr4.sin_family = AF_INET;
|
addr4.sin_family = AF_INET;
|
||||||
addr4.sin_port = htons(8080);
|
addr4.sin_port = htons(port);
|
||||||
addr4.sin_addr.s_addr = htonl(INADDR_ANY);
|
addr4.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
if (connect(httpSocket, (void*)&addr4, sizeof(addr4)) == 0) {
|
if (connect(httpSocket, (void*)&addr4, sizeof(addr4)) == 0) {
|
||||||
if (write(httpSocket, inData.bytes, inData.length) == (ssize_t)inData.length) {
|
if (write(httpSocket, inData.bytes, inData.length) == (ssize_t)inData.length) {
|
||||||
@@ -1190,7 +1212,7 @@ static void _LogResult(NSString* format, ...) {
|
|||||||
fprintf(stdout, "%s\n", [message UTF8String]);
|
fprintf(stdout, "%s\n", [message UTF8String]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSInteger)runTestsWithOptions:(NSDictionary*)options inDirectory:(NSString*)path {
|
- (NSInteger)runTestsWithOptions:(NSDictionary<NSString*, id>*)options inDirectory:(NSString*)path {
|
||||||
GWS_DCHECK([NSThread isMainThread]);
|
GWS_DCHECK([NSThread isMainThread]);
|
||||||
NSArray* ignoredHeaders = @[ @"Date", @"Etag" ]; // Dates are always different by definition and ETags depend on file system node IDs
|
NSArray* ignoredHeaders = @[ @"Date", @"Etag" ]; // Dates are always different by definition and ETags depend on file system node IDs
|
||||||
NSInteger result = -1;
|
NSInteger result = -1;
|
||||||
@@ -1198,7 +1220,7 @@ static void _LogResult(NSString* format, ...) {
|
|||||||
_ExecuteMainThreadRunLoopSources();
|
_ExecuteMainThreadRunLoopSources();
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
NSArray* files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL];
|
NSArray* files = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL] sortedArrayUsingSelector:@selector(localizedStandardCompare:)];
|
||||||
for (NSString* requestFile in files) {
|
for (NSString* requestFile in files) {
|
||||||
if (![requestFile hasSuffix:@".request"]) {
|
if (![requestFile hasSuffix:@".request"]) {
|
||||||
continue;
|
continue;
|
||||||
@@ -1258,7 +1280,7 @@ static void _LogResult(NSString* format, ...) {
|
|||||||
if ([actualContentLength isEqualToString:expectedContentLength] && (actualBody.length > expectedBody.length)) { // Handle web browser closing connection before retrieving entire body (e.g. when playing a video file)
|
if ([actualContentLength isEqualToString:expectedContentLength] && (actualBody.length > expectedBody.length)) { // Handle web browser closing connection before retrieving entire body (e.g. when playing a video file)
|
||||||
actualBody = [actualBody subdataWithRange:NSMakeRange(0, expectedBody.length)];
|
actualBody = [actualBody subdataWithRange:NSMakeRange(0, expectedBody.length)];
|
||||||
}
|
}
|
||||||
if (![actualBody isEqualToData:expectedBody]) {
|
if ((actualBody && expectedBody && ![actualBody isEqualToData:expectedBody]) || (actualBody && !expectedBody) || (!actualBody && expectedBody)) {
|
||||||
_LogResult(@" Bodies not matching:\n Expected: %lu bytes\n Actual: %lu bytes", (unsigned long)expectedBody.length, (unsigned long)actualBody.length);
|
_LogResult(@" Bodies not matching:\n Expected: %lu bytes\n Actual: %lu bytes", (unsigned long)expectedBody.length, (unsigned long)actualBody.length);
|
||||||
success = NO;
|
success = NO;
|
||||||
#if !TARGET_OS_IPHONE
|
#if !TARGET_OS_IPHONE
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -130,7 +130,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
*
|
*
|
||||||
* The default implementation returns the original URL.
|
* The default implementation returns the original URL.
|
||||||
*/
|
*/
|
||||||
- (NSURL*)rewriteRequestURL:(NSURL*)url withMethod:(NSString*)method headers:(NSDictionary*)headers;
|
- (NSURL*)rewriteRequestURL:(NSURL*)url withMethod:(NSString*)method headers:(NSDictionary<NSString*, NSString*>*)headers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assuming a valid HTTP request was received, this method is called before
|
* Assuming a valid HTTP request was received, this method is called before
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -193,22 +193,18 @@ NS_ASSUME_NONNULL_END
|
|||||||
CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Transfer-Encoding"), CFSTR("chunked"));
|
CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Transfer-Encoding"), CFSTR("chunked"));
|
||||||
}
|
}
|
||||||
[_response.additionalHeaders enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL* stop) {
|
[_response.additionalHeaders enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL* stop) {
|
||||||
CFHTTPMessageSetHeaderFieldValue(_responseMessage, (__bridge CFStringRef)key, (__bridge CFStringRef)obj);
|
CFHTTPMessageSetHeaderFieldValue(self->_responseMessage, (__bridge CFStringRef)key, (__bridge CFStringRef)obj);
|
||||||
}];
|
}];
|
||||||
[self writeHeadersWithCompletionBlock:^(BOOL success) {
|
[self writeHeadersWithCompletionBlock:^(BOOL success) {
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
if (hasBody) {
|
if (hasBody) {
|
||||||
[self writeBodyWithCompletionBlock:^(BOOL successInner) {
|
[self writeBodyWithCompletionBlock:^(BOOL successInner) {
|
||||||
|
[self->_response performClose]; // TODO: There's nothing we can do on failure as headers have already been sent
|
||||||
[_response performClose]; // TODO: There's nothing we can do on failure as headers have already been sent
|
|
||||||
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
} else if (hasBody) {
|
} else if (hasBody) {
|
||||||
[_response performClose];
|
[self->_response performClose];
|
||||||
}
|
}
|
||||||
|
|
||||||
}];
|
}];
|
||||||
} else {
|
} else {
|
||||||
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
||||||
@@ -238,15 +234,13 @@ NS_ASSUME_NONNULL_END
|
|||||||
if (length) {
|
if (length) {
|
||||||
[self readBodyWithRemainingLength:length
|
[self readBodyWithRemainingLength:length
|
||||||
completionBlock:^(BOOL success) {
|
completionBlock:^(BOOL success) {
|
||||||
|
|
||||||
NSError* localError = nil;
|
NSError* localError = nil;
|
||||||
if ([_request performClose:&localError]) {
|
if ([self->_request performClose:&localError]) {
|
||||||
[self _startProcessingRequest];
|
[self _startProcessingRequest];
|
||||||
} else {
|
} else {
|
||||||
GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error);
|
GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", self->_socket, error);
|
||||||
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
[self abortRequest:self->_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
||||||
}
|
}
|
||||||
|
|
||||||
}];
|
}];
|
||||||
} else {
|
} else {
|
||||||
if ([_request performClose:&error]) {
|
if ([_request performClose:&error]) {
|
||||||
@@ -269,15 +263,13 @@ NS_ASSUME_NONNULL_END
|
|||||||
NSMutableData* chunkData = [[NSMutableData alloc] initWithData:initialData];
|
NSMutableData* chunkData = [[NSMutableData alloc] initWithData:initialData];
|
||||||
[self readNextBodyChunk:chunkData
|
[self readNextBodyChunk:chunkData
|
||||||
completionBlock:^(BOOL success) {
|
completionBlock:^(BOOL success) {
|
||||||
|
|
||||||
NSError* localError = nil;
|
NSError* localError = nil;
|
||||||
if ([_request performClose:&localError]) {
|
if ([self->_request performClose:&localError]) {
|
||||||
[self _startProcessingRequest];
|
[self _startProcessingRequest];
|
||||||
} else {
|
} else {
|
||||||
GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error);
|
GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", self->_socket, error);
|
||||||
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
[self abortRequest:self->_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
||||||
}
|
}
|
||||||
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,15 +278,14 @@ NS_ASSUME_NONNULL_END
|
|||||||
NSMutableData* headersData = [[NSMutableData alloc] initWithCapacity:kHeadersReadCapacity];
|
NSMutableData* headersData = [[NSMutableData alloc] initWithCapacity:kHeadersReadCapacity];
|
||||||
[self readHeaders:headersData
|
[self readHeaders:headersData
|
||||||
withCompletionBlock:^(NSData* extraData) {
|
withCompletionBlock:^(NSData* extraData) {
|
||||||
|
|
||||||
if (extraData) {
|
if (extraData) {
|
||||||
NSString* requestMethod = CFBridgingRelease(CFHTTPMessageCopyRequestMethod(_requestMessage)); // Method verbs are case-sensitive and uppercase
|
NSString* requestMethod = CFBridgingRelease(CFHTTPMessageCopyRequestMethod(self->_requestMessage)); // Method verbs are case-sensitive and uppercase
|
||||||
if (_server.shouldAutomaticallyMapHEADToGET && [requestMethod isEqualToString:@"HEAD"]) {
|
if (self->_server.shouldAutomaticallyMapHEADToGET && [requestMethod isEqualToString:@"HEAD"]) {
|
||||||
requestMethod = @"GET";
|
requestMethod = @"GET";
|
||||||
_virtualHEAD = YES;
|
self->_virtualHEAD = YES;
|
||||||
}
|
}
|
||||||
NSDictionary* requestHeaders = CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(_requestMessage)); // Header names are case-insensitive but CFHTTPMessageCopyAllHeaderFields() will standardize the common ones
|
NSDictionary* requestHeaders = CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(self->_requestMessage)); // Header names are case-insensitive but CFHTTPMessageCopyAllHeaderFields() will standardize the common ones
|
||||||
NSURL* requestURL = CFBridgingRelease(CFHTTPMessageCopyRequestURL(_requestMessage));
|
NSURL* requestURL = CFBridgingRelease(CFHTTPMessageCopyRequestURL(self->_requestMessage));
|
||||||
if (requestURL) {
|
if (requestURL) {
|
||||||
requestURL = [self rewriteRequestURL:requestURL withMethod:requestMethod headers:requestHeaders];
|
requestURL = [self rewriteRequestURL:requestURL withMethod:requestMethod headers:requestHeaders];
|
||||||
GWS_DCHECK(requestURL);
|
GWS_DCHECK(requestURL);
|
||||||
@@ -307,55 +298,53 @@ NS_ASSUME_NONNULL_END
|
|||||||
NSString* queryString = requestURL ? CFBridgingRelease(CFURLCopyQueryString((CFURLRef)requestURL, NULL)) : nil; // Don't use -[NSURL query] to make sure query is not unescaped;
|
NSString* queryString = requestURL ? CFBridgingRelease(CFURLCopyQueryString((CFURLRef)requestURL, NULL)) : nil; // Don't use -[NSURL query] to make sure query is not unescaped;
|
||||||
NSDictionary* requestQuery = queryString ? GCDWebServerParseURLEncodedForm(queryString) : @{};
|
NSDictionary* requestQuery = queryString ? GCDWebServerParseURLEncodedForm(queryString) : @{};
|
||||||
if (requestMethod && requestURL && requestHeaders && requestPath && requestQuery) {
|
if (requestMethod && requestURL && requestHeaders && requestPath && requestQuery) {
|
||||||
for (_handler in _server.handlers) {
|
for (self->_handler in self->_server.handlers) {
|
||||||
_request = _handler.matchBlock(requestMethod, requestURL, requestHeaders, requestPath, requestQuery);
|
self->_request = self->_handler.matchBlock(requestMethod, requestURL, requestHeaders, requestPath, requestQuery);
|
||||||
if (_request) {
|
if (self->_request) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_request) {
|
if (self->_request) {
|
||||||
_request.localAddressData = self.localAddressData;
|
self->_request.localAddressData = self.localAddressData;
|
||||||
_request.remoteAddressData = self.remoteAddressData;
|
self->_request.remoteAddressData = self.remoteAddressData;
|
||||||
if ([_request hasBody]) {
|
if ([self->_request hasBody]) {
|
||||||
[_request prepareForWriting];
|
[self->_request prepareForWriting];
|
||||||
if (_request.usesChunkedTransferEncoding || (extraData.length <= _request.contentLength)) {
|
if (self->_request.usesChunkedTransferEncoding || (extraData.length <= self->_request.contentLength)) {
|
||||||
NSString* expectHeader = [requestHeaders objectForKey:@"Expect"];
|
NSString* expectHeader = [requestHeaders objectForKey:@"Expect"];
|
||||||
if (expectHeader) {
|
if (expectHeader) {
|
||||||
if ([expectHeader caseInsensitiveCompare:@"100-continue"] == NSOrderedSame) { // TODO: Actually validate request before continuing
|
if ([expectHeader caseInsensitiveCompare:@"100-continue"] == NSOrderedSame) { // TODO: Actually validate request before continuing
|
||||||
[self writeData:_continueData
|
[self writeData:_continueData
|
||||||
withCompletionBlock:^(BOOL success) {
|
withCompletionBlock:^(BOOL success) {
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
if (_request.usesChunkedTransferEncoding) {
|
if (self->_request.usesChunkedTransferEncoding) {
|
||||||
[self _readChunkedBodyWithInitialData:extraData];
|
[self _readChunkedBodyWithInitialData:extraData];
|
||||||
} else {
|
} else {
|
||||||
[self _readBodyWithLength:_request.contentLength initialData:extraData];
|
[self _readBodyWithLength:self->_request.contentLength initialData:extraData];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}];
|
}];
|
||||||
} else {
|
} else {
|
||||||
GWS_LOG_ERROR(@"Unsupported 'Expect' / 'Content-Length' header combination on socket %i", _socket);
|
GWS_LOG_ERROR(@"Unsupported 'Expect' / 'Content-Length' header combination on socket %i", self->_socket);
|
||||||
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_ExpectationFailed];
|
[self abortRequest:self->_request withStatusCode:kGCDWebServerHTTPStatusCode_ExpectationFailed];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_request.usesChunkedTransferEncoding) {
|
if (self->_request.usesChunkedTransferEncoding) {
|
||||||
[self _readChunkedBodyWithInitialData:extraData];
|
[self _readChunkedBodyWithInitialData:extraData];
|
||||||
} else {
|
} else {
|
||||||
[self _readBodyWithLength:_request.contentLength initialData:extraData];
|
[self _readBodyWithLength:self->_request.contentLength initialData:extraData];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GWS_LOG_ERROR(@"Unexpected 'Content-Length' header value on socket %i", _socket);
|
GWS_LOG_ERROR(@"Unexpected 'Content-Length' header value on socket %i", self->_socket);
|
||||||
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_BadRequest];
|
[self abortRequest:self->_request withStatusCode:kGCDWebServerHTTPStatusCode_BadRequest];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
[self _startProcessingRequest];
|
[self _startProcessingRequest];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_request = [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:requestPath query:requestQuery];
|
self->_request = [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:requestPath query:requestQuery];
|
||||||
GWS_DCHECK(_request);
|
GWS_DCHECK(self->_request);
|
||||||
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_NotImplemented];
|
[self abortRequest:self->_request withStatusCode:kGCDWebServerHTTPStatusCode_NotImplemented];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
[self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
[self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
||||||
@@ -364,7 +353,6 @@ NS_ASSUME_NONNULL_END
|
|||||||
} else {
|
} else {
|
||||||
[self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
[self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
||||||
}
|
}
|
||||||
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,7 +414,6 @@ NS_ASSUME_NONNULL_END
|
|||||||
|
|
||||||
- (void)readData:(NSMutableData*)data withLength:(NSUInteger)length completionBlock:(ReadDataCompletionBlock)block {
|
- (void)readData:(NSMutableData*)data withLength:(NSUInteger)length completionBlock:(ReadDataCompletionBlock)block {
|
||||||
dispatch_read(_socket, length, dispatch_get_global_queue(_server.dispatchQueuePriority, 0), ^(dispatch_data_t buffer, int error) {
|
dispatch_read(_socket, length, dispatch_get_global_queue(_server.dispatchQueuePriority, 0), ^(dispatch_data_t buffer, int error) {
|
||||||
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
size_t size = dispatch_data_get_size(buffer);
|
size_t size = dispatch_data_get_size(buffer);
|
||||||
@@ -439,19 +426,18 @@ NS_ASSUME_NONNULL_END
|
|||||||
[self didReadBytes:((char*)data.bytes + originalLength) length:(data.length - originalLength)];
|
[self didReadBytes:((char*)data.bytes + originalLength) length:(data.length - originalLength)];
|
||||||
block(YES);
|
block(YES);
|
||||||
} else {
|
} else {
|
||||||
if (_totalBytesRead > 0) {
|
if (self->_totalBytesRead > 0) {
|
||||||
GWS_LOG_ERROR(@"No more data available on socket %i", _socket);
|
GWS_LOG_ERROR(@"No more data available on socket %i", self->_socket);
|
||||||
} else {
|
} else {
|
||||||
GWS_LOG_WARNING(@"No data received from socket %i", _socket);
|
GWS_LOG_WARNING(@"No data received from socket %i", self->_socket);
|
||||||
}
|
}
|
||||||
block(NO);
|
block(NO);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GWS_LOG_ERROR(@"Error while reading from socket %i: %s (%i)", _socket, strerror(error), error);
|
GWS_LOG_ERROR(@"Error while reading from socket %i: %s (%i)", self->_socket, strerror(error), error);
|
||||||
block(NO);
|
block(NO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,29 +446,27 @@ NS_ASSUME_NONNULL_END
|
|||||||
[self readData:headersData
|
[self readData:headersData
|
||||||
withLength:NSUIntegerMax
|
withLength:NSUIntegerMax
|
||||||
completionBlock:^(BOOL success) {
|
completionBlock:^(BOOL success) {
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
NSRange range = [headersData rangeOfData:_CRLFCRLFData options:0 range:NSMakeRange(0, headersData.length)];
|
NSRange range = [headersData rangeOfData:_CRLFCRLFData options:0 range:NSMakeRange(0, headersData.length)];
|
||||||
if (range.location == NSNotFound) {
|
if (range.location == NSNotFound) {
|
||||||
[self readHeaders:headersData withCompletionBlock:block];
|
[self readHeaders:headersData withCompletionBlock:block];
|
||||||
} else {
|
} else {
|
||||||
NSUInteger length = range.location + range.length;
|
NSUInteger length = range.location + range.length;
|
||||||
if (CFHTTPMessageAppendBytes(_requestMessage, headersData.bytes, length)) {
|
if (CFHTTPMessageAppendBytes(self->_requestMessage, headersData.bytes, length)) {
|
||||||
if (CFHTTPMessageIsHeaderComplete(_requestMessage)) {
|
if (CFHTTPMessageIsHeaderComplete(self->_requestMessage)) {
|
||||||
block([headersData subdataWithRange:NSMakeRange(length, headersData.length - length)]);
|
block([headersData subdataWithRange:NSMakeRange(length, headersData.length - length)]);
|
||||||
} else {
|
} else {
|
||||||
GWS_LOG_ERROR(@"Failed parsing request headers from socket %i", _socket);
|
GWS_LOG_ERROR(@"Failed parsing request headers from socket %i", self->_socket);
|
||||||
block(nil);
|
block(nil);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GWS_LOG_ERROR(@"Failed appending request headers data from socket %i", _socket);
|
GWS_LOG_ERROR(@"Failed appending request headers data from socket %i", self->_socket);
|
||||||
block(nil);
|
block(nil);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
block(nil);
|
block(nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,11 +476,10 @@ NS_ASSUME_NONNULL_END
|
|||||||
[self readData:bodyData
|
[self readData:bodyData
|
||||||
withLength:length
|
withLength:length
|
||||||
completionBlock:^(BOOL success) {
|
completionBlock:^(BOOL success) {
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
if (bodyData.length <= length) {
|
if (bodyData.length <= length) {
|
||||||
NSError* error = nil;
|
NSError* error = nil;
|
||||||
if ([_request performWriteData:bodyData error:&error]) {
|
if ([self->_request performWriteData:bodyData error:&error]) {
|
||||||
NSUInteger remainingLength = length - bodyData.length;
|
NSUInteger remainingLength = length - bodyData.length;
|
||||||
if (remainingLength) {
|
if (remainingLength) {
|
||||||
[self readBodyWithRemainingLength:remainingLength completionBlock:block];
|
[self readBodyWithRemainingLength:remainingLength completionBlock:block];
|
||||||
@@ -504,18 +487,17 @@ NS_ASSUME_NONNULL_END
|
|||||||
block(YES);
|
block(YES);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error);
|
GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", self->_socket, error);
|
||||||
block(NO);
|
block(NO);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GWS_LOG_ERROR(@"Unexpected extra content reading request body on socket %i", _socket);
|
GWS_LOG_ERROR(@"Unexpected extra content reading request body on socket %i", self->_socket);
|
||||||
block(NO);
|
block(NO);
|
||||||
GWS_DNOT_REACHED();
|
GWS_DNOT_REACHED();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
block(NO);
|
block(NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -575,13 +557,11 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
|||||||
[self readData:chunkData
|
[self readData:chunkData
|
||||||
withLength:NSUIntegerMax
|
withLength:NSUIntegerMax
|
||||||
completionBlock:^(BOOL success) {
|
completionBlock:^(BOOL success) {
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
[self readNextBodyChunk:chunkData completionBlock:block];
|
[self readNextBodyChunk:chunkData completionBlock:block];
|
||||||
} else {
|
} else {
|
||||||
block(NO);
|
block(NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -594,18 +574,16 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
|||||||
[data self]; // Keeps ARC from releasing data too early
|
[data self]; // Keeps ARC from releasing data too early
|
||||||
});
|
});
|
||||||
dispatch_write(_socket, buffer, dispatch_get_global_queue(_server.dispatchQueuePriority, 0), ^(dispatch_data_t remainingData, int error) {
|
dispatch_write(_socket, buffer, dispatch_get_global_queue(_server.dispatchQueuePriority, 0), ^(dispatch_data_t remainingData, int error) {
|
||||||
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
GWS_DCHECK(remainingData == NULL);
|
GWS_DCHECK(remainingData == NULL);
|
||||||
[self didWriteBytes:data.bytes length:data.length];
|
[self didWriteBytes:data.bytes length:data.length];
|
||||||
block(YES);
|
block(YES);
|
||||||
} else {
|
} else {
|
||||||
GWS_LOG_ERROR(@"Error while writing to socket %i: %s (%i)", _socket, strerror(error), error);
|
GWS_LOG_ERROR(@"Error while writing to socket %i: %s (%i)", self->_socket, strerror(error), error);
|
||||||
block(NO);
|
block(NO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
#if !OS_OBJECT_USE_OBJC_RETAIN_RELEASE
|
#if !OS_OBJECT_USE_OBJC_RETAIN_RELEASE
|
||||||
dispatch_release(buffer);
|
dispatch_release(buffer);
|
||||||
@@ -622,15 +600,14 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
|||||||
- (void)writeBodyWithCompletionBlock:(WriteBodyCompletionBlock)block {
|
- (void)writeBodyWithCompletionBlock:(WriteBodyCompletionBlock)block {
|
||||||
GWS_DCHECK([_response hasBody]);
|
GWS_DCHECK([_response hasBody]);
|
||||||
[_response performReadDataWithCompletion:^(NSData* data, NSError* error) {
|
[_response performReadDataWithCompletion:^(NSData* data, NSError* error) {
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
if (data.length) {
|
if (data.length) {
|
||||||
if (_response.usesChunkedTransferEncoding) {
|
if (self->_response.usesChunkedTransferEncoding) {
|
||||||
const char* hexString = [[NSString stringWithFormat:@"%lx", (unsigned long)data.length] UTF8String];
|
const char* hexString = [[NSString stringWithFormat:@"%lx", (unsigned long)data.length] UTF8String];
|
||||||
size_t hexLength = strlen(hexString);
|
size_t hexLength = strlen(hexString);
|
||||||
NSData* chunk = [NSMutableData dataWithLength:(hexLength + 2 + data.length + 2)];
|
NSData* chunk = [NSMutableData dataWithLength:(hexLength + 2 + data.length + 2)];
|
||||||
if (chunk == nil) {
|
if (chunk == nil) {
|
||||||
GWS_LOG_ERROR(@"Failed allocating memory for response body chunk for socket %i: %@", _socket, error);
|
GWS_LOG_ERROR(@"Failed allocating memory for response body chunk for socket %i: %@", self->_socket, error);
|
||||||
block(NO);
|
block(NO);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -647,31 +624,26 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
|||||||
}
|
}
|
||||||
[self writeData:data
|
[self writeData:data
|
||||||
withCompletionBlock:^(BOOL success) {
|
withCompletionBlock:^(BOOL success) {
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
[self writeBodyWithCompletionBlock:block];
|
[self writeBodyWithCompletionBlock:block];
|
||||||
} else {
|
} else {
|
||||||
block(NO);
|
block(NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
}];
|
}];
|
||||||
} else {
|
} else {
|
||||||
if (_response.usesChunkedTransferEncoding) {
|
if (self->_response.usesChunkedTransferEncoding) {
|
||||||
[self writeData:_lastChunkData
|
[self writeData:_lastChunkData
|
||||||
withCompletionBlock:^(BOOL success) {
|
withCompletionBlock:^(BOOL success) {
|
||||||
|
|
||||||
block(success);
|
block(success);
|
||||||
|
|
||||||
}];
|
}];
|
||||||
} else {
|
} else {
|
||||||
block(YES);
|
block(YES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GWS_LOG_ERROR(@"Failed reading response body for socket %i: %@", _socket, error);
|
GWS_LOG_ERROR(@"Failed reading response body for socket %i: %@", self->_socket, error);
|
||||||
block(NO);
|
block(NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -726,7 +698,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSURL*)rewriteRequestURL:(NSURL*)url withMethod:(NSString*)method headers:(NSDictionary*)headers {
|
- (NSURL*)rewriteRequestURL:(NSURL*)url withMethod:(NSString*)method headers:(NSDictionary<NSString*, NSString*>*)headers {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -822,8 +794,8 @@ static inline BOOL _CompareResources(NSString* responseETag, NSString* requestET
|
|||||||
GWS_DCHECK(_responseMessage == NULL);
|
GWS_DCHECK(_responseMessage == NULL);
|
||||||
GWS_DCHECK((statusCode >= 400) && (statusCode < 600));
|
GWS_DCHECK((statusCode >= 400) && (statusCode < 600));
|
||||||
[self _initializeResponseHeadersWithStatusCode:statusCode];
|
[self _initializeResponseHeadersWithStatusCode:statusCode];
|
||||||
[self writeHeadersWithCompletionBlock:^(BOOL success) {
|
[self writeHeadersWithCompletionBlock:^(BOOL success){
|
||||||
; // Nothing more to do
|
// Nothing more to do
|
||||||
}];
|
}];
|
||||||
GWS_LOG_DEBUG(@"Connection aborted with status code %i on socket %i", (int)statusCode, _socket);
|
GWS_LOG_DEBUG(@"Connection aborted with status code %i on socket %i", (int)statusCode, _socket);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -41,7 +41,7 @@ extern "C" {
|
|||||||
* types. Keys of the dictionary must be lowercased file extensions without
|
* types. Keys of the dictionary must be lowercased file extensions without
|
||||||
* the period, and the values must be the corresponding MIME types.
|
* the period, and the values must be the corresponding MIME types.
|
||||||
*/
|
*/
|
||||||
NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension, NSDictionary* _Nullable overrides);
|
NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension, NSDictionary<NSString*, NSString*>* _Nullable overrides);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add percent-escapes to a string so it can be used in a URL.
|
* Add percent-escapes to a string so it can be used in a URL.
|
||||||
@@ -60,7 +60,7 @@ NSString* _Nullable GCDWebServerUnescapeURLString(NSString* string);
|
|||||||
* "application/x-www-form-urlencoded" form.
|
* "application/x-www-form-urlencoded" form.
|
||||||
* http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
|
* http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
|
||||||
*/
|
*/
|
||||||
NSDictionary* GCDWebServerParseURLEncodedForm(NSString* form);
|
NSDictionary<NSString*, NSString*>* GCDWebServerParseURLEncodedForm(NSString* form);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* On OS X, returns the IPv4 or IPv6 address as a string of the primary
|
* On OS X, returns the IPv4 or IPv6 address as a string of the primary
|
||||||
@@ -102,6 +102,11 @@ NSString* GCDWebServerFormatISO8601(NSDate* date);
|
|||||||
*/
|
*/
|
||||||
NSDate* _Nullable GCDWebServerParseISO8601(NSString* string);
|
NSDate* _Nullable GCDWebServerParseISO8601(NSString* string);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes "//", "/./" and "/../" components from path as well as any trailing slash.
|
||||||
|
*/
|
||||||
|
NSString* GCDWebServerNormalizePath(NSString* path);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
#import <TargetConditionals.h>
|
#import <TargetConditionals.h>
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
#import <MobileCoreServices/MobileCoreServices.h>
|
#import <CoreServices/CoreServices.h>
|
||||||
#else
|
#else
|
||||||
#import <SystemConfiguration/SystemConfiguration.h>
|
#import <SystemConfiguration/SystemConfiguration.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -166,8 +166,8 @@ NSString* GCDWebServerDescribeData(NSData* data, NSString* type) {
|
|||||||
return [NSString stringWithFormat:@"<%lu bytes>", (unsigned long)data.length];
|
return [NSString stringWithFormat:@"<%lu bytes>", (unsigned long)data.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension, NSDictionary* overrides) {
|
NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension, NSDictionary<NSString*, NSString*>* overrides) {
|
||||||
NSDictionary* builtInOverrides = @{ @"css" : @"text/css" };
|
NSDictionary* builtInOverrides = @{@"css" : @"text/css"};
|
||||||
NSString* mimeType = nil;
|
NSString* mimeType = nil;
|
||||||
extension = [extension lowercaseString];
|
extension = [extension lowercaseString];
|
||||||
if (extension.length) {
|
if (extension.length) {
|
||||||
@@ -200,7 +200,7 @@ NSString* GCDWebServerUnescapeURLString(NSString* string) {
|
|||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
|
|
||||||
NSDictionary* GCDWebServerParseURLEncodedForm(NSString* form) {
|
NSDictionary<NSString*, NSString*>* GCDWebServerParseURLEncodedForm(NSString* form) {
|
||||||
NSMutableDictionary* parameters = [NSMutableDictionary dictionary];
|
NSMutableDictionary* parameters = [NSMutableDictionary dictionary];
|
||||||
NSScanner* scanner = [[NSScanner alloc] initWithString:form];
|
NSScanner* scanner = [[NSScanner alloc] initWithString:form];
|
||||||
[scanner setCharactersToBeSkipped:nil];
|
[scanner setCharactersToBeSkipped:nil];
|
||||||
@@ -302,7 +302,10 @@ NSString* GCDWebServerComputeMD5Digest(NSString* format, ...) {
|
|||||||
const char* string = [[[NSString alloc] initWithFormat:format arguments:arguments] UTF8String];
|
const char* string = [[[NSString alloc] initWithFormat:format arguments:arguments] UTF8String];
|
||||||
va_end(arguments);
|
va_end(arguments);
|
||||||
unsigned char md5[CC_MD5_DIGEST_LENGTH];
|
unsigned char md5[CC_MD5_DIGEST_LENGTH];
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
CC_MD5(string, (CC_LONG)strlen(string), md5);
|
CC_MD5(string, (CC_LONG)strlen(string), md5);
|
||||||
|
#pragma clang diagnostic pop
|
||||||
char buffer[2 * CC_MD5_DIGEST_LENGTH + 1];
|
char buffer[2 * CC_MD5_DIGEST_LENGTH + 1];
|
||||||
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; ++i) {
|
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; ++i) {
|
||||||
unsigned char byte = md5[i];
|
unsigned char byte = md5[i];
|
||||||
@@ -314,3 +317,18 @@ NSString* GCDWebServerComputeMD5Digest(NSString* format, ...) {
|
|||||||
buffer[2 * CC_MD5_DIGEST_LENGTH] = 0;
|
buffer[2 * CC_MD5_DIGEST_LENGTH] = 0;
|
||||||
return (NSString*)[NSString stringWithUTF8String:buffer];
|
return (NSString*)[NSString stringWithUTF8String:buffer];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NSString* GCDWebServerNormalizePath(NSString* path) {
|
||||||
|
NSMutableArray* components = [[NSMutableArray alloc] init];
|
||||||
|
for (NSString* component in [path componentsSeparatedByString:@"/"]) {
|
||||||
|
if ([component isEqualToString:@".."]) {
|
||||||
|
[components removeLastObject];
|
||||||
|
} else if (component.length && ![component isEqualToString:@"."]) {
|
||||||
|
[components addObject:component];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (path.length && ([path characterAtIndex:0] == '/')) {
|
||||||
|
return [@"/" stringByAppendingString:[components componentsJoinedByString:@"/"]]; // Preserve initial slash
|
||||||
|
}
|
||||||
|
return [components componentsJoinedByString:@"/"];
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -170,7 +170,7 @@ static inline NSError* GCDWebServerMakePosixError(int code) {
|
|||||||
return [NSError errorWithDomain:NSPOSIXErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey : (NSString*)[NSString stringWithUTF8String:strerror(code)]}];
|
return [NSError errorWithDomain:NSPOSIXErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey : (NSString*)[NSString stringWithUTF8String:strerror(code)]}];
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void GCDWebServerInitializeFunctions();
|
extern void GCDWebServerInitializeFunctions(void);
|
||||||
extern NSString* _Nullable GCDWebServerNormalizeHeaderValue(NSString* _Nullable value);
|
extern NSString* _Nullable GCDWebServerNormalizeHeaderValue(NSString* _Nullable value);
|
||||||
extern NSString* _Nullable GCDWebServerTruncateHeaderValue(NSString* _Nullable value);
|
extern NSString* _Nullable GCDWebServerTruncateHeaderValue(NSString* _Nullable value);
|
||||||
extern NSString* _Nullable GCDWebServerExtractHeaderValueParameter(NSString* _Nullable value, NSString* attribute);
|
extern NSString* _Nullable GCDWebServerExtractHeaderValueParameter(NSString* _Nullable value, NSString* attribute);
|
||||||
@@ -185,11 +185,11 @@ extern NSString* GCDWebServerStringFromSockAddr(const struct sockaddr* addr, BOO
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
@interface GCDWebServer ()
|
@interface GCDWebServer ()
|
||||||
@property(nonatomic, readonly) NSMutableArray* handlers;
|
@property(nonatomic, readonly) NSMutableArray<GCDWebServerHandler*>* handlers;
|
||||||
@property(nonatomic, readonly, nullable) NSString* serverName;
|
@property(nonatomic, readonly, nullable) NSString* serverName;
|
||||||
@property(nonatomic, readonly, nullable) NSString* authenticationRealm;
|
@property(nonatomic, readonly, nullable) NSString* authenticationRealm;
|
||||||
@property(nonatomic, readonly, nullable) NSMutableDictionary* authenticationBasicAccounts;
|
@property(nonatomic, readonly, nullable) NSMutableDictionary<NSString*, NSString*>* authenticationBasicAccounts;
|
||||||
@property(nonatomic, readonly, nullable) NSMutableDictionary* authenticationDigestAccounts;
|
@property(nonatomic, readonly, nullable) NSMutableDictionary<NSString*, NSString*>* authenticationDigestAccounts;
|
||||||
@property(nonatomic, readonly) BOOL shouldAutomaticallyMapHEADToGET;
|
@property(nonatomic, readonly) BOOL shouldAutomaticallyMapHEADToGET;
|
||||||
@property(nonatomic, readonly) dispatch_queue_priority_t dispatchQueuePriority;
|
@property(nonatomic, readonly) dispatch_queue_priority_t dispatchQueuePriority;
|
||||||
- (void)willStartConnection:(GCDWebServerConnection*)connection;
|
- (void)willStartConnection:(GCDWebServerConnection*)connection;
|
||||||
@@ -213,7 +213,7 @@ extern NSString* GCDWebServerStringFromSockAddr(const struct sockaddr* addr, BOO
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
@interface GCDWebServerResponse ()
|
@interface GCDWebServerResponse ()
|
||||||
@property(nonatomic, readonly) NSDictionary* additionalHeaders;
|
@property(nonatomic, readonly) NSDictionary<NSString*, NSString*>* additionalHeaders;
|
||||||
@property(nonatomic, readonly) BOOL usesChunkedTransferEncoding;
|
@property(nonatomic, readonly) BOOL usesChunkedTransferEncoding;
|
||||||
- (void)prepareForReading;
|
- (void)prepareForReading;
|
||||||
- (BOOL)performOpen:(NSError**)error;
|
- (BOOL)performOpen:(NSError**)error;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -102,7 +102,7 @@ extern NSString* const GCDWebServerRequestAttribute_RegexCaptures;
|
|||||||
/**
|
/**
|
||||||
* Returns the HTTP headers for the request.
|
* Returns the HTTP headers for the request.
|
||||||
*/
|
*/
|
||||||
@property(nonatomic, readonly) NSDictionary* headers;
|
@property(nonatomic, readonly) NSDictionary<NSString*, NSString*>* headers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the path component of the URL for the request.
|
* Returns the path component of the URL for the request.
|
||||||
@@ -114,7 +114,7 @@ extern NSString* const GCDWebServerRequestAttribute_RegexCaptures;
|
|||||||
*
|
*
|
||||||
* @warning This property will be nil if there is no query in the URL.
|
* @warning This property will be nil if there is no query in the URL.
|
||||||
*/
|
*/
|
||||||
@property(nonatomic, readonly, nullable) NSDictionary* query;
|
@property(nonatomic, readonly, nullable) NSDictionary<NSString*, NSString*>* query;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the content type for the body of the request parsed from the
|
* Returns the content type for the body of the request parsed from the
|
||||||
@@ -186,7 +186,7 @@ extern NSString* const GCDWebServerRequestAttribute_RegexCaptures;
|
|||||||
/**
|
/**
|
||||||
* This method is the designated initializer for the class.
|
* This method is the designated initializer for the class.
|
||||||
*/
|
*/
|
||||||
- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(nullable NSDictionary*)query;
|
- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary<NSString*, NSString*>*)headers path:(NSString*)path query:(nullable NSDictionary<NSString*, NSString*>*)query;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method that checks if the contentType property is defined.
|
* Convenience method that checks if the contentType property is defined.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -136,12 +136,12 @@ NSString* const GCDWebServerRequestAttribute_RegexCaptures = @"GCDWebServerReque
|
|||||||
|
|
||||||
@implementation GCDWebServerRequest {
|
@implementation GCDWebServerRequest {
|
||||||
BOOL _opened;
|
BOOL _opened;
|
||||||
NSMutableArray* _decoders;
|
NSMutableArray<GCDWebServerBodyDecoder*>* _decoders;
|
||||||
id<GCDWebServerBodyWriter> __unsafe_unretained _writer;
|
id<GCDWebServerBodyWriter> __unsafe_unretained _writer;
|
||||||
NSMutableDictionary* _attributes;
|
NSMutableDictionary<NSString*, id>* _attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query {
|
- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary<NSString*, NSString*>*)headers path:(NSString*)path query:(NSDictionary<NSString*, NSString*>*)query {
|
||||||
if ((self = [super init])) {
|
if ((self = [super init])) {
|
||||||
_method = [method copy];
|
_method = [method copy];
|
||||||
_URL = url;
|
_URL = url;
|
||||||
@@ -188,7 +188,7 @@ NSString* const GCDWebServerRequestAttribute_RegexCaptures = @"GCDWebServerReque
|
|||||||
if ([rangeHeader hasPrefix:@"bytes="]) {
|
if ([rangeHeader hasPrefix:@"bytes="]) {
|
||||||
NSArray* components = [[rangeHeader substringFromIndex:6] componentsSeparatedByString:@","];
|
NSArray* components = [[rangeHeader substringFromIndex:6] componentsSeparatedByString:@","];
|
||||||
if (components.count == 1) {
|
if (components.count == 1) {
|
||||||
components = [[components firstObject] componentsSeparatedByString:@"-"];
|
components = [(NSString*)[components firstObject] componentsSeparatedByString:@"-"];
|
||||||
if (components.count == 2) {
|
if (components.count == 2) {
|
||||||
NSString* startString = [components objectAtIndex:0];
|
NSString* startString = [components objectAtIndex:0];
|
||||||
NSInteger startValue = [startString integerValue];
|
NSInteger startValue = [startString integerValue];
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -33,7 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
* The GCDWebServerBodyReaderCompletionBlock is passed by GCDWebServer to the
|
* The GCDWebServerBodyReaderCompletionBlock is passed by GCDWebServer to the
|
||||||
* GCDWebServerBodyReader object when reading data from it asynchronously.
|
* GCDWebServerBodyReader object when reading data from it asynchronously.
|
||||||
*/
|
*/
|
||||||
typedef void (^GCDWebServerBodyReaderCompletionBlock)(NSData* data, NSError* _Nullable error);
|
typedef void (^GCDWebServerBodyReaderCompletionBlock)(NSData* _Nullable data, NSError* _Nullable error);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This protocol is used by the GCDWebServerConnection to communicate with
|
* This protocol is used by the GCDWebServerConnection to communicate with
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -150,12 +150,12 @@
|
|||||||
|
|
||||||
@implementation GCDWebServerResponse {
|
@implementation GCDWebServerResponse {
|
||||||
BOOL _opened;
|
BOOL _opened;
|
||||||
NSMutableArray* _encoders;
|
NSMutableArray<GCDWebServerBodyEncoder*>* _encoders;
|
||||||
id<GCDWebServerBodyReader> __unsafe_unretained _reader;
|
id<GCDWebServerBodyReader> __unsafe_unretained _reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)response {
|
+ (instancetype)response {
|
||||||
return [[[self class] alloc] init];
|
return [(GCDWebServerResponse*)[[self class] alloc] init];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)init {
|
- (instancetype)init {
|
||||||
@@ -259,11 +259,11 @@
|
|||||||
@implementation GCDWebServerResponse (Extensions)
|
@implementation GCDWebServerResponse (Extensions)
|
||||||
|
|
||||||
+ (instancetype)responseWithStatusCode:(NSInteger)statusCode {
|
+ (instancetype)responseWithStatusCode:(NSInteger)statusCode {
|
||||||
return [[self alloc] initWithStatusCode:statusCode];
|
return [(GCDWebServerResponse*)[self alloc] initWithStatusCode:statusCode];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)responseWithRedirect:(NSURL*)location permanent:(BOOL)permanent {
|
+ (instancetype)responseWithRedirect:(NSURL*)location permanent:(BOOL)permanent {
|
||||||
return [[self alloc] initWithRedirect:location permanent:permanent];
|
return [(GCDWebServerResponse*)[self alloc] initWithRedirect:location permanent:permanent];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithStatusCode:(NSInteger)statusCode {
|
- (instancetype)initWithStatusCode:(NSInteger)statusCode {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
}
|
}
|
||||||
if (_data == nil) {
|
if (_data == nil) {
|
||||||
if (error) {
|
if (error) {
|
||||||
*error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Failed allocating memory" }];
|
*error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Failed allocating memory"}];
|
||||||
}
|
}
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
int _file;
|
int _file;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query {
|
- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary<NSString*, NSString*>*)headers path:(NSString*)path query:(NSDictionary<NSString*, NSString*>*)query {
|
||||||
if ((self = [super initWithMethod:method url:url headers:headers path:path query:query])) {
|
if ((self = [super initWithMethod:method url:url headers:headers path:path query:query])) {
|
||||||
_temporaryPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];
|
_temporaryPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -107,13 +107,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
* Returns the argument parts from the multipart encoded form as
|
* Returns the argument parts from the multipart encoded form as
|
||||||
* name / GCDWebServerMultiPartArgument pairs.
|
* name / GCDWebServerMultiPartArgument pairs.
|
||||||
*/
|
*/
|
||||||
@property(nonatomic, readonly) NSArray* arguments;
|
@property(nonatomic, readonly) NSArray<GCDWebServerMultiPartArgument*>* arguments;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the files parts from the multipart encoded form as
|
* Returns the files parts from the multipart encoded form as
|
||||||
* name / GCDWebServerMultiPartFile pairs.
|
* name / GCDWebServerMultiPartFile pairs.
|
||||||
*/
|
*/
|
||||||
@property(nonatomic, readonly) NSArray* files;
|
@property(nonatomic, readonly) NSArray<GCDWebServerMultiPartFile*>* files;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the MIME type for multipart encoded forms
|
* Returns the MIME type for multipart encoded forms
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -106,8 +106,8 @@ static NSData* _dashNewlineData = nil;
|
|||||||
NSString* _defaultcontrolName;
|
NSString* _defaultcontrolName;
|
||||||
ParserState _state;
|
ParserState _state;
|
||||||
NSMutableData* _data;
|
NSMutableData* _data;
|
||||||
NSMutableArray* _arguments;
|
NSMutableArray<GCDWebServerMultiPartArgument*>* _arguments;
|
||||||
NSMutableArray* _files;
|
NSMutableArray<GCDWebServerMultiPartFile*>* _files;
|
||||||
|
|
||||||
NSString* _controlName;
|
NSString* _controlName;
|
||||||
NSString* _fileName;
|
NSString* _fileName;
|
||||||
@@ -132,7 +132,7 @@ static NSData* _dashNewlineData = nil;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithBoundary:(NSString* _Nonnull)boundary defaultControlName:(NSString* _Nullable)name arguments:(NSMutableArray* _Nonnull)arguments files:(NSMutableArray* _Nonnull)files {
|
- (instancetype)initWithBoundary:(NSString* _Nonnull)boundary defaultControlName:(NSString* _Nullable)name arguments:(NSMutableArray<GCDWebServerMultiPartArgument*>* _Nonnull)arguments files:(NSMutableArray<GCDWebServerMultiPartFile*>* _Nonnull)files {
|
||||||
NSData* data = boundary.length ? [[NSString stringWithFormat:@"--%@", boundary] dataUsingEncoding:NSASCIIStringEncoding] : nil;
|
NSData* data = boundary.length ? [[NSString stringWithFormat:@"--%@", boundary] dataUsingEncoding:NSASCIIStringEncoding] : nil;
|
||||||
if (data == nil) {
|
if (data == nil) {
|
||||||
GWS_DNOT_REACHED();
|
GWS_DNOT_REACHED();
|
||||||
@@ -312,8 +312,8 @@ static NSData* _dashNewlineData = nil;
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
@interface GCDWebServerMultiPartFormRequest ()
|
@interface GCDWebServerMultiPartFormRequest ()
|
||||||
@property(nonatomic) NSMutableArray* arguments;
|
@property(nonatomic) NSMutableArray<GCDWebServerMultiPartArgument*>* arguments;
|
||||||
@property(nonatomic) NSMutableArray* files;
|
@property(nonatomic) NSMutableArray<GCDWebServerMultiPartFile*>* files;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GCDWebServerMultiPartFormRequest {
|
@implementation GCDWebServerMultiPartFormRequest {
|
||||||
@@ -324,7 +324,7 @@ static NSData* _dashNewlineData = nil;
|
|||||||
return @"multipart/form-data";
|
return @"multipart/form-data";
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query {
|
- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary<NSString*, NSString*>*)headers path:(NSString*)path query:(NSDictionary<NSString*, NSString*>*)query {
|
||||||
if ((self = [super initWithMethod:method url:url headers:headers path:path query:query])) {
|
if ((self = [super initWithMethod:method url:url headers:headers path:path query:query])) {
|
||||||
_arguments = [[NSMutableArray alloc] init];
|
_arguments = [[NSMutableArray alloc] init];
|
||||||
_files = [[NSMutableArray alloc] init];
|
_files = [[NSMutableArray alloc] init];
|
||||||
@@ -337,7 +337,7 @@ static NSData* _dashNewlineData = nil;
|
|||||||
_parser = [[GCDWebServerMIMEStreamParser alloc] initWithBoundary:boundary defaultControlName:nil arguments:_arguments files:_files];
|
_parser = [[GCDWebServerMIMEStreamParser alloc] initWithBoundary:boundary defaultControlName:nil arguments:_arguments files:_files];
|
||||||
if (_parser == nil) {
|
if (_parser == nil) {
|
||||||
if (error) {
|
if (error) {
|
||||||
*error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Failed starting to parse multipart form data" }];
|
*error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Failed starting to parse multipart form data"}];
|
||||||
}
|
}
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
@@ -347,7 +347,7 @@ static NSData* _dashNewlineData = nil;
|
|||||||
- (BOOL)writeData:(NSData*)data error:(NSError**)error {
|
- (BOOL)writeData:(NSData*)data error:(NSError**)error {
|
||||||
if (![_parser appendBytes:data.bytes length:data.length]) {
|
if (![_parser appendBytes:data.bytes length:data.length]) {
|
||||||
if (error) {
|
if (error) {
|
||||||
*error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Failed continuing to parse multipart form data" }];
|
*error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Failed continuing to parse multipart form data"}];
|
||||||
}
|
}
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
@@ -359,7 +359,7 @@ static NSData* _dashNewlineData = nil;
|
|||||||
_parser = nil;
|
_parser = nil;
|
||||||
if (!atEnd) {
|
if (!atEnd) {
|
||||||
if (error) {
|
if (error) {
|
||||||
*error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Failed finishing to parse multipart form data" }];
|
*error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Failed finishing to parse multipart form data"}];
|
||||||
}
|
}
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -42,7 +42,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
* The text encoding used to interpret the data is extracted from the
|
* The text encoding used to interpret the data is extracted from the
|
||||||
* "Content-Type" header or defaults to UTF-8.
|
* "Content-Type" header or defaults to UTF-8.
|
||||||
*/
|
*/
|
||||||
@property(nonatomic, readonly) NSDictionary* arguments;
|
@property(nonatomic, readonly) NSDictionary<NSString*, NSString*>* arguments;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the MIME type for URL encoded forms
|
* Returns the MIME type for URL encoded forms
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -64,7 +64,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
* Creates a data response from an HTML template encoded using UTF-8.
|
* Creates a data response from an HTML template encoded using UTF-8.
|
||||||
* See -initWithHTMLTemplate:variables: for details.
|
* See -initWithHTMLTemplate:variables: for details.
|
||||||
*/
|
*/
|
||||||
+ (nullable instancetype)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables;
|
+ (nullable instancetype)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary<NSString*, NSString*>*)variables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a data response from a serialized JSON object and the default
|
* Creates a data response from a serialized JSON object and the default
|
||||||
@@ -94,7 +94,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
* All occurences of "%variable%" within the HTML template are replaced with
|
* All occurences of "%variable%" within the HTML template are replaced with
|
||||||
* their corresponding values.
|
* their corresponding values.
|
||||||
*/
|
*/
|
||||||
- (nullable instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables;
|
- (nullable instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary<NSString*, NSString*>*)variables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a data response from a serialized JSON object and the default
|
* Initializes a data response from a serialized JSON object and the default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
@dynamic contentType;
|
@dynamic contentType;
|
||||||
|
|
||||||
+ (instancetype)responseWithData:(NSData*)data contentType:(NSString*)type {
|
+ (instancetype)responseWithData:(NSData*)data contentType:(NSString*)type {
|
||||||
return [[[self class] alloc] initWithData:data contentType:type];
|
return [(GCDWebServerDataResponse*)[[self class] alloc] initWithData:data contentType:type];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithData:(NSData*)data contentType:(NSString*)type {
|
- (instancetype)initWithData:(NSData*)data contentType:(NSString*)type {
|
||||||
@@ -75,23 +75,23 @@
|
|||||||
@implementation GCDWebServerDataResponse (Extensions)
|
@implementation GCDWebServerDataResponse (Extensions)
|
||||||
|
|
||||||
+ (instancetype)responseWithText:(NSString*)text {
|
+ (instancetype)responseWithText:(NSString*)text {
|
||||||
return [[self alloc] initWithText:text];
|
return [(GCDWebServerDataResponse*)[self alloc] initWithText:text];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)responseWithHTML:(NSString*)html {
|
+ (instancetype)responseWithHTML:(NSString*)html {
|
||||||
return [[self alloc] initWithHTML:html];
|
return [(GCDWebServerDataResponse*)[self alloc] initWithHTML:html];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables {
|
+ (instancetype)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary<NSString*, NSString*>*)variables {
|
||||||
return [[self alloc] initWithHTMLTemplate:path variables:variables];
|
return [(GCDWebServerDataResponse*)[self alloc] initWithHTMLTemplate:path variables:variables];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)responseWithJSONObject:(id)object {
|
+ (instancetype)responseWithJSONObject:(id)object {
|
||||||
return [[self alloc] initWithJSONObject:object];
|
return [(GCDWebServerDataResponse*)[self alloc] initWithJSONObject:object];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)responseWithJSONObject:(id)object contentType:(NSString*)type {
|
+ (instancetype)responseWithJSONObject:(id)object contentType:(NSString*)type {
|
||||||
return [[self alloc] initWithJSONObject:object contentType:type];
|
return [(GCDWebServerDataResponse*)[self alloc] initWithJSONObject:object contentType:type];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithText:(NSString*)text {
|
- (instancetype)initWithText:(NSString*)text {
|
||||||
@@ -112,7 +112,7 @@
|
|||||||
return [self initWithData:data contentType:@"text/html; charset=utf-8"];
|
return [self initWithData:data contentType:@"text/html; charset=utf-8"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables {
|
- (instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary<NSString*, NSString*>*)variables {
|
||||||
NSMutableString* html = [[NSMutableString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
|
NSMutableString* html = [[NSMutableString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
|
||||||
[variables enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSString* value, BOOL* stop) {
|
[variables enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSString* value, BOOL* stop) {
|
||||||
[html replaceOccurrencesOfString:[NSString stringWithFormat:@"%%%@%%", key] withString:value options:0 range:NSMakeRange(0, html.length)];
|
[html replaceOccurrencesOfString:[NSString stringWithFormat:@"%%%@%%", key] withString:value options:0 range:NSMakeRange(0, html.length)];
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
|
GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
|
||||||
va_list arguments;
|
va_list arguments;
|
||||||
va_start(arguments, format);
|
va_start(arguments, format);
|
||||||
GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments];
|
GCDWebServerErrorResponse* response = [(GCDWebServerErrorResponse*)[self alloc] initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments];
|
||||||
va_end(arguments);
|
va_end(arguments);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
|
GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
|
||||||
va_list arguments;
|
va_list arguments;
|
||||||
va_start(arguments, format);
|
va_start(arguments, format);
|
||||||
GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments];
|
GCDWebServerErrorResponse* response = [(GCDWebServerErrorResponse*)[self alloc] initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments];
|
||||||
va_end(arguments);
|
va_end(arguments);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
|
GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
|
||||||
va_list arguments;
|
va_list arguments;
|
||||||
va_start(arguments, format);
|
va_start(arguments, format);
|
||||||
GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments];
|
GCDWebServerErrorResponse* response = [(GCDWebServerErrorResponse*)[self alloc] initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments];
|
||||||
va_end(arguments);
|
va_end(arguments);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
|
GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
|
||||||
va_list arguments;
|
va_list arguments;
|
||||||
va_start(arguments, format);
|
va_start(arguments, format);
|
||||||
GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments];
|
GCDWebServerErrorResponse* response = [(GCDWebServerErrorResponse*)[self alloc] initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments];
|
||||||
va_end(arguments);
|
va_end(arguments);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -101,7 +101,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
* file extensions without the period, and the values must be the corresponding
|
* file extensions without the period, and the values must be the corresponding
|
||||||
* MIME types.
|
* MIME types.
|
||||||
*/
|
*/
|
||||||
- (nullable instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment mimeTypeOverrides:(nullable NSDictionary*)overrides;
|
- (nullable instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment mimeTypeOverrides:(nullable NSDictionary<NSString*, NSString*>*)overrides;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -45,19 +45,19 @@
|
|||||||
@dynamic contentType, lastModifiedDate, eTag;
|
@dynamic contentType, lastModifiedDate, eTag;
|
||||||
|
|
||||||
+ (instancetype)responseWithFile:(NSString*)path {
|
+ (instancetype)responseWithFile:(NSString*)path {
|
||||||
return [[[self class] alloc] initWithFile:path];
|
return [(GCDWebServerFileResponse*)[[self class] alloc] initWithFile:path];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)responseWithFile:(NSString*)path isAttachment:(BOOL)attachment {
|
+ (instancetype)responseWithFile:(NSString*)path isAttachment:(BOOL)attachment {
|
||||||
return [[[self class] alloc] initWithFile:path isAttachment:attachment];
|
return [(GCDWebServerFileResponse*)[[self class] alloc] initWithFile:path isAttachment:attachment];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range {
|
+ (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range {
|
||||||
return [[[self class] alloc] initWithFile:path byteRange:range];
|
return [(GCDWebServerFileResponse*)[[self class] alloc] initWithFile:path byteRange:range];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment {
|
+ (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment {
|
||||||
return [[[self class] alloc] initWithFile:path byteRange:range isAttachment:attachment mimeTypeOverrides:nil];
|
return [(GCDWebServerFileResponse*)[[self class] alloc] initWithFile:path byteRange:range isAttachment:attachment mimeTypeOverrides:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithFile:(NSString*)path {
|
- (instancetype)initWithFile:(NSString*)path {
|
||||||
@@ -76,7 +76,7 @@ static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) {
|
|||||||
return [NSDate dateWithTimeIntervalSince1970:((NSTimeInterval)t->tv_sec + (NSTimeInterval)t->tv_nsec / 1000000000.0)];
|
return [NSDate dateWithTimeIntervalSince1970:((NSTimeInterval)t->tv_sec + (NSTimeInterval)t->tv_nsec / 1000000000.0)];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment mimeTypeOverrides:(NSDictionary*)overrides {
|
- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment mimeTypeOverrides:(NSDictionary<NSString*, NSString*>*)overrides {
|
||||||
struct stat info;
|
struct stat info;
|
||||||
if (lstat([path fileSystemRepresentation], &info) || !(info.st_mode & S_IFREG)) {
|
if (lstat([path fileSystemRepresentation], &info) || !(info.st_mode & S_IFREG)) {
|
||||||
GWS_DNOT_REACHED();
|
GWS_DNOT_REACHED();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -38,21 +38,19 @@
|
|||||||
@dynamic contentType;
|
@dynamic contentType;
|
||||||
|
|
||||||
+ (instancetype)responseWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block {
|
+ (instancetype)responseWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block {
|
||||||
return [[[self class] alloc] initWithContentType:type streamBlock:block];
|
return [(GCDWebServerStreamedResponse*)[[self class] alloc] initWithContentType:type streamBlock:block];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)responseWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block {
|
+ (instancetype)responseWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block {
|
||||||
return [[[self class] alloc] initWithContentType:type asyncStreamBlock:block];
|
return [(GCDWebServerStreamedResponse*)[[self class] alloc] initWithContentType:type asyncStreamBlock:block];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block {
|
- (instancetype)initWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block {
|
||||||
return [self initWithContentType:type
|
return [self initWithContentType:type
|
||||||
asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock completionBlock) {
|
asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock completionBlock) {
|
||||||
|
|
||||||
NSError* error = nil;
|
NSError* error = nil;
|
||||||
NSData* data = block(&error);
|
NSData* data = block(&error);
|
||||||
completionBlock(data, error);
|
completionBlock(data, error);
|
||||||
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -93,7 +93,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
*
|
*
|
||||||
* The default value is nil i.e. all file extensions are allowed.
|
* The default value is nil i.e. all file extensions are allowed.
|
||||||
*/
|
*/
|
||||||
@property(nonatomic, copy) NSArray* allowedFileExtensions;
|
@property(nonatomic, copy) NSArray<NSString*>* allowedFileExtensions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets if files and directories whose name start with a period are allowed to
|
* Sets if files and directories whose name start with a period are allowed to
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -37,6 +37,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#import "GCDWebUploader.h"
|
#import "GCDWebUploader.h"
|
||||||
|
#import "GCDWebServerFunctions.h"
|
||||||
|
|
||||||
#import "GCDWebServerDataRequest.h"
|
#import "GCDWebServerDataRequest.h"
|
||||||
#import "GCDWebServerMultiPartFormRequest.h"
|
#import "GCDWebServerMultiPartFormRequest.h"
|
||||||
@@ -73,7 +74,7 @@ NS_ASSUME_NONNULL_END
|
|||||||
if (siteBundle == nil) {
|
if (siteBundle == nil) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
_uploadDirectory = [[path stringByStandardizingPath] copy];
|
_uploadDirectory = [path copy];
|
||||||
GCDWebUploader* __unsafe_unretained server = self;
|
GCDWebUploader* __unsafe_unretained server = self;
|
||||||
|
|
||||||
// Resource files
|
// Resource files
|
||||||
@@ -117,6 +118,9 @@ NS_ASSUME_NONNULL_END
|
|||||||
NSString* footer = server.footer;
|
NSString* footer = server.footer;
|
||||||
if (footer == nil) {
|
if (footer == nil) {
|
||||||
NSString* name = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
|
NSString* name = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
|
||||||
|
if (name == nil) {
|
||||||
|
name = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
|
||||||
|
}
|
||||||
NSString* version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
|
NSString* version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
|
||||||
#if !TARGET_OS_IPHONE
|
#if !TARGET_OS_IPHONE
|
||||||
if (!name && !version) {
|
if (!name && !version) {
|
||||||
@@ -135,7 +139,6 @@ NS_ASSUME_NONNULL_END
|
|||||||
@"epilogue" : epilogue,
|
@"epilogue" : epilogue,
|
||||||
@"footer" : footer
|
@"footer" : footer
|
||||||
}];
|
}];
|
||||||
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
// File listing
|
// File listing
|
||||||
@@ -193,11 +196,6 @@ NS_ASSUME_NONNULL_END
|
|||||||
|
|
||||||
@implementation GCDWebUploader (Methods)
|
@implementation GCDWebUploader (Methods)
|
||||||
|
|
||||||
// Must match implementation in GCDWebDAVServer
|
|
||||||
- (BOOL)_checkSandboxedPath:(NSString*)path {
|
|
||||||
return [[path stringByStandardizingPath] hasPrefix:_uploadDirectory];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)_checkFileExtension:(NSString*)fileName {
|
- (BOOL)_checkFileExtension:(NSString*)fileName {
|
||||||
if (_allowedFileExtensions && ![_allowedFileExtensions containsObject:[[fileName pathExtension] lowercaseString]]) {
|
if (_allowedFileExtensions && ![_allowedFileExtensions containsObject:[[fileName pathExtension] lowercaseString]]) {
|
||||||
return NO;
|
return NO;
|
||||||
@@ -225,9 +223,9 @@ NS_ASSUME_NONNULL_END
|
|||||||
|
|
||||||
- (GCDWebServerResponse*)listDirectory:(GCDWebServerRequest*)request {
|
- (GCDWebServerResponse*)listDirectory:(GCDWebServerRequest*)request {
|
||||||
NSString* relativePath = [[request query] objectForKey:@"path"];
|
NSString* relativePath = [[request query] objectForKey:@"path"];
|
||||||
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
|
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)];
|
||||||
BOOL isDirectory = NO;
|
BOOL isDirectory = NO;
|
||||||
if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
if (!absolutePath || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
||||||
}
|
}
|
||||||
if (!isDirectory) {
|
if (!isDirectory) {
|
||||||
@@ -240,7 +238,7 @@ NS_ASSUME_NONNULL_END
|
|||||||
}
|
}
|
||||||
|
|
||||||
NSError* error = nil;
|
NSError* error = nil;
|
||||||
NSArray* contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:absolutePath error:&error];
|
NSArray* contents = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:absolutePath error:&error] sortedArrayUsingSelector:@selector(localizedStandardCompare:)];
|
||||||
if (contents == nil) {
|
if (contents == nil) {
|
||||||
return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed listing directory \"%@\"", relativePath];
|
return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed listing directory \"%@\"", relativePath];
|
||||||
}
|
}
|
||||||
@@ -269,9 +267,9 @@ NS_ASSUME_NONNULL_END
|
|||||||
|
|
||||||
- (GCDWebServerResponse*)downloadFile:(GCDWebServerRequest*)request {
|
- (GCDWebServerResponse*)downloadFile:(GCDWebServerRequest*)request {
|
||||||
NSString* relativePath = [[request query] objectForKey:@"path"];
|
NSString* relativePath = [[request query] objectForKey:@"path"];
|
||||||
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
|
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)];
|
||||||
BOOL isDirectory = NO;
|
BOOL isDirectory = NO;
|
||||||
if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
||||||
}
|
}
|
||||||
if (isDirectory) {
|
if (isDirectory) {
|
||||||
@@ -300,10 +298,7 @@ NS_ASSUME_NONNULL_END
|
|||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploaded file name \"%@\" is not allowed", file.fileName];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploaded file name \"%@\" is not allowed", file.fileName];
|
||||||
}
|
}
|
||||||
NSString* relativePath = [[request firstArgumentForControlName:@"path"] string];
|
NSString* relativePath = [[request firstArgumentForControlName:@"path"] string];
|
||||||
NSString* absolutePath = [self _uniquePathForPath:[[_uploadDirectory stringByAppendingPathComponent:relativePath] stringByAppendingPathComponent:file.fileName]];
|
NSString* absolutePath = [self _uniquePathForPath:[[_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)] stringByAppendingPathComponent:file.fileName]];
|
||||||
if (![self _checkSandboxedPath:absolutePath]) {
|
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (![self shouldUploadFileAtPath:absolutePath withTemporaryFile:file.temporaryPath]) {
|
if (![self shouldUploadFileAtPath:absolutePath withTemporaryFile:file.temporaryPath]) {
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploading file \"%@\" to \"%@\" is not permitted", file.fileName, relativePath];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploading file \"%@\" to \"%@\" is not permitted", file.fileName, relativePath];
|
||||||
@@ -324,21 +319,23 @@ NS_ASSUME_NONNULL_END
|
|||||||
|
|
||||||
- (GCDWebServerResponse*)moveItem:(GCDWebServerURLEncodedFormRequest*)request {
|
- (GCDWebServerResponse*)moveItem:(GCDWebServerURLEncodedFormRequest*)request {
|
||||||
NSString* oldRelativePath = [request.arguments objectForKey:@"oldPath"];
|
NSString* oldRelativePath = [request.arguments objectForKey:@"oldPath"];
|
||||||
NSString* oldAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:oldRelativePath];
|
NSString* oldAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(oldRelativePath)];
|
||||||
BOOL isDirectory = NO;
|
BOOL isDirectory = NO;
|
||||||
if (![self _checkSandboxedPath:oldAbsolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:oldAbsolutePath isDirectory:&isDirectory]) {
|
if (![[NSFileManager defaultManager] fileExistsAtPath:oldAbsolutePath isDirectory:&isDirectory]) {
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", oldRelativePath];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", oldRelativePath];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString* newRelativePath = [request.arguments objectForKey:@"newPath"];
|
NSString* oldItemName = [oldAbsolutePath lastPathComponent];
|
||||||
NSString* newAbsolutePath = [self _uniquePathForPath:[_uploadDirectory stringByAppendingPathComponent:newRelativePath]];
|
if ((!_allowHiddenItems && [oldItemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:oldItemName])) {
|
||||||
if (![self _checkSandboxedPath:newAbsolutePath]) {
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Moving from item name \"%@\" is not allowed", oldItemName];
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", newRelativePath];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString* itemName = [newAbsolutePath lastPathComponent];
|
NSString* newRelativePath = [request.arguments objectForKey:@"newPath"];
|
||||||
if ((!_allowHiddenItems && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) {
|
NSString* newAbsolutePath = [self _uniquePathForPath:[_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(newRelativePath)]];
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Moving to item name \"%@\" is not allowed", itemName];
|
|
||||||
|
NSString* newItemName = [newAbsolutePath lastPathComponent];
|
||||||
|
if ((!_allowHiddenItems && [newItemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:newItemName])) {
|
||||||
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Moving to item name \"%@\" is not allowed", newItemName];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (![self shouldMoveItemFromPath:oldAbsolutePath toPath:newAbsolutePath]) {
|
if (![self shouldMoveItemFromPath:oldAbsolutePath toPath:newAbsolutePath]) {
|
||||||
@@ -360,9 +357,9 @@ NS_ASSUME_NONNULL_END
|
|||||||
|
|
||||||
- (GCDWebServerResponse*)deleteItem:(GCDWebServerURLEncodedFormRequest*)request {
|
- (GCDWebServerResponse*)deleteItem:(GCDWebServerURLEncodedFormRequest*)request {
|
||||||
NSString* relativePath = [request.arguments objectForKey:@"path"];
|
NSString* relativePath = [request.arguments objectForKey:@"path"];
|
||||||
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
|
NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)];
|
||||||
BOOL isDirectory = NO;
|
BOOL isDirectory = NO;
|
||||||
if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,10 +387,7 @@ NS_ASSUME_NONNULL_END
|
|||||||
|
|
||||||
- (GCDWebServerResponse*)createDirectory:(GCDWebServerURLEncodedFormRequest*)request {
|
- (GCDWebServerResponse*)createDirectory:(GCDWebServerURLEncodedFormRequest*)request {
|
||||||
NSString* relativePath = [request.arguments objectForKey:@"path"];
|
NSString* relativePath = [request.arguments objectForKey:@"path"];
|
||||||
NSString* absolutePath = [self _uniquePathForPath:[_uploadDirectory stringByAppendingPathComponent:relativePath]];
|
NSString* absolutePath = [self _uniquePathForPath:[_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)]];
|
||||||
if (![self _checkSandboxedPath:absolutePath]) {
|
|
||||||
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
|
|
||||||
}
|
|
||||||
|
|
||||||
NSString* directoryName = [absolutePath lastPathComponent];
|
NSString* directoryName = [absolutePath lastPathComponent];
|
||||||
if (!_allowHiddenItems && [directoryName hasPrefix:@"."]) {
|
if (!_allowHiddenItems && [directoryName hasPrefix:@"."]) {
|
||||||
|
|||||||
54
Mac/main.m
54
Mac/main.m
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -178,10 +178,10 @@ int main(int argc, const char* argv[]) {
|
|||||||
recording = YES;
|
recording = YES;
|
||||||
} else if (!strcmp(argv[i], "-root") && (i + 1 < argc)) {
|
} else if (!strcmp(argv[i], "-root") && (i + 1 < argc)) {
|
||||||
++i;
|
++i;
|
||||||
rootDirectory = [[[NSFileManager defaultManager] stringWithFileSystemRepresentation:argv[i] length:strlen(argv[i])] stringByStandardizingPath];
|
rootDirectory = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:argv[i] length:strlen(argv[i])];
|
||||||
} else if (!strcmp(argv[i], "-tests") && (i + 1 < argc)) {
|
} else if (!strcmp(argv[i], "-tests") && (i + 1 < argc)) {
|
||||||
++i;
|
++i;
|
||||||
testDirectory = [[[NSFileManager defaultManager] stringWithFileSystemRepresentation:argv[i] length:strlen(argv[i])] stringByStandardizingPath];
|
testDirectory = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:argv[i] length:strlen(argv[i])];
|
||||||
} else if (!strcmp(argv[i], "-authenticationMethod") && (i + 1 < argc)) {
|
} else if (!strcmp(argv[i], "-authenticationMethod") && (i + 1 < argc)) {
|
||||||
++i;
|
++i;
|
||||||
authenticationMethod = [NSString stringWithUTF8String:argv[i]];
|
authenticationMethod = [NSString stringWithUTF8String:argv[i]];
|
||||||
@@ -206,7 +206,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
switch (mode) {
|
switch (mode) {
|
||||||
// Simply serve contents of home directory
|
// Simply serve contents of home directory
|
||||||
case kMode_WebServer: {
|
case kMode_WebServer: {
|
||||||
fprintf(stdout, "Running in Web Server mode from \"%s\"", [rootDirectory UTF8String]);
|
fprintf(stdout, "Running in Web Server mode from \"%s\"\n", [rootDirectory UTF8String]);
|
||||||
webServer = [[GCDWebServer alloc] init];
|
webServer = [[GCDWebServer alloc] init];
|
||||||
[webServer addGETHandlerForBasePath:@"/" directoryPath:rootDirectory indexFilename:nil cacheAge:0 allowRangeRequests:YES];
|
[webServer addGETHandlerForBasePath:@"/" directoryPath:rootDirectory indexFilename:nil cacheAge:0 allowRangeRequests:YES];
|
||||||
break;
|
break;
|
||||||
@@ -214,27 +214,24 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
// Renders a HTML page
|
// Renders a HTML page
|
||||||
case kMode_HTMLPage: {
|
case kMode_HTMLPage: {
|
||||||
fprintf(stdout, "Running in HTML Page mode");
|
fprintf(stdout, "Running in HTML Page mode\n");
|
||||||
webServer = [[GCDWebServer alloc] init];
|
webServer = [[GCDWebServer alloc] init];
|
||||||
[webServer addDefaultHandlerForMethod:@"GET"
|
[webServer addDefaultHandlerForMethod:@"GET"
|
||||||
requestClass:[GCDWebServerRequest class]
|
requestClass:[GCDWebServerRequest class]
|
||||||
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
||||||
|
|
||||||
return [GCDWebServerDataResponse responseWithHTML:@"<html><body><p>Hello World</p></body></html>"];
|
return [GCDWebServerDataResponse responseWithHTML:@"<html><body><p>Hello World</p></body></html>"];
|
||||||
|
|
||||||
}];
|
}];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements an HTML form
|
// Implements an HTML form
|
||||||
case kMode_HTMLForm: {
|
case kMode_HTMLForm: {
|
||||||
fprintf(stdout, "Running in HTML Form mode");
|
fprintf(stdout, "Running in HTML Form mode\n");
|
||||||
webServer = [[GCDWebServer alloc] init];
|
webServer = [[GCDWebServer alloc] init];
|
||||||
[webServer addHandlerForMethod:@"GET"
|
[webServer addHandlerForMethod:@"GET"
|
||||||
path:@"/"
|
path:@"/"
|
||||||
requestClass:[GCDWebServerRequest class]
|
requestClass:[GCDWebServerRequest class]
|
||||||
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
||||||
|
|
||||||
NSString* html = @" \
|
NSString* html = @" \
|
||||||
<html><body> \
|
<html><body> \
|
||||||
<form name=\"input\" action=\"/\" method=\"post\" enctype=\"application/x-www-form-urlencoded\"> \
|
<form name=\"input\" action=\"/\" method=\"post\" enctype=\"application/x-www-form-urlencoded\"> \
|
||||||
@@ -244,24 +241,21 @@ int main(int argc, const char* argv[]) {
|
|||||||
</body></html> \
|
</body></html> \
|
||||||
";
|
";
|
||||||
return [GCDWebServerDataResponse responseWithHTML:html];
|
return [GCDWebServerDataResponse responseWithHTML:html];
|
||||||
|
|
||||||
}];
|
}];
|
||||||
[webServer addHandlerForMethod:@"POST"
|
[webServer addHandlerForMethod:@"POST"
|
||||||
path:@"/"
|
path:@"/"
|
||||||
requestClass:[GCDWebServerURLEncodedFormRequest class]
|
requestClass:[GCDWebServerURLEncodedFormRequest class]
|
||||||
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
||||||
|
|
||||||
NSString* value = [[(GCDWebServerURLEncodedFormRequest*)request arguments] objectForKey:@"value"];
|
NSString* value = [[(GCDWebServerURLEncodedFormRequest*)request arguments] objectForKey:@"value"];
|
||||||
NSString* html = [NSString stringWithFormat:@"<html><body><p>%@</p></body></html>", value];
|
NSString* html = [NSString stringWithFormat:@"<html><body><p>%@</p></body></html>", value];
|
||||||
return [GCDWebServerDataResponse responseWithHTML:html];
|
return [GCDWebServerDataResponse responseWithHTML:html];
|
||||||
|
|
||||||
}];
|
}];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements HTML file upload
|
// Implements HTML file upload
|
||||||
case kMode_HTMLFileUpload: {
|
case kMode_HTMLFileUpload: {
|
||||||
fprintf(stdout, "Running in HTML File Upload mode");
|
fprintf(stdout, "Running in HTML File Upload mode\n");
|
||||||
webServer = [[GCDWebServer alloc] init];
|
webServer = [[GCDWebServer alloc] init];
|
||||||
NSString* formHTML = @" \
|
NSString* formHTML = @" \
|
||||||
<form name=\"input\" action=\"/\" method=\"post\" enctype=\"multipart/form-data\"> \
|
<form name=\"input\" action=\"/\" method=\"post\" enctype=\"multipart/form-data\"> \
|
||||||
@@ -274,16 +268,13 @@ int main(int argc, const char* argv[]) {
|
|||||||
path:@"/"
|
path:@"/"
|
||||||
requestClass:[GCDWebServerRequest class]
|
requestClass:[GCDWebServerRequest class]
|
||||||
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
||||||
|
|
||||||
NSString* html = [NSString stringWithFormat:@"<html><body>%@</body></html>", formHTML];
|
NSString* html = [NSString stringWithFormat:@"<html><body>%@</body></html>", formHTML];
|
||||||
return [GCDWebServerDataResponse responseWithHTML:html];
|
return [GCDWebServerDataResponse responseWithHTML:html];
|
||||||
|
|
||||||
}];
|
}];
|
||||||
[webServer addHandlerForMethod:@"POST"
|
[webServer addHandlerForMethod:@"POST"
|
||||||
path:@"/"
|
path:@"/"
|
||||||
requestClass:[GCDWebServerMultiPartFormRequest class]
|
requestClass:[GCDWebServerMultiPartFormRequest class]
|
||||||
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
||||||
|
|
||||||
NSMutableString* string = [NSMutableString string];
|
NSMutableString* string = [NSMutableString string];
|
||||||
for (GCDWebServerMultiPartArgument* argument in [(GCDWebServerMultiPartFormRequest*)request arguments]) {
|
for (GCDWebServerMultiPartArgument* argument in [(GCDWebServerMultiPartFormRequest*)request arguments]) {
|
||||||
[string appendFormat:@"%@ = %@<br>", argument.controlName, argument.string];
|
[string appendFormat:@"%@ = %@<br>", argument.controlName, argument.string];
|
||||||
@@ -296,108 +287,87 @@ int main(int argc, const char* argv[]) {
|
|||||||
};
|
};
|
||||||
NSString* html = [NSString stringWithFormat:@"<html><body><p>%@</p><hr>%@</body></html>", string, formHTML];
|
NSString* html = [NSString stringWithFormat:@"<html><body><p>%@</p><hr>%@</body></html>", string, formHTML];
|
||||||
return [GCDWebServerDataResponse responseWithHTML:html];
|
return [GCDWebServerDataResponse responseWithHTML:html];
|
||||||
|
|
||||||
}];
|
}];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serve home directory through WebDAV
|
// Serve home directory through WebDAV
|
||||||
case kMode_WebDAV: {
|
case kMode_WebDAV: {
|
||||||
fprintf(stdout, "Running in WebDAV mode from \"%s\"", [rootDirectory UTF8String]);
|
fprintf(stdout, "Running in WebDAV mode from \"%s\"\n", [rootDirectory UTF8String]);
|
||||||
webServer = [[GCDWebDAVServer alloc] initWithUploadDirectory:rootDirectory];
|
webServer = [[GCDWebDAVServer alloc] initWithUploadDirectory:rootDirectory];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serve home directory through web uploader
|
// Serve home directory through web uploader
|
||||||
case kMode_WebUploader: {
|
case kMode_WebUploader: {
|
||||||
fprintf(stdout, "Running in Web Uploader mode from \"%s\"", [rootDirectory UTF8String]);
|
fprintf(stdout, "Running in Web Uploader mode from \"%s\"\n", [rootDirectory UTF8String]);
|
||||||
webServer = [[GCDWebUploader alloc] initWithUploadDirectory:rootDirectory];
|
webServer = [[GCDWebUploader alloc] initWithUploadDirectory:rootDirectory];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test streaming responses
|
// Test streaming responses
|
||||||
case kMode_StreamingResponse: {
|
case kMode_StreamingResponse: {
|
||||||
fprintf(stdout, "Running in Streaming Response mode");
|
fprintf(stdout, "Running in Streaming Response mode\n");
|
||||||
webServer = [[GCDWebServer alloc] init];
|
webServer = [[GCDWebServer alloc] init];
|
||||||
[webServer addHandlerForMethod:@"GET"
|
[webServer addHandlerForMethod:@"GET"
|
||||||
path:@"/sync"
|
path:@"/sync"
|
||||||
requestClass:[GCDWebServerRequest class]
|
requestClass:[GCDWebServerRequest class]
|
||||||
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
||||||
|
|
||||||
__block int countDown = 10;
|
__block int countDown = 10;
|
||||||
return [GCDWebServerStreamedResponse responseWithContentType:@"text/plain"
|
return [GCDWebServerStreamedResponse responseWithContentType:@"text/plain"
|
||||||
streamBlock:^NSData*(NSError** error) {
|
streamBlock:^NSData*(NSError** error) {
|
||||||
|
|
||||||
usleep(100 * 1000);
|
usleep(100 * 1000);
|
||||||
if (countDown) {
|
if (countDown) {
|
||||||
return [[NSString stringWithFormat:@"%i\n", countDown--] dataUsingEncoding:NSUTF8StringEncoding];
|
return [[NSString stringWithFormat:@"%i\n", countDown--] dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
} else {
|
} else {
|
||||||
return [NSData data];
|
return [NSData data];
|
||||||
}
|
}
|
||||||
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
}];
|
}];
|
||||||
[webServer addHandlerForMethod:@"GET"
|
[webServer addHandlerForMethod:@"GET"
|
||||||
path:@"/async"
|
path:@"/async"
|
||||||
requestClass:[GCDWebServerRequest class]
|
requestClass:[GCDWebServerRequest class]
|
||||||
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
|
||||||
|
|
||||||
__block int countDown = 10;
|
__block int countDown = 10;
|
||||||
return [GCDWebServerStreamedResponse responseWithContentType:@"text/plain"
|
return [GCDWebServerStreamedResponse responseWithContentType:@"text/plain"
|
||||||
asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock completionBlock) {
|
asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock completionBlock) {
|
||||||
|
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
NSData* data = countDown ? [[NSString stringWithFormat:@"%i\n", countDown--] dataUsingEncoding:NSUTF8StringEncoding] : [NSData data];
|
NSData* data = countDown ? [[NSString stringWithFormat:@"%i\n", countDown--] dataUsingEncoding:NSUTF8StringEncoding] : [NSData data];
|
||||||
completionBlock(data, nil);
|
completionBlock(data, nil);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
}];
|
}];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test async responses
|
// Test async responses
|
||||||
case kMode_AsyncResponse: {
|
case kMode_AsyncResponse: {
|
||||||
fprintf(stdout, "Running in Async Response mode");
|
fprintf(stdout, "Running in Async Response mode\n");
|
||||||
webServer = [[GCDWebServer alloc] init];
|
webServer = [[GCDWebServer alloc] init];
|
||||||
[webServer addHandlerForMethod:@"GET"
|
[webServer addHandlerForMethod:@"GET"
|
||||||
path:@"/async"
|
path:@"/async"
|
||||||
requestClass:[GCDWebServerRequest class]
|
requestClass:[GCDWebServerRequest class]
|
||||||
asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) {
|
asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) {
|
||||||
|
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||||
GCDWebServerDataResponse* response = [GCDWebServerDataResponse responseWithData:(NSData*)[@"Hello World!" dataUsingEncoding:NSUTF8StringEncoding] contentType:@"text/plain"];
|
GCDWebServerDataResponse* response = [GCDWebServerDataResponse responseWithData:(NSData*)[@"Hello World!" dataUsingEncoding:NSUTF8StringEncoding] contentType:@"text/plain"];
|
||||||
completionBlock(response);
|
completionBlock(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
}];
|
}];
|
||||||
[webServer addHandlerForMethod:@"GET"
|
[webServer addHandlerForMethod:@"GET"
|
||||||
path:@"/async2"
|
path:@"/async2"
|
||||||
requestClass:[GCDWebServerRequest class]
|
requestClass:[GCDWebServerRequest class]
|
||||||
asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock handlerCompletionBlock) {
|
asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock handlerCompletionBlock) {
|
||||||
|
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||||
|
|
||||||
__block int countDown = 10;
|
__block int countDown = 10;
|
||||||
GCDWebServerStreamedResponse* response = [GCDWebServerStreamedResponse responseWithContentType:@"text/plain"
|
GCDWebServerStreamedResponse* response = [GCDWebServerStreamedResponse responseWithContentType:@"text/plain"
|
||||||
asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock readerCompletionBlock) {
|
asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock readerCompletionBlock) {
|
||||||
|
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
NSData* data = countDown ? [[NSString stringWithFormat:@"%i\n", countDown--] dataUsingEncoding:NSUTF8StringEncoding] : [NSData data];
|
NSData* data = countDown ? [[NSString stringWithFormat:@"%i\n", countDown--] dataUsingEncoding:NSUTF8StringEncoding] : [NSData data];
|
||||||
readerCompletionBlock(data, nil);
|
readerCompletionBlock(data, nil);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}];
|
}];
|
||||||
handlerCompletionBlock(response);
|
handlerCompletionBlock(response);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}];
|
}];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -410,7 +380,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
webServer.delegate = delegate;
|
webServer.delegate = delegate;
|
||||||
#endif
|
#endif
|
||||||
fprintf(stdout, "<RUNNING TESTS FROM \"%s\">\n\n", [testDirectory UTF8String]);
|
fprintf(stdout, "<RUNNING TESTS FROM \"%s\">\n\n", [testDirectory UTF8String]);
|
||||||
result = (int)[webServer runTestsWithOptions:@{ GCDWebServerOption_Port : @8080 } inDirectory:testDirectory];
|
result = (int)[webServer runTestsWithOptions:@{GCDWebServerOption_Port : @8080} inDirectory:testDirectory];
|
||||||
} else {
|
} else {
|
||||||
webServer.delegate = delegate;
|
webServer.delegate = delegate;
|
||||||
if (recording) {
|
if (recording) {
|
||||||
|
|||||||
37
README.md
37
README.md
@@ -2,11 +2,11 @@ Overview
|
|||||||
========
|
========
|
||||||
|
|
||||||
[](https://travis-ci.org/swisspol/GCDWebServer)
|
[](https://travis-ci.org/swisspol/GCDWebServer)
|
||||||
[](http://cocoadocs.org/docsets/GCDWebServer)
|
[](https://cocoapods.org/pods/GCDWebServer)
|
||||||
[](https://github.com/swisspol/GCDWebServer)
|
[](https://github.com/swisspol/GCDWebServer)
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
|
|
||||||
GCDWebServer is a modern and lightweight GCD based HTTP 1.1 server designed to be embedded in OS X & iOS apps. It was written from scratch with the following goals in mind:
|
GCDWebServer is a modern and lightweight GCD based HTTP 1.1 server designed to be embedded in iOS, macOS & tvOS apps. It was written from scratch with the following goals in mind:
|
||||||
* Elegant and easy to use architecture with only 4 core classes: server, connection, request and response (see "Understanding GCDWebServer's Architecture" below)
|
* Elegant and easy to use architecture with only 4 core classes: server, connection, request and response (see "Understanding GCDWebServer's Architecture" below)
|
||||||
* Well designed API with fully documented headers for easy integration and customization
|
* Well designed API with fully documented headers for easy integration and customization
|
||||||
* Entirely built with an event-driven design using [Grand Central Dispatch](http://en.wikipedia.org/wiki/Grand_Central_Dispatch) for best performance and concurrency
|
* Entirely built with an event-driven design using [Grand Central Dispatch](http://en.wikipedia.org/wiki/Grand_Central_Dispatch) for best performance and concurrency
|
||||||
@@ -28,23 +28,22 @@ Extra built-in features:
|
|||||||
|
|
||||||
Included extensions:
|
Included extensions:
|
||||||
* [GCDWebUploader](GCDWebUploader/GCDWebUploader.h): subclass of ```GCDWebServer``` that implements an interface for uploading and downloading files using a web browser
|
* [GCDWebUploader](GCDWebUploader/GCDWebUploader.h): subclass of ```GCDWebServer``` that implements an interface for uploading and downloading files using a web browser
|
||||||
* [GCDWebDAVServer](GCDWebDAVServer/GCDWebDAVServer.h): subclass of ```GCDWebServer``` that implements a class 1 [WebDAV](https://en.wikipedia.org/wiki/WebDAV) server (with partial class 2 support for OS X Finder)
|
* [GCDWebDAVServer](GCDWebDAVServer/GCDWebDAVServer.h): subclass of ```GCDWebServer``` that implements a class 1 [WebDAV](https://en.wikipedia.org/wiki/WebDAV) server (with partial class 2 support for macOS Finder)
|
||||||
|
|
||||||
What's not supported (but not really required from an embedded HTTP server):
|
What's not supported (but not really required from an embedded HTTP server):
|
||||||
* Keep-alive connections
|
* Keep-alive connections
|
||||||
* HTTPS
|
* HTTPS
|
||||||
|
|
||||||
Requirements:
|
Requirements:
|
||||||
* OS X 10.7 or later (x86_64)
|
* macOS 10.7 or later (x86_64)
|
||||||
* iOS 8.0 or later (armv7, armv7s or arm64)
|
* iOS 8.0 or later (armv7, armv7s or arm64)
|
||||||
* ARC memory management only (if you need MRC support use GCDWebServer 3.1 and earlier)
|
* tvOS 9.0 or later (arm64)
|
||||||
|
* ARC memory management only (if you need MRC support use GCDWebServer 3.1 or earlier)
|
||||||
|
|
||||||
Getting Started
|
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.
|
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. Finally link to `libz` (via Target > Build Phases > Link Binary With Libraries) and add `$(SDKROOT)/usr/include/libxml2` to your header search paths (via Target > Build Settings > HEADER_SEARCH_PATHS).
|
||||||
|
|
||||||
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:
|
Alternatively, you can install GCDWebServer using [CocoaPods](http://cocoapods.org/) by simply adding this line to your Podfile:
|
||||||
```
|
```
|
||||||
@@ -82,7 +81,7 @@ These code snippets show how to implement a custom HTTP server that runs on port
|
|||||||
|
|
||||||
**IMPORTANT:** If not using CocoaPods, be sure to add the `libz` shared system library to the Xcode target for your app.
|
**IMPORTANT:** If not using CocoaPods, be sure to add the `libz` shared system library to the Xcode target for your app.
|
||||||
|
|
||||||
**OS X version (command line tool):**
|
**macOS version (command line tool):**
|
||||||
```objectivec
|
```objectivec
|
||||||
#import "GCDWebServer.h"
|
#import "GCDWebServer.h"
|
||||||
#import "GCDWebServerDataResponse.h"
|
#import "GCDWebServerDataResponse.h"
|
||||||
@@ -148,7 +147,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
@end
|
@end
|
||||||
```
|
```
|
||||||
|
|
||||||
**OS X Swift version (command line tool):**
|
**macOS Swift version (command line tool):**
|
||||||
|
|
||||||
***webServer.swift***
|
***webServer.swift***
|
||||||
```swift
|
```swift
|
||||||
@@ -159,12 +158,12 @@ func initWebServer() {
|
|||||||
|
|
||||||
let webServer = GCDWebServer()
|
let webServer = GCDWebServer()
|
||||||
|
|
||||||
webServer.addDefaultHandlerForMethod("GET", requestClass: GCDWebServerRequest.self, processBlock: {request in
|
webServer.addDefaultHandler(forMethod: "GET", request: GCDWebServerRequest.self, processBlock: {request in
|
||||||
return GCDWebServerDataResponse(HTML:"<html><body><p>Hello World</p></body></html>")
|
return GCDWebServerDataResponse(html:"<html><body><p>Hello World</p></body></html>")
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
})
|
webServer.start(withPort: 8080, bonjourName: "GCD Web Server")
|
||||||
|
|
||||||
webServer.runWithPort(8080, bonjourName: "GCD Web Server")
|
|
||||||
|
|
||||||
print("Visit \(webServer.serverURL) in your web browser")
|
print("Visit \(webServer.serverURL) in your web browser")
|
||||||
}
|
}
|
||||||
@@ -209,7 +208,7 @@ WebDAV Server in iOS Apps
|
|||||||
|
|
||||||
GCDWebDAVServer is a subclass of ```GCDWebServer``` that provides a class 1 compliant [WebDAV](https://en.wikipedia.org/wiki/WebDAV) server. This lets users upload, download, delete files and create directories from a directory inside your iOS app's sandbox using any WebDAV client like [Transmit](https://panic.com/transmit/) (Mac), [ForkLift](http://binarynights.com/forklift/) (Mac) or [CyberDuck](http://cyberduck.io/) (Mac / Windows).
|
GCDWebDAVServer is a subclass of ```GCDWebServer``` that provides a class 1 compliant [WebDAV](https://en.wikipedia.org/wiki/WebDAV) server. This lets users upload, download, delete files and create directories from a directory inside your iOS app's sandbox using any WebDAV client like [Transmit](https://panic.com/transmit/) (Mac), [ForkLift](http://binarynights.com/forklift/) (Mac) or [CyberDuck](http://cyberduck.io/) (Mac / Windows).
|
||||||
|
|
||||||
GCDWebDAVServer should also work with the [OS X Finder](http://support.apple.com/kb/PH13859) as it is partially class 2 compliant (but only when the client is the OS X WebDAV implementation).
|
GCDWebDAVServer should also work with the [macOS Finder](http://support.apple.com/kb/PH13859) as it is partially class 2 compliant (but only when the client is the macOS WebDAV implementation).
|
||||||
|
|
||||||
Simply instantiate and run a ```GCDWebDAVServer``` instance then connect to ```http://{YOUR-IOS-DEVICE-IP-ADDRESS}/``` using a WebDAV client:
|
Simply instantiate and run a ```GCDWebDAVServer``` instance then connect to ```http://{YOUR-IOS-DEVICE-IP-ADDRESS}/``` using a WebDAV client:
|
||||||
|
|
||||||
@@ -239,7 +238,7 @@ Serving a Static Website
|
|||||||
|
|
||||||
GCDWebServer includes a built-in handler that can recursively serve a directory (it also lets you control how the ["Cache-Control"](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9) header should be set):
|
GCDWebServer includes a built-in handler that can recursively serve a directory (it also lets you control how the ["Cache-Control"](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9) header should be set):
|
||||||
|
|
||||||
**OS X version (command line tool):**
|
**macOS version (command line tool):**
|
||||||
```objectivec
|
```objectivec
|
||||||
#import "GCDWebServer.h"
|
#import "GCDWebServer.h"
|
||||||
|
|
||||||
@@ -350,8 +349,8 @@ GCDWebServer & Background Mode for iOS Apps
|
|||||||
When doing networking operations in iOS apps, you must handle carefully [what happens when iOS puts the app in the background](https://developer.apple.com/library/ios/technotes/tn2277/_index.html). Typically you must stop any network servers while the app is in the background and restart them when the app comes back to the foreground. This can become quite complex considering servers might have ongoing connections when they need to be stopped.
|
When doing networking operations in iOS apps, you must handle carefully [what happens when iOS puts the app in the background](https://developer.apple.com/library/ios/technotes/tn2277/_index.html). Typically you must stop any network servers while the app is in the background and restart them when the app comes back to the foreground. This can become quite complex considering servers might have ongoing connections when they need to be stopped.
|
||||||
|
|
||||||
Fortunately, GCDWebServer does all of this automatically for you:
|
Fortunately, GCDWebServer does all of this automatically for you:
|
||||||
- GCDWebServer begins a [background task](https://developer.apple.com/library/ios/documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html) whenever the first HTTP connection is opened and ends it only when the last one is closed. This prevents iOS from suspending the app after it goes in the background, which would immediately kill HTTP connections to the client.
|
- GCDWebServer begins a [background task](https://developer.apple.com/library/archive/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html) whenever the first HTTP connection is opened and ends it only when the last one is closed. This prevents iOS from suspending the app after it goes in the background, which would immediately kill HTTP connections to the client.
|
||||||
- While the app is in the background, as long as new HTTP connections keep being initiated, the background task will continue to exist and iOS will not suspend the app (unless under sudden and unexpected memory pressure).
|
- While the app is in the background, as long as new HTTP connections keep being initiated, the background task will continue to exist and iOS will not suspend the app **for up to 10 minutes** (unless under sudden and unexpected memory pressure).
|
||||||
- If the app is still in the background when the last HTTP connection is closed, GCDWebServer will suspend itself and stop accepting new connections as if you had called ```-stop``` (this behavior can be disabled with the ```GCDWebServerOption_AutomaticallySuspendInBackground``` option).
|
- If the app is still in the background when the last HTTP connection is closed, GCDWebServer will suspend itself and stop accepting new connections as if you had called ```-stop``` (this behavior can be disabled with the ```GCDWebServerOption_AutomaticallySuspendInBackground``` option).
|
||||||
- If the app goes in the background while no HTTP connections are opened, GCDWebServer will immediately suspend itself and stop accepting new connections as if you had called ```-stop``` (this behavior can be disabled with the ```GCDWebServerOption_AutomaticallySuspendInBackground``` option).
|
- If the app goes in the background while no HTTP connections are opened, GCDWebServer will immediately suspend itself and stop accepting new connections as if you had called ```-stop``` (this behavior can be disabled with the ```GCDWebServerOption_AutomaticallySuspendInBackground``` option).
|
||||||
- If the app comes back to the foreground and GCDWebServer had been suspended, it will automatically resume itself and start accepting again new HTTP connections as if you had called ```-start```.
|
- If the app comes back to the foreground and GCDWebServer had been suspended, it will automatically resume itself and start accepting again new HTTP connections as if you had called ```-start```.
|
||||||
|
|||||||
33
Run-Tests.sh
33
Run-Tests.sh
@@ -1,4 +1,10 @@
|
|||||||
#!/bin/bash -ex
|
#!/bin/bash -exu -o pipefail
|
||||||
|
|
||||||
|
if [[ -f "/usr/local/bin/xcpretty" ]]; then
|
||||||
|
PRETTYFIER="xcpretty"
|
||||||
|
else
|
||||||
|
PRETTYFIER="tee" # Passthrough stdout
|
||||||
|
fi
|
||||||
|
|
||||||
OSX_SDK="macosx"
|
OSX_SDK="macosx"
|
||||||
IOS_SDK="iphonesimulator"
|
IOS_SDK="iphonesimulator"
|
||||||
@@ -15,23 +21,28 @@ CONFIGURATION="Release"
|
|||||||
|
|
||||||
OSX_TEST_SCHEME="GCDWebServers (Mac)"
|
OSX_TEST_SCHEME="GCDWebServers (Mac)"
|
||||||
|
|
||||||
BUILD_DIR="/tmp/GCDWebServer-Build"
|
BUILD_DIR="`pwd`/build"
|
||||||
PRODUCT="$BUILD_DIR/$CONFIGURATION/GCDWebServer"
|
PRODUCT="$BUILD_DIR/$CONFIGURATION/GCDWebServer"
|
||||||
|
|
||||||
PAYLOAD_ZIP="Tests/Payload.zip"
|
PAYLOAD_ZIP="Tests/Payload.zip"
|
||||||
PAYLOAD_DIR="/tmp/GCDWebServer-Payload"
|
PAYLOAD_DIR="`pwd`/build/Payload"
|
||||||
|
|
||||||
function runTests {
|
function runTests {
|
||||||
|
EXECUTABLE="$1"
|
||||||
|
MODE="$2"
|
||||||
|
TESTS="$3"
|
||||||
|
FILE="${4:-}"
|
||||||
|
|
||||||
rm -rf "$PAYLOAD_DIR"
|
rm -rf "$PAYLOAD_DIR"
|
||||||
ditto -x -k "$PAYLOAD_ZIP" "$PAYLOAD_DIR"
|
ditto -x -k "$PAYLOAD_ZIP" "$PAYLOAD_DIR"
|
||||||
TZ=GMT find "$PAYLOAD_DIR" -type d -exec SetFile -d "1/1/2014 00:00:00" -m "1/1/2014 00:00:00" '{}' \; # ZIP archives do not preserve directories dates
|
TZ=GMT find "$PAYLOAD_DIR" -type d -exec SetFile -d "1/1/2014 00:00:00" -m "1/1/2014 00:00:00" '{}' \; # ZIP archives do not preserve directories dates
|
||||||
if [ "$4" != "" ]; then
|
if [ "$FILE" != "" ]; then
|
||||||
cp -f "$4" "$PAYLOAD_DIR/Payload"
|
cp -f "$4" "$PAYLOAD_DIR/Payload"
|
||||||
pushd "$PAYLOAD_DIR/Payload"
|
pushd "$PAYLOAD_DIR/Payload"
|
||||||
TZ=GMT SetFile -d "1/1/2014 00:00:00" -m "1/1/2014 00:00:00" `basename "$4"`
|
TZ=GMT SetFile -d "1/1/2014 00:00:00" -m "1/1/2014 00:00:00" `basename "$FILE"`
|
||||||
popd
|
popd
|
||||||
fi
|
fi
|
||||||
logLevel=2 $1 -mode "$2" -root "$PAYLOAD_DIR/Payload" -tests "$3"
|
logLevel=2 $EXECUTABLE -mode "$MODE" -root "$PAYLOAD_DIR/Payload" -tests "$TESTS"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Run built-in OS X tests
|
# Run built-in OS X tests
|
||||||
@@ -40,7 +51,7 @@ xcodebuild test -scheme "$OSX_TEST_SCHEME" "SYMROOT=$BUILD_DIR"
|
|||||||
|
|
||||||
# Build for OS X for oldest supported deployment target
|
# Build for OS X for oldest supported deployment target
|
||||||
rm -rf "$BUILD_DIR"
|
rm -rf "$BUILD_DIR"
|
||||||
xcodebuild build -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" "SYMROOT=$BUILD_DIR" "MACOSX_DEPLOYMENT_TARGET=10.7" > /dev/null
|
xcodebuild build -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" "SYMROOT=$BUILD_DIR" "MACOSX_DEPLOYMENT_TARGET=10.7" | $PRETTYFIER
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
runTests $PRODUCT "htmlForm" "Tests/HTMLForm"
|
runTests $PRODUCT "htmlForm" "Tests/HTMLForm"
|
||||||
@@ -54,19 +65,19 @@ runTests $PRODUCT "webServer" "Tests/WebServer-Sample-Movie" "Tests/Sample-Movie
|
|||||||
|
|
||||||
# Build for OS X for current deployment target
|
# Build for OS X for current deployment target
|
||||||
rm -rf "$BUILD_DIR"
|
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
|
xcodebuild build -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" "SYMROOT=$BUILD_DIR" "MACOSX_DEPLOYMENT_TARGET=$OSX_SDK_VERSION" | $PRETTYFIER
|
||||||
|
|
||||||
# Build for iOS for oldest supported deployment target
|
# Build for iOS for oldest supported deployment target
|
||||||
rm -rf "$BUILD_DIR"
|
rm -rf "$BUILD_DIR"
|
||||||
xcodebuild build -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" "SYMROOT=$BUILD_DIR" "IPHONEOS_DEPLOYMENT_TARGET=8.0" > /dev/null
|
xcodebuild build -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" "SYMROOT=$BUILD_DIR" "IPHONEOS_DEPLOYMENT_TARGET=8.0" | $PRETTYFIER
|
||||||
|
|
||||||
# Build for iOS for current deployment target
|
# Build for iOS for current deployment target
|
||||||
rm -rf "$BUILD_DIR"
|
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
|
xcodebuild build -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" "SYMROOT=$BUILD_DIR" "IPHONEOS_DEPLOYMENT_TARGET=$IOS_SDK_VERSION" | $PRETTYFIER
|
||||||
|
|
||||||
# Build for tvOS for current deployment target
|
# Build for tvOS for current deployment target
|
||||||
rm -rf "$BUILD_DIR"
|
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
|
xcodebuild build -sdk "$TVOS_SDK" -target "$TVOS_TARGET" -configuration "$CONFIGURATION" "SYMROOT=$BUILD_DIR" "TVOS_DEPLOYMENT_TARGET=$TVOS_SDK_VERSION" | $PRETTYFIER
|
||||||
|
|
||||||
# Done
|
# Done
|
||||||
echo "\nAll tests completed successfully!"
|
echo "\nAll tests completed successfully!"
|
||||||
|
|||||||
@@ -1,13 +1,22 @@
|
|||||||
#!/bin/sh -ex
|
#!/bin/sh -exuo pipefail
|
||||||
|
|
||||||
# brew install clang-format
|
# brew install clang-format
|
||||||
|
|
||||||
|
SWIFT_FORMAT_VERSION='0.44.5'
|
||||||
|
|
||||||
CLANG_FORMAT_VERSION=`clang-format -version | awk '{ print $3 }'`
|
CLANG_FORMAT_VERSION=`clang-format -version | awk '{ print $3 }'`
|
||||||
if [[ "$CLANG_FORMAT_VERSION" != "5.0.0" ]]; then
|
if [[ "$CLANG_FORMAT_VERSION" != "9.0.0" ]]; then
|
||||||
echo "Unsupported clang-format version"
|
echo "Unsupported clang-format version"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "build/swiftformat" ]]; then
|
||||||
|
mkdir -p "build"
|
||||||
|
curl -sfL -o "build/SwiftFormat.zip" "https://github.com/nicklockwood/SwiftFormat/archive/$SWIFT_FORMAT_VERSION.zip"
|
||||||
|
unzip "build/SwiftFormat.zip" "SwiftFormat-$SWIFT_FORMAT_VERSION/CommandLineTool/swiftformat" -d "build"
|
||||||
|
mv "build/SwiftFormat-$SWIFT_FORMAT_VERSION/CommandLineTool/swiftformat" "build/swiftformat"
|
||||||
|
fi
|
||||||
|
|
||||||
pushd "GCDWebServer/Core"
|
pushd "GCDWebServer/Core"
|
||||||
clang-format -style=file -i *.h *.m
|
clang-format -style=file -i *.h *.m
|
||||||
popd
|
popd
|
||||||
@@ -30,11 +39,7 @@ popd
|
|||||||
pushd "Mac"
|
pushd "Mac"
|
||||||
clang-format -style=file -i *.m
|
clang-format -style=file -i *.m
|
||||||
popd
|
popd
|
||||||
pushd "iOS"
|
|
||||||
clang-format -style=file -i *.h *.m
|
build/swiftformat --indent 2 "iOS" "tvOS"
|
||||||
popd
|
|
||||||
pushd "tvOS"
|
|
||||||
clang-format -style=file -i *.h *.m
|
|
||||||
popd
|
|
||||||
|
|
||||||
echo "OK"
|
echo "OK"
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
* Redistributions of source code must retain the above copyright
|
* Redistributions of source code must retain the above copyright
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
* The name of Pierre-Olivier Latour may not be used to endorse
|
* The name of Pierre-Olivier Latour may not be used to endorse
|
||||||
or promote products derived from this software without specific
|
or promote products derived from this software without specific
|
||||||
prior written permission.
|
prior written permission.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
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
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
@@ -25,7 +25,9 @@
|
|||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
import UIKit
|
||||||
|
|
||||||
@interface ViewController : UIViewController
|
@UIApplicationMain
|
||||||
@end
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
|
var window: UIWindow?
|
||||||
|
}
|
||||||
@@ -84,6 +84,11 @@
|
|||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"size" : "83.5x83.5",
|
"size" : "83.5x83.5",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ios-marketing",
|
||||||
|
"size" : "1024x1024",
|
||||||
|
"scale" : "1x"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<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">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||||
|
<device id="retina4_7" orientation="portrait">
|
||||||
|
<adaptation id="fullscreen"/>
|
||||||
|
</device>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
<!--View Controller-->
|
<!--View Controller-->
|
||||||
@@ -10,14 +14,13 @@
|
|||||||
<objects>
|
<objects>
|
||||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||||
<layoutGuides>
|
<layoutGuides>
|
||||||
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
|
<viewControllerLayoutGuide type="top" id="2rF-0L-CS8"/>
|
||||||
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
|
<viewControllerLayoutGuide type="bottom" id="kyj-O7-82f"/>
|
||||||
</layoutGuides>
|
</layoutGuides>
|
||||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<animations/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
|
||||||
</view>
|
</view>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
|||||||
@@ -1,41 +1,49 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<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">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||||
|
<device id="retina4_7" orientation="portrait">
|
||||||
|
<adaptation id="fullscreen"/>
|
||||||
|
</device>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
<!--View Controller-->
|
<!--View Controller-->
|
||||||
<scene sceneID="tne-QT-ifu">
|
<scene sceneID="tne-QT-ifu">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
|
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="GCDWebServer" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<layoutGuides>
|
<layoutGuides>
|
||||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
<viewControllerLayoutGuide type="top" id="dzM-0Q-5lj"/>
|
||||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
<viewControllerLayoutGuide type="bottom" id="NtI-um-tgL"/>
|
||||||
</layoutGuides>
|
</layoutGuides>
|
||||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<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">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jIj-j0-ef8">
|
||||||
<rect key="frame" x="279" y="290" width="42" height="21"/>
|
<rect key="frame" x="50" y="313" width="275" height="41"/>
|
||||||
|
<string key="text">Label
|
||||||
|
Label</string>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="fqi-2H-Bq5" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="fQm-a5-p9Z"/>
|
<constraint firstAttribute="trailing" secondItem="jIj-j0-ef8" secondAttribute="trailing" constant="50" id="3B8-fm-R8n"/>
|
||||||
<constraint firstItem="fqi-2H-Bq5" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="vB0-cp-Fhd"/>
|
<constraint firstItem="jIj-j0-ef8" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="CPv-7h-UCM"/>
|
||||||
|
<constraint firstItem="jIj-j0-ef8" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" constant="50" id="U0S-p4-n8S"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="label" destination="fqi-2H-Bq5" id="maJ-eb-cCq"/>
|
<outlet property="label" destination="jIj-j0-ef8" id="6Lh-Oa-nCp"/>
|
||||||
</connections>
|
</connections>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
|
<point key="canvasLocation" x="53.600000000000001" y="27.436281859070466"/>
|
||||||
</scene>
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>net.pol-online.${PRODUCT_NAME:rfc1034identifier}</string>
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
77
iOS/ViewController.swift
Normal file
77
iOS/ViewController.swift
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2012-2019, 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 GCDWebServers
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class ViewController: UIViewController {
|
||||||
|
@IBOutlet var label: UILabel?
|
||||||
|
var webServer: GCDWebUploader!
|
||||||
|
|
||||||
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
|
super.viewWillAppear(animated)
|
||||||
|
|
||||||
|
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
|
||||||
|
webServer = GCDWebUploader(uploadDirectory: documentsPath)
|
||||||
|
webServer.delegate = self
|
||||||
|
webServer.allowHiddenItems = true
|
||||||
|
if webServer.start() {
|
||||||
|
label?.text = "GCDWebServer running locally on port \(webServer.port)"
|
||||||
|
} else {
|
||||||
|
label?.text = "GCDWebServer not running!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidDisappear(_ animated: Bool) {
|
||||||
|
super.viewDidDisappear(animated)
|
||||||
|
|
||||||
|
webServer.stop()
|
||||||
|
webServer = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ViewController: GCDWebUploaderDelegate {
|
||||||
|
func webUploader(_: GCDWebUploader, didUploadFileAtPath path: String) {
|
||||||
|
print("[UPLOAD] \(path)")
|
||||||
|
}
|
||||||
|
|
||||||
|
func webUploader(_: GCDWebUploader, didDownloadFileAtPath path: String) {
|
||||||
|
print("[DOWNLOAD] \(path)")
|
||||||
|
}
|
||||||
|
|
||||||
|
func webUploader(_: GCDWebUploader, didMoveItemFromPath fromPath: String, toPath: String) {
|
||||||
|
print("[MOVE] \(fromPath) -> \(toPath)")
|
||||||
|
}
|
||||||
|
|
||||||
|
func webUploader(_: GCDWebUploader, didCreateDirectoryAtPath path: String) {
|
||||||
|
print("[CREATE] \(path)")
|
||||||
|
}
|
||||||
|
|
||||||
|
func webUploader(_: GCDWebUploader, didDeleteItemAtPath path: String) {
|
||||||
|
print("[DELETE] \(path)")
|
||||||
|
}
|
||||||
|
}
|
||||||
34
iOS/main.m
34
iOS/main.m
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
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]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2015, Pierre-Olivier Latour
|
Copyright (c) 2012-2019, Pierre-Olivier Latour
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
* Redistributions of source code must retain the above copyright
|
* Redistributions of source code must retain the above copyright
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
* The name of Pierre-Olivier Latour may not be used to endorse
|
* The name of Pierre-Olivier Latour may not be used to endorse
|
||||||
or promote products derived from this software without specific
|
or promote products derived from this software without specific
|
||||||
prior written permission.
|
prior written permission.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
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
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
@@ -25,7 +25,9 @@
|
|||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
import UIKit
|
||||||
|
|
||||||
@interface ViewController : UIViewController
|
@UIApplicationMain
|
||||||
@end
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
|
var window: UIWindow?
|
||||||
|
}
|
||||||
@@ -1,13 +1,18 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder.AppleTV.Storyboard" version="3.0" toolsVersion="9059" systemVersion="14F1021" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES" initialViewController="BYZ-38-t0r">
|
<document type="com.apple.InterfaceBuilder.AppleTV.Storyboard" version="3.0" toolsVersion="14460.31" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||||
|
<device id="appleTV" orientation="landscape">
|
||||||
|
<adaptation id="light"/>
|
||||||
|
</device>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/>
|
<deployment identifier="tvOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
<!--View Controller-->
|
<!--View Controller-->
|
||||||
<scene sceneID="tne-QT-ifu">
|
<scene sceneID="tne-QT-ifu">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
|
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="GCDWebServer" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<layoutGuides>
|
<layoutGuides>
|
||||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||||
@@ -16,21 +21,22 @@
|
|||||||
<rect key="frame" x="0.0" y="0.0" width="1920" height="1080"/>
|
<rect key="frame" x="0.0" y="0.0" width="1920" height="1080"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<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">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="V4U-rJ-6D1">
|
||||||
<rect key="frame" x="939" y="530" width="42" height="21"/>
|
<rect key="frame" x="100" y="517" width="1720" height="46"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
|
||||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="IHC-Pp-Jrx" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="BOG-hA-JgS"/>
|
<constraint firstItem="V4U-rJ-6D1" firstAttribute="leading" relation="lessThanOrEqual" secondItem="8bC-Xf-vdC" secondAttribute="leading" constant="100" id="Ljd-Mz-k93"/>
|
||||||
<constraint firstItem="IHC-Pp-Jrx" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="a9B-4C-wVj"/>
|
<constraint firstItem="V4U-rJ-6D1" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="ZcT-KC-osO"/>
|
||||||
|
<constraint firstAttribute="trailing" relation="lessThanOrEqual" secondItem="V4U-rJ-6D1" secondAttribute="trailing" constant="100" id="ibV-Ar-n9i"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="label" destination="IHC-Pp-Jrx" id="lnE-JP-l00"/>
|
<outlet property="label" destination="V4U-rJ-6D1" id="wPM-aF-IlM"/>
|
||||||
</connections>
|
</connections>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>net.pol-online.${PRODUCT_NAME:rfc1034identifier}</string>
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
77
tvOS/ViewController.swift
Normal file
77
tvOS/ViewController.swift
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2012-2019, 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 GCDWebServers
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class ViewController: UIViewController {
|
||||||
|
@IBOutlet var label: UILabel?
|
||||||
|
var webServer: GCDWebUploader!
|
||||||
|
|
||||||
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
|
super.viewWillAppear(animated)
|
||||||
|
|
||||||
|
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
|
||||||
|
webServer = GCDWebUploader(uploadDirectory: documentsPath)
|
||||||
|
webServer.delegate = self
|
||||||
|
webServer.allowHiddenItems = true
|
||||||
|
if webServer.start() {
|
||||||
|
label?.text = "GCDWebServer running locally on port \(webServer.port)"
|
||||||
|
} else {
|
||||||
|
label?.text = "GCDWebServer not running!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidDisappear(_ animated: Bool) {
|
||||||
|
super.viewDidDisappear(animated)
|
||||||
|
|
||||||
|
webServer.stop()
|
||||||
|
webServer = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ViewController: GCDWebUploaderDelegate {
|
||||||
|
func webUploader(_: GCDWebUploader, didUploadFileAtPath path: String) {
|
||||||
|
print("[UPLOAD] \(path)")
|
||||||
|
}
|
||||||
|
|
||||||
|
func webUploader(_: GCDWebUploader, didDownloadFileAtPath path: String) {
|
||||||
|
print("[DOWNLOAD] \(path)")
|
||||||
|
}
|
||||||
|
|
||||||
|
func webUploader(_: GCDWebUploader, didMoveItemFromPath fromPath: String, toPath: String) {
|
||||||
|
print("[MOVE] \(fromPath) -> \(toPath)")
|
||||||
|
}
|
||||||
|
|
||||||
|
func webUploader(_: GCDWebUploader, didCreateDirectoryAtPath path: String) {
|
||||||
|
print("[CREATE] \(path)")
|
||||||
|
}
|
||||||
|
|
||||||
|
func webUploader(_: GCDWebUploader, didDeleteItemAtPath path: String) {
|
||||||
|
print("[DELETE] \(path)")
|
||||||
|
}
|
||||||
|
}
|
||||||
34
tvOS/main.m
34
tvOS/main.m
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
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]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user