summaryrefslogtreecommitdiff
path: root/StoneIsland/platforms/ios/CordovaLib
diff options
context:
space:
mode:
authorJules Laplace <jules@okfoc.us>2015-09-10 14:58:03 -0400
committerJules Laplace <jules@okfoc.us>2015-09-10 14:58:03 -0400
commitd73a4b1c5a2540077607dcc4001acbae85980ae4 (patch)
treec30089f1742f9430bb18679dc6664157a5dc66f4 /StoneIsland/platforms/ios/CordovaLib
parent124e6c0a8d9577b4a30e0b265f5c23d637c41966 (diff)
app skeleton
Diffstat (limited to 'StoneIsland/platforms/ios/CordovaLib')
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDV.h41
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVAvailability.h92
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVAvailabilityDeprecated.h38
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegate.h50
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegateImpl.h36
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegateImpl.m180
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandQueue.h40
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandQueue.m211
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVConfigParser.h31
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVConfigParser.m88
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVDebug.h25
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVHandleOpenURL.h28
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVHandleOpenURL.m74
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVInvokedUrlCommand.h52
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVInvokedUrlCommand.m117
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON.h37
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON.m52
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON_private.h31
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON_private.m91
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVLocalStorage.h50
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVLocalStorage.m492
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVPlugin.h67
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVPlugin.m154
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVPluginResult.h71
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVPluginResult.m224
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVScreenOrientationDelegate.h28
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVShared.h22
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVTimer.h27
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVTimer.m123
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVURLProtocol.h29
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVURLProtocol.m213
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVUserAgentUtil.h27
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVUserAgentUtil.m122
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.h84
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.m1049
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVWebViewDelegate.h41
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVWebViewDelegate.m412
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVWhitelist.h34
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/CDVWhitelist.m285
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/NSArray+Comparisons.h27
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/NSArray+Comparisons.m43
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/NSData+Base64.h47
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/NSData+Base64.m308
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/NSDictionary+Extensions.h43
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/NSDictionary+Extensions.m159
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/NSMutableArray+QueueAdditions.h29
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/NSMutableArray+QueueAdditions.m58
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/UIDevice+Extensions.h32
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/Classes/UIDevice+Extensions.m47
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/CordovaLib.xcodeproj/project.pbxproj507
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/CordovaLib.xcodeproj/xcuserdata/jules.xcuserdatad/xcschemes/CordovaLib.xcscheme77
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/CordovaLib.xcodeproj/xcuserdata/jules.xcuserdatad/xcschemes/xcschememanagement.plist22
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/CordovaLib_Prefix.pch22
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/VERSION1
-rw-r--r--StoneIsland/platforms/ios/CordovaLib/cordova.js1810
55 files changed, 8100 insertions, 0 deletions
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDV.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDV.h
new file mode 100644
index 00000000..6cf592a0
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDV.h
@@ -0,0 +1,41 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVAvailability.h"
+
+#import "CDVPlugin.h"
+#import "CDVViewController.h"
+#import "CDVCommandDelegate.h"
+#import "CDVURLProtocol.h"
+#import "CDVInvokedUrlCommand.h"
+
+#import "CDVDebug.h"
+#import "CDVPluginResult.h"
+#import "CDVWhitelist.h"
+#import "CDVLocalStorage.h"
+#import "CDVScreenOrientationDelegate.h"
+#import "CDVTimer.h"
+
+#import "NSArray+Comparisons.h"
+#import "NSData+Base64.h"
+#import "NSDictionary+Extensions.h"
+#import "NSMutableArray+QueueAdditions.h"
+#import "UIDevice+Extensions.h"
+
+#import "CDVJSON.h"
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVAvailability.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVAvailability.h
new file mode 100644
index 00000000..71e20b97
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVAvailability.h
@@ -0,0 +1,92 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVAvailabilityDeprecated.h"
+
+#define __CORDOVA_IOS__
+
+#define __CORDOVA_0_9_6 906
+#define __CORDOVA_1_0_0 10000
+#define __CORDOVA_1_1_0 10100
+#define __CORDOVA_1_2_0 10200
+#define __CORDOVA_1_3_0 10300
+#define __CORDOVA_1_4_0 10400
+#define __CORDOVA_1_4_1 10401
+#define __CORDOVA_1_5_0 10500
+#define __CORDOVA_1_6_0 10600
+#define __CORDOVA_1_6_1 10601
+#define __CORDOVA_1_7_0 10700
+#define __CORDOVA_1_8_0 10800
+#define __CORDOVA_1_8_1 10801
+#define __CORDOVA_1_9_0 10900
+#define __CORDOVA_2_0_0 20000
+#define __CORDOVA_2_1_0 20100
+#define __CORDOVA_2_2_0 20200
+#define __CORDOVA_2_3_0 20300
+#define __CORDOVA_2_4_0 20400
+#define __CORDOVA_2_5_0 20500
+#define __CORDOVA_2_6_0 20600
+#define __CORDOVA_2_7_0 20700
+#define __CORDOVA_2_8_0 20800
+#define __CORDOVA_2_9_0 20900
+#define __CORDOVA_3_0_0 30000
+#define __CORDOVA_3_1_0 30100
+#define __CORDOVA_3_2_0 30200
+#define __CORDOVA_3_3_0 30300
+#define __CORDOVA_3_4_0 30400
+#define __CORDOVA_3_4_1 30401
+#define __CORDOVA_3_5_0 30500
+#define __CORDOVA_3_6_0 30600
+#define __CORDOVA_3_7_0 30700
+#define __CORDOVA_3_8_0 30800
+#define __CORDOVA_NA 99999 /* not available */
+
+/*
+ #if CORDOVA_VERSION_MIN_REQUIRED >= __CORDOVA_1_7_0
+ // do something when its at least 1.7.0
+ #else
+ // do something else (non 1.7.0)
+ #endif
+ */
+#ifndef CORDOVA_VERSION_MIN_REQUIRED
+ #define CORDOVA_VERSION_MIN_REQUIRED __CORDOVA_3_8_0
+#endif
+
+/*
+ Returns YES if it is at least version specified as NSString(X)
+ Usage:
+ if (IsAtLeastiOSVersion(@"5.1")) {
+ // do something for iOS 5.1 or greater
+ }
+ */
+#define IsAtLeastiOSVersion(X) ([[[UIDevice currentDevice] systemVersion] compare:X options:NSNumericSearch] != NSOrderedAscending)
+
+/* Return the string version of the decimal version */
+#define CDV_VERSION [NSString stringWithFormat:@"%d.%d.%d", \
+ (CORDOVA_VERSION_MIN_REQUIRED / 10000), \
+ (CORDOVA_VERSION_MIN_REQUIRED % 10000) / 100, \
+ (CORDOVA_VERSION_MIN_REQUIRED % 10000) % 100]
+
+// Enable this to log all exec() calls.
+#define CDV_ENABLE_EXEC_LOGGING 0
+#if CDV_ENABLE_EXEC_LOGGING
+ #define CDV_EXEC_LOG NSLog
+#else
+ #define CDV_EXEC_LOG(...) do {} while (NO)
+#endif
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVAvailabilityDeprecated.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVAvailabilityDeprecated.h
new file mode 100644
index 00000000..216b4c1d
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVAvailabilityDeprecated.h
@@ -0,0 +1,38 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+
+#import <UIKit/UIKit.h>
+
+#ifdef __clang__
+#define CDV_DEPRECATED(version, msg) __attribute__((deprecated("Deprecated in Cordova " #version ". " msg)))
+#else
+#define CDV_DEPRECATED(version, msg) __attribute__((deprecated()))
+#endif
+
+static inline BOOL CDV_IsIPad(void) CDV_DEPRECATED(3.7.0, "This will be removed in 4.0.0");
+static inline BOOL CDV_IsIPhone5(void) CDV_DEPRECATED(3.7.0, "This will be removed in 4.0.0");
+
+static inline BOOL CDV_IsIPad(void) {
+ return [[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)] && [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad;
+}
+
+static inline BOOL CDV_IsIPhone5(void) {
+ return ([[UIScreen mainScreen] bounds].size.width == 568 && [[UIScreen mainScreen] bounds].size.height == 320) || ([[UIScreen mainScreen] bounds].size.height == 568 && [[UIScreen mainScreen] bounds].size.width == 320);
+} \ No newline at end of file
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegate.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegate.h
new file mode 100644
index 00000000..04df6bc7
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegate.h
@@ -0,0 +1,50 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVAvailability.h"
+#import "CDVInvokedUrlCommand.h"
+
+@class CDVPlugin;
+@class CDVPluginResult;
+@class CDVWhitelist;
+
+@protocol CDVCommandDelegate <NSObject>
+
+@property (nonatomic, readonly) NSDictionary* settings;
+
+- (NSString*)pathForResource:(NSString*)resourcepath;
+- (id)getCommandInstance:(NSString*)pluginName;
+
+// Sends a plugin result to the JS. This is thread-safe.
+- (void)sendPluginResult:(CDVPluginResult*)result callbackId:(NSString*)callbackId;
+// Evaluates the given JS. This is thread-safe.
+- (void)evalJs:(NSString*)js;
+// Can be used to evaluate JS right away instead of scheduling it on the run-loop.
+// This is required for dispatch resign and pause events, but should not be used
+// without reason. Without the run-loop delay, alerts used in JS callbacks may result
+// in dead-lock. This method must be called from the UI thread.
+- (void)evalJs:(NSString*)js scheduledOnRunLoop:(BOOL)scheduledOnRunLoop;
+// Runs the given block on a background thread using a shared thread-pool.
+- (void)runInBackground:(void (^)())block;
+// Returns the User-Agent of the associated UIWebView.
+- (NSString*)userAgent;
+// Returns whether the given URL passes the white-list.
+- (BOOL)URLIsWhitelisted:(NSURL*)url;
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegateImpl.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegateImpl.h
new file mode 100644
index 00000000..05311343
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegateImpl.h
@@ -0,0 +1,36 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <UIKit/UIKit.h>
+#import "CDVCommandDelegate.h"
+
+@class CDVViewController;
+@class CDVCommandQueue;
+
+@interface CDVCommandDelegateImpl : NSObject <CDVCommandDelegate>{
+ @private
+ __weak CDVViewController* _viewController;
+ NSRegularExpression* _callbackIdPattern;
+ @protected
+ __weak CDVCommandQueue* _commandQueue;
+ BOOL _delayResponses;
+}
+- (id)initWithViewController:(CDVViewController*)viewController;
+- (void)flushCommandQueueWithDelayedJs;
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegateImpl.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegateImpl.m
new file mode 100644
index 00000000..9407e0a8
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegateImpl.m
@@ -0,0 +1,180 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVCommandDelegateImpl.h"
+#import "CDVJSON_private.h"
+#import "CDVCommandQueue.h"
+#import "CDVPluginResult.h"
+#import "CDVViewController.h"
+
+@implementation CDVCommandDelegateImpl
+
+- (id)initWithViewController:(CDVViewController*)viewController
+{
+ self = [super init];
+ if (self != nil) {
+ _viewController = viewController;
+ _commandQueue = _viewController.commandQueue;
+
+ NSError* err = nil;
+ _callbackIdPattern = [NSRegularExpression regularExpressionWithPattern:@"[^A-Za-z0-9._-]" options:0 error:&err];
+ if (err != nil) {
+ // Couldn't initialize Regex
+ NSLog(@"Error: Couldn't initialize regex");
+ _callbackIdPattern = nil;
+ }
+ }
+ return self;
+}
+
+- (NSString*)pathForResource:(NSString*)resourcepath
+{
+ NSBundle* mainBundle = [NSBundle mainBundle];
+ NSMutableArray* directoryParts = [NSMutableArray arrayWithArray:[resourcepath componentsSeparatedByString:@"/"]];
+ NSString* filename = [directoryParts lastObject];
+
+ [directoryParts removeLastObject];
+
+ NSString* directoryPartsJoined = [directoryParts componentsJoinedByString:@"/"];
+ NSString* directoryStr = _viewController.wwwFolderName;
+
+ if ([directoryPartsJoined length] > 0) {
+ directoryStr = [NSString stringWithFormat:@"%@/%@", _viewController.wwwFolderName, [directoryParts componentsJoinedByString:@"/"]];
+ }
+
+ return [mainBundle pathForResource:filename ofType:@"" inDirectory:directoryStr];
+}
+
+- (void)flushCommandQueueWithDelayedJs
+{
+ _delayResponses = YES;
+ [_commandQueue executePending];
+ _delayResponses = NO;
+}
+
+- (void)evalJsHelper2:(NSString*)js
+{
+ CDV_EXEC_LOG(@"Exec: evalling: %@", [js substringToIndex:MIN([js length], 160)]);
+ NSString* commandsJSON = [_viewController.webView stringByEvaluatingJavaScriptFromString:js];
+ if ([commandsJSON length] > 0) {
+ CDV_EXEC_LOG(@"Exec: Retrieved new exec messages by chaining.");
+ }
+
+ [_commandQueue enqueueCommandBatch:commandsJSON];
+ [_commandQueue executePending];
+}
+
+- (void)evalJsHelper:(NSString*)js
+{
+ // Cycle the run-loop before executing the JS.
+ // For _delayResponses -
+ // This ensures that we don't eval JS during the middle of an existing JS
+ // function (possible since UIWebViewDelegate callbacks can be synchronous).
+ // For !isMainThread -
+ // It's a hard error to eval on the non-UI thread.
+ // For !_commandQueue.currentlyExecuting -
+ // This works around a bug where sometimes alerts() within callbacks can cause
+ // dead-lock.
+ // If the commandQueue is currently executing, then we know that it is safe to
+ // execute the callback immediately.
+ // Using (dispatch_get_main_queue()) does *not* fix deadlocks for some reason,
+ // but performSelectorOnMainThread: does.
+ if (_delayResponses || ![NSThread isMainThread] || !_commandQueue.currentlyExecuting) {
+ [self performSelectorOnMainThread:@selector(evalJsHelper2:) withObject:js waitUntilDone:NO];
+ } else {
+ [self evalJsHelper2:js];
+ }
+}
+
+- (BOOL)isValidCallbackId:(NSString*)callbackId
+{
+ if ((callbackId == nil) || (_callbackIdPattern == nil)) {
+ return NO;
+ }
+
+ // Disallow if too long or if any invalid characters were found.
+ if (([callbackId length] > 100) || [_callbackIdPattern firstMatchInString:callbackId options:0 range:NSMakeRange(0, [callbackId length])]) {
+ return NO;
+ }
+ return YES;
+}
+
+- (void)sendPluginResult:(CDVPluginResult*)result callbackId:(NSString*)callbackId
+{
+ CDV_EXEC_LOG(@"Exec(%@): Sending result. Status=%@", callbackId, result.status);
+ // This occurs when there is are no win/fail callbacks for the call.
+ if ([@"INVALID" isEqualToString : callbackId]) {
+ return;
+ }
+ // This occurs when the callback id is malformed.
+ if (![self isValidCallbackId:callbackId]) {
+ NSLog(@"Invalid callback id received by sendPluginResult");
+ return;
+ }
+ int status = [result.status intValue];
+ BOOL keepCallback = [result.keepCallback boolValue];
+ NSString* argumentsAsJSON = [result argumentsAsJSON];
+
+ NSString* js = [NSString stringWithFormat:@"cordova.require('cordova/exec').nativeCallback('%@',%d,%@,%d)", callbackId, status, argumentsAsJSON, keepCallback];
+
+ [self evalJsHelper:js];
+}
+
+- (void)evalJs:(NSString*)js
+{
+ [self evalJs:js scheduledOnRunLoop:YES];
+}
+
+- (void)evalJs:(NSString*)js scheduledOnRunLoop:(BOOL)scheduledOnRunLoop
+{
+ js = [NSString stringWithFormat:@"cordova.require('cordova/exec').nativeEvalAndFetch(function(){%@})", js];
+ if (scheduledOnRunLoop) {
+ [self evalJsHelper:js];
+ } else {
+ [self evalJsHelper2:js];
+ }
+}
+
+- (id)getCommandInstance:(NSString*)pluginName
+{
+ return [_viewController getCommandInstance:pluginName];
+}
+
+- (void)runInBackground:(void (^)())block
+{
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);
+}
+
+- (NSString*)userAgent
+{
+ return [_viewController userAgent];
+}
+
+- (BOOL)URLIsWhitelisted:(NSURL*)url
+{
+ return ![_viewController.whitelist schemeIsAllowed:[url scheme]] ||
+ [_viewController.whitelist URLIsAllowed:url logFailure:NO];
+}
+
+- (NSDictionary*)settings
+{
+ return _viewController.settings;
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandQueue.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandQueue.h
new file mode 100644
index 00000000..3329078a
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandQueue.h
@@ -0,0 +1,40 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@class CDVInvokedUrlCommand;
+@class CDVViewController;
+
+@interface CDVCommandQueue : NSObject
+
+@property (nonatomic, readonly) BOOL currentlyExecuting;
+
+- (id)initWithViewController:(CDVViewController*)viewController;
+- (void)dispose;
+
+- (void)resetRequestId;
+- (void)enqueueCommandBatch:(NSString*)batchJSON;
+
+- (void)processXhrExecBridgePoke:(NSNumber*)requestId;
+- (void)fetchCommandsFromJs;
+- (void)executePending;
+- (BOOL)execute:(CDVInvokedUrlCommand*)command;
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandQueue.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandQueue.m
new file mode 100644
index 00000000..48264b2a
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandQueue.m
@@ -0,0 +1,211 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#include <objc/message.h>
+#import "CDV.h"
+#import "CDVCommandQueue.h"
+#import "CDVViewController.h"
+#import "CDVCommandDelegateImpl.h"
+#import "CDVJSON_private.h"
+
+// Parse JS on the main thread if it's shorter than this.
+static const NSInteger JSON_SIZE_FOR_MAIN_THREAD = 4 * 1024; // Chosen arbitrarily.
+// Execute multiple commands in one go until this many seconds have passed.
+static const double MAX_EXECUTION_TIME = .008; // Half of a 60fps frame.
+
+@interface CDVCommandQueue () {
+ NSInteger _lastCommandQueueFlushRequestId;
+ __weak CDVViewController* _viewController;
+ NSMutableArray* _queue;
+ NSTimeInterval _startExecutionTime;
+}
+@end
+
+@implementation CDVCommandQueue
+
+- (BOOL)currentlyExecuting
+{
+ return _startExecutionTime > 0;
+}
+
+- (id)initWithViewController:(CDVViewController*)viewController
+{
+ self = [super init];
+ if (self != nil) {
+ _viewController = viewController;
+ _queue = [[NSMutableArray alloc] init];
+ }
+ return self;
+}
+
+- (void)dispose
+{
+ // TODO(agrieve): Make this a zeroing weak ref once we drop support for 4.3.
+ _viewController = nil;
+}
+
+- (void)resetRequestId
+{
+ _lastCommandQueueFlushRequestId = 0;
+}
+
+- (void)enqueueCommandBatch:(NSString*)batchJSON
+{
+ if ([batchJSON length] > 0) {
+ NSMutableArray* commandBatchHolder = [[NSMutableArray alloc] init];
+ [_queue addObject:commandBatchHolder];
+ if ([batchJSON length] < JSON_SIZE_FOR_MAIN_THREAD) {
+ [commandBatchHolder addObject:[batchJSON cdv_JSONObject]];
+ } else {
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^() {
+ NSMutableArray* result = [batchJSON cdv_JSONObject];
+ @synchronized(commandBatchHolder) {
+ [commandBatchHolder addObject:result];
+ }
+ [self performSelectorOnMainThread:@selector(executePending) withObject:nil waitUntilDone:NO];
+ });
+ }
+ }
+}
+
+- (void)processXhrExecBridgePoke:(NSNumber*)requestId
+{
+ NSInteger rid = [requestId integerValue];
+
+ // An ID of 1 is a special case because that signifies the first request of
+ // the page. Since resetRequestId is called from webViewDidStartLoad, and the
+ // JS context at the time of webViewDidStartLoad is still that of the previous
+ // page, it's possible for requests from the previous page to come in after this
+ // point. We ignore these by enforcing that ID=1 be the first ID.
+ if ((_lastCommandQueueFlushRequestId == 0) && (rid != 1)) {
+ CDV_EXEC_LOG(@"Exec: Ignoring exec request from previous page.");
+ return;
+ }
+
+ // Use the request ID to determine if we've already flushed for this request.
+ // This is required only because the NSURLProtocol enqueues the same request
+ // multiple times.
+ if (rid > _lastCommandQueueFlushRequestId) {
+ _lastCommandQueueFlushRequestId = [requestId integerValue];
+ [self fetchCommandsFromJs];
+ [self executePending];
+ }
+}
+
+- (void)fetchCommandsFromJs
+{
+ // Grab all the queued commands from the JS side.
+ NSString* queuedCommandsJSON = [_viewController.webView stringByEvaluatingJavaScriptFromString:
+ @"cordova.require('cordova/exec').nativeFetchMessages()"];
+
+ CDV_EXEC_LOG(@"Exec: Flushed JS->native queue (hadCommands=%d).", [queuedCommandsJSON length] > 0);
+ [self enqueueCommandBatch:queuedCommandsJSON];
+}
+
+- (void)executePending
+{
+ // Make us re-entrant-safe.
+ if (_startExecutionTime > 0) {
+ return;
+ }
+ @try {
+ _startExecutionTime = [NSDate timeIntervalSinceReferenceDate];
+
+ while ([_queue count] > 0) {
+ NSMutableArray* commandBatchHolder = _queue[0];
+ NSMutableArray* commandBatch = nil;
+ @synchronized(commandBatchHolder) {
+ // If the next-up command is still being decoded, wait for it.
+ if ([commandBatchHolder count] == 0) {
+ break;
+ }
+ commandBatch = commandBatchHolder[0];
+ }
+
+ while ([commandBatch count] > 0) {
+ @autoreleasepool {
+ // Execute the commands one-at-a-time.
+ NSArray* jsonEntry = [commandBatch dequeue];
+ if ([commandBatch count] == 0) {
+ [_queue removeObjectAtIndex:0];
+ }
+ CDVInvokedUrlCommand* command = [CDVInvokedUrlCommand commandFromJson:jsonEntry];
+ CDV_EXEC_LOG(@"Exec(%@): Calling %@.%@", command.callbackId, command.className, command.methodName);
+
+ if (![self execute:command]) {
+#ifdef DEBUG
+ NSString* commandJson = [jsonEntry cdv_JSONString];
+ static NSUInteger maxLogLength = 1024;
+ NSString* commandString = ([commandJson length] > maxLogLength) ?
+ [NSString stringWithFormat:@"%@[...]", [commandJson substringToIndex:maxLogLength]] :
+ commandJson;
+
+ DLog(@"FAILED pluginJSON = %@", commandString);
+#endif
+ }
+ }
+
+ // Yield if we're taking too long.
+ if (([_queue count] > 0) && ([NSDate timeIntervalSinceReferenceDate] - _startExecutionTime > MAX_EXECUTION_TIME)) {
+ [self performSelector:@selector(executePending) withObject:nil afterDelay:0];
+ return;
+ }
+ }
+ }
+ } @finally
+ {
+ _startExecutionTime = 0;
+ }
+}
+
+- (BOOL)execute:(CDVInvokedUrlCommand*)command
+{
+ if ((command.className == nil) || (command.methodName == nil)) {
+ NSLog(@"ERROR: Classname and/or methodName not found for command.");
+ return NO;
+ }
+
+ // Fetch an instance of this class
+ CDVPlugin* obj = [_viewController.commandDelegate getCommandInstance:command.className];
+
+ if (!([obj isKindOfClass:[CDVPlugin class]])) {
+ NSLog(@"ERROR: Plugin '%@' not found, or is not a CDVPlugin. Check your plugin mapping in config.xml.", command.className);
+ return NO;
+ }
+ BOOL retVal = YES;
+ double started = [[NSDate date] timeIntervalSince1970] * 1000.0;
+ // Find the proper selector to call.
+ NSString* methodName = [NSString stringWithFormat:@"%@:", command.methodName];
+ SEL normalSelector = NSSelectorFromString(methodName);
+ if ([obj respondsToSelector:normalSelector]) {
+ // [obj performSelector:normalSelector withObject:command];
+ ((void (*)(id, SEL, id))objc_msgSend)(obj, normalSelector, command);
+ } else {
+ // There's no method to call, so throw an error.
+ NSLog(@"ERROR: Method '%@' not defined in Plugin '%@'", methodName, command.className);
+ retVal = NO;
+ }
+ double elapsed = [[NSDate date] timeIntervalSince1970] * 1000.0 - started;
+ if (elapsed > 10) {
+ NSLog(@"THREAD WARNING: ['%@'] took '%f' ms. Plugin should use a background thread.", command.className, elapsed);
+ }
+ return retVal;
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVConfigParser.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVConfigParser.h
new file mode 100644
index 00000000..2e06c88f
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVConfigParser.h
@@ -0,0 +1,31 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+@interface CDVConfigParser : NSObject <NSXMLParserDelegate>
+{
+ NSString* featureName;
+}
+
+@property (nonatomic, readonly, strong) NSMutableDictionary* pluginsDict;
+@property (nonatomic, readonly, strong) NSMutableDictionary* settings;
+@property (nonatomic, readonly, strong) NSMutableArray* whitelistHosts;
+@property (nonatomic, readonly, strong) NSMutableArray* startupPluginNames;
+@property (nonatomic, readonly, strong) NSString* startPage;
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVConfigParser.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVConfigParser.m
new file mode 100644
index 00000000..4b73b60a
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVConfigParser.m
@@ -0,0 +1,88 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVConfigParser.h"
+
+@interface CDVConfigParser ()
+
+@property (nonatomic, readwrite, strong) NSMutableDictionary* pluginsDict;
+@property (nonatomic, readwrite, strong) NSMutableDictionary* settings;
+@property (nonatomic, readwrite, strong) NSMutableArray* whitelistHosts;
+@property (nonatomic, readwrite, strong) NSMutableArray* startupPluginNames;
+@property (nonatomic, readwrite, strong) NSString* startPage;
+
+@end
+
+@implementation CDVConfigParser
+
+@synthesize pluginsDict, settings, whitelistHosts, startPage, startupPluginNames;
+
+- (id)init
+{
+ self = [super init];
+ if (self != nil) {
+ self.pluginsDict = [[NSMutableDictionary alloc] initWithCapacity:30];
+ self.settings = [[NSMutableDictionary alloc] initWithCapacity:30];
+ self.whitelistHosts = [[NSMutableArray alloc] initWithCapacity:30];
+ [self.whitelistHosts addObject:@"file:///*"];
+ [self.whitelistHosts addObject:@"content:///*"];
+ [self.whitelistHosts addObject:@"data:///*"];
+ self.startupPluginNames = [[NSMutableArray alloc] initWithCapacity:8];
+ featureName = nil;
+ }
+ return self;
+}
+
+- (void)parser:(NSXMLParser*)parser didStartElement:(NSString*)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString*)qualifiedName attributes:(NSDictionary*)attributeDict
+{
+ if ([elementName isEqualToString:@"preference"]) {
+ settings[[attributeDict[@"name"] lowercaseString]] = attributeDict[@"value"];
+ } else if ([elementName isEqualToString:@"feature"]) { // store feature name to use with correct parameter set
+ featureName = [attributeDict[@"name"] lowercaseString];
+ } else if ((featureName != nil) && [elementName isEqualToString:@"param"]) {
+ NSString* paramName = [attributeDict[@"name"] lowercaseString];
+ id value = attributeDict[@"value"];
+ if ([paramName isEqualToString:@"ios-package"]) {
+ pluginsDict[featureName] = value;
+ }
+ BOOL paramIsOnload = ([paramName isEqualToString:@"onload"] && [@"true" isEqualToString : value]);
+ BOOL attribIsOnload = [@"true" isEqualToString :[attributeDict[@"onload"] lowercaseString]];
+ if (paramIsOnload || attribIsOnload) {
+ [self.startupPluginNames addObject:featureName];
+ }
+ } else if ([elementName isEqualToString:@"access"]) {
+ [whitelistHosts addObject:attributeDict[@"origin"]];
+ } else if ([elementName isEqualToString:@"content"]) {
+ self.startPage = attributeDict[@"src"];
+ }
+}
+
+- (void)parser:(NSXMLParser*)parser didEndElement:(NSString*)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString*)qualifiedName
+{
+ if ([elementName isEqualToString:@"feature"]) { // no longer handling a feature so release
+ featureName = nil;
+ }
+}
+
+- (void)parser:(NSXMLParser*)parser parseErrorOccurred:(NSError*)parseError
+{
+ NSAssert(NO, @"config.xml parse error line %ld col %ld", (long)[parser lineNumber], (long)[parser columnNumber]);
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVDebug.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVDebug.h
new file mode 100644
index 00000000..4a0d9f92
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVDebug.h
@@ -0,0 +1,25 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#ifdef DEBUG
+ #define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
+#else
+ #define DLog(...)
+#endif
+#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVHandleOpenURL.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVHandleOpenURL.h
new file mode 100644
index 00000000..24f461f3
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVHandleOpenURL.h
@@ -0,0 +1,28 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVPlugin.h"
+
+@interface CDVHandleOpenURL : CDVPlugin
+
+@property (nonatomic, strong) NSURL* url;
+@property (nonatomic, assign) BOOL pageLoaded;
+
+@end
+
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVHandleOpenURL.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVHandleOpenURL.m
new file mode 100644
index 00000000..e5dcdd5a
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVHandleOpenURL.m
@@ -0,0 +1,74 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVHandleOpenURL.h"
+#import "CDV.h"
+
+@implementation CDVHandleOpenURL
+
+- (void)pluginInitialize
+{
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationLaunchedWithUrl:) name:CDVPluginHandleOpenURLNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationPageDidLoad:) name:CDVPageDidLoadNotification object:nil];
+}
+
+- (void)applicationLaunchedWithUrl:(NSNotification*)notification
+{
+ NSURL *url = [notification object];
+ self.url = url;
+
+ // warm-start handler
+ if (self.pageLoaded) {
+ [self processOpenUrl:self.url pageLoaded:YES];
+ self.url = nil;
+ }
+}
+
+- (void)applicationPageDidLoad:(NSNotification*)notification
+{
+ // cold-start handler
+
+ self.pageLoaded = YES;
+
+ if (self.url) {
+ [self processOpenUrl:self.url pageLoaded:YES];
+ self.url = nil;
+ }
+}
+
+- (void)processOpenUrl:(NSURL*)url pageLoaded:(BOOL)pageLoaded
+{
+ if (!pageLoaded) {
+ // query the webview for readystate
+ NSString* readyState = [self.webView stringByEvaluatingJavaScriptFromString:@"document.readyState"];
+ pageLoaded = [readyState isEqualToString:@"loaded"] || [readyState isEqualToString:@"complete"];
+ }
+
+ if (pageLoaded) {
+ // calls into javascript global function 'handleOpenURL'
+ NSString* jsString = [NSString stringWithFormat:@"document.addEventListener('deviceready',function(){if (typeof handleOpenURL === 'function') { handleOpenURL(\"%@\");}});", url];
+ [self.webView stringByEvaluatingJavaScriptFromString:jsString];
+ } else {
+ // save for when page has loaded
+ self.url = url;
+ }
+}
+
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVInvokedUrlCommand.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVInvokedUrlCommand.h
new file mode 100644
index 00000000..993e0a28
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVInvokedUrlCommand.h
@@ -0,0 +1,52 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface CDVInvokedUrlCommand : NSObject {
+ NSString* _callbackId;
+ NSString* _className;
+ NSString* _methodName;
+ NSArray* _arguments;
+}
+
+@property (nonatomic, readonly) NSArray* arguments;
+@property (nonatomic, readonly) NSString* callbackId;
+@property (nonatomic, readonly) NSString* className;
+@property (nonatomic, readonly) NSString* methodName;
+
++ (CDVInvokedUrlCommand*)commandFromJson:(NSArray*)jsonEntry;
+
+- (id)initWithArguments:(NSArray*)arguments
+ callbackId:(NSString*)callbackId
+ className:(NSString*)className
+ methodName:(NSString*)methodName;
+
+- (id)initFromJson:(NSArray*)jsonEntry;
+
+// Returns the argument at the given index.
+// If index >= the number of arguments, returns nil.
+// If the argument at the given index is NSNull, returns nil.
+- (id)argumentAtIndex:(NSUInteger)index;
+// Same as above, but returns defaultValue instead of nil.
+- (id)argumentAtIndex:(NSUInteger)index withDefault:(id)defaultValue;
+// Same as above, but returns defaultValue instead of nil, and if the argument is not of the expected class, returns defaultValue
+- (id)argumentAtIndex:(NSUInteger)index withDefault:(id)defaultValue andClass:(Class)aClass;
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVInvokedUrlCommand.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVInvokedUrlCommand.m
new file mode 100644
index 00000000..3a5e8e75
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVInvokedUrlCommand.m
@@ -0,0 +1,117 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVInvokedUrlCommand.h"
+#import "CDVJSON_private.h"
+#import "NSData+Base64.h"
+
+@implementation CDVInvokedUrlCommand
+
+@synthesize arguments = _arguments;
+@synthesize callbackId = _callbackId;
+@synthesize className = _className;
+@synthesize methodName = _methodName;
+
++ (CDVInvokedUrlCommand*)commandFromJson:(NSArray*)jsonEntry
+{
+ return [[CDVInvokedUrlCommand alloc] initFromJson:jsonEntry];
+}
+
+- (id)initFromJson:(NSArray*)jsonEntry
+{
+ id tmp = [jsonEntry objectAtIndex:0];
+ NSString* callbackId = tmp == [NSNull null] ? nil : tmp;
+ NSString* className = [jsonEntry objectAtIndex:1];
+ NSString* methodName = [jsonEntry objectAtIndex:2];
+ NSMutableArray* arguments = [jsonEntry objectAtIndex:3];
+
+ return [self initWithArguments:arguments
+ callbackId:callbackId
+ className:className
+ methodName:methodName];
+}
+
+- (id)initWithArguments:(NSArray*)arguments
+ callbackId:(NSString*)callbackId
+ className:(NSString*)className
+ methodName:(NSString*)methodName
+{
+ self = [super init];
+ if (self != nil) {
+ _arguments = arguments;
+ _callbackId = callbackId;
+ _className = className;
+ _methodName = methodName;
+ }
+ [self massageArguments];
+ return self;
+}
+
+- (void)massageArguments
+{
+ NSMutableArray* newArgs = nil;
+
+ for (NSUInteger i = 0, count = [_arguments count]; i < count; ++i) {
+ id arg = [_arguments objectAtIndex:i];
+ if (![arg isKindOfClass:[NSDictionary class]]) {
+ continue;
+ }
+ NSDictionary* dict = arg;
+ NSString* type = [dict objectForKey:@"CDVType"];
+ if (!type || ![type isEqualToString:@"ArrayBuffer"]) {
+ continue;
+ }
+ NSString* data = [dict objectForKey:@"data"];
+ if (!data) {
+ continue;
+ }
+ if (newArgs == nil) {
+ newArgs = [NSMutableArray arrayWithArray:_arguments];
+ _arguments = newArgs;
+ }
+ [newArgs replaceObjectAtIndex:i withObject:[NSData cdv_dataFromBase64String:data]];
+ }
+}
+
+- (id)argumentAtIndex:(NSUInteger)index
+{
+ return [self argumentAtIndex:index withDefault:nil];
+}
+
+- (id)argumentAtIndex:(NSUInteger)index withDefault:(id)defaultValue
+{
+ return [self argumentAtIndex:index withDefault:defaultValue andClass:nil];
+}
+
+- (id)argumentAtIndex:(NSUInteger)index withDefault:(id)defaultValue andClass:(Class)aClass
+{
+ if (index >= [_arguments count]) {
+ return defaultValue;
+ }
+ id ret = [_arguments objectAtIndex:index];
+ if (ret == [NSNull null]) {
+ ret = defaultValue;
+ }
+ if ((aClass != nil) && ![ret isKindOfClass:aClass]) {
+ ret = defaultValue;
+ }
+ return ret;
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON.h
new file mode 100644
index 00000000..ede708f9
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON.h
@@ -0,0 +1,37 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVAvailabilityDeprecated.h"
+
+@interface NSArray (CDVJSONSerializing)
+- (NSString*)JSONString CDV_DEPRECATED(3.8 .0, "Use NSJSONSerialization instead.");
+
+@end
+
+@interface NSDictionary (CDVJSONSerializing)
+- (NSString*)JSONString CDV_DEPRECATED(3.8 .0, "Use NSJSONSerialization instead.");
+
+@end
+
+@interface NSString (CDVJSONSerializing)
+- (id)JSONObject CDV_DEPRECATED(3.8 .0, "Use NSJSONSerialization instead.");
+
+- (id)JSONFragment CDV_DEPRECATED(3.8 .0, "Use NSJSONSerialization instead.");
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON.m
new file mode 100644
index 00000000..85db545a
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON.m
@@ -0,0 +1,52 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVJSON_private.h"
+
+@implementation NSArray (CDVJSONSerializing)
+
+- (NSString*)JSONString
+{
+ return [self cdv_JSONString];
+}
+
+@end
+
+@implementation NSDictionary (CDVJSONSerializing)
+
+- (NSString*)JSONString
+{
+ return [self cdv_JSONString];
+}
+
+@end
+
+@implementation NSString (CDVJSONSerializing)
+
+- (id)JSONObject
+{
+ return [self cdv_JSONObject];
+}
+
+- (id)JSONFragment
+{
+ return [self cdv_JSONFragment];
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON_private.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON_private.h
new file mode 100644
index 00000000..afb5cc66
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON_private.h
@@ -0,0 +1,31 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+@interface NSArray (CDVJSONSerializingPrivate)
+- (NSString*)cdv_JSONString;
+@end
+
+@interface NSDictionary (CDVJSONSerializingPrivate)
+- (NSString*)cdv_JSONString;
+@end
+
+@interface NSString (CDVJSONSerializingPrivate)
+- (id)cdv_JSONObject;
+- (id)cdv_JSONFragment;
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON_private.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON_private.m
new file mode 100644
index 00000000..53856806
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON_private.m
@@ -0,0 +1,91 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVJSON_private.h"
+#import <Foundation/NSJSONSerialization.h>
+
+@implementation NSArray (CDVJSONSerializingPrivate)
+
+- (NSString*)cdv_JSONString
+{
+ NSError* error = nil;
+ NSData* jsonData = [NSJSONSerialization dataWithJSONObject:self
+ options:0
+ error:&error];
+
+ if (error != nil) {
+ NSLog(@"NSArray JSONString error: %@", [error localizedDescription]);
+ return nil;
+ } else {
+ return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
+ }
+}
+
+@end
+
+@implementation NSDictionary (CDVJSONSerializingPrivate)
+
+- (NSString*)cdv_JSONString
+{
+ NSError* error = nil;
+ NSData* jsonData = [NSJSONSerialization dataWithJSONObject:self
+ options:NSJSONWritingPrettyPrinted
+ error:&error];
+
+ if (error != nil) {
+ NSLog(@"NSDictionary JSONString error: %@", [error localizedDescription]);
+ return nil;
+ } else {
+ return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
+ }
+}
+
+@end
+
+@implementation NSString (CDVJSONSerializingPrivate)
+
+- (id)cdv_JSONObject
+{
+ NSError* error = nil;
+ id object = [NSJSONSerialization JSONObjectWithData:[self dataUsingEncoding:NSUTF8StringEncoding]
+ options:NSJSONReadingMutableContainers
+ error:&error];
+
+ if (error != nil) {
+ NSLog(@"NSString JSONObject error: %@", [error localizedDescription]);
+ }
+
+ return object;
+}
+
+- (id)cdv_JSONFragment
+{
+ NSError* error = nil;
+ id object = [NSJSONSerialization JSONObjectWithData:[self dataUsingEncoding:NSUTF8StringEncoding]
+ options:NSJSONReadingAllowFragments
+ error:&error];
+
+ if (error != nil) {
+ NSLog(@"NSString JSONObject error: %@", [error localizedDescription]);
+ }
+
+ return object;
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVLocalStorage.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVLocalStorage.h
new file mode 100644
index 00000000..dec6ab3b
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVLocalStorage.h
@@ -0,0 +1,50 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVPlugin.h"
+
+#define kCDVLocalStorageErrorDomain @"kCDVLocalStorageErrorDomain"
+#define kCDVLocalStorageFileOperationError 1
+
+@interface CDVLocalStorage : CDVPlugin
+
+@property (nonatomic, readonly, strong) NSMutableArray* backupInfo;
+
+- (BOOL)shouldBackup;
+- (BOOL)shouldRestore;
+- (void)backup:(CDVInvokedUrlCommand*)command;
+- (void)restore:(CDVInvokedUrlCommand*)command;
+
++ (void)__fixupDatabaseLocationsWithBackupType:(NSString*)backupType;
+// Visible for testing.
++ (BOOL)__verifyAndFixDatabaseLocationsWithAppPlistDict:(NSMutableDictionary*)appPlistDict
+ bundlePath:(NSString*)bundlePath
+ fileManager:(NSFileManager*)fileManager;
+@end
+
+@interface CDVBackupInfo : NSObject
+
+@property (nonatomic, copy) NSString* original;
+@property (nonatomic, copy) NSString* backup;
+@property (nonatomic, copy) NSString* label;
+
+- (BOOL)shouldBackup;
+- (BOOL)shouldRestore;
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVLocalStorage.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVLocalStorage.m
new file mode 100644
index 00000000..8aec403b
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVLocalStorage.m
@@ -0,0 +1,492 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVLocalStorage.h"
+#import "CDV.h"
+
+@interface CDVLocalStorage ()
+
+@property (nonatomic, readwrite, strong) NSMutableArray* backupInfo; // array of CDVBackupInfo objects
+@property (nonatomic, readwrite, weak) id <UIWebViewDelegate> webviewDelegate;
+
+@end
+
+@implementation CDVLocalStorage
+
+@synthesize backupInfo, webviewDelegate;
+
+- (void)pluginInitialize
+{
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onResignActive)
+ name:UIApplicationWillResignActiveNotification object:nil];
+ BOOL cloudBackup = [@"cloud" isEqualToString : self.commandDelegate.settings[[@"BackupWebStorage" lowercaseString]]];
+
+ self.backupInfo = [[self class] createBackupInfoWithCloudBackup:cloudBackup];
+}
+
+#pragma mark -
+#pragma mark Plugin interface methods
+
++ (NSMutableArray*)createBackupInfoWithTargetDir:(NSString*)targetDir backupDir:(NSString*)backupDir targetDirNests:(BOOL)targetDirNests backupDirNests:(BOOL)backupDirNests rename:(BOOL)rename
+{
+ /*
+ This "helper" does so much work and has so many options it would probably be clearer to refactor the whole thing.
+ Basically, there are three database locations:
+
+ 1. "Normal" dir -- LIB/<nested dires WebKit/LocalStorage etc>/<normal filenames>
+ 2. "Caches" dir -- LIB/Caches/<normal filenames>
+ 3. "Backup" dir -- DOC/Backups/<renamed filenames>
+
+ And between these three, there are various migration paths, most of which only consider 2 of the 3, which is why this helper is based on 2 locations and has a notion of "direction".
+ */
+ NSMutableArray* backupInfo = [NSMutableArray arrayWithCapacity:3];
+
+ NSString* original;
+ NSString* backup;
+ CDVBackupInfo* backupItem;
+
+ // ////////// LOCALSTORAGE
+
+ original = [targetDir stringByAppendingPathComponent:targetDirNests ? @"WebKit/LocalStorage/file__0.localstorage":@"file__0.localstorage"];
+ backup = [backupDir stringByAppendingPathComponent:(backupDirNests ? @"WebKit/LocalStorage" : @"")];
+ backup = [backup stringByAppendingPathComponent:(rename ? @"localstorage.appdata.db" : @"file__0.localstorage")];
+
+ backupItem = [[CDVBackupInfo alloc] init];
+ backupItem.backup = backup;
+ backupItem.original = original;
+ backupItem.label = @"localStorage database";
+
+ [backupInfo addObject:backupItem];
+
+ // ////////// WEBSQL MAIN DB
+
+ original = [targetDir stringByAppendingPathComponent:targetDirNests ? @"WebKit/LocalStorage/Databases.db":@"Databases.db"];
+ backup = [backupDir stringByAppendingPathComponent:(backupDirNests ? @"WebKit/LocalStorage" : @"")];
+ backup = [backup stringByAppendingPathComponent:(rename ? @"websqlmain.appdata.db" : @"Databases.db")];
+
+ backupItem = [[CDVBackupInfo alloc] init];
+ backupItem.backup = backup;
+ backupItem.original = original;
+ backupItem.label = @"websql main database";
+
+ [backupInfo addObject:backupItem];
+
+ // ////////// WEBSQL DATABASES
+
+ original = [targetDir stringByAppendingPathComponent:targetDirNests ? @"WebKit/LocalStorage/file__0":@"file__0"];
+ backup = [backupDir stringByAppendingPathComponent:(backupDirNests ? @"WebKit/LocalStorage" : @"")];
+ backup = [backup stringByAppendingPathComponent:(rename ? @"websqldbs.appdata.db" : @"file__0")];
+
+ backupItem = [[CDVBackupInfo alloc] init];
+ backupItem.backup = backup;
+ backupItem.original = original;
+ backupItem.label = @"websql databases";
+
+ [backupInfo addObject:backupItem];
+
+ return backupInfo;
+}
+
++ (NSMutableArray*)createBackupInfoWithCloudBackup:(BOOL)cloudBackup
+{
+ // create backup info from backup folder to caches folder
+ NSString* appLibraryFolder = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
+ NSString* appDocumentsFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
+ NSString* cacheFolder = [appLibraryFolder stringByAppendingPathComponent:@"Caches"];
+ NSString* backupsFolder = [appDocumentsFolder stringByAppendingPathComponent:@"Backups"];
+
+ // create the backups folder, if needed
+ [[NSFileManager defaultManager] createDirectoryAtPath:backupsFolder withIntermediateDirectories:YES attributes:nil error:nil];
+
+ [self addSkipBackupAttributeToItemAtURL:[NSURL fileURLWithPath:backupsFolder] skip:!cloudBackup];
+
+ return [self createBackupInfoWithTargetDir:cacheFolder backupDir:backupsFolder targetDirNests:NO backupDirNests:NO rename:YES];
+}
+
++ (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL*)URL skip:(BOOL)skip
+{
+ NSAssert(IsAtLeastiOSVersion(@"5.1"), @"Cannot mark files for NSURLIsExcludedFromBackupKey on iOS less than 5.1");
+
+ NSError* error = nil;
+ BOOL success = [URL setResourceValue:[NSNumber numberWithBool:skip] forKey:NSURLIsExcludedFromBackupKey error:&error];
+ if (!success) {
+ NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
+ }
+ return success;
+}
+
++ (BOOL)copyFrom:(NSString*)src to:(NSString*)dest error:(NSError* __autoreleasing*)error
+{
+ NSFileManager* fileManager = [NSFileManager defaultManager];
+
+ if (![fileManager fileExistsAtPath:src]) {
+ NSString* errorString = [NSString stringWithFormat:@"%@ file does not exist.", src];
+ if (error != NULL) {
+ (*error) = [NSError errorWithDomain:kCDVLocalStorageErrorDomain
+ code:kCDVLocalStorageFileOperationError
+ userInfo:[NSDictionary dictionaryWithObject:errorString
+ forKey:NSLocalizedDescriptionKey]];
+ }
+ return NO;
+ }
+
+ // generate unique filepath in temp directory
+ CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
+ CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
+ NSString* tempBackup = [[NSTemporaryDirectory() stringByAppendingPathComponent:(__bridge NSString*)uuidString] stringByAppendingPathExtension:@"bak"];
+ CFRelease(uuidString);
+ CFRelease(uuidRef);
+
+ BOOL destExists = [fileManager fileExistsAtPath:dest];
+
+ // backup the dest
+ if (destExists && ![fileManager copyItemAtPath:dest toPath:tempBackup error:error]) {
+ return NO;
+ }
+
+ // remove the dest
+ if (destExists && ![fileManager removeItemAtPath:dest error:error]) {
+ return NO;
+ }
+
+ // create path to dest
+ if (!destExists && ![fileManager createDirectoryAtPath:[dest stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:error]) {
+ return NO;
+ }
+
+ // copy src to dest
+ if ([fileManager copyItemAtPath:src toPath:dest error:error]) {
+ // success - cleanup - delete the backup to the dest
+ if ([fileManager fileExistsAtPath:tempBackup]) {
+ [fileManager removeItemAtPath:tempBackup error:error];
+ }
+ return YES;
+ } else {
+ // failure - we restore the temp backup file to dest
+ [fileManager copyItemAtPath:tempBackup toPath:dest error:error];
+ // cleanup - delete the backup to the dest
+ if ([fileManager fileExistsAtPath:tempBackup]) {
+ [fileManager removeItemAtPath:tempBackup error:error];
+ }
+ return NO;
+ }
+}
+
+- (BOOL)shouldBackup
+{
+ for (CDVBackupInfo* info in self.backupInfo) {
+ if ([info shouldBackup]) {
+ return YES;
+ }
+ }
+
+ return NO;
+}
+
+- (BOOL)shouldRestore
+{
+ for (CDVBackupInfo* info in self.backupInfo) {
+ if ([info shouldRestore]) {
+ return YES;
+ }
+ }
+
+ return NO;
+}
+
+/* copy from webkitDbLocation to persistentDbLocation */
+- (void)backup:(CDVInvokedUrlCommand*)command
+{
+ NSString* callbackId = command.callbackId;
+
+ NSError* __autoreleasing error = nil;
+ CDVPluginResult* result = nil;
+ NSString* message = nil;
+
+ for (CDVBackupInfo* info in self.backupInfo) {
+ if ([info shouldBackup]) {
+ [[self class] copyFrom:info.original to:info.backup error:&error];
+
+ if (callbackId) {
+ if (error == nil) {
+ message = [NSString stringWithFormat:@"Backed up: %@", info.label];
+ NSLog(@"%@", message);
+
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message];
+ [self.commandDelegate sendPluginResult:result callbackId:callbackId];
+ } else {
+ message = [NSString stringWithFormat:@"Error in CDVLocalStorage (%@) backup: %@", info.label, [error localizedDescription]];
+ NSLog(@"%@", message);
+
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:message];
+ [self.commandDelegate sendPluginResult:result callbackId:callbackId];
+ }
+ }
+ }
+ }
+}
+
+/* copy from persistentDbLocation to webkitDbLocation */
+- (void)restore:(CDVInvokedUrlCommand*)command
+{
+ NSError* __autoreleasing error = nil;
+ CDVPluginResult* result = nil;
+ NSString* message = nil;
+
+ for (CDVBackupInfo* info in self.backupInfo) {
+ if ([info shouldRestore]) {
+ [[self class] copyFrom:info.backup to:info.original error:&error];
+
+ if (error == nil) {
+ message = [NSString stringWithFormat:@"Restored: %@", info.label];
+ NSLog(@"%@", message);
+
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message];
+ [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+ } else {
+ message = [NSString stringWithFormat:@"Error in CDVLocalStorage (%@) restore: %@", info.label, [error localizedDescription]];
+ NSLog(@"%@", message);
+
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:message];
+ [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+ }
+ }
+ }
+}
+
++ (void)__fixupDatabaseLocationsWithBackupType:(NSString*)backupType
+{
+ [self __verifyAndFixDatabaseLocations];
+ [self __restoreLegacyDatabaseLocationsWithBackupType:backupType];
+}
+
++ (void)__verifyAndFixDatabaseLocations
+{
+ NSBundle* mainBundle = [NSBundle mainBundle];
+ NSString* bundlePath = [[mainBundle bundlePath] stringByDeletingLastPathComponent];
+ NSString* bundleIdentifier = [[mainBundle infoDictionary] objectForKey:@"CFBundleIdentifier"];
+ NSString* appPlistPath = [bundlePath stringByAppendingPathComponent:[NSString stringWithFormat:@"Library/Preferences/%@.plist", bundleIdentifier]];
+
+ NSMutableDictionary* appPlistDict = [NSMutableDictionary dictionaryWithContentsOfFile:appPlistPath];
+ BOOL modified = [[self class] __verifyAndFixDatabaseLocationsWithAppPlistDict:appPlistDict
+ bundlePath:bundlePath
+ fileManager:[NSFileManager defaultManager]];
+
+ if (modified) {
+ BOOL ok = [appPlistDict writeToFile:appPlistPath atomically:YES];
+ [[NSUserDefaults standardUserDefaults] synchronize];
+ NSLog(@"Fix applied for database locations?: %@", ok ? @"YES" : @"NO");
+ }
+}
+
++ (BOOL)__verifyAndFixDatabaseLocationsWithAppPlistDict:(NSMutableDictionary*)appPlistDict
+ bundlePath:(NSString*)bundlePath
+ fileManager:(NSFileManager*)fileManager
+{
+ NSString* libraryCaches = @"Library/Caches";
+ NSString* libraryWebKit = @"Library/WebKit";
+
+ NSArray* keysToCheck = [NSArray arrayWithObjects:
+ @"WebKitLocalStorageDatabasePathPreferenceKey",
+ @"WebDatabaseDirectory",
+ nil];
+
+ BOOL dirty = NO;
+
+ for (NSString* key in keysToCheck) {
+ NSString* value = [appPlistDict objectForKey:key];
+ // verify key exists, and path is in app bundle, if not - fix
+ if ((value != nil) && ![value hasPrefix:bundlePath]) {
+ // the pathSuffix to use may be wrong - OTA upgrades from < 5.1 to 5.1 do keep the old path Library/WebKit,
+ // while Xcode synced ones do change the storage location to Library/Caches
+ NSString* newBundlePath = [bundlePath stringByAppendingPathComponent:libraryCaches];
+ if (![fileManager fileExistsAtPath:newBundlePath]) {
+ newBundlePath = [bundlePath stringByAppendingPathComponent:libraryWebKit];
+ }
+ [appPlistDict setValue:newBundlePath forKey:key];
+ dirty = YES;
+ }
+ }
+
+ return dirty;
+}
+
++ (void)__restoreLegacyDatabaseLocationsWithBackupType:(NSString*)backupType
+{
+ // on iOS 6, if you toggle between cloud/local backup, you must move database locations. Default upgrade from iOS5.1 to iOS6 is like a toggle from local to cloud.
+ if (!IsAtLeastiOSVersion(@"6.0")) {
+ return;
+ }
+
+ NSString* appLibraryFolder = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
+ NSString* appDocumentsFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
+
+ NSMutableArray* backupInfo = [NSMutableArray arrayWithCapacity:0];
+
+ if ([backupType isEqualToString:@"cloud"]) {
+#ifdef DEBUG
+ NSLog(@"\n\nStarted backup to iCloud! Please be careful."
+ "\nYour application might be rejected by Apple if you store too much data."
+ "\nFor more information please read \"iOS Data Storage Guidelines\" at:"
+ "\nhttps://developer.apple.com/icloud/documentation/data-storage/"
+ "\nTo disable web storage backup to iCloud, set the BackupWebStorage preference to \"local\" in the Cordova config.xml file\n\n");
+#endif
+ // We would like to restore old backups/caches databases to the new destination (nested in lib folder)
+ [backupInfo addObjectsFromArray:[self createBackupInfoWithTargetDir:appLibraryFolder backupDir:[appDocumentsFolder stringByAppendingPathComponent:@"Backups"] targetDirNests:YES backupDirNests:NO rename:YES]];
+ [backupInfo addObjectsFromArray:[self createBackupInfoWithTargetDir:appLibraryFolder backupDir:[appLibraryFolder stringByAppendingPathComponent:@"Caches"] targetDirNests:YES backupDirNests:NO rename:NO]];
+ } else {
+ // For ios6 local backups we also want to restore from Backups dir -- but we don't need to do that here, since the plugin will do that itself.
+ [backupInfo addObjectsFromArray:[self createBackupInfoWithTargetDir:[appLibraryFolder stringByAppendingPathComponent:@"Caches"] backupDir:appLibraryFolder targetDirNests:NO backupDirNests:YES rename:NO]];
+ }
+
+ NSFileManager* manager = [NSFileManager defaultManager];
+
+ for (CDVBackupInfo* info in backupInfo) {
+ if ([manager fileExistsAtPath:info.backup]) {
+ if ([info shouldRestore]) {
+ NSLog(@"Restoring old webstorage backup. From: '%@' To: '%@'.", info.backup, info.original);
+ [self copyFrom:info.backup to:info.original error:nil];
+ }
+ NSLog(@"Removing old webstorage backup: '%@'.", info.backup);
+ [manager removeItemAtPath:info.backup error:nil];
+ }
+ }
+
+ [[NSUserDefaults standardUserDefaults] setBool:[backupType isEqualToString:@"cloud"] forKey:@"WebKitStoreWebDataForBackup"];
+}
+
+#pragma mark -
+#pragma mark Notification handlers
+
+- (void)onResignActive
+{
+ UIDevice* device = [UIDevice currentDevice];
+ NSNumber* exitsOnSuspend = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIApplicationExitsOnSuspend"];
+
+ BOOL isMultitaskingSupported = [device respondsToSelector:@selector(isMultitaskingSupported)] && [device isMultitaskingSupported];
+
+ if (exitsOnSuspend == nil) { // if it's missing, it should be NO (i.e. multi-tasking on by default)
+ exitsOnSuspend = [NSNumber numberWithBool:NO];
+ }
+
+ if (exitsOnSuspend) {
+ [self backup:nil];
+ } else if (isMultitaskingSupported) {
+ __block UIBackgroundTaskIdentifier backgroundTaskID = UIBackgroundTaskInvalid;
+
+ backgroundTaskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
+ [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskID];
+ backgroundTaskID = UIBackgroundTaskInvalid;
+ NSLog(@"Background task to backup WebSQL/LocalStorage expired.");
+ }];
+ CDVLocalStorage __weak* weakSelf = self;
+ [self.commandDelegate runInBackground:^{
+ [weakSelf backup:nil];
+
+ [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskID];
+ backgroundTaskID = UIBackgroundTaskInvalid;
+ }];
+ }
+}
+
+- (void)onAppTerminate
+{
+ [self onResignActive];
+}
+
+- (void)onReset
+{
+ [self restore:nil];
+}
+
+@end
+
+#pragma mark -
+#pragma mark CDVBackupInfo implementation
+
+@implementation CDVBackupInfo
+
+@synthesize original, backup, label;
+
+- (BOOL)file:(NSString*)aPath isNewerThanFile:(NSString*)bPath
+{
+ NSFileManager* fileManager = [NSFileManager defaultManager];
+ NSError* __autoreleasing error = nil;
+
+ NSDictionary* aPathAttribs = [fileManager attributesOfItemAtPath:aPath error:&error];
+ NSDictionary* bPathAttribs = [fileManager attributesOfItemAtPath:bPath error:&error];
+
+ NSDate* aPathModDate = [aPathAttribs objectForKey:NSFileModificationDate];
+ NSDate* bPathModDate = [bPathAttribs objectForKey:NSFileModificationDate];
+
+ if ((nil == aPathModDate) && (nil == bPathModDate)) {
+ return NO;
+ }
+
+ return [aPathModDate compare:bPathModDate] == NSOrderedDescending || bPathModDate == nil;
+}
+
+- (BOOL)item:(NSString*)aPath isNewerThanItem:(NSString*)bPath
+{
+ NSFileManager* fileManager = [NSFileManager defaultManager];
+
+ BOOL aPathIsDir = NO, bPathIsDir = NO;
+ BOOL aPathExists = [fileManager fileExistsAtPath:aPath isDirectory:&aPathIsDir];
+
+ [fileManager fileExistsAtPath:bPath isDirectory:&bPathIsDir];
+
+ if (!aPathExists) {
+ return NO;
+ }
+
+ if (!(aPathIsDir && bPathIsDir)) { // just a file
+ return [self file:aPath isNewerThanFile:bPath];
+ }
+
+ // essentially we want rsync here, but have to settle for our poor man's implementation
+ // we get the files in aPath, and see if it is newer than the file in bPath
+ // (it is newer if it doesn't exist in bPath) if we encounter the FIRST file that is newer,
+ // we return YES
+ NSDirectoryEnumerator* directoryEnumerator = [fileManager enumeratorAtPath:aPath];
+ NSString* path;
+
+ while ((path = [directoryEnumerator nextObject])) {
+ NSString* aPathFile = [aPath stringByAppendingPathComponent:path];
+ NSString* bPathFile = [bPath stringByAppendingPathComponent:path];
+
+ BOOL isNewer = [self file:aPathFile isNewerThanFile:bPathFile];
+ if (isNewer) {
+ return YES;
+ }
+ }
+
+ return NO;
+}
+
+- (BOOL)shouldBackup
+{
+ return [self item:self.original isNewerThanItem:self.backup];
+}
+
+- (BOOL)shouldRestore
+{
+ return [self item:self.backup isNewerThanItem:self.original];
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPlugin.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPlugin.h
new file mode 100644
index 00000000..5e8b2830
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPlugin.h
@@ -0,0 +1,67 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+#import "CDVPluginResult.h"
+#import "NSMutableArray+QueueAdditions.h"
+#import "CDVCommandDelegate.h"
+
+extern NSString* const CDVPageDidLoadNotification;
+extern NSString* const CDVPluginHandleOpenURLNotification;
+extern NSString* const CDVPluginResetNotification;
+extern NSString* const CDVLocalNotification;
+extern NSString* const CDVRemoteNotification;
+extern NSString* const CDVRemoteNotificationError;
+
+@interface CDVPlugin : NSObject {}
+
+@property (nonatomic, weak) UIWebView* webView;
+@property (nonatomic, weak) UIViewController* viewController;
+@property (nonatomic, weak) id <CDVCommandDelegate> commandDelegate;
+
+@property (readonly, assign) BOOL hasPendingOperation;
+
+- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView;
+- (void)pluginInitialize;
+
+- (void)handleOpenURL:(NSNotification*)notification;
+- (void)onAppTerminate;
+- (void)onMemoryWarning;
+- (void)onReset;
+- (void)dispose;
+
+/*
+ // see initWithWebView implementation
+ - (void) onPause {}
+ - (void) onResume {}
+ - (void) onOrientationWillChange {}
+ - (void) onOrientationDidChange {}
+ - (void)didReceiveLocalNotification:(NSNotification *)notification;
+ */
+
+- (id)appDelegate;
+
+- (NSString*)writeJavascript:(NSString*)javascript CDV_DEPRECATED(3.6, "Use the CDVCommandDelegate equivalent of evalJs:. This will be removed in 4.0.0");
+
+- (NSString*)success:(CDVPluginResult*)pluginResult callbackId:(NSString*)callbackId CDV_DEPRECATED(3.6, "Use the CDVCommandDelegate equivalent of sendPluginResult:callbackId. This will be removed in 4.0.0");
+
+- (NSString*)error:(CDVPluginResult*)pluginResult callbackId:(NSString*)callbackId CDV_DEPRECATED(3.6, "Use the CDVCommandDelegate equivalent of sendPluginResult:callbackId. This will be removed in 4.0.0");
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPlugin.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPlugin.m
new file mode 100644
index 00000000..ea81ddd1
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPlugin.m
@@ -0,0 +1,154 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVPlugin.h"
+
+NSString* const CDVPageDidLoadNotification = @"CDVPageDidLoadNotification";
+NSString* const CDVPluginHandleOpenURLNotification = @"CDVPluginHandleOpenURLNotification";
+NSString* const CDVPluginResetNotification = @"CDVPluginResetNotification";
+NSString* const CDVLocalNotification = @"CDVLocalNotification";
+NSString* const CDVRemoteNotification = @"CDVRemoteNotification";
+NSString* const CDVRemoteNotificationError = @"CDVRemoteNotificationError";
+
+@interface CDVPlugin ()
+
+@property (readwrite, assign) BOOL hasPendingOperation;
+
+@end
+
+@implementation CDVPlugin
+@synthesize webView, viewController, commandDelegate, hasPendingOperation;
+
+// Do not override these methods. Use pluginInitialize instead.
+- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView settings:(NSDictionary*)classSettings
+{
+ return [self initWithWebView:theWebView];
+}
+
+- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView
+{
+ self = [super init];
+ if (self) {
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppTerminate) name:UIApplicationWillTerminateNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleOpenURL:) name:CDVPluginHandleOpenURLNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onReset) name:CDVPluginResetNotification object:theWebView];
+
+ self.webView = theWebView;
+ }
+ return self;
+}
+
+- (void)pluginInitialize
+{
+ // You can listen to more app notifications, see:
+ // http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIApplication_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006728-CH3-DontLinkElementID_4
+
+ // NOTE: if you want to use these, make sure you uncomment the corresponding notification handler
+
+ // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onPause) name:UIApplicationDidEnterBackgroundNotification object:nil];
+ // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onResume) name:UIApplicationWillEnterForegroundNotification object:nil];
+ // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onOrientationWillChange) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
+ // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onOrientationDidChange) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
+
+ // Added in 2.3.0
+ // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveLocalNotification:) name:CDVLocalNotification object:nil];
+
+ // Added in 2.5.0
+ // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pageDidLoad:) name:CDVPageDidLoadNotification object:self.webView];
+}
+
+- (void)dispose
+{
+ viewController = nil;
+ commandDelegate = nil;
+ webView = nil;
+}
+
+/*
+// NOTE: for onPause and onResume, calls into JavaScript must not call or trigger any blocking UI, like alerts
+- (void) onPause {}
+- (void) onResume {}
+- (void) onOrientationWillChange {}
+- (void) onOrientationDidChange {}
+*/
+
+/* NOTE: calls into JavaScript must not call or trigger any blocking UI, like alerts */
+- (void)handleOpenURL:(NSNotification*)notification
+{
+ // override to handle urls sent to your app
+ // register your url schemes in your App-Info.plist
+
+ NSURL* url = [notification object];
+
+ if ([url isKindOfClass:[NSURL class]]) {
+ /* Do your thing! */
+ }
+}
+
+/* NOTE: calls into JavaScript must not call or trigger any blocking UI, like alerts */
+- (void)onAppTerminate
+{
+ // override this if you need to do any cleanup on app exit
+}
+
+- (void)onMemoryWarning
+{
+ // override to remove caches, etc
+}
+
+- (void)onReset
+{
+ // Override to cancel any long-running requests when the WebView navigates or refreshes.
+}
+
+- (void)dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self]; // this will remove all notification unless added using addObserverForName:object:queue:usingBlock:
+}
+
+- (id)appDelegate
+{
+ return [[UIApplication sharedApplication] delegate];
+}
+
+- (NSString*)writeJavascript:(NSString*)javascript
+{
+ return [self.webView stringByEvaluatingJavaScriptFromString:javascript];
+}
+
+- (NSString*)success:(CDVPluginResult*)pluginResult callbackId:(NSString*)callbackId
+{
+ [self.commandDelegate evalJs:[pluginResult toSuccessCallbackString:callbackId]];
+ return @"";
+}
+
+- (NSString*)error:(CDVPluginResult*)pluginResult callbackId:(NSString*)callbackId
+{
+ [self.commandDelegate evalJs:[pluginResult toErrorCallbackString:callbackId]];
+ return @"";
+}
+
+// default implementation does nothing, ideally, we are not registered for notification if we aren't going to do anything.
+// - (void)didReceiveLocalNotification:(NSNotification *)notification
+// {
+// // UILocalNotification* localNotification = [notification object]; // get the payload as a LocalNotification
+// }
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPluginResult.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPluginResult.h
new file mode 100644
index 00000000..e624d4de
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPluginResult.h
@@ -0,0 +1,71 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "CDVAvailability.h"
+
+typedef enum {
+ CDVCommandStatus_NO_RESULT = 0,
+ CDVCommandStatus_OK,
+ CDVCommandStatus_CLASS_NOT_FOUND_EXCEPTION,
+ CDVCommandStatus_ILLEGAL_ACCESS_EXCEPTION,
+ CDVCommandStatus_INSTANTIATION_EXCEPTION,
+ CDVCommandStatus_MALFORMED_URL_EXCEPTION,
+ CDVCommandStatus_IO_EXCEPTION,
+ CDVCommandStatus_INVALID_ACTION,
+ CDVCommandStatus_JSON_EXCEPTION,
+ CDVCommandStatus_ERROR
+} CDVCommandStatus;
+
+@interface CDVPluginResult : NSObject {}
+
+@property (nonatomic, strong, readonly) NSNumber* status;
+@property (nonatomic, strong, readonly) id message;
+@property (nonatomic, strong) NSNumber* keepCallback;
+// This property can be used to scope the lifetime of another object. For example,
+// Use it to store the associated NSData when `message` is created using initWithBytesNoCopy.
+@property (nonatomic, strong) id associatedObject;
+
+- (CDVPluginResult*)init;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsString:(NSString*)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsArray:(NSArray*)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsInt:(int)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsDouble:(double)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsBool:(BOOL)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsDictionary:(NSDictionary*)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsArrayBuffer:(NSData*)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsMultipart:(NSArray*)theMessages;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageToErrorObject:(int)errorCode;
+
++ (void)setVerbose:(BOOL)verbose;
++ (BOOL)isVerbose;
+
+- (void)setKeepCallbackAsBool:(BOOL)bKeepCallback;
+
+- (NSString*)argumentsAsJSON;
+
+// These methods are used by the legacy plugin return result method
+- (NSString*)toJSONString CDV_DEPRECATED(3.6, "Only used by toSuccessCallbackString and toErrorCallbackString which are deprecated. This will be removed in 4.0.0");
+
+- (NSString*)toSuccessCallbackString:(NSString*)callbackId CDV_DEPRECATED(3.6, "Use the CDVCommandDelegate method sendPluginResult:callbackId instead. This will be removed in 4.0.0");
+
+- (NSString*)toErrorCallbackString:(NSString*)callbackId CDV_DEPRECATED(3.6, "Use the CDVCommandDelegate method sendPluginResult:callbackId instead. This will be removed in 4.0.0");
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPluginResult.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPluginResult.m
new file mode 100644
index 00000000..13839efd
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPluginResult.m
@@ -0,0 +1,224 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVPluginResult.h"
+#import "CDVJSON_private.h"
+#import "CDVDebug.h"
+#import "NSData+Base64.h"
+
+@interface CDVPluginResult ()
+
+- (CDVPluginResult*)initWithStatus:(CDVCommandStatus)statusOrdinal message:(id)theMessage;
+
+@end
+
+@implementation CDVPluginResult
+@synthesize status, message, keepCallback, associatedObject;
+
+static NSArray* org_apache_cordova_CommandStatusMsgs;
+
+id messageFromArrayBuffer(NSData* data)
+{
+ return @{
+ @"CDVType" : @"ArrayBuffer",
+ @"data" :[data cdv_base64EncodedString]
+ };
+}
+
+id massageMessage(id message)
+{
+ if ([message isKindOfClass:[NSData class]]) {
+ return messageFromArrayBuffer(message);
+ }
+ return message;
+}
+
+id messageFromMultipart(NSArray* theMessages)
+{
+ NSMutableArray* messages = [NSMutableArray arrayWithArray:theMessages];
+
+ for (NSUInteger i = 0; i < messages.count; ++i) {
+ [messages replaceObjectAtIndex:i withObject:massageMessage([messages objectAtIndex:i])];
+ }
+
+ return @{
+ @"CDVType" : @"MultiPart",
+ @"messages" : messages
+ };
+}
+
++ (void)initialize
+{
+ org_apache_cordova_CommandStatusMsgs = [[NSArray alloc] initWithObjects:@"No result",
+ @"OK",
+ @"Class not found",
+ @"Illegal access",
+ @"Instantiation error",
+ @"Malformed url",
+ @"IO error",
+ @"Invalid action",
+ @"JSON error",
+ @"Error",
+ nil];
+}
+
+- (CDVPluginResult*)init
+{
+ return [self initWithStatus:CDVCommandStatus_NO_RESULT message:nil];
+}
+
+- (CDVPluginResult*)initWithStatus:(CDVCommandStatus)statusOrdinal message:(id)theMessage
+{
+ self = [super init];
+ if (self) {
+ status = [NSNumber numberWithInt:statusOrdinal];
+ message = theMessage;
+ keepCallback = [NSNumber numberWithBool:NO];
+ }
+ return self;
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal
+{
+ return [[self alloc] initWithStatus:statusOrdinal message:nil];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsString:(NSString*)theMessage
+{
+ return [[self alloc] initWithStatus:statusOrdinal message:theMessage];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsArray:(NSArray*)theMessage
+{
+ return [[self alloc] initWithStatus:statusOrdinal message:theMessage];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsInt:(int)theMessage
+{
+ return [[self alloc] initWithStatus:statusOrdinal message:[NSNumber numberWithInt:theMessage]];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsDouble:(double)theMessage
+{
+ return [[self alloc] initWithStatus:statusOrdinal message:[NSNumber numberWithDouble:theMessage]];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsBool:(BOOL)theMessage
+{
+ return [[self alloc] initWithStatus:statusOrdinal message:[NSNumber numberWithBool:theMessage]];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsDictionary:(NSDictionary*)theMessage
+{
+ return [[self alloc] initWithStatus:statusOrdinal message:theMessage];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsArrayBuffer:(NSData*)theMessage
+{
+ return [[self alloc] initWithStatus:statusOrdinal message:messageFromArrayBuffer(theMessage)];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsMultipart:(NSArray*)theMessages
+{
+ return [[self alloc] initWithStatus:statusOrdinal message:messageFromMultipart(theMessages)];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageToErrorObject:(int)errorCode
+{
+ NSDictionary* errDict = @{@"code" :[NSNumber numberWithInt:errorCode]};
+
+ return [[self alloc] initWithStatus:statusOrdinal message:errDict];
+}
+
+- (void)setKeepCallbackAsBool:(BOOL)bKeepCallback
+{
+ [self setKeepCallback:[NSNumber numberWithBool:bKeepCallback]];
+}
+
+- (NSString*)argumentsAsJSON
+{
+ id arguments = (self.message == nil ? [NSNull null] : self.message);
+ NSArray* argumentsWrappedInArray = [NSArray arrayWithObject:arguments];
+
+ NSString* argumentsJSON = [argumentsWrappedInArray cdv_JSONString];
+
+ argumentsJSON = [argumentsJSON substringWithRange:NSMakeRange(1, [argumentsJSON length] - 2)];
+
+ return argumentsJSON;
+}
+
+// These methods are used by the legacy plugin return result method
+- (NSString*)toJSONString
+{
+ NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
+ self.status, @"status",
+ self.message ? self. message:[NSNull null], @"message",
+ self.keepCallback, @"keepCallback",
+ nil];
+
+ NSError* error = nil;
+ NSData* jsonData = [NSJSONSerialization dataWithJSONObject:dict
+ options:NSJSONWritingPrettyPrinted
+ error:&error];
+ NSString* resultString = nil;
+
+ if (error != nil) {
+ NSLog(@"toJSONString error: %@", [error localizedDescription]);
+ } else {
+ resultString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
+ }
+
+ if ([[self class] isVerbose]) {
+ NSLog(@"PluginResult:toJSONString - %@", resultString);
+ }
+ return resultString;
+}
+
+- (NSString*)toSuccessCallbackString:(NSString*)callbackId
+{
+ NSString* successCB = [NSString stringWithFormat:@"cordova.callbackSuccess('%@',%@);", callbackId, [self toJSONString]];
+
+ if ([[self class] isVerbose]) {
+ NSLog(@"PluginResult toSuccessCallbackString: %@", successCB);
+ }
+ return successCB;
+}
+
+- (NSString*)toErrorCallbackString:(NSString*)callbackId
+{
+ NSString* errorCB = [NSString stringWithFormat:@"cordova.callbackError('%@',%@);", callbackId, [self toJSONString]];
+
+ if ([[self class] isVerbose]) {
+ NSLog(@"PluginResult toErrorCallbackString: %@", errorCB);
+ }
+ return errorCB;
+}
+
+static BOOL gIsVerbose = NO;
++ (void)setVerbose:(BOOL)verbose
+{
+ gIsVerbose = verbose;
+}
+
++ (BOOL)isVerbose
+{
+ return gIsVerbose;
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVScreenOrientationDelegate.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVScreenOrientationDelegate.h
new file mode 100644
index 00000000..7226205a
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVScreenOrientationDelegate.h
@@ -0,0 +1,28 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@protocol CDVScreenOrientationDelegate <NSObject>
+
+- (NSUInteger)supportedInterfaceOrientations;
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
+- (BOOL)shouldAutorotate;
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVShared.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVShared.h
new file mode 100644
index 00000000..68acc5c2
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVShared.h
@@ -0,0 +1,22 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+// This file was emptied out in 3.6.0 release (July 2014).
+// It will be deleted in a future release.
+#import <CoreLocation/CoreLocation.h>
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVTimer.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVTimer.h
new file mode 100644
index 00000000..6d31593f
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVTimer.h
@@ -0,0 +1,27 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface CDVTimer : NSObject
+
++ (void)start:(NSString*)name;
++ (void)stop:(NSString*)name;
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVTimer.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVTimer.m
new file mode 100644
index 00000000..784e94d3
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVTimer.m
@@ -0,0 +1,123 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVTimer.h"
+
+#pragma mark CDVTimerItem
+
+@interface CDVTimerItem : NSObject
+
+@property (nonatomic, strong) NSString* name;
+@property (nonatomic, strong) NSDate* started;
+@property (nonatomic, strong) NSDate* ended;
+
+- (void)log;
+
+@end
+
+@implementation CDVTimerItem
+
+- (void)log
+{
+ NSLog(@"[CDVTimer][%@] %fms", self.name, [self.ended timeIntervalSinceDate:self.started] * 1000.0);
+}
+
+@end
+
+#pragma mark CDVTimer
+
+@interface CDVTimer ()
+
+@property (nonatomic, strong) NSMutableDictionary* items;
+
+@end
+
+@implementation CDVTimer
+
+#pragma mark object methods
+
+- (id)init
+{
+ if (self = [super init]) {
+ self.items = [NSMutableDictionary dictionaryWithCapacity:6];
+ }
+
+ return self;
+}
+
+- (void)add:(NSString*)name
+{
+ if ([self.items objectForKey:[name lowercaseString]] == nil) {
+ CDVTimerItem* item = [CDVTimerItem new];
+ item.name = name;
+ item.started = [NSDate new];
+ [self.items setObject:item forKey:[name lowercaseString]];
+ } else {
+ NSLog(@"Timer called '%@' already exists.", name);
+ }
+}
+
+- (void)remove:(NSString*)name
+{
+ CDVTimerItem* item = [self.items objectForKey:[name lowercaseString]];
+
+ if (item != nil) {
+ item.ended = [NSDate new];
+ [item log];
+ [self.items removeObjectForKey:[name lowercaseString]];
+ } else {
+ NSLog(@"Timer called '%@' does not exist.", name);
+ }
+}
+
+- (void)removeAll
+{
+ [self.items removeAllObjects];
+}
+
+#pragma mark class methods
+
++ (void)start:(NSString*)name
+{
+ [[CDVTimer sharedInstance] add:name];
+}
+
++ (void)stop:(NSString*)name
+{
+ [[CDVTimer sharedInstance] remove:name];
+}
+
++ (void)clearAll
+{
+ [[CDVTimer sharedInstance] removeAll];
+}
+
++ (CDVTimer*)sharedInstance
+{
+ static dispatch_once_t pred = 0;
+ __strong static CDVTimer* _sharedObject = nil;
+
+ dispatch_once(&pred, ^{
+ _sharedObject = [[self alloc] init];
+ });
+
+ return _sharedObject;
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVURLProtocol.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVURLProtocol.h
new file mode 100644
index 00000000..5444f6d1
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVURLProtocol.h
@@ -0,0 +1,29 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "CDVAvailability.h"
+
+@class CDVViewController;
+
+@interface CDVURLProtocol : NSURLProtocol {}
+
++ (void)registerViewController:(CDVViewController*)viewController;
++ (void)unregisterViewController:(CDVViewController*)viewController;
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVURLProtocol.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVURLProtocol.m
new file mode 100644
index 00000000..fce5783a
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVURLProtocol.m
@@ -0,0 +1,213 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <AssetsLibrary/ALAsset.h>
+#import <AssetsLibrary/ALAssetRepresentation.h>
+#import <AssetsLibrary/ALAssetsLibrary.h>
+#import <MobileCoreServices/MobileCoreServices.h>
+#import "CDVURLProtocol.h"
+#import "CDVCommandQueue.h"
+#import "CDVWhitelist.h"
+#import "CDVViewController.h"
+
+static CDVWhitelist* gWhitelist = nil;
+// Contains a set of NSNumbers of addresses of controllers. It doesn't store
+// the actual pointer to avoid retaining.
+static NSMutableSet* gRegisteredControllers = nil;
+
+NSString* const kCDVAssetsLibraryPrefixes = @"assets-library://";
+
+// Returns the registered view controller that sent the given request.
+// If the user-agent is not from a UIWebView, or if it's from an unregistered one,
+// then nil is returned.
+static CDVViewController *viewControllerForRequest(NSURLRequest* request)
+{
+ // The exec bridge explicitly sets the VC address in a header.
+ // This works around the User-Agent not being set for file: URLs.
+ NSString* addrString = [request valueForHTTPHeaderField:@"vc"];
+
+ if (addrString == nil) {
+ NSString* userAgent = [request valueForHTTPHeaderField:@"User-Agent"];
+ if (userAgent == nil) {
+ return nil;
+ }
+ NSUInteger bracketLocation = [userAgent rangeOfString:@"(" options:NSBackwardsSearch].location;
+ if (bracketLocation == NSNotFound) {
+ return nil;
+ }
+ addrString = [userAgent substringFromIndex:bracketLocation + 1];
+ }
+
+ long long viewControllerAddress = [addrString longLongValue];
+ @synchronized(gRegisteredControllers) {
+ if (![gRegisteredControllers containsObject:[NSNumber numberWithLongLong:viewControllerAddress]]) {
+ return nil;
+ }
+ }
+
+ return (__bridge CDVViewController*)(void*)viewControllerAddress;
+}
+
+@implementation CDVURLProtocol
+
++ (void)registerPGHttpURLProtocol {}
+
++ (void)registerURLProtocol {}
+
+// Called to register the URLProtocol, and to make it away of an instance of
+// a ViewController.
++ (void)registerViewController:(CDVViewController*)viewController
+{
+ if (gRegisteredControllers == nil) {
+ [NSURLProtocol registerClass:[CDVURLProtocol class]];
+ gRegisteredControllers = [[NSMutableSet alloc] initWithCapacity:8];
+ // The whitelist doesn't change, so grab the first one and store it.
+ gWhitelist = viewController.whitelist;
+
+ // Note that we grab the whitelist from the first viewcontroller for now - but this will change
+ // when we allow a registered viewcontroller to have its own whitelist (e.g InAppBrowser)
+ // Differentiating the requests will be through the 'vc' http header below as used for the js->objc bridge.
+ // The 'vc' value is generated by casting the viewcontroller object to a (long long) value (see CDVViewController::webViewDidFinishLoad)
+ if (gWhitelist == nil) {
+ NSLog(@"WARNING: NO whitelist has been set in CDVURLProtocol.");
+ }
+ }
+
+ @synchronized(gRegisteredControllers) {
+ [gRegisteredControllers addObject:[NSNumber numberWithLongLong:(long long)viewController]];
+ }
+}
+
++ (void)unregisterViewController:(CDVViewController*)viewController
+{
+ @synchronized(gRegisteredControllers) {
+ [gRegisteredControllers removeObject:[NSNumber numberWithLongLong:(long long)viewController]];
+ }
+}
+
++ (BOOL)canInitWithRequest:(NSURLRequest*)theRequest
+{
+ NSURL* theUrl = [theRequest URL];
+ CDVViewController* viewController = viewControllerForRequest(theRequest);
+
+ if ([[theUrl absoluteString] hasPrefix:kCDVAssetsLibraryPrefixes]) {
+ return YES;
+ } else if (viewController != nil) {
+ if ([[theUrl path] isEqualToString:@"/!gap_exec"]) {
+ NSString* queuedCommandsJSON = [theRequest valueForHTTPHeaderField:@"cmds"];
+ NSString* requestId = [theRequest valueForHTTPHeaderField:@"rc"];
+ if (requestId == nil) {
+ NSLog(@"!cordova request missing rc header");
+ return NO;
+ }
+ BOOL hasCmds = [queuedCommandsJSON length] > 0;
+ if (hasCmds) {
+ SEL sel = @selector(enqueueCommandBatch:);
+ [viewController.commandQueue performSelectorOnMainThread:sel withObject:queuedCommandsJSON waitUntilDone:NO];
+ [viewController.commandQueue performSelectorOnMainThread:@selector(executePending) withObject:nil waitUntilDone:NO];
+ } else {
+ SEL sel = @selector(processXhrExecBridgePoke:);
+ [viewController.commandQueue performSelectorOnMainThread:sel withObject:[NSNumber numberWithInteger:[requestId integerValue]] waitUntilDone:NO];
+ }
+ // Returning NO here would be 20% faster, but it spams WebInspector's console with failure messages.
+ // If JS->Native bridge speed is really important for an app, they should use the iframe bridge.
+ // Returning YES here causes the request to come through canInitWithRequest two more times.
+ // For this reason, we return NO when cmds exist.
+ return !hasCmds;
+ }
+ // we only care about http and https connections.
+ // CORS takes care of http: trying to access file: URLs.
+ if ([gWhitelist schemeIsAllowed:[theUrl scheme]]) {
+ // if it FAILS the whitelist, we return TRUE, so we can fail the connection later
+ return ![gWhitelist URLIsAllowed:theUrl];
+ }
+ }
+
+ return NO;
+}
+
++ (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)request
+{
+ // NSLog(@"%@ received %@", self, NSStringFromSelector(_cmd));
+ return request;
+}
+
+- (void)startLoading
+{
+ // NSLog(@"%@ received %@ - start", self, NSStringFromSelector(_cmd));
+ NSURL* url = [[self request] URL];
+
+ if ([[url path] isEqualToString:@"/!gap_exec"]) {
+ [self sendResponseWithResponseCode:200 data:nil mimeType:nil];
+ return;
+ } else if ([[url absoluteString] hasPrefix:kCDVAssetsLibraryPrefixes]) {
+ ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) {
+ if (asset) {
+ // We have the asset! Get the data and send it along.
+ ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
+ NSString* MIMEType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)[assetRepresentation UTI], kUTTagClassMIMEType);
+ Byte* buffer = (Byte*)malloc((unsigned long)[assetRepresentation size]);
+ NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:0.0 length:(NSUInteger)[assetRepresentation size] error:nil];
+ NSData* data = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES];
+ [self sendResponseWithResponseCode:200 data:data mimeType:MIMEType];
+ } else {
+ // Retrieving the asset failed for some reason. Send an error.
+ [self sendResponseWithResponseCode:404 data:nil mimeType:nil];
+ }
+ };
+ ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) {
+ // Retrieving the asset failed for some reason. Send an error.
+ [self sendResponseWithResponseCode:401 data:nil mimeType:nil];
+ };
+
+ ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
+ [assetsLibrary assetForURL:url resultBlock:resultBlock failureBlock:failureBlock];
+ return;
+ }
+
+ NSString* body = [gWhitelist errorStringForURL:url];
+ [self sendResponseWithResponseCode:401 data:[body dataUsingEncoding:NSASCIIStringEncoding] mimeType:nil];
+}
+
+- (void)stopLoading
+{
+ // do any cleanup here
+}
+
++ (BOOL)requestIsCacheEquivalent:(NSURLRequest*)requestA toRequest:(NSURLRequest*)requestB
+{
+ return NO;
+}
+
+- (void)sendResponseWithResponseCode:(NSInteger)statusCode data:(NSData*)data mimeType:(NSString*)mimeType
+{
+ if (mimeType == nil) {
+ mimeType = @"text/plain";
+ }
+
+ NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc] initWithURL:[[self request] URL] statusCode:statusCode HTTPVersion:@"HTTP/1.1" headerFields:@{@"Content-Type" : mimeType}];
+
+ [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
+ if (data != nil) {
+ [[self client] URLProtocol:self didLoadData:data];
+ }
+ [[self client] URLProtocolDidFinishLoading:self];
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVUserAgentUtil.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVUserAgentUtil.h
new file mode 100644
index 00000000..4de382f0
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVUserAgentUtil.h
@@ -0,0 +1,27 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface CDVUserAgentUtil : NSObject
++ (NSString*)originalUserAgent;
++ (void)acquireLock:(void (^)(NSInteger lockToken))block;
++ (void)releaseLock:(NSInteger*)lockToken;
++ (void)setUserAgent:(NSString*)value lockToken:(NSInteger)lockToken;
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVUserAgentUtil.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVUserAgentUtil.m
new file mode 100644
index 00000000..c3402d08
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVUserAgentUtil.m
@@ -0,0 +1,122 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVUserAgentUtil.h"
+
+#import <UIKit/UIKit.h>
+
+// #define VerboseLog NSLog
+#define VerboseLog(...) do {} while (0)
+
+static NSString* const kCdvUserAgentKey = @"Cordova-User-Agent";
+static NSString* const kCdvUserAgentVersionKey = @"Cordova-User-Agent-Version";
+
+static NSString* gOriginalUserAgent = nil;
+static NSInteger gNextLockToken = 0;
+static NSInteger gCurrentLockToken = 0;
+static NSMutableArray* gPendingSetUserAgentBlocks = nil;
+
+@implementation CDVUserAgentUtil
+
++ (NSString*)originalUserAgent
+{
+ if (gOriginalUserAgent == nil) {
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppLocaleDidChange:)
+ name:NSCurrentLocaleDidChangeNotification object:nil];
+
+ NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
+ NSString* systemVersion = [[UIDevice currentDevice] systemVersion];
+ NSString* localeStr = [[NSLocale currentLocale] localeIdentifier];
+ // Record the model since simulator can change it without re-install (CB-5420).
+ NSString* model = [UIDevice currentDevice].model;
+ NSString* systemAndLocale = [NSString stringWithFormat:@"%@ %@ %@", model, systemVersion, localeStr];
+
+ NSString* cordovaUserAgentVersion = [userDefaults stringForKey:kCdvUserAgentVersionKey];
+ gOriginalUserAgent = [userDefaults stringForKey:kCdvUserAgentKey];
+ BOOL cachedValueIsOld = ![systemAndLocale isEqualToString:cordovaUserAgentVersion];
+
+ if ((gOriginalUserAgent == nil) || cachedValueIsOld) {
+ UIWebView* sampleWebView = [[UIWebView alloc] initWithFrame:CGRectZero];
+ gOriginalUserAgent = [sampleWebView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
+
+ [userDefaults setObject:gOriginalUserAgent forKey:kCdvUserAgentKey];
+ [userDefaults setObject:systemAndLocale forKey:kCdvUserAgentVersionKey];
+
+ [userDefaults synchronize];
+ }
+ }
+ return gOriginalUserAgent;
+}
+
++ (void)onAppLocaleDidChange:(NSNotification*)notification
+{
+ // TODO: We should figure out how to update the user-agent of existing UIWebViews when this happens.
+ // Maybe use the PDF bug (noted in setUserAgent:).
+ gOriginalUserAgent = nil;
+}
+
++ (void)acquireLock:(void (^)(NSInteger lockToken))block
+{
+ if (gCurrentLockToken == 0) {
+ gCurrentLockToken = ++gNextLockToken;
+ VerboseLog(@"Gave lock %d", gCurrentLockToken);
+ block(gCurrentLockToken);
+ } else {
+ if (gPendingSetUserAgentBlocks == nil) {
+ gPendingSetUserAgentBlocks = [[NSMutableArray alloc] initWithCapacity:4];
+ }
+ VerboseLog(@"Waiting for lock");
+ [gPendingSetUserAgentBlocks addObject:block];
+ }
+}
+
++ (void)releaseLock:(NSInteger*)lockToken
+{
+ if (*lockToken == 0) {
+ return;
+ }
+ NSAssert(gCurrentLockToken == *lockToken, @"Got token %ld, expected %ld", (long)*lockToken, (long)gCurrentLockToken);
+
+ VerboseLog(@"Released lock %d", *lockToken);
+ if ([gPendingSetUserAgentBlocks count] > 0) {
+ void (^block)() = [gPendingSetUserAgentBlocks objectAtIndex:0];
+ [gPendingSetUserAgentBlocks removeObjectAtIndex:0];
+ gCurrentLockToken = ++gNextLockToken;
+ NSLog(@"Gave lock %ld", (long)gCurrentLockToken);
+ block(gCurrentLockToken);
+ } else {
+ gCurrentLockToken = 0;
+ }
+ *lockToken = 0;
+}
+
++ (void)setUserAgent:(NSString*)value lockToken:(NSInteger)lockToken
+{
+ NSAssert(gCurrentLockToken == lockToken, @"Got token %ld, expected %ld", (long)lockToken, (long)gCurrentLockToken);
+ VerboseLog(@"User-Agent set to: %@", value);
+
+ // Setting the UserAgent must occur before a UIWebView is instantiated.
+ // It is read per instantiation, so it does not affect previously created views.
+ // Except! When a PDF is loaded, all currently active UIWebViews reload their
+ // User-Agent from the NSUserDefaults some time after the DidFinishLoad of the PDF bah!
+ NSDictionary* dict = [[NSDictionary alloc] initWithObjectsAndKeys:value, @"UserAgent", nil];
+ [[NSUserDefaults standardUserDefaults] registerDefaults:dict];
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.h
new file mode 100644
index 00000000..51863a59
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.h
@@ -0,0 +1,84 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <UIKit/UIKit.h>
+#import <Foundation/NSJSONSerialization.h>
+#import "CDVAvailability.h"
+#import "CDVInvokedUrlCommand.h"
+#import "CDVCommandDelegate.h"
+#import "CDVCommandQueue.h"
+#import "CDVWhitelist.h"
+#import "CDVScreenOrientationDelegate.h"
+#import "CDVPlugin.h"
+
+@interface CDVViewController : UIViewController <UIWebViewDelegate, CDVScreenOrientationDelegate>{
+ @protected
+ id <CDVCommandDelegate> _commandDelegate;
+ @protected
+ CDVCommandQueue* _commandQueue;
+ NSString* _userAgent;
+}
+
+@property (nonatomic, strong) IBOutlet UIWebView* webView;
+
+@property (nonatomic, readonly, strong) NSMutableDictionary* pluginObjects;
+@property (nonatomic, readonly, strong) NSDictionary* pluginsMap;
+@property (nonatomic, readonly, strong) NSMutableDictionary* settings;
+@property (nonatomic, readonly, strong) NSXMLParser* configParser;
+@property (nonatomic, readonly, strong) CDVWhitelist* whitelist; // readonly for public
+@property (nonatomic, readonly, assign) BOOL loadFromString;
+
+@property (nonatomic, readwrite, copy) NSString* wwwFolderName;
+@property (nonatomic, readwrite, copy) NSString* startPage;
+@property (nonatomic, readonly, strong) CDVCommandQueue* commandQueue;
+@property (nonatomic, readonly, strong) id <CDVCommandDelegate> commandDelegate;
+
+/**
+ The complete user agent that Cordova will use when sending web requests.
+ */
+@property (nonatomic, readonly) NSString* userAgent;
+
+/**
+ The base user agent data that Cordova will use to build its user agent. If this
+ property isn't set, Cordova will use the standard web view user agent as its
+ base.
+ */
+@property (nonatomic, readwrite, copy) NSString* baseUserAgent;
+
++ (NSDictionary*)getBundlePlist:(NSString*)plistName;
++ (NSString*)applicationDocumentsDirectory;
+
+- (void)printMultitaskingInfo;
+- (void)createGapView;
+- (UIWebView*)newCordovaViewWithFrame:(CGRect)bounds;
+
+- (void)javascriptAlert:(NSString*)text;
+- (NSString*)appURLScheme;
+
+- (NSArray*)parseInterfaceOrientations:(NSArray*)orientations;
+- (BOOL)supportsOrientation:(UIInterfaceOrientation)orientation;
+
+- (id)getCommandInstance:(NSString*)pluginName;
+- (void)registerPlugin:(CDVPlugin*)plugin withClassName:(NSString*)className;
+- (void)registerPlugin:(CDVPlugin*)plugin withPluginName:(NSString*)pluginName;
+
+- (BOOL)URLisAllowed:(NSURL*)url;
+- (void)processOpenUrl:(NSURL*)url;
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.m
new file mode 100644
index 00000000..6d81e8d9
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.m
@@ -0,0 +1,1049 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <objc/message.h>
+#import "CDV.h"
+#import "CDVCommandDelegateImpl.h"
+#import "CDVConfigParser.h"
+#import "CDVUserAgentUtil.h"
+#import "CDVWebViewDelegate.h"
+#import <AVFoundation/AVFoundation.h>
+#import "CDVHandleOpenURL.h"
+
+#define degreesToRadian(x) (M_PI * (x) / 180.0)
+
+@interface CDVViewController () {
+ NSInteger _userAgentLockToken;
+ CDVWebViewDelegate* _webViewDelegate;
+}
+
+@property (nonatomic, readwrite, strong) NSXMLParser* configParser;
+@property (nonatomic, readwrite, strong) NSMutableDictionary* settings;
+@property (nonatomic, readwrite, strong) CDVWhitelist* whitelist;
+@property (nonatomic, readwrite, strong) NSMutableDictionary* pluginObjects;
+@property (nonatomic, readwrite, strong) NSArray* startupPluginNames;
+@property (nonatomic, readwrite, strong) NSDictionary* pluginsMap;
+@property (nonatomic, readwrite, strong) NSArray* supportedOrientations;
+@property (nonatomic, readwrite, assign) BOOL loadFromString;
+
+@property (readwrite, assign) BOOL initialized;
+
+@property (atomic, strong) NSURL* openURL;
+
+@end
+
+@implementation CDVViewController
+
+@synthesize webView, supportedOrientations;
+@synthesize pluginObjects, pluginsMap, whitelist, startupPluginNames;
+@synthesize configParser, settings, loadFromString;
+@synthesize wwwFolderName, startPage, initialized, openURL, baseUserAgent;
+@synthesize commandDelegate = _commandDelegate;
+@synthesize commandQueue = _commandQueue;
+
+- (void)__init
+{
+ if ((self != nil) && !self.initialized) {
+ _commandQueue = [[CDVCommandQueue alloc] initWithViewController:self];
+ _commandDelegate = [[CDVCommandDelegateImpl alloc] initWithViewController:self];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillTerminate:)
+ name:UIApplicationWillTerminateNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive:)
+ name:UIApplicationWillResignActiveNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidBecomeActive:)
+ name:UIApplicationDidBecomeActiveNotification object:nil];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillEnterForeground:)
+ name:UIApplicationWillEnterForegroundNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidEnterBackground:)
+ name:UIApplicationDidEnterBackgroundNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onPageDidLoad:)
+ name:CDVPageDidLoadNotification object:nil];
+
+ // read from UISupportedInterfaceOrientations (or UISupportedInterfaceOrientations~iPad, if its iPad) from -Info.plist
+ self.supportedOrientations = [self parseInterfaceOrientations:
+ [[[NSBundle mainBundle] infoDictionary] objectForKey:@"UISupportedInterfaceOrientations"]];
+
+ [self printVersion];
+ [self printMultitaskingInfo];
+ [self printPlatformVersionWarning];
+ self.initialized = YES;
+
+ // load config.xml settings
+ [self loadSettings];
+ }
+}
+
+- (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil
+{
+ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+ [self __init];
+ return self;
+}
+
+- (id)initWithCoder:(NSCoder*)aDecoder
+{
+ self = [super initWithCoder:aDecoder];
+ [self __init];
+ return self;
+}
+
+- (id)init
+{
+ self = [super init];
+ [self __init];
+ return self;
+}
+
+- (void)viewWillAppear:(BOOL)animated
+{
+ [super viewWillAppear:animated];
+}
+
+- (void)viewWillDisappear:(BOOL)animated
+{
+ [super viewWillDisappear:animated];
+}
+
+- (void)printVersion
+{
+ NSLog(@"Apache Cordova native platform version %@ is starting.", CDV_VERSION);
+}
+
+- (void)printPlatformVersionWarning
+{
+ if (!IsAtLeastiOSVersion(@"6.0")) {
+ NSLog(@"CRITICAL: For Cordova 3.5.0 and above, you will need to upgrade to at least iOS 6.0 or greater. Your current version of iOS is %@.",
+ [[UIDevice currentDevice] systemVersion]
+ );
+ }
+}
+
+- (void)printMultitaskingInfo
+{
+ UIDevice* device = [UIDevice currentDevice];
+ BOOL backgroundSupported = NO;
+
+ if ([device respondsToSelector:@selector(isMultitaskingSupported)]) {
+ backgroundSupported = device.multitaskingSupported;
+ }
+
+ NSNumber* exitsOnSuspend = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIApplicationExitsOnSuspend"];
+ if (exitsOnSuspend == nil) { // if it's missing, it should be NO (i.e. multi-tasking on by default)
+ exitsOnSuspend = [NSNumber numberWithBool:NO];
+ }
+
+ NSLog(@"Multi-tasking -> Device: %@, App: %@", (backgroundSupported ? @"YES" : @"NO"), (![exitsOnSuspend intValue]) ? @"YES" : @"NO");
+}
+
+- (BOOL)URLisAllowed:(NSURL*)url
+{
+ if (self.whitelist == nil) {
+ return YES;
+ }
+
+ return [self.whitelist URLIsAllowed:url];
+}
+
+- (void)loadSettings
+{
+ CDVConfigParser* delegate = [[CDVConfigParser alloc] init];
+
+ // read from config.xml in the app bundle
+ NSString* path = [[NSBundle mainBundle] pathForResource:@"config" ofType:@"xml"];
+
+ if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
+ NSAssert(NO, @"ERROR: config.xml does not exist. Please run cordova-ios/bin/cordova_plist_to_config_xml path/to/project.");
+ return;
+ }
+
+ NSURL* url = [NSURL fileURLWithPath:path];
+
+ configParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
+ if (configParser == nil) {
+ NSLog(@"Failed to initialize XML parser.");
+ return;
+ }
+ [configParser setDelegate:((id < NSXMLParserDelegate >)delegate)];
+ [configParser parse];
+
+ // Get the plugin dictionary, whitelist and settings from the delegate.
+ self.pluginsMap = delegate.pluginsDict;
+ self.startupPluginNames = delegate.startupPluginNames;
+ self.whitelist = [[CDVWhitelist alloc] initWithArray:delegate.whitelistHosts];
+ self.settings = delegate.settings;
+
+ // And the start folder/page.
+ self.wwwFolderName = @"www";
+ self.startPage = delegate.startPage;
+ if (self.startPage == nil) {
+ self.startPage = @"index.html";
+ }
+
+ // Initialize the plugin objects dict.
+ self.pluginObjects = [[NSMutableDictionary alloc] initWithCapacity:20];
+}
+
+- (NSURL*)appUrl
+{
+ NSURL* appURL = nil;
+
+ if ([self.startPage rangeOfString:@"://"].location != NSNotFound) {
+ appURL = [NSURL URLWithString:self.startPage];
+ } else if ([self.wwwFolderName rangeOfString:@"://"].location != NSNotFound) {
+ appURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/%@", self.wwwFolderName, self.startPage]];
+ } else {
+ // CB-3005 strip parameters from start page to check if page exists in resources
+ NSURL* startURL = [NSURL URLWithString:self.startPage];
+ NSString* startFilePath = [self.commandDelegate pathForResource:[startURL path]];
+
+ if (startFilePath == nil) {
+ self.loadFromString = YES;
+ appURL = nil;
+ } else {
+ appURL = [NSURL fileURLWithPath:startFilePath];
+ // CB-3005 Add on the query params or fragment.
+ NSString* startPageNoParentDirs = self.startPage;
+ NSRange r = [startPageNoParentDirs rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"?#"] options:0];
+ if (r.location != NSNotFound) {
+ NSString* queryAndOrFragment = [self.startPage substringFromIndex:r.location];
+ appURL = [NSURL URLWithString:queryAndOrFragment relativeToURL:appURL];
+ }
+ }
+ }
+
+ return appURL;
+}
+
+- (NSURL*)errorUrl
+{
+ NSURL* errorURL = nil;
+
+ id setting = [self settingForKey:@"ErrorUrl"];
+
+ if (setting) {
+ NSString* errorUrlString = (NSString*)setting;
+ if ([errorUrlString rangeOfString:@"://"].location != NSNotFound) {
+ errorURL = [NSURL URLWithString:errorUrlString];
+ } else {
+ NSURL* url = [NSURL URLWithString:(NSString*)setting];
+ NSString* errorFilePath = [self.commandDelegate pathForResource:[url path]];
+ if (errorFilePath) {
+ errorURL = [NSURL fileURLWithPath:errorFilePath];
+ }
+ }
+ }
+
+ return errorURL;
+}
+
+// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+
+ // // Fix the iOS 5.1 SECURITY_ERR bug (CB-347), this must be before the webView is instantiated ////
+
+ NSString* backupWebStorageType = @"cloud"; // default value
+
+ id backupWebStorage = [self settingForKey:@"BackupWebStorage"];
+ if ([backupWebStorage isKindOfClass:[NSString class]]) {
+ backupWebStorageType = backupWebStorage;
+ }
+ [self setSetting:backupWebStorageType forKey:@"BackupWebStorage"];
+
+ if (IsAtLeastiOSVersion(@"5.1")) {
+ [CDVLocalStorage __fixupDatabaseLocationsWithBackupType:backupWebStorageType];
+ }
+
+ // // Instantiate the WebView ///////////////
+
+ if (!self.webView) {
+ [self createGapView];
+ }
+
+ // Configure WebView
+ _webViewDelegate = [[CDVWebViewDelegate alloc] initWithDelegate:self];
+ self.webView.delegate = _webViewDelegate;
+
+ // register this viewcontroller with the NSURLProtocol, only after the User-Agent is set
+ [CDVURLProtocol registerViewController:self];
+
+ // /////////////////
+
+ NSString* enableViewportScale = [self settingForKey:@"EnableViewportScale"];
+ NSNumber* allowInlineMediaPlayback = [self settingForKey:@"AllowInlineMediaPlayback"];
+ BOOL mediaPlaybackRequiresUserAction = YES; // default value
+ if ([self settingForKey:@"MediaPlaybackRequiresUserAction"]) {
+ mediaPlaybackRequiresUserAction = [(NSNumber*)[self settingForKey:@"MediaPlaybackRequiresUserAction"] boolValue];
+ }
+
+ self.webView.scalesPageToFit = [enableViewportScale boolValue];
+
+ /*
+ * Fire up CDVLocalStorage to work-around WebKit storage limitations: on all iOS 5.1+ versions for local-only backups, but only needed on iOS 5.1 for cloud backup.
+ */
+ if (IsAtLeastiOSVersion(@"5.1") && (([backupWebStorageType isEqualToString:@"local"]) ||
+ ([backupWebStorageType isEqualToString:@"cloud"] && !IsAtLeastiOSVersion(@"6.0")))) {
+ [self registerPlugin:[[CDVLocalStorage alloc] initWithWebView:self.webView] withClassName:NSStringFromClass([CDVLocalStorage class])];
+ }
+
+ /*
+ * This is for iOS 4.x, where you can allow inline <video> and <audio>, and also autoplay them
+ */
+ if ([allowInlineMediaPlayback boolValue] && [self.webView respondsToSelector:@selector(allowsInlineMediaPlayback)]) {
+ self.webView.allowsInlineMediaPlayback = YES;
+ }
+ if ((mediaPlaybackRequiresUserAction == NO) && [self.webView respondsToSelector:@selector(mediaPlaybackRequiresUserAction)]) {
+ self.webView.mediaPlaybackRequiresUserAction = NO;
+ }
+
+ // By default, overscroll bouncing is allowed.
+ // UIWebViewBounce has been renamed to DisallowOverscroll, but both are checked.
+ BOOL bounceAllowed = YES;
+ NSNumber* disallowOverscroll = [self settingForKey:@"DisallowOverscroll"];
+ if (disallowOverscroll == nil) {
+ NSNumber* bouncePreference = [self settingForKey:@"UIWebViewBounce"];
+ bounceAllowed = (bouncePreference == nil || [bouncePreference boolValue]);
+ } else {
+ bounceAllowed = ![disallowOverscroll boolValue];
+ }
+
+ // prevent webView from bouncing
+ // based on the DisallowOverscroll/UIWebViewBounce key in config.xml
+ if (!bounceAllowed) {
+ if ([self.webView respondsToSelector:@selector(scrollView)]) {
+ ((UIScrollView*)[self.webView scrollView]).bounces = NO;
+ } else {
+ for (id subview in self.webView.subviews) {
+ if ([[subview class] isSubclassOfClass:[UIScrollView class]]) {
+ ((UIScrollView*)subview).bounces = NO;
+ }
+ }
+ }
+ }
+
+ NSString* decelerationSetting = [self settingForKey:@"UIWebViewDecelerationSpeed"];
+ if (![@"fast" isEqualToString:decelerationSetting]) {
+ [self.webView.scrollView setDecelerationRate:UIScrollViewDecelerationRateNormal];
+ }
+
+ /*
+ * iOS 6.0 UIWebView properties
+ */
+ if (IsAtLeastiOSVersion(@"6.0")) {
+ BOOL keyboardDisplayRequiresUserAction = YES; // KeyboardDisplayRequiresUserAction - defaults to YES
+ if ([self settingForKey:@"KeyboardDisplayRequiresUserAction"] != nil) {
+ if ([self settingForKey:@"KeyboardDisplayRequiresUserAction"]) {
+ keyboardDisplayRequiresUserAction = [(NSNumber*)[self settingForKey:@"KeyboardDisplayRequiresUserAction"] boolValue];
+ }
+ }
+
+ // property check for compiling under iOS < 6
+ if ([self.webView respondsToSelector:@selector(setKeyboardDisplayRequiresUserAction:)]) {
+ [self.webView setValue:[NSNumber numberWithBool:keyboardDisplayRequiresUserAction] forKey:@"keyboardDisplayRequiresUserAction"];
+ }
+
+ BOOL suppressesIncrementalRendering = NO; // SuppressesIncrementalRendering - defaults to NO
+ if ([self settingForKey:@"SuppressesIncrementalRendering"] != nil) {
+ if ([self settingForKey:@"SuppressesIncrementalRendering"]) {
+ suppressesIncrementalRendering = [(NSNumber*)[self settingForKey:@"SuppressesIncrementalRendering"] boolValue];
+ }
+ }
+
+ // property check for compiling under iOS < 6
+ if ([self.webView respondsToSelector:@selector(setSuppressesIncrementalRendering:)]) {
+ [self.webView setValue:[NSNumber numberWithBool:suppressesIncrementalRendering] forKey:@"suppressesIncrementalRendering"];
+ }
+ }
+
+ /*
+ * iOS 7.0 UIWebView properties
+ */
+ if (IsAtLeastiOSVersion(@"7.0")) {
+ SEL ios7sel = nil;
+ id prefObj = nil;
+
+ CGFloat gapBetweenPages = 0.0; // default
+ prefObj = [self settingForKey:@"GapBetweenPages"];
+ if (prefObj != nil) {
+ gapBetweenPages = [prefObj floatValue];
+ }
+
+ // property check for compiling under iOS < 7
+ ios7sel = NSSelectorFromString(@"setGapBetweenPages:");
+ if ([self.webView respondsToSelector:ios7sel]) {
+ [self.webView setValue:[NSNumber numberWithFloat:gapBetweenPages] forKey:@"gapBetweenPages"];
+ }
+
+ CGFloat pageLength = 0.0; // default
+ prefObj = [self settingForKey:@"PageLength"];
+ if (prefObj != nil) {
+ pageLength = [[self settingForKey:@"PageLength"] floatValue];
+ }
+
+ // property check for compiling under iOS < 7
+ ios7sel = NSSelectorFromString(@"setPageLength:");
+ if ([self.webView respondsToSelector:ios7sel]) {
+ [self.webView setValue:[NSNumber numberWithBool:pageLength] forKey:@"pageLength"];
+ }
+
+ NSInteger paginationBreakingMode = 0; // default - UIWebPaginationBreakingModePage
+ prefObj = [self settingForKey:@"PaginationBreakingMode"];
+ if (prefObj != nil) {
+ NSArray* validValues = @[@"page", @"column"];
+ NSString* prefValue = [validValues objectAtIndex:0];
+
+ if ([prefObj isKindOfClass:[NSString class]]) {
+ prefValue = prefObj;
+ }
+
+ paginationBreakingMode = [validValues indexOfObject:[prefValue lowercaseString]];
+ if (paginationBreakingMode == NSNotFound) {
+ paginationBreakingMode = 0;
+ }
+ }
+
+ // property check for compiling under iOS < 7
+ ios7sel = NSSelectorFromString(@"setPaginationBreakingMode:");
+ if ([self.webView respondsToSelector:ios7sel]) {
+ [self.webView setValue:[NSNumber numberWithInteger:paginationBreakingMode] forKey:@"paginationBreakingMode"];
+ }
+
+ NSInteger paginationMode = 0; // default - UIWebPaginationModeUnpaginated
+ prefObj = [self settingForKey:@"PaginationMode"];
+ if (prefObj != nil) {
+ NSArray* validValues = @[@"unpaginated", @"lefttoright", @"toptobottom", @"bottomtotop", @"righttoleft"];
+ NSString* prefValue = [validValues objectAtIndex:0];
+
+ if ([prefObj isKindOfClass:[NSString class]]) {
+ prefValue = prefObj;
+ }
+
+ paginationMode = [validValues indexOfObject:[prefValue lowercaseString]];
+ if (paginationMode == NSNotFound) {
+ paginationMode = 0;
+ }
+ }
+
+ // property check for compiling under iOS < 7
+ ios7sel = NSSelectorFromString(@"setPaginationMode:");
+ if ([self.webView respondsToSelector:ios7sel]) {
+ [self.webView setValue:[NSNumber numberWithInteger:paginationMode] forKey:@"paginationMode"];
+ }
+ }
+
+ if ([self.startupPluginNames count] > 0) {
+ [CDVTimer start:@"TotalPluginStartup"];
+
+ for (NSString* pluginName in self.startupPluginNames) {
+ [CDVTimer start:pluginName];
+ [self getCommandInstance:pluginName];
+ [CDVTimer stop:pluginName];
+ }
+
+ [CDVTimer stop:@"TotalPluginStartup"];
+ }
+
+ [self registerPlugin:[[CDVHandleOpenURL alloc] initWithWebView:self.webView] withClassName:NSStringFromClass([CDVHandleOpenURL class])];
+
+ // /////////////////
+ NSURL* appURL = [self appUrl];
+
+ [CDVUserAgentUtil acquireLock:^(NSInteger lockToken) {
+ _userAgentLockToken = lockToken;
+ [CDVUserAgentUtil setUserAgent:self.userAgent lockToken:lockToken];
+ if (appURL) {
+ NSURLRequest* appReq = [NSURLRequest requestWithURL:appURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
+ [self.webView loadRequest:appReq];
+ } else {
+ NSString* loadErr = [NSString stringWithFormat:@"ERROR: Start Page at '%@/%@' was not found.", self.wwwFolderName, self.startPage];
+ NSLog(@"%@", loadErr);
+
+ NSURL* errorUrl = [self errorUrl];
+ if (errorUrl) {
+ errorUrl = [NSURL URLWithString:[NSString stringWithFormat:@"?error=%@", [loadErr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] relativeToURL:errorUrl];
+ NSLog(@"%@", [errorUrl absoluteString]);
+ [self.webView loadRequest:[NSURLRequest requestWithURL:errorUrl]];
+ } else {
+ NSString* html = [NSString stringWithFormat:@"<html><body> %@ </body></html>", loadErr];
+ [self.webView loadHTMLString:html baseURL:nil];
+ }
+ }
+ }];
+}
+
+- (id)settingForKey:(NSString*)key
+{
+ return [[self settings] objectForKey:[key lowercaseString]];
+}
+
+- (void)setSetting:(id)setting forKey:(NSString*)key
+{
+ [[self settings] setObject:setting forKey:[key lowercaseString]];
+}
+
+- (NSArray*)parseInterfaceOrientations:(NSArray*)orientations
+{
+ NSMutableArray* result = [[NSMutableArray alloc] init];
+
+ if (orientations != nil) {
+ NSEnumerator* enumerator = [orientations objectEnumerator];
+ NSString* orientationString;
+
+ while (orientationString = [enumerator nextObject]) {
+ if ([orientationString isEqualToString:@"UIInterfaceOrientationPortrait"]) {
+ [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationPortrait]];
+ } else if ([orientationString isEqualToString:@"UIInterfaceOrientationPortraitUpsideDown"]) {
+ [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationPortraitUpsideDown]];
+ } else if ([orientationString isEqualToString:@"UIInterfaceOrientationLandscapeLeft"]) {
+ [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]];
+ } else if ([orientationString isEqualToString:@"UIInterfaceOrientationLandscapeRight"]) {
+ [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight]];
+ }
+ }
+ }
+
+ // default
+ if ([result count] == 0) {
+ [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationPortrait]];
+ }
+
+ return result;
+}
+
+- (NSInteger)mapIosOrientationToJsOrientation:(UIInterfaceOrientation)orientation
+{
+ switch (orientation) {
+ case UIInterfaceOrientationPortraitUpsideDown:
+ return 180;
+
+ case UIInterfaceOrientationLandscapeLeft:
+ return -90;
+
+ case UIInterfaceOrientationLandscapeRight:
+ return 90;
+
+ case UIInterfaceOrientationPortrait:
+ return 0;
+
+ default:
+ return 0;
+ }
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ // First, ask the webview via JS if it supports the new orientation
+ NSString* jsCall = [NSString stringWithFormat:
+ @"window.shouldRotateToOrientation && window.shouldRotateToOrientation(%ld);"
+ , (long)[self mapIosOrientationToJsOrientation:interfaceOrientation]];
+ NSString* res = [webView stringByEvaluatingJavaScriptFromString:jsCall];
+
+ if ([res length] > 0) {
+ return [res boolValue];
+ }
+
+ // if js did not handle the new orientation (no return value), use values from the plist (via supportedOrientations)
+ return [self supportsOrientation:interfaceOrientation];
+}
+
+- (BOOL)shouldAutorotate
+{
+ return YES;
+}
+
+- (NSUInteger)supportedInterfaceOrientations
+{
+ NSUInteger ret = 0;
+
+ if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortrait]) {
+ ret = ret | (1 << UIInterfaceOrientationPortrait);
+ }
+ if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortraitUpsideDown]) {
+ ret = ret | (1 << UIInterfaceOrientationPortraitUpsideDown);
+ }
+ if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeRight]) {
+ ret = ret | (1 << UIInterfaceOrientationLandscapeRight);
+ }
+ if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeLeft]) {
+ ret = ret | (1 << UIInterfaceOrientationLandscapeLeft);
+ }
+
+ return ret;
+}
+
+- (BOOL)supportsOrientation:(UIInterfaceOrientation)orientation
+{
+ return [self.supportedOrientations containsObject:[NSNumber numberWithInt:orientation]];
+}
+
+- (UIWebView*)newCordovaViewWithFrame:(CGRect)bounds
+{
+ return [[UIWebView alloc] initWithFrame:bounds];
+}
+
+- (NSString*)userAgent
+{
+ if (_userAgent == nil) {
+ NSString* localBaseUserAgent;
+ if (self.baseUserAgent != nil) {
+ localBaseUserAgent = self.baseUserAgent;
+ } else {
+ localBaseUserAgent = [CDVUserAgentUtil originalUserAgent];
+ }
+ // Use our address as a unique number to append to the User-Agent.
+ _userAgent = [NSString stringWithFormat:@"%@ (%lld)", localBaseUserAgent, (long long)self];
+ }
+ return _userAgent;
+}
+
+- (void)createGapView
+{
+ CGRect webViewBounds = self.view.bounds;
+
+ webViewBounds.origin = self.view.bounds.origin;
+
+ self.webView = [self newCordovaViewWithFrame:webViewBounds];
+ self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+
+ [self.view addSubview:self.webView];
+ [self.view sendSubviewToBack:self.webView];
+}
+
+- (void)didReceiveMemoryWarning
+{
+ // iterate through all the plugin objects, and call hasPendingOperation
+ // if at least one has a pending operation, we don't call [super didReceiveMemoryWarning]
+
+ NSEnumerator* enumerator = [self.pluginObjects objectEnumerator];
+ CDVPlugin* plugin;
+
+ BOOL doPurge = YES;
+
+ while ((plugin = [enumerator nextObject])) {
+ if (plugin.hasPendingOperation) {
+ NSLog(@"Plugin '%@' has a pending operation, memory purge is delayed for didReceiveMemoryWarning.", NSStringFromClass([plugin class]));
+ doPurge = NO;
+ }
+ }
+
+ if (doPurge) {
+ // Releases the view if it doesn't have a superview.
+ [super didReceiveMemoryWarning];
+ }
+
+ // Release any cached data, images, etc. that aren't in use.
+}
+
+- (void)viewDidUnload
+{
+ // Release any retained subviews of the main view.
+ // e.g. self.myOutlet = nil;
+
+ self.webView.delegate = nil;
+ self.webView = nil;
+ [CDVUserAgentUtil releaseLock:&_userAgentLockToken];
+
+ [super viewDidUnload];
+}
+
+#pragma mark UIWebViewDelegate
+
+/**
+ When web application loads Add stuff to the DOM, mainly the user-defined settings from the Settings.plist file, and
+ the device's data such as device ID, platform version, etc.
+ */
+- (void)webViewDidStartLoad:(UIWebView*)theWebView
+{
+ NSLog(@"Resetting plugins due to page load.");
+ [_commandQueue resetRequestId];
+ [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginResetNotification object:self.webView]];
+}
+
+/**
+ Called when the webview finishes loading. This stops the activity view.
+ */
+- (void)webViewDidFinishLoad:(UIWebView*)theWebView
+{
+ NSLog(@"Finished load of: %@", theWebView.request.URL);
+ // It's safe to release the lock even if this is just a sub-frame that's finished loading.
+ [CDVUserAgentUtil releaseLock:&_userAgentLockToken];
+
+ /*
+ * Hide the Top Activity THROBBER in the Battery Bar
+ */
+ [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
+
+ [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPageDidLoadNotification object:self.webView]];
+}
+
+- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error
+{
+ [CDVUserAgentUtil releaseLock:&_userAgentLockToken];
+
+ NSString* message = [NSString stringWithFormat:@"Failed to load webpage with error: %@", [error localizedDescription]];
+ NSLog(@"%@", message);
+
+ NSURL* errorUrl = [self errorUrl];
+ if (errorUrl) {
+ errorUrl = [NSURL URLWithString:[NSString stringWithFormat:@"?error=%@", [message stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] relativeToURL:errorUrl];
+ NSLog(@"%@", [errorUrl absoluteString]);
+ [theWebView loadRequest:[NSURLRequest requestWithURL:errorUrl]];
+ }
+}
+
+- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
+{
+ NSURL* url = [request URL];
+
+ /*
+ * Execute any commands queued with cordova.exec() on the JS side.
+ * The part of the URL after gap:// is irrelevant.
+ */
+ if ([[url scheme] isEqualToString:@"gap"]) {
+ [_commandQueue fetchCommandsFromJs];
+ // The delegate is called asynchronously in this case, so we don't have to use
+ // flushCommandQueueWithDelayedJs (setTimeout(0)) as we do with hash changes.
+ [_commandQueue executePending];
+ return NO;
+ }
+
+ if ([[url fragment] hasPrefix:@"%01"] || [[url fragment] hasPrefix:@"%02"]) {
+ // Delegate is called *immediately* for hash changes. This means that any
+ // calls to stringByEvaluatingJavascriptFromString will occur in the middle
+ // of an existing (paused) call stack. This doesn't cause errors, but may
+ // be unexpected to callers (exec callbacks will be called before exec() even
+ // returns). To avoid this, we do not do any synchronous JS evals by using
+ // flushCommandQueueWithDelayedJs.
+ NSString* inlineCommands = [[url fragment] substringFromIndex:3];
+ if ([inlineCommands length] == 0) {
+ // Reach in right away since the WebCore / Main thread are already synchronized.
+ [_commandQueue fetchCommandsFromJs];
+ } else {
+ inlineCommands = [inlineCommands stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
+ [_commandQueue enqueueCommandBatch:inlineCommands];
+ }
+ // Switch these for minor performance improvements, and to really live on the wild side.
+ // Callbacks will occur in the middle of the location.hash = ... statement!
+ [(CDVCommandDelegateImpl*)_commandDelegate flushCommandQueueWithDelayedJs];
+ // [_commandQueue executePending];
+
+ // Although we return NO, the hash change does end up taking effect.
+ return NO;
+ }
+
+ /*
+ * Give plugins the chance to handle the url
+ */
+ for (NSString* pluginName in pluginObjects) {
+ CDVPlugin* plugin = [pluginObjects objectForKey:pluginName];
+ SEL selector = NSSelectorFromString(@"shouldOverrideLoadWithRequest:navigationType:");
+ if ([plugin respondsToSelector:selector]) {
+ if (((BOOL (*)(id, SEL, id, int))objc_msgSend)(plugin, selector, request, navigationType) == YES) {
+ return NO;
+ }
+ }
+ }
+
+ /*
+ * If a URL is being loaded that's a file/http/https URL, just load it internally
+ */
+ if ([url isFileURL]) {
+ return YES;
+ }
+
+ /*
+ * If we loaded the HTML from a string, we let the app handle it
+ */
+ else if (self.loadFromString == YES) {
+ self.loadFromString = NO;
+ return YES;
+ }
+
+ /*
+ * all tel: scheme urls we let the UIWebview handle it using the default behavior
+ */
+ else if ([[url scheme] isEqualToString:@"tel"]) {
+ return YES;
+ }
+
+ /*
+ * all about: scheme urls are not handled
+ */
+ else if ([[url scheme] isEqualToString:@"about"]) {
+ return NO;
+ }
+
+ /*
+ * all data: scheme urls are handled
+ */
+ else if ([[url scheme] isEqualToString:@"data"]) {
+ return YES;
+ }
+
+ /*
+ * Handle all other types of urls (tel:, sms:), and requests to load a url in the main webview.
+ */
+ else {
+ if ([self.whitelist schemeIsAllowed:[url scheme]]) {
+ return [self.whitelist URLIsAllowed:url];
+ } else {
+ if ([[UIApplication sharedApplication] canOpenURL:url]) {
+ [[UIApplication sharedApplication] openURL:url];
+ } else { // handle any custom schemes to plugins
+ [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]];
+ }
+ }
+
+ return NO;
+ }
+
+ return YES;
+}
+
+#pragma mark GapHelpers
+
+- (void)javascriptAlert:(NSString*)text
+{
+ NSString* jsString = [NSString stringWithFormat:@"alert('%@');", text];
+
+ [self.commandDelegate evalJs:jsString];
+}
+
++ (NSString*)applicationDocumentsDirectory
+{
+ NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ NSString* basePath = (([paths count] > 0) ? ([paths objectAtIndex : 0]) : nil);
+
+ return basePath;
+}
+
+#pragma mark CordovaCommands
+
+- (void)registerPlugin:(CDVPlugin*)plugin withClassName:(NSString*)className
+{
+ if ([plugin respondsToSelector:@selector(setViewController:)]) {
+ [plugin setViewController:self];
+ }
+
+ if ([plugin respondsToSelector:@selector(setCommandDelegate:)]) {
+ [plugin setCommandDelegate:_commandDelegate];
+ }
+
+ [self.pluginObjects setObject:plugin forKey:className];
+ [plugin pluginInitialize];
+}
+
+- (void)registerPlugin:(CDVPlugin*)plugin withPluginName:(NSString*)pluginName
+{
+ if ([plugin respondsToSelector:@selector(setViewController:)]) {
+ [plugin setViewController:self];
+ }
+
+ if ([plugin respondsToSelector:@selector(setCommandDelegate:)]) {
+ [plugin setCommandDelegate:_commandDelegate];
+ }
+
+ NSString* className = NSStringFromClass([plugin class]);
+ [self.pluginObjects setObject:plugin forKey:className];
+ [self.pluginsMap setValue:className forKey:[pluginName lowercaseString]];
+ [plugin pluginInitialize];
+}
+
+/**
+ Returns an instance of a CordovaCommand object, based on its name. If one exists already, it is returned.
+ */
+- (id)getCommandInstance:(NSString*)pluginName
+{
+ // first, we try to find the pluginName in the pluginsMap
+ // (acts as a whitelist as well) if it does not exist, we return nil
+ // NOTE: plugin names are matched as lowercase to avoid problems - however, a
+ // possible issue is there can be duplicates possible if you had:
+ // "org.apache.cordova.Foo" and "org.apache.cordova.foo" - only the lower-cased entry will match
+ NSString* className = [self.pluginsMap objectForKey:[pluginName lowercaseString]];
+
+ if (className == nil) {
+ return nil;
+ }
+
+ id obj = [self.pluginObjects objectForKey:className];
+ if (!obj) {
+ obj = [[NSClassFromString(className)alloc] initWithWebView:webView];
+
+ if (obj != nil) {
+ [self registerPlugin:obj withClassName:className];
+ } else {
+ NSLog(@"CDVPlugin class %@ (pluginName: %@) does not exist.", className, pluginName);
+ }
+ }
+ return obj;
+}
+
+#pragma mark -
+
+- (NSString*)appURLScheme
+{
+ NSString* URLScheme = nil;
+
+ NSArray* URLTypes = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleURLTypes"];
+
+ if (URLTypes != nil) {
+ NSDictionary* dict = [URLTypes objectAtIndex:0];
+ if (dict != nil) {
+ NSArray* URLSchemes = [dict objectForKey:@"CFBundleURLSchemes"];
+ if (URLSchemes != nil) {
+ URLScheme = [URLSchemes objectAtIndex:0];
+ }
+ }
+ }
+
+ return URLScheme;
+}
+
+/**
+ Returns the contents of the named plist bundle, loaded as a dictionary object
+ */
++ (NSDictionary*)getBundlePlist:(NSString*)plistName
+{
+ NSString* errorDesc = nil;
+ NSPropertyListFormat format;
+ NSString* plistPath = [[NSBundle mainBundle] pathForResource:plistName ofType:@"plist"];
+ NSData* plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
+ NSDictionary* temp = (NSDictionary*)[NSPropertyListSerialization
+ propertyListFromData:plistXML
+ mutabilityOption:NSPropertyListMutableContainersAndLeaves
+ format:&format errorDescription:&errorDesc];
+
+ return temp;
+}
+
+#pragma mark -
+#pragma mark UIApplicationDelegate impl
+
+/*
+ This method lets your application know that it is about to be terminated and purged from memory entirely
+ */
+- (void)onAppWillTerminate:(NSNotification*)notification
+{
+ // empty the tmp directory
+ NSFileManager* fileMgr = [[NSFileManager alloc] init];
+ NSError* __autoreleasing err = nil;
+
+ // clear contents of NSTemporaryDirectory
+ NSString* tempDirectoryPath = NSTemporaryDirectory();
+ NSDirectoryEnumerator* directoryEnumerator = [fileMgr enumeratorAtPath:tempDirectoryPath];
+ NSString* fileName = nil;
+ BOOL result;
+
+ while ((fileName = [directoryEnumerator nextObject])) {
+ NSString* filePath = [tempDirectoryPath stringByAppendingPathComponent:fileName];
+ result = [fileMgr removeItemAtPath:filePath error:&err];
+ if (!result && err) {
+ NSLog(@"Failed to delete: %@ (error: %@)", filePath, err);
+ }
+ }
+}
+
+/*
+ This method is called to let your application know that it is about to move from the active to inactive state.
+ You should use this method to pause ongoing tasks, disable timer, ...
+ */
+- (void)onAppWillResignActive:(NSNotification*)notification
+{
+ // NSLog(@"%@",@"applicationWillResignActive");
+ [self.commandDelegate evalJs:@"cordova.fireDocumentEvent('resign');" scheduledOnRunLoop:NO];
+}
+
+/*
+ In iOS 4.0 and later, this method is called as part of the transition from the background to the inactive state.
+ You can use this method to undo many of the changes you made to your application upon entering the background.
+ invariably followed by applicationDidBecomeActive
+ */
+- (void)onAppWillEnterForeground:(NSNotification*)notification
+{
+ // NSLog(@"%@",@"applicationWillEnterForeground");
+ [self.commandDelegate evalJs:@"cordova.fireDocumentEvent('resume');"];
+}
+
+// This method is called to let your application know that it moved from the inactive to active state.
+- (void)onAppDidBecomeActive:(NSNotification*)notification
+{
+ // NSLog(@"%@",@"applicationDidBecomeActive");
+ [self.commandDelegate evalJs:@"cordova.fireDocumentEvent('active');"];
+}
+
+/*
+ In iOS 4.0 and later, this method is called instead of the applicationWillTerminate: method
+ when the user quits an application that supports background execution.
+ */
+- (void)onAppDidEnterBackground:(NSNotification*)notification
+{
+ // NSLog(@"%@",@"applicationDidEnterBackground");
+ [self.commandDelegate evalJs:@"cordova.fireDocumentEvent('pause', null, true);" scheduledOnRunLoop:NO];
+}
+
+// ///////////////////////
+
+- (void)onPageDidLoad:(NSNotification*)notification
+{
+ if (self.openURL) {
+ [self processOpenUrl:self.openURL pageLoaded:YES];
+ self.openURL = nil;
+ }
+}
+
+- (void)processOpenUrl:(NSURL*)url pageLoaded:(BOOL)pageLoaded
+{
+ if (!pageLoaded) {
+ // query the webview for readystate
+ NSString* readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"];
+ pageLoaded = [readyState isEqualToString:@"loaded"] || [readyState isEqualToString:@"complete"];
+ }
+
+ if (pageLoaded) {
+ // calls into javascript global function 'handleOpenURL'
+ NSString* jsString = [NSString stringWithFormat:@"if (typeof handleOpenURL === 'function') { handleOpenURL(\"%@\");}", url];
+ [self.webView stringByEvaluatingJavaScriptFromString:jsString];
+ } else {
+ // save for when page has loaded
+ self.openURL = url;
+ }
+}
+
+- (void)processOpenUrl:(NSURL*)url
+{
+ [self processOpenUrl:url pageLoaded:NO];
+}
+
+// ///////////////////////
+
+- (void)dealloc
+{
+ [CDVURLProtocol unregisterViewController:self];
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+ self.webView.delegate = nil;
+ self.webView = nil;
+ [CDVUserAgentUtil releaseLock:&_userAgentLockToken];
+ [_commandQueue dispose];
+ [[self.pluginObjects allValues] makeObjectsPerformSelector:@selector(dispose)];
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWebViewDelegate.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWebViewDelegate.h
new file mode 100644
index 00000000..f6c419f7
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWebViewDelegate.h
@@ -0,0 +1,41 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <UIKit/UIKit.h>
+#import "CDVAvailability.h"
+
+/**
+ * Distinguishes top-level navigations from sub-frame navigations.
+ * shouldStartLoadWithRequest is called for every request, but didStartLoad
+ * and didFinishLoad is called only for top-level navigations.
+ * Relevant bug: CB-2389
+ */
+@interface CDVWebViewDelegate : NSObject <UIWebViewDelegate>{
+ __weak NSObject <UIWebViewDelegate>* _delegate;
+ NSInteger _loadCount;
+ NSInteger _state;
+ NSInteger _curLoadToken;
+ NSInteger _loadStartPollCount;
+}
+
+- (id)initWithDelegate:(NSObject <UIWebViewDelegate>*)delegate;
+
+- (BOOL)request:(NSURLRequest*)newRequest isEqualToRequestAfterStrippingFragments:(NSURLRequest*)originalRequest;
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWebViewDelegate.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWebViewDelegate.m
new file mode 100644
index 00000000..514827e5
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWebViewDelegate.m
@@ -0,0 +1,412 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+//
+// Testing shows:
+//
+// In all cases, webView.request.URL is the previous page's URL (or empty) during the didStartLoad callback.
+// When loading a page with a redirect:
+// 1. shouldStartLoading (requestURL is target page)
+// 2. didStartLoading
+// 3. shouldStartLoading (requestURL is redirect target)
+// 4. didFinishLoad (request.URL is redirect target)
+//
+// Note the lack of a second didStartLoading **
+//
+// When loading a page with iframes:
+// 1. shouldStartLoading (requestURL is main page)
+// 2. didStartLoading
+// 3. shouldStartLoading (requestURL is one of the iframes)
+// 4. didStartLoading
+// 5. didFinishLoad
+// 6. didFinishLoad
+//
+// Note there is no way to distinguish which didFinishLoad maps to which didStartLoad **
+//
+// Loading a page by calling window.history.go(-1):
+// 1. didStartLoading
+// 2. didFinishLoad
+//
+// Note the lack of a shouldStartLoading call **
+// Actually - this is fixed on iOS6. iOS6 has a shouldStart. **
+//
+// Loading a page by calling location.reload()
+// 1. shouldStartLoading
+// 2. didStartLoading
+// 3. didFinishLoad
+//
+// Loading a page with an iframe that fails to load:
+// 1. shouldStart (main page)
+// 2. didStart
+// 3. shouldStart (iframe)
+// 4. didStart
+// 5. didFailWithError
+// 6. didFinish
+//
+// Loading a page with an iframe that fails to load due to an invalid URL:
+// 1. shouldStart (main page)
+// 2. didStart
+// 3. shouldStart (iframe)
+// 5. didFailWithError
+// 6. didFinish
+//
+// This case breaks our logic since there is a missing didStart. To prevent this,
+// we check URLs in shouldStart and return NO if they are invalid.
+//
+// Loading a page with an invalid URL
+// 1. shouldStart (main page)
+// 2. didFailWithError
+//
+// TODO: Record order when page is re-navigated before the first navigation finishes.
+//
+
+#import "CDVWebViewDelegate.h"
+#import "CDVAvailability.h"
+
+// #define VerboseLog NSLog
+#define VerboseLog(...) do {} while (0)
+
+typedef enum {
+ STATE_IDLE = 0,
+ STATE_WAITING_FOR_LOAD_START = 1,
+ STATE_WAITING_FOR_LOAD_FINISH = 2,
+ STATE_IOS5_POLLING_FOR_LOAD_START = 3,
+ STATE_IOS5_POLLING_FOR_LOAD_FINISH = 4,
+ STATE_CANCELLED = 5
+} State;
+
+static NSString *stripFragment(NSString* url)
+{
+ NSRange r = [url rangeOfString:@"#"];
+
+ if (r.location == NSNotFound) {
+ return url;
+ }
+ return [url substringToIndex:r.location];
+}
+
+@implementation CDVWebViewDelegate
+
+- (id)initWithDelegate:(NSObject <UIWebViewDelegate>*)delegate
+{
+ self = [super init];
+ if (self != nil) {
+ _delegate = delegate;
+ _loadCount = -1;
+ _state = STATE_IDLE;
+ }
+ return self;
+}
+
+- (BOOL)request:(NSURLRequest*)newRequest isEqualToRequestAfterStrippingFragments:(NSURLRequest*)originalRequest
+{
+ if (originalRequest.URL && newRequest.URL) {
+ NSString* originalRequestUrl = [originalRequest.URL absoluteString];
+ NSString* newRequestUrl = [newRequest.URL absoluteString];
+
+ NSString* baseOriginalRequestUrl = stripFragment(originalRequestUrl);
+ NSString* baseNewRequestUrl = stripFragment(newRequestUrl);
+ return [baseOriginalRequestUrl isEqualToString:baseNewRequestUrl];
+ }
+
+ return NO;
+}
+
+- (BOOL)isPageLoaded:(UIWebView*)webView
+{
+ NSString* readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"];
+
+ return [readyState isEqualToString:@"loaded"] || [readyState isEqualToString:@"complete"];
+}
+
+- (BOOL)isJsLoadTokenSet:(UIWebView*)webView
+{
+ NSString* loadToken = [webView stringByEvaluatingJavaScriptFromString:@"window.__cordovaLoadToken"];
+
+ return [[NSString stringWithFormat:@"%ld", (long)_curLoadToken] isEqualToString:loadToken];
+}
+
+- (void)setLoadToken:(UIWebView*)webView
+{
+ _curLoadToken += 1;
+ [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.__cordovaLoadToken=%ld", (long)_curLoadToken]];
+}
+
+- (NSString*)evalForCurrentURL:(UIWebView*)webView
+{
+ return [webView stringByEvaluatingJavaScriptFromString:@"location.href"];
+}
+
+- (void)pollForPageLoadStart:(UIWebView*)webView
+{
+ if (_state != STATE_IOS5_POLLING_FOR_LOAD_START) {
+ return;
+ }
+ if (![self isJsLoadTokenSet:webView]) {
+ VerboseLog(@"Polled for page load start. result = YES!");
+ _state = STATE_IOS5_POLLING_FOR_LOAD_FINISH;
+ [self setLoadToken:webView];
+ if ([_delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
+ [_delegate webViewDidStartLoad:webView];
+ }
+ [self pollForPageLoadFinish:webView];
+ } else {
+ VerboseLog(@"Polled for page load start. result = NO");
+ // Poll only for 1 second, and then fall back on checking only when delegate methods are called.
+ ++_loadStartPollCount;
+ if (_loadStartPollCount < (1000 * .05)) {
+ [self performSelector:@selector(pollForPageLoadStart:) withObject:webView afterDelay:.05];
+ }
+ }
+}
+
+- (void)pollForPageLoadFinish:(UIWebView*)webView
+{
+ if (_state != STATE_IOS5_POLLING_FOR_LOAD_FINISH) {
+ return;
+ }
+ if ([self isPageLoaded:webView]) {
+ VerboseLog(@"Polled for page load finish. result = YES!");
+ _state = STATE_IDLE;
+ if ([_delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
+ [_delegate webViewDidFinishLoad:webView];
+ }
+ } else {
+ VerboseLog(@"Polled for page load finish. result = NO");
+ [self performSelector:@selector(pollForPageLoadFinish:) withObject:webView afterDelay:.05];
+ }
+}
+
+- (BOOL)shouldLoadRequest:(NSURLRequest*)request
+{
+ NSString* scheme = [[request URL] scheme];
+
+ if ([scheme isEqualToString:@"mailto"] || [scheme isEqualToString:@"tel"]) {
+ return YES;
+ }
+
+ return [NSURLConnection canHandleRequest:request];
+}
+
+- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
+{
+ BOOL shouldLoad = YES;
+
+ if ([_delegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {
+ shouldLoad = [_delegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
+ }
+
+ VerboseLog(@"webView shouldLoad=%d (before) state=%d loadCount=%d URL=%@", shouldLoad, _state, _loadCount, request.URL);
+
+ if (shouldLoad) {
+ // When devtools refresh occurs, it blindly uses the same request object. If a history.replaceState() has occured, then
+ // mainDocumentURL != URL even though it's a top-level navigation.
+ BOOL isDevToolsRefresh = (request == webView.request);
+ BOOL isTopLevelNavigation = isDevToolsRefresh || [request.URL isEqual:[request mainDocumentURL]];
+ if (isTopLevelNavigation) {
+ // Ignore hash changes that don't navigate to a different page.
+ // webView.request does actually update when history.replaceState() gets called.
+ if ([self request:request isEqualToRequestAfterStrippingFragments:webView.request]) {
+ NSString* prevURL = [self evalForCurrentURL:webView];
+ if ([prevURL isEqualToString:[request.URL absoluteString]]) {
+ VerboseLog(@"Page reload detected.");
+ } else {
+ VerboseLog(@"Detected hash change shouldLoad");
+ return shouldLoad;
+ }
+ }
+
+ switch (_state) {
+ case STATE_WAITING_FOR_LOAD_FINISH:
+ // Redirect case.
+ // We expect loadCount == 1.
+ if (_loadCount != 1) {
+ NSLog(@"CDVWebViewDelegate: Detected redirect when loadCount=%ld", (long)_loadCount);
+ }
+ break;
+
+ case STATE_IDLE:
+ case STATE_IOS5_POLLING_FOR_LOAD_START:
+ case STATE_CANCELLED:
+ // Page navigation start.
+ _loadCount = 0;
+ _state = STATE_WAITING_FOR_LOAD_START;
+ break;
+
+ default:
+ {
+ _loadCount = 0;
+ _state = STATE_WAITING_FOR_LOAD_START;
+ NSString* description = [NSString stringWithFormat:@"CDVWebViewDelegate: Navigation started when state=%ld", (long)_state];
+ NSLog(@"%@", description);
+ if ([_delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
+ NSDictionary* errorDictionary = @{NSLocalizedDescriptionKey : description};
+ NSError* error = [[NSError alloc] initWithDomain:@"CDVWebViewDelegate" code:1 userInfo:errorDictionary];
+ [_delegate webView:webView didFailLoadWithError:error];
+ }
+ }
+ }
+ } else {
+ // Deny invalid URLs so that we don't get the case where we go straight from
+ // webViewShouldLoad -> webViewDidFailLoad (messes up _loadCount).
+ shouldLoad = shouldLoad && [self shouldLoadRequest:request];
+ }
+ VerboseLog(@"webView shouldLoad=%d (after) isTopLevelNavigation=%d state=%d loadCount=%d", shouldLoad, isTopLevelNavigation, _state, _loadCount);
+ }
+ return shouldLoad;
+}
+
+- (void)webViewDidStartLoad:(UIWebView*)webView
+{
+ VerboseLog(@"webView didStartLoad (before). state=%d loadCount=%d", _state, _loadCount);
+ BOOL fireCallback = NO;
+ switch (_state) {
+ case STATE_IDLE:
+ if (IsAtLeastiOSVersion(@"6.0")) {
+ break;
+ }
+ // If history.go(-1) is used pre-iOS6, the shouldStartLoadWithRequest function is not called.
+ // Without shouldLoad, we can't distinguish an iframe from a top-level navigation.
+ // We could try to distinguish using [UIWebView canGoForward], but that's too much complexity,
+ // and would work only on the first time it was used.
+
+ // Our work-around is to set a JS variable and poll until it disappears (from a navigation).
+ _state = STATE_IOS5_POLLING_FOR_LOAD_START;
+ _loadStartPollCount = 0;
+ [self setLoadToken:webView];
+ [self pollForPageLoadStart:webView];
+ break;
+
+ case STATE_CANCELLED:
+ fireCallback = YES;
+ _state = STATE_WAITING_FOR_LOAD_FINISH;
+ _loadCount += 1;
+ break;
+
+ case STATE_WAITING_FOR_LOAD_START:
+ if (_loadCount != 0) {
+ NSLog(@"CDVWebViewDelegate: Unexpected loadCount in didStart. count=%ld", (long)_loadCount);
+ }
+ fireCallback = YES;
+ _state = STATE_WAITING_FOR_LOAD_FINISH;
+ _loadCount = 1;
+ break;
+
+ case STATE_WAITING_FOR_LOAD_FINISH:
+ _loadCount += 1;
+ break;
+
+ case STATE_IOS5_POLLING_FOR_LOAD_START:
+ [self pollForPageLoadStart:webView];
+ break;
+
+ case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
+ [self pollForPageLoadFinish:webView];
+ break;
+
+ default:
+ NSLog(@"CDVWebViewDelegate: Unexpected didStart with state=%ld loadCount=%ld", (long)_state, (long)_loadCount);
+ }
+ VerboseLog(@"webView didStartLoad (after). state=%d loadCount=%d fireCallback=%d", _state, _loadCount, fireCallback);
+ if (fireCallback && [_delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
+ [_delegate webViewDidStartLoad:webView];
+ }
+}
+
+- (void)webViewDidFinishLoad:(UIWebView*)webView
+{
+ VerboseLog(@"webView didFinishLoad (before). state=%d loadCount=%d", _state, _loadCount);
+ BOOL fireCallback = NO;
+ switch (_state) {
+ case STATE_IDLE:
+ break;
+
+ case STATE_WAITING_FOR_LOAD_START:
+ NSLog(@"CDVWebViewDelegate: Unexpected didFinish while waiting for load start.");
+ break;
+
+ case STATE_WAITING_FOR_LOAD_FINISH:
+ if (_loadCount == 1) {
+ fireCallback = YES;
+ _state = STATE_IDLE;
+ }
+ _loadCount -= 1;
+ break;
+
+ case STATE_IOS5_POLLING_FOR_LOAD_START:
+ [self pollForPageLoadStart:webView];
+ break;
+
+ case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
+ [self pollForPageLoadFinish:webView];
+ break;
+ }
+ VerboseLog(@"webView didFinishLoad (after). state=%d loadCount=%d fireCallback=%d", _state, _loadCount, fireCallback);
+ if (fireCallback && [_delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
+ [_delegate webViewDidFinishLoad:webView];
+ }
+}
+
+- (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error
+{
+ VerboseLog(@"webView didFailLoad (before). state=%d loadCount=%d", _state, _loadCount);
+ BOOL fireCallback = NO;
+
+ switch (_state) {
+ case STATE_IDLE:
+ break;
+
+ case STATE_WAITING_FOR_LOAD_START:
+ if ([error code] == NSURLErrorCancelled) {
+ _state = STATE_CANCELLED;
+ } else {
+ _state = STATE_IDLE;
+ }
+ fireCallback = YES;
+ break;
+
+ case STATE_WAITING_FOR_LOAD_FINISH:
+ if ([error code] != NSURLErrorCancelled) {
+ if (_loadCount == 1) {
+ _state = STATE_IDLE;
+ fireCallback = YES;
+ }
+ _loadCount = -1;
+ } else {
+ fireCallback = YES;
+ _state = STATE_CANCELLED;
+ _loadCount -= 1;
+ }
+ break;
+
+ case STATE_IOS5_POLLING_FOR_LOAD_START:
+ [self pollForPageLoadStart:webView];
+ break;
+
+ case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
+ [self pollForPageLoadFinish:webView];
+ break;
+ }
+ VerboseLog(@"webView didFailLoad (after). state=%d loadCount=%d, fireCallback=%d", _state, _loadCount, fireCallback);
+ if (fireCallback && [_delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
+ [_delegate webView:webView didFailLoadWithError:error];
+ }
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWhitelist.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWhitelist.h
new file mode 100644
index 00000000..91650970
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWhitelist.h
@@ -0,0 +1,34 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+extern NSString* const kCDVDefaultWhitelistRejectionString;
+
+@interface CDVWhitelist : NSObject
+
+@property (nonatomic, copy) NSString* whitelistRejectionFormatString;
+
+- (id)initWithArray:(NSArray*)array;
+- (BOOL)schemeIsAllowed:(NSString*)scheme;
+- (BOOL)URLIsAllowed:(NSURL*)url;
+- (BOOL)URLIsAllowed:(NSURL*)url logFailure:(BOOL)logFailure;
+- (NSString*)errorStringForURL:(NSURL*)url;
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWhitelist.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWhitelist.m
new file mode 100644
index 00000000..8e3be752
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWhitelist.m
@@ -0,0 +1,285 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVWhitelist.h"
+
+NSString* const kCDVDefaultWhitelistRejectionString = @"ERROR whitelist rejection: url='%@'";
+NSString* const kCDVDefaultSchemeName = @"cdv-default-scheme";
+
+@interface CDVWhitelistPattern : NSObject {
+ @private
+ NSRegularExpression* _scheme;
+ NSRegularExpression* _host;
+ NSNumber* _port;
+ NSRegularExpression* _path;
+}
+
++ (NSString*)regexFromPattern:(NSString*)pattern allowWildcards:(bool)allowWildcards;
+- (id)initWithScheme:(NSString*)scheme host:(NSString*)host port:(NSString*)port path:(NSString*)path;
+- (bool)matches:(NSURL*)url;
+
+@end
+
+@implementation CDVWhitelistPattern
+
++ (NSString*)regexFromPattern:(NSString*)pattern allowWildcards:(bool)allowWildcards
+{
+ NSString* regex = [NSRegularExpression escapedPatternForString:pattern];
+
+ if (allowWildcards) {
+ regex = [regex stringByReplacingOccurrencesOfString:@"\\*" withString:@".*"];
+
+ /* [NSURL path] has the peculiarity that a trailing slash at the end of a path
+ * will be omitted. This regex tweak compensates for that.
+ */
+ if ([regex hasSuffix:@"\\/.*"]) {
+ regex = [NSString stringWithFormat:@"%@(\\/.*)?", [regex substringToIndex:([regex length] - 4)]];
+ }
+ }
+ return [NSString stringWithFormat:@"%@$", regex];
+}
+
+- (id)initWithScheme:(NSString*)scheme host:(NSString*)host port:(NSString*)port path:(NSString*)path
+{
+ self = [super init]; // Potentially change "self"
+ if (self) {
+ if ((scheme == nil) || [scheme isEqualToString:@"*"]) {
+ _scheme = nil;
+ } else {
+ _scheme = [NSRegularExpression regularExpressionWithPattern:[CDVWhitelistPattern regexFromPattern:scheme allowWildcards:NO] options:NSRegularExpressionCaseInsensitive error:nil];
+ }
+ if ([host isEqualToString:@"*"]) {
+ _host = nil;
+ } else if ([host hasPrefix:@"*."]) {
+ _host = [NSRegularExpression regularExpressionWithPattern:[NSString stringWithFormat:@"([a-z0-9.-]*\\.)?%@", [CDVWhitelistPattern regexFromPattern:[host substringFromIndex:2] allowWildcards:false]] options:NSRegularExpressionCaseInsensitive error:nil];
+ } else {
+ _host = [NSRegularExpression regularExpressionWithPattern:[CDVWhitelistPattern regexFromPattern:host allowWildcards:NO] options:NSRegularExpressionCaseInsensitive error:nil];
+ }
+ if ((port == nil) || [port isEqualToString:@"*"]) {
+ _port = nil;
+ } else {
+ _port = [[NSNumber alloc] initWithInteger:[port integerValue]];
+ }
+ if ((path == nil) || [path isEqualToString:@"/*"]) {
+ _path = nil;
+ } else {
+ _path = [NSRegularExpression regularExpressionWithPattern:[CDVWhitelistPattern regexFromPattern:path allowWildcards:YES] options:0 error:nil];
+ }
+ }
+ return self;
+}
+
+- (bool)matches:(NSURL*)url
+{
+ return (_scheme == nil || [_scheme numberOfMatchesInString:[url scheme] options:NSMatchingAnchored range:NSMakeRange(0, [[url scheme] length])]) &&
+ (_host == nil || [_host numberOfMatchesInString:[url host] options:NSMatchingAnchored range:NSMakeRange(0, [[url host] length])]) &&
+ (_port == nil || [[url port] isEqualToNumber:_port]) &&
+ (_path == nil || [_path numberOfMatchesInString:[url path] options:NSMatchingAnchored range:NSMakeRange(0, [[url path] length])])
+ ;
+}
+
+@end
+
+@interface CDVWhitelist ()
+
+@property (nonatomic, readwrite, strong) NSMutableArray* whitelist;
+@property (nonatomic, readwrite, strong) NSMutableSet* permittedSchemes;
+
+- (void)addWhiteListEntry:(NSString*)pattern;
+
+@end
+
+@implementation CDVWhitelist
+
+@synthesize whitelist, permittedSchemes, whitelistRejectionFormatString;
+
+- (id)initWithArray:(NSArray*)array
+{
+ self = [super init];
+ if (self) {
+ self.whitelist = [[NSMutableArray alloc] init];
+ self.permittedSchemes = [[NSMutableSet alloc] init];
+ self.whitelistRejectionFormatString = kCDVDefaultWhitelistRejectionString;
+
+ for (NSString* pattern in array) {
+ [self addWhiteListEntry:pattern];
+ }
+ }
+ return self;
+}
+
+- (BOOL)isIPv4Address:(NSString*)externalHost
+{
+ // an IPv4 address has 4 octets b.b.b.b where b is a number between 0 and 255.
+ // for our purposes, b can also be the wildcard character '*'
+
+ // we could use a regex to solve this problem but then I would have two problems
+ // anyways, this is much clearer and maintainable
+ NSArray* octets = [externalHost componentsSeparatedByString:@"."];
+ NSUInteger num_octets = [octets count];
+
+ // quick check
+ if (num_octets != 4) {
+ return NO;
+ }
+
+ // restrict number parsing to 0-255
+ NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init];
+ [numberFormatter setMinimum:[NSNumber numberWithUnsignedInteger:0]];
+ [numberFormatter setMaximum:[NSNumber numberWithUnsignedInteger:255]];
+
+ // iterate through each octet, and test for a number between 0-255 or if it equals '*'
+ for (NSUInteger i = 0; i < num_octets; ++i) {
+ NSString* octet = [octets objectAtIndex:i];
+
+ if ([octet isEqualToString:@"*"]) { // passes - check next octet
+ continue;
+ } else if ([numberFormatter numberFromString:octet] == nil) { // fails - not a number and not within our range, return
+ return NO;
+ }
+ }
+
+ return YES;
+}
+
+- (void)addWhiteListEntry:(NSString*)origin
+{
+ if (self.whitelist == nil) {
+ return;
+ }
+
+ if ([origin isEqualToString:@"*"]) {
+ NSLog(@"Unlimited access to network resources");
+ self.whitelist = nil;
+ self.permittedSchemes = nil;
+ } else { // specific access
+ NSRegularExpression* parts = [NSRegularExpression regularExpressionWithPattern:@"^((\\*|[A-Za-z-]+)://)?(((\\*\\.)?[^*/:]+)|\\*)?(:(\\d+))?(/.*)?" options:0 error:nil];
+ NSTextCheckingResult* m = [parts firstMatchInString:origin options:NSMatchingAnchored range:NSMakeRange(0, [origin length])];
+ if (m != nil) {
+ NSRange r;
+ NSString* scheme = nil;
+ r = [m rangeAtIndex:2];
+ if (r.location != NSNotFound) {
+ scheme = [origin substringWithRange:r];
+ }
+
+ NSString* host = nil;
+ r = [m rangeAtIndex:3];
+ if (r.location != NSNotFound) {
+ host = [origin substringWithRange:r];
+ }
+
+ // Special case for two urls which are allowed to have empty hosts
+ if (([scheme isEqualToString:@"file"] || [scheme isEqualToString:@"content"]) && (host == nil)) {
+ host = @"*";
+ }
+
+ NSString* port = nil;
+ r = [m rangeAtIndex:7];
+ if (r.location != NSNotFound) {
+ port = [origin substringWithRange:r];
+ }
+
+ NSString* path = nil;
+ r = [m rangeAtIndex:8];
+ if (r.location != NSNotFound) {
+ path = [origin substringWithRange:r];
+ }
+
+ if (scheme == nil) {
+ // XXX making it stupid friendly for people who forget to include protocol/SSL
+ [self.whitelist addObject:[[CDVWhitelistPattern alloc] initWithScheme:@"http" host:host port:port path:path]];
+ [self.whitelist addObject:[[CDVWhitelistPattern alloc] initWithScheme:@"https" host:host port:port path:path]];
+ } else {
+ [self.whitelist addObject:[[CDVWhitelistPattern alloc] initWithScheme:scheme host:host port:port path:path]];
+ }
+
+ if (self.permittedSchemes != nil) {
+ if ([scheme isEqualToString:@"*"]) {
+ self.permittedSchemes = nil;
+ } else if (scheme != nil) {
+ [self.permittedSchemes addObject:scheme];
+ }
+ }
+ }
+ }
+}
+
+- (BOOL)schemeIsAllowed:(NSString*)scheme
+{
+ if ([scheme isEqualToString:@"http"] ||
+ [scheme isEqualToString:@"https"] ||
+ [scheme isEqualToString:@"ftp"] ||
+ [scheme isEqualToString:@"ftps"]) {
+ return YES;
+ }
+
+ return (self.permittedSchemes == nil) || [self.permittedSchemes containsObject:scheme];
+}
+
+- (BOOL)URLIsAllowed:(NSURL*)url
+{
+ return [self URLIsAllowed:url logFailure:YES];
+}
+
+- (BOOL)URLIsAllowed:(NSURL*)url logFailure:(BOOL)logFailure
+{
+ // Shortcut acceptance: Are all urls whitelisted ("*" in whitelist)?
+ if (whitelist == nil) {
+ return YES;
+ }
+
+ // Shortcut rejection: Check that the scheme is supported
+ NSString* scheme = [[url scheme] lowercaseString];
+ if (![self schemeIsAllowed:scheme]) {
+ if (logFailure) {
+ NSLog(@"%@", [self errorStringForURL:url]);
+ }
+ return NO;
+ }
+
+ // http[s] and ftp[s] should also validate against the common set in the kCDVDefaultSchemeName list
+ if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"] || [scheme isEqualToString:@"ftp"] || [scheme isEqualToString:@"ftps"]) {
+ NSURL* newUrl = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@%@", kCDVDefaultSchemeName, [url host], [[url path] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
+ // If it is allowed, we are done. If not, continue to check for the actual scheme-specific list
+ if ([self URLIsAllowed:newUrl logFailure:NO]) {
+ return YES;
+ }
+ }
+
+ // Check the url against patterns in the whitelist
+ for (CDVWhitelistPattern* p in self.whitelist) {
+ if ([p matches:url]) {
+ return YES;
+ }
+ }
+
+ if (logFailure) {
+ NSLog(@"%@", [self errorStringForURL:url]);
+ }
+ // if we got here, the url host is not in the white-list, do nothing
+ return NO;
+}
+
+- (NSString*)errorStringForURL:(NSURL*)url
+{
+ return [NSString stringWithFormat:self.whitelistRejectionFormatString, [url absoluteString]];
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSArray+Comparisons.h b/StoneIsland/platforms/ios/CordovaLib/Classes/NSArray+Comparisons.h
new file mode 100644
index 00000000..7dd68290
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/NSArray+Comparisons.h
@@ -0,0 +1,27 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "CDVAvailabilityDeprecated.h"
+
+@interface NSArray (Comparisons)
+
+- (id)objectAtIndex:(NSUInteger)index withDefault:(id)aDefault CDV_DEPRECATED(3.8 .0, "Use [command argumentAtIndex] instead.");
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSArray+Comparisons.m b/StoneIsland/platforms/ios/CordovaLib/Classes/NSArray+Comparisons.m
new file mode 100644
index 00000000..e29c03da
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/NSArray+Comparisons.m
@@ -0,0 +1,43 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "NSArray+Comparisons.h"
+
+@implementation NSArray (Comparisons)
+
+- (id)objectAtIndex:(NSUInteger)index withDefault:(id)aDefault
+{
+ id obj = nil;
+
+ @try {
+ if (index < [self count]) {
+ obj = [self objectAtIndex:index];
+ }
+ if ((obj == [NSNull null]) || (obj == nil)) {
+ return aDefault;
+ }
+ }
+ @catch(NSException* exception) {
+ NSLog(@"Exception - Name: %@ Reason: %@", [exception name], [exception reason]);
+ }
+
+ return obj;
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSData+Base64.h b/StoneIsland/platforms/ios/CordovaLib/Classes/NSData+Base64.h
new file mode 100644
index 00000000..c92d1f6a
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/NSData+Base64.h
@@ -0,0 +1,47 @@
+//
+// NSData+Base64.h
+// base64
+//
+// Created by Matt Gallagher on 2009/06/03.
+// Copyright 2009 Matt Gallagher. All rights reserved.
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software. Permission is granted to anyone to
+// use this software for any purpose, including commercial applications, and to
+// alter it and redistribute it freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+
+#import <Foundation/Foundation.h>
+#import "CDVAvailabilityDeprecated.h"
+
+void *CDVNewBase64Decode(
+ const char* inputBuffer,
+ size_t length,
+ size_t * outputLength);
+
+char *CDVNewBase64Encode(
+ const void* inputBuffer,
+ size_t length,
+ bool separateLines,
+ size_t * outputLength);
+
+@interface NSData (CDVBase64)
+
++ (NSData*)dataFromBase64String:(NSString*)aString CDV_DEPRECATED(3.8 .0, "Use cdv_dataFromBase64String");
+
+- (NSString*)base64EncodedString CDV_DEPRECATED(3.8 .0, "Use [NSData cdv_base64EncodedString]");
+
++ (NSData*)cdv_dataFromBase64String:(NSString*)aString;
+- (NSString*)cdv_base64EncodedString;
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSData+Base64.m b/StoneIsland/platforms/ios/CordovaLib/Classes/NSData+Base64.m
new file mode 100644
index 00000000..634dff67
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/NSData+Base64.m
@@ -0,0 +1,308 @@
+//
+// NSData+Base64.m
+// base64
+//
+// Created by Matt Gallagher on 2009/06/03.
+// Copyright 2009 Matt Gallagher. All rights reserved.
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software. Permission is granted to anyone to
+// use this software for any purpose, including commercial applications, and to
+// alter it and redistribute it freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+
+#import "NSData+Base64.h"
+
+//
+// Mapping from 6 bit pattern to ASCII character.
+//
+static unsigned char base64EncodeLookup[65] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+//
+// Definition for "masked-out" areas of the base64DecodeLookup mapping
+//
+#define xx 65
+
+//
+// Mapping from ASCII character to 6 bit pattern.
+//
+static unsigned char base64DecodeLookup[256] =
+{
+ xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
+ xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
+ xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, xx, xx, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx,
+ xx, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, xx,
+ xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx,
+ xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
+ xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
+ xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
+ xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
+ xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
+ xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
+ xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
+ xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
+};
+
+//
+// Fundamental sizes of the binary and base64 encode/decode units in bytes
+//
+#define BINARY_UNIT_SIZE 3
+#define BASE64_UNIT_SIZE 4
+
+//
+// NewBase64Decode
+//
+// Decodes the base64 ASCII string in the inputBuffer to a newly malloced
+// output buffer.
+//
+// inputBuffer - the source ASCII string for the decode
+// length - the length of the string or -1 (to specify strlen should be used)
+// outputLength - if not-NULL, on output will contain the decoded length
+//
+// returns the decoded buffer. Must be free'd by caller. Length is given by
+// outputLength.
+//
+void *CDVNewBase64Decode(
+ const char* inputBuffer,
+ size_t length,
+ size_t * outputLength)
+{
+ if (length == -1) {
+ length = strlen(inputBuffer);
+ }
+
+ size_t outputBufferSize =
+ ((length + BASE64_UNIT_SIZE - 1) / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE;
+ unsigned char* outputBuffer = (unsigned char*)malloc(outputBufferSize);
+
+ size_t i = 0;
+ size_t j = 0;
+
+ while (i < length) {
+ //
+ // Accumulate 4 valid characters (ignore everything else)
+ //
+ unsigned char accumulated[BASE64_UNIT_SIZE];
+ size_t accumulateIndex = 0;
+
+ while (i < length) {
+ unsigned char decode = base64DecodeLookup[inputBuffer[i++]];
+ if (decode != xx) {
+ accumulated[accumulateIndex] = decode;
+ accumulateIndex++;
+
+ if (accumulateIndex == BASE64_UNIT_SIZE) {
+ break;
+ }
+ }
+ }
+
+ //
+ // Store the 6 bits from each of the 4 characters as 3 bytes
+ //
+ // (Uses improved bounds checking suggested by Alexandre Colucci)
+ //
+ if (accumulateIndex >= 2) {
+ outputBuffer[j] = (accumulated[0] << 2) | (accumulated[1] >> 4);
+ }
+ if (accumulateIndex >= 3) {
+ outputBuffer[j + 1] = (accumulated[1] << 4) | (accumulated[2] >> 2);
+ }
+ if (accumulateIndex >= 4) {
+ outputBuffer[j + 2] = (accumulated[2] << 6) | accumulated[3];
+ }
+ j += accumulateIndex - 1;
+ }
+
+ if (outputLength) {
+ *outputLength = j;
+ }
+ return outputBuffer;
+}
+
+//
+// NewBase64Encode
+//
+// Encodes the arbitrary data in the inputBuffer as base64 into a newly malloced
+// output buffer.
+//
+// inputBuffer - the source data for the encode
+// length - the length of the input in bytes
+// separateLines - if zero, no CR/LF characters will be added. Otherwise
+// a CR/LF pair will be added every 64 encoded chars.
+// outputLength - if not-NULL, on output will contain the encoded length
+// (not including terminating 0 char)
+//
+// returns the encoded buffer. Must be free'd by caller. Length is given by
+// outputLength.
+//
+char *CDVNewBase64Encode(
+ const void* buffer,
+ size_t length,
+ bool separateLines,
+ size_t * outputLength)
+{
+ const unsigned char* inputBuffer = (const unsigned char*)buffer;
+
+#define MAX_NUM_PADDING_CHARS 2
+#define OUTPUT_LINE_LENGTH 64
+#define INPUT_LINE_LENGTH ((OUTPUT_LINE_LENGTH / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE)
+#define CR_LF_SIZE 2
+
+ //
+ // Byte accurate calculation of final buffer size
+ //
+ size_t outputBufferSize =
+ ((length / BINARY_UNIT_SIZE)
+ + ((length % BINARY_UNIT_SIZE) ? 1 : 0))
+ * BASE64_UNIT_SIZE;
+ if (separateLines) {
+ outputBufferSize +=
+ (outputBufferSize / OUTPUT_LINE_LENGTH) * CR_LF_SIZE;
+ }
+
+ //
+ // Include space for a terminating zero
+ //
+ outputBufferSize += 1;
+
+ //
+ // Allocate the output buffer
+ //
+ char* outputBuffer = (char*)malloc(outputBufferSize);
+ if (!outputBuffer) {
+ return NULL;
+ }
+
+ size_t i = 0;
+ size_t j = 0;
+ const size_t lineLength = separateLines ? INPUT_LINE_LENGTH : length;
+ size_t lineEnd = lineLength;
+
+ while (true) {
+ if (lineEnd > length) {
+ lineEnd = length;
+ }
+
+ for (; i + BINARY_UNIT_SIZE - 1 < lineEnd; i += BINARY_UNIT_SIZE) {
+ //
+ // Inner loop: turn 48 bytes into 64 base64 characters
+ //
+ outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
+ outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)
+ | ((inputBuffer[i + 1] & 0xF0) >> 4)];
+ outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2)
+ | ((inputBuffer[i + 2] & 0xC0) >> 6)];
+ outputBuffer[j++] = base64EncodeLookup[inputBuffer[i + 2] & 0x3F];
+ }
+
+ if (lineEnd == length) {
+ break;
+ }
+
+ //
+ // Add the newline
+ //
+ // outputBuffer[j++] = '\r';
+ // outputBuffer[j++] = '\n';
+ lineEnd += lineLength;
+ }
+
+ if (i + 1 < length) {
+ //
+ // Handle the single '=' case
+ //
+ outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
+ outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)
+ | ((inputBuffer[i + 1] & 0xF0) >> 4)];
+ outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2];
+ outputBuffer[j++] = '=';
+ } else if (i < length) {
+ //
+ // Handle the double '=' case
+ //
+ outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
+ outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0x03) << 4];
+ outputBuffer[j++] = '=';
+ outputBuffer[j++] = '=';
+ }
+ outputBuffer[j] = 0;
+
+ //
+ // Set the output length and return the buffer
+ //
+ if (outputLength) {
+ *outputLength = j;
+ }
+ return outputBuffer;
+}
+
+@implementation NSData (CDVBase64)
+
+//
+// dataFromBase64String:
+//
+// Creates an NSData object containing the base64 decoded representation of
+// the base64 string 'aString'
+//
+// Parameters:
+// aString - the base64 string to decode
+//
+// returns the autoreleased NSData representation of the base64 string
+//
++ (NSData*)cdv_dataFromBase64String:(NSString*)aString
+{
+ size_t outputLength = 0;
+ void* outputBuffer = CDVNewBase64Decode([aString UTF8String], [aString length], &outputLength);
+
+ return [NSData dataWithBytesNoCopy:outputBuffer length:outputLength freeWhenDone:YES];
+}
+
+//
+// base64EncodedString
+//
+// Creates an NSString object that contains the base 64 encoding of the
+// receiver's data. Lines are broken at 64 characters long.
+//
+// returns an autoreleased NSString being the base 64 representation of the
+// receiver.
+//
+- (NSString*)cdv_base64EncodedString
+{
+ size_t outputLength = 0;
+ char* outputBuffer =
+ CDVNewBase64Encode([self bytes], [self length], true, &outputLength);
+
+ NSString* result = [[NSString alloc] initWithBytesNoCopy:outputBuffer
+ length:outputLength
+ encoding:NSASCIIStringEncoding
+ freeWhenDone:YES];
+
+ return result;
+}
+
++ (NSData*)dataFromBase64String:(NSString*)aString
+{
+ return [self cdv_dataFromBase64String:aString];
+}
+
+- (NSString*)base64EncodedString
+{
+ return [self cdv_base64EncodedString];
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSDictionary+Extensions.h b/StoneIsland/platforms/ios/CordovaLib/Classes/NSDictionary+Extensions.h
new file mode 100644
index 00000000..4020864e
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/NSDictionary+Extensions.h
@@ -0,0 +1,43 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "CDVAvailabilityDeprecated.h"
+
+@interface NSDictionary (org_apache_cordova_NSDictionary_Extension)
+
+- (bool)existsValue:(NSString*)expectedValue forKey:(NSString*)key CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0");
+
+- (NSInteger)integerValueForKey:(NSString*)key defaultValue:(NSInteger)defaultValue withRange:(NSRange)range CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0");
+
+- (NSInteger)integerValueForKey:(NSString*)key defaultValue:(NSInteger)defaultValue CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0");
+
+- (BOOL)typeValueForKey:(NSString*)key isArray:(BOOL*)bArray isNull:(BOOL*)bNull isNumber:(BOOL*)bNumber isString:(BOOL*)bString CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0");
+
+- (BOOL)valueForKeyIsArray:(NSString*)key CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0");
+
+- (BOOL)valueForKeyIsNull:(NSString*)key CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0");
+
+- (BOOL)valueForKeyIsString:(NSString*)key CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0");
+
+- (BOOL)valueForKeyIsNumber:(NSString*)key CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0");
+
+- (NSDictionary*)dictionaryWithLowercaseKeys CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0");
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSDictionary+Extensions.m b/StoneIsland/platforms/ios/CordovaLib/Classes/NSDictionary+Extensions.m
new file mode 100644
index 00000000..0361ff95
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/NSDictionary+Extensions.m
@@ -0,0 +1,159 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "NSDictionary+Extensions.h"
+#import <math.h>
+
+@implementation NSDictionary (org_apache_cordova_NSDictionary_Extension)
+
+- (bool)existsValue:(NSString*)expectedValue forKey:(NSString*)key
+{
+ id val = [self valueForKey:key];
+ bool exists = false;
+
+ if (val != nil) {
+ exists = [(NSString*)val compare : expectedValue options : NSCaseInsensitiveSearch] == 0;
+ }
+
+ return exists;
+}
+
+- (NSInteger)integerValueForKey:(NSString*)key defaultValue:(NSInteger)defaultValue withRange:(NSRange)range
+{
+ NSInteger value = defaultValue;
+
+ NSNumber* val = [self valueForKey:key]; // value is an NSNumber
+
+ if (val != nil) {
+ value = [val integerValue];
+ }
+
+ // min, max checks
+ value = MAX(range.location, value);
+ value = MIN(range.length, value);
+
+ return value;
+}
+
+- (NSInteger)integerValueForKey:(NSString*)key defaultValue:(NSInteger)defaultValue
+{
+ NSInteger value = defaultValue;
+
+ NSNumber* val = [self valueForKey:key]; // value is an NSNumber
+
+ if (val != nil) {
+ value = [val integerValue];
+ }
+ return value;
+}
+
+/*
+ * Determine the type of object stored in a dictionary
+ * IN:
+ * (BOOL*) bString - if exists will be set to YES if object is an NSString, NO if not
+ * (BOOL*) bNull - if exists will be set to YES if object is an NSNull, NO if not
+ * (BOOL*) bArray - if exists will be set to YES if object is an NSArray, NO if not
+ * (BOOL*) bNumber - if exists will be set to YES if object is an NSNumber, NO if not
+ *
+ * OUT:
+ * YES if key exists
+ * NO if key does not exist. Input parameters remain untouched
+ *
+ */
+
+- (BOOL)typeValueForKey:(NSString*)key isArray:(BOOL*)bArray isNull:(BOOL*)bNull isNumber:(BOOL*)bNumber isString:(BOOL*)bString
+{
+ BOOL bExists = YES;
+ NSObject* value = [self objectForKey:key];
+
+ if (value) {
+ bExists = YES;
+ if (bString) {
+ *bString = [value isKindOfClass:[NSString class]];
+ }
+ if (bNull) {
+ *bNull = [value isKindOfClass:[NSNull class]];
+ }
+ if (bArray) {
+ *bArray = [value isKindOfClass:[NSArray class]];
+ }
+ if (bNumber) {
+ *bNumber = [value isKindOfClass:[NSNumber class]];
+ }
+ }
+ return bExists;
+}
+
+- (BOOL)valueForKeyIsArray:(NSString*)key
+{
+ BOOL bArray = NO;
+ NSObject* value = [self objectForKey:key];
+
+ if (value) {
+ bArray = [value isKindOfClass:[NSArray class]];
+ }
+ return bArray;
+}
+
+- (BOOL)valueForKeyIsNull:(NSString*)key
+{
+ BOOL bNull = NO;
+ NSObject* value = [self objectForKey:key];
+
+ if (value) {
+ bNull = [value isKindOfClass:[NSNull class]];
+ }
+ return bNull;
+}
+
+- (BOOL)valueForKeyIsString:(NSString*)key
+{
+ BOOL bString = NO;
+ NSObject* value = [self objectForKey:key];
+
+ if (value) {
+ bString = [value isKindOfClass:[NSString class]];
+ }
+ return bString;
+}
+
+- (BOOL)valueForKeyIsNumber:(NSString*)key
+{
+ BOOL bNumber = NO;
+ NSObject* value = [self objectForKey:key];
+
+ if (value) {
+ bNumber = [value isKindOfClass:[NSNumber class]];
+ }
+ return bNumber;
+}
+
+- (NSDictionary*)dictionaryWithLowercaseKeys
+{
+ NSMutableDictionary* result = [NSMutableDictionary dictionaryWithCapacity:self.count];
+ NSString* key;
+
+ for (key in self) {
+ [result setObject:[self objectForKey:key] forKey:[key lowercaseString]];
+ }
+
+ return result;
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSMutableArray+QueueAdditions.h b/StoneIsland/platforms/ios/CordovaLib/Classes/NSMutableArray+QueueAdditions.h
new file mode 100644
index 00000000..31940949
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/NSMutableArray+QueueAdditions.h
@@ -0,0 +1,29 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface NSMutableArray (QueueAdditions)
+
+- (id)pop;
+- (id)queueHead;
+- (id)dequeue;
+- (void)enqueue:(id)obj;
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSMutableArray+QueueAdditions.m b/StoneIsland/platforms/ios/CordovaLib/Classes/NSMutableArray+QueueAdditions.m
new file mode 100644
index 00000000..9e67edeb
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/NSMutableArray+QueueAdditions.m
@@ -0,0 +1,58 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "NSMutableArray+QueueAdditions.h"
+
+@implementation NSMutableArray (QueueAdditions)
+
+- (id)queueHead
+{
+ if ([self count] == 0) {
+ return nil;
+ }
+
+ return [self objectAtIndex:0];
+}
+
+- (__autoreleasing id)dequeue
+{
+ if ([self count] == 0) {
+ return nil;
+ }
+
+ id head = [self objectAtIndex:0];
+ if (head != nil) {
+ // [[head retain] autorelease]; ARC - the __autoreleasing on the return value should so the same thing
+ [self removeObjectAtIndex:0];
+ }
+
+ return head;
+}
+
+- (id)pop
+{
+ return [self dequeue];
+}
+
+- (void)enqueue:(id)object
+{
+ [self addObject:object];
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/UIDevice+Extensions.h b/StoneIsland/platforms/ios/CordovaLib/Classes/UIDevice+Extensions.h
new file mode 100644
index 00000000..1b2c0739
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/UIDevice+Extensions.h
@@ -0,0 +1,32 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "CDVAvailabilityDeprecated.h"
+
+@interface UIDevice (org_apache_cordova_UIDevice_Extension)
+
+/*
+ Get the unique identifier from the app bundle's folder, which is already a GUID
+ Upgrading and/or deleting the app and re-installing will get you a new GUID, so
+ this is only unique per install per device.
+ */
+- (NSString*)uniqueAppInstanceIdentifier CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0");
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/UIDevice+Extensions.m b/StoneIsland/platforms/ios/CordovaLib/Classes/UIDevice+Extensions.m
new file mode 100644
index 00000000..c0c91af2
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/Classes/UIDevice+Extensions.m
@@ -0,0 +1,47 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <UIKit/UIKit.h>
+#import "UIDevice+Extensions.h"
+
+@implementation UIDevice (org_apache_cordova_UIDevice_Extension)
+
+- (NSString*)uniqueAppInstanceIdentifier
+{
+ NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
+ static NSString* UUID_KEY = @"CDVUUID";
+
+ NSString* app_uuid = [userDefaults stringForKey:UUID_KEY];
+
+ if (app_uuid == nil) {
+ CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
+ CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
+
+ app_uuid = [NSString stringWithString:(__bridge NSString*)uuidString];
+ [userDefaults setObject:app_uuid forKey:UUID_KEY];
+ [userDefaults synchronize];
+
+ CFRelease(uuidString);
+ CFRelease(uuidRef);
+ }
+
+ return app_uuid;
+}
+
+@end
diff --git a/StoneIsland/platforms/ios/CordovaLib/CordovaLib.xcodeproj/project.pbxproj b/StoneIsland/platforms/ios/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..c6b0f234
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
@@ -0,0 +1,507 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1B701028177A61CF00AE11F4 /* CDVShared.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B701026177A61CF00AE11F4 /* CDVShared.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 1F92F4A01314023E0046367C /* CDVPluginResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F92F49E1314023E0046367C /* CDVPluginResult.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 1F92F4A11314023E0046367C /* CDVPluginResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F92F49F1314023E0046367C /* CDVPluginResult.m */; };
+ 301F2F2A14F3C9CA003FE9FC /* CDV.h in Headers */ = {isa = PBXBuildFile; fileRef = 301F2F2914F3C9CA003FE9FC /* CDV.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 302965BC13A94E9D007046C5 /* CDVDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 302965BB13A94E9D007046C5 /* CDVDebug.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 3034979C1513D56A0090E688 /* CDVLocalStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 3034979A1513D56A0090E688 /* CDVLocalStorage.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 3034979E1513D56A0090E688 /* CDVLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 3034979B1513D56A0090E688 /* CDVLocalStorage.m */; };
+ 30392E4E14F4FCAB00B9E0B8 /* CDVAvailability.h in Headers */ = {isa = PBXBuildFile; fileRef = 30392E4D14F4FCAB00B9E0B8 /* CDVAvailability.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 3062D120151D0EDB000D9128 /* UIDevice+Extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3062D11E151D0EDB000D9128 /* UIDevice+Extensions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 3062D122151D0EDB000D9128 /* UIDevice+Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3062D11F151D0EDB000D9128 /* UIDevice+Extensions.m */; };
+ 3073E9ED1656D51200957977 /* CDVScreenOrientationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 3073E9EC1656D51200957977 /* CDVScreenOrientationDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 30C684801406CB38004C1A8E /* CDVWhitelist.h in Headers */ = {isa = PBXBuildFile; fileRef = 30C6847E1406CB38004C1A8E /* CDVWhitelist.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 30C684821406CB38004C1A8E /* CDVWhitelist.m in Sources */ = {isa = PBXBuildFile; fileRef = 30C6847F1406CB38004C1A8E /* CDVWhitelist.m */; };
+ 30C684941407044B004C1A8E /* CDVURLProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 30C684921407044A004C1A8E /* CDVURLProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 30C684961407044B004C1A8E /* CDVURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 30C684931407044A004C1A8E /* CDVURLProtocol.m */; };
+ 30E33AF213A7E24B00594D64 /* CDVPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E33AF013A7E24B00594D64 /* CDVPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 30E33AF313A7E24B00594D64 /* CDVPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 30E33AF113A7E24B00594D64 /* CDVPlugin.m */; };
+ 30E563CF13E217EC00C949AA /* NSMutableArray+QueueAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E563CD13E217EC00C949AA /* NSMutableArray+QueueAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 30E563D013E217EC00C949AA /* NSMutableArray+QueueAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 30E563CE13E217EC00C949AA /* NSMutableArray+QueueAdditions.m */; };
+ 30E6B8CD1A8ADD900025B9EE /* CDVHandleOpenURL.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E6B8CB1A8ADD900025B9EE /* CDVHandleOpenURL.h */; };
+ 30E6B8CE1A8ADD900025B9EE /* CDVHandleOpenURL.m in Sources */ = {isa = PBXBuildFile; fileRef = 30E6B8CC1A8ADD900025B9EE /* CDVHandleOpenURL.m */; };
+ 30F3930B169F839700B22307 /* CDVJSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 30F39309169F839700B22307 /* CDVJSON.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 30F3930C169F839700B22307 /* CDVJSON.m in Sources */ = {isa = PBXBuildFile; fileRef = 30F3930A169F839700B22307 /* CDVJSON.m */; };
+ 30F5EBAB14CA26E700987760 /* CDVCommandDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 30F5EBA914CA26E700987760 /* CDVCommandDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 7E14B5A81705050A0032169E /* CDVTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E14B5A61705050A0032169E /* CDVTimer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 7E14B5A91705050A0032169E /* CDVTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E14B5A71705050A0032169E /* CDVTimer.m */; };
+ 7E22B88519E4C0210026F95E /* CDVAvailabilityDeprecated.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E22B88419E4C0210026F95E /* CDVAvailabilityDeprecated.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 8852C43A14B65FD800F0E735 /* CDVViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 8852C43614B65FD800F0E735 /* CDVViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 8852C43C14B65FD800F0E735 /* CDVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8852C43714B65FD800F0E735 /* CDVViewController.m */; };
+ 8887FD681090FBE7009987E8 /* NSDictionary+Extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD281090FBE7009987E8 /* NSDictionary+Extensions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 8887FD691090FBE7009987E8 /* NSDictionary+Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD291090FBE7009987E8 /* NSDictionary+Extensions.m */; };
+ 8887FD741090FBE7009987E8 /* CDVInvokedUrlCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD341090FBE7009987E8 /* CDVInvokedUrlCommand.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 8887FD751090FBE7009987E8 /* CDVInvokedUrlCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD351090FBE7009987E8 /* CDVInvokedUrlCommand.m */; };
+ 8887FD8F1090FBE7009987E8 /* NSData+Base64.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD501090FBE7009987E8 /* NSData+Base64.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 8887FD901090FBE7009987E8 /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD511090FBE7009987E8 /* NSData+Base64.m */; };
+ EB3B3547161CB44D003DBE7D /* CDVCommandQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = EB3B3545161CB44D003DBE7D /* CDVCommandQueue.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EB3B3548161CB44D003DBE7D /* CDVCommandQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = EB3B3546161CB44D003DBE7D /* CDVCommandQueue.m */; };
+ EB3B357C161F2A45003DBE7D /* CDVCommandDelegateImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = EB3B357A161F2A44003DBE7D /* CDVCommandDelegateImpl.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EB3B357D161F2A45003DBE7D /* CDVCommandDelegateImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = EB3B357B161F2A45003DBE7D /* CDVCommandDelegateImpl.m */; };
+ EB6A98541A77EE470013FCDB /* CDVJSON_private.m in Sources */ = {isa = PBXBuildFile; fileRef = EB6A98521A77EE470013FCDB /* CDVJSON_private.m */; };
+ EB96673B16A8970A00D86CDF /* CDVUserAgentUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = EB96673916A8970900D86CDF /* CDVUserAgentUtil.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EB96673C16A8970A00D86CDF /* CDVUserAgentUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = EB96673A16A8970900D86CDF /* CDVUserAgentUtil.m */; };
+ EBA3557315ABD38C00F4DE24 /* NSArray+Comparisons.h in Headers */ = {isa = PBXBuildFile; fileRef = EBA3557115ABD38C00F4DE24 /* NSArray+Comparisons.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EBA3557515ABD38C00F4DE24 /* NSArray+Comparisons.m in Sources */ = {isa = PBXBuildFile; fileRef = EBA3557215ABD38C00F4DE24 /* NSArray+Comparisons.m */; };
+ EBFF4DBC16D3FE2E008F452B /* CDVWebViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EBFF4DBA16D3FE2E008F452B /* CDVWebViewDelegate.m */; };
+ EBFF4DBD16D3FE2E008F452B /* CDVWebViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = EBFF4DBB16D3FE2E008F452B /* CDVWebViewDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ F858FBC6166009A8007DA594 /* CDVConfigParser.h in Headers */ = {isa = PBXBuildFile; fileRef = F858FBC4166009A8007DA594 /* CDVConfigParser.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ F858FBC7166009A8007DA594 /* CDVConfigParser.m in Sources */ = {isa = PBXBuildFile; fileRef = F858FBC5166009A8007DA594 /* CDVConfigParser.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 1B701026177A61CF00AE11F4 /* CDVShared.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVShared.h; path = Classes/CDVShared.h; sourceTree = "<group>"; };
+ 1F92F49E1314023E0046367C /* CDVPluginResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVPluginResult.h; path = Classes/CDVPluginResult.h; sourceTree = "<group>"; };
+ 1F92F49F1314023E0046367C /* CDVPluginResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVPluginResult.m; path = Classes/CDVPluginResult.m; sourceTree = "<group>"; };
+ 301F2F2914F3C9CA003FE9FC /* CDV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDV.h; path = Classes/CDV.h; sourceTree = "<group>"; };
+ 302965BB13A94E9D007046C5 /* CDVDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVDebug.h; path = Classes/CDVDebug.h; sourceTree = "<group>"; };
+ 30325A0B136B343700982B63 /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
+ 3034979A1513D56A0090E688 /* CDVLocalStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVLocalStorage.h; path = Classes/CDVLocalStorage.h; sourceTree = "<group>"; };
+ 3034979B1513D56A0090E688 /* CDVLocalStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVLocalStorage.m; path = Classes/CDVLocalStorage.m; sourceTree = "<group>"; };
+ 30392E4D14F4FCAB00B9E0B8 /* CDVAvailability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVAvailability.h; path = Classes/CDVAvailability.h; sourceTree = "<group>"; };
+ 3062D11E151D0EDB000D9128 /* UIDevice+Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIDevice+Extensions.h"; path = "Classes/UIDevice+Extensions.h"; sourceTree = "<group>"; };
+ 3062D11F151D0EDB000D9128 /* UIDevice+Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIDevice+Extensions.m"; path = "Classes/UIDevice+Extensions.m"; sourceTree = "<group>"; };
+ 3073E9EC1656D51200957977 /* CDVScreenOrientationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVScreenOrientationDelegate.h; path = Classes/CDVScreenOrientationDelegate.h; sourceTree = "<group>"; };
+ 30C6847E1406CB38004C1A8E /* CDVWhitelist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVWhitelist.h; path = Classes/CDVWhitelist.h; sourceTree = "<group>"; };
+ 30C6847F1406CB38004C1A8E /* CDVWhitelist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVWhitelist.m; path = Classes/CDVWhitelist.m; sourceTree = "<group>"; };
+ 30C684921407044A004C1A8E /* CDVURLProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVURLProtocol.h; path = Classes/CDVURLProtocol.h; sourceTree = "<group>"; };
+ 30C684931407044A004C1A8E /* CDVURLProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVURLProtocol.m; path = Classes/CDVURLProtocol.m; sourceTree = "<group>"; };
+ 30E33AF013A7E24B00594D64 /* CDVPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVPlugin.h; path = Classes/CDVPlugin.h; sourceTree = "<group>"; };
+ 30E33AF113A7E24B00594D64 /* CDVPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVPlugin.m; path = Classes/CDVPlugin.m; sourceTree = "<group>"; };
+ 30E563CD13E217EC00C949AA /* NSMutableArray+QueueAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSMutableArray+QueueAdditions.h"; path = "Classes/NSMutableArray+QueueAdditions.h"; sourceTree = "<group>"; };
+ 30E563CE13E217EC00C949AA /* NSMutableArray+QueueAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSMutableArray+QueueAdditions.m"; path = "Classes/NSMutableArray+QueueAdditions.m"; sourceTree = "<group>"; };
+ 30E6B8CB1A8ADD900025B9EE /* CDVHandleOpenURL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVHandleOpenURL.h; path = Classes/CDVHandleOpenURL.h; sourceTree = "<group>"; };
+ 30E6B8CC1A8ADD900025B9EE /* CDVHandleOpenURL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVHandleOpenURL.m; path = Classes/CDVHandleOpenURL.m; sourceTree = "<group>"; };
+ 30F39309169F839700B22307 /* CDVJSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVJSON.h; path = Classes/CDVJSON.h; sourceTree = "<group>"; };
+ 30F3930A169F839700B22307 /* CDVJSON.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVJSON.m; path = Classes/CDVJSON.m; sourceTree = "<group>"; };
+ 30F5EBA914CA26E700987760 /* CDVCommandDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCommandDelegate.h; path = Classes/CDVCommandDelegate.h; sourceTree = "<group>"; };
+ 686357AA141002F100DF4CF2 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 686357AC141002F100DF4CF2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 686357AE141002F100DF4CF2 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 686357CC14100AAD00DF4CF2 /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = System/Library/Frameworks/AddressBookUI.framework; sourceTree = SDKROOT; };
+ 686357CE14100ADA00DF4CF2 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
+ 686357CF14100ADB00DF4CF2 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
+ 686357D014100ADE00DF4CF2 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
+ 686357D214100AE700DF4CF2 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
+ 686357D414100AF200DF4CF2 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+ 686357DC14100B1600DF4CF2 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
+ 68A32D7114102E1C006B237C /* libCordova.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCordova.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 68A32D7414103017006B237C /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
+ 7E14B5A61705050A0032169E /* CDVTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVTimer.h; path = Classes/CDVTimer.h; sourceTree = "<group>"; };
+ 7E14B5A71705050A0032169E /* CDVTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVTimer.m; path = Classes/CDVTimer.m; sourceTree = "<group>"; };
+ 7E22B88419E4C0210026F95E /* CDVAvailabilityDeprecated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVAvailabilityDeprecated.h; path = Classes/CDVAvailabilityDeprecated.h; sourceTree = "<group>"; };
+ 8220B5C316D5427E00EC3921 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; };
+ 8852C43614B65FD800F0E735 /* CDVViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVViewController.h; path = Classes/CDVViewController.h; sourceTree = "<group>"; };
+ 8852C43714B65FD800F0E735 /* CDVViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVViewController.m; path = Classes/CDVViewController.m; sourceTree = "<group>"; };
+ 8887FD281090FBE7009987E8 /* NSDictionary+Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+Extensions.h"; path = "Classes/NSDictionary+Extensions.h"; sourceTree = "<group>"; };
+ 8887FD291090FBE7009987E8 /* NSDictionary+Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+Extensions.m"; path = "Classes/NSDictionary+Extensions.m"; sourceTree = "<group>"; };
+ 8887FD341090FBE7009987E8 /* CDVInvokedUrlCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVInvokedUrlCommand.h; path = Classes/CDVInvokedUrlCommand.h; sourceTree = "<group>"; };
+ 8887FD351090FBE7009987E8 /* CDVInvokedUrlCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVInvokedUrlCommand.m; path = Classes/CDVInvokedUrlCommand.m; sourceTree = "<group>"; };
+ 8887FD501090FBE7009987E8 /* NSData+Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSData+Base64.h"; path = "Classes/NSData+Base64.h"; sourceTree = "<group>"; };
+ 8887FD511090FBE7009987E8 /* NSData+Base64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSData+Base64.m"; path = "Classes/NSData+Base64.m"; sourceTree = "<group>"; };
+ AA747D9E0F9514B9006C5449 /* CordovaLib_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CordovaLib_Prefix.pch; sourceTree = SOURCE_ROOT; };
+ EB3B3545161CB44D003DBE7D /* CDVCommandQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCommandQueue.h; path = Classes/CDVCommandQueue.h; sourceTree = "<group>"; };
+ EB3B3546161CB44D003DBE7D /* CDVCommandQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCommandQueue.m; path = Classes/CDVCommandQueue.m; sourceTree = "<group>"; };
+ EB3B357A161F2A44003DBE7D /* CDVCommandDelegateImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCommandDelegateImpl.h; path = Classes/CDVCommandDelegateImpl.h; sourceTree = "<group>"; };
+ EB3B357B161F2A45003DBE7D /* CDVCommandDelegateImpl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCommandDelegateImpl.m; path = Classes/CDVCommandDelegateImpl.m; sourceTree = "<group>"; };
+ EB6A98521A77EE470013FCDB /* CDVJSON_private.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVJSON_private.m; path = Classes/CDVJSON_private.m; sourceTree = "<group>"; };
+ EB6A98531A77EE470013FCDB /* CDVJSON_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVJSON_private.h; path = Classes/CDVJSON_private.h; sourceTree = "<group>"; };
+ EB96673916A8970900D86CDF /* CDVUserAgentUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVUserAgentUtil.h; path = Classes/CDVUserAgentUtil.h; sourceTree = "<group>"; };
+ EB96673A16A8970900D86CDF /* CDVUserAgentUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVUserAgentUtil.m; path = Classes/CDVUserAgentUtil.m; sourceTree = "<group>"; };
+ EBA3557115ABD38C00F4DE24 /* NSArray+Comparisons.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+Comparisons.h"; path = "Classes/NSArray+Comparisons.h"; sourceTree = "<group>"; };
+ EBA3557215ABD38C00F4DE24 /* NSArray+Comparisons.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+Comparisons.m"; path = "Classes/NSArray+Comparisons.m"; sourceTree = "<group>"; };
+ EBFF4DBA16D3FE2E008F452B /* CDVWebViewDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVWebViewDelegate.m; path = Classes/CDVWebViewDelegate.m; sourceTree = "<group>"; };
+ EBFF4DBB16D3FE2E008F452B /* CDVWebViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVWebViewDelegate.h; path = Classes/CDVWebViewDelegate.h; sourceTree = "<group>"; };
+ F858FBC4166009A8007DA594 /* CDVConfigParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVConfigParser.h; path = Classes/CDVConfigParser.h; sourceTree = "<group>"; };
+ F858FBC5166009A8007DA594 /* CDVConfigParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVConfigParser.m; path = Classes/CDVConfigParser.m; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ D2AAC07C0554694100DB518D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 034768DFFF38A50411DB9C8B /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 68A32D7114102E1C006B237C /* libCordova.a */,
+ );
+ name = Products;
+ sourceTree = CORDOVALIB;
+ };
+ 0867D691FE84028FC02AAC07 /* CordovaLib */ = {
+ isa = PBXGroup;
+ children = (
+ 8887FD101090FB43009987E8 /* Classes */,
+ 32C88DFF0371C24200C91783 /* Other Sources */,
+ 0867D69AFE84028FC02AAC07 /* Frameworks */,
+ 034768DFFF38A50411DB9C8B /* Products */,
+ 30325A0B136B343700982B63 /* VERSION */,
+ );
+ name = CordovaLib;
+ sourceTree = "<group>";
+ };
+ 0867D69AFE84028FC02AAC07 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 68A32D7414103017006B237C /* AddressBook.framework */,
+ 8220B5C316D5427E00EC3921 /* AssetsLibrary.framework */,
+ 686357DC14100B1600DF4CF2 /* CoreMedia.framework */,
+ 686357CE14100ADA00DF4CF2 /* AudioToolbox.framework */,
+ 686357CF14100ADB00DF4CF2 /* AVFoundation.framework */,
+ 686357D014100ADE00DF4CF2 /* CoreLocation.framework */,
+ 686357D214100AE700DF4CF2 /* MobileCoreServices.framework */,
+ 686357D414100AF200DF4CF2 /* SystemConfiguration.framework */,
+ 686357CC14100AAD00DF4CF2 /* AddressBookUI.framework */,
+ 686357AA141002F100DF4CF2 /* UIKit.framework */,
+ 686357AC141002F100DF4CF2 /* Foundation.framework */,
+ 686357AE141002F100DF4CF2 /* CoreGraphics.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 3054098714B77FF3009841CA /* Cleaver */ = {
+ isa = PBXGroup;
+ children = (
+ F858FBC4166009A8007DA594 /* CDVConfigParser.h */,
+ F858FBC5166009A8007DA594 /* CDVConfigParser.m */,
+ 8852C43614B65FD800F0E735 /* CDVViewController.h */,
+ 8852C43714B65FD800F0E735 /* CDVViewController.m */,
+ EB3B3545161CB44D003DBE7D /* CDVCommandQueue.h */,
+ EB3B3546161CB44D003DBE7D /* CDVCommandQueue.m */,
+ );
+ name = Cleaver;
+ sourceTree = "<group>";
+ };
+ 32C88DFF0371C24200C91783 /* Other Sources */ = {
+ isa = PBXGroup;
+ children = (
+ AA747D9E0F9514B9006C5449 /* CordovaLib_Prefix.pch */,
+ );
+ name = "Other Sources";
+ sourceTree = "<group>";
+ };
+ 888700D710922F56009987E8 /* Commands */ = {
+ isa = PBXGroup;
+ children = (
+ 30E6B8CB1A8ADD900025B9EE /* CDVHandleOpenURL.h */,
+ 30E6B8CC1A8ADD900025B9EE /* CDVHandleOpenURL.m */,
+ 7E22B88419E4C0210026F95E /* CDVAvailabilityDeprecated.h */,
+ EBFF4DBA16D3FE2E008F452B /* CDVWebViewDelegate.m */,
+ EBFF4DBB16D3FE2E008F452B /* CDVWebViewDelegate.h */,
+ 301F2F2914F3C9CA003FE9FC /* CDV.h */,
+ 3034979A1513D56A0090E688 /* CDVLocalStorage.h */,
+ 3034979B1513D56A0090E688 /* CDVLocalStorage.m */,
+ 30392E4D14F4FCAB00B9E0B8 /* CDVAvailability.h */,
+ 30F5EBA914CA26E700987760 /* CDVCommandDelegate.h */,
+ EB3B357A161F2A44003DBE7D /* CDVCommandDelegateImpl.h */,
+ EB3B357B161F2A45003DBE7D /* CDVCommandDelegateImpl.m */,
+ 30C684921407044A004C1A8E /* CDVURLProtocol.h */,
+ 30C684931407044A004C1A8E /* CDVURLProtocol.m */,
+ 30C6847E1406CB38004C1A8E /* CDVWhitelist.h */,
+ 1B701026177A61CF00AE11F4 /* CDVShared.h */,
+ 30C6847F1406CB38004C1A8E /* CDVWhitelist.m */,
+ 30E33AF013A7E24B00594D64 /* CDVPlugin.h */,
+ 30E33AF113A7E24B00594D64 /* CDVPlugin.m */,
+ 1F92F49E1314023E0046367C /* CDVPluginResult.h */,
+ 1F92F49F1314023E0046367C /* CDVPluginResult.m */,
+ 8887FD341090FBE7009987E8 /* CDVInvokedUrlCommand.h */,
+ 8887FD351090FBE7009987E8 /* CDVInvokedUrlCommand.m */,
+ 3073E9EC1656D51200957977 /* CDVScreenOrientationDelegate.h */,
+ 30F39309169F839700B22307 /* CDVJSON.h */,
+ 30F3930A169F839700B22307 /* CDVJSON.m */,
+ EB6A98521A77EE470013FCDB /* CDVJSON_private.m */,
+ EB6A98531A77EE470013FCDB /* CDVJSON_private.h */,
+ EB96673916A8970900D86CDF /* CDVUserAgentUtil.h */,
+ EB96673A16A8970900D86CDF /* CDVUserAgentUtil.m */,
+ );
+ name = Commands;
+ sourceTree = "<group>";
+ };
+ 888700D910923009009987E8 /* Util */ = {
+ isa = PBXGroup;
+ children = (
+ 3062D11E151D0EDB000D9128 /* UIDevice+Extensions.h */,
+ 3062D11F151D0EDB000D9128 /* UIDevice+Extensions.m */,
+ EBA3557115ABD38C00F4DE24 /* NSArray+Comparisons.h */,
+ EBA3557215ABD38C00F4DE24 /* NSArray+Comparisons.m */,
+ 8887FD281090FBE7009987E8 /* NSDictionary+Extensions.h */,
+ 8887FD291090FBE7009987E8 /* NSDictionary+Extensions.m */,
+ 302965BB13A94E9D007046C5 /* CDVDebug.h */,
+ 30E563CD13E217EC00C949AA /* NSMutableArray+QueueAdditions.h */,
+ 30E563CE13E217EC00C949AA /* NSMutableArray+QueueAdditions.m */,
+ 8887FD501090FBE7009987E8 /* NSData+Base64.h */,
+ 8887FD511090FBE7009987E8 /* NSData+Base64.m */,
+ 7E14B5A61705050A0032169E /* CDVTimer.h */,
+ 7E14B5A71705050A0032169E /* CDVTimer.m */,
+ );
+ name = Util;
+ sourceTree = "<group>";
+ };
+ 8887FD101090FB43009987E8 /* Classes */ = {
+ isa = PBXGroup;
+ children = (
+ 3054098714B77FF3009841CA /* Cleaver */,
+ 888700D710922F56009987E8 /* Commands */,
+ 888700D910923009009987E8 /* Util */,
+ );
+ name = Classes;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ D2AAC07A0554694100DB518D /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8887FD681090FBE7009987E8 /* NSDictionary+Extensions.h in Headers */,
+ 8887FD741090FBE7009987E8 /* CDVInvokedUrlCommand.h in Headers */,
+ 8887FD8F1090FBE7009987E8 /* NSData+Base64.h in Headers */,
+ 1F92F4A01314023E0046367C /* CDVPluginResult.h in Headers */,
+ 30E33AF213A7E24B00594D64 /* CDVPlugin.h in Headers */,
+ 30E6B8CD1A8ADD900025B9EE /* CDVHandleOpenURL.h in Headers */,
+ 302965BC13A94E9D007046C5 /* CDVDebug.h in Headers */,
+ 30E563CF13E217EC00C949AA /* NSMutableArray+QueueAdditions.h in Headers */,
+ 30C684801406CB38004C1A8E /* CDVWhitelist.h in Headers */,
+ 30C684941407044B004C1A8E /* CDVURLProtocol.h in Headers */,
+ 8852C43A14B65FD800F0E735 /* CDVViewController.h in Headers */,
+ 30F5EBAB14CA26E700987760 /* CDVCommandDelegate.h in Headers */,
+ 301F2F2A14F3C9CA003FE9FC /* CDV.h in Headers */,
+ 30392E4E14F4FCAB00B9E0B8 /* CDVAvailability.h in Headers */,
+ 7E22B88519E4C0210026F95E /* CDVAvailabilityDeprecated.h in Headers */,
+ 3034979C1513D56A0090E688 /* CDVLocalStorage.h in Headers */,
+ 3062D120151D0EDB000D9128 /* UIDevice+Extensions.h in Headers */,
+ EBA3557315ABD38C00F4DE24 /* NSArray+Comparisons.h in Headers */,
+ EB3B3547161CB44D003DBE7D /* CDVCommandQueue.h in Headers */,
+ EB3B357C161F2A45003DBE7D /* CDVCommandDelegateImpl.h in Headers */,
+ 1B701028177A61CF00AE11F4 /* CDVShared.h in Headers */,
+ 3073E9ED1656D51200957977 /* CDVScreenOrientationDelegate.h in Headers */,
+ F858FBC6166009A8007DA594 /* CDVConfigParser.h in Headers */,
+ 30F3930B169F839700B22307 /* CDVJSON.h in Headers */,
+ EBFF4DBD16D3FE2E008F452B /* CDVWebViewDelegate.h in Headers */,
+ EB96673B16A8970A00D86CDF /* CDVUserAgentUtil.h in Headers */,
+ 7E14B5A81705050A0032169E /* CDVTimer.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ D2AAC07D0554694100DB518D /* CordovaLib */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "CordovaLib" */;
+ buildPhases = (
+ D2AAC07A0554694100DB518D /* Headers */,
+ D2AAC07B0554694100DB518D /* Sources */,
+ D2AAC07C0554694100DB518D /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = CordovaLib;
+ productName = CordovaLib;
+ productReference = 68A32D7114102E1C006B237C /* libCordova.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 0867D690FE84028FC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0510;
+ };
+ buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "CordovaLib" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ en,
+ );
+ mainGroup = 0867D691FE84028FC02AAC07 /* CordovaLib */;
+ productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ D2AAC07D0554694100DB518D /* CordovaLib */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ D2AAC07B0554694100DB518D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8887FD691090FBE7009987E8 /* NSDictionary+Extensions.m in Sources */,
+ 8887FD751090FBE7009987E8 /* CDVInvokedUrlCommand.m in Sources */,
+ 8887FD901090FBE7009987E8 /* NSData+Base64.m in Sources */,
+ 1F92F4A11314023E0046367C /* CDVPluginResult.m in Sources */,
+ 30E33AF313A7E24B00594D64 /* CDVPlugin.m in Sources */,
+ 30E563D013E217EC00C949AA /* NSMutableArray+QueueAdditions.m in Sources */,
+ 30C684821406CB38004C1A8E /* CDVWhitelist.m in Sources */,
+ 30C684961407044B004C1A8E /* CDVURLProtocol.m in Sources */,
+ 8852C43C14B65FD800F0E735 /* CDVViewController.m in Sources */,
+ 3034979E1513D56A0090E688 /* CDVLocalStorage.m in Sources */,
+ 3062D122151D0EDB000D9128 /* UIDevice+Extensions.m in Sources */,
+ EBA3557515ABD38C00F4DE24 /* NSArray+Comparisons.m in Sources */,
+ EB3B3548161CB44D003DBE7D /* CDVCommandQueue.m in Sources */,
+ EB6A98541A77EE470013FCDB /* CDVJSON_private.m in Sources */,
+ EB3B357D161F2A45003DBE7D /* CDVCommandDelegateImpl.m in Sources */,
+ F858FBC7166009A8007DA594 /* CDVConfigParser.m in Sources */,
+ 30F3930C169F839700B22307 /* CDVJSON.m in Sources */,
+ EB96673C16A8970A00D86CDF /* CDVUserAgentUtil.m in Sources */,
+ 30E6B8CE1A8ADD900025B9EE /* CDVHandleOpenURL.m in Sources */,
+ EBFF4DBC16D3FE2E008F452B /* CDVWebViewDelegate.m in Sources */,
+ 7E14B5A91705050A0032169E /* CDVTimer.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB921F08733DC00010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ COPY_PHASE_STRIP = NO;
+ DSTROOT = "/tmp/$(PROJECT_NAME).dst";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = CordovaLib_Prefix.pch;
+ GCC_PREPROCESSOR_DEFINITIONS = "";
+ GCC_THUMB_SUPPORT = NO;
+ GCC_VERSION = "";
+ INSTALL_PATH = /usr/local/lib;
+ IPHONEOS_DEPLOYMENT_TARGET = 6.0;
+ PRODUCT_NAME = Cordova;
+ PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
+ SKIP_INSTALL = YES;
+ };
+ name = Debug;
+ };
+ 1DEB922008733DC00010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ DSTROOT = "/tmp/$(PROJECT_NAME).dst";
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = CordovaLib_Prefix.pch;
+ GCC_PREPROCESSOR_DEFINITIONS = "";
+ GCC_THUMB_SUPPORT = NO;
+ GCC_VERSION = "";
+ INSTALL_PATH = /usr/local/lib;
+ IPHONEOS_DEPLOYMENT_TARGET = 6.0;
+ PRODUCT_NAME = Cordova;
+ PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
+ SKIP_INSTALL = YES;
+ };
+ name = Release;
+ };
+ 1DEB922308733DC00010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = "";
+ GCC_THUMB_SUPPORT = NO;
+ GCC_VERSION = "";
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 6.0;
+ ONLY_ACTIVE_ARCH = YES;
+ OTHER_CFLAGS = "-DDEBUG";
+ PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
+ SDKROOT = iphoneos;
+ SKIP_INSTALL = YES;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ USER_HEADER_SEARCH_PATHS = "";
+ };
+ name = Debug;
+ };
+ 1DEB922408733DC00010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_PREPROCESSOR_DEFINITIONS = "";
+ GCC_THUMB_SUPPORT = NO;
+ GCC_VERSION = "";
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 6.0;
+ ONLY_ACTIVE_ARCH = NO;
+ PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
+ SDKROOT = iphoneos;
+ SKIP_INSTALL = YES;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "CordovaLib" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB921F08733DC00010E9CD /* Debug */,
+ 1DEB922008733DC00010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "CordovaLib" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB922308733DC00010E9CD /* Debug */,
+ 1DEB922408733DC00010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}
diff --git a/StoneIsland/platforms/ios/CordovaLib/CordovaLib.xcodeproj/xcuserdata/jules.xcuserdatad/xcschemes/CordovaLib.xcscheme b/StoneIsland/platforms/ios/CordovaLib/CordovaLib.xcodeproj/xcuserdata/jules.xcuserdatad/xcschemes/CordovaLib.xcscheme
new file mode 100644
index 00000000..5dce491f
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/CordovaLib.xcodeproj/xcuserdata/jules.xcuserdatad/xcschemes/CordovaLib.xcscheme
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0640"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "D2AAC07D0554694100DB518D"
+ BuildableName = "libCordova.a"
+ BlueprintName = "CordovaLib"
+ ReferencedContainer = "container:CordovaLib.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Debug">
+ <Testables>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Debug"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "D2AAC07D0554694100DB518D"
+ BuildableName = "libCordova.a"
+ BlueprintName = "CordovaLib"
+ ReferencedContainer = "container:CordovaLib.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "D2AAC07D0554694100DB518D"
+ BuildableName = "libCordova.a"
+ BlueprintName = "CordovaLib"
+ ReferencedContainer = "container:CordovaLib.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/StoneIsland/platforms/ios/CordovaLib/CordovaLib.xcodeproj/xcuserdata/jules.xcuserdatad/xcschemes/xcschememanagement.plist b/StoneIsland/platforms/ios/CordovaLib/CordovaLib.xcodeproj/xcuserdata/jules.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 00000000..283503be
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/CordovaLib.xcodeproj/xcuserdata/jules.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,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>SchemeUserState</key>
+ <dict>
+ <key>CordovaLib.xcscheme</key>
+ <dict>
+ <key>orderHint</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>SuppressBuildableAutocreation</key>
+ <dict>
+ <key>D2AAC07D0554694100DB518D</key>
+ <dict>
+ <key>primary</key>
+ <true/>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/StoneIsland/platforms/ios/CordovaLib/CordovaLib_Prefix.pch b/StoneIsland/platforms/ios/CordovaLib/CordovaLib_Prefix.pch
new file mode 100644
index 00000000..95455807
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/CordovaLib_Prefix.pch
@@ -0,0 +1,22 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#ifdef __OBJC__
+ #import <Foundation/Foundation.h>
+#endif
diff --git a/StoneIsland/platforms/ios/CordovaLib/VERSION b/StoneIsland/platforms/ios/CordovaLib/VERSION
new file mode 100644
index 00000000..19811903
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/VERSION
@@ -0,0 +1 @@
+3.8.0
diff --git a/StoneIsland/platforms/ios/CordovaLib/cordova.js b/StoneIsland/platforms/ios/CordovaLib/cordova.js
new file mode 100644
index 00000000..4f781077
--- /dev/null
+++ b/StoneIsland/platforms/ios/CordovaLib/cordova.js
@@ -0,0 +1,1810 @@
+// Platform: ios
+// fc4db9145934bd0053161cbf9ffc0caf83b770c6
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+;(function() {
+var PLATFORM_VERSION_BUILD_LABEL = '3.8.0';
+// file: src/scripts/require.js
+
+/*jshint -W079 */
+/*jshint -W020 */
+
+var require,
+ define;
+
+(function () {
+ var modules = {},
+ // Stack of moduleIds currently being built.
+ requireStack = [],
+ // Map of module ID -> index into requireStack of modules currently being built.
+ inProgressModules = {},
+ SEPARATOR = ".";
+
+
+
+ function build(module) {
+ var factory = module.factory,
+ localRequire = function (id) {
+ var resultantId = id;
+ //Its a relative path, so lop off the last portion and add the id (minus "./")
+ if (id.charAt(0) === ".") {
+ resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
+ }
+ return require(resultantId);
+ };
+ module.exports = {};
+ delete module.factory;
+ factory(localRequire, module.exports, module);
+ return module.exports;
+ }
+
+ require = function (id) {
+ if (!modules[id]) {
+ throw "module " + id + " not found";
+ } else if (id in inProgressModules) {
+ var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
+ throw "Cycle in require graph: " + cycle;
+ }
+ if (modules[id].factory) {
+ try {
+ inProgressModules[id] = requireStack.length;
+ requireStack.push(id);
+ return build(modules[id]);
+ } finally {
+ delete inProgressModules[id];
+ requireStack.pop();
+ }
+ }
+ return modules[id].exports;
+ };
+
+ define = function (id, factory) {
+ if (modules[id]) {
+ throw "module " + id + " already defined";
+ }
+
+ modules[id] = {
+ id: id,
+ factory: factory
+ };
+ };
+
+ define.remove = function (id) {
+ delete modules[id];
+ };
+
+ define.moduleMap = modules;
+})();
+
+//Export for use in node
+if (typeof module === "object" && typeof require === "function") {
+ module.exports.require = require;
+ module.exports.define = define;
+}
+
+// file: src/cordova.js
+define("cordova", function(require, exports, module) {
+
+
+var channel = require('cordova/channel');
+var platform = require('cordova/platform');
+
+/**
+ * Intercept calls to addEventListener + removeEventListener and handle deviceready,
+ * resume, and pause events.
+ */
+var m_document_addEventListener = document.addEventListener;
+var m_document_removeEventListener = document.removeEventListener;
+var m_window_addEventListener = window.addEventListener;
+var m_window_removeEventListener = window.removeEventListener;
+
+/**
+ * Houses custom event handlers to intercept on document + window event listeners.
+ */
+var documentEventHandlers = {},
+ windowEventHandlers = {};
+
+document.addEventListener = function(evt, handler, capture) {
+ var e = evt.toLowerCase();
+ if (typeof documentEventHandlers[e] != 'undefined') {
+ documentEventHandlers[e].subscribe(handler);
+ } else {
+ m_document_addEventListener.call(document, evt, handler, capture);
+ }
+};
+
+window.addEventListener = function(evt, handler, capture) {
+ var e = evt.toLowerCase();
+ if (typeof windowEventHandlers[e] != 'undefined') {
+ windowEventHandlers[e].subscribe(handler);
+ } else {
+ m_window_addEventListener.call(window, evt, handler, capture);
+ }
+};
+
+document.removeEventListener = function(evt, handler, capture) {
+ var e = evt.toLowerCase();
+ // If unsubscribing from an event that is handled by a plugin
+ if (typeof documentEventHandlers[e] != "undefined") {
+ documentEventHandlers[e].unsubscribe(handler);
+ } else {
+ m_document_removeEventListener.call(document, evt, handler, capture);
+ }
+};
+
+window.removeEventListener = function(evt, handler, capture) {
+ var e = evt.toLowerCase();
+ // If unsubscribing from an event that is handled by a plugin
+ if (typeof windowEventHandlers[e] != "undefined") {
+ windowEventHandlers[e].unsubscribe(handler);
+ } else {
+ m_window_removeEventListener.call(window, evt, handler, capture);
+ }
+};
+
+function createEvent(type, data) {
+ var event = document.createEvent('Events');
+ event.initEvent(type, false, false);
+ if (data) {
+ for (var i in data) {
+ if (data.hasOwnProperty(i)) {
+ event[i] = data[i];
+ }
+ }
+ }
+ return event;
+}
+
+
+var cordova = {
+ define:define,
+ require:require,
+ version:PLATFORM_VERSION_BUILD_LABEL,
+ platformVersion:PLATFORM_VERSION_BUILD_LABEL,
+ platformId:platform.id,
+ /**
+ * Methods to add/remove your own addEventListener hijacking on document + window.
+ */
+ addWindowEventHandler:function(event) {
+ return (windowEventHandlers[event] = channel.create(event));
+ },
+ addStickyDocumentEventHandler:function(event) {
+ return (documentEventHandlers[event] = channel.createSticky(event));
+ },
+ addDocumentEventHandler:function(event) {
+ return (documentEventHandlers[event] = channel.create(event));
+ },
+ removeWindowEventHandler:function(event) {
+ delete windowEventHandlers[event];
+ },
+ removeDocumentEventHandler:function(event) {
+ delete documentEventHandlers[event];
+ },
+ /**
+ * Retrieve original event handlers that were replaced by Cordova
+ *
+ * @return object
+ */
+ getOriginalHandlers: function() {
+ return {'document': {'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener},
+ 'window': {'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener}};
+ },
+ /**
+ * Method to fire event from native code
+ * bNoDetach is required for events which cause an exception which needs to be caught in native code
+ */
+ fireDocumentEvent: function(type, data, bNoDetach) {
+ var evt = createEvent(type, data);
+ if (typeof documentEventHandlers[type] != 'undefined') {
+ if( bNoDetach ) {
+ documentEventHandlers[type].fire(evt);
+ }
+ else {
+ setTimeout(function() {
+ // Fire deviceready on listeners that were registered before cordova.js was loaded.
+ if (type == 'deviceready') {
+ document.dispatchEvent(evt);
+ }
+ documentEventHandlers[type].fire(evt);
+ }, 0);
+ }
+ } else {
+ document.dispatchEvent(evt);
+ }
+ },
+ fireWindowEvent: function(type, data) {
+ var evt = createEvent(type,data);
+ if (typeof windowEventHandlers[type] != 'undefined') {
+ setTimeout(function() {
+ windowEventHandlers[type].fire(evt);
+ }, 0);
+ } else {
+ window.dispatchEvent(evt);
+ }
+ },
+
+ /**
+ * Plugin callback mechanism.
+ */
+ // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
+ // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
+ callbackId: Math.floor(Math.random() * 2000000000),
+ callbacks: {},
+ callbackStatus: {
+ NO_RESULT: 0,
+ OK: 1,
+ CLASS_NOT_FOUND_EXCEPTION: 2,
+ ILLEGAL_ACCESS_EXCEPTION: 3,
+ INSTANTIATION_EXCEPTION: 4,
+ MALFORMED_URL_EXCEPTION: 5,
+ IO_EXCEPTION: 6,
+ INVALID_ACTION: 7,
+ JSON_EXCEPTION: 8,
+ ERROR: 9
+ },
+
+ /**
+ * Called by native code when returning successful result from an action.
+ */
+ callbackSuccess: function(callbackId, args) {
+ cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
+ },
+
+ /**
+ * Called by native code when returning error result from an action.
+ */
+ callbackError: function(callbackId, args) {
+ // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
+ // Derive success from status.
+ cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
+ },
+
+ /**
+ * Called by native code when returning the result from an action.
+ */
+ callbackFromNative: function(callbackId, isSuccess, status, args, keepCallback) {
+ try {
+ var callback = cordova.callbacks[callbackId];
+ if (callback) {
+ if (isSuccess && status == cordova.callbackStatus.OK) {
+ callback.success && callback.success.apply(null, args);
+ } else if (!isSuccess) {
+ callback.fail && callback.fail.apply(null, args);
+ }
+ /*
+ else
+ Note, this case is intentionally not caught.
+ this can happen if isSuccess is true, but callbackStatus is NO_RESULT
+ which is used to remove a callback from the list without calling the callbacks
+ typically keepCallback is false in this case
+ */
+ // Clear callback if not expecting any more results
+ if (!keepCallback) {
+ delete cordova.callbacks[callbackId];
+ }
+ }
+ }
+ catch (err) {
+ var msg = "Error in " + (isSuccess ? "Success" : "Error") + " callbackId: " + callbackId + " : " + err;
+ console && console.log && console.log(msg);
+ cordova.fireWindowEvent("cordovacallbackerror", { 'message': msg });
+ throw err;
+ }
+ },
+ addConstructor: function(func) {
+ channel.onCordovaReady.subscribe(function() {
+ try {
+ func();
+ } catch(e) {
+ console.log("Failed to run constructor: " + e);
+ }
+ });
+ }
+};
+
+
+module.exports = cordova;
+
+});
+
+// file: src/common/argscheck.js
+define("cordova/argscheck", function(require, exports, module) {
+
+var exec = require('cordova/exec');
+var utils = require('cordova/utils');
+
+var moduleExports = module.exports;
+
+var typeMap = {
+ 'A': 'Array',
+ 'D': 'Date',
+ 'N': 'Number',
+ 'S': 'String',
+ 'F': 'Function',
+ 'O': 'Object'
+};
+
+function extractParamName(callee, argIndex) {
+ return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
+}
+
+function checkArgs(spec, functionName, args, opt_callee) {
+ if (!moduleExports.enableChecks) {
+ return;
+ }
+ var errMsg = null;
+ var typeName;
+ for (var i = 0; i < spec.length; ++i) {
+ var c = spec.charAt(i),
+ cUpper = c.toUpperCase(),
+ arg = args[i];
+ // Asterix means allow anything.
+ if (c == '*') {
+ continue;
+ }
+ typeName = utils.typeName(arg);
+ if ((arg === null || arg === undefined) && c == cUpper) {
+ continue;
+ }
+ if (typeName != typeMap[cUpper]) {
+ errMsg = 'Expected ' + typeMap[cUpper];
+ break;
+ }
+ }
+ if (errMsg) {
+ errMsg += ', but got ' + typeName + '.';
+ errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
+ // Don't log when running unit tests.
+ if (typeof jasmine == 'undefined') {
+ console.error(errMsg);
+ }
+ throw TypeError(errMsg);
+ }
+}
+
+function getValue(value, defaultValue) {
+ return value === undefined ? defaultValue : value;
+}
+
+moduleExports.checkArgs = checkArgs;
+moduleExports.getValue = getValue;
+moduleExports.enableChecks = true;
+
+
+});
+
+// file: src/common/base64.js
+define("cordova/base64", function(require, exports, module) {
+
+var base64 = exports;
+
+base64.fromArrayBuffer = function(arrayBuffer) {
+ var array = new Uint8Array(arrayBuffer);
+ return uint8ToBase64(array);
+};
+
+base64.toArrayBuffer = function(str) {
+ var decodedStr = typeof atob != 'undefined' ? atob(str) : new Buffer(str,'base64').toString('binary');
+ var arrayBuffer = new ArrayBuffer(decodedStr.length);
+ var array = new Uint8Array(arrayBuffer);
+ for (var i=0, len=decodedStr.length; i < len; i++) {
+ array[i] = decodedStr.charCodeAt(i);
+ }
+ return arrayBuffer;
+};
+
+//------------------------------------------------------------------------------
+
+/* This code is based on the performance tests at http://jsperf.com/b64tests
+ * This 12-bit-at-a-time algorithm was the best performing version on all
+ * platforms tested.
+ */
+
+var b64_6bit = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+var b64_12bit;
+
+var b64_12bitTable = function() {
+ b64_12bit = [];
+ for (var i=0; i<64; i++) {
+ for (var j=0; j<64; j++) {
+ b64_12bit[i*64+j] = b64_6bit[i] + b64_6bit[j];
+ }
+ }
+ b64_12bitTable = function() { return b64_12bit; };
+ return b64_12bit;
+};
+
+function uint8ToBase64(rawData) {
+ var numBytes = rawData.byteLength;
+ var output="";
+ var segment;
+ var table = b64_12bitTable();
+ for (var i=0;i<numBytes-2;i+=3) {
+ segment = (rawData[i] << 16) + (rawData[i+1] << 8) + rawData[i+2];
+ output += table[segment >> 12];
+ output += table[segment & 0xfff];
+ }
+ if (numBytes - i == 2) {
+ segment = (rawData[i] << 16) + (rawData[i+1] << 8);
+ output += table[segment >> 12];
+ output += b64_6bit[(segment & 0xfff) >> 6];
+ output += '=';
+ } else if (numBytes - i == 1) {
+ segment = (rawData[i] << 16);
+ output += table[segment >> 12];
+ output += '==';
+ }
+ return output;
+}
+
+});
+
+// file: src/common/builder.js
+define("cordova/builder", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+function each(objects, func, context) {
+ for (var prop in objects) {
+ if (objects.hasOwnProperty(prop)) {
+ func.apply(context, [objects[prop], prop]);
+ }
+ }
+}
+
+function clobber(obj, key, value) {
+ exports.replaceHookForTesting(obj, key);
+ var needsProperty = false;
+ try {
+ obj[key] = value;
+ } catch (e) {
+ needsProperty = true;
+ }
+ // Getters can only be overridden by getters.
+ if (needsProperty || obj[key] !== value) {
+ utils.defineGetter(obj, key, function() {
+ return value;
+ });
+ }
+}
+
+function assignOrWrapInDeprecateGetter(obj, key, value, message) {
+ if (message) {
+ utils.defineGetter(obj, key, function() {
+ console.log(message);
+ delete obj[key];
+ clobber(obj, key, value);
+ return value;
+ });
+ } else {
+ clobber(obj, key, value);
+ }
+}
+
+function include(parent, objects, clobber, merge) {
+ each(objects, function (obj, key) {
+ try {
+ var result = obj.path ? require(obj.path) : {};
+
+ if (clobber) {
+ // Clobber if it doesn't exist.
+ if (typeof parent[key] === 'undefined') {
+ assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+ } else if (typeof obj.path !== 'undefined') {
+ // If merging, merge properties onto parent, otherwise, clobber.
+ if (merge) {
+ recursiveMerge(parent[key], result);
+ } else {
+ assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+ }
+ }
+ result = parent[key];
+ } else {
+ // Overwrite if not currently defined.
+ if (typeof parent[key] == 'undefined') {
+ assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+ } else {
+ // Set result to what already exists, so we can build children into it if they exist.
+ result = parent[key];
+ }
+ }
+
+ if (obj.children) {
+ include(result, obj.children, clobber, merge);
+ }
+ } catch(e) {
+ utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
+ }
+ });
+}
+
+/**
+ * Merge properties from one object onto another recursively. Properties from
+ * the src object will overwrite existing target property.
+ *
+ * @param target Object to merge properties into.
+ * @param src Object to merge properties from.
+ */
+function recursiveMerge(target, src) {
+ for (var prop in src) {
+ if (src.hasOwnProperty(prop)) {
+ if (target.prototype && target.prototype.constructor === target) {
+ // If the target object is a constructor override off prototype.
+ clobber(target.prototype, prop, src[prop]);
+ } else {
+ if (typeof src[prop] === 'object' && typeof target[prop] === 'object') {
+ recursiveMerge(target[prop], src[prop]);
+ } else {
+ clobber(target, prop, src[prop]);
+ }
+ }
+ }
+ }
+}
+
+exports.buildIntoButDoNotClobber = function(objects, target) {
+ include(target, objects, false, false);
+};
+exports.buildIntoAndClobber = function(objects, target) {
+ include(target, objects, true, false);
+};
+exports.buildIntoAndMerge = function(objects, target) {
+ include(target, objects, true, true);
+};
+exports.recursiveMerge = recursiveMerge;
+exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
+exports.replaceHookForTesting = function() {};
+
+});
+
+// file: src/common/channel.js
+define("cordova/channel", function(require, exports, module) {
+
+var utils = require('cordova/utils'),
+ nextGuid = 1;
+
+/**
+ * Custom pub-sub "channel" that can have functions subscribed to it
+ * This object is used to define and control firing of events for
+ * cordova initialization, as well as for custom events thereafter.
+ *
+ * The order of events during page load and Cordova startup is as follows:
+ *
+ * onDOMContentLoaded* Internal event that is received when the web page is loaded and parsed.
+ * onNativeReady* Internal event that indicates the Cordova native side is ready.
+ * onCordovaReady* Internal event fired when all Cordova JavaScript objects have been created.
+ * onDeviceReady* User event fired to indicate that Cordova is ready
+ * onResume User event fired to indicate a start/resume lifecycle event
+ * onPause User event fired to indicate a pause lifecycle event
+ *
+ * The events marked with an * are sticky. Once they have fired, they will stay in the fired state.
+ * All listeners that subscribe after the event is fired will be executed right away.
+ *
+ * The only Cordova events that user code should register for are:
+ * deviceready Cordova native code is initialized and Cordova APIs can be called from JavaScript
+ * pause App has moved to background
+ * resume App has returned to foreground
+ *
+ * Listeners can be registered as:
+ * document.addEventListener("deviceready", myDeviceReadyListener, false);
+ * document.addEventListener("resume", myResumeListener, false);
+ * document.addEventListener("pause", myPauseListener, false);
+ *
+ * The DOM lifecycle events should be used for saving and restoring state
+ * window.onload
+ * window.onunload
+ *
+ */
+
+/**
+ * Channel
+ * @constructor
+ * @param type String the channel name
+ */
+var Channel = function(type, sticky) {
+ this.type = type;
+ // Map of guid -> function.
+ this.handlers = {};
+ // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired.
+ this.state = sticky ? 1 : 0;
+ // Used in sticky mode to remember args passed to fire().
+ this.fireArgs = null;
+ // Used by onHasSubscribersChange to know if there are any listeners.
+ this.numHandlers = 0;
+ // Function that is called when the first listener is subscribed, or when
+ // the last listener is unsubscribed.
+ this.onHasSubscribersChange = null;
+},
+ channel = {
+ /**
+ * Calls the provided function only after all of the channels specified
+ * have been fired. All channels must be sticky channels.
+ */
+ join: function(h, c) {
+ var len = c.length,
+ i = len,
+ f = function() {
+ if (!(--i)) h();
+ };
+ for (var j=0; j<len; j++) {
+ if (c[j].state === 0) {
+ throw Error('Can only use join with sticky channels.');
+ }
+ c[j].subscribe(f);
+ }
+ if (!len) h();
+ },
+ create: function(type) {
+ return channel[type] = new Channel(type, false);
+ },
+ createSticky: function(type) {
+ return channel[type] = new Channel(type, true);
+ },
+
+ /**
+ * cordova Channels that must fire before "deviceready" is fired.
+ */
+ deviceReadyChannelsArray: [],
+ deviceReadyChannelsMap: {},
+
+ /**
+ * Indicate that a feature needs to be initialized before it is ready to be used.
+ * This holds up Cordova's "deviceready" event until the feature has been initialized
+ * and Cordova.initComplete(feature) is called.
+ *
+ * @param feature {String} The unique feature name
+ */
+ waitForInitialization: function(feature) {
+ if (feature) {
+ var c = channel[feature] || this.createSticky(feature);
+ this.deviceReadyChannelsMap[feature] = c;
+ this.deviceReadyChannelsArray.push(c);
+ }
+ },
+
+ /**
+ * Indicate that initialization code has completed and the feature is ready to be used.
+ *
+ * @param feature {String} The unique feature name
+ */
+ initializationComplete: function(feature) {
+ var c = this.deviceReadyChannelsMap[feature];
+ if (c) {
+ c.fire();
+ }
+ }
+ };
+
+function forceFunction(f) {
+ if (typeof f != 'function') throw "Function required as first argument!";
+}
+
+/**
+ * Subscribes the given function to the channel. Any time that
+ * Channel.fire is called so too will the function.
+ * Optionally specify an execution context for the function
+ * and a guid that can be used to stop subscribing to the channel.
+ * Returns the guid.
+ */
+Channel.prototype.subscribe = function(f, c) {
+ // need a function to call
+ forceFunction(f);
+ if (this.state == 2) {
+ f.apply(c || this, this.fireArgs);
+ return;
+ }
+
+ var func = f,
+ guid = f.observer_guid;
+ if (typeof c == "object") { func = utils.close(c, f); }
+
+ if (!guid) {
+ // first time any channel has seen this subscriber
+ guid = '' + nextGuid++;
+ }
+ func.observer_guid = guid;
+ f.observer_guid = guid;
+
+ // Don't add the same handler more than once.
+ if (!this.handlers[guid]) {
+ this.handlers[guid] = func;
+ this.numHandlers++;
+ if (this.numHandlers == 1) {
+ this.onHasSubscribersChange && this.onHasSubscribersChange();
+ }
+ }
+};
+
+/**
+ * Unsubscribes the function with the given guid from the channel.
+ */
+Channel.prototype.unsubscribe = function(f) {
+ // need a function to unsubscribe
+ forceFunction(f);
+
+ var guid = f.observer_guid,
+ handler = this.handlers[guid];
+ if (handler) {
+ delete this.handlers[guid];
+ this.numHandlers--;
+ if (this.numHandlers === 0) {
+ this.onHasSubscribersChange && this.onHasSubscribersChange();
+ }
+ }
+};
+
+/**
+ * Calls all functions subscribed to this channel.
+ */
+Channel.prototype.fire = function(e) {
+ var fail = false,
+ fireArgs = Array.prototype.slice.call(arguments);
+ // Apply stickiness.
+ if (this.state == 1) {
+ this.state = 2;
+ this.fireArgs = fireArgs;
+ }
+ if (this.numHandlers) {
+ // Copy the values first so that it is safe to modify it from within
+ // callbacks.
+ var toCall = [];
+ for (var item in this.handlers) {
+ toCall.push(this.handlers[item]);
+ }
+ for (var i = 0; i < toCall.length; ++i) {
+ toCall[i].apply(this, fireArgs);
+ }
+ if (this.state == 2 && this.numHandlers) {
+ this.numHandlers = 0;
+ this.handlers = {};
+ this.onHasSubscribersChange && this.onHasSubscribersChange();
+ }
+ }
+};
+
+
+// defining them here so they are ready super fast!
+// DOM event that is received when the web page is loaded and parsed.
+channel.createSticky('onDOMContentLoaded');
+
+// Event to indicate the Cordova native side is ready.
+channel.createSticky('onNativeReady');
+
+// Event to indicate that all Cordova JavaScript objects have been created
+// and it's time to run plugin constructors.
+channel.createSticky('onCordovaReady');
+
+// Event to indicate that all automatically loaded JS plugins are loaded and ready.
+// FIXME remove this
+channel.createSticky('onPluginsReady');
+
+// Event to indicate that Cordova is ready
+channel.createSticky('onDeviceReady');
+
+// Event to indicate a resume lifecycle event
+channel.create('onResume');
+
+// Event to indicate a pause lifecycle event
+channel.create('onPause');
+
+// Channels that must fire before "deviceready" is fired.
+channel.waitForInitialization('onCordovaReady');
+channel.waitForInitialization('onDOMContentLoaded');
+
+module.exports = channel;
+
+});
+
+// file: src/ios/exec.js
+define("cordova/exec", function(require, exports, module) {
+
+/**
+ * Creates a gap bridge iframe used to notify the native code about queued
+ * commands.
+ */
+var cordova = require('cordova'),
+ channel = require('cordova/channel'),
+ utils = require('cordova/utils'),
+ base64 = require('cordova/base64'),
+ // XHR mode does not work on iOS 4.2.
+ // XHR mode's main advantage is working around a bug in -webkit-scroll, which
+ // doesn't exist only on iOS 5.x devices.
+ // IFRAME_NAV is the fastest.
+ // IFRAME_HASH could be made to enable synchronous bridge calls if we wanted this feature.
+ jsToNativeModes = {
+ IFRAME_NAV: 0, // Default. Uses a new iframe for each poke.
+ // XHR bridge appears to be flaky sometimes: CB-3900, CB-3359, CB-5457, CB-4970, CB-4998, CB-5134
+ XHR_NO_PAYLOAD: 1, // About the same speed as IFRAME_NAV. Performance not about the same as IFRAME_NAV, but more variable.
+ XHR_WITH_PAYLOAD: 2, // Flakey, and not as performant
+ XHR_OPTIONAL_PAYLOAD: 3, // Flakey, and not as performant
+ IFRAME_HASH_NO_PAYLOAD: 4, // Not fully baked. A bit faster than IFRAME_NAV, but risks jank since poke happens synchronously.
+ IFRAME_HASH_WITH_PAYLOAD: 5, // Slower than no payload. Maybe since it has to be URI encoded / decoded.
+ WK_WEBVIEW_BINDING: 6 // Only way that works for WKWebView :)
+ },
+ bridgeMode,
+ execIframe,
+ execHashIframe,
+ hashToggle = 1,
+ execXhr,
+ requestCount = 0,
+ vcHeaderValue = null,
+ commandQueue = [], // Contains pending JS->Native messages.
+ isInContextOfEvalJs = 0,
+ failSafeTimerId = 0;
+
+function shouldBundleCommandJson() {
+ if (bridgeMode === jsToNativeModes.XHR_WITH_PAYLOAD) {
+ return true;
+ }
+ if (bridgeMode === jsToNativeModes.XHR_OPTIONAL_PAYLOAD) {
+ var payloadLength = 0;
+ for (var i = 0; i < commandQueue.length; ++i) {
+ payloadLength += commandQueue[i].length;
+ }
+ // The value here was determined using the benchmark within CordovaLibApp on an iPad 3.
+ return payloadLength < 4500;
+ }
+ return false;
+}
+
+function massageArgsJsToNative(args) {
+ if (!args || utils.typeName(args) != 'Array') {
+ return args;
+ }
+ var ret = [];
+ args.forEach(function(arg, i) {
+ if (utils.typeName(arg) == 'ArrayBuffer') {
+ ret.push({
+ 'CDVType': 'ArrayBuffer',
+ 'data': base64.fromArrayBuffer(arg)
+ });
+ } else {
+ ret.push(arg);
+ }
+ });
+ return ret;
+}
+
+function massageMessageNativeToJs(message) {
+ if (message.CDVType == 'ArrayBuffer') {
+ var stringToArrayBuffer = function(str) {
+ var ret = new Uint8Array(str.length);
+ for (var i = 0; i < str.length; i++) {
+ ret[i] = str.charCodeAt(i);
+ }
+ return ret.buffer;
+ };
+ var base64ToArrayBuffer = function(b64) {
+ return stringToArrayBuffer(atob(b64));
+ };
+ message = base64ToArrayBuffer(message.data);
+ }
+ return message;
+}
+
+function convertMessageToArgsNativeToJs(message) {
+ var args = [];
+ if (!message || !message.hasOwnProperty('CDVType')) {
+ args.push(message);
+ } else if (message.CDVType == 'MultiPart') {
+ message.messages.forEach(function(e) {
+ args.push(massageMessageNativeToJs(e));
+ });
+ } else {
+ args.push(massageMessageNativeToJs(message));
+ }
+ return args;
+}
+
+function iOSExec() {
+ if (bridgeMode === undefined) {
+ bridgeMode = jsToNativeModes.IFRAME_NAV;
+ }
+
+ if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.cordova && window.webkit.messageHandlers.cordova.postMessage) {
+ bridgeMode = jsToNativeModes.WK_WEBVIEW_BINDING;
+ }
+
+ var successCallback, failCallback, service, action, actionArgs, splitCommand;
+ var callbackId = null;
+ if (typeof arguments[0] !== "string") {
+ // FORMAT ONE
+ successCallback = arguments[0];
+ failCallback = arguments[1];
+ service = arguments[2];
+ action = arguments[3];
+ actionArgs = arguments[4];
+
+ // Since we need to maintain backwards compatibility, we have to pass
+ // an invalid callbackId even if no callback was provided since plugins
+ // will be expecting it. The Cordova.exec() implementation allocates
+ // an invalid callbackId and passes it even if no callbacks were given.
+ callbackId = 'INVALID';
+ } else {
+ // FORMAT TWO, REMOVED
+ try {
+ splitCommand = arguments[0].split(".");
+ action = splitCommand.pop();
+ service = splitCommand.join(".");
+ actionArgs = Array.prototype.splice.call(arguments, 1);
+
+ console.log('The old format of this exec call has been removed (deprecated since 2.1). Change to: ' +
+ "cordova.exec(null, null, \"" + service + "\", \"" + action + "\"," + JSON.stringify(actionArgs) + ");"
+ );
+ return;
+ } catch (e) {}
+ }
+
+ // If actionArgs is not provided, default to an empty array
+ actionArgs = actionArgs || [];
+
+ // Register the callbacks and add the callbackId to the positional
+ // arguments if given.
+ if (successCallback || failCallback) {
+ callbackId = service + cordova.callbackId++;
+ cordova.callbacks[callbackId] =
+ {success:successCallback, fail:failCallback};
+ }
+
+ actionArgs = massageArgsJsToNative(actionArgs);
+
+ var command = [callbackId, service, action, actionArgs];
+
+ // Stringify and queue the command. We stringify to command now to
+ // effectively clone the command arguments in case they are mutated before
+ // the command is executed.
+ commandQueue.push(JSON.stringify(command));
+
+ if (bridgeMode === jsToNativeModes.WK_WEBVIEW_BINDING) {
+ window.webkit.messageHandlers.cordova.postMessage(command);
+ } else {
+ // If we're in the context of a stringByEvaluatingJavaScriptFromString call,
+ // then the queue will be flushed when it returns; no need for a poke.
+ // Also, if there is already a command in the queue, then we've already
+ // poked the native side, so there is no reason to do so again.
+ if (!isInContextOfEvalJs && commandQueue.length == 1) {
+ pokeNative();
+ }
+ }
+}
+
+function pokeNative() {
+ switch (bridgeMode) {
+ case jsToNativeModes.XHR_NO_PAYLOAD:
+ case jsToNativeModes.XHR_WITH_PAYLOAD:
+ case jsToNativeModes.XHR_OPTIONAL_PAYLOAD:
+ pokeNativeViaXhr();
+ break;
+ default: // iframe-based.
+ pokeNativeViaIframe();
+ }
+}
+
+function pokeNativeViaXhr() {
+ // This prevents sending an XHR when there is already one being sent.
+ // This should happen only in rare circumstances (refer to unit tests).
+ if (execXhr && execXhr.readyState != 4) {
+ execXhr = null;
+ }
+ // Re-using the XHR improves exec() performance by about 10%.
+ execXhr = execXhr || new XMLHttpRequest();
+ // Changing this to a GET will make the XHR reach the URIProtocol on 4.2.
+ // For some reason it still doesn't work though...
+ // Add a timestamp to the query param to prevent caching.
+ execXhr.open('HEAD', "/!gap_exec?" + (+new Date()), true);
+ if (!vcHeaderValue) {
+ vcHeaderValue = /.*\((.*)\)$/.exec(navigator.userAgent)[1];
+ }
+ execXhr.setRequestHeader('vc', vcHeaderValue);
+ execXhr.setRequestHeader('rc', ++requestCount);
+ if (shouldBundleCommandJson()) {
+ execXhr.setRequestHeader('cmds', iOSExec.nativeFetchMessages());
+ }
+ execXhr.send(null);
+}
+
+function pokeNativeViaIframe() {
+ // CB-5488 - Don't attempt to create iframe before document.body is available.
+ if (!document.body) {
+ setTimeout(pokeNativeViaIframe);
+ return;
+ }
+ if (bridgeMode === jsToNativeModes.IFRAME_HASH_NO_PAYLOAD || bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) {
+ // TODO: This bridge mode doesn't properly support being removed from the DOM (CB-7735)
+ if (!execHashIframe) {
+ execHashIframe = document.createElement('iframe');
+ execHashIframe.style.display = 'none';
+ document.body.appendChild(execHashIframe);
+ // Hash changes don't work on about:blank, so switch it to file:///.
+ execHashIframe.contentWindow.history.replaceState(null, null, 'file:///#');
+ }
+ // The delegate method is called only when the hash changes, so toggle it back and forth.
+ hashToggle = hashToggle ^ 3;
+ var hashValue = '%0' + hashToggle;
+ if (bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) {
+ hashValue += iOSExec.nativeFetchMessages();
+ }
+ execHashIframe.contentWindow.location.hash = hashValue;
+ } else {
+ // Check if they've removed it from the DOM, and put it back if so.
+ if (execIframe && execIframe.contentWindow) {
+ execIframe.contentWindow.location = 'gap://ready';
+ } else {
+ execIframe = document.createElement('iframe');
+ execIframe.style.display = 'none';
+ execIframe.src = 'gap://ready';
+ document.body.appendChild(execIframe);
+ }
+ // Use a timer to protect against iframe being unloaded during the poke (CB-7735).
+ // This makes the bridge ~ 7% slower, but works around the poke getting lost
+ // when the iframe is removed from the DOM.
+ // An onunload listener could be used in the case where the iframe has just been
+ // created, but since unload events fire only once, it doesn't work in the normal
+ // case of iframe reuse (where unload will have already fired due to the attempted
+ // navigation of the page).
+ failSafeTimerId = setTimeout(function() {
+ if (commandQueue.length) {
+ pokeNative();
+ }
+ }, 50); // Making this > 0 improves performance (marginally) in the normal case (where it doesn't fire).
+ }
+}
+
+iOSExec.jsToNativeModes = jsToNativeModes;
+
+iOSExec.setJsToNativeBridgeMode = function(mode) {
+ // Remove the iFrame since it may be no longer required, and its existence
+ // can trigger browser bugs.
+ // https://issues.apache.org/jira/browse/CB-593
+ if (execIframe) {
+ if (execIframe.parentNode) {
+ execIframe.parentNode.removeChild(execIframe);
+ }
+ execIframe = null;
+ }
+ bridgeMode = mode;
+};
+
+iOSExec.nativeFetchMessages = function() {
+ // Stop listing for window detatch once native side confirms poke.
+ if (failSafeTimerId) {
+ clearTimeout(failSafeTimerId);
+ failSafeTimerId = 0;
+ }
+ // Each entry in commandQueue is a JSON string already.
+ if (!commandQueue.length) {
+ return '';
+ }
+ var json = '[' + commandQueue.join(',') + ']';
+ commandQueue.length = 0;
+ return json;
+};
+
+iOSExec.nativeCallback = function(callbackId, status, message, keepCallback) {
+ return iOSExec.nativeEvalAndFetch(function() {
+ var success = status === 0 || status === 1;
+ var args = convertMessageToArgsNativeToJs(message);
+ cordova.callbackFromNative(callbackId, success, status, args, keepCallback);
+ });
+};
+
+iOSExec.nativeEvalAndFetch = function(func) {
+ // This shouldn't be nested, but better to be safe.
+ isInContextOfEvalJs++;
+ try {
+ func();
+ return iOSExec.nativeFetchMessages();
+ } finally {
+ isInContextOfEvalJs--;
+ }
+};
+
+module.exports = iOSExec;
+
+});
+
+// file: src/common/exec/proxy.js
+define("cordova/exec/proxy", function(require, exports, module) {
+
+
+// internal map of proxy function
+var CommandProxyMap = {};
+
+module.exports = {
+
+ // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
+ add:function(id,proxyObj) {
+ console.log("adding proxy for " + id);
+ CommandProxyMap[id] = proxyObj;
+ return proxyObj;
+ },
+
+ // cordova.commandProxy.remove("Accelerometer");
+ remove:function(id) {
+ var proxy = CommandProxyMap[id];
+ delete CommandProxyMap[id];
+ CommandProxyMap[id] = null;
+ return proxy;
+ },
+
+ get:function(service,action) {
+ return ( CommandProxyMap[service] ? CommandProxyMap[service][action] : null );
+ }
+};
+});
+
+// file: src/common/init.js
+define("cordova/init", function(require, exports, module) {
+
+var channel = require('cordova/channel');
+var cordova = require('cordova');
+var modulemapper = require('cordova/modulemapper');
+var platform = require('cordova/platform');
+var pluginloader = require('cordova/pluginloader');
+var utils = require('cordova/utils');
+
+var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
+
+function logUnfiredChannels(arr) {
+ for (var i = 0; i < arr.length; ++i) {
+ if (arr[i].state != 2) {
+ console.log('Channel not fired: ' + arr[i].type);
+ }
+ }
+}
+
+window.setTimeout(function() {
+ if (channel.onDeviceReady.state != 2) {
+ console.log('deviceready has not fired after 5 seconds.');
+ logUnfiredChannels(platformInitChannelsArray);
+ logUnfiredChannels(channel.deviceReadyChannelsArray);
+ }
+}, 5000);
+
+// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
+// We replace it so that properties that can't be clobbered can instead be overridden.
+function replaceNavigator(origNavigator) {
+ var CordovaNavigator = function() {};
+ CordovaNavigator.prototype = origNavigator;
+ var newNavigator = new CordovaNavigator();
+ // This work-around really only applies to new APIs that are newer than Function.bind.
+ // Without it, APIs such as getGamepads() break.
+ if (CordovaNavigator.bind) {
+ for (var key in origNavigator) {
+ if (typeof origNavigator[key] == 'function') {
+ newNavigator[key] = origNavigator[key].bind(origNavigator);
+ }
+ else {
+ (function(k) {
+ utils.defineGetterSetter(newNavigator,key,function() {
+ return origNavigator[k];
+ });
+ })(key);
+ }
+ }
+ }
+ return newNavigator;
+}
+
+if (window.navigator) {
+ window.navigator = replaceNavigator(window.navigator);
+}
+
+if (!window.console) {
+ window.console = {
+ log: function(){}
+ };
+}
+if (!window.console.warn) {
+ window.console.warn = function(msg) {
+ this.log("warn: " + msg);
+ };
+}
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+// Listen for DOMContentLoaded and notify our channel subscribers.
+if (document.readyState == 'complete' || document.readyState == 'interactive') {
+ channel.onDOMContentLoaded.fire();
+} else {
+ document.addEventListener('DOMContentLoaded', function() {
+ channel.onDOMContentLoaded.fire();
+ }, false);
+}
+
+// _nativeReady is global variable that the native side can set
+// to signify that the native code is ready. It is a global since
+// it may be called before any cordova JS is ready.
+if (window._nativeReady) {
+ channel.onNativeReady.fire();
+}
+
+modulemapper.clobbers('cordova', 'cordova');
+modulemapper.clobbers('cordova/exec', 'cordova.exec');
+modulemapper.clobbers('cordova/exec', 'Cordova.exec');
+
+// Call the platform-specific initialization.
+platform.bootstrap && platform.bootstrap();
+
+// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
+// The delay allows the attached modules to be defined before the plugin loader looks for them.
+setTimeout(function() {
+ pluginloader.load(function() {
+ channel.onPluginsReady.fire();
+ });
+}, 0);
+
+/**
+ * Create all cordova objects once native side is ready.
+ */
+channel.join(function() {
+ modulemapper.mapModules(window);
+
+ platform.initialize && platform.initialize();
+
+ // Fire event to notify that all objects are created
+ channel.onCordovaReady.fire();
+
+ // Fire onDeviceReady event once page has fully loaded, all
+ // constructors have run and cordova info has been received from native
+ // side.
+ channel.join(function() {
+ require('cordova').fireDocumentEvent('deviceready');
+ }, channel.deviceReadyChannelsArray);
+
+}, platformInitChannelsArray);
+
+
+});
+
+// file: src/common/init_b.js
+define("cordova/init_b", function(require, exports, module) {
+
+var channel = require('cordova/channel');
+var cordova = require('cordova');
+var platform = require('cordova/platform');
+var utils = require('cordova/utils');
+
+var platformInitChannelsArray = [channel.onDOMContentLoaded, channel.onNativeReady];
+
+// setting exec
+cordova.exec = require('cordova/exec');
+
+function logUnfiredChannels(arr) {
+ for (var i = 0; i < arr.length; ++i) {
+ if (arr[i].state != 2) {
+ console.log('Channel not fired: ' + arr[i].type);
+ }
+ }
+}
+
+window.setTimeout(function() {
+ if (channel.onDeviceReady.state != 2) {
+ console.log('deviceready has not fired after 5 seconds.');
+ logUnfiredChannels(platformInitChannelsArray);
+ logUnfiredChannels(channel.deviceReadyChannelsArray);
+ }
+}, 5000);
+
+// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
+// We replace it so that properties that can't be clobbered can instead be overridden.
+function replaceNavigator(origNavigator) {
+ var CordovaNavigator = function() {};
+ CordovaNavigator.prototype = origNavigator;
+ var newNavigator = new CordovaNavigator();
+ // This work-around really only applies to new APIs that are newer than Function.bind.
+ // Without it, APIs such as getGamepads() break.
+ if (CordovaNavigator.bind) {
+ for (var key in origNavigator) {
+ if (typeof origNavigator[key] == 'function') {
+ newNavigator[key] = origNavigator[key].bind(origNavigator);
+ }
+ else {
+ (function(k) {
+ utils.defineGetterSetter(newNavigator,key,function() {
+ return origNavigator[k];
+ });
+ })(key);
+ }
+ }
+ }
+ return newNavigator;
+}
+if (window.navigator) {
+ window.navigator = replaceNavigator(window.navigator);
+}
+
+if (!window.console) {
+ window.console = {
+ log: function(){}
+ };
+}
+if (!window.console.warn) {
+ window.console.warn = function(msg) {
+ this.log("warn: " + msg);
+ };
+}
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+// Listen for DOMContentLoaded and notify our channel subscribers.
+if (document.readyState == 'complete' || document.readyState == 'interactive') {
+ channel.onDOMContentLoaded.fire();
+} else {
+ document.addEventListener('DOMContentLoaded', function() {
+ channel.onDOMContentLoaded.fire();
+ }, false);
+}
+
+// _nativeReady is global variable that the native side can set
+// to signify that the native code is ready. It is a global since
+// it may be called before any cordova JS is ready.
+if (window._nativeReady) {
+ channel.onNativeReady.fire();
+}
+
+// Call the platform-specific initialization.
+platform.bootstrap && platform.bootstrap();
+
+/**
+ * Create all cordova objects once native side is ready.
+ */
+channel.join(function() {
+
+ platform.initialize && platform.initialize();
+
+ // Fire event to notify that all objects are created
+ channel.onCordovaReady.fire();
+
+ // Fire onDeviceReady event once page has fully loaded, all
+ // constructors have run and cordova info has been received from native
+ // side.
+ channel.join(function() {
+ require('cordova').fireDocumentEvent('deviceready');
+ }, channel.deviceReadyChannelsArray);
+
+}, platformInitChannelsArray);
+
+});
+
+// file: src/common/modulemapper.js
+define("cordova/modulemapper", function(require, exports, module) {
+
+var builder = require('cordova/builder'),
+ moduleMap = define.moduleMap,
+ symbolList,
+ deprecationMap;
+
+exports.reset = function() {
+ symbolList = [];
+ deprecationMap = {};
+};
+
+function addEntry(strategy, moduleName, symbolPath, opt_deprecationMessage) {
+ if (!(moduleName in moduleMap)) {
+ throw new Error('Module ' + moduleName + ' does not exist.');
+ }
+ symbolList.push(strategy, moduleName, symbolPath);
+ if (opt_deprecationMessage) {
+ deprecationMap[symbolPath] = opt_deprecationMessage;
+ }
+}
+
+// Note: Android 2.3 does have Function.bind().
+exports.clobbers = function(moduleName, symbolPath, opt_deprecationMessage) {
+ addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.merges = function(moduleName, symbolPath, opt_deprecationMessage) {
+ addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.defaults = function(moduleName, symbolPath, opt_deprecationMessage) {
+ addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.runs = function(moduleName) {
+ addEntry('r', moduleName, null);
+};
+
+function prepareNamespace(symbolPath, context) {
+ if (!symbolPath) {
+ return context;
+ }
+ var parts = symbolPath.split('.');
+ var cur = context;
+ for (var i = 0, part; part = parts[i]; ++i) {
+ cur = cur[part] = cur[part] || {};
+ }
+ return cur;
+}
+
+exports.mapModules = function(context) {
+ var origSymbols = {};
+ context.CDV_origSymbols = origSymbols;
+ for (var i = 0, len = symbolList.length; i < len; i += 3) {
+ var strategy = symbolList[i];
+ var moduleName = symbolList[i + 1];
+ var module = require(moduleName);
+ // <runs/>
+ if (strategy == 'r') {
+ continue;
+ }
+ var symbolPath = symbolList[i + 2];
+ var lastDot = symbolPath.lastIndexOf('.');
+ var namespace = symbolPath.substr(0, lastDot);
+ var lastName = symbolPath.substr(lastDot + 1);
+
+ var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
+ var parentObj = prepareNamespace(namespace, context);
+ var target = parentObj[lastName];
+
+ if (strategy == 'm' && target) {
+ builder.recursiveMerge(target, module);
+ } else if ((strategy == 'd' && !target) || (strategy != 'd')) {
+ if (!(symbolPath in origSymbols)) {
+ origSymbols[symbolPath] = target;
+ }
+ builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
+ }
+ }
+};
+
+exports.getOriginalSymbol = function(context, symbolPath) {
+ var origSymbols = context.CDV_origSymbols;
+ if (origSymbols && (symbolPath in origSymbols)) {
+ return origSymbols[symbolPath];
+ }
+ var parts = symbolPath.split('.');
+ var obj = context;
+ for (var i = 0; i < parts.length; ++i) {
+ obj = obj && obj[parts[i]];
+ }
+ return obj;
+};
+
+exports.reset();
+
+
+});
+
+// file: src/ios/platform.js
+define("cordova/platform", function(require, exports, module) {
+
+module.exports = {
+ id: 'ios',
+ bootstrap: function() {
+ require('cordova/channel').onNativeReady.fire();
+ }
+};
+
+
+});
+
+// file: src/common/pluginloader.js
+define("cordova/pluginloader", function(require, exports, module) {
+
+var modulemapper = require('cordova/modulemapper');
+var urlutil = require('cordova/urlutil');
+
+// Helper function to inject a <script> tag.
+// Exported for testing.
+exports.injectScript = function(url, onload, onerror) {
+ var script = document.createElement("script");
+ // onload fires even when script fails loads with an error.
+ script.onload = onload;
+ // onerror fires for malformed URLs.
+ script.onerror = onerror;
+ script.src = url;
+ document.head.appendChild(script);
+};
+
+function injectIfNecessary(id, url, onload, onerror) {
+ onerror = onerror || onload;
+ if (id in define.moduleMap) {
+ onload();
+ } else {
+ exports.injectScript(url, function() {
+ if (id in define.moduleMap) {
+ onload();
+ } else {
+ onerror();
+ }
+ }, onerror);
+ }
+}
+
+function onScriptLoadingComplete(moduleList, finishPluginLoading) {
+ // Loop through all the plugins and then through their clobbers and merges.
+ for (var i = 0, module; module = moduleList[i]; i++) {
+ if (module.clobbers && module.clobbers.length) {
+ for (var j = 0; j < module.clobbers.length; j++) {
+ modulemapper.clobbers(module.id, module.clobbers[j]);
+ }
+ }
+
+ if (module.merges && module.merges.length) {
+ for (var k = 0; k < module.merges.length; k++) {
+ modulemapper.merges(module.id, module.merges[k]);
+ }
+ }
+
+ // Finally, if runs is truthy we want to simply require() the module.
+ if (module.runs) {
+ modulemapper.runs(module.id);
+ }
+ }
+
+ finishPluginLoading();
+}
+
+// Handler for the cordova_plugins.js content.
+// See plugman's plugin_loader.js for the details of this object.
+// This function is only called if the really is a plugins array that isn't empty.
+// Otherwise the onerror response handler will just call finishPluginLoading().
+function handlePluginsObject(path, moduleList, finishPluginLoading) {
+ // Now inject the scripts.
+ var scriptCounter = moduleList.length;
+
+ if (!scriptCounter) {
+ finishPluginLoading();
+ return;
+ }
+ function scriptLoadedCallback() {
+ if (!--scriptCounter) {
+ onScriptLoadingComplete(moduleList, finishPluginLoading);
+ }
+ }
+
+ for (var i = 0; i < moduleList.length; i++) {
+ injectIfNecessary(moduleList[i].id, path + moduleList[i].file, scriptLoadedCallback);
+ }
+}
+
+function findCordovaPath() {
+ var path = null;
+ var scripts = document.getElementsByTagName('script');
+ var term = '/cordova.js';
+ for (var n = scripts.length-1; n>-1; n--) {
+ var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
+ if (src.indexOf(term) == (src.length - term.length)) {
+ path = src.substring(0, src.length - term.length) + '/';
+ break;
+ }
+ }
+ return path;
+}
+
+// Tries to load all plugins' js-modules.
+// This is an async process, but onDeviceReady is blocked on onPluginsReady.
+// onPluginsReady is fired when there are no plugins to load, or they are all done.
+exports.load = function(callback) {
+ var pathPrefix = findCordovaPath();
+ if (pathPrefix === null) {
+ console.log('Could not find cordova.js script tag. Plugin loading may fail.');
+ pathPrefix = '';
+ }
+ injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function() {
+ var moduleList = require("cordova/plugin_list");
+ handlePluginsObject(pathPrefix, moduleList, callback);
+ }, callback);
+};
+
+
+});
+
+// file: src/common/urlutil.js
+define("cordova/urlutil", function(require, exports, module) {
+
+
+/**
+ * For already absolute URLs, returns what is passed in.
+ * For relative URLs, converts them to absolute ones.
+ */
+exports.makeAbsolute = function makeAbsolute(url) {
+ var anchorEl = document.createElement('a');
+ anchorEl.href = url;
+ return anchorEl.href;
+};
+
+
+});
+
+// file: src/common/utils.js
+define("cordova/utils", function(require, exports, module) {
+
+var utils = exports;
+
+/**
+ * Defines a property getter / setter for obj[key].
+ */
+utils.defineGetterSetter = function(obj, key, getFunc, opt_setFunc) {
+ if (Object.defineProperty) {
+ var desc = {
+ get: getFunc,
+ configurable: true
+ };
+ if (opt_setFunc) {
+ desc.set = opt_setFunc;
+ }
+ Object.defineProperty(obj, key, desc);
+ } else {
+ obj.__defineGetter__(key, getFunc);
+ if (opt_setFunc) {
+ obj.__defineSetter__(key, opt_setFunc);
+ }
+ }
+};
+
+/**
+ * Defines a property getter for obj[key].
+ */
+utils.defineGetter = utils.defineGetterSetter;
+
+utils.arrayIndexOf = function(a, item) {
+ if (a.indexOf) {
+ return a.indexOf(item);
+ }
+ var len = a.length;
+ for (var i = 0; i < len; ++i) {
+ if (a[i] == item) {
+ return i;
+ }
+ }
+ return -1;
+};
+
+/**
+ * Returns whether the item was found in the array.
+ */
+utils.arrayRemove = function(a, item) {
+ var index = utils.arrayIndexOf(a, item);
+ if (index != -1) {
+ a.splice(index, 1);
+ }
+ return index != -1;
+};
+
+utils.typeName = function(val) {
+ return Object.prototype.toString.call(val).slice(8, -1);
+};
+
+/**
+ * Returns an indication of whether the argument is an array or not
+ */
+utils.isArray = function(a) {
+ return utils.typeName(a) == 'Array';
+};
+
+/**
+ * Returns an indication of whether the argument is a Date or not
+ */
+utils.isDate = function(d) {
+ return utils.typeName(d) == 'Date';
+};
+
+/**
+ * Does a deep clone of the object.
+ */
+utils.clone = function(obj) {
+ if(!obj || typeof obj == 'function' || utils.isDate(obj) || typeof obj != 'object') {
+ return obj;
+ }
+
+ var retVal, i;
+
+ if(utils.isArray(obj)){
+ retVal = [];
+ for(i = 0; i < obj.length; ++i){
+ retVal.push(utils.clone(obj[i]));
+ }
+ return retVal;
+ }
+
+ retVal = {};
+ for(i in obj){
+ if(!(i in retVal) || retVal[i] != obj[i]) {
+ retVal[i] = utils.clone(obj[i]);
+ }
+ }
+ return retVal;
+};
+
+/**
+ * Returns a wrapped version of the function
+ */
+utils.close = function(context, func, params) {
+ if (typeof params == 'undefined') {
+ return function() {
+ return func.apply(context, arguments);
+ };
+ } else {
+ return function() {
+ return func.apply(context, params);
+ };
+ }
+};
+
+/**
+ * Create a UUID
+ */
+utils.createUUID = function() {
+ return UUIDcreatePart(4) + '-' +
+ UUIDcreatePart(2) + '-' +
+ UUIDcreatePart(2) + '-' +
+ UUIDcreatePart(2) + '-' +
+ UUIDcreatePart(6);
+};
+
+/**
+ * Extends a child object from a parent object using classical inheritance
+ * pattern.
+ */
+utils.extend = (function() {
+ // proxy used to establish prototype chain
+ var F = function() {};
+ // extend Child from Parent
+ return function(Child, Parent) {
+ F.prototype = Parent.prototype;
+ Child.prototype = new F();
+ Child.__super__ = Parent.prototype;
+ Child.prototype.constructor = Child;
+ };
+}());
+
+/**
+ * Alerts a message in any available way: alert or console.log.
+ */
+utils.alert = function(msg) {
+ if (window.alert) {
+ window.alert(msg);
+ } else if (console && console.log) {
+ console.log(msg);
+ }
+};
+
+
+//------------------------------------------------------------------------------
+function UUIDcreatePart(length) {
+ var uuidpart = "";
+ for (var i=0; i<length; i++) {
+ var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
+ if (uuidchar.length == 1) {
+ uuidchar = "0" + uuidchar;
+ }
+ uuidpart += uuidchar;
+ }
+ return uuidpart;
+}
+
+
+});
+
+window.cordova = require('cordova');
+// file: src/scripts/bootstrap.js
+
+require('cordova/init');
+
+})(); \ No newline at end of file