Merge branch 'dev'
diff --git a/CHANGELOG.md b/RELEASENOTES.md
similarity index 64%
rename from CHANGELOG.md
rename to RELEASENOTES.md
index 810e68a..1f83d64 100644
--- a/CHANGELOG.md
+++ b/RELEASENOTES.md
@@ -24,3 +24,13 @@
 * [CB-4580] Fixed up duplicate definitions of module id
 * [CB-4432] Copyright notice change
 
+### 0.2.3 (Sept 25, 2013)
+* CB-4889 bumping&resetting version
+* [BlackBerry10] removed uneeded permission tags in plugin.xml
+* [BlackBerry10] removed uneeded permission tags in plugin.xml
+* CB-4889 renaming blackberry10 reference in plugin.xml
+* CB-4888 renaming org.apache.cordova.core.contacts to org.apache.cordova.contacts
+* added contacts api for firefoxos
+* Rename CHANGELOG.md -> RELEASENOTES.md
+* [CB-4824] Fix XCode 5 contacts plugin warnings
+* [CB-4752] Incremented plugin version on dev branch.
diff --git a/plugin.xml b/plugin.xml
index 4db4d7d..2b407af 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -3,8 +3,8 @@
 <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
     xmlns:rim="http://www.blackberry.com/ns/widgets"
     xmlns:android="http://schemas.android.com/apk/res/android"
-    id="org.apache.cordova.core.contacts"
-    version="0.2.1">
+    id="org.apache.cordova.contacts"
+    version="0.2.3">
 
     <name>Contacts</name>
     <description>Cordova Contacts Plugin</description>
@@ -144,5 +144,17 @@
 
         <source-file src="src/wp/Contacts.cs" />
     </platform>
+    
+    <!-- firefoxos -->
+    <platform name="firefoxos">
+        <config-file target="config.xml" parent="/*">
+            <feature name="Camera">
+                <param name="firefoxos-package" value="Contacts" />
+            </feature>
+        </config-file>                                         
+        <js-module src="src/firefoxos/ContactsProxy.js" name="ContactsProxy">
+            <runs />
+        </js-module>
+    </platform>    
 
 </plugin>
diff --git a/src/blackberry10/plugin.xml b/src/blackberry10/plugin.xml
index d163585..58b7f2b 100644
--- a/src/blackberry10/plugin.xml
+++ b/src/blackberry10/plugin.xml
@@ -16,7 +16,7 @@
 -->
 
 <plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
-    id="org.apache.cordova.core.Contacts"
+    id="org.apache.cordova.Contacts"
     version="0.0.1">
 
     <name>Contacts</name>
diff --git a/src/firefoxos/ContactsProxy.js b/src/firefoxos/ContactsProxy.js
new file mode 100644
index 0000000..6c074ce
--- /dev/null
+++ b/src/firefoxos/ContactsProxy.js
@@ -0,0 +1,107 @@
+/*
+ *
+ * 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.
+ *
+*/ 
+
+// somehow call this function by this:
+// exec(success, fail, "Contacts", "save", [dupContact]);
+// Cordova contact definition: 
+// http://cordova.apache.org/docs/en/2.5.0/cordova_contacts_contacts.md.html#Contact
+// FxOS contact definition:
+// https://developer.mozilla.org/en-US/docs/Web/API/mozContact
+function saveContact(contacts, success, fail) {
+    // success and fail will be called every time a contact is saved
+    for (var contact in contacts) {
+        var moz = new mozContact(),
+            request;
+            
+            function exportContactFieldArray(contactFieldArray, key) {
+                if (!key) {
+                    key = 'value';
+                }                 
+                
+                var arr = [];
+                
+                for (var i in contactFieldArray) {
+                    arr.push(contactFieldArray[i][key]);
+                };                                       
+                
+                return arr;
+            }              
+            
+            function exportAddress (addresses) {
+                // TODO: check moz address format
+                var arr = [];
+                
+                for (var i in addresses) {
+                    var addr = {};
+                
+                    for (var key in addresses[i]) {
+                        addr[key] = addresses[i][key];    
+                    } 
+                    
+                    arr.push(addr);
+                    
+                }                                 
+                
+                return arr;
+            } 
+            
+            // prepare mozContact object
+            // TODO: find a way to link existing mozContact and Contact 
+            // (by ID?)
+            moz.init({
+                name: [contact.name.familyName, 
+                       contact.name.givenName, 
+                       contact.name.middleName, 
+                       contact.name.nickname],
+                honorificPrefix: [contact.name.honorificPrefix],
+                givenName: [contact.name.givenName],
+                familyName: [contact.name.familyName],
+                honorificSuffix: [contact.name.honorificSuffix], 
+                nickname: [contact.nickname],
+                email: exportContactFieldArray(contact.emails),
+                // photo: Blob
+                // url: Array with metadata (?)
+                category: exportContactFieldArray(contact.categories),
+                adr: exportAddress(contact.addresses),
+                tel: exportContactFieldArray(contact.phoneNumbers),
+                org: exportContactFieldArray(contact.organizations, 'name'),
+                jobTitle: exportContactFieldArray(contact.organizations, 'title'),
+                bday: contact.birthday,
+                note: contact.note,
+                // impp: exportIM(contact.ims), TODO: find the moz impp definition
+                // anniversary
+                // sex
+                // genderIdentity
+                // key
+            });
+            
+            request = navigator.mozContacts.save(moz);
+            request.onsuccess = success;
+            request.onerror = fail;                
+    }
+}   
+
+module.exports = {
+    saveContact: saveContact,
+    cleanup: function(){}
+};    
+    
+require("cordova/firefoxos/commandProxy").add("Contacts", module.exports); 
diff --git a/src/ios/CDVContacts.m b/src/ios/CDVContacts.m
index 3ca3e81..7ca6c80 100644
--- a/src/ios/CDVContacts.m
+++ b/src/ios/CDVContacts.m
@@ -91,9 +91,11 @@
 
         UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:npController];
 
-        if ([weakSelf.viewController respondsToSelector:@selector(presentViewController:::)]) {
+        SEL selector = NSSelectorFromString(@"presentViewController:animated:completion:");
+        if ([weakSelf.viewController respondsToSelector:selector]) {
             [weakSelf.viewController presentViewController:navController animated:YES completion:nil];
         } else {
+            // deprecated as of iOS >= 6.0
             [weakSelf.viewController presentModalViewController:navController animated:YES];
         }
     }];
@@ -151,9 +153,11 @@
 
             [navController pushViewController:personController animated:YES];
 
-            if ([self.viewController respondsToSelector:@selector(presentViewController:::)]) {
+            SEL selector = NSSelectorFromString(@"presentViewController:animated:completion:");
+            if ([self.viewController respondsToSelector:selector]) {
                 [self.viewController presentViewController:navController animated:YES completion:nil];
             } else {
+                // deprecated as of iOS >= 6.0
                 [self.viewController presentModalViewController:navController animated:YES];
             }
 
@@ -193,9 +197,11 @@
     pickerController.pickedContactDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:kABRecordInvalidID], kW3ContactId, nil];
     pickerController.allowsEditing = (BOOL)[options existsValue : @"true" forKey : @"allowsEditing"];
 
-    if ([self.viewController respondsToSelector:@selector(presentViewController:::)]) {
+    SEL selector = NSSelectorFromString(@"presentViewController:animated:completion:");
+    if ([self.viewController respondsToSelector:selector]) {
         [self.viewController presentViewController:pickerController animated:YES completion:nil];
     } else {
+        // deprecated as of iOS >= 6.0
         [self.viewController presentModalViewController:pickerController animated:YES];
     }
 }