You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by sh...@apache.org on 2016/07/25 07:57:42 UTC
[56/57] [abbrv] cordova-plugins git commit: Merge commit
'394cfb12f80de35255a506c0dcbf4a21910e849a'
Merge commit '394cfb12f80de35255a506c0dcbf4a21910e849a'
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugins/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugins/commit/36f1a43e
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugins/tree/36f1a43e
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugins/diff/36f1a43e
Branch: refs/heads/master
Commit: 36f1a43e29c3e49c9c2cab7af6fb3909ddfc74df
Parents: 9f15b12 394cfb1
Author: Andreas Kohn <an...@gmail.com>
Authored: Thu Mar 24 12:42:43 2016 +0100
Committer: Andreas Kohn <an...@gmail.com>
Committed: Thu Mar 24 12:42:43 2016 +0100
----------------------------------------------------------------------
local-webserver/src/ios/GCDWebServer/.gitignore | 1 +
.../src/ios/GCDWebServer/.travis.yml | 1 +
.../ios/GCDWebServer/Frameworks/GCDWebServers.h | 52 +
.../src/ios/GCDWebServer/Frameworks/Info.plist | 22 +
.../src/ios/GCDWebServer/Frameworks/Tests.m | 24 +
.../GCDWebDAVServer/GCDWebDAVServer.h | 2 +-
.../GCDWebDAVServer/GCDWebDAVServer.m | 15 +-
.../src/ios/GCDWebServer/GCDWebServer.podspec | 52 +-
.../GCDWebServer.xcodeproj/project.pbxproj | 1135 ++++++++++++++++--
.../xcschemes/GCDWebServers (Mac).xcscheme | 90 ++
.../xcschemes/GCDWebServers (iOS).xcscheme | 89 ++
.../xcschemes/GCDWebServers (tvOS).xcscheme | 89 ++
.../GCDWebServer/Core/GCDWebServer.h | 59 +-
.../GCDWebServer/Core/GCDWebServer.m | 161 ++-
.../GCDWebServer/Core/GCDWebServerConnection.h | 2 +-
.../GCDWebServer/Core/GCDWebServerConnection.m | 20 +-
.../GCDWebServer/Core/GCDWebServerFunctions.h | 2 +-
.../GCDWebServer/Core/GCDWebServerFunctions.m | 16 +-
.../Core/GCDWebServerHTTPStatusCodes.h | 2 +-
.../GCDWebServer/Core/GCDWebServerPrivate.h | 34 +-
.../GCDWebServer/Core/GCDWebServerRequest.h | 26 +-
.../GCDWebServer/Core/GCDWebServerRequest.m | 27 +-
.../GCDWebServer/Core/GCDWebServerResponse.h | 2 +-
.../GCDWebServer/Core/GCDWebServerResponse.m | 12 +-
.../Requests/GCDWebServerDataRequest.h | 2 +-
.../Requests/GCDWebServerDataRequest.m | 6 +-
.../Requests/GCDWebServerFileRequest.h | 2 +-
.../Requests/GCDWebServerFileRequest.m | 14 +-
.../Requests/GCDWebServerMultiPartFormRequest.h | 2 +-
.../Requests/GCDWebServerMultiPartFormRequest.m | 14 +-
.../GCDWebServerURLEncodedFormRequest.h | 2 +-
.../GCDWebServerURLEncodedFormRequest.m | 2 +-
.../Responses/GCDWebServerDataResponse.h | 2 +-
.../Responses/GCDWebServerDataResponse.m | 2 +-
.../Responses/GCDWebServerErrorResponse.h | 2 +-
.../Responses/GCDWebServerErrorResponse.m | 2 +-
.../Responses/GCDWebServerFileResponse.h | 2 +-
.../Responses/GCDWebServerFileResponse.m | 14 +-
.../Responses/GCDWebServerStreamedResponse.h | 15 +-
.../Responses/GCDWebServerStreamedResponse.m | 2 +-
.../GCDWebUploader.bundle/css/index.css | 2 +-
.../GCDWebUploader.bundle/index.html | 4 +-
.../GCDWebUploader.bundle/js/index.js | 13 +-
.../GCDWebUploader/GCDWebUploader.h | 2 +-
.../GCDWebUploader/GCDWebUploader.m | 6 +-
local-webserver/src/ios/GCDWebServer/Mac/main.m | 41 +-
local-webserver/src/ios/GCDWebServer/README.md | 166 +--
.../src/ios/GCDWebServer/Run-Tests.sh | 48 +-
.../Tests/WebDAV-Finder/059-200.response | Bin 107049 -> 0 bytes
.../Tests/WebDAV-Finder/059-206.response | Bin 0 -> 8774 bytes
.../Tests/WebDAV-Finder/062-200.response | Bin 116315 -> 0 bytes
.../Tests/WebDAV-Finder/062-206.response | Bin 0 -> 18041 bytes
.../WebServer-Sample-Movie/001-200.response | Bin 1278221 -> 1278221 bytes
.../WebServer-Sample-Movie/002-206.response | Bin 1278274 -> 1278274 bytes
.../WebServer-Sample-Movie/003-206.response | Bin 9265 -> 9265 bytes
.../WebServer-Sample-Movie/004-206.response | Bin 3391644 -> 3391644 bytes
.../WebServer-Sample-Movie/005-206.response | Bin 1173 -> 1173 bytes
.../src/ios/GCDWebServer/iOS/AppDelegate.h | 4 +-
.../src/ios/GCDWebServer/iOS/AppDelegate.m | 36 +-
.../AppIcon.appiconset/Contents.json | 68 ++
.../iOS/Base.lproj/LaunchScreen.storyboard | 28 +
.../GCDWebServer/iOS/Base.lproj/Main.storyboard | 41 +
.../src/ios/GCDWebServer/iOS/Info.plist | 12 +-
.../src/ios/GCDWebServer/iOS/ViewController.h | 31 +
.../src/ios/GCDWebServer/iOS/ViewController.m | 77 ++
local-webserver/src/ios/GCDWebServer/iOS/main.m | 2 +-
.../src/ios/GCDWebServer/tvOS/AppDelegate.h | 32 +
.../src/ios/GCDWebServer/tvOS/AppDelegate.m | 36 +
.../Content.imageset/Contents.json | 12 +
.../Back.imagestacklayer/Contents.json | 6 +
.../App Icon - Large.imagestack/Contents.json | 17 +
.../Content.imageset/Contents.json | 12 +
.../Front.imagestacklayer/Contents.json | 6 +
.../Content.imageset/Contents.json | 12 +
.../Middle.imagestacklayer/Contents.json | 6 +
.../Content.imageset/Contents.json | 12 +
.../Back.imagestacklayer/Contents.json | 6 +
.../App Icon - Small.imagestack/Contents.json | 17 +
.../Content.imageset/Contents.json | 12 +
.../Front.imagestacklayer/Contents.json | 6 +
.../Content.imageset/Contents.json | 12 +
.../Middle.imagestacklayer/Contents.json | 6 +
.../Contents.json | 26 +
.../Top Shelf Image.imageset/Contents.json | 12 +
.../tvOS/Assets.xcassets/Contents.json | 6 +
.../LaunchImage.launchimage/Contents.json | 15 +
.../tvOS/Base.lproj/Main.storyboard | 40 +
.../src/ios/GCDWebServer/tvOS/Info.plist | 30 +
.../src/ios/GCDWebServer/tvOS/ViewController.h | 31 +
.../src/ios/GCDWebServer/tvOS/ViewController.m | 77 ++
.../src/ios/GCDWebServer/tvOS/main.m | 34 +
91 files changed, 2708 insertions(+), 374 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/36f1a43e/local-webserver/src/ios/GCDWebServer/.gitignore
----------------------------------------------------------------------
diff --cc local-webserver/src/ios/GCDWebServer/.gitignore
index f8bf09a,0000000..d7d4abb
mode 100644,000000..100644
--- a/local-webserver/src/ios/GCDWebServer/.gitignore
+++ b/local-webserver/src/ios/GCDWebServer/.gitignore
@@@ -1,5 -1,0 +1,6 @@@
+.DS_Store
+xcuserdata
+project.xcworkspace
+
+Tests/Payload
++Carthage/Build
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/36f1a43e/local-webserver/src/ios/GCDWebServer/.travis.yml
----------------------------------------------------------------------
diff --cc local-webserver/src/ios/GCDWebServer/.travis.yml
index 0bad31e,0000000..05cfcb6
mode 100644,000000..100644
--- a/local-webserver/src/ios/GCDWebServer/.travis.yml
+++ b/local-webserver/src/ios/GCDWebServer/.travis.yml
@@@ -1,2 -1,0 +1,3 @@@
+language: objective-c
+script: ./Run-Tests.sh
++osx_image: xcode7.1
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/36f1a43e/local-webserver/src/ios/GCDWebServer/Frameworks/GCDWebServers.h
----------------------------------------------------------------------
diff --cc local-webserver/src/ios/GCDWebServer/Frameworks/GCDWebServers.h
index 0000000,0000000..60f42da
new file mode 100644
--- /dev/null
+++ b/local-webserver/src/ios/GCDWebServer/Frameworks/GCDWebServers.h
@@@ -1,0 -1,0 +1,52 @@@
++/*
++ 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.
++ */
++
++// GCDWebServer Core
++#import <GCDWebServers/GCDWebServer.h>
++#import <GCDWebServers/GCDWebServerConnection.h>
++#import <GCDWebServers/GCDWebServerFunctions.h>
++#import <GCDWebServers/GCDWebServerHTTPStatusCodes.h>
++#import <GCDWebServers/GCDWebServerResponse.h>
++#import <GCDWebServers/GCDWebServerRequest.h>
++
++// GCDWebServer Requests
++#import <GCDWebServers/GCDWebServerDataRequest.h>
++#import <GCDWebServers/GCDWebServerFileRequest.h>
++#import <GCDWebServers/GCDWebServerMultiPartFormRequest.h>
++#import <GCDWebServers/GCDWebServerURLEncodedFormRequest.h>
++
++// GCDWebServer Responses
++#import <GCDWebServers/GCDWebServerDataResponse.h>
++#import <GCDWebServers/GCDWebServerErrorResponse.h>
++#import <GCDWebServers/GCDWebServerFileResponse.h>
++#import <GCDWebServers/GCDWebServerStreamedResponse.h>
++
++// GCDWebUploader
++#import <GCDWebServers/GCDWebUploader.h>
++
++// GCDWebDAVServer
++#import <GCDWebServers/GCDWebDAVServer.h>
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/36f1a43e/local-webserver/src/ios/GCDWebServer/Frameworks/Info.plist
----------------------------------------------------------------------
diff --cc local-webserver/src/ios/GCDWebServer/Frameworks/Info.plist
index 0000000,0000000..537b5cb
new file mode 100644
--- /dev/null
+++ b/local-webserver/src/ios/GCDWebServer/Frameworks/Info.plist
@@@ -1,0 -1,0 +1,22 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
++<plist version="1.0">
++<dict>
++ <key>CFBundleDevelopmentRegion</key>
++ <string>en</string>
++ <key>CFBundleExecutable</key>
++ <string>$(EXECUTABLE_NAME)</string>
++ <key>CFBundleIdentifier</key>
++ <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
++ <key>CFBundleInfoDictionaryVersion</key>
++ <string>6.0</string>
++ <key>CFBundleName</key>
++ <string>$(PRODUCT_NAME)</string>
++ <key>CFBundlePackageType</key>
++ <string>FMWK</string>
++ <key>CFBundleVersion</key>
++ <string>${BUNDLE_VERSION_STRING}</string>
++ <key>CFBundleShortVersionString</key>
++ <string>${BUNDLE_VERSION_STRING}</string>
++</dict>
++</plist>
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/36f1a43e/local-webserver/src/ios/GCDWebServer/Frameworks/Tests.m
----------------------------------------------------------------------
diff --cc local-webserver/src/ios/GCDWebServer/Frameworks/Tests.m
index 0000000,0000000..b1d69e7
new file mode 100644
--- /dev/null
+++ b/local-webserver/src/ios/GCDWebServer/Frameworks/Tests.m
@@@ -1,0 -1,0 +1,24 @@@
++#import <GCDWebServers/GCDWebServers.h>
++#import <XCTest/XCTest.h>
++
++@interface Tests : XCTestCase
++@end
++
++@implementation Tests
++
++- (void)testWebServer {
++ GCDWebServer* server = [[GCDWebServer alloc] init];
++ XCTAssertNotNil(server);
++}
++
++- (void)testDAVServer {
++ GCDWebDAVServer* server = [[GCDWebDAVServer alloc] init];
++ XCTAssertNotNil(server);
++}
++
++- (void)testWebUploader {
++ GCDWebUploader* server = [[GCDWebUploader alloc] init];
++ XCTAssertNotNil(server);
++}
++
++@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/36f1a43e/local-webserver/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.h
----------------------------------------------------------------------
diff --cc local-webserver/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.h
index de3b538,0000000..84914db
mode 100644,000000..100644
--- a/local-webserver/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.h
+++ b/local-webserver/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.h
@@@ -1,156 -1,0 +1,156 @@@
+/*
- Copyright (c) 2012-2014, Pierre-Olivier Latour
++ Copyright (c) 2012-2015, Pierre-Olivier Latour
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ 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 "GCDWebServer.h"
+
+@class GCDWebDAVServer;
+
+/**
+ * Delegate methods for GCDWebDAVServer.
+ *
+ * @warning These methods are always called on the main thread in a serialized way.
+ */
+@protocol GCDWebDAVServerDelegate <GCDWebServerDelegate>
+@optional
+
+/**
+ * This method is called whenever a file has been downloaded.
+ */
+- (void)davServer:(GCDWebDAVServer*)server didDownloadFileAtPath:(NSString*)path;
+
+/**
+ * This method is called whenever a file has been uploaded.
+ */
+- (void)davServer:(GCDWebDAVServer*)server didUploadFileAtPath:(NSString*)path;
+
+/**
+ * This method is called whenever a file or directory has been moved.
+ */
+- (void)davServer:(GCDWebDAVServer*)server didMoveItemFromPath:(NSString*)fromPath toPath:(NSString*)toPath;
+
+/**
+ * This method is called whenever a file or directory has been copied.
+ */
+- (void)davServer:(GCDWebDAVServer*)server didCopyItemFromPath:(NSString*)fromPath toPath:(NSString*)toPath;
+
+/**
+ * This method is called whenever a file or directory has been deleted.
+ */
+- (void)davServer:(GCDWebDAVServer*)server didDeleteItemAtPath:(NSString*)path;
+
+/**
+ * This method is called whenever a directory has been created.
+ */
+- (void)davServer:(GCDWebDAVServer*)server didCreateDirectoryAtPath:(NSString*)path;
+
+@end
+
+/**
+ * The GCDWebDAVServer subclass of GCDWebServer implements a class 1 compliant
+ * WebDAV server. It is also partially class 2 compliant but only when the
+ * client is the OS X WebDAV implementation (so it can work with the OS X Finder).
+ *
+ * See the README.md file for more information about the features of GCDWebDAVServer.
+ */
+@interface GCDWebDAVServer : GCDWebServer
+
+/**
+ * Returns the upload directory as specified when the server was initialized.
+ */
+@property(nonatomic, readonly) NSString* uploadDirectory;
+
+/**
+ * Sets the delegate for the server.
+ */
+@property(nonatomic, assign) id<GCDWebDAVServerDelegate> delegate;
+
+/**
+ * Sets which files are allowed to be operated on depending on their extension.
+ *
+ * The default value is nil i.e. all file extensions are allowed.
+ */
+@property(nonatomic, copy) NSArray* allowedFileExtensions;
+
+/**
+ * Sets if files and directories whose name start with a period are allowed to
+ * be operated on.
+ *
+ * The default value is NO.
+ */
+@property(nonatomic) BOOL allowHiddenItems;
+
+/**
+ * This method is the designated initializer for the class.
+ */
+- (instancetype)initWithUploadDirectory:(NSString*)path;
+
+@end
+
+/**
+ * Hooks to customize the behavior of GCDWebDAVServer.
+ *
+ * @warning These methods can be called on any GCD thread.
+ */
+@interface GCDWebDAVServer (Subclassing)
+
+/**
+ * This method is called to check if a file upload is allowed to complete.
+ * The uploaded file is available for inspection at "tempPath".
+ *
+ * The default implementation returns YES.
+ */
+- (BOOL)shouldUploadFileAtPath:(NSString*)path withTemporaryFile:(NSString*)tempPath;
+
+/**
+ * This method is called to check if a file or directory is allowed to be moved.
+ *
+ * The default implementation returns YES.
+ */
+- (BOOL)shouldMoveItemFromPath:(NSString*)fromPath toPath:(NSString*)toPath;
+
+/**
+ * This method is called to check if a file or directory is allowed to be copied.
+ *
+ * The default implementation returns YES.
+ */
+- (BOOL)shouldCopyItemFromPath:(NSString*)fromPath toPath:(NSString*)toPath;
+
+/**
+ * This method is called to check if a file or directory is allowed to be deleted.
+ *
+ * The default implementation returns YES.
+ */
+- (BOOL)shouldDeleteItemAtPath:(NSString*)path;
+
+/**
+ * This method is called to check if a directory is allowed to be created.
+ *
+ * The default implementation returns YES.
+ */
+- (BOOL)shouldCreateDirectoryAtPath:(NSString*)path;
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/36f1a43e/local-webserver/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.m
----------------------------------------------------------------------
diff --cc local-webserver/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.m
index c7341fa,0000000..33025d4
mode 100644,000000..100644
--- a/local-webserver/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.m
+++ b/local-webserver/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.m
@@@ -1,688 -1,0 +1,701 @@@
+/*
- Copyright (c) 2012-2014, Pierre-Olivier Latour
++ Copyright (c) 2012-2015, Pierre-Olivier Latour
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ 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.
+ */
+
+#if !__has_feature(objc_arc)
+#error GCDWebDAVServer requires ARC
+#endif
+
+// WebDAV specifications: http://webdav.org/specs/rfc4918.html
+
+// Requires "HEADER_SEARCH_PATHS = $(SDKROOT)/usr/include/libxml2" in Xcode build settings
+#import <libxml/parser.h>
+
+#import "GCDWebDAVServer.h"
+
+#import "GCDWebServerFunctions.h"
+
+#import "GCDWebServerDataRequest.h"
+#import "GCDWebServerFileRequest.h"
+
+#import "GCDWebServerDataResponse.h"
+#import "GCDWebServerErrorResponse.h"
+#import "GCDWebServerFileResponse.h"
+
+#define kXMLParseOptions (XML_PARSE_NONET | XML_PARSE_RECOVER | XML_PARSE_NOBLANKS | XML_PARSE_COMPACT | XML_PARSE_NOWARNING | XML_PARSE_NOERROR)
+
+typedef NS_ENUM(NSInteger, DAVProperties) {
+ kDAVProperty_ResourceType = (1 << 0),
+ kDAVProperty_CreationDate = (1 << 1),
+ kDAVProperty_LastModified = (1 << 2),
+ kDAVProperty_ContentLength = (1 << 3),
+ kDAVAllProperties = kDAVProperty_ResourceType | kDAVProperty_CreationDate | kDAVProperty_LastModified | kDAVProperty_ContentLength
+};
+
+@interface GCDWebDAVServer () {
+@private
+ NSString* _uploadDirectory;
+ NSArray* _allowedExtensions;
+ BOOL _allowHidden;
+}
+@end
+
+@implementation GCDWebDAVServer (Methods)
+
+// Must match implementation in GCDWebUploader
+- (BOOL)_checkSandboxedPath:(NSString*)path {
+ return [[path stringByStandardizingPath] hasPrefix:_uploadDirectory];
+}
+
+- (BOOL)_checkFileExtension:(NSString*)fileName {
+ if (_allowedExtensions && ![_allowedExtensions containsObject:[[fileName pathExtension] lowercaseString]]) {
+ return NO;
+ }
+ return YES;
+}
+
+static inline BOOL _IsMacFinder(GCDWebServerRequest* request) {
+ NSString* userAgentHeader = [request.headers objectForKey:@"User-Agent"];
+ return ([userAgentHeader hasPrefix:@"WebDAVFS/"] || [userAgentHeader hasPrefix:@"WebDAVLib/"]); // OS X WebDAV client
+}
+
+- (GCDWebServerResponse*)performOPTIONS:(GCDWebServerRequest*)request {
+ GCDWebServerResponse* response = [GCDWebServerResponse response];
+ if (_IsMacFinder(request)) {
+ [response setValue:@"1, 2" forAdditionalHeader:@"DAV"]; // Classes 1 and 2
+ } else {
+ [response setValue:@"1" forAdditionalHeader:@"DAV"]; // Class 1
+ }
+ return response;
+}
+
+- (GCDWebServerResponse*)performGET:(GCDWebServerRequest*)request {
+ NSString* relativePath = request.path;
+ NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
+ BOOL isDirectory = NO;
+ if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
+ }
+
+ NSString* itemName = [absolutePath lastPathComponent];
+ if (([itemName hasPrefix:@"."] && !_allowHidden) || (!isDirectory && ![self _checkFileExtension:itemName])) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Downlading item name \"%@\" is not allowed", itemName];
+ }
+
+ // Because HEAD requests are mapped to GET ones, we need to handle directories but it's OK to return nothing per http://webdav.org/specs/rfc4918.html#rfc.section.9.4
+ if (isDirectory) {
+ return [GCDWebServerResponse response];
+ }
+
+ if ([self.delegate respondsToSelector:@selector(davServer:didDownloadFileAtPath:)]) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self.delegate davServer:self didDownloadFileAtPath:absolutePath];
+ });
+ }
++
++ if ([request hasByteRange]) {
++ return [GCDWebServerFileResponse responseWithFile:absolutePath byteRange:request.byteRange];
++ }
++
+ return [GCDWebServerFileResponse responseWithFile:absolutePath];
+}
+
+- (GCDWebServerResponse*)performPUT:(GCDWebServerFileRequest*)request {
+ if ([request hasByteRange]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Range uploads not supported"];
+ }
+
+ NSString* relativePath = request.path;
+ NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
+ if (![self _checkSandboxedPath:absolutePath]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
+ }
+ BOOL isDirectory;
+ if (![[NSFileManager defaultManager] fileExistsAtPath:[absolutePath stringByDeletingLastPathComponent] isDirectory:&isDirectory] || !isDirectory) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Conflict message:@"Missing intermediate collection(s) for \"%@\"", relativePath];
+ }
+
+ BOOL existing = [[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory];
+ if (existing && isDirectory) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_MethodNotAllowed message:@"PUT not allowed on existing collection \"%@\"", relativePath];
+ }
+
+ NSString* fileName = [absolutePath lastPathComponent];
+ if (([fileName hasPrefix:@"."] && !_allowHidden) || ![self _checkFileExtension:fileName]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploading file name \"%@\" is not allowed", fileName];
+ }
+
+ if (![self shouldUploadFileAtPath:absolutePath withTemporaryFile:request.temporaryPath]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploading file to \"%@\" is not permitted", relativePath];
+ }
+
+ [[NSFileManager defaultManager] removeItemAtPath:absolutePath error:NULL];
+ NSError* error = nil;
+ if (![[NSFileManager defaultManager] moveItemAtPath:request.temporaryPath toPath:absolutePath error:&error]) {
+ return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed moving uploaded file to \"%@\"", relativePath];
+ }
+
+ if ([self.delegate respondsToSelector:@selector(davServer:didUploadFileAtPath:)]) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self.delegate davServer:self didUploadFileAtPath:absolutePath];
+ });
+ }
+ return [GCDWebServerResponse responseWithStatusCode:(existing ? kGCDWebServerHTTPStatusCode_NoContent : kGCDWebServerHTTPStatusCode_Created)];
+}
+
+- (GCDWebServerResponse*)performDELETE:(GCDWebServerRequest*)request {
+ NSString* depthHeader = [request.headers objectForKey:@"Depth"];
+ if (depthHeader && ![depthHeader isEqualToString:@"infinity"]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Unsupported 'Depth' header: %@", depthHeader];
+ }
+
+ NSString* relativePath = request.path;
+ NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
+ BOOL isDirectory = NO;
+ if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
+ }
+
+ NSString* itemName = [absolutePath lastPathComponent];
+ if (([itemName hasPrefix:@"."] && !_allowHidden) || (!isDirectory && ![self _checkFileExtension:itemName])) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Deleting item name \"%@\" is not allowed", itemName];
+ }
+
+ if (![self shouldDeleteItemAtPath:absolutePath]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Deleting \"%@\" is not permitted", relativePath];
+ }
+
+ NSError* error = nil;
+ if (![[NSFileManager defaultManager] removeItemAtPath:absolutePath error:&error]) {
+ return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed deleting \"%@\"", relativePath];
+ }
+
+ if ([self.delegate respondsToSelector:@selector(davServer:didDeleteItemAtPath:)]) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self.delegate davServer:self didDeleteItemAtPath:absolutePath];
+ });
+ }
+ return [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_NoContent];
+}
+
+- (GCDWebServerResponse*)performMKCOL:(GCDWebServerDataRequest*)request {
+ if ([request hasBody] && (request.contentLength > 0)) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_UnsupportedMediaType message:@"Unexpected request body for MKCOL method"];
+ }
+
+ NSString* relativePath = request.path;
+ NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
+ if (![self _checkSandboxedPath:absolutePath]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
+ }
+ BOOL isDirectory;
+ if (![[NSFileManager defaultManager] fileExistsAtPath:[absolutePath stringByDeletingLastPathComponent] isDirectory:&isDirectory] || !isDirectory) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Conflict message:@"Missing intermediate collection(s) for \"%@\"", relativePath];
+ }
+
+ NSString* directoryName = [absolutePath lastPathComponent];
+ if (!_allowHidden && [directoryName hasPrefix:@"."]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Creating directory name \"%@\" is not allowed", directoryName];
+ }
+
+ if (![self shouldCreateDirectoryAtPath:absolutePath]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Creating directory \"%@\" is not permitted", relativePath];
+ }
+
+ NSError* error = nil;
+ if (![[NSFileManager defaultManager] createDirectoryAtPath:absolutePath withIntermediateDirectories:NO attributes:nil error:&error]) {
+ return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed creating directory \"%@\"", relativePath];
+ }
+#ifdef __GCDWEBSERVER_ENABLE_TESTING__
+ NSString* creationDateHeader = [request.headers objectForKey:@"X-GCDWebServer-CreationDate"];
+ if (creationDateHeader) {
+ NSDate* date = GCDWebServerParseISO8601(creationDateHeader);
+ if (!date || ![[NSFileManager defaultManager] setAttributes:@{NSFileCreationDate: date} ofItemAtPath:absolutePath error:&error]) {
+ return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed setting creation date for directory \"%@\"", relativePath];
+ }
+ }
+#endif
+
+ if ([self.delegate respondsToSelector:@selector(davServer:didCreateDirectoryAtPath:)]) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self.delegate davServer:self didCreateDirectoryAtPath:absolutePath];
+ });
+ }
+ return [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_Created];
+}
+
+- (GCDWebServerResponse*)performCOPY:(GCDWebServerRequest*)request isMove:(BOOL)isMove {
+ if (!isMove) {
+ NSString* depthHeader = [request.headers objectForKey:@"Depth"]; // TODO: Support "Depth: 0"
+ if (depthHeader && ![depthHeader isEqualToString:@"infinity"]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Unsupported 'Depth' header: %@", depthHeader];
+ }
+ }
+
+ NSString* srcRelativePath = request.path;
+ NSString* srcAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:srcRelativePath];
+ if (![self _checkSandboxedPath:srcAbsolutePath]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", srcRelativePath];
+ }
+
+ NSString* dstRelativePath = [request.headers objectForKey:@"Destination"];
+ NSRange range = [dstRelativePath rangeOfString:[request.headers objectForKey:@"Host"]];
+ if ((dstRelativePath == nil) || (range.location == NSNotFound)) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Malformed 'Destination' header: %@", dstRelativePath];
+ }
++#pragma clang diagnostic push
++#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ dstRelativePath = [[dstRelativePath substringFromIndex:(range.location + range.length)] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
++#pragma clang diagnostic pop
+ NSString* dstAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:dstRelativePath];
+ if (![self _checkSandboxedPath:dstAbsolutePath]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", srcRelativePath];
+ }
+
+ BOOL isDirectory;
+ if (![[NSFileManager defaultManager] fileExistsAtPath:[dstAbsolutePath stringByDeletingLastPathComponent] isDirectory:&isDirectory] || !isDirectory) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Conflict message:@"Invalid destination \"%@\"", dstRelativePath];
+ }
+
+ NSString* itemName = [dstAbsolutePath lastPathComponent];
+ if ((!_allowHidden && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"%@ to item name \"%@\" is not allowed", isMove ? @"Moving" : @"Copying", itemName];
+ }
+
+ NSString* overwriteHeader = [request.headers objectForKey:@"Overwrite"];
+ BOOL existing = [[NSFileManager defaultManager] fileExistsAtPath:dstAbsolutePath];
+ if (existing && ((isMove && ![overwriteHeader isEqualToString:@"T"]) || (!isMove && [overwriteHeader isEqualToString:@"F"]))) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_PreconditionFailed message:@"Destination \"%@\" already exists", dstRelativePath];
+ }
+
+ if (isMove) {
+ if (![self shouldMoveItemFromPath:srcAbsolutePath toPath:dstAbsolutePath]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Moving \"%@\" to \"%@\" is not permitted", srcRelativePath, dstRelativePath];
+ }
+ } else {
+ if (![self shouldCopyItemFromPath:srcAbsolutePath toPath:dstAbsolutePath]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Copying \"%@\" to \"%@\" is not permitted", srcRelativePath, dstRelativePath];
+ }
+ }
+
+ NSError* error = nil;
+ if (isMove) {
+ [[NSFileManager defaultManager] removeItemAtPath:dstAbsolutePath error:NULL];
+ if (![[NSFileManager defaultManager] moveItemAtPath:srcAbsolutePath toPath:dstAbsolutePath error:&error]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden underlyingError:error message:@"Failed copying \"%@\" to \"%@\"", srcRelativePath, dstRelativePath];
+ }
+ } else {
+ if (![[NSFileManager defaultManager] copyItemAtPath:srcAbsolutePath toPath:dstAbsolutePath error:&error]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden underlyingError:error message:@"Failed copying \"%@\" to \"%@\"", srcRelativePath, dstRelativePath];
+ }
+ }
+
+ if (isMove) {
+ if ([self.delegate respondsToSelector:@selector(davServer:didMoveItemFromPath:toPath:)]) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self.delegate davServer:self didMoveItemFromPath:srcAbsolutePath toPath:dstAbsolutePath];
+ });
+ }
+ } else {
+ if ([self.delegate respondsToSelector:@selector(davServer:didCopyItemFromPath:toPath:)]) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self.delegate davServer:self didCopyItemFromPath:srcAbsolutePath toPath:dstAbsolutePath];
+ });
+ }
+ }
+
+ return [GCDWebServerResponse responseWithStatusCode:(existing ? kGCDWebServerHTTPStatusCode_NoContent : kGCDWebServerHTTPStatusCode_Created)];
+}
+
+static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name) {
+ while (child) {
+ if ((child->type == XML_ELEMENT_NODE) && !xmlStrcmp(child->name, name)) {
+ return child;
+ }
+ child = child->next;
+ }
+ return NULL;
+}
+
+- (void)_addPropertyResponseForItem:(NSString*)itemPath resource:(NSString*)resourcePath properties:(DAVProperties)properties xmlString:(NSMutableString*)xmlString {
++#pragma clang diagnostic push
++#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ CFStringRef escapedPath = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)resourcePath, NULL, CFSTR("<&>?+"), kCFStringEncodingUTF8);
++#pragma clang diagnostic pop
+ if (escapedPath) {
+ NSDictionary* attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:itemPath error:NULL];
+ NSString* type = [attributes objectForKey:NSFileType];
+ BOOL isFile = [type isEqualToString:NSFileTypeRegular];
+ BOOL isDirectory = [type isEqualToString:NSFileTypeDirectory];
+ if ((isFile && [self _checkFileExtension:itemPath]) || isDirectory) {
+ [xmlString appendString:@"<D:response>"];
+ [xmlString appendFormat:@"<D:href>%@</D:href>", escapedPath];
+ [xmlString appendString:@"<D:propstat>"];
+ [xmlString appendString:@"<D:prop>"];
+
+ if (properties & kDAVProperty_ResourceType) {
+ if (isDirectory) {
+ [xmlString appendString:@"<D:resourcetype><D:collection/></D:resourcetype>"];
+ } else {
+ [xmlString appendString:@"<D:resourcetype/>"];
+ }
+ }
+
+ if ((properties & kDAVProperty_CreationDate) && [attributes objectForKey:NSFileCreationDate]) {
+ [xmlString appendFormat:@"<D:creationdate>%@</D:creationdate>", GCDWebServerFormatISO8601([attributes fileCreationDate])];
+ }
+
+ if ((properties & kDAVProperty_LastModified) && isFile && [attributes objectForKey:NSFileModificationDate]) { // Last modification date is not useful for directories as it changes implicitely and 'Last-Modified' header is not provided for directories anyway
+ [xmlString appendFormat:@"<D:getlastmodified>%@</D:getlastmodified>", GCDWebServerFormatRFC822([attributes fileModificationDate])];
+ }
+
+ if ((properties & kDAVProperty_ContentLength) && !isDirectory && [attributes objectForKey:NSFileSize]) {
+ [xmlString appendFormat:@"<D:getcontentlength>%llu</D:getcontentlength>", [attributes fileSize]];
+ }
+
+ [xmlString appendString:@"</D:prop>"];
+ [xmlString appendString:@"<D:status>HTTP/1.1 200 OK</D:status>"];
+ [xmlString appendString:@"</D:propstat>"];
+ [xmlString appendString:@"</D:response>\n"];
+ }
+ CFRelease(escapedPath);
+ } else {
+ [self logError:@"Failed escaping path: %@", itemPath];
+ }
+}
+
+- (GCDWebServerResponse*)performPROPFIND:(GCDWebServerDataRequest*)request {
+ NSInteger depth;
+ NSString* depthHeader = [request.headers objectForKey:@"Depth"];
+ if ([depthHeader isEqualToString:@"0"]) {
+ depth = 0;
+ } else if ([depthHeader isEqualToString:@"1"]) {
+ depth = 1;
+ } else {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Unsupported 'Depth' header: %@", depthHeader]; // TODO: Return 403 / propfind-finite-depth for "infinity" depth
+ }
+
+ DAVProperties properties = 0;
+ if (request.data.length) {
+ BOOL success = YES;
+ xmlDocPtr document = xmlReadMemory(request.data.bytes, (int)request.data.length, NULL, NULL, kXMLParseOptions);
+ if (document) {
+ xmlNodePtr rootNode = _XMLChildWithName(document->children, (const xmlChar*)"propfind");
+ xmlNodePtr allNode = rootNode ? _XMLChildWithName(rootNode->children, (const xmlChar*)"allprop") : NULL;
+ xmlNodePtr propNode = rootNode ? _XMLChildWithName(rootNode->children, (const xmlChar*)"prop") : NULL;
+ if (allNode) {
+ properties = kDAVAllProperties;
+ } else if (propNode) {
+ xmlNodePtr node = propNode->children;
+ while (node) {
+ if (!xmlStrcmp(node->name, (const xmlChar*)"resourcetype")) {
+ properties |= kDAVProperty_ResourceType;
+ } else if (!xmlStrcmp(node->name, (const xmlChar*)"creationdate")) {
+ properties |= kDAVProperty_CreationDate;
+ } else if (!xmlStrcmp(node->name, (const xmlChar*)"getlastmodified")) {
+ properties |= kDAVProperty_LastModified;
+ } else if (!xmlStrcmp(node->name, (const xmlChar*)"getcontentlength")) {
+ properties |= kDAVProperty_ContentLength;
+ } else {
+ [self logWarning:@"Unknown DAV property requested \"%s\"", node->name];
+ }
+ node = node->next;
+ }
+ } else {
+ success = NO;
+ }
+ xmlFreeDoc(document);
+ } else {
+ success = NO;
+ }
+ if (!success) {
+ NSString* string = [[NSString alloc] initWithData:request.data encoding:NSUTF8StringEncoding];
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Invalid DAV properties:\n%@", string];
+ }
+ } else {
+ properties = kDAVAllProperties;
+ }
+
+ NSString* relativePath = request.path;
+ NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
+ BOOL isDirectory = NO;
+ if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
+ }
+
+ NSString* itemName = [absolutePath lastPathComponent];
+ if (([itemName hasPrefix:@"."] && !_allowHidden) || (!isDirectory && ![self _checkFileExtension:itemName])) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Retrieving properties for item name \"%@\" is not allowed", itemName];
+ }
+
+ NSArray* items = nil;
+ if (isDirectory) {
+ NSError* error = nil;
+ items = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:absolutePath error:&error];
+ if (items == nil) {
+ return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed listing directory \"%@\"", relativePath];
+ }
+ }
+
+ NSMutableString* xmlString = [NSMutableString stringWithString:@"<?xml version=\"1.0\" encoding=\"utf-8\" ?>"];
+ [xmlString appendString:@"<D:multistatus xmlns:D=\"DAV:\">\n"];
+ if (![relativePath hasPrefix:@"/"]) {
+ relativePath = [@"/" stringByAppendingString:relativePath];
+ }
+ [self _addPropertyResponseForItem:absolutePath resource:relativePath properties:properties xmlString:xmlString];
+ if (depth == 1) {
+ if (![relativePath hasSuffix:@"/"]) {
+ relativePath = [relativePath stringByAppendingString:@"/"];
+ }
+ for (NSString* item in items) {
+ if (_allowHidden || ![item hasPrefix:@"."]) {
+ [self _addPropertyResponseForItem:[absolutePath stringByAppendingPathComponent:item] resource:[relativePath stringByAppendingString:item] properties:properties xmlString:xmlString];
+ }
+ }
+ }
+ [xmlString appendString:@"</D:multistatus>"];
+
+ GCDWebServerDataResponse* response = [GCDWebServerDataResponse responseWithData:[xmlString dataUsingEncoding:NSUTF8StringEncoding]
+ contentType:@"application/xml; charset=\"utf-8\""];
+ response.statusCode = kGCDWebServerHTTPStatusCode_MultiStatus;
+ return response;
+}
+
+- (GCDWebServerResponse*)performLOCK:(GCDWebServerDataRequest*)request {
+ if (!_IsMacFinder(request)) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_MethodNotAllowed message:@"LOCK method only allowed for Mac Finder"];
+ }
+
+ NSString* relativePath = request.path;
+ NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
+ BOOL isDirectory = NO;
+ if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
+ }
+
+ NSString* depthHeader = [request.headers objectForKey:@"Depth"];
+ NSString* timeoutHeader = [request.headers objectForKey:@"Timeout"];
+ NSString* scope = nil;
+ NSString* type = nil;
+ NSString* owner = nil;
+ NSString* token = nil;
+ BOOL success = YES;
+ xmlDocPtr document = xmlReadMemory(request.data.bytes, (int)request.data.length, NULL, NULL, kXMLParseOptions);
+ if (document) {
+ xmlNodePtr node = _XMLChildWithName(document->children, (const xmlChar*)"lockinfo");
+ if (node) {
+ xmlNodePtr scopeNode = _XMLChildWithName(node->children, (const xmlChar*)"lockscope");
+ if (scopeNode && scopeNode->children && scopeNode->children->name) {
+ scope = [NSString stringWithUTF8String:(const char*)scopeNode->children->name];
+ }
+ xmlNodePtr typeNode = _XMLChildWithName(node->children, (const xmlChar*)"locktype");
+ if (typeNode && typeNode->children && typeNode->children->name) {
+ type = [NSString stringWithUTF8String:(const char*)typeNode->children->name];
+ }
+ xmlNodePtr ownerNode = _XMLChildWithName(node->children, (const xmlChar*)"owner");
+ if (ownerNode) {
+ ownerNode = _XMLChildWithName(ownerNode->children, (const xmlChar*)"href");
+ if (ownerNode && ownerNode->children && ownerNode->children->content) {
+ owner = [NSString stringWithUTF8String:(const char*)ownerNode->children->content];
+ }
+ }
+ } else {
+ success = NO;
+ }
+ xmlFreeDoc(document);
+ } else {
+ success = NO;
+ }
+ if (!success) {
+ NSString* string = [[NSString alloc] initWithData:request.data encoding:NSUTF8StringEncoding];
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Invalid DAV properties:\n%@", string];
+ }
+
+ if (![scope isEqualToString:@"exclusive"] || ![type isEqualToString:@"write"] || ![depthHeader isEqualToString:@"0"]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Locking request \"%@/%@/%@\" for \"%@\" is not allowed", scope, type, depthHeader, relativePath];
+ }
+
+ NSString* itemName = [absolutePath lastPathComponent];
+ if ((!_allowHidden && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Locking item name \"%@\" is not allowed", itemName];
+ }
+
+#ifdef __GCDWEBSERVER_ENABLE_TESTING__
+ NSString* lockTokenHeader = [request.headers objectForKey:@"X-GCDWebServer-LockToken"];
+ if (lockTokenHeader) {
+ token = lockTokenHeader;
+ }
+#endif
+ if (!token) {
+ CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
+ CFStringRef string = CFUUIDCreateString(kCFAllocatorDefault, uuid);
+ token = [NSString stringWithFormat:@"urn:uuid:%@", (__bridge NSString*)string];
+ CFRelease(string);
+ CFRelease(uuid);
+ }
+
+ NSMutableString* xmlString = [NSMutableString stringWithString:@"<?xml version=\"1.0\" encoding=\"utf-8\" ?>"];
+ [xmlString appendString:@"<D:prop xmlns:D=\"DAV:\">\n"];
+ [xmlString appendString:@"<D:lockdiscovery>\n<D:activelock>\n"];
+ [xmlString appendFormat:@"<D:locktype><D:%@/></D:locktype>\n", type];
+ [xmlString appendFormat:@"<D:lockscope><D:%@/></D:lockscope>\n", scope];
+ [xmlString appendFormat:@"<D:depth>%@</D:depth>\n", depthHeader];
+ if (owner) {
+ [xmlString appendFormat:@"<D:owner><D:href>%@</D:href></D:owner>\n", owner];
+ }
+ if (timeoutHeader) {
+ [xmlString appendFormat:@"<D:timeout>%@</D:timeout>\n", timeoutHeader];
+ }
+ [xmlString appendFormat:@"<D:locktoken><D:href>%@</D:href></D:locktoken>\n", token];
+ NSString* lockroot = [@"http://" stringByAppendingString:[[request.headers objectForKey:@"Host"] stringByAppendingString:[@"/" stringByAppendingString:relativePath]]];
+ [xmlString appendFormat:@"<D:lockroot><D:href>%@</D:href></D:lockroot>\n", lockroot];
+ [xmlString appendString:@"</D:activelock>\n</D:lockdiscovery>\n"];
+ [xmlString appendString:@"</D:prop>"];
+
+ [self logVerbose:@"WebDAV pretending to lock \"%@\"", relativePath];
+ GCDWebServerDataResponse* response = [GCDWebServerDataResponse responseWithData:[xmlString dataUsingEncoding:NSUTF8StringEncoding]
+ contentType:@"application/xml; charset=\"utf-8\""];
+ return response;
+}
+
+- (GCDWebServerResponse*)performUNLOCK:(GCDWebServerRequest*)request {
+ if (!_IsMacFinder(request)) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_MethodNotAllowed message:@"UNLOCK method only allowed for Mac Finder"];
+ }
+
+ NSString* relativePath = request.path;
+ NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath];
+ BOOL isDirectory = NO;
+ if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath];
+ }
+
+ NSString* tokenHeader = [request.headers objectForKey:@"Lock-Token"];
+ if (!tokenHeader.length) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Missing 'Lock-Token' header"];
+ }
+
+ NSString* itemName = [absolutePath lastPathComponent];
+ if ((!_allowHidden && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) {
+ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Unlocking item name \"%@\" is not allowed", itemName];
+ }
+
+ [self logVerbose:@"WebDAV pretending to unlock \"%@\"", relativePath];
+ return [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_NoContent];
+}
+
+@end
+
+@implementation GCDWebDAVServer
+
+@synthesize uploadDirectory=_uploadDirectory, allowedFileExtensions=_allowedExtensions, allowHiddenItems=_allowHidden;
+
++@dynamic delegate;
++
+- (instancetype)initWithUploadDirectory:(NSString*)path {
+ if ((self = [super init])) {
+ _uploadDirectory = [[path stringByStandardizingPath] copy];
+ GCDWebDAVServer* __unsafe_unretained server = self;
+
+ // 9.1 PROPFIND method
+ [self addDefaultHandlerForMethod:@"PROPFIND" requestClass:[GCDWebServerDataRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
+ return [server performPROPFIND:(GCDWebServerDataRequest*)request];
+ }];
+
+ // 9.3 MKCOL Method
+ [self addDefaultHandlerForMethod:@"MKCOL" requestClass:[GCDWebServerDataRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
+ return [server performMKCOL:(GCDWebServerDataRequest*)request];
+ }];
+
+ // 9.4 GET & HEAD methods
+ [self addDefaultHandlerForMethod:@"GET" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
+ return [server performGET:request];
+ }];
+
+ // 9.6 DELETE method
+ [self addDefaultHandlerForMethod:@"DELETE" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
+ return [server performDELETE:request];
+ }];
+
+ // 9.7 PUT method
+ [self addDefaultHandlerForMethod:@"PUT" requestClass:[GCDWebServerFileRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
+ return [server performPUT:(GCDWebServerFileRequest*)request];
+ }];
+
+ // 9.8 COPY method
+ [self addDefaultHandlerForMethod:@"COPY" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
+ return [server performCOPY:request isMove:NO];
+ }];
+
+ // 9.9 MOVE method
+ [self addDefaultHandlerForMethod:@"MOVE" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
+ return [server performCOPY:request isMove:YES];
+ }];
+
+ // 9.10 LOCK method
+ [self addDefaultHandlerForMethod:@"LOCK" requestClass:[GCDWebServerDataRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
+ return [server performLOCK:(GCDWebServerDataRequest*)request];
+ }];
+
+ // 9.11 UNLOCK method
+ [self addDefaultHandlerForMethod:@"UNLOCK" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
+ return [server performUNLOCK:request];
+ }];
+
+ // 10.1 OPTIONS method / DAV Header
+ [self addDefaultHandlerForMethod:@"OPTIONS" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
+ return [server performOPTIONS:request];
+ }];
+
+ }
+ return self;
+}
+
+@end
+
+@implementation GCDWebDAVServer (Subclassing)
+
+- (BOOL)shouldUploadFileAtPath:(NSString*)path withTemporaryFile:(NSString*)tempPath {
+ return YES;
+}
+
+- (BOOL)shouldMoveItemFromPath:(NSString*)fromPath toPath:(NSString*)toPath {
+ return YES;
+}
+
+- (BOOL)shouldCopyItemFromPath:(NSString*)fromPath toPath:(NSString*)toPath {
+ return YES;
+}
+
+- (BOOL)shouldDeleteItemAtPath:(NSString*)path {
+ return YES;
+}
+
+- (BOOL)shouldCreateDirectoryAtPath:(NSString*)path {
+ return YES;
+}
+
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/36f1a43e/local-webserver/src/ios/GCDWebServer/GCDWebServer.podspec
----------------------------------------------------------------------
diff --cc local-webserver/src/ios/GCDWebServer/GCDWebServer.podspec
index d713b26,0000000..901de93
mode 100644,000000..100644
--- a/local-webserver/src/ios/GCDWebServer/GCDWebServer.podspec
+++ b/local-webserver/src/ios/GCDWebServer/GCDWebServer.podspec
@@@ -1,49 -1,0 +1,75 @@@
+# http://guides.cocoapods.org/syntax/podspec.html
+# http://guides.cocoapods.org/making/getting-setup-with-trunk.html
+# $ sudo gem update cocoapods
+# (optional) $ pod trunk register {email} {name} --description={computer}
- # $ pod trunk push
++# $ pod trunk --verbose push
+# DELETE THIS SECTION BEFORE PROCEEDING!
+
+Pod::Spec.new do |s|
+ s.name = 'GCDWebServer'
- s.version = '3.1'
++ s.version = '3.3.3'
+ s.author = { 'Pierre-Olivier Latour' => 'info@pol-online.net' }
+ s.license = { :type => 'BSD', :file => 'LICENSE' }
+ s.homepage = 'https://github.com/swisspol/GCDWebServer'
+ s.summary = 'Lightweight GCD based HTTP server for OS X & iOS (includes web based uploader & WebDAV server)'
+
+ s.source = { :git => 'https://github.com/swisspol/GCDWebServer.git', :tag => s.version.to_s }
+ s.ios.deployment_target = '5.0'
++ s.tvos.deployment_target = '9.0'
+ s.osx.deployment_target = '10.7'
+ s.requires_arc = true
+
+ s.default_subspec = 'Core'
+
+ s.subspec 'Core' do |cs|
+ cs.source_files = 'GCDWebServer/**/*.{h,m}'
+ cs.private_header_files = "GCDWebServer/Core/GCDWebServerPrivate.h"
+ cs.requires_arc = true
+ cs.ios.library = 'z'
+ cs.ios.frameworks = 'MobileCoreServices', 'CFNetwork'
++ cs.tvos.library = 'z'
++ cs.tvos.frameworks = 'MobileCoreServices', 'CFNetwork'
+ cs.osx.library = 'z'
+ cs.osx.framework = 'SystemConfiguration'
+ end
+
- s.subspec 'WebDAV' do |cs|
++ s.subspec "CocoaLumberjack" do |cs|
+ cs.dependency 'GCDWebServer/Core'
- cs.source_files = 'GCDWebDAVServer/*.{h,m}'
- cs.requires_arc = true
- cs.ios.library = 'xml2'
- cs.osx.library = 'xml2'
- cs.compiler_flags = '-I$(SDKROOT)/usr/include/libxml2'
++ cs.dependency 'CocoaLumberjack', '~> 2'
+ end
+
- s.subspec 'WebUploader' do |cs|
- cs.dependency 'GCDWebServer/Core'
- cs.source_files = 'GCDWebUploader/*.{h,m}'
- cs.requires_arc = true
- cs.resource = "GCDWebUploader/GCDWebUploader.bundle"
++ s.subspec 'WebDAV' do |cs|
++ cs.default_subspec = 'Core'
++
++ cs.subspec "Core" do |ccs|
++ ccs.dependency 'GCDWebServer/Core'
++ ccs.source_files = 'GCDWebDAVServer/*.{h,m}'
++ ccs.requires_arc = true
++ ccs.ios.library = 'xml2'
++ ccs.tvos.library = 'xml2'
++ ccs.osx.library = 'xml2'
++ ccs.compiler_flags = '-I$(SDKROOT)/usr/include/libxml2'
++ end
++
++ cs.subspec "CocoaLumberjack" do |cscl|
++ cscl.dependency 'GCDWebServer/WebDAV/Core'
++ cscl.dependency 'GCDWebServer/CocoaLumberjack'
++ end
+ end
+
++ s.subspec 'WebUploader' do |cs|
++ cs.default_subspec = 'Core'
++
++ cs.subspec "Core" do |ccs|
++ ccs.dependency 'GCDWebServer/Core'
++ ccs.source_files = 'GCDWebUploader/*.{h,m}'
++ ccs.requires_arc = true
++ ccs.resource = "GCDWebUploader/GCDWebUploader.bundle"
++ end
++
++ cs.subspec "CocoaLumberjack" do |cscl|
++ cscl.dependency 'GCDWebServer/WebUploader/Core'
++ cscl.dependency 'GCDWebServer/CocoaLumberjack'
++ end
++ end
+end
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org