You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by st...@apache.org on 2013/05/23 00:54:31 UTC

[1/3] removed contact code

Updated Branches:
  refs/heads/3.0.0 cec787432 -> 6189baaf6


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/b3a1ea79/CordovaLib/Classes/CDVContacts.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVContacts.h b/CordovaLib/Classes/CDVContacts.h
deleted file mode 100644
index 0342f5b..0000000
--- a/CordovaLib/Classes/CDVContacts.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-
-#import <Foundation/Foundation.h>
-#import <AddressBook/ABAddressBook.h>
-#import <AddressBookUI/AddressBookUI.h>
-#import "CDVPlugin.h"
-#import "CDVContact.h"
-
-@interface CDVContacts : CDVPlugin <ABNewPersonViewControllerDelegate,
-                         ABPersonViewControllerDelegate,
-                         ABPeoplePickerNavigationControllerDelegate
-                         >
-{
-    ABAddressBookRef addressBook;
-}
-
-/*
- * newContact - create a new contact via the GUI
- *
- * arguments:
- *	1: successCallback: this is the javascript function that will be called with the newly created contactId
- */
-- (void)newContact:(CDVInvokedUrlCommand*)command;
-
-/*
- * displayContact  - IN PROGRESS
- *
- * arguments:
- *	1: recordID of the contact to display in the iPhone contact display
- *	2: successCallback - currently not used
- *  3: error callback
- * options:
- *	allowsEditing: set to true to allow the user to edit the contact - currently not supported
- */
-- (void)displayContact:(CDVInvokedUrlCommand*)command;
-
-/*
- * chooseContact
- *
- * arguments:
- *	1: this is the javascript function that will be called with the contact data as a JSON object (as the first param)
- * options:
- *	allowsEditing: set to true to not choose the contact, but to edit it in the iPhone contact editor
- */
-- (void)chooseContact:(CDVInvokedUrlCommand*)command;
-
-- (void)newPersonViewController:(ABNewPersonViewController*)newPersonViewController didCompleteWithNewPerson:(ABRecordRef)person;
-- (BOOL)personViewController:(ABPersonViewController*)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person
-                    property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue;
-
-/*
- * search - searches for contacts.  Only person records are currently supported.
- *
- * arguments:
- *  1: successcallback - this is the javascript function that will be called with the array of found contacts
- *  2:  errorCallback - optional javascript function to be called in the event of an error with an error code.
- * options:  dictionary containing ContactFields and ContactFindOptions
- *	fields - ContactFields array
- *  findOptions - ContactFindOptions object as dictionary
- *
- */
-- (void)search:(CDVInvokedUrlCommand*)command;
-
-/*
- * save - saves a new contact or updates and existing contact
- *
- * arguments:
- *  1: success callback - this is the javascript function that will be called with the JSON representation of the saved contact
- *		search calls a fixed navigator.service.contacts._findCallback which then calls the success callback stored before making the call into obj-c
- */
-- (void)save:(CDVInvokedUrlCommand*)command;
-
-/*
- * remove - removes a contact from the address book
- *
- * arguments:
- *  1:  1: successcallback - this is the javascript function that will be called with a (now) empty contact object
- *
- * options:  dictionary containing Contact object to remove
- *	contact - Contact object as dictionary
- */
-- (void)remove:(CDVInvokedUrlCommand*)command;
-
-// - (void) dealloc;
-
-@end
-
-@interface CDVContactsPicker : ABPeoplePickerNavigationController
-{
-    BOOL allowsEditing;
-    NSString* callbackId;
-    NSDictionary* options;
-    NSDictionary* pickedContactDictionary;
-}
-
-@property BOOL allowsEditing;
-@property (copy) NSString* callbackId;
-@property (nonatomic, strong) NSDictionary* options;
-@property (nonatomic, strong) NSDictionary* pickedContactDictionary;
-
-@end
-
-@interface CDVNewContactsController : ABNewPersonViewController
-{
-    NSString* callbackId;
-}
-@property (copy) NSString* callbackId;
-@end
-
-/* ABPersonViewController does not have any UI to dismiss.  Adding navigationItems to it does not work properly,  the navigationItems are lost when the app goes into the background.
-    The solution was to create an empty NavController in front of the ABPersonViewController. This
-    causes the ABPersonViewController to have a back button. By subclassing the ABPersonViewController,
-    we can override viewWillDisappear and take down the entire NavigationController at that time.
- */
-@interface CDVDisplayContactViewController : ABPersonViewController
-{}
-@property (nonatomic, strong) CDVPlugin* contactsPlugin;
-
-@end
-@interface CDVAddressBookAccessError : NSObject
-{}
-@property (assign) CDVContactError errorCode;
-- (CDVAddressBookAccessError*)initWithCode:(CDVContactError)code;
-@end
-
-typedef void (^ CDVAddressBookWorkerBlock)(
-    ABAddressBookRef         addressBook,
-    CDVAddressBookAccessError* error
-    );
-@interface CDVAddressBookHelper : NSObject
-{}
-
-- (void)createAddressBook:(CDVAddressBookWorkerBlock)workerBlock;
-@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/b3a1ea79/CordovaLib/Classes/CDVContacts.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVContacts.m b/CordovaLib/Classes/CDVContacts.m
deleted file mode 100644
index 40c038e..0000000
--- a/CordovaLib/Classes/CDVContacts.m
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-
-#import "CDVContacts.h"
-#import <UIKit/UIKit.h>
-#import "NSArray+Comparisons.h"
-#import "NSDictionary+Extensions.h"
-
-@implementation CDVContactsPicker
-
-@synthesize allowsEditing;
-@synthesize callbackId;
-@synthesize options;
-@synthesize pickedContactDictionary;
-
-@end
-@implementation CDVNewContactsController
-
-@synthesize callbackId;
-
-@end
-
-@implementation CDVContacts
-
-// no longer used since code gets AddressBook for each operation.
-// If address book changes during save or remove operation, may get error but not much we can do about it
-// If address book changes during UI creation, display or edit, we don't control any saves so no need for callback
-
-/*void addressBookChanged(ABAddressBookRef addressBook, CFDictionaryRef info, void* context)
-{
-    // note that this function is only called when another AddressBook instance modifies
-    // the address book, not the current one. For example, through an OTA MobileMe sync
-    Contacts* contacts = (Contacts*)context;
-    [contacts addressBookDirty];
-}*/
-
-- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView
-{
-    self = (CDVContacts*)[super initWithWebView:(UIWebView*)theWebView];
-
-    /*if (self) {
-        addressBook = ABAddressBookCreate();
-        ABAddressBookRegisterExternalChangeCallback(addressBook, addressBookChanged, self);
-    }*/
-
-    return self;
-}
-
-// overridden to clean up Contact statics
-- (void)onAppTerminate
-{
-    // NSLog(@"Contacts::onAppTerminate");
-}
-
-// iPhone only method to create a new contact through the GUI
-- (void)newContact:(CDVInvokedUrlCommand*)command
-{
-    NSString* callbackId = command.callbackId;
-
-    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);
-
-        npController.newPersonViewDelegate = self;
-        npController.callbackId = callbackId;
-
-        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];
-        }
-    }];
-}
-
-- (void)newPersonViewController:(ABNewPersonViewController*)newPersonViewController didCompleteWithNewPerson:(ABRecordRef)person
-{
-    ABRecordID recordId = kABRecordInvalidID;
-    CDVNewContactsController* newCP = (CDVNewContactsController*)newPersonViewController;
-    NSString* callbackId = newCP.callbackId;
-
-    if (person != NULL) {
-        // return the contact id
-        recordId = ABRecordGetRecordID(person);
-    }
-
-    if ([newPersonViewController respondsToSelector:@selector(presentingViewController)]) {
-        [[newPersonViewController presentingViewController] dismissViewControllerAnimated:YES completion:nil];
-    } else {
-        [[newPersonViewController parentViewController] dismissModalViewControllerAnimated:YES];
-    }
-
-    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:recordId];
-    [self.commandDelegate sendPluginResult:result callbackId:callbackId];
-}
-
-- (void)displayContact:(CDVInvokedUrlCommand*)command
-{
-    NSString* callbackId = command.callbackId;
-    ABRecordID recordID = [[command.arguments objectAtIndex:0] intValue];
-    NSDictionary* options = [command.arguments objectAtIndex:1 withDefault:[NSNull null]];
-    bool bEdit = [options isKindOfClass:[NSNull class]] ? false : [options existsValue:@"true" forKey:@"allowsEditing"];
-
-    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;
-
-            // create this so DisplayContactViewController will have a "back" button.
-            UIViewController* parentController = [[UIViewController alloc] init];
-            UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:parentController];
-
-            [navController pushViewController:personController animated:YES];
-
-            if ([self.viewController respondsToSelector:@selector(presentViewController:::)]) {
-                [self.viewController presentViewController:navController animated:YES completion:nil];
-            } else {
-                [self.viewController presentModalViewController:navController 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];
-            }
-        } 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
-                    property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue
-{
-    return YES;
-}
-
-- (void)chooseContact:(CDVInvokedUrlCommand*)command
-{
-    NSString* callbackId = command.callbackId;
-    NSDictionary* options = [command.arguments objectAtIndex:0 withDefault:[NSNull null]];
-
-    CDVContactsPicker* pickerController = [[CDVContactsPicker alloc] init];
-
-    pickerController.peoplePickerDelegate = self;
-    pickerController.callbackId = callbackId;
-    pickerController.options = options;
-    pickerController.pickedContactDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:kABRecordInvalidID], kW3ContactId, nil];
-    pickerController.allowsEditing = (BOOL)[options existsValue : @"true" forKey : @"allowsEditing"];
-
-    if ([self.viewController respondsToSelector:@selector(presentViewController:::)]) {
-        [self.viewController presentViewController:pickerController animated:YES completion:nil];
-    } else {
-        [self.viewController presentModalViewController:pickerController animated:YES];
-    }
-}
-
-- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker
-      shouldContinueAfterSelectingPerson:(ABRecordRef)person
-{
-    CDVContactsPicker* picker = (CDVContactsPicker*)peoplePicker;
-    NSNumber* pickedId = [NSNumber numberWithInt:ABRecordGetRecordID(person)];
-
-    if (picker.allowsEditing) {
-        ABPersonViewController* personController = [[ABPersonViewController alloc] init];
-        personController.displayedPerson = person;
-        personController.personViewDelegate = self;
-        personController.allowsEditing = picker.allowsEditing;
-        // store id so can get info in peoplePickerNavigationControllerDidCancel
-        picker.pickedContactDictionary = [NSDictionary dictionaryWithObjectsAndKeys:pickedId, kW3ContactId, nil];
-
-        [peoplePicker pushViewController:personController animated:YES];
-    } else {
-        // Retrieve and return pickedContact information
-        CDVContact* pickedContact = [[CDVContact alloc] initFromABRecord:(ABRecordRef)person];
-        NSArray* fields = [picker.options objectForKey:@"fields"];
-        NSDictionary* returnFields = [[CDVContact class] calcReturnFields:fields];
-        picker.pickedContactDictionary = [pickedContact toDictionary:returnFields];
-
-        CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:picker.pickedContactDictionary];
-        [self.commandDelegate sendPluginResult:result callbackId:picker.callbackId];
-
-        if ([picker respondsToSelector:@selector(presentingViewController)]) {
-            [[picker presentingViewController] dismissViewControllerAnimated:YES completion:nil];
-        } else {
-            [[picker parentViewController] dismissModalViewControllerAnimated:YES];
-        }
-    }
-    return NO;
-}
-
-- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker
-      shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
-{
-    return YES;
-}
-
-- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController*)peoplePicker
-{
-    // return contactId or invalid if none picked
-    CDVContactsPicker* picker = (CDVContactsPicker*)peoplePicker;
-
-    if (picker.allowsEditing) {
-        // get the info after possible edit
-        // if we got this far, user has already approved/ disapproved addressBook access
-        ABAddressBookRef addrBook = nil;
-#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000
-            if (&ABAddressBookCreateWithOptions != NULL) {
-                addrBook = ABAddressBookCreateWithOptions(NULL, NULL);
-            } else
-#endif
-        {
-            // iOS 4 & 5
-            addrBook = ABAddressBookCreate();
-        }
-        ABRecordRef person = ABAddressBookGetPersonWithRecordID(addrBook, [[picker.pickedContactDictionary objectForKey:kW3ContactId] integerValue]);
-        if (person) {
-            CDVContact* pickedContact = [[CDVContact alloc] initFromABRecord:(ABRecordRef)person];
-            NSArray* fields = [picker.options objectForKey:@"fields"];
-            NSDictionary* returnFields = [[CDVContact class] calcReturnFields:fields];
-            picker.pickedContactDictionary = [pickedContact toDictionary:returnFields];
-        }
-        CFRelease(addrBook);
-    }
-    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:picker.pickedContactDictionary];
-    [self.commandDelegate sendPluginResult:result callbackId:picker.callbackId];
-
-    if ([peoplePicker respondsToSelector:@selector(presentingViewController)]) {
-        [[peoplePicker presentingViewController] dismissViewControllerAnimated:YES completion:nil];
-    } else {
-        [[peoplePicker parentViewController] dismissModalViewControllerAnimated:YES];
-    }
-}
-
-- (void)search:(CDVInvokedUrlCommand*)command
-{
-    NSString* callbackId = command.callbackId;
-    NSArray* fields = [command.arguments objectAtIndex:0];
-    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;
-            }
-
-            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;
-                    }
-                }
-            }
-            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];
-                    }
-                }
-            }
-            // 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;
-}
-
-- (void)save:(CDVInvokedUrlCommand*)command
-{
-    NSString* callbackId = command.callbackId;
-    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
-
-    [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;
-}
-
-@end
-
-/* ABPersonViewController does not have any UI to dismiss.  Adding navigationItems to it does not work properly
- * The navigationItems are lost when the app goes into the background.  The solution was to create an empty
- * NavController in front of the ABPersonViewController. This will cause the ABPersonViewController to have a back button. By subclassing the ABPersonViewController, we can override viewDidDisappear and take down the entire NavigationController.
- */
-@implementation CDVDisplayContactViewController
-@synthesize contactsPlugin;
-
-- (void)viewWillDisappear:(BOOL)animated
-{
-    [super viewWillDisappear:animated];
-
-    if ([self respondsToSelector:@selector(presentingViewController)]) {
-        [[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
-    } else {
-        [[self parentViewController] dismissModalViewControllerAnimated:YES];
-    }
-}
-
-@end
-@implementation CDVAddressBookAccessError
-
-@synthesize errorCode;
-
-- (CDVAddressBookAccessError*)initWithCode:(CDVContactError)code
-{
-    self = [super init];
-    if (self) {
-        self.errorCode = code;
-    }
-    return self;
-}
-
-@end
-
-@implementation CDVAddressBookHelper
-
-/**
- * NOTE: workerBlock is responsible for releasing the addressBook that is passed to it
- */
-- (void)createAddressBook:(CDVAddressBookWorkerBlock)workerBlock
-{
-    // TODO: this probably should be reworked - seems like the workerBlock can just create and release its own AddressBook,
-    // and also this important warning from (http://developer.apple.com/library/ios/#documentation/ContactData/Conceptual/AddressBookProgrammingGuideforiPhone/Chapters/BasicObjects.html):
-    // "Important: Instances of ABAddressBookRef cannot be used by multiple threads. Each thread must make its own instance."
-    ABAddressBookRef addressBook;
-
-#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000
-        if (&ABAddressBookCreateWithOptions != NULL) {
-            CFErrorRef error = nil;
-            // CFIndex status = ABAddressBookGetAuthorizationStatus();
-            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(), ^{
-                        if (error) {
-                            workerBlock(NULL, [[CDVAddressBookAccessError alloc] initWithCode:UNKNOWN_ERROR]);
-                        } else if (!granted) {
-                            workerBlock(NULL, [[CDVAddressBookAccessError alloc] initWithCode:PERMISSION_DENIED_ERROR]);
-                        } else {
-                            // access granted
-                            workerBlock(addressBook, [[CDVAddressBookAccessError alloc] initWithCode:UNKNOWN_ERROR]);
-                        }
-                    });
-                });
-        } else
-#endif
-    {
-        // iOS 4 or 5 no checks needed
-        addressBook = ABAddressBookCreate();
-        workerBlock(addressBook, NULL);
-    }
-}
-
-@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/b3a1ea79/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/CordovaLib/CordovaLib.xcodeproj/project.pbxproj b/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
index 5e0f67a..6accb9e 100644
--- a/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
+++ b/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
@@ -7,8 +7,6 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		1F3C04CE12BC247D004F9E10 /* CDVContact.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F3C04CC12BC247D004F9E10 /* CDVContact.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		1F3C04CF12BC247D004F9E10 /* CDVContact.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F3C04CD12BC247D004F9E10 /* CDVContact.m */; };
 		1F584B9B1385A28A00ED25E8 /* CDVCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F584B991385A28900ED25E8 /* CDVCapture.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		1F584B9C1385A28A00ED25E8 /* CDVCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F584B9A1385A28900ED25E8 /* CDVCapture.m */; };
 		1F92F4A01314023E0046367C /* CDVPluginResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F92F49E1314023E0046367C /* CDVPluginResult.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -49,8 +47,6 @@
 		8887FD671090FBE7009987E8 /* CDVCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD271090FBE7009987E8 /* CDVCamera.m */; };
 		8887FD681090FBE7009987E8 /* NSDictionary+Extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD281090FBE7009987E8 /* NSDictionary+Extensions.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		8887FD691090FBE7009987E8 /* NSDictionary+Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD291090FBE7009987E8 /* NSDictionary+Extensions.m */; };
-		8887FD6A1090FBE7009987E8 /* CDVContacts.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD2A1090FBE7009987E8 /* CDVContacts.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		8887FD6B1090FBE7009987E8 /* CDVContacts.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD2B1090FBE7009987E8 /* CDVContacts.m */; };
 		8887FD701090FBE7009987E8 /* CDVFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD301090FBE7009987E8 /* CDVFile.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		8887FD711090FBE7009987E8 /* CDVFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD311090FBE7009987E8 /* CDVFile.m */; };
 		8887FD741090FBE7009987E8 /* CDVInvokedUrlCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD341090FBE7009987E8 /* CDVInvokedUrlCommand.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -82,8 +78,6 @@
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
-		1F3C04CC12BC247D004F9E10 /* CDVContact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVContact.h; path = Classes/CDVContact.h; sourceTree = "<group>"; };
-		1F3C04CD12BC247D004F9E10 /* CDVContact.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVContact.m; path = Classes/CDVContact.m; sourceTree = "<group>"; };
 		1F584B991385A28900ED25E8 /* CDVCapture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCapture.h; path = Classes/CDVCapture.h; sourceTree = "<group>"; };
 		1F584B9A1385A28900ED25E8 /* CDVCapture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCapture.m; path = Classes/CDVCapture.m; sourceTree = "<group>"; };
 		1F92F49E1314023E0046367C /* CDVPluginResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVPluginResult.h; path = Classes/CDVPluginResult.h; sourceTree = "<group>"; };
@@ -138,8 +132,6 @@
 		8887FD271090FBE7009987E8 /* CDVCamera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCamera.m; path = Classes/CDVCamera.m; sourceTree = "<group>"; };
 		8887FD281090FBE7009987E8 /* NSDictionary+Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+Extensions.h"; path = "Classes/NSDictionary+Extensions.h"; sourceTree = "<group>"; };
 		8887FD291090FBE7009987E8 /* NSDictionary+Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+Extensions.m"; path = "Classes/NSDictionary+Extensions.m"; sourceTree = "<group>"; };
-		8887FD2A1090FBE7009987E8 /* CDVContacts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVContacts.h; path = Classes/CDVContacts.h; sourceTree = "<group>"; };
-		8887FD2B1090FBE7009987E8 /* CDVContacts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVContacts.m; path = Classes/CDVContacts.m; sourceTree = "<group>"; };
 		8887FD301090FBE7009987E8 /* CDVFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVFile.h; path = Classes/CDVFile.h; sourceTree = "<group>"; };
 		8887FD311090FBE7009987E8 /* CDVFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVFile.m; path = Classes/CDVFile.m; sourceTree = "<group>"; };
 		8887FD341090FBE7009987E8 /* CDVInvokedUrlCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVInvokedUrlCommand.h; path = Classes/CDVInvokedUrlCommand.h; sourceTree = "<group>"; };
@@ -273,10 +265,6 @@
 				68B7516A16FD18190076A8B4 /* CDVExif.h */,
 				68B7516B16FD18190076A8B4 /* CDVJpegHeaderWriter.h */,
 				68B7516C16FD18190076A8B4 /* CDVJpegHeaderWriter.m */,
-				1F3C04CC12BC247D004F9E10 /* CDVContact.h */,
-				1F3C04CD12BC247D004F9E10 /* CDVContact.m */,
-				8887FD2A1090FBE7009987E8 /* CDVContacts.h */,
-				8887FD2B1090FBE7009987E8 /* CDVContacts.m */,
 				EB80C2AA15DEA63D004D9E7B /* CDVEcho.h */,
 				EB80C2AB15DEA63D004D9E7B /* CDVEcho.m */,
 				8887FD301090FBE7009987E8 /* CDVFile.h */,
@@ -343,13 +331,11 @@
 				68B7516E16FD18190076A8B4 /* CDVJpegHeaderWriter.h in Headers */,
 				8887FD661090FBE7009987E8 /* CDVCamera.h in Headers */,
 				8887FD681090FBE7009987E8 /* NSDictionary+Extensions.h in Headers */,
-				8887FD6A1090FBE7009987E8 /* CDVContacts.h in Headers */,
 				8887FD701090FBE7009987E8 /* CDVFile.h in Headers */,
 				8887FD741090FBE7009987E8 /* CDVInvokedUrlCommand.h in Headers */,
 				8887FD8F1090FBE7009987E8 /* NSData+Base64.h in Headers */,
 				8887FD9D1090FBE7009987E8 /* CDVReachability.h in Headers */,
 				8887FD9F1090FBE7009987E8 /* CDVSound.h in Headers */,
-				1F3C04CE12BC247D004F9E10 /* CDVContact.h in Headers */,
 				1F92F4A01314023E0046367C /* CDVPluginResult.h in Headers */,
 				C937A4561337599E002C4C79 /* CDVFileTransfer.h in Headers */,
 				307A8F9E1385A2EC00E43782 /* CDVConnection.h in Headers */,
@@ -437,13 +423,11 @@
 			files = (
 				8887FD671090FBE7009987E8 /* CDVCamera.m in Sources */,
 				8887FD691090FBE7009987E8 /* NSDictionary+Extensions.m in Sources */,
-				8887FD6B1090FBE7009987E8 /* CDVContacts.m in Sources */,
 				8887FD711090FBE7009987E8 /* CDVFile.m in Sources */,
 				8887FD751090FBE7009987E8 /* CDVInvokedUrlCommand.m in Sources */,
 				8887FD901090FBE7009987E8 /* NSData+Base64.m in Sources */,
 				8887FD9E1090FBE7009987E8 /* CDVReachability.m in Sources */,
 				8887FDA01090FBE7009987E8 /* CDVSound.m in Sources */,
-				1F3C04CF12BC247D004F9E10 /* CDVContact.m in Sources */,
 				1F92F4A11314023E0046367C /* CDVPluginResult.m in Sources */,
 				C937A4571337599E002C4C79 /* CDVFileTransfer.m in Sources */,
 				307A8F9F1385A2EC00E43782 /* CDVConnection.m in Sources */,

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/b3a1ea79/bin/templates/project/__TESTING__/config.xml
----------------------------------------------------------------------
diff --git a/bin/templates/project/__TESTING__/config.xml b/bin/templates/project/__TESTING__/config.xml
index 1bf2536..d2f5e29 100644
--- a/bin/templates/project/__TESTING__/config.xml
+++ b/bin/templates/project/__TESTING__/config.xml
@@ -44,9 +44,6 @@
     <feature name="Camera">
       <param name="ios-package" value="CDVCamera"/>
     </feature>
-    <feature name="Contacts">
-      <param name="ios-package" value="CDVContacts"/>
-    </feature>
     <feature name="File">
       <param name="ios-package"  value="CDVFile"/>
     </feature>


[3/3] ios commit: updated template to arc

Posted by st...@apache.org.
updated template to arc


Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/6189baaf
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/6189baaf
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/6189baaf

Branch: refs/heads/3.0.0
Commit: 6189baaf624634f4de5a99bc51d3f07a39c49373
Parents: b3a1ea7
Author: Steven Gill <st...@gmail.com>
Authored: Wed May 22 15:20:32 2013 -0700
Committer: Steven Gill <st...@gmail.com>
Committed: Wed May 22 15:20:32 2013 -0700

----------------------------------------------------------------------
 .../project/__TESTING__.xcodeproj/project.pbxproj  |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/6189baaf/bin/templates/project/__TESTING__.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/bin/templates/project/__TESTING__.xcodeproj/project.pbxproj b/bin/templates/project/__TESTING__.xcodeproj/project.pbxproj
index 6b81e10..951b069 100755
--- a/bin/templates/project/__TESTING__.xcodeproj/project.pbxproj
+++ b/bin/templates/project/__TESTING__.xcodeproj/project.pbxproj
@@ -481,7 +481,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
-				CLANG_ENABLE_OBJC_ARC = NO;
+				CLANG_ENABLE_OBJC_ARC = YES;
 				COPY_PHASE_STRIP = NO;
 				GCC_DYNAMIC_NO_PIC = NO;
 				GCC_OPTIMIZATION_LEVEL = 0;
@@ -500,7 +500,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
-				CLANG_ENABLE_OBJC_ARC = NO;
+				CLANG_ENABLE_OBJC_ARC = YES;
 				COPY_PHASE_STRIP = YES;
 				GCC_PRECOMPILE_PREFIX_HEADER = YES;
 				GCC_PREFIX_HEADER = "__TESTING__/__TESTING__-Prefix.pch";


[2/3] ios commit: removed contact code

Posted by st...@apache.org.
removed contact code


Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/b3a1ea79
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/b3a1ea79
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/b3a1ea79

Branch: refs/heads/3.0.0
Commit: b3a1ea7973a0d19f11c2a6f4fe3d33095aab8123
Parents: cec7874
Author: Steven Gill <st...@gmail.com>
Authored: Wed May 22 13:54:57 2013 -0700
Committer: Steven Gill <st...@gmail.com>
Committed: Wed May 22 13:54:57 2013 -0700

----------------------------------------------------------------------
 CordovaLib/Classes/CDV.h                        |    2 -
 CordovaLib/Classes/CDVContact.h                 |  136 --
 CordovaLib/Classes/CDVContact.m                 | 1752 ------------------
 CordovaLib/Classes/CDVContacts.h                |  151 --
 CordovaLib/Classes/CDVContacts.m                |  592 ------
 CordovaLib/CordovaLib.xcodeproj/project.pbxproj |   16 -
 bin/templates/project/__TESTING__/config.xml    |    3 -
 7 files changed, 0 insertions(+), 2652 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/b3a1ea79/CordovaLib/Classes/CDV.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDV.h b/CordovaLib/Classes/CDV.h
index e9c8e16..9da128a 100644
--- a/CordovaLib/Classes/CDV.h
+++ b/CordovaLib/Classes/CDV.h
@@ -28,8 +28,6 @@
 #import "CDVCamera.h"
 #import "CDVCapture.h"
 #import "CDVConnection.h"
-#import "CDVContact.h"
-#import "CDVContacts.h"
 #import "CDVDebug.h"
 #import "CDVDevice.h"
 #import "CDVFile.h"

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/b3a1ea79/CordovaLib/Classes/CDVContact.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVContact.h b/CordovaLib/Classes/CDVContact.h
deleted file mode 100644
index 5187efc..0000000
--- a/CordovaLib/Classes/CDVContact.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-
-#import <Foundation/Foundation.h>
-#import <AddressBook/ABAddressBook.h>
-#import <AddressBookUI/AddressBookUI.h>
-
-enum CDVContactError {
-    UNKNOWN_ERROR = 0,
-    INVALID_ARGUMENT_ERROR = 1,
-    TIMEOUT_ERROR = 2,
-    PENDING_OPERATION_ERROR = 3,
-    IO_ERROR = 4,
-    NOT_SUPPORTED_ERROR = 5,
-    PERMISSION_DENIED_ERROR = 20
-};
-typedef NSUInteger CDVContactError;
-
-@interface CDVContact : NSObject {
-    ABRecordRef record;         // the ABRecord associated with this contact
-    NSDictionary* returnFields; // dictionary of fields to return when performing search
-}
-
-@property (nonatomic, assign) ABRecordRef record;
-@property (nonatomic, strong) NSDictionary* returnFields;
-
-+ (NSDictionary*)defaultABtoW3C;
-+ (NSDictionary*)defaultW3CtoAB;
-+ (NSSet*)defaultW3CtoNull;
-+ (NSDictionary*)defaultObjectAndProperties;
-+ (NSDictionary*)defaultFields;
-
-+ (NSDictionary*)calcReturnFields:(NSArray*)fields;
-- (id)init;
-- (id)initFromABRecord:(ABRecordRef)aRecord;
-- (bool)setFromContactDict:(NSDictionary*)aContact asUpdate:(BOOL)bUpdate;
-
-+ (BOOL)needsConversion:(NSString*)W3Label;
-+ (CFStringRef)convertContactTypeToPropertyLabel:(NSString*)label;
-+ (NSString*)convertPropertyLabelToContactType:(NSString*)label;
-+ (BOOL)isValidW3ContactType:(NSString*)label;
-- (bool)setValue:(id)aValue forProperty:(ABPropertyID)aProperty inRecord:(ABRecordRef)aRecord asUpdate:(BOOL)bUpdate;
-
-- (NSDictionary*)toDictionary:(NSDictionary*)withFields;
-- (NSNumber*)getDateAsNumber:(ABPropertyID)datePropId;
-- (NSObject*)extractName;
-- (NSObject*)extractMultiValue:(NSString*)propertyId;
-- (NSObject*)extractAddresses;
-- (NSObject*)extractIms;
-- (NSObject*)extractOrganizations;
-- (NSObject*)extractPhotos;
-
-- (NSMutableDictionary*)translateW3Dict:(NSDictionary*)dict forProperty:(ABPropertyID)prop;
-- (bool)setMultiValueStrings:(NSArray*)fieldArray forProperty:(ABPropertyID)prop inRecord:(ABRecordRef)person asUpdate:(BOOL)bUpdate;
-- (bool)setMultiValueDictionary:(NSArray*)array forProperty:(ABPropertyID)prop inRecord:(ABRecordRef)person asUpdate:(BOOL)bUpdate;
-- (ABMultiValueRef)allocStringMultiValueFromArray:array;
-- (ABMultiValueRef)allocDictMultiValueFromArray:array forProperty:(ABPropertyID)prop;
-- (BOOL)foundValue:(NSString*)testValue inFields:(NSDictionary*)searchFields;
-- (BOOL)testStringValue:(NSString*)testValue forW3CProperty:(NSString*)property;
-- (BOOL)testDateValue:(NSString*)testValue forW3CProperty:(NSString*)property;
-- (BOOL)searchContactFields:(NSArray*)fields forMVStringProperty:(ABPropertyID)propId withValue:testValue;
-- (BOOL)testMultiValueStrings:(NSString*)testValue forProperty:(ABPropertyID)propId ofType:(NSString*)type;
-- (NSArray*)valuesForProperty:(ABPropertyID)propId inRecord:(ABRecordRef)aRecord;
-- (NSArray*)labelsForProperty:(ABPropertyID)propId inRecord:(ABRecordRef)aRecord;
-- (BOOL)searchContactFields:(NSArray*)fields forMVDictionaryProperty:(ABPropertyID)propId withValue:(NSString*)testValue;
-
-@end
-
-// generic ContactField types
-#define kW3ContactFieldType @"type"
-#define kW3ContactFieldValue @"value"
-#define kW3ContactFieldPrimary @"pref"
-// Various labels for ContactField types
-#define kW3ContactWorkLabel @"work"
-#define kW3ContactHomeLabel @"home"
-#define kW3ContactOtherLabel @"other"
-#define kW3ContactPhoneFaxLabel @"fax"
-#define kW3ContactPhoneMobileLabel @"mobile"
-#define kW3ContactPhonePagerLabel @"pager"
-#define kW3ContactUrlBlog @"blog"
-#define kW3ContactUrlProfile @"profile"
-#define kW3ContactImAIMLabel @"aim"
-#define kW3ContactImICQLabel @"icq"
-#define kW3ContactImMSNLabel @"msn"
-#define kW3ContactImYahooLabel @"yahoo"
-#define kW3ContactFieldId @"id"
-// special translation for IM field value and type
-#define kW3ContactImType @"type"
-#define kW3ContactImValue @"value"
-
-// Contact object
-#define kW3ContactId @"id"
-#define kW3ContactName @"name"
-#define kW3ContactFormattedName @"formatted"
-#define kW3ContactGivenName @"givenName"
-#define kW3ContactFamilyName @"familyName"
-#define kW3ContactMiddleName @"middleName"
-#define kW3ContactHonorificPrefix @"honorificPrefix"
-#define kW3ContactHonorificSuffix @"honorificSuffix"
-#define kW3ContactDisplayName @"displayName"
-#define kW3ContactNickname @"nickname"
-#define kW3ContactPhoneNumbers @"phoneNumbers"
-#define kW3ContactAddresses @"addresses"
-#define kW3ContactAddressFormatted @"formatted"
-#define kW3ContactStreetAddress @"streetAddress"
-#define kW3ContactLocality @"locality"
-#define kW3ContactRegion @"region"
-#define kW3ContactPostalCode @"postalCode"
-#define kW3ContactCountry @"country"
-#define kW3ContactEmails @"emails"
-#define kW3ContactIms @"ims"
-#define kW3ContactOrganizations @"organizations"
-#define kW3ContactOrganizationName @"name"
-#define kW3ContactTitle @"title"
-#define kW3ContactDepartment @"department"
-#define kW3ContactBirthday @"birthday"
-#define kW3ContactNote @"note"
-#define kW3ContactPhotos @"photos"
-#define kW3ContactCategories @"categories"
-#define kW3ContactUrls @"urls"

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/b3a1ea79/CordovaLib/Classes/CDVContact.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVContact.m b/CordovaLib/Classes/CDVContact.m
deleted file mode 100644
index 3844525..0000000
--- a/CordovaLib/Classes/CDVContact.m
+++ /dev/null
@@ -1,1752 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-
-#import "CDVContact.h"
-#import "NSDictionary+Extensions.h"
-
-#define DATE_OR_NULL(dateObj) ((aDate != nil) ? (id)([aDate descriptionWithLocale:[NSLocale currentLocale]]) : (id)([NSNull null]))
-#define IS_VALID_VALUE(value) ((value != nil) && (![value isKindOfClass:[NSNull class]]))
-
-static NSDictionary* org_apache_cordova_contacts_W3CtoAB = nil;
-static NSDictionary* org_apache_cordova_contacts_ABtoW3C = nil;
-static NSSet* org_apache_cordova_contacts_W3CtoNull = nil;
-static NSDictionary* org_apache_cordova_contacts_objectAndProperties = nil;
-static NSDictionary* org_apache_cordova_contacts_defaultFields = nil;
-
-@implementation CDVContact : NSObject
-
-                             @synthesize returnFields;
-
-- (id)init
-{
-    if ((self = [super init]) != nil) {
-        ABRecordRef rec = ABPersonCreate();
-        self.record = rec;
-        if (rec) {
-            CFRelease(rec);
-        }
-    }
-    return self;
-}
-
-- (id)initFromABRecord:(ABRecordRef)aRecord
-{
-    if ((self = [super init]) != nil) {
-        self.record = aRecord;
-    }
-    return self;
-}
-
-/* synthesize 'record' ourselves to have retain properties for CF types */
-
-- (void)setRecord:(ABRecordRef)aRecord
-{
-    if (record != NULL) {
-        CFRelease(record);
-    }
-    if (aRecord != NULL) {
-        record = CFRetain(aRecord);
-    }
-}
-
-- (ABRecordRef)record
-{
-    return record;
-}
-
-/* Rather than creating getters and setters for each AddressBook (AB) Property, generic methods are used to deal with
- * simple properties,  MultiValue properties( phone numbers and emails) and MultiValueDictionary properties (Ims and addresses).
- * The dictionaries below are used to translate between the W3C identifiers and the AB properties.   Using the dictionaries,
- * allows looping through sets of properties to extract from or set into the W3C dictionary to/from the ABRecord.
- */
-
-/* The two following dictionaries translate between W3C properties and AB properties.  It currently mixes both
- * Properties (kABPersonAddressProperty for example) and Strings (kABPersonAddressStreetKey) so users should be aware of
- * what types of values are expected.
- * a bit.
-*/
-+ (NSDictionary*)defaultABtoW3C
-{
-    if (org_apache_cordova_contacts_ABtoW3C == nil) {
-        org_apache_cordova_contacts_ABtoW3C = [NSDictionary dictionaryWithObjectsAndKeys:
-            kW3ContactNickname, [NSNumber numberWithInt:kABPersonNicknameProperty],
-            kW3ContactGivenName, [NSNumber numberWithInt:kABPersonFirstNameProperty],
-            kW3ContactFamilyName, [NSNumber numberWithInt:kABPersonLastNameProperty],
-            kW3ContactMiddleName, [NSNumber numberWithInt:kABPersonMiddleNameProperty],
-            kW3ContactHonorificPrefix, [NSNumber numberWithInt:kABPersonPrefixProperty],
-            kW3ContactHonorificSuffix, [NSNumber numberWithInt:kABPersonSuffixProperty],
-            kW3ContactPhoneNumbers, [NSNumber numberWithInt:kABPersonPhoneProperty],
-            kW3ContactAddresses, [NSNumber numberWithInt:kABPersonAddressProperty],
-            kW3ContactStreetAddress, kABPersonAddressStreetKey,
-            kW3ContactLocality, kABPersonAddressCityKey,
-            kW3ContactRegion, kABPersonAddressStateKey,
-            kW3ContactPostalCode, kABPersonAddressZIPKey,
-            kW3ContactCountry, kABPersonAddressCountryKey,
-            kW3ContactEmails, [NSNumber numberWithInt:kABPersonEmailProperty],
-            kW3ContactIms, [NSNumber numberWithInt:kABPersonInstantMessageProperty],
-            kW3ContactOrganizations, [NSNumber numberWithInt:kABPersonOrganizationProperty],
-            kW3ContactOrganizationName, [NSNumber numberWithInt:kABPersonOrganizationProperty],
-            kW3ContactTitle, [NSNumber numberWithInt:kABPersonJobTitleProperty],
-            kW3ContactDepartment, [NSNumber numberWithInt:kABPersonDepartmentProperty],
-            kW3ContactBirthday, [NSNumber numberWithInt:kABPersonBirthdayProperty],
-            kW3ContactUrls, [NSNumber numberWithInt:kABPersonURLProperty],
-            kW3ContactNote, [NSNumber numberWithInt:kABPersonNoteProperty],
-            nil];
-    }
-
-    return org_apache_cordova_contacts_ABtoW3C;
-}
-
-+ (NSDictionary*)defaultW3CtoAB
-{
-    if (org_apache_cordova_contacts_W3CtoAB == nil) {
-        org_apache_cordova_contacts_W3CtoAB = [NSDictionary dictionaryWithObjectsAndKeys:
-            [NSNumber numberWithInt:kABPersonNicknameProperty], kW3ContactNickname,
-            [NSNumber numberWithInt:kABPersonFirstNameProperty], kW3ContactGivenName,
-            [NSNumber numberWithInt:kABPersonLastNameProperty], kW3ContactFamilyName,
-            [NSNumber numberWithInt:kABPersonMiddleNameProperty], kW3ContactMiddleName,
-            [NSNumber numberWithInt:kABPersonPrefixProperty], kW3ContactHonorificPrefix,
-            [NSNumber numberWithInt:kABPersonSuffixProperty], kW3ContactHonorificSuffix,
-            [NSNumber numberWithInt:kABPersonPhoneProperty], kW3ContactPhoneNumbers,
-            [NSNumber numberWithInt:kABPersonAddressProperty], kW3ContactAddresses,
-            kABPersonAddressStreetKey, kW3ContactStreetAddress,
-            kABPersonAddressCityKey, kW3ContactLocality,
-            kABPersonAddressStateKey, kW3ContactRegion,
-            kABPersonAddressZIPKey, kW3ContactPostalCode,
-            kABPersonAddressCountryKey, kW3ContactCountry,
-            [NSNumber numberWithInt:kABPersonEmailProperty], kW3ContactEmails,
-            [NSNumber numberWithInt:kABPersonInstantMessageProperty], kW3ContactIms,
-            [NSNumber numberWithInt:kABPersonOrganizationProperty], kW3ContactOrganizations,
-            [NSNumber numberWithInt:kABPersonJobTitleProperty], kW3ContactTitle,
-            [NSNumber numberWithInt:kABPersonDepartmentProperty], kW3ContactDepartment,
-            [NSNumber numberWithInt:kABPersonBirthdayProperty], kW3ContactBirthday,
-            [NSNumber numberWithInt:kABPersonNoteProperty], kW3ContactNote,
-            [NSNumber numberWithInt:kABPersonURLProperty], kW3ContactUrls,
-            kABPersonInstantMessageUsernameKey, kW3ContactImValue,
-            kABPersonInstantMessageServiceKey, kW3ContactImType,
-            [NSNull null], kW3ContactFieldType,     /* include entries in dictionary to indicate ContactField properties */
-            [NSNull null], kW3ContactFieldValue,
-            [NSNull null], kW3ContactFieldPrimary,
-            [NSNull null], kW3ContactFieldId,
-            [NSNumber numberWithInt:kABPersonOrganizationProperty], kW3ContactOrganizationName,      /* careful, name is used multiple times*/
-            nil];
-    }
-    return org_apache_cordova_contacts_W3CtoAB;
-}
-
-+ (NSSet*)defaultW3CtoNull
-{
-    // these are values that have no AddressBook Equivalent OR have not been implemented yet
-    if (org_apache_cordova_contacts_W3CtoNull == nil) {
-        org_apache_cordova_contacts_W3CtoNull = [NSSet setWithObjects:kW3ContactDisplayName,
-            kW3ContactCategories, kW3ContactFormattedName, nil];
-    }
-    return org_apache_cordova_contacts_W3CtoNull;
-}
-
-/*
- *	The objectAndProperties dictionary contains the all of the properties of the W3C Contact Objects specified by the key
- *	Used in calcReturnFields, and various extract<Property> methods
- */
-+ (NSDictionary*)defaultObjectAndProperties
-{
-    if (org_apache_cordova_contacts_objectAndProperties == nil) {
-        org_apache_cordova_contacts_objectAndProperties = [NSDictionary dictionaryWithObjectsAndKeys:
-            [NSArray arrayWithObjects:kW3ContactGivenName, kW3ContactFamilyName,
-            kW3ContactMiddleName, kW3ContactHonorificPrefix, kW3ContactHonorificSuffix, kW3ContactFormattedName, nil], kW3ContactName,
-            [NSArray arrayWithObjects:kW3ContactStreetAddress, kW3ContactLocality, kW3ContactRegion,
-            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,
-            [NSArray arrayWithObjects:kW3ContactFieldType, kW3ContactFieldValue, kW3ContactFieldPrimary, nil], kW3ContactPhotos,
-            [NSArray arrayWithObjects:kW3ContactFieldType, kW3ContactFieldValue, kW3ContactFieldPrimary, nil], kW3ContactUrls,
-            [NSArray arrayWithObjects:kW3ContactImValue, kW3ContactImType, nil], kW3ContactIms,
-            nil];
-    }
-    return org_apache_cordova_contacts_objectAndProperties;
-}
-
-+ (NSDictionary*)defaultFields
-{
-    if (org_apache_cordova_contacts_defaultFields == nil) {
-        org_apache_cordova_contacts_defaultFields = [NSDictionary dictionaryWithObjectsAndKeys:
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactName], kW3ContactName,
-            [NSNull null], kW3ContactNickname,
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactAddresses], kW3ContactAddresses,
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactOrganizations], kW3ContactOrganizations,
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactPhoneNumbers], kW3ContactPhoneNumbers,
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactEmails], kW3ContactEmails,
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactIms], kW3ContactIms,
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactPhotos], kW3ContactPhotos,
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactUrls], kW3ContactUrls,
-            [NSNull null], kW3ContactBirthday,
-            [NSNull null], kW3ContactNote,
-            nil];
-    }
-    return org_apache_cordova_contacts_defaultFields;
-}
-
-/*  Translate W3C Contact data into ABRecordRef
- *
- *	New contact information comes in as a NSMutableDictionary.  All Null entries in Contact object are set
- *	as [NSNull null] in the dictionary when translating from the JSON input string of Contact data. However, if
- *  user did not set a value within a Contact object or sub-object (by not using the object constructor) some data
- *	may not exist.
- *  bUpdate = YES indicates this is a save of an existing record
- */
-- (bool)setFromContactDict:(NSDictionary*)aContact asUpdate:(BOOL)bUpdate
-{
-    if (![aContact isKindOfClass:[NSDictionary class]]) {
-        return FALSE; // can't do anything if no dictionary!
-    }
-
-    ABRecordRef person = self.record;
-    bool bSuccess = TRUE;
-    CFErrorRef error;
-
-    // set name info
-    // iOS doesn't have displayName - might have to pull parts from it to create name
-    bool bName = false;
-    NSDictionary* dict = [aContact valueForKey:kW3ContactName];
-    if ([dict isKindOfClass:[NSDictionary class]]) {
-        bName = true;
-        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
-                [self setValue:[dict valueForKey:i] forProperty:(ABPropertyID)[(NSNumber*)[[CDVContact defaultW3CtoAB] objectForKey:i] intValue]
-                      inRecord:person asUpdate:bUpdate];
-            }
-        }
-    }
-
-    id nn = [aContact valueForKey:kW3ContactNickname];
-    if (![nn isKindOfClass:[NSNull class]]) {
-        bName = true;
-        [self setValue:nn forProperty:kABPersonNicknameProperty inRecord:person asUpdate:bUpdate];
-    }
-    if (!bName) {
-        // if no name or nickname - try and use displayName as W3Contact must have displayName or ContactName
-        [self setValue:[aContact valueForKey:kW3ContactDisplayName] forProperty:kABPersonNicknameProperty
-              inRecord:person asUpdate:bUpdate];
-    }
-
-    // set phoneNumbers
-    // NSLog(@"setting phoneNumbers");
-    NSArray* array = [aContact valueForKey:kW3ContactPhoneNumbers];
-    if ([array isKindOfClass:[NSArray class]]) {
-        [self setMultiValueStrings:array forProperty:kABPersonPhoneProperty inRecord:person asUpdate:bUpdate];
-    }
-    // set Emails
-    // NSLog(@"setting emails");
-    array = [aContact valueForKey:kW3ContactEmails];
-    if ([array isKindOfClass:[NSArray class]]) {
-        [self setMultiValueStrings:array forProperty:kABPersonEmailProperty inRecord:person asUpdate:bUpdate];
-    }
-    // set Urls
-    // NSLog(@"setting urls");
-    array = [aContact valueForKey:kW3ContactUrls];
-    if ([array isKindOfClass:[NSArray class]]) {
-        [self setMultiValueStrings:array forProperty:kABPersonURLProperty inRecord:person asUpdate:bUpdate];
-    }
-
-    // set multivalue dictionary properties
-    // set addresses:  streetAddress, locality, region, postalCode, country
-    // set ims:  value = username, type = servicetype
-    // iOS addresses and im are a MultiValue Properties with label, value=dictionary of  info, and id
-    // NSLog(@"setting addresses");
-    error = nil;
-    array = [aContact valueForKey:kW3ContactAddresses];
-    if ([array isKindOfClass:[NSArray class]]) {
-        [self setMultiValueDictionary:array forProperty:kABPersonAddressProperty inRecord:person asUpdate:bUpdate];
-    }
-    // ims
-    // NSLog(@"setting ims");
-    array = [aContact valueForKey:kW3ContactIms];
-    if ([array isKindOfClass:[NSArray class]]) {
-        [self setMultiValueDictionary:array forProperty:kABPersonInstantMessageProperty inRecord:person asUpdate:bUpdate];
-    }
-
-    // organizations
-    // W3C ContactOrganization has pref, type, name, title, department
-    // iOS only supports name, title, department
-    // NSLog(@"setting organizations");
-    // TODO this may need work - should Organization information be removed when array is empty??
-    array = [aContact valueForKey:kW3ContactOrganizations];  // iOS only supports one organization - use first one
-    if ([array isKindOfClass:[NSArray class]]) {
-        BOOL bRemove = NO;
-        NSDictionary* dict = nil;
-        if ([array count] > 0) {
-            dict = [array objectAtIndex:0];
-        } else {
-            // remove the organization info entirely
-            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];
-        }
-    }
-    // add dates
-    // Dates come in as milliseconds in NSNumber Object
-    id ms = [aContact valueForKey:kW3ContactBirthday];
-    NSDate* aDate = nil;
-    if (ms && [ms isKindOfClass:[NSNumber class]]) {
-        double msValue = [ms doubleValue];
-        msValue = msValue / 1000;
-        aDate = [NSDate dateWithTimeIntervalSince1970:msValue];
-    }
-    if ((aDate != nil) || [ms isKindOfClass:[NSString class]]) {
-        [self setValue:aDate != nil ? aDate:ms forProperty:kABPersonBirthdayProperty inRecord:person asUpdate:bUpdate];
-    }
-    // don't update creation date
-    // modification date will get updated when save
-    // anniversary is removed from W3C Contact api Dec 9, 2010 spec - don't waste time on it yet
-
-    // kABPersonDateProperty
-
-    // kABPersonAnniversaryLabel
-
-    // iOS doesn't have gender - ignore
-    // note
-    [self setValue:[aContact valueForKey:kW3ContactNote] forProperty:kABPersonNoteProperty inRecord:person asUpdate:bUpdate];
-
-    // iOS doesn't have preferredName- ignore
-
-    // photo
-    array = [aContact valueForKey:kW3ContactPhotos];
-    if ([array isKindOfClass:[NSArray class]]) {
-        if (bUpdate && ([array count] == 0)) {
-            // remove photo
-            bSuccess = ABPersonRemoveImageData(person, &error);
-        } else if ([array count] > 0) {
-            NSDictionary* dict = [array objectAtIndex:0]; // currently only support one photo
-            if ([dict isKindOfClass:[NSDictionary class]]) {
-                id value = [dict objectForKey:kW3ContactFieldValue];
-                if ([value isKindOfClass:[NSString class]]) {
-                    if (bUpdate && ([value length] == 0)) {
-                        // remove the current image
-                        bSuccess = ABPersonRemoveImageData(person, &error);
-                    } else {
-                        // use this image
-                        // don't know if string is encoded or not so first unencode it then encode it again
-                        NSString* cleanPath = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
-                        NSURL* photoUrl = [NSURL URLWithString:[cleanPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
-                        // caller is responsible for checking for a connection, if no connection this will fail
-                        NSError* err = nil;
-                        NSData* data = nil;
-                        if (photoUrl) {
-                            data = [NSData dataWithContentsOfURL:photoUrl options:NSDataReadingUncached error:&err];
-                        }
-                        if (data && ([data length] > 0)) {
-                            bSuccess = ABPersonSetImageData(person, (__bridge CFDataRef)data, &error);
-                        }
-                        if (!data || !bSuccess) {
-                            NSLog(@"error setting contact image: %@", (err != nil ? [err localizedDescription] : @""));
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    // TODO WebURLs
-
-    // TODO timezone
-
-    return bSuccess;
-}
-
-/* Set item into an AddressBook Record for the specified property.
- * aValue - the value to set into the address book (code checks for null or [NSNull null]
- * aProperty - AddressBook property ID
- * aRecord - the record to update
- * bUpdate - whether this is a possible update vs a new entry
- * RETURN
- *	true - property was set (or input value as null)
- *	false - property was not set
- */
-- (bool)setValue:(id)aValue forProperty:(ABPropertyID)aProperty inRecord:(ABRecordRef)aRecord asUpdate:(BOOL)bUpdate
-{
-    bool bSuccess = true;  // if property was null, just ignore and return success
-    CFErrorRef error;
-
-    if (aValue && ![aValue isKindOfClass:[NSNull class]]) {
-        if (bUpdate && ([aValue isKindOfClass:[NSString class]] && ([aValue length] == 0))) { // if updating, empty string means to delete
-            aValue = NULL;
-        } // really only need to set if different - more efficient to just update value or compare and only set if necessary???
-        bSuccess = ABRecordSetValue(aRecord, aProperty, (__bridge CFTypeRef)aValue, &error);
-        if (!bSuccess) {
-            NSLog(@"error setting %d property", aProperty);
-        }
-    }
-
-    return bSuccess;
-}
-
-- (bool)removeProperty:(ABPropertyID)aProperty inRecord:(ABRecordRef)aRecord
-{
-    CFErrorRef err;
-    bool bSuccess = ABRecordRemoveValue(aRecord, aProperty, &err);
-
-    if (!bSuccess) {
-        CFStringRef errDescription = CFErrorCopyDescription(err);
-        NSLog(@"Unable to remove property %d: %@", aProperty, errDescription);
-        CFRelease(errDescription);
-    }
-    return bSuccess;
-}
-
-- (bool)addToMultiValue:(ABMultiValueRef)multi fromDictionary:dict
-{
-    bool bSuccess = FALSE;
-    id value = [dict valueForKey:kW3ContactFieldValue];
-
-    if (IS_VALID_VALUE(value)) {
-        CFStringRef label = [CDVContact convertContactTypeToPropertyLabel:[dict valueForKey:kW3ContactFieldType]];
-        bSuccess = ABMultiValueAddValueAndLabel(multi, (__bridge CFTypeRef)value, label, NULL);
-        if (!bSuccess) {
-            NSLog(@"Error setting Value: %@ and label: %@", value, label);
-        }
-    }
-    return bSuccess;
-}
-
-- (ABMultiValueRef)allocStringMultiValueFromArray:array
-{
-    ABMutableMultiValueRef multi = ABMultiValueCreateMutable(kABMultiStringPropertyType);
-
-    for (NSDictionary* dict in array) {
-        [self addToMultiValue:multi fromDictionary:dict];
-    }
-
-    return multi;  // caller is responsible for releasing multi
-}
-
-- (bool)setValue:(CFTypeRef)value forProperty:(ABPropertyID)prop inRecord:(ABRecordRef)person
-{
-    CFErrorRef error;
-    bool bSuccess = ABRecordSetValue(person, prop, value, &error);
-
-    if (!bSuccess) {
-        NSLog(@"Error setting value for property: %d", prop);
-    }
-    return bSuccess;
-}
-
-/* Set MultiValue string properties into Address Book Record.
- * NSArray* fieldArray - array of dictionaries containing W3C properties to be set into record
- * ABPropertyID prop - the property to be set (generally used for phones and emails)
- * ABRecordRef  person - the record to set values into
- * BOOL bUpdate - whether or not to update date or set as new.
- *	When updating:
- *	  empty array indicates to remove entire property
- *	  empty string indicates to remove
- *    [NSNull null] do not modify (keep existing record value)
- * RETURNS
- * bool false indicates error
- *
- * used for phones and emails
- */
-- (bool)setMultiValueStrings:(NSArray*)fieldArray forProperty:(ABPropertyID)prop inRecord:(ABRecordRef)person asUpdate:(BOOL)bUpdate
-{
-    bool bSuccess = TRUE;
-    ABMutableMultiValueRef multi = nil;
-
-    if (!bUpdate) {
-        multi = [self allocStringMultiValueFromArray:fieldArray];
-        bSuccess = [self setValue:multi forProperty:prop inRecord:person];
-    } else if (bUpdate && ([fieldArray count] == 0)) {
-        // remove entire property
-        bSuccess = [self removeProperty:prop inRecord:person];
-    } else { // check for and apply changes
-        ABMultiValueRef copy = ABRecordCopyValue(person, prop);
-        if (copy != nil) {
-            multi = ABMultiValueCreateMutableCopy(copy);
-            CFRelease(copy);
-
-            for (NSDictionary* dict in fieldArray) {
-                id val;
-                NSString* label = nil;
-                val = [dict valueForKey:kW3ContactFieldValue];
-                label = (__bridge NSString*)[CDVContact convertContactTypeToPropertyLabel:[dict valueForKey:kW3ContactFieldType]];
-                if (IS_VALID_VALUE(val)) {
-                    // is an update,  find index of entry with matching id, if values are different, update.
-                    id idValue = [dict valueForKey:kW3ContactFieldId];
-                    int identifier = [idValue isKindOfClass:[NSNumber class]] ? [idValue intValue] : -1;
-                    CFIndex i = identifier >= 0 ? ABMultiValueGetIndexForIdentifier(multi, identifier) : kCFNotFound;
-                    if (i != kCFNotFound) {
-                        if ([val length] == 0) {
-                            // remove both value and label
-                            ABMultiValueRemoveValueAndLabelAtIndex(multi, i);
-                        } else {
-                            NSString* valueAB = (__bridge_transfer NSString*)ABMultiValueCopyValueAtIndex(multi, i);
-                            NSString* labelAB = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(multi, i);
-                            if ((valueAB == nil) || ![val isEqualToString:valueAB]) {
-                                ABMultiValueReplaceValueAtIndex(multi, (__bridge CFTypeRef)val, i);
-                            }
-                            if ((labelAB == nil) || ![label isEqualToString:labelAB]) {
-                                ABMultiValueReplaceLabelAtIndex(multi, (__bridge CFStringRef)label, i);
-                            }
-                        }
-                    } else {
-                        // is a new value - insert
-                        [self addToMultiValue:multi fromDictionary:dict];
-                    }
-                } // end of if value
-            } // end of for
-        } else { // adding all new value(s)
-            multi = [self allocStringMultiValueFromArray:fieldArray];
-        }
-        // set the (updated) copy as the new value
-        bSuccess = [self setValue:multi forProperty:prop inRecord:person];
-    }
-
-    if (multi) {
-        CFRelease(multi);
-    }
-
-    return bSuccess;
-}
-
-// used for ims and addresses
-- (ABMultiValueRef)allocDictMultiValueFromArray:array forProperty:(ABPropertyID)prop
-{
-    ABMutableMultiValueRef multi = ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);
-    NSMutableDictionary* newDict;
-    NSMutableDictionary* addDict;
-
-    for (NSDictionary* dict in array) {
-        newDict = [self translateW3Dict:dict forProperty:prop];
-        addDict = [NSMutableDictionary dictionaryWithCapacity:2];
-        if (newDict) { // create a new dictionary with a Label and Value, value is the dictionary previously created
-            // June, 2011 W3C Contact spec adds type into ContactAddress book
-            // get the type out of the original dictionary for address
-            NSString* addrType = (NSString*)[dict valueForKey:kW3ContactFieldType];
-            if (!addrType) {
-                addrType = (NSString*)kABOtherLabel;
-            }
-            NSObject* typeValue = ((prop == kABPersonInstantMessageProperty) ? (NSObject*)kABOtherLabel : addrType);
-            // NSLog(@"typeValue: %@", typeValue);
-            [addDict setObject:typeValue forKey:kW3ContactFieldType];    //  im labels will be set as Other and address labels as type from dictionary
-            [addDict setObject:newDict forKey:kW3ContactFieldValue];
-            [self addToMultiValue:multi fromDictionary:addDict];
-        }
-    }
-
-    return multi; // caller is responsible for releasing
-}
-
-// used for ims and addresses to convert W3 dictionary of values to AB Dictionary
-// got messier when June, 2011 W3C Contact spec added type field into ContactAddress
-- (NSMutableDictionary*)translateW3Dict:(NSDictionary*)dict forProperty:(ABPropertyID)prop
-{
-    NSArray* propArray = [[CDVContact defaultObjectAndProperties] valueForKey:[[CDVContact defaultABtoW3C] objectForKey:[NSNumber numberWithInt:prop]]];
-
-    NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:1];
-    id value;
-
-    for (NSString* key in propArray) { // for each W3 Contact key get the value
-        if (((value = [dict valueForKey:key]) != nil) && ![value isKindOfClass:[NSNull class]]) {
-            // if necessary convert the W3 value to AB Property label
-            NSString* setValue = value;
-            if ([CDVContact needsConversion:key]) { // IM types must be converted
-                setValue = (NSString*)[CDVContact convertContactTypeToPropertyLabel:value];
-                // IMs must have a valid AB value!
-                if ((prop == kABPersonInstantMessageProperty) && [setValue isEqualToString:(NSString*)kABOtherLabel]) {
-                    setValue = @""; // try empty string
-                }
-            }
-            // set the AB value into the dictionary
-            [newDict setObject:setValue forKey:(NSString*)[[CDVContact defaultW3CtoAB] valueForKey:(NSString*)key]];
-        }
-    }
-
-    if ([newDict count] == 0) {
-        newDict = nil; // no items added
-    }
-    return newDict;
-}
-
-/* set multivalue dictionary properties into an AddressBook Record
- * NSArray* array - array of dictionaries containing the W3C properties to set into the record
- * ABPropertyID prop - the property id for the multivalue dictionary (addresses and ims)
- * ABRecordRef person - the record to set the values into
- * BOOL bUpdate - YES if this is an update to an existing record
- *	When updating:
- *	  empty array indicates to remove entire property
- *	  value/label == "" indicates to remove
- *    value/label == [NSNull null] do not modify (keep existing record value)
- * RETURN
- *   bool false indicates fatal error
- *
- *  iOS addresses and im are a MultiValue Properties with label, value=dictionary of  info, and id
- *  set addresses:  streetAddress, locality, region, postalCode, country
- *  set ims:  value = username, type = servicetype
- *  there are some special cases in here for ims - needs cleanup / simplification
- *
- */
-- (bool)setMultiValueDictionary:(NSArray*)array forProperty:(ABPropertyID)prop inRecord:(ABRecordRef)person asUpdate:(BOOL)bUpdate
-{
-    bool bSuccess = FALSE;
-    ABMutableMultiValueRef multi = nil;
-
-    if (!bUpdate) {
-        multi = [self allocDictMultiValueFromArray:array forProperty:prop];
-        bSuccess = [self setValue:multi forProperty:prop inRecord:person];
-    } else if (bUpdate && ([array count] == 0)) {
-        // remove property
-        bSuccess = [self removeProperty:prop inRecord:person];
-    } else { // check for and apply changes
-        ABMultiValueRef copy = ABRecordCopyValue(person, prop);
-        if (copy) {
-            multi = ABMultiValueCreateMutableCopy(copy);
-            CFRelease(copy);
-            // get the W3C values for this property
-            NSArray* propArray = [[CDVContact defaultObjectAndProperties] valueForKey:[[CDVContact defaultABtoW3C] objectForKey:[NSNumber numberWithInt:prop]]];
-            id value;
-            id valueAB;
-
-            for (NSDictionary* field in array) {
-                NSMutableDictionary* dict;
-                // find the index for the current property
-                id idValue = [field valueForKey:kW3ContactFieldId];
-                int identifier = [idValue isKindOfClass:[NSNumber class]] ? [idValue intValue] : -1;
-                CFIndex idx = identifier >= 0 ? ABMultiValueGetIndexForIdentifier(multi, identifier) : kCFNotFound;
-                BOOL bUpdateLabel = NO;
-                if (idx != kCFNotFound) {
-                    dict = [NSMutableDictionary dictionaryWithCapacity:1];
-                    // NSDictionary* existingDictionary = (NSDictionary*)ABMultiValueCopyValueAtIndex(multi, idx);
-                    CFTypeRef existingDictionary = ABMultiValueCopyValueAtIndex(multi, idx);
-                    NSString* existingABLabel = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(multi, idx);
-                    NSString* testLabel = [field valueForKey:kW3ContactFieldType];
-                    // fixes cb-143 where setting empty label could cause address to not be removed
-                    //   (because empty label would become 'other'  in convertContactTypeToPropertyLabel
-                    //   which may not have matched existing label thus resulting in an incorrect updating of the label
-                    //   and the address not getting removed at the end of the for loop)
-                    if (testLabel && [testLabel isKindOfClass:[NSString class]] && ([testLabel length] > 0)) {
-                        CFStringRef w3cLabel = [CDVContact convertContactTypeToPropertyLabel:testLabel];
-                        if (w3cLabel && ![existingABLabel isEqualToString:(__bridge NSString*)w3cLabel]) {
-                            // replace the label
-                            ABMultiValueReplaceLabelAtIndex(multi, w3cLabel, idx);
-                            bUpdateLabel = YES;
-                        }
-                    } // else was invalid or empty label string so do not update
-
-                    for (id k in propArray) {
-                        value = [field valueForKey:k];
-                        bool bSet = (value != nil && ![value isKindOfClass:[NSNull class]] && ([value isKindOfClass:[NSString class]] && [value length] > 0));
-                        // if there is a contact value, put it into dictionary
-                        if (bSet) {
-                            NSString* setValue = [CDVContact needsConversion:(NSString*)k] ? (NSString*)[CDVContact convertContactTypeToPropertyLabel:value] : value;
-                            [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]];
-                            if (valueAB != nil) {
-                                [dict setValue:valueAB forKey:[[CDVContact defaultW3CtoAB] valueForKey:k]];
-                            }
-                        } // else if value == "" it will not be added into updated dict and thus removed
-                    } // end of for loop (moving here fixes cb-143, need to end for loop before replacing or removing multivalue)
-
-                    if ([dict count] > 0) {
-                        // something was added into new dict,
-                        ABMultiValueReplaceValueAtIndex(multi, (__bridge CFTypeRef)dict, idx);
-                    } else if (!bUpdateLabel) {
-                        // nothing added into new dict and no label change so remove this property entry
-                        ABMultiValueRemoveValueAndLabelAtIndex(multi, idx);
-                    }
-
-                    CFRelease(existingDictionary);
-                } else {
-                    // not found in multivalue so add it
-                    dict = [self translateW3Dict:field forProperty:prop];
-                    if (dict) {
-                        NSMutableDictionary* addDict = [NSMutableDictionary dictionaryWithCapacity:2];
-                        // get the type out of the original dictionary for address
-                        NSObject* typeValue = ((prop == kABPersonInstantMessageProperty) ? (NSObject*)kABOtherLabel : (NSString*)[field valueForKey:kW3ContactFieldType]);
-                        // NSLog(@"typeValue: %@", typeValue);
-                        [addDict setObject:typeValue forKey:kW3ContactFieldType];        //  im labels will be set as Other and address labels as type from dictionary
-                        [addDict setObject:dict forKey:kW3ContactFieldValue];
-                        [self addToMultiValue:multi fromDictionary:addDict];
-                    }
-                }
-            } // end of looping through dictionaries
-
-            // set the (updated) copy as the new value
-            bSuccess = [self setValue:multi forProperty:prop inRecord:person];
-        }
-    } // end of copy and apply changes
-    if (multi) {
-        CFRelease(multi);
-    }
-
-    return bSuccess;
-}
-
-/* Determine which W3C labels need to be converted
- */
-+ (BOOL)needsConversion:(NSString*)W3Label
-{
-    BOOL bConvert = NO;
-
-    if ([W3Label isEqualToString:kW3ContactFieldType] || [W3Label isEqualToString:kW3ContactImType]) {
-        bConvert = YES;
-    }
-    return bConvert;
-}
-
-/* Translation of property type labels  contact API ---> iPhone
- *
- *	phone:  work, home, other, mobile, fax, pager -->
- *		kABWorkLabel, kABHomeLabel, kABOtherLabel, kABPersonPhoneMobileLabel, kABPersonHomeFAXLabel || kABPersonHomeFAXLabel, kABPersonPhonePagerLabel
- *	emails:  work, home, other ---> kABWorkLabel, kABHomeLabel, kABOtherLabel
- *	ims: aim, gtalk, icq, xmpp, msn, skype, qq, yahoo --> kABPersonInstantMessageService + (AIM, ICG, MSN, Yahoo).  No support for gtalk, xmpp, skype, qq
- * addresses: work, home, other --> kABWorkLabel, kABHomeLabel, kABOtherLabel
- *
- *
- */
-+ (CFStringRef)convertContactTypeToPropertyLabel:(NSString*)label
-{
-    CFStringRef type;
-
-    if ([label isKindOfClass:[NSNull class]] || ![label isKindOfClass:[NSString class]]) {
-        type = NULL; // no label
-    } else if ([label caseInsensitiveCompare:kW3ContactWorkLabel] == NSOrderedSame) {
-        type = kABWorkLabel;
-    } else if ([label caseInsensitiveCompare:kW3ContactHomeLabel] == NSOrderedSame) {
-        type = kABHomeLabel;
-    } else if ([label caseInsensitiveCompare:kW3ContactOtherLabel] == NSOrderedSame) {
-        type = kABOtherLabel;
-    } else if ([label caseInsensitiveCompare:kW3ContactPhoneMobileLabel] == NSOrderedSame) {
-        type = kABPersonPhoneMobileLabel;
-    } else if ([label caseInsensitiveCompare:kW3ContactPhonePagerLabel] == NSOrderedSame) {
-        type = kABPersonPhonePagerLabel;
-    } else if ([label caseInsensitiveCompare:kW3ContactImAIMLabel] == NSOrderedSame) {
-        type = kABPersonInstantMessageServiceAIM;
-    } else if ([label caseInsensitiveCompare:kW3ContactImICQLabel] == NSOrderedSame) {
-        type = kABPersonInstantMessageServiceICQ;
-    } else if ([label caseInsensitiveCompare:kW3ContactImMSNLabel] == NSOrderedSame) {
-        type = kABPersonInstantMessageServiceMSN;
-    } else if ([label caseInsensitiveCompare:kW3ContactImYahooLabel] == NSOrderedSame) {
-        type = kABPersonInstantMessageServiceYahoo;
-    } else if ([label caseInsensitiveCompare:kW3ContactUrlProfile] == NSOrderedSame) {
-        type = kABPersonHomePageLabel;
-    } else {
-        type = kABOtherLabel;
-    }
-
-    return type;
-}
-
-+ (NSString*)convertPropertyLabelToContactType:(NSString*)label
-{
-    NSString* type = nil;
-
-    if (label != nil) { // improve efficiency......
-        if ([label isEqualToString:(NSString*)kABPersonPhoneMobileLabel]) {
-            type = kW3ContactPhoneMobileLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonPhoneHomeFAXLabel] ||
-            [label isEqualToString:(NSString*)kABPersonPhoneWorkFAXLabel]) {
-            type = kW3ContactPhoneFaxLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonPhonePagerLabel]) {
-            type = kW3ContactPhonePagerLabel;
-        } else if ([label isEqualToString:(NSString*)kABHomeLabel]) {
-            type = kW3ContactHomeLabel;
-        } else if ([label isEqualToString:(NSString*)kABWorkLabel]) {
-            type = kW3ContactWorkLabel;
-        } else if ([label isEqualToString:(NSString*)kABOtherLabel]) {
-            type = kW3ContactOtherLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonInstantMessageServiceAIM]) {
-            type = kW3ContactImAIMLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonInstantMessageServiceICQ]) {
-            type = kW3ContactImICQLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonInstantMessageServiceJabber]) {
-            type = kW3ContactOtherLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonInstantMessageServiceMSN]) {
-            type = kW3ContactImMSNLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonInstantMessageServiceYahoo]) {
-            type = kW3ContactImYahooLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonHomePageLabel]) {
-            type = kW3ContactUrlProfile;
-        } else {
-            type = kW3ContactOtherLabel;
-        }
-    }
-    return type;
-}
-
-/* Check if the input label is a valid W3C ContactField.type. This is used when searching,
- * only search field types if the search string is a valid type.  If we converted any search
- * string to a ABPropertyLabel it could convert to kABOtherLabel which is probably not want
- * the user wanted to search for and could skew the results.
- */
-+ (BOOL)isValidW3ContactType:(NSString*)label
-{
-    BOOL isValid = NO;
-
-    if ([label isKindOfClass:[NSNull class]] || ![label isKindOfClass:[NSString class]]) {
-        isValid = NO; // no label
-    } else if ([label caseInsensitiveCompare:kW3ContactWorkLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactHomeLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactOtherLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactPhoneMobileLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactPhonePagerLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactImAIMLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactImICQLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactImMSNLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactImYahooLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else {
-        isValid = NO;
-    }
-
-    return isValid;
-}
-
-/* Create a new Contact Dictionary object from an ABRecordRef that contains information in a format such that
- * it can be returned to JavaScript callback as JSON object string.
- * Uses:
- * ABRecordRef set into Contact Object
- * NSDictionary withFields indicates which fields to return from the AddressBook Record
- *
- * JavaScript Contact:
- * @param {DOMString} id unique identifier
- * @param {DOMString} displayName
- * @param {ContactName} name
- * @param {DOMString} nickname
- * @param {ContactField[]} phoneNumbers array of phone numbers
- * @param {ContactField[]} emails array of email addresses
- * @param {ContactAddress[]} addresses array of addresses
- * @param {ContactField[]} ims instant messaging user ids
- * @param {ContactOrganization[]} organizations
- * @param {DOMString} published date contact was first created
- * @param {DOMString} updated date contact was last updated
- * @param {DOMString} birthday contact's birthday
- * @param (DOMString} anniversary contact's anniversary
- * @param {DOMString} gender contact's gender
- * @param {DOMString} note user notes about contact
- * @param {DOMString} preferredUsername
- * @param {ContactField[]} photos
- * @param {ContactField[]} tags
- * @param {ContactField[]} relationships
- * @param {ContactField[]} urls contact's web sites
- * @param {ContactAccounts[]} accounts contact's online accounts
- * @param {DOMString} timezone UTC time zone offset
- * @param {DOMString} connected
- */
-
-- (NSDictionary*)toDictionary:(NSDictionary*)withFields
-{
-    // if not a person type record bail out for now
-    if (ABRecordGetRecordType(self.record) != kABPersonType) {
-        return NULL;
-    }
-    id value = nil;
-    self.returnFields = withFields;
-
-    NSMutableDictionary* nc = [NSMutableDictionary dictionaryWithCapacity:1];  // new contact dictionary to fill in from ABRecordRef
-    // id
-    [nc setObject:[NSNumber numberWithInt:ABRecordGetRecordID(self.record)] forKey:kW3ContactId];
-    if (self.returnFields == nil) {
-        // if no returnFields specified, W3C says to return empty contact (but Cordova will at least return id)
-        return nc;
-    }
-    if ([self.returnFields objectForKey:kW3ContactDisplayName]) {
-        // displayname requested -  iOS doesn't have so return null
-        [nc setObject:[NSNull null] forKey:kW3ContactDisplayName];
-        // may overwrite below if requested ContactName and there are no values
-    }
-    // nickname
-    if ([self.returnFields valueForKey:kW3ContactNickname]) {
-        value = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, kABPersonNicknameProperty);
-        [nc setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactNickname];
-    }
-
-    // name dictionary
-    // NSLog(@"getting name info");
-    NSObject* data = [self extractName];
-    if (data != nil) {
-        [nc setObject:data forKey:kW3ContactName];
-    }
-    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);
-        if (tryName != nil) {
-            [nc setObject:tryName forKey:kW3ContactDisplayName];
-        } else {
-            // use nickname or empty string
-            value = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, kABPersonNicknameProperty);
-            [nc setObject:(value != nil) ? value:@"" forKey:kW3ContactDisplayName];
-        }
-    }
-    // phoneNumbers array
-    // NSLog(@"getting phoneNumbers");
-    value = [self extractMultiValue:kW3ContactPhoneNumbers];
-    if (value != nil) {
-        [nc setObject:value forKey:kW3ContactPhoneNumbers];
-    }
-    // emails array
-    // NSLog(@"getting emails");
-    value = [self extractMultiValue:kW3ContactEmails];
-    if (value != nil) {
-        [nc setObject:value forKey:kW3ContactEmails];
-    }
-    // urls array
-    value = [self extractMultiValue:kW3ContactUrls];
-    if (value != nil) {
-        [nc setObject:value forKey:kW3ContactUrls];
-    }
-    // addresses array
-    // NSLog(@"getting addresses");
-    value = [self extractAddresses];
-    if (value != nil) {
-        [nc setObject:value forKey:kW3ContactAddresses];
-    }
-    // im array
-    // NSLog(@"getting ims");
-    value = [self extractIms];
-    if (value != nil) {
-        [nc setObject:value forKey:kW3ContactIms];
-    }
-    // organization array (only info for one organization in iOS)
-    // NSLog(@"getting organizations");
-    value = [self extractOrganizations];
-    if (value != nil) {
-        [nc setObject:value forKey:kW3ContactOrganizations];
-    }
-
-    // for simple properties, could make this a bit more efficient by storing all simple properties in a single
-    // array in the returnFields dictionary and setting them via a for loop through the array
-
-    // add dates
-    // NSLog(@"getting dates");
-    NSNumber* ms;
-
-    /** Contact Revision field removed from June 16, 2011 version of specification
-
-    if ([self.returnFields valueForKey:kW3ContactUpdated]){
-        ms = [self getDateAsNumber: kABPersonModificationDateProperty];
-        if (!ms){
-            // try and get published date
-            ms = [self getDateAsNumber: kABPersonCreationDateProperty];
-        }
-        if (ms){
-            [nc setObject:  ms forKey:kW3ContactUpdated];
-        }
-
-    }
-    */
-
-    if ([self.returnFields valueForKey:kW3ContactBirthday]) {
-        ms = [self getDateAsNumber:kABPersonBirthdayProperty];
-        if (ms) {
-            [nc setObject:ms forKey:kW3ContactBirthday];
-        }
-    }
-
-    /*  Anniversary removed from 12-09-2010 W3C Contacts api spec
-     if ([self.returnFields valueForKey:kW3ContactAnniversary]){
-        // Anniversary date is stored in a multivalue property
-        ABMultiValueRef multi = ABRecordCopyValue(self.record, kABPersonDateProperty);
-        if (multi){
-            CFStringRef label = nil;
-            CFIndex count = ABMultiValueGetCount(multi);
-            // see if contains an Anniversary date
-            for(CFIndex i=0; i<count; i++){
-                label = ABMultiValueCopyLabelAtIndex(multi, i);
-                if(label && [(NSString*)label isEqualToString:(NSString*)kABPersonAnniversaryLabel]){
-                    CFDateRef aDate = ABMultiValueCopyValueAtIndex(multi, i);
-                    if(aDate){
-                        [nc setObject: (NSString*)aDate forKey: kW3ContactAnniversary];
-                        CFRelease(aDate);
-                    }
-                    CFRelease(label);
-                    break;
-                }
-            }
-            CFRelease(multi);
-        }
-    }*/
-
-    if ([self.returnFields valueForKey:kW3ContactNote]) {
-        // note
-        value = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, kABPersonNoteProperty);
-        [nc setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactNote];
-    }
-
-    if ([self.returnFields valueForKey:kW3ContactPhotos]) {
-        value = [self extractPhotos];
-        [nc setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactPhotos];
-    }
-
-    /* TimeZone removed from June 16, 2011 Contacts spec
-     *
-    if ([self.returnFields valueForKey:kW3ContactTimezone]){
-        [NSTimeZone resetSystemTimeZone];
-        NSTimeZone* currentTZ = [NSTimeZone localTimeZone];
-        NSInteger seconds = [currentTZ secondsFromGMT];
-        NSString* tz = [NSString stringWithFormat:@"%2d:%02u",  seconds/3600, seconds % 3600 ];
-        [nc setObject:tz forKey:kW3ContactTimezone];
-    }
-    */
-    // TODO WebURLs
-    // [nc setObject:[NSNull null] forKey:kW3ContactUrls];
-    // online accounts - not available on iOS
-
-    return nc;
-}
-
-- (NSNumber*)getDateAsNumber:(ABPropertyID)datePropId
-{
-    NSNumber* msDate = nil;
-    NSDate* aDate = nil;
-    CFTypeRef cfDate = ABRecordCopyValue(self.record, datePropId);
-
-    if (cfDate) {
-        aDate = (__bridge NSDate*)cfDate;
-        msDate = [NSNumber numberWithDouble:([aDate timeIntervalSince1970] * 1000)];
-        CFRelease(cfDate);
-    }
-    return msDate;
-}
-
-/* Create Dictionary to match JavaScript ContactName object:
- *	formatted - ABRecordCopyCompositeName
- *	familyName
- *	givenName
- *	middleName
- *	honorificPrefix
- *	honorificSuffix
-*/
-
-- (NSObject*)extractName
-{
-    NSArray* fields = [self.returnFields objectForKey:kW3ContactName];
-
-    if (fields == nil) { // no name fields requested
-        return nil;
-    }
-
-    NSMutableDictionary* newName = [NSMutableDictionary dictionaryWithCapacity:6];
-    id value;
-
-    for (NSString* i in fields) {
-        if ([i isEqualToString:kW3ContactFormattedName]) {
-            value = (__bridge_transfer NSString*)ABRecordCopyCompositeName(self.record);
-            [newName setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactFormattedName];
-        } else {
-            // W3CtoAB returns NSNumber for AB name properties, get intValue and cast to ABPropertyID)
-            value = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, (ABPropertyID)[[[CDVContact defaultW3CtoAB] valueForKey:i] intValue]);
-            [newName setObject:(value != nil) ? value:[NSNull null] forKey:(NSString*)i];
-        }
-    }
-
-    return newName;
-}
-
-/* Create array of Dictionaries to match JavaScript ContactField object for simple multiValue properties phoneNumbers, emails
- * Input: (NSString*) W3Contact Property name
- * type
- *		for phoneNumbers type is one of (work,home,other, mobile, fax, pager)
- *		for emails type is one of (work,home, other)
- * value - phone number or email address
- * (bool) primary (not supported on iphone)
- * id
-*/
-- (NSObject*)extractMultiValue:(NSString*)propertyId
-{
-    NSArray* fields = [self.returnFields objectForKey:propertyId];
-
-    if (fields == nil) {
-        return nil;
-    }
-    ABMultiValueRef multi = nil;
-    NSObject* valuesArray = nil;
-    NSNumber* propNumber = [[CDVContact defaultW3CtoAB] valueForKey:propertyId];
-    ABPropertyID propId = [propNumber intValue];
-    multi = ABRecordCopyValue(self.record, propId);
-    // multi = ABRecordCopyValue(self.record, (ABPropertyID)[[[Contact defaultW3CtoAB] valueForKey:propertyId] intValue]);
-    CFIndex count = multi != nil ? ABMultiValueGetCount(multi) : 0;
-    id value;
-    if (count) {
-        valuesArray = [NSMutableArray arrayWithCapacity:count];
-
-        for (CFIndex i = 0; i < count; i++) {
-            NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:4];
-            if ([fields containsObject:kW3ContactFieldType]) {
-                NSString* label = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(multi, i);
-                value = [CDVContact convertPropertyLabelToContactType:label];
-                [newDict setObject:(value != nil) ? value:[NSNull null]   forKey:kW3ContactFieldType];
-            }
-            if ([fields containsObject:kW3ContactFieldValue]) {
-                value = (__bridge_transfer NSString*)ABMultiValueCopyValueAtIndex(multi, i);
-                [newDict setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactFieldValue];
-            }
-            if ([fields containsObject:kW3ContactFieldPrimary]) {
-                [newDict setObject:[NSNumber numberWithBool:(BOOL)NO] forKey:kW3ContactFieldPrimary];   // iOS doesn't support primary so set all to false
-            }
-            // always set id
-            value = [NSNumber numberWithUnsignedInt:ABMultiValueGetIdentifierAtIndex(multi, i)];
-            [newDict setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactFieldId];
-            [(NSMutableArray*)valuesArray addObject : newDict];
-        }
-    } else {
-        valuesArray = [NSNull null];
-    }
-    if (multi) {
-        CFRelease(multi);
-    }
-
-    return valuesArray;
-}
-
-/* Create array of Dictionaries to match JavaScript ContactAddress object for addresses
- *  pref - not supported
- *  type - address type
- *	formatted  - formatted for mailing label (what about localization?)
- *	streetAddress
- *	locality
- *	region;
- *	postalCode
- *	country
- *	id
- *
- *	iOS addresses are a MultiValue Properties with label, value=dictionary of address info, and id
- */
-- (NSObject*)extractAddresses
-{
-    NSArray* fields = [self.returnFields objectForKey:kW3ContactAddresses];
-
-    if (fields == nil) { // no name fields requested
-        return nil;
-    }
-    CFStringRef value;
-    NSObject* addresses;
-    ABMultiValueRef multi = ABRecordCopyValue(self.record, kABPersonAddressProperty);
-    CFIndex count = multi ? ABMultiValueGetCount(multi) : 0;
-    if (count) {
-        addresses = [NSMutableArray arrayWithCapacity:count];
-
-        for (CFIndex i = 0; i < count; i++) {
-            NSMutableDictionary* newAddress = [NSMutableDictionary dictionaryWithCapacity:7];
-            // if we got this far, at least some address info is being requested.
-
-            // Always set id
-            id identifier = [NSNumber numberWithUnsignedInt:ABMultiValueGetIdentifierAtIndex(multi, i)];
-            [newAddress setObject:(identifier != nil) ? identifier:[NSNull null] forKey:kW3ContactFieldId];
-            // set the type label
-            NSString* label = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(multi, i);
-
-            [newAddress setObject:(label != nil) ? (NSObject*)[[CDVContact class] convertPropertyLabelToContactType:label]:[NSNull null] forKey:kW3ContactFieldType];
-            // set the pref - iOS doesn't support so set to default of false
-            [newAddress setObject:@"false" forKey:kW3ContactFieldPrimary];
-            // get dictionary of values for this address
-            CFDictionaryRef dict = (CFDictionaryRef)ABMultiValueCopyValueAtIndex(multi, i);
-
-            for (id k in fields) {
-                bool bFound;
-                id key = [[CDVContact defaultW3CtoAB] valueForKey:k];
-                if (key && ![k isKindOfClass:[NSNull class]]) {
-                    bFound = CFDictionaryGetValueIfPresent(dict, (__bridge const void*)key, (void*)&value);
-                    if (bFound && (value != NULL)) {
-                        CFRetain(value);
-                        [newAddress setObject:(__bridge id)value forKey:k];
-                        CFRelease(value);
-                    } else {
-                        [newAddress setObject:[NSNull null] forKey:k];
-                    }
-                } else {
-                    // was a property that iPhone doesn't support
-                    [newAddress setObject:[NSNull null] forKey:k];
-                }
-            }
-
-            if ([newAddress count] > 0) { // ?? this will always be true since we set id,label,primary field??
-                [(NSMutableArray*)addresses addObject : newAddress];
-            }
-            CFRelease(dict);
-        } // end of loop through addresses
-    } else {
-        addresses = [NSNull null];
-    }
-    if (multi) {
-        CFRelease(multi);
-    }
-
-    return addresses;
-}
-
-/* Create array of Dictionaries to match JavaScript ContactField object for ims
- * type one of [aim, gtalk, icq, xmpp, msn, skype, qq, yahoo] needs other as well
- * value
- * (bool) primary
- * id
- *
- *	iOS IMs are a MultiValue Properties with label, value=dictionary of IM details (service, username), and id
- */
-- (NSObject*)extractIms
-{
-    NSArray* fields = [self.returnFields objectForKey:kW3ContactIms];
-
-    if (fields == nil) { // no name fields requested
-        return nil;
-    }
-    NSObject* imArray;
-    ABMultiValueRef multi = ABRecordCopyValue(self.record, kABPersonInstantMessageProperty);
-    CFIndex count = multi ? ABMultiValueGetCount(multi) : 0;
-    if (count) {
-        imArray = [NSMutableArray arrayWithCapacity:count];
-
-        for (CFIndex i = 0; i < ABMultiValueGetCount(multi); i++) {
-            NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:3];
-            // iOS has label property (work, home, other) for each IM but W3C contact API doesn't use
-            CFDictionaryRef dict = (CFDictionaryRef)ABMultiValueCopyValueAtIndex(multi, i);
-            CFStringRef value;  // all values should be CFStringRefs / NSString*
-            bool bFound;
-            if ([fields containsObject:kW3ContactFieldValue]) {
-                // value = user name
-                bFound = CFDictionaryGetValueIfPresent(dict, kABPersonInstantMessageUsernameKey, (void*)&value);
-                if (bFound && (value != NULL)) {
-                    CFRetain(value);
-                    [newDict setObject:(__bridge id)value forKey:kW3ContactFieldValue];
-                    CFRelease(value);
-                } else {
-                    [newDict setObject:[NSNull null] forKey:kW3ContactFieldValue];
-                }
-            }
-            if ([fields containsObject:kW3ContactFieldType]) {
-                bFound = CFDictionaryGetValueIfPresent(dict, kABPersonInstantMessageServiceKey, (void*)&value);
-                if (bFound && (value != NULL)) {
-                    CFRetain(value);
-                    [newDict setObject:(id)[[CDVContact class] convertPropertyLabelToContactType : (__bridge NSString*)value] forKey:kW3ContactFieldType];
-                    CFRelease(value);
-                } else {
-                    [newDict setObject:[NSNull null] forKey:kW3ContactFieldType];
-                }
-            }
-            // always set ID
-            id identifier = [NSNumber numberWithUnsignedInt:ABMultiValueGetIdentifierAtIndex(multi, i)];
-            [newDict setObject:(identifier != nil) ? identifier:[NSNull null] forKey:kW3ContactFieldId];
-
-            [(NSMutableArray*)imArray addObject : newDict];
-            CFRelease(dict);
-        }
-    } else {
-        imArray = [NSNull null];
-    }
-
-    if (multi) {
-        CFRelease(multi);
-    }
-    return imArray;
-}
-
-/* Create array of Dictionaries to match JavaScript ContactOrganization object
- *	pref - not supported in iOS
- *  type - not supported in iOS
- *  name
- *	department
- *	title
- */
-
-- (NSObject*)extractOrganizations
-{
-    NSArray* fields = [self.returnFields objectForKey:kW3ContactOrganizations];
-
-    if (fields == nil) { // no name fields requested
-        return nil;
-    }
-    NSObject* array = nil;
-    NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:5];
-    id value;
-    int validValueCount = 0;
-
-    for (id i in fields) {
-        id key = [[CDVContact defaultW3CtoAB] valueForKey:i];
-        if (key && [key isKindOfClass:[NSNumber class]]) {
-            value = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, (ABPropertyID)[[[CDVContact defaultW3CtoAB] valueForKey:i] intValue]);
-            if (value != nil) {
-                // if there are no organization values we should return null for organization
-                // this counter keeps indicates if any organization values have been set
-                validValueCount++;
-            }
-            [newDict setObject:(value != nil) ? value:[NSNull null] forKey:i];
-        } else { // not a key iOS supports, set to null
-            [newDict setObject:[NSNull null] forKey:i];
-        }
-    }
-
-    if (([newDict count] > 0) && (validValueCount > 0)) {
-        // add pref and type
-        // they are not supported by iOS and thus these values never change
-        [newDict setObject:@"false" forKey:kW3ContactFieldPrimary];
-        [newDict setObject:[NSNull null] forKey:kW3ContactFieldType];
-        array = [NSMutableArray arrayWithCapacity:1];
-        [(NSMutableArray*)array addObject : newDict];
-    } else {
-        array = [NSNull null];
-    }
-    return array;
-}
-
-// W3C Contacts expects an array of photos.  Can return photos in more than one format, currently
-// just returning the default format
-// Save the photo data into tmp directory and return FileURI - temp directory is deleted upon application exit
-- (NSObject*)extractPhotos
-{
-    NSMutableArray* photos = nil;
-
-    if (ABPersonHasImageData(self.record)) {
-        CFDataRef photoData = ABPersonCopyImageData(self.record);
-        NSData* data = (__bridge NSData*)photoData;
-        // write to temp directory and store URI in photos array
-        // get the temp directory path
-        NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
-        NSError* err = nil;
-        NSString* filePath = [NSString stringWithFormat:@"%@/photo_XXXXX", docsPath];
-        char template[filePath.length + 1];
-        strcpy(template, [filePath cStringUsingEncoding:NSASCIIStringEncoding]);
-        mkstemp(template);
-        filePath = [[NSFileManager defaultManager]
-            stringWithFileSystemRepresentation:template
-                                        length:strlen(template)];
-
-        // save file
-        if ([data writeToFile:filePath options:NSAtomicWrite error:&err]) {
-            photos = [NSMutableArray arrayWithCapacity:1];
-            NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:2];
-            [newDict setObject:filePath forKey:kW3ContactFieldValue];
-            [newDict setObject:@"url" forKey:kW3ContactFieldType];
-            [newDict setObject:@"false" forKey:kW3ContactFieldPrimary];
-            [photos addObject:newDict];
-        }
-
-        CFRelease(photoData);
-    }
-    return photos;
-}
-
-/**
- *	given an array of W3C Contact field names, create a dictionary of field names to extract
- *	if field name represents an object, return all properties for that object:  "name" - returns all properties in ContactName
- *	if field name is an explicit property, return only those properties:  "name.givenName - returns a ContactName with only ContactName.givenName
- *  if field contains ONLY ["*"] return all fields
- *	dictionary format:
- *	key is W3Contact #define
- *		value is NSMutableArray* for complex keys:  name,addresses,organizations, phone, emails, ims
- *		value is [NSNull null] for simple keys
-*/
-+ (NSDictionary*)calcReturnFields:(NSArray*)fieldsArray // NSLog(@"getting self.returnFields");
-{
-    NSMutableDictionary* d = [NSMutableDictionary dictionaryWithCapacity:1];
-
-    if ((fieldsArray != nil) && [fieldsArray isKindOfClass:[NSArray class]]) {
-        if (([fieldsArray count] == 1) && [[fieldsArray objectAtIndex:0] isEqualToString:@"*"]) {
-            return [CDVContact defaultFields];  // return all fields
-        }
-
-        for (id i in fieldsArray) {
-            NSMutableArray* keys = nil;
-            NSString* fieldStr = nil;
-            if ([i isKindOfClass:[NSNumber class]]) {
-                fieldStr = [i stringValue];
-            } else {
-                fieldStr = i;
-            }
-
-            // see if this is specific property request in object - object.property
-            NSArray* parts = [fieldStr componentsSeparatedByString:@"."]; // returns original string if no separator found
-            NSString* name = [parts objectAtIndex:0];
-            NSString* property = nil;
-            if ([parts count] > 1) {
-                property = [parts objectAtIndex:1];
-            }
-            // see if this is a complex field by looking for its array of properties in objectAndProperties dictionary
-            id fields = [[CDVContact defaultObjectAndProperties] objectForKey:name];
-
-            // if find complex name (name,addresses,organizations, phone, emails, ims) in fields, add name as key
-            // with array of associated properties as the value
-            if ((fields != nil) && (property == nil)) { // request was for full object
-                keys = [NSMutableArray arrayWithArray:fields];
-                if (keys != nil) {
-                    [d setObject:keys forKey:name]; // will replace if prop array already exists
-                }
-            } else if ((fields != nil) && (property != nil)) {
-                // found an individual property request  in form of name.property
-                // verify is real property name by using it as key in W3CtoAB
-                id abEquiv = [[CDVContact defaultW3CtoAB] objectForKey:property];
-                if (abEquiv || [[CDVContact defaultW3CtoNull] containsObject:property]) {
-                    // if existing array add to it
-                    if ((keys = [d objectForKey:name]) != nil) {
-                        [keys addObject:property];
-                    } else {
-                        keys = [NSMutableArray arrayWithObject:property];
-                        [d setObject:keys forKey:name];
-                    }
-                } else {
-                    NSLog(@"Contacts.find -- request for invalid property ignored: %@.%@", name, property);
-                }
-            } else { // is an individual property, verify is real property name by using it as key in W3CtoAB
-                id valid = [[CDVContact defaultW3CtoAB] objectForKey:name];
-                if (valid || [[CDVContact defaultW3CtoNull] containsObject:name]) {
-                    [d setObject:[NSNull null] forKey:name];
-                }
-            }
-        }
-    }
-    if ([d count] == 0) {
-        // no array or nothing in the array. W3C spec says to return nothing
-        return nil;   // [Contact defaultFields];
-    }
-    return d;
-}
-
-/*
- * Search for the specified value in each of the fields specified in the searchFields dictionary.
- * NSString* value - the string value to search for (need clarification from W3C on how to search for dates)
- * NSDictionary* searchFields - a dictionary created via calcReturnFields where the key is the top level W3C
- *	object and the object is the array of specific fields within that object or null if it is a single property
- * RETURNS
- *	YES as soon as a match is found in any of the fields
- *	NO - the specified value does not exist in any of the fields in this contact
- *
- *  Note: I'm not a fan of returning in the middle of methods but have done it some in this method in order to
- *    keep the code simpler. bgibson
- */
-- (BOOL)foundValue:(NSString*)testValue inFields:(NSDictionary*)searchFields
-{
-    BOOL bFound = NO;
-
-    if ((testValue == nil) || ![testValue isKindOfClass:[NSString class]] || ([testValue length] == 0)) {
-        // nothing to find so return NO
-        return NO;
-    }
-    NSInteger valueAsInt = [testValue integerValue];
-
-    // per W3C spec, always include id in search
-    int recordId = ABRecordGetRecordID(self.record);
-    if (valueAsInt && (recordId == valueAsInt)) {
-        return YES;
-    }
-
-    if (searchFields == nil) {
-        // no fields to search
-        return NO;
-    }
-
-    if ([searchFields valueForKey:kW3ContactNickname]) {
-        bFound = [self testStringValue:testValue forW3CProperty:kW3ContactNickname];
-        if (bFound == YES) {
-            return bFound;
-        }
-    }
-
-    if ([searchFields valueForKeyIsArray:kW3ContactName]) {
-        // test name fields.  All are string properties obtained via ABRecordCopyValue except kW3ContactFormattedName
-        NSArray* fields = [searchFields valueForKey:kW3ContactName];
-
-        for (NSString* testItem in fields) {
-            if ([testItem isEqualToString:kW3ContactFormattedName]) {
-                NSString* propValue = (__bridge_transfer NSString*)ABRecordCopyCompositeName(self.record);
-                if ((propValue != nil) && ([propValue length] > 0)) {
-                    NSRange range = [propValue rangeOfString:testValue options:NSCaseInsensitiveSearch];
-                    bFound = (range.location != NSNotFound);
-                    propValue = nil;
-                }
-            } else {
-                bFound = [self testStringValue:testValue forW3CProperty:testItem];
-            }
-
-            if (bFound) {
-                break;
-            }
-        }
-    }
-    if (!bFound && [searchFields valueForKeyIsArray:kW3ContactPhoneNumbers]) {
-        bFound = [self searchContactFields:(NSArray*)[searchFields valueForKey:kW3ContactPhoneNumbers]
-                       forMVStringProperty:kABPersonPhoneProperty withValue:testValue];
-    }
-    if (!bFound && [searchFields valueForKeyIsArray:kW3ContactEmails]) {
-        bFound = [self searchContactFields:(NSArray*)[searchFields valueForKey:kW3ContactEmails]
-                       forMVStringProperty:kABPersonEmailProperty withValue:testValue];
-    }
-
-    if (!bFound && [searchFields valueForKeyIsArray:kW3ContactAddresses]) {
-        bFound = [self searchContactFields:[searchFields valueForKey:kW3ContactAddresses]
-                   forMVDictionaryProperty:kABPersonAddressProperty withValue:testValue];
-    }
-
-    if (!bFound && [searchFields valueForKeyIsArray:kW3ContactIms]) {
-        bFound = [self searchContactFields:[searchFields valueForKey:kW3ContactIms]
-                   forMVDictionaryProperty:kABPersonInstantMessageProperty withValue:testValue];
-    }
-
-    if (!bFound && [searchFields valueForKeyIsArray:kW3ContactOrganizations]) {
-        NSArray* fields = [searchFields valueForKey:kW3ContactOrganizations];
-
-        for (NSString* testItem in fields) {
-            bFound = [self testStringValue:testValue forW3CProperty:testItem];
-            if (bFound == YES) {
-                break;
-            }
-        }
-    }
-    if (!bFound && [searchFields valueForKey:kW3ContactNote]) {
-        bFound = [self testStringValue:testValue forW3CProperty:kW3ContactNote];
-    }
-
-    // if searching for a date field is requested, get the date field as a localized string then look for match against testValue in date string
-    // searching for photos is not supported
-    if (!bFound && [searchFields valueForKey:kW3ContactBirthday]) {
-        bFound = [self testDateValue:testValue forW3CProperty:kW3ContactBirthday];
-    }
-    if (!bFound && [searchFields valueForKeyIsArray:kW3ContactUrls]) {
-        bFound = [self searchContactFields:(NSArray*)[searchFields valueForKey:kW3ContactUrls]
-                       forMVStringProperty:kABPersonURLProperty withValue:testValue];
-    }
-
-    return bFound;
-}
-
-/*
- * Test for the existence of a given string within the value of a ABPersonRecord string property based on the W3c property name.
- *
- * IN:
- *	NSString* testValue - the value to find - search is case insensitive
- *  NSString* property - the W3c property string
- * OUT:
- * BOOL YES if the given string was found within the property value
- *		NO if the testValue was not found, W3C property string was invalid or the AddressBook property was not a string
- */
-- (BOOL)testStringValue:(NSString*)testValue forW3CProperty:(NSString*)property
-{
-    BOOL bFound = NO;
-
-    if ([[CDVContact defaultW3CtoAB] valueForKeyIsNumber:property]) {
-        ABPropertyID propId = [[[CDVContact defaultW3CtoAB] objectForKey:property] intValue];
-        if (ABPersonGetTypeOfProperty(propId) == kABStringPropertyType) {
-            NSString* propValue = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, propId);
-            if ((propValue != nil) && ([propValue length] > 0)) {
-                NSPredicate* containPred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", testValue];
-                bFound = [containPred evaluateWithObject:propValue];
-                // NSRange range = [propValue rangeOfString:testValue options: NSCaseInsensitiveSearch];
-                // bFound = (range.location != NSNotFound);
-            }
-        }
-    }
-    return bFound;
-}
-
-/*
- * Test for the existence of a given Date string within the value of a ABPersonRecord datetime property based on the W3c property name.
- *
- * IN:
- *	NSString* testValue - the value to find - search is case insensitive
- *  NSString* property - the W3c property string
- * OUT:
- * BOOL YES if the given string was found within the localized date string value
- *		NO if the testValue was not found, W3C property string was invalid or the AddressBook property was not a DateTime
- */
-- (BOOL)testDateValue:(NSString*)testValue forW3CProperty:(NSString*)property
-{
-    BOOL bFound = NO;
-
-    if ([[CDVContact defaultW3CtoAB] valueForKeyIsNumber:property]) {
-        ABPropertyID propId = [[[CDVContact defaultW3CtoAB] objectForKey:property] intValue];
-        if (ABPersonGetTypeOfProperty(propId) == kABDateTimePropertyType) {
-            NSDate* date = (__bridge_transfer NSDate*)ABRecordCopyValue(self.record, propId);
-            if (date != nil) {
-                NSString* dateString = [date descriptionWithLocale:[NSLocale currentLocale]];
-                NSPredicate* containPred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", testValue];
-                bFound = [containPred evaluateWithObject:dateString];
-            }
-        }
-    }
-    return bFound;
-}
-
-/*
- * Search the specified fields within an AddressBook multivalue string property for the specified test value.
- * Used for phoneNumbers, emails and urls.
- * IN:
- *	NSArray* fields - the fields to search for within the multistring property (value and/or type)
- *	ABPropertyID - the property to search
- *	NSString* testValue - the value to search for. Will convert between W3C types and AB types.  Will only
- *		search for types if the testValue is a valid ContactField type.
- * OUT:
- *	YES if the test value was found in one of the specified fields
- *	NO if the test value was not found
- */
-- (BOOL)searchContactFields:(NSArray*)fields forMVStringProperty:(ABPropertyID)propId withValue:testValue
-{
-    BOOL bFound = NO;
-
-    for (NSString* type in fields) {
-        NSString* testString = nil;
-        if ([type isEqualToString:kW3ContactFieldType]) {
-            if ([CDVContact isValidW3ContactType:testValue]) {
-                // only search types if the filter string is a valid ContactField.type
-                testString = (NSString*)[CDVContact convertContactTypeToPropertyLabel:testValue];
-            }
-        } else {
-            testString = testValue;
-        }
-
-        if (testString != nil) {
-            bFound = [self testMultiValueStrings:testString forProperty:propId ofType:type];
-        }
-        if (bFound == YES) {
-            break;
-        }
-    }
-
-    return bFound;
-}
-
-/*
- * Searches a multiString value of the specified type for the specified test value.
- *
- * IN:
- *	NSString* testValue - the value to test for
- *	ABPropertyID propId - the property id of the multivalue property to search
- *	NSString* type - the W3C contact type to search for (value or type)
- * OUT:
- * YES is the test value was found
- * NO if the test value was not found
- */
-- (BOOL)testMultiValueStrings:(NSString*)testValue forProperty:(ABPropertyID)propId ofType:(NSString*)type
-{
-    BOOL bFound = NO;
-
-    if (ABPersonGetTypeOfProperty(propId) == kABMultiStringPropertyType) {
-        NSArray* valueArray = nil;
-        if ([type isEqualToString:kW3ContactFieldType]) {
-            valueArray = [self labelsForProperty:propId inRecord:self.record];
-        } else if ([type isEqualToString:kW3ContactFieldValue]) {
-            valueArray = [self valuesForProperty:propId inRecord:self.record];
-        }
-        if (valueArray) {
-            NSString* valuesAsString = [valueArray componentsJoinedByString:@" "];
-            NSPredicate* containPred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", testValue];
-            bFound = [containPred evaluateWithObject:valuesAsString];
-        }
-    }
-    return bFound;
-}
-
-/*
- * Returns the array of values for a multivalue string property of the specified property id
- */
-- (__autoreleasing NSArray*)valuesForProperty:(ABPropertyID)propId inRecord:(ABRecordRef)aRecord
-{
-    ABMultiValueRef multi = ABRecordCopyValue(aRecord, propId);
-    NSArray* values = (__bridge_transfer NSArray*)ABMultiValueCopyArrayOfAllValues(multi);
-
-    CFRelease(multi);
-    return values;
-}
-
-/*
- * Returns the array of labels for a multivalue string property of the specified property id
- */
-- (NSArray*)labelsForProperty:(ABPropertyID)propId inRecord:(ABRecordRef)aRecord
-{
-    ABMultiValueRef multi = ABRecordCopyValue(aRecord, propId);
-    CFIndex count = ABMultiValueGetCount(multi);
-    NSMutableArray* labels = [NSMutableArray arrayWithCapacity:count];
-
-    for (int i = 0; i < count; i++) {
-        NSString* label = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(multi, i);
-        if (label) {
-            [labels addObject:label];
-        }
-    }
-
-    CFRelease(multi);
-    return labels;
-}
-
-/* search for values within MultiValue Dictionary properties Address or IM property
- * IN:
- * (NSArray*) fields - the array of W3C field names to search within
- * (ABPropertyID) propId - the AddressBook property that returns a multivalue dictionary
- * (NSString*) testValue - the string to search for within the specified fields
- *
- */
-- (BOOL)searchContactFields:(NSArray*)fields forMVDictionaryProperty:(ABPropertyID)propId withValue:(NSString*)testValue
-{
-    BOOL bFound = NO;
-
-    NSArray* values = [self valuesForProperty:propId inRecord:self.record];  // array of dictionaries (as CFDictionaryRef)
-    int dictCount = [values count];
-
-    // for ims dictionary contains with service (w3C type) and username (W3c value)
-    // for addresses dictionary contains street, city, state, zip, country
-    for (int i = 0; i < dictCount; i++) {
-        CFDictionaryRef dict = (__bridge CFDictionaryRef)[values objectAtIndex:i];
-
-        for (NSString* member in fields) {
-            NSString* abKey = [[CDVContact defaultW3CtoAB] valueForKey:member]; // im and address fields are all strings
-            CFStringRef abValue = nil;
-            if (abKey) {
-                NSString* testString = nil;
-                if ([member isEqualToString:kW3ContactImType]) {
-                    if ([CDVContact isValidW3ContactType:testValue]) {
-                        // only search service/types if the filter string is a valid ContactField.type
-                        testString = (NSString*)[CDVContact convertContactTypeToPropertyLabel:testValue];
-                    }
-                } else {
-                    testString = testValue;
-                }
-                if (testString != nil) {
-                    BOOL bExists = CFDictionaryGetValueIfPresent(dict, (__bridge const void*)abKey, (void*)&abValue);
-                    if (bExists) {
-                        CFRetain(abValue);
-                        NSPredicate* containPred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", testString];
-                        bFound = [containPred evaluateWithObject:(__bridge id)abValue];
-                        CFRelease(abValue);
-                    }
-                }
-            }
-            if (bFound == YES) {
-                break;
-            }
-        } // end of for each member in fields
-
-        if (bFound == YES) {
-            break;
-        }
-    } // end of for each dictionary
-
-    return bFound;
-}
-
-@end