You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by fi...@apache.org on 2013/03/25 22:53:27 UTC

[4/6] 2.6.0rc1 used for libs now. Bumped npm version to 2.6.0. added androids local.properties to gitignore.

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/util/FileUtils.java
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/util/FileUtils.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/util/FileUtils.java
index 2655ef6..20ef492 100644
--- a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/util/FileUtils.java
+++ b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/util/FileUtils.java
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Enumeration;
+import java.util.Random;
 
 import javax.microedition.io.Connector;
 import javax.microedition.io.file.FileConnection;
@@ -35,6 +36,7 @@ import net.rim.device.api.io.FileNotFoundException;
 import net.rim.device.api.io.IOUtilities;
 import net.rim.device.api.io.MIMETypeAssociations;
 import net.rim.device.api.system.Application;
+import net.rim.device.api.system.ControlledAccessException;
 
 /**
  * Contains file utility methods.
@@ -45,7 +47,13 @@ public class FileUtils {
     public static final String LOCAL_PROTOCOL = "local://";
     public static final String FILE_PROTOCOL = "file://";
 
-    private static final String APP_TMP_DIR    = "tmp" + CordovaExtension.getAppID();
+    private static final String APP_TMP_DIR;
+    
+    // init APP_TMP_DIR with a random value
+    static {
+        Random gen = new Random();
+        APP_TMP_DIR = "tmp" + Math.abs(gen.nextInt());
+    }
 
     /**
      * Reads file as byte array.
@@ -226,6 +234,9 @@ public class FileUtils {
                 return;
             }
             fconn.mkdir();
+        } catch (ControlledAccessException e) {
+            Logger.log("ControlledAccessException on dir " + dirPath + ", either directory conflict after reinstall of app, or device is connected via usb, see Cordova Docs File Blackberry Quirks");
+            Logger.log(e.toString());
         }
         finally {
             try {
@@ -237,6 +248,26 @@ public class FileUtils {
     }
 
     /**
+     * Determines the size of a file on the file system. Size always represents number of bytes contained in the file; never pre-allocated but empty space
+     * @return size in bytes of the selected file, or -1 if the file does not exist or is inaccessible
+     */
+    public static long fileSize(String path) throws IOException {
+        FileConnection fconn = null;
+        long fsize = -1;
+        try {
+            fconn = (FileConnection)Connector.open(path);
+            fsize = fconn.fileSize();
+        } catch (IOException e) {
+            Logger.log(FileUtils.class.getName() + " fileSize:  " + path + "not found or inaccessible");
+        } finally {
+            try {
+                if (fconn != null) fconn.close();
+            } catch (IOException ignored) {}
+        }
+       return fsize;
+    }
+
+    /**
      * Copies a file or directory to a new location. If copying a directory, the
      * entire contents of the directory are copied recursively.
      *

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-blackberry/javascript/cordova.blackberry.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/javascript/cordova.blackberry.js b/lib/cordova-blackberry/javascript/cordova.blackberry.js
index 988dd43..fbe61f5 100644
--- a/lib/cordova-blackberry/javascript/cordova.blackberry.js
+++ b/lib/cordova-blackberry/javascript/cordova.blackberry.js
@@ -1,8 +1,8 @@
 // Platform: blackberry
 
-// commit c5437f050947a65045222c6ac9fa70cf71ba334e
+// commit bbf1562d4934b1331ffb263424b6ae054cedeb71
 
-// File generated at :: Wed Feb 27 2013 13:16:46 GMT-0800 (PST)
+// File generated at :: Fri Mar 22 2013 14:49:45 GMT-0700 (PDT)
 
 /*
  Licensed to the Apache Software Foundation (ASF) under one
@@ -725,7 +725,6 @@ channel.createSticky('onCordovaInfoReady');
 channel.createSticky('onCordovaConnectionReady');
 
 // Event to indicate that all automatically loaded JS plugins are loaded and ready.
-// This is used in conjunction with the automatic plugin JS loading CLI prototype.
 channel.createSticky('onPluginsReady');
 
 // Event to indicate that Cordova is ready
@@ -1033,9 +1032,10 @@ cameraExport.getPicture = function(successCallback, errorCallback, options) {
     var correctOrientation = !!options.correctOrientation;
     var saveToPhotoAlbum = !!options.saveToPhotoAlbum;
     var popoverOptions = getValue(options.popoverOptions, null);
+    var cameraDirection = getValue(options.cameraDirection, Camera.Direction.BACK);
 
     var args = [quality, destinationType, sourceType, targetWidth, targetHeight, encodingType,
-                mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions];
+                mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions, cameraDirection];
 
     exec(successCallback, errorCallback, "Camera", "takePicture", args);
     return new CameraPopoverHandle();
@@ -1078,6 +1078,10 @@ module.exports = {
       ARROW_LEFT : 4,
       ARROW_RIGHT : 8,
       ARROW_ANY : 15
+  },
+  Direction:{
+      BACK: 0,
+      FRONT: 1
   }
 };
 
@@ -2269,14 +2273,7 @@ FileReader.prototype.readAsText = function(file, encoding) {
     // Default encoding is UTF-8
     var enc = encoding ? encoding : "UTF-8";
     var me = this;
-    var execArgs = [this._fileName, enc];
-
-    // Maybe add slice parameters.
-    if (file.end < file.size) {
-        execArgs.push(file.start, file.end);
-    } else if (file.start > 0) {
-        execArgs.push(file.start);
-    }
+    var execArgs = [this._fileName, enc, file.start, file.end];
 
     // Read file
     exec(
@@ -2345,14 +2342,7 @@ FileReader.prototype.readAsDataURL = function(file) {
     }
 
     var me = this;
-    var execArgs = [this._fileName];
-
-    // Maybe add slice parameters.
-    if (file.end < file.size) {
-        execArgs.push(file.start, file.end);
-    } else if (file.start > 0) {
-        execArgs.push(file.start);
-    }
+    var execArgs = [this._fileName, file.start, file.end];
 
     // Read file
     exec(
@@ -2415,9 +2405,59 @@ FileReader.prototype.readAsBinaryString = function(file) {
     if (initRead(this, file)) {
         return this._realReader.readAsBinaryString(file);
     }
-    // TODO - Can't return binary data to browser.
-    console.log('method "readAsBinaryString" is not supported at this time.');
-    this.abort();
+
+    var me = this;
+    var execArgs = [this._fileName, file.start, file.end];
+
+    // Read file
+    exec(
+        // Success callback
+        function(r) {
+            // If DONE (cancelled), then don't do anything
+            if (me._readyState === FileReader.DONE) {
+                return;
+            }
+
+            // DONE state
+            me._readyState = FileReader.DONE;
+
+            me._result = r;
+
+            // If onload callback
+            if (typeof me.onload === "function") {
+                me.onload(new ProgressEvent("load", {target:me}));
+            }
+
+            // If onloadend callback
+            if (typeof me.onloadend === "function") {
+                me.onloadend(new ProgressEvent("loadend", {target:me}));
+            }
+        },
+        // Error callback
+        function(e) {
+            // If DONE (cancelled), then don't do anything
+            if (me._readyState === FileReader.DONE) {
+                return;
+            }
+
+            // DONE state
+            me._readyState = FileReader.DONE;
+
+            me._result = null;
+
+            // Save error
+            me._error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === "function") {
+                me.onerror(new ProgressEvent("error", {target:me}));
+            }
+
+            // If onloadend callback
+            if (typeof me.onloadend === "function") {
+                me.onloadend(new ProgressEvent("loadend", {target:me}));
+            }
+        }, "File", "readAsBinaryString", execArgs);
 };
 
 /**
@@ -2429,9 +2469,59 @@ FileReader.prototype.readAsArrayBuffer = function(file) {
     if (initRead(this, file)) {
         return this._realReader.readAsArrayBuffer(file);
     }
-    // TODO - Can't return binary data to browser.
-    console.log('This method is not supported at this time.');
-    this.abort();
+
+    var me = this;
+    var execArgs = [this._fileName, file.start, file.end];
+
+    // Read file
+    exec(
+        // Success callback
+        function(r) {
+            // If DONE (cancelled), then don't do anything
+            if (me._readyState === FileReader.DONE) {
+                return;
+            }
+
+            // DONE state
+            me._readyState = FileReader.DONE;
+
+            me._result = r;
+
+            // If onload callback
+            if (typeof me.onload === "function") {
+                me.onload(new ProgressEvent("load", {target:me}));
+            }
+
+            // If onloadend callback
+            if (typeof me.onloadend === "function") {
+                me.onloadend(new ProgressEvent("loadend", {target:me}));
+            }
+        },
+        // Error callback
+        function(e) {
+            // If DONE (cancelled), then don't do anything
+            if (me._readyState === FileReader.DONE) {
+                return;
+            }
+
+            // DONE state
+            me._readyState = FileReader.DONE;
+
+            me._result = null;
+
+            // Save error
+            me._error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === "function") {
+                me.onerror(new ProgressEvent("error", {target:me}));
+            }
+
+            // If onloadend callback
+            if (typeof me.onloadend === "function") {
+                me.onloadend(new ProgressEvent("loadend", {target:me}));
+            }
+        }, "File", "readAsArrayBuffer", execArgs);
 };
 
 module.exports = FileReader;
@@ -2477,6 +2567,38 @@ function newProgressEvent(result) {
     return pe;
 }
 
+function getBasicAuthHeader(urlString) {
+    var header =  null;
+
+    if (window.btoa) {
+        // parse the url using the Location object
+        var url = document.createElement('a');
+        url.href = urlString;
+
+        var credentials = null;
+        var protocol = url.protocol + "//";
+        var origin = protocol + url.host;
+
+        // check whether there are the username:password credentials in the url
+        if (url.href.indexOf(origin) != 0) { // credentials found
+            var atIndex = url.href.indexOf("@");
+            credentials = url.href.substring(protocol.length, atIndex);
+        }
+
+        if (credentials) {
+            var authHeader = "Authorization";
+            var authHeaderValue = "Basic " + window.btoa(credentials);
+
+            header = {
+                name : authHeader,
+                value : authHeaderValue
+            };
+        }
+    }
+
+    return header;
+}
+
 var idCounter = 0;
 
 /**
@@ -2507,6 +2629,18 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro
     var params = null;
     var chunkedMode = true;
     var headers = null;
+
+    var basicAuthHeader = getBasicAuthHeader(server);
+    if (basicAuthHeader) {
+        if (!options) {
+            options = new FileUploadOptions();
+        }
+        if (!options.headers) {
+            options.headers = {};
+        }
+        options.headers[basicAuthHeader.name] = basicAuthHeader.value;
+    }
+
     if (options) {
         fileKey = options.fileKey;
         fileName = options.fileName;
@@ -2548,10 +2682,28 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro
  * @param successCallback (Function}  Callback to be invoked when upload has completed
  * @param errorCallback {Function}    Callback to be invoked upon error
  * @param trustAllHosts {Boolean} Optional trust all hosts (e.g. for self-signed certs), defaults to false
+ * @param options {FileDownloadOptions} Optional parameters such as headers
  */
-FileTransfer.prototype.download = function(source, target, successCallback, errorCallback, trustAllHosts) {
+FileTransfer.prototype.download = function(source, target, successCallback, errorCallback, trustAllHosts, options) {
     argscheck.checkArgs('ssFF*', 'FileTransfer.download', arguments);
     var self = this;
+
+    var basicAuthHeader = getBasicAuthHeader(source);
+    if (basicAuthHeader) {
+        if (!options) {
+            options = {};
+        }
+        if (!options.headers) {
+            options.headers = {};
+        }
+        options.headers[basicAuthHeader.name] = basicAuthHeader.value;
+    }
+
+    var headers = null;
+    if (options) {
+        headers = options.headers || null;
+    }
+
     var win = function(result) {
         if (typeof result.lengthComputable != "undefined") {
             if (self.onprogress) {
@@ -2578,7 +2730,7 @@ FileTransfer.prototype.download = function(source, target, successCallback, erro
         errorCallback(error);
     };
 
-    exec(win, fail, 'FileTransfer', 'download', [source, target, trustAllHosts, this._id]);
+    exec(win, fail, 'FileTransfer', 'download', [source, target, trustAllHosts, this._id, headers]);
 };
 
 /**
@@ -2976,6 +3128,7 @@ function InAppBrowser() {
    this.channels = {
         'loadstart': channel.create('loadstart'),
         'loadstop' : channel.create('loadstop'),
+        'loaderror' : channel.create('loaderror'),
         'exit' : channel.create('exit')
    };
 }
@@ -3006,7 +3159,7 @@ module.exports = function(strUrl, strWindowName, strWindowFeatures) {
     var cb = function(eventname) {
        iab._eventHandler(eventname);
     };
-    exec(cb, null, "InAppBrowser", "open", [strUrl, strWindowName, strWindowFeatures]);
+    exec(cb, cb, "InAppBrowser", "open", [strUrl, strWindowName, strWindowFeatures]);
     return iab;
 };
 
@@ -8682,6 +8835,7 @@ modulemapper.defaults('cordova/plugin/Connection', 'Connection');
 define("cordova/plugin/notification", function(require, exports, module) {
 
 var exec = require('cordova/exec');
+var platform = require('cordova/platform');
 
 /**
  * Provides access to notifications on the device.
@@ -8710,15 +8864,53 @@ module.exports = {
      * @param {String} message              Message to print in the body of the alert
      * @param {Function} resultCallback     The callback that is called when user clicks on a button.
      * @param {String} title                Title of the alert dialog (default: Confirm)
-     * @param {String} buttonLabels         Comma separated list of the labels of the buttons (default: 'OK,Cancel')
+     * @param {Array} buttonLabels          Array of the labels of the buttons (default: ['OK', 'Cancel'])
      */
     confirm: function(message, resultCallback, title, buttonLabels) {
         var _title = (title || "Confirm");
-        var _buttonLabels = (buttonLabels || "OK,Cancel");
+        var _buttonLabels = (buttonLabels || ["OK", "Cancel"]);
+
+        // Strings are deprecated!
+        if (typeof _buttonLabels === 'string') {
+            console.log("Notification.confirm(string, function, string, string) is deprecated.  Use Notification.confirm(string, function, string, array).");
+        }
+
+        // Android and iOS take an array of button label names.
+        // Other platforms take a comma separated list.
+        // For compatibility, we convert to the desired type based on the platform.
+        if (platform.id == "android" || platform.id == "ios") {
+            if (typeof _buttonLabels === 'string') {
+                var buttonLabelString = _buttonLabels;
+                _buttonLabels = buttonLabelString.split(",");
+            }
+        } else {
+            if (Array.isArray(_buttonLabels)) {
+                var buttonLabelArray = _buttonLabels;
+                _buttonLabels = buttonLabelArray.toString();
+            }
+        }
         exec(resultCallback, null, "Notification", "confirm", [message, _title, _buttonLabels]);
     },
 
     /**
+     * Open a native prompt dialog, with a customizable title and button text.
+     * The following results are returned to the result callback:
+     *  buttonIndex     Index number of the button selected.
+     *  input1          The text entered in the prompt dialog box.
+     *
+     * @param {String} message              Dialog message to display (default: "Prompt message")
+     * @param {Function} resultCallback     The callback that is called when user clicks on a button.
+     * @param {String} title                Title of the dialog (default: "Prompt")
+     * @param {Array} buttonLabels          Array of strings for the button labels (default: ["OK","Cancel"])
+     */
+    prompt: function(message, resultCallback, title, buttonLabels) {
+        var _message = (message || "Prompt message");
+        var _title = (title || "Prompt");
+        var _buttonLabels = (buttonLabels || ["OK","Cancel"]);
+        exec(resultCallback, null, "Notification", "prompt", [_message, _title, _buttonLabels]);
+    },
+
+    /**
      * Causes the device to vibrate.
      *
      * @param {Integer} mills       The number of milliseconds to vibrate for.
@@ -10506,15 +10698,6 @@ window.cordova = require('cordova');
     /**
      * Create all cordova objects once page has fully loaded and native side is ready.
      */
-    var joinEvents = [ channel.onDOMContentLoaded, channel.onNativeReady ];
-
-    // If this property is set to something truthy, join on onPluginsReady too.
-    // This property is set by the automatic JS installation prototype in cordova-cli,
-    // and will be removed when the prototype either becomes mainline or is dropped.
-    if (window.__onPluginsLoadedHack) {
-        joinEvents.push(channel.onPluginsReady);
-    }
-
     channel.join(function() {
         var builder = require('cordova/builder'),
             platform = require('cordova/platform');
@@ -10535,7 +10718,7 @@ window.cordova = require('cordova');
             require('cordova').fireDocumentEvent('deviceready');
         }, channel.deviceReadyChannelsArray);
 
-    }, joinEvents);
+    }, [ channel.onDOMContentLoaded, channel.onNativeReady, channel.onPluginsReady ]);
 
 }(window));
 
@@ -10565,5 +10748,105 @@ document.addEventListener("DOMContentLoaded", function () {
     }
 });
 
+// file: lib/scripts/plugin_loader.js
+
+// 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.
+(function (context) {
+    // To be populated with the handler by handlePluginsObject.
+    var onScriptLoadingComplete;
+
+    var scriptCounter = 0;
+    function scriptLoadedCallback() {
+        scriptCounter--;
+        if (scriptCounter === 0) {
+            onScriptLoadingComplete && onScriptLoadingComplete();
+        }
+    }
+
+    // Helper function to inject a <script> tag.
+    function injectScript(path) {
+        scriptCounter++;
+        var script = document.createElement("script");
+        script.onload = scriptLoadedCallback;
+        script.src = path;
+        document.head.appendChild(script);
+    }
+
+    // Called when:
+    // * There are plugins defined and all plugins are finished loading.
+    // * There are no plugins to load.
+    function finishPluginLoading() {
+        context.cordova.require('cordova/channel').onPluginsReady.fire();
+    }
+
+    // Handler for the cordova_plugins.json 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 XHR response handler will just call finishPluginLoading().
+    function handlePluginsObject(modules) {
+        // First create the callback for when all plugins are loaded.
+        var mapper = context.cordova.require('cordova/modulemapper');
+        onScriptLoadingComplete = function() {
+            // Loop through all the plugins and then through their clobbers and merges.
+            for (var i = 0; i < modules.length; i++) {
+                var module = modules[i];
+                if (!module) continue;
+
+                if (module.clobbers && module.clobbers.length) {
+                    for (var j = 0; j < module.clobbers.length; j++) {
+                        mapper.clobbers(module.id, module.clobbers[j]);
+                    }
+                }
+
+                if (module.merges && module.merges.length) {
+                    for (var k = 0; k < module.merges.length; k++) {
+                        mapper.merges(module.id, module.merges[k]);
+                    }
+                }
+
+                // Finally, if runs is truthy we want to simply require() the module.
+                // This can be skipped if it had any merges or clobbers, though,
+                // since the mapper will already have required the module.
+                if (module.runs && !(module.clobbers && module.clobbers.length) && !(module.merges && module.merges.length)) {
+                    context.cordova.require(module.id);
+                }
+            }
+
+            finishPluginLoading();
+        };
+
+        // Now inject the scripts.
+        for (var i = 0; i < modules.length; i++) {
+            injectScript(modules[i].file);
+        }
+    }
+
+    // Try to XHR the cordova_plugins.json file asynchronously.
+    var xhr = new context.XMLHttpRequest();
+    xhr.onreadystatechange = function() {
+        if (this.readyState != 4) { // not DONE
+            return;
+        }
+
+        // If the response is a JSON string which composes an array, call handlePluginsObject.
+        // If the request fails, or the response is not a JSON array, just call finishPluginLoading.
+        if (this.status == 200) {
+            var obj = JSON.parse(this.responseText);
+            if (obj && obj instanceof Array && obj.length > 0) {
+                handlePluginsObject(obj);
+            } else {
+                finishPluginLoading();
+            }
+        } else {
+            finishPluginLoading();
+        }
+    };
+    xhr.open('GET', 'cordova_plugins.json', true); // Async
+    xhr.send();
+}(window));
+
+
 
 })();
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVAvailability.h
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVAvailability.h b/lib/cordova-ios/CordovaLib/Classes/CDVAvailability.h
index 33c6799..947ae2d 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVAvailability.h
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVAvailability.h
@@ -17,6 +17,8 @@
  under the License.
  */
 
+#define __CORDOVA_IOS__
+
 #define __CORDOVA_0_9_6 906
 #define __CORDOVA_1_0_0 10000
 #define __CORDOVA_1_1_0 10100
@@ -37,6 +39,7 @@
 #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_NA 99999      /* not available */
 
 /*
@@ -47,7 +50,7 @@
  #endif
  */
 #ifndef CORDOVA_VERSION_MIN_REQUIRED
-    #define CORDOVA_VERSION_MIN_REQUIRED __CORDOVA_2_5_0
+    #define CORDOVA_VERSION_MIN_REQUIRED __CORDOVA_2_6_0
 #endif
 
 /*
@@ -65,12 +68,20 @@
 
 /* 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]
+    (CORDOVA_VERSION_MIN_REQUIRED / 10000),                 \
+    (CORDOVA_VERSION_MIN_REQUIRED % 10000) / 100,           \
+    (CORDOVA_VERSION_MIN_REQUIRED % 10000) % 100]
 
 #ifdef __clang__
     #define CDV_DEPRECATED(version, msg) __attribute__((deprecated("Deprecated in Cordova " #version ". " msg)))
 #else
     #define CDV_DEPRECATED(version, msg) __attribute__((deprecated()))
 #endif
+
+// 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

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVCamera.h
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVCamera.h b/lib/cordova-ios/CordovaLib/Classes/CDVCamera.h
index 204d25f..65eac77 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVCamera.h
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVCamera.h
@@ -61,8 +61,8 @@ typedef NSUInteger CDVMediaType;
 // ======================================================================= //
 
 @interface CDVCamera : CDVPlugin <UIImagePickerControllerDelegate,
-    UINavigationControllerDelegate,
-    UIPopoverControllerDelegate>
+                       UINavigationControllerDelegate,
+                       UIPopoverControllerDelegate>
 {}
 
 @property (strong) CDVCameraPicker* pickerController;

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVCamera.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVCamera.m b/lib/cordova-ios/CordovaLib/Classes/CDVCamera.m
index aabe844..ab1154e 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVCamera.m
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVCamera.m
@@ -18,6 +18,7 @@
  */
 
 #import "CDVCamera.h"
+#import "CDVJpegHeaderWriter.h"
 #import "NSArray+Comparisons.h"
 #import "NSData+Base64.h"
 #import "NSDictionary+Extensions.h"
@@ -60,6 +61,8 @@ static NSSet* org_apache_cordova_validArrowDirections;
  *  7       allowsEdit
  *  8       correctOrientation
  *  9       saveToPhotoAlbum
+ *  10      popoverOptions
+ *  11      cameraDirection
  */
 - (void)takePicture:(CDVInvokedUrlCommand*)command
 {
@@ -82,6 +85,12 @@ static NSSet* org_apache_cordova_validArrowDirections;
         return;
     }
 
+    NSNumber* cameraDirection = [arguments objectAtIndex:11];
+    UIImagePickerControllerCameraDevice cameraDevice = UIImagePickerControllerCameraDeviceRear; // default
+    if (cameraDirection != nil) {
+        cameraDevice = (UIImagePickerControllerSourceType)[cameraDirection intValue];
+    }
+
     bool allowEdit = [[arguments objectAtIndex:7] boolValue];
     NSNumber* targetWidth = [arguments objectAtIndex:3];
     NSNumber* targetHeight = [arguments objectAtIndex:4];
@@ -105,6 +114,7 @@ static NSSet* org_apache_cordova_validArrowDirections;
 
     cameraPicker.delegate = self;
     cameraPicker.sourceType = sourceType;
+    cameraPicker.cameraDevice = cameraDevice;
     cameraPicker.allowsEditing = allowEdit; // THIS IS ALL IT TAKES FOR CROPPING - jm
     cameraPicker.callbackId = callbackId;
     cameraPicker.targetSize = targetSize;
@@ -289,6 +299,49 @@ static NSSet* org_apache_cordova_validArrowDirections;
                 data = UIImagePNGRepresentation(scaledImage == nil ? image : scaledImage);
             } else {
                 data = UIImageJPEGRepresentation(scaledImage == nil ? image : scaledImage, cameraPicker.quality / 100.0f);
+                
+                CDVJpegHeaderWriter * exifWriter = [[CDVJpegHeaderWriter alloc] init];
+                
+                NSString * headerstring = [exifWriter createExifAPP1: [info objectForKey:@"UIImagePickerControllerMediaMetadata"]];
+                NSMutableData * exifdata = [NSMutableData dataWithCapacity: [headerstring length]/2];
+                int idx;
+                for (idx = 0; idx+1 < [headerstring length]; idx+=2) {
+                    NSRange range = NSMakeRange(idx, 2);
+                    NSString* hexStr = [headerstring substringWithRange:range];
+                    NSScanner* scanner = [NSScanner scannerWithString:hexStr];
+                    unsigned int intValue;
+                    [scanner scanHexInt:&intValue];
+                    [exifdata appendBytes:&intValue length:1];
+                }
+               
+                NSMutableData * ddata = [NSMutableData dataWithCapacity: [data length]];
+                NSMakeRange(0,4);
+                int loc = 0;
+                bool done = false;
+                // read the jpeg data until we encounter the app1==0xFFE1 marker
+                while (loc+1 < [data length]) {
+                    NSData * blag = [data subdataWithRange: NSMakeRange(loc,2)];
+                    if( [[blag description] isEqualToString : @"<ffe1>"]) {
+                        // read the APP1 block size bits
+                        NSString * the = [exifWriter hexStringFromData:[data subdataWithRange: NSMakeRange(loc+2,2)]];
+                        NSNumber * app1width = [exifWriter numericFromHexString:the];
+                        //consume the original app1 block
+                        [ddata appendData:exifdata];
+                        // advance our loc marker past app1
+                        loc += [app1width intValue] + 2;
+                        done = true;
+                    } else {
+                        if(!done) {
+                            [ddata appendData:blag];
+                            loc += 2;
+                        } else {
+                            break;
+                        }
+                    }
+                }
+                // copy the remaining data
+                [ddata appendData:[data subdataWithRange: NSMakeRange(loc,[data length]-loc)]];
+                data = ddata;
             }
 
             if (cameraPicker.returnType == DestinationTypeFileUri) {

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVCapture.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVCapture.m b/lib/cordova-ios/CordovaLib/Classes/CDVCapture.m
index ed9f664..d89e3d3 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVCapture.m
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVCapture.m
@@ -169,7 +169,7 @@
     }
 
     // write to temp directory and return URI
-    NSString* docsPath = [NSTemporaryDirectory ()stringByStandardizingPath];  // use file system temporary directory
+    NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];   // use file system temporary directory
     NSError* err = nil;
     NSFileManager* fileMgr = [[NSFileManager alloc] init];
 
@@ -439,7 +439,7 @@
         if ([command isKindOfClass:[CDVFile class]]) {
             CDVFile* cdvFile = (CDVFile*)command;
             NSString* mimeType = [cdvFile getMimeTypeFromPath:fullPath];
-            [fileDict setObject:(mimeType != nil ? (NSObject*)mimeType:[NSNull null]) forKey:@"type"];
+            [fileDict setObject:(mimeType != nil ? (NSObject*)mimeType : [NSNull null]) forKey:@"type"];
         }
     }
     NSDictionary* fileAttrs = [fileMgr attributesOfItemAtPath:fullPath error:nil];
@@ -533,7 +533,6 @@
         // delegate to CVDAudioRecorderViewController
         return [self.topViewController supportedInterfaceOrientations];
     }
-
 #endif
 
 @end
@@ -663,7 +662,7 @@
 
     // create file to record to in temporary dir
 
-    NSString* docsPath = [NSTemporaryDirectory ()stringByStandardizingPath];  // use file system temporary directory
+    NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];   // use file system temporary directory
     NSError* err = nil;
     NSFileManager* fileMgr = [[NSFileManager alloc] init];
 
@@ -701,7 +700,6 @@
         orientation = orientation | (supported & UIInterfaceOrientationMaskPortraitUpsideDown);
         return orientation;
     }
-
 #endif
 
 - (void)viewDidUnload
@@ -766,7 +764,7 @@
         BOOL isUIAccessibilityAnnouncementNotification = (&UIAccessibilityAnnouncementNotification != NULL);
         if (isUIAccessibilityAnnouncementNotification) {
             dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 500ull * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{
-                    UIAccessibilityPostNotification (UIAccessibilityAnnouncementNotification, NSLocalizedString (@"timed recording complete", nil));
+                    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, NSLocalizedString(@"timed recording complete", nil));
                 });
         }
     } else {

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVCommandDelegate.h
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVCommandDelegate.h b/lib/cordova-ios/CordovaLib/Classes/CDVCommandDelegate.h
index e177c63..0401136 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVCommandDelegate.h
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVCommandDelegate.h
@@ -30,7 +30,6 @@
 
 - (NSString*)pathForResource:(NSString*)resourcepath;
 - (id)getCommandInstance:(NSString*)pluginName;
-- (void)registerPlugin:(CDVPlugin*)plugin withClassName:(NSString*)className CDV_DEPRECATED(2.2, "Use CDVViewController to register plugins, or use config.xml.");
 
 // Plugins should not be using this interface to call other plugins since it
 // will result in bogus callbacks being made.

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVCommandDelegateImpl.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVCommandDelegateImpl.m b/lib/cordova-ios/CordovaLib/Classes/CDVCommandDelegateImpl.m
index e399289..fa0e5e0 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVCommandDelegateImpl.m
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVCommandDelegateImpl.m
@@ -55,7 +55,11 @@
 
 - (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 enqueCommandBatch:commandsJSON];
 }
@@ -78,21 +82,16 @@
 
 - (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]) {
+    if ([@"INVALID" isEqualToString : callbackId]) {
         return;
     }
     int status = [result.status intValue];
     BOOL keepCallback = [result.keepCallback boolValue];
-    id message = result.message == nil ? [NSNull null] : result.message;
+    NSString* argumentsAsJSON = [result argumentsAsJSON];
 
-    // Use an array to encode the message as JSON.
-    message = [NSArray arrayWithObject:message];
-    NSString* encodedMessage = [message JSONString];
-    // And then strip off the outer []s.
-    encodedMessage = [encodedMessage substringWithRange:NSMakeRange(1, [encodedMessage length] - 2)];
-    NSString* js = [NSString stringWithFormat:@"cordova.require('cordova/exec').nativeCallback('%@',%d,%@,%d)",
-        callbackId, status, encodedMessage, keepCallback];
+    NSString* js = [NSString stringWithFormat:@"cordova.require('cordova/exec').nativeCallback('%@',%d,%@,%d)", callbackId, status, argumentsAsJSON, keepCallback];
 
     [self evalJsHelper:js];
 }
@@ -122,11 +121,6 @@
     return [_viewController getCommandInstance:pluginName];
 }
 
-- (void)registerPlugin:(CDVPlugin*)plugin withClassName:(NSString*)className
-{
-    [_viewController registerPlugin:plugin withClassName:className];
-}
-
 - (void)runInBackground:(void (^)())block
 {
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVCommandQueue.h
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVCommandQueue.h b/lib/cordova-ios/CordovaLib/Classes/CDVCommandQueue.h
index ebdf844..27c47b5 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVCommandQueue.h
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVCommandQueue.h
@@ -22,13 +22,7 @@
 @class CDVInvokedUrlCommand;
 @class CDVViewController;
 
-@interface CDVCommandQueue : NSObject {
-    @private
-    NSInteger _lastCommandQueueFlushRequestId;
-    __weak CDVViewController* _viewController;
-    NSMutableArray* _queue;
-    BOOL _currentlyExecuting;
-}
+@interface CDVCommandQueue : NSObject
 
 @property (nonatomic, readonly) BOOL currentlyExecuting;
 

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVCommandQueue.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVCommandQueue.m b/lib/cordova-ios/CordovaLib/Classes/CDVCommandQueue.m
index a8a58b7..1a0dfa0 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVCommandQueue.m
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVCommandQueue.m
@@ -23,6 +23,14 @@
 #import "CDVViewController.h"
 #import "CDVCommandDelegateImpl.h"
 
+@interface CDVCommandQueue () {
+    NSInteger _lastCommandQueueFlushRequestId;
+    __weak CDVViewController* _viewController;
+    NSMutableArray* _queue;
+    BOOL _currentlyExecuting;
+}
+@end
+
 @implementation CDVCommandQueue
 
 @synthesize currentlyExecuting = _currentlyExecuting;
@@ -74,6 +82,9 @@
         @"cordova.require('cordova/exec').nativeFetchMessages()"];
 
     [self enqueCommandBatch:queuedCommandsJSON];
+    if ([queuedCommandsJSON length] > 0) {
+        CDV_EXEC_LOG(@"Exec: Retrieved new exec messages by request.");
+    }
 }
 
 - (void)executePending
@@ -92,13 +103,15 @@
             // Iterate over and execute all of the commands.
             for (NSArray* jsonEntry in commandBatch) {
                 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 JSONString];
                         static NSUInteger maxLogLength = 1024;
                         NSString* commandString = ([commandJson length] > maxLogLength) ?
-                        [NSString stringWithFormat:@"%@[...]", [commandJson substringToIndex:maxLogLength]] :
-                        commandJson;
+                            [NSString stringWithFormat:@"%@[...]", [commandJson substringToIndex:maxLogLength]] :
+                            commandJson;
 
                         DLog(@"FAILED pluginJSON = %@", commandString);
 #endif

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVConfigParser.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVConfigParser.m b/lib/cordova-ios/CordovaLib/Classes/CDVConfigParser.m
index 6fd5913..ffc8ede 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVConfigParser.m
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVConfigParser.m
@@ -52,7 +52,7 @@
     } else if ([elementName isEqualToString:@"plugin"]) {
         NSString* name = [attributeDict[@"name"] lowercaseString];
         pluginsDict[name] = attributeDict[@"value"];
-        if ([@"true" isEqualToString:attributeDict[@"onload"]]) {
+        if ([@"true" isEqualToString : attributeDict[@"onload"]]) {
             [self.startupPluginNames addObject:name];
         }
     } else if ([elementName isEqualToString:@"access"]) {

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVConnection.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVConnection.m b/lib/cordova-ios/CordovaLib/Classes/CDVConnection.m
index 3030711..b3f5cab 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVConnection.m
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVConnection.m
@@ -52,7 +52,8 @@
             return @"none";
 
         case ReachableViaWWAN:
-            return @"2g"; // no generic default, so we use the lowest common denominator
+            // Return value of '2g' is deprecated as of 2.6.0 and will be replaced with 'cellular' in 3.0.0
+            return @"2g";
 
         case ReachableViaWiFi:
             return @"wifi";
@@ -66,7 +67,8 @@
 {
     return [theConnectionType isEqualToString:@"2g"] ||
            [theConnectionType isEqualToString:@"3g"] ||
-           [theConnectionType isEqualToString:@"4g"];
+           [theConnectionType isEqualToString:@"4g"] ||
+           [theConnectionType isEqualToString:@"cellular"];
 }
 
 - (void)updateReachability:(CDVReachability*)reachability
@@ -111,6 +113,7 @@
         self.internetReach = [CDVReachability reachabilityForInternetConnection];
         self.connectionType = [self w3cConnectionTypeFor:self.internetReach];
         [self.internetReach startNotifier];
+        [self printDeprecationNotice];
         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateConnectionType:)
                                                      name:kReachabilityChangedNotification object:nil];
         if (&UIApplicationDidEnterBackgroundNotification && &UIApplicationWillEnterForegroundNotification) {
@@ -121,4 +124,9 @@
     return self;
 }
 
+- (void)printDeprecationNotice
+{
+    NSLog(@"DEPRECATION NOTICE: The Connection ReachableViaWWAN return value of '2g' is deprecated as of Cordova version 2.6.0 and will be changed to 'cellular' in a future release. ");
+}
+
 @end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVContact.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVContact.m b/lib/cordova-ios/CordovaLib/Classes/CDVContact.m
index 9efaf10..3844525 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVContact.m
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVContact.m
@@ -38,7 +38,9 @@ static NSDictionary* org_apache_cordova_contacts_defaultFields = nil;
     if ((self = [super init]) != nil) {
         ABRecordRef rec = ABPersonCreate();
         self.record = rec;
-        CFRelease(rec);
+        if (rec) {
+            CFRelease(rec);
+        }
     }
     return self;
 }
@@ -167,9 +169,9 @@ static NSDictionary* org_apache_cordova_contacts_defaultFields = nil;
     if (org_apache_cordova_contacts_objectAndProperties == nil) {
         org_apache_cordova_contacts_objectAndProperties = [NSDictionary dictionaryWithObjectsAndKeys:
             [NSArray arrayWithObjects:kW3ContactGivenName, kW3ContactFamilyName,
-                kW3ContactMiddleName, kW3ContactHonorificPrefix, kW3ContactHonorificSuffix, kW3ContactFormattedName, nil], kW3ContactName,
+            kW3ContactMiddleName, kW3ContactHonorificPrefix, kW3ContactHonorificSuffix, kW3ContactFormattedName, nil], kW3ContactName,
             [NSArray arrayWithObjects:kW3ContactStreetAddress, kW3ContactLocality, kW3ContactRegion,
-                kW3ContactPostalCode, kW3ContactCountry, /*kW3ContactAddressFormatted,*/ nil], kW3ContactAddresses,
+            kW3ContactPostalCode, kW3ContactCountry, /*kW3ContactAddressFormatted,*/ nil], kW3ContactAddresses,
             [NSArray arrayWithObjects:kW3ContactOrganizationName, kW3ContactTitle, kW3ContactDepartment, nil], kW3ContactOrganizations,
             [NSArray arrayWithObjects:kW3ContactFieldType, kW3ContactFieldValue, kW3ContactFieldPrimary, nil], kW3ContactPhoneNumbers,
             [NSArray arrayWithObjects:kW3ContactFieldType, kW3ContactFieldValue, kW3ContactFieldPrimary, nil], kW3ContactEmails,
@@ -228,7 +230,7 @@ static NSDictionary* org_apache_cordova_contacts_defaultFields = nil;
         NSArray* propArray = [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactName];
 
         for (id i in propArray) {
-            if (![(NSString*) i isEqualToString:kW3ContactFormattedName]) { // kW3ContactFormattedName is generated from ABRecordCopyCompositeName() and can't be set
+            if (![(NSString*)i isEqualToString : kW3ContactFormattedName]) { // kW3ContactFormattedName is generated from ABRecordCopyCompositeName() and can't be set
                 [self setValue:[dict valueForKey:i] forProperty:(ABPropertyID)[(NSNumber*)[[CDVContact defaultW3CtoAB] objectForKey:i] intValue]
                       inRecord:person asUpdate:bUpdate];
             }
@@ -298,9 +300,9 @@ static NSDictionary* org_apache_cordova_contacts_defaultFields = nil;
             bRemove = YES;
         }
         if ([dict isKindOfClass:[NSDictionary class]] || (bRemove == YES)) {
-            [self setValue:(bRemove ? @"":[dict valueForKey:@"name"]) forProperty:kABPersonOrganizationProperty inRecord:person asUpdate:bUpdate];
-            [self setValue:(bRemove ? @"":[dict valueForKey:kW3ContactTitle]) forProperty:kABPersonJobTitleProperty inRecord:person asUpdate:bUpdate];
-            [self setValue:(bRemove ? @"":[dict valueForKey:kW3ContactDepartment]) forProperty:kABPersonDepartmentProperty inRecord:person asUpdate:bUpdate];
+            [self setValue:(bRemove ? @"" : [dict valueForKey:@"name"]) forProperty:kABPersonOrganizationProperty inRecord:person asUpdate:bUpdate];
+            [self setValue:(bRemove ? @"" : [dict valueForKey:kW3ContactTitle]) forProperty:kABPersonJobTitleProperty inRecord:person asUpdate:bUpdate];
+            [self setValue:(bRemove ? @"" : [dict valueForKey:kW3ContactDepartment]) forProperty:kABPersonDepartmentProperty inRecord:person asUpdate:bUpdate];
         }
     }
     // add dates
@@ -658,7 +660,7 @@ static NSDictionary* org_apache_cordova_contacts_defaultFields = nil;
                             [dict setObject:setValue forKey:(NSString*)[[CDVContact defaultW3CtoAB] valueForKey:(NSString*)k]];
                         } else if ((value == nil) || ([value isKindOfClass:[NSString class]] && ([value length] != 0))) {
                             // value not provided in contact dictionary - if prop exists in AB dictionary, preserve it
-                            valueAB = [(__bridge NSDictionary*) existingDictionary valueForKey:[[CDVContact defaultW3CtoAB] valueForKey:k]];
+                            valueAB = [(__bridge NSDictionary*)existingDictionary valueForKey : [[CDVContact defaultW3CtoAB] valueForKey:k]];
                             if (valueAB != nil) {
                                 [dict setValue:valueAB forKey:[[CDVContact defaultW3CtoAB] valueForKey:k]];
                             }
@@ -893,7 +895,7 @@ static NSDictionary* org_apache_cordova_contacts_defaultFields = nil;
     if (data != nil) {
         [nc setObject:data forKey:kW3ContactName];
     }
-    if ([self.returnFields objectForKey:kW3ContactDisplayName] && ((data == nil) || ([(NSDictionary*) data objectForKey:kW3ContactFormattedName] == [NSNull null]))) {
+    if ([self.returnFields objectForKey:kW3ContactDisplayName] && ((data == nil) || ([(NSDictionary*)data objectForKey : kW3ContactFormattedName] == [NSNull null]))) {
         // user asked for displayName which iOS doesn't support but there is no other name data being returned
         // try and use Composite Name so some name is returned
         id tryName = (__bridge_transfer NSString*)ABRecordCopyCompositeName(self.record);
@@ -1114,7 +1116,7 @@ static NSDictionary* org_apache_cordova_contacts_defaultFields = nil;
             // always set id
             value = [NSNumber numberWithUnsignedInt:ABMultiValueGetIdentifierAtIndex(multi, i)];
             [newDict setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactFieldId];
-            [(NSMutableArray*) valuesArray addObject:newDict];
+            [(NSMutableArray*)valuesArray addObject : newDict];
         }
     } else {
         valuesArray = [NSNull null];
@@ -1188,7 +1190,7 @@ static NSDictionary* org_apache_cordova_contacts_defaultFields = nil;
             }
 
             if ([newAddress count] > 0) { // ?? this will always be true since we set id,label,primary field??
-                [(NSMutableArray*) addresses addObject:newAddress];
+                [(NSMutableArray*)addresses addObject : newAddress];
             }
             CFRelease(dict);
         } // end of loop through addresses
@@ -1244,7 +1246,7 @@ static NSDictionary* org_apache_cordova_contacts_defaultFields = nil;
                 bFound = CFDictionaryGetValueIfPresent(dict, kABPersonInstantMessageServiceKey, (void*)&value);
                 if (bFound && (value != NULL)) {
                     CFRetain(value);
-                    [newDict setObject:(id)[[CDVContact class] convertPropertyLabelToContactType:(__bridge NSString*)value] forKey:kW3ContactFieldType];
+                    [newDict setObject:(id)[[CDVContact class] convertPropertyLabelToContactType : (__bridge NSString*)value] forKey:kW3ContactFieldType];
                     CFRelease(value);
                 } else {
                     [newDict setObject:[NSNull null] forKey:kW3ContactFieldType];
@@ -1254,7 +1256,7 @@ static NSDictionary* org_apache_cordova_contacts_defaultFields = nil;
             id identifier = [NSNumber numberWithUnsignedInt:ABMultiValueGetIdentifierAtIndex(multi, i)];
             [newDict setObject:(identifier != nil) ? identifier:[NSNull null] forKey:kW3ContactFieldId];
 
-            [(NSMutableArray*) imArray addObject:newDict];
+            [(NSMutableArray*)imArray addObject : newDict];
             CFRelease(dict);
         }
     } else {
@@ -1308,7 +1310,7 @@ static NSDictionary* org_apache_cordova_contacts_defaultFields = nil;
         [newDict setObject:@"false" forKey:kW3ContactFieldPrimary];
         [newDict setObject:[NSNull null] forKey:kW3ContactFieldType];
         array = [NSMutableArray arrayWithCapacity:1];
-        [(NSMutableArray*) array addObject:newDict];
+        [(NSMutableArray*)array addObject : newDict];
     } else {
         array = [NSNull null];
     }
@@ -1327,7 +1329,7 @@ static NSDictionary* org_apache_cordova_contacts_defaultFields = nil;
         NSData* data = (__bridge NSData*)photoData;
         // write to temp directory and store URI in photos array
         // get the temp directory path
-        NSString* docsPath = [NSTemporaryDirectory ()stringByStandardizingPath];
+        NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
         NSError* err = nil;
         NSString* filePath = [NSString stringWithFormat:@"%@/photo_XXXXX", docsPath];
         char template[filePath.length + 1];

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVContacts.h
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVContacts.h b/lib/cordova-ios/CordovaLib/Classes/CDVContacts.h
index 17470c0..0342f5b 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVContacts.h
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVContacts.h
@@ -24,9 +24,9 @@
 #import "CDVContact.h"
 
 @interface CDVContacts : CDVPlugin <ABNewPersonViewControllerDelegate,
-    ABPersonViewControllerDelegate,
-    ABPeoplePickerNavigationControllerDelegate
-    >
+                         ABPersonViewControllerDelegate,
+                         ABPeoplePickerNavigationControllerDelegate
+                         >
 {
     ABAddressBookRef addressBook;
 }
@@ -63,7 +63,7 @@
 
 - (void)newPersonViewController:(ABNewPersonViewController*)newPersonViewController didCompleteWithNewPerson:(ABRecordRef)person;
 - (BOOL)personViewController:(ABPersonViewController*)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person
-   property                 :(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue;
+                    property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue;
 
 /*
  * search - searches for contacts.  Only person records are currently supported.
@@ -140,9 +140,9 @@
 - (CDVAddressBookAccessError*)initWithCode:(CDVContactError)code;
 @end
 
-typedef void (^CDVAddressBookWorkerBlock)(
-    ABAddressBookRef addressBook,
-    CDVAddressBookAccessError * error
+typedef void (^ CDVAddressBookWorkerBlock)(
+    ABAddressBookRef         addressBook,
+    CDVAddressBookAccessError* error
     );
 @interface CDVAddressBookHelper : NSObject
 {}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVContacts.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVContacts.m b/lib/cordova-ios/CordovaLib/Classes/CDVContacts.m
index 3faf6ba..6cb9f08 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVContacts.m
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVContacts.m
@@ -77,26 +77,26 @@
     CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
     CDVContacts* __weak weakSelf = self;  // play it safe to avoid retain cycles
 
-    [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError * errCode) {
-            if (addrBook == NULL) {
-                // permission was denied or other error just return (no error callback)
-                return;
-            }
-            CDVNewContactsController* npController = [[CDVNewContactsController alloc] init];
-            npController.addressBook = addrBook; // a CF retaining assign
-            CFRelease (addrBook);
+    [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errCode) {
+        if (addrBook == NULL) {
+            // permission was denied or other error just return (no error callback)
+            return;
+        }
+        CDVNewContactsController* npController = [[CDVNewContactsController alloc] init];
+        npController.addressBook = addrBook;     // a CF retaining assign
+        CFRelease(addrBook);
 
-            npController.newPersonViewDelegate = self;
-            npController.callbackId = callbackId;
+        npController.newPersonViewDelegate = self;
+        npController.callbackId = callbackId;
 
-            UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:npController];
+        UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:npController];
 
-            if ([weakSelf.viewController respondsToSelector:@selector(presentViewController:::)]) {
-                [weakSelf.viewController presentViewController:navController animated:YES completion:nil];
-            } else {
-                [weakSelf.viewController presentModalViewController:navController animated:YES];
-            }
-        }];
+        if ([weakSelf.viewController respondsToSelector:@selector(presentViewController:::)]) {
+            [weakSelf.viewController presentViewController:navController animated:YES completion:nil];
+        } else {
+            [weakSelf.viewController presentModalViewController:navController animated:YES];
+        }
+    }];
 }
 
 - (void)newPersonViewController:(ABNewPersonViewController*)newPersonViewController didCompleteWithNewPerson:(ABRecordRef)person
@@ -130,48 +130,48 @@
     CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
     CDVContacts* __weak weakSelf = self;  // play it safe to avoid retain cycles
 
-    [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError * errCode) {
-            if (addrBook == NULL) {
-                // permission was denied or other error - return error
-                CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:errCode ? errCode.errorCode:UNKNOWN_ERROR];
-                [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
-                return;
-            }
-            ABRecordRef rec = ABAddressBookGetPersonWithRecordID (addrBook, recordID);
-
-            if (rec) {
-                CDVDisplayContactViewController* personController = [[CDVDisplayContactViewController alloc] init];
-                personController.displayedPerson = rec;
-                personController.personViewDelegate = self;
-                personController.allowsEditing = NO;
+    [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errCode) {
+        if (addrBook == NULL) {
+            // permission was denied or other error - return error
+            CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:errCode ? errCode.errorCode:UNKNOWN_ERROR];
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
+            return;
+        }
+        ABRecordRef rec = ABAddressBookGetPersonWithRecordID(addrBook, recordID);
 
-                // create this so DisplayContactViewController will have a "back" button.
-                UIViewController* parentController = [[UIViewController alloc] init];
-                UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:parentController];
+        if (rec) {
+            CDVDisplayContactViewController* personController = [[CDVDisplayContactViewController alloc] init];
+            personController.displayedPerson = rec;
+            personController.personViewDelegate = self;
+            personController.allowsEditing = NO;
 
-                [navController pushViewController:personController animated:YES];
+            // create this so DisplayContactViewController will have a "back" button.
+            UIViewController* parentController = [[UIViewController alloc] init];
+            UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:parentController];
 
-                if ([self.viewController respondsToSelector:@selector(presentViewController:::)]) {
-                    [self.viewController presentViewController:navController animated:YES completion:nil];
-                } else {
-                    [self.viewController presentModalViewController:navController animated:YES];
-                }
+            [navController pushViewController:personController animated:YES];
 
-                if (bEdit) {
-                    // create the editing controller and push it onto the stack
-                    ABPersonViewController* editPersonController = [[ABPersonViewController alloc] init];
-                    editPersonController.displayedPerson = rec;
-                    editPersonController.personViewDelegate = self;
-                    editPersonController.allowsEditing = YES;
-                    [navController pushViewController:editPersonController animated:YES];
-                }
+            if ([self.viewController respondsToSelector:@selector(presentViewController:::)]) {
+                [self.viewController presentViewController:navController animated:YES completion:nil];
             } else {
-                // no record, return error
-                CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:UNKNOWN_ERROR];
-                [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
+                [self.viewController presentModalViewController:navController animated:YES];
             }
-            CFRelease (addrBook);
-        }];
+
+            if (bEdit) {
+                // create the editing controller and push it onto the stack
+                ABPersonViewController* editPersonController = [[ABPersonViewController alloc] init];
+                editPersonController.displayedPerson = rec;
+                editPersonController.personViewDelegate = self;
+                editPersonController.allowsEditing = YES;
+                [navController pushViewController:editPersonController animated:YES];
+            }
+        } else {
+            // no record, return error
+            CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:UNKNOWN_ERROR];
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
+        }
+        CFRelease(addrBook);
+    }];
 }
 
 - (BOOL)personViewController:(ABPersonViewController*)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person
@@ -284,95 +284,95 @@
     NSDictionary* findOptions = [command.arguments objectAtIndex:1 withDefault:[NSNull null]];
 
     [self.commandDelegate runInBackground:^{
-            // from Apple:  Important You must ensure that an instance of ABAddressBookRef is used by only one thread.
-            // which is why address book is created within the dispatch queue.
-            // more details here: http: //blog.byadrian.net/2012/05/05/ios-addressbook-framework-and-gcd/
-            CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
-            CDVContacts* __weak weakSelf = self; // play it safe to avoid retain cycles
-            // it gets uglier, block within block.....
-            [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError * errCode) {
-                    if (addrBook == NULL) {
-                        // permission was denied or other error - return error
-                        CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:errCode ? errCode.errorCode:UNKNOWN_ERROR];
-                        [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
-                        return;
-                    }
+        // from Apple:  Important You must ensure that an instance of ABAddressBookRef is used by only one thread.
+        // which is why address book is created within the dispatch queue.
+        // more details here: http: //blog.byadrian.net/2012/05/05/ios-addressbook-framework-and-gcd/
+        CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
+        CDVContacts* __weak weakSelf = self;     // play it safe to avoid retain cycles
+        // it gets uglier, block within block.....
+        [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errCode) {
+            if (addrBook == NULL) {
+                // permission was denied or other error - return error
+                CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:errCode ? errCode.errorCode:UNKNOWN_ERROR];
+                [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
+                return;
+            }
 
-                    NSArray* foundRecords = nil;
-                    // get the findOptions values
-                    BOOL multiple = NO; // default is false
-                    NSString* filter = nil;
-                    if (![findOptions isKindOfClass:[NSNull class]]) {
-                        id value = nil;
-                        filter = (NSString*)[findOptions objectForKey:@"filter"];
-                        value = [findOptions objectForKey:@"multiple"];
-                        if ([value isKindOfClass:[NSNumber class]]) {
-                            // multiple is a boolean that will come through as an NSNumber
-                            multiple = [(NSNumber*) value boolValue];
-                            // NSLog(@"multiple is: %d", multiple);
-                        }
-                    }
+            NSArray* foundRecords = nil;
+            // get the findOptions values
+            BOOL multiple = NO;         // default is false
+            NSString* filter = nil;
+            if (![findOptions isKindOfClass:[NSNull class]]) {
+                id value = nil;
+                filter = (NSString*)[findOptions objectForKey:@"filter"];
+                value = [findOptions objectForKey:@"multiple"];
+                if ([value isKindOfClass:[NSNumber class]]) {
+                    // multiple is a boolean that will come through as an NSNumber
+                    multiple = [(NSNumber*)value boolValue];
+                    // NSLog(@"multiple is: %d", multiple);
+                }
+            }
 
-                    NSDictionary* returnFields = [[CDVContact class] calcReturnFields:fields];
-
-                    NSMutableArray* matches = nil;
-                    if (!filter || [filter isEqualToString:@""]) {
-                        // get all records
-                        foundRecords = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople (addrBook);
-                        if (foundRecords && [foundRecords count] > 0) {
-                            // create Contacts and put into matches array
-                            // doesn't make sense to ask for all records when multiple == NO but better check
-                            int xferCount = multiple == YES ? [foundRecords count]:1;
-                            matches = [NSMutableArray arrayWithCapacity:xferCount];
-
-                            for (int k = 0; k < xferCount; k++) {
-                                CDVContact* xferContact = [[CDVContact alloc] initFromABRecord:(__bridge ABRecordRef)[foundRecords objectAtIndex:k]];
-                                [matches addObject:xferContact];
-                                xferContact = nil;
-                            }
-                        }
-                    } else {
-                        foundRecords = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople (addrBook);
-                        matches = [NSMutableArray arrayWithCapacity:1];
-                        BOOL bFound = NO;
-                        int testCount = [foundRecords count];
-
-                        for (int j = 0; j < testCount; j++) {
-                            CDVContact* testContact = [[CDVContact alloc] initFromABRecord:(__bridge ABRecordRef)[foundRecords objectAtIndex:j]];
-                            if (testContact) {
-                                bFound = [testContact foundValue:filter inFields:returnFields];
-                                if (bFound) {
-                                    [matches addObject:testContact];
-                                }
-                                testContact = nil;
-                            }
-                        }
+            NSDictionary* returnFields = [[CDVContact class] calcReturnFields:fields];
+
+            NSMutableArray* matches = nil;
+            if (!filter || [filter isEqualToString:@""]) {
+                // get all records
+                foundRecords = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addrBook);
+                if (foundRecords && ([foundRecords count] > 0)) {
+                    // create Contacts and put into matches array
+                    // doesn't make sense to ask for all records when multiple == NO but better check
+                    int xferCount = multiple == YES ? [foundRecords count] : 1;
+                    matches = [NSMutableArray arrayWithCapacity:xferCount];
+
+                    for (int k = 0; k < xferCount; k++) {
+                        CDVContact* xferContact = [[CDVContact alloc] initFromABRecord:(__bridge ABRecordRef)[foundRecords objectAtIndex:k]];
+                        [matches addObject:xferContact];
+                        xferContact = nil;
                     }
-                    NSMutableArray* returnContacts = [NSMutableArray arrayWithCapacity:1];
-
-                    if (matches != nil && [matches count] > 0) {
-                        // convert to JS Contacts format and return in callback
-                        // - returnFields  determines what properties to return
-                        @autoreleasepool {
-                            int count = multiple == YES ? [matches count]:1;
-
-                            for (int i = 0; i < count; i++) {
-                                CDVContact* newContact = [matches objectAtIndex:i];
-                                NSDictionary* aContact = [newContact toDictionary:returnFields];
-                                [returnContacts addObject:aContact];
-                            }
+                }
+            } else {
+                foundRecords = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addrBook);
+                matches = [NSMutableArray arrayWithCapacity:1];
+                BOOL bFound = NO;
+                int testCount = [foundRecords count];
+
+                for (int j = 0; j < testCount; j++) {
+                    CDVContact* testContact = [[CDVContact alloc] initFromABRecord:(__bridge ABRecordRef)[foundRecords objectAtIndex:j]];
+                    if (testContact) {
+                        bFound = [testContact foundValue:filter inFields:returnFields];
+                        if (bFound) {
+                            [matches addObject:testContact];
                         }
+                        testContact = nil;
                     }
-                    // return found contacts (array is empty if no contacts found)
-                    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:returnContacts];
-                    [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
-                    // NSLog(@"findCallback string: %@", jsString);
-
-                    if (addrBook) {
-                        CFRelease (addrBook);
+                }
+            }
+            NSMutableArray* returnContacts = [NSMutableArray arrayWithCapacity:1];
+
+            if ((matches != nil) && ([matches count] > 0)) {
+                // convert to JS Contacts format and return in callback
+                // - returnFields  determines what properties to return
+                @autoreleasepool {
+                    int count = multiple == YES ? [matches count] : 1;
+
+                    for (int i = 0; i < count; i++) {
+                        CDVContact* newContact = [matches objectAtIndex:i];
+                        NSDictionary* aContact = [newContact toDictionary:returnFields];
+                        [returnContacts addObject:aContact];
                     }
-                }];
-        }]; // end of workQueue block
+                }
+            }
+            // return found contacts (array is empty if no contacts found)
+            CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:returnContacts];
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
+            // NSLog(@"findCallback string: %@", jsString);
+
+            if (addrBook) {
+                CFRelease(addrBook);
+            }
+        }];
+    }];     // end of workQueue block
 
     return;
 }
@@ -383,81 +383,10 @@
     NSDictionary* contactDict = [command.arguments objectAtIndex:0];
 
     [self.commandDelegate runInBackground:^{
-            CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
-            CDVContacts* __weak weakSelf = self; // play it safe to avoid retain cycles
-
-            [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError * errorCode) {
-                    CDVPluginResult* result = nil;
-                    if (addrBook == NULL) {
-                        // permission was denied or other error - return error
-                        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errorCode ? errorCode.errorCode:UNKNOWN_ERROR];
-                        [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
-                        return;
-                    }
-
-                    bool bIsError = FALSE, bSuccess = FALSE;
-                    BOOL bUpdate = NO;
-                    CDVContactError errCode = UNKNOWN_ERROR;
-                    CFErrorRef error;
-                    NSNumber* cId = [contactDict valueForKey:kW3ContactId];
-                    CDVContact* aContact = nil;
-                    ABRecordRef rec = nil;
-                    if (cId && ![cId isKindOfClass:[NSNull class]]) {
-                        rec = ABAddressBookGetPersonWithRecordID (addrBook, [cId intValue]);
-                        if (rec) {
-                            aContact = [[CDVContact alloc] initFromABRecord:rec];
-                            bUpdate = YES;
-                        }
-                    }
-                    if (!aContact) {
-                        aContact = [[CDVContact alloc] init];
-                    }
-
-                    bSuccess = [aContact setFromContactDict:contactDict asUpdate:bUpdate];
-                    if (bSuccess) {
-                        if (!bUpdate) {
-                            bSuccess = ABAddressBookAddRecord (addrBook, [aContact record], &error);
-                        }
-                        if (bSuccess) {
-                            bSuccess = ABAddressBookSave (addrBook, &error);
-                        }
-                        if (!bSuccess) { // need to provide error codes
-                            bIsError = TRUE;
-                            errCode = IO_ERROR;
-                        } else {
-                            // give original dictionary back?  If generate dictionary from saved contact, have no returnFields specified
-                            // so would give back all fields (which W3C spec. indicates is not desired)
-                            // for now (while testing) give back saved, full contact
-                            NSDictionary* newContact = [aContact toDictionary:[CDVContact defaultFields]];
-                            // NSString* contactStr = [newContact JSONRepresentation];
-                            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:newContact];
-                        }
-                    } else {
-                        bIsError = TRUE;
-                        errCode = IO_ERROR;
-                    }
-                    CFRelease (addrBook);
-
-                    if (bIsError) {
-                        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errCode];
-                    }
-
-                    if (result) {
-                        [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
-                    }
-                }];
-        }]; // end of  queue
-}
-
-- (void)remove:(CDVInvokedUrlCommand*)command
-{
-    NSString* callbackId = command.callbackId;
-    NSNumber* cId = [command.arguments objectAtIndex:0];
-
-    CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
-    CDVContacts* __weak weakSelf = self;  // play it safe to avoid retain cycles
+        CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
+        CDVContacts* __weak weakSelf = self;     // play it safe to avoid retain cycles
 
-    [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError * errorCode) {
+        [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errorCode) {
             CDVPluginResult* result = nil;
             if (addrBook == NULL) {
                 // permission was denied or other error - return error
@@ -467,50 +396,121 @@
             }
 
             bool bIsError = FALSE, bSuccess = FALSE;
+            BOOL bUpdate = NO;
             CDVContactError errCode = UNKNOWN_ERROR;
             CFErrorRef error;
+            NSNumber* cId = [contactDict valueForKey:kW3ContactId];
+            CDVContact* aContact = nil;
             ABRecordRef rec = nil;
-            if (cId && ![cId isKindOfClass:[NSNull class]] && ([cId intValue] != kABRecordInvalidID)) {
-                rec = ABAddressBookGetPersonWithRecordID (addrBook, [cId intValue]);
+            if (cId && ![cId isKindOfClass:[NSNull class]]) {
+                rec = ABAddressBookGetPersonWithRecordID(addrBook, [cId intValue]);
                 if (rec) {
-                    bSuccess = ABAddressBookRemoveRecord (addrBook, rec, &error);
-                    if (!bSuccess) {
-                        bIsError = TRUE;
-                        errCode = IO_ERROR;
-                    } else {
-                        bSuccess = ABAddressBookSave (addrBook, &error);
-                        if (!bSuccess) {
-                            bIsError = TRUE;
-                            errCode = IO_ERROR;
-                        } else {
-                            // set id to null
-                            // [contactDict setObject:[NSNull null] forKey:kW3ContactId];
-                            // result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary: contactDict];
-                            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
-                            // NSString* contactStr = [contactDict JSONRepresentation];
-                        }
-                    }
-                } else {
-                    // no record found return error
+                    aContact = [[CDVContact alloc] initFromABRecord:rec];
+                    bUpdate = YES;
+                }
+            }
+            if (!aContact) {
+                aContact = [[CDVContact alloc] init];
+            }
+
+            bSuccess = [aContact setFromContactDict:contactDict asUpdate:bUpdate];
+            if (bSuccess) {
+                if (!bUpdate) {
+                    bSuccess = ABAddressBookAddRecord(addrBook, [aContact record], &error);
+                }
+                if (bSuccess) {
+                    bSuccess = ABAddressBookSave(addrBook, &error);
+                }
+                if (!bSuccess) {         // need to provide error codes
                     bIsError = TRUE;
-                    errCode = UNKNOWN_ERROR;
+                    errCode = IO_ERROR;
+                } else {
+                    // give original dictionary back?  If generate dictionary from saved contact, have no returnFields specified
+                    // so would give back all fields (which W3C spec. indicates is not desired)
+                    // for now (while testing) give back saved, full contact
+                    NSDictionary* newContact = [aContact toDictionary:[CDVContact defaultFields]];
+                    // NSString* contactStr = [newContact JSONRepresentation];
+                    result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:newContact];
                 }
             } else {
-                // invalid contact id provided
                 bIsError = TRUE;
-                errCode = INVALID_ARGUMENT_ERROR;
+                errCode = IO_ERROR;
             }
+            CFRelease(addrBook);
 
-            if (addrBook) {
-                CFRelease (addrBook);
-            }
             if (bIsError) {
                 result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errCode];
             }
+
             if (result) {
                 [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
             }
         }];
+    }];     // end of  queue
+}
+
+- (void)remove:(CDVInvokedUrlCommand*)command
+{
+    NSString* callbackId = command.callbackId;
+    NSNumber* cId = [command.arguments objectAtIndex:0];
+
+    CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
+    CDVContacts* __weak weakSelf = self;  // play it safe to avoid retain cycles
+
+    [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errorCode) {
+        CDVPluginResult* result = nil;
+        if (addrBook == NULL) {
+            // permission was denied or other error - return error
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errorCode ? errorCode.errorCode:UNKNOWN_ERROR];
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
+            return;
+        }
+
+        bool bIsError = FALSE, bSuccess = FALSE;
+        CDVContactError errCode = UNKNOWN_ERROR;
+        CFErrorRef error;
+        ABRecordRef rec = nil;
+        if (cId && ![cId isKindOfClass:[NSNull class]] && ([cId intValue] != kABRecordInvalidID)) {
+            rec = ABAddressBookGetPersonWithRecordID(addrBook, [cId intValue]);
+            if (rec) {
+                bSuccess = ABAddressBookRemoveRecord(addrBook, rec, &error);
+                if (!bSuccess) {
+                    bIsError = TRUE;
+                    errCode = IO_ERROR;
+                } else {
+                    bSuccess = ABAddressBookSave(addrBook, &error);
+                    if (!bSuccess) {
+                        bIsError = TRUE;
+                        errCode = IO_ERROR;
+                    } else {
+                        // set id to null
+                        // [contactDict setObject:[NSNull null] forKey:kW3ContactId];
+                        // result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary: contactDict];
+                        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
+                        // NSString* contactStr = [contactDict JSONRepresentation];
+                    }
+                }
+            } else {
+                // no record found return error
+                bIsError = TRUE;
+                errCode = UNKNOWN_ERROR;
+            }
+        } else {
+            // invalid contact id provided
+            bIsError = TRUE;
+            errCode = INVALID_ARGUMENT_ERROR;
+        }
+
+        if (addrBook) {
+            CFRelease(addrBook);
+        }
+        if (bIsError) {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errCode];
+        }
+        if (result) {
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
+        }
+    }];
     return;
 }
 
@@ -569,24 +569,24 @@
             addressBook = ABAddressBookCreateWithOptions(NULL, &error);
             // NSLog(@"addressBook access: %lu", status);
             ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
-                // callback can occur in background, address book must be accessed on thread it was created on
-                dispatch_sync (dispatch_get_main_queue (), ^{
+                    // callback can occur in background, address book must be accessed on thread it was created on
+                    dispatch_sync(dispatch_get_main_queue(), ^{
                         if (error) {
-                            workerBlock (NULL, [[CDVAddressBookAccessError alloc] initWithCode:UNKNOWN_ERROR]);
+                            workerBlock(NULL, [[CDVAddressBookAccessError alloc] initWithCode:UNKNOWN_ERROR]);
                         } else if (!granted) {
-                            workerBlock (NULL, [[CDVAddressBookAccessError alloc] initWithCode:PERMISSION_DENIED_ERROR]);
+                            workerBlock(NULL, [[CDVAddressBookAccessError alloc] initWithCode:PERMISSION_DENIED_ERROR]);
                         } else {
                             // access granted
-                            workerBlock (addressBook, [[CDVAddressBookAccessError alloc] initWithCode:UNKNOWN_ERROR]);
+                            workerBlock(addressBook, [[CDVAddressBookAccessError alloc] initWithCode:UNKNOWN_ERROR]);
                         }
                     });
-            });
+                });
         } else
 #endif
     {
         // iOS 4 or 5 no checks needed
-        addressBook = ABAddressBookCreate ();
-        workerBlock (addressBook, NULL);
+        addressBook = ABAddressBookCreate();
+        workerBlock(addressBook, NULL);
     }
 }
 

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVEcho.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVEcho.m b/lib/cordova-ios/CordovaLib/Classes/CDVEcho.m
index 916e315..c74990d 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVEcho.m
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVEcho.m
@@ -51,4 +51,11 @@
     [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
 }
 
+- (void)echoMultiPart:(CDVInvokedUrlCommand*)command
+{
+    CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsMultipart:command.arguments];
+
+    [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+}
+
 @end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVExif.h
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVExif.h b/lib/cordova-ios/CordovaLib/Classes/CDVExif.h
new file mode 100644
index 0000000..3e8adbd
--- /dev/null
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVExif.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.
+ */
+
+#ifndef CordovaLib_ExifData_h
+#define CordovaLib_ExifData_h
+
+// exif data types
+typedef enum exifDataTypes {
+    EDT_UBYTE = 1,      // 8 bit unsigned integer
+    EDT_ASCII_STRING,   // 8 bits containing 7 bit ASCII code, null terminated
+    EDT_USHORT,         // 16 bit unsigned integer
+    EDT_ULONG,          // 32 bit unsigned integer
+    EDT_URATIONAL,      // 2 longs, first is numerator and second is denominator
+    EDT_SBYTE,
+    EDT_UNDEFINED,      // 8 bits
+    EDT_SSHORT,
+    EDT_SLONG,          // 32bit signed integer (2's complement)
+    EDT_SRATIONAL,      // 2 SLONGS, first long is numerator, second is denominator
+    EDT_SINGLEFLOAT,
+    EDT_DOUBLEFLOAT
+} ExifDataTypes;
+
+// maps integer code for exif data types to width in bytes
+static const int DataTypeToWidth[] = {1,1,2,4,8,1,1,2,4,8,4,8};
+
+static const int RECURSE_HORIZON = 8;
+#endif

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/37b92ff4/lib/cordova-ios/CordovaLib/Classes/CDVFile.h
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVFile.h b/lib/cordova-ios/CordovaLib/Classes/CDVFile.h
index 4862921..eaf8cbe 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVFile.h
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVFile.h
@@ -21,6 +21,7 @@
 #import "CDVPlugin.h"
 
 enum CDVFileError {
+    NO_ERROR = 0,
     NOT_FOUND_ERR = 1,
     SECURITY_ERR = 2,
     ABORT_ERR = 3,
@@ -76,6 +77,7 @@ extern NSString* const kCDVAssetsLibraryPrefix;
 
 - (void)readAsText:(CDVInvokedUrlCommand*)command;
 - (void)readAsDataURL:(CDVInvokedUrlCommand*)command;
+- (void)readAsArrayBuffer:(CDVInvokedUrlCommand*)command;
 - (NSString*)getMimeTypeFromPath:(NSString*)fullPath;
 - (void)write:(CDVInvokedUrlCommand*)command;
 - (void)testFileExists:(CDVInvokedUrlCommand*)command;