2006-06-15 21:34:10 +02:00
|
|
|
/*
|
2017-03-03 16:35:23 +01:00
|
|
|
Copyright (C) 2005-2017 Inverse inc.
|
2010-06-30 18:53:23 +02:00
|
|
|
|
|
|
|
This file is part of SOGo.
|
2017-03-03 16:35:23 +01:00
|
|
|
|
2010-06-30 18:53:23 +02:00
|
|
|
SOGo is free software; you can redistribute it and/or modify it under
|
2006-06-15 21:34:10 +02:00
|
|
|
the terms of the GNU Lesser General Public License as published by the
|
|
|
|
Free Software Foundation; either version 2, or (at your option) any
|
|
|
|
later version.
|
2017-03-03 16:35:23 +01:00
|
|
|
|
2010-06-30 18:53:23 +02:00
|
|
|
SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
|
2006-06-15 21:34:10 +02:00
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
|
|
|
License for more details.
|
2017-03-03 16:35:23 +01:00
|
|
|
|
2006-06-15 21:34:10 +02:00
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
|
|
License along with OGo; see the file COPYING. If not, write to the
|
|
|
|
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2010-07-16 21:35:25 +02:00
|
|
|
#import <Foundation/NSURL.h>
|
2014-06-19 21:51:57 +02:00
|
|
|
#import <Foundation/NSValue.h>
|
2010-07-16 21:35:25 +02:00
|
|
|
|
2007-08-06 16:46:38 +02:00
|
|
|
#import <NGObjWeb/NSException+HTTP.h>
|
|
|
|
#import <NGObjWeb/WOResponse.h>
|
2006-09-13 23:30:37 +02:00
|
|
|
#import <NGCards/NSArray+NGCards.h>
|
2006-09-19 16:09:03 +02:00
|
|
|
#import <NGExtensions/NSString+Ext.h>
|
2014-02-07 21:52:43 +01:00
|
|
|
#import <NGExtensions/NSString+misc.h>
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2014-06-19 21:51:57 +02:00
|
|
|
#import <SOGo/NSArray+Utilities.h>
|
2013-01-30 14:40:27 +01:00
|
|
|
#import <SOGo/NSCalendarDate+SOGo.h>
|
2014-06-19 21:51:57 +02:00
|
|
|
#import <SOGo/NSDictionary+Utilities.h>
|
2013-01-30 14:40:27 +01:00
|
|
|
#import <SOGo/SOGoUser.h>
|
2014-06-19 21:51:57 +02:00
|
|
|
#import <SOGo/SOGoUserDefaults.h>
|
2014-01-22 17:27:27 +01:00
|
|
|
|
|
|
|
#import <Contacts/NGVCard+SOGo.h>
|
2010-07-16 21:35:25 +02:00
|
|
|
#import <Contacts/SOGoContactObject.h>
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2006-09-13 23:30:37 +02:00
|
|
|
#import "UIxContactView.h"
|
2006-06-15 21:34:10 +02:00
|
|
|
|
|
|
|
@implementation UIxContactView
|
|
|
|
|
2010-07-16 21:35:25 +02:00
|
|
|
- (id) init
|
|
|
|
{
|
|
|
|
if ((self = [super init]))
|
|
|
|
{
|
|
|
|
photosURL = nil;
|
2010-10-27 17:18:14 +02:00
|
|
|
card = nil;
|
|
|
|
phones = nil;
|
|
|
|
homeAdr = nil;
|
|
|
|
workAdr = nil;
|
2010-07-16 21:35:25 +02:00
|
|
|
}
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2010-07-16 21:35:25 +02:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
{
|
2011-12-30 21:39:07 +01:00
|
|
|
[card release];
|
2010-07-16 21:35:25 +02:00
|
|
|
[photosURL release];
|
|
|
|
[super dealloc];
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
|
|
|
|
2014-06-19 21:51:57 +02:00
|
|
|
- (NSArray *) _languageContactsCategories
|
|
|
|
{
|
|
|
|
NSArray *categoryLabels;
|
|
|
|
|
|
|
|
categoryLabels = [[self labelForKey: @"contacts_category_labels"] componentsSeparatedByString: @","];
|
|
|
|
if (!categoryLabels)
|
|
|
|
categoryLabels = [NSArray array];
|
2017-03-03 16:35:23 +01:00
|
|
|
|
2014-06-19 21:51:57 +02:00
|
|
|
return [categoryLabels trimmedComponents];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *) _fetchAndCombineCategoriesList
|
|
|
|
{
|
|
|
|
NSString *ownerLogin;
|
|
|
|
SOGoUserDefaults *ud;
|
|
|
|
NSArray *cats, *newCats, *contactCategories;
|
|
|
|
|
|
|
|
ownerLogin = [[self clientObject] ownerInContext: context];
|
|
|
|
ud = [[SOGoUser userWithLogin: ownerLogin] userDefaults];
|
|
|
|
cats = [ud contactsCategories];
|
|
|
|
if (!cats)
|
|
|
|
cats = [self _languageContactsCategories];
|
|
|
|
|
|
|
|
contactCategories = [card categories];
|
|
|
|
if (contactCategories)
|
|
|
|
{
|
2015-04-27 19:18:05 +02:00
|
|
|
newCats = [cats mergedArrayWithArray: [contactCategories trimmedComponents]];
|
2014-06-19 21:51:57 +02:00
|
|
|
if ([newCats count] != [cats count])
|
|
|
|
{
|
|
|
|
cats = [newCats sortedArrayUsingSelector:
|
|
|
|
@selector (localizedCaseInsensitiveCompare:)];
|
|
|
|
[ud setContactsCategories: cats];
|
|
|
|
[ud synchronize];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return cats;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *) categories
|
|
|
|
{
|
|
|
|
NSMutableArray *categories;
|
|
|
|
NSArray *values;
|
|
|
|
NSString *category;
|
|
|
|
NSUInteger count, max;
|
|
|
|
|
|
|
|
values = [card categories];
|
|
|
|
max = [values count];
|
|
|
|
if (max > 0)
|
|
|
|
{
|
|
|
|
categories = [NSMutableArray arrayWithCapacity: max];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
category = [values objectAtIndex: count];
|
|
|
|
if ([category length] > 0)
|
|
|
|
[categories addObject: [NSDictionary dictionaryWithObject: category forKey: @"value"]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
categories = nil;
|
|
|
|
|
|
|
|
return categories;
|
|
|
|
}
|
|
|
|
|
2016-03-01 22:53:08 +01:00
|
|
|
- (NSArray *) urls
|
|
|
|
{
|
|
|
|
NSMutableArray *urls;
|
|
|
|
NSMutableDictionary *attrs;
|
|
|
|
NSArray *values;
|
|
|
|
NSString *type, *value;
|
|
|
|
NSURL *url;
|
|
|
|
CardElement *element;
|
|
|
|
NSUInteger count, max;
|
|
|
|
|
|
|
|
values = [card childrenWithTag: @"url"];
|
|
|
|
max = [values count];
|
|
|
|
if (max > 0)
|
|
|
|
{
|
|
|
|
urls = [NSMutableArray arrayWithCapacity: max];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
attrs = [NSMutableDictionary dictionary];
|
|
|
|
element = [values objectAtIndex: count];
|
|
|
|
type = [element value: 0 ofAttribute: @"type"];
|
|
|
|
if ([type length])
|
|
|
|
[attrs setObject: type forKey: @"type"];
|
|
|
|
value = [element flattenedValuesForKey: @""];
|
|
|
|
url = [NSURL URLWithString: value];
|
|
|
|
if (![url scheme] && [value length] > 0)
|
|
|
|
url = [NSURL URLWithString: [NSString stringWithFormat: @"http://%@", value]];
|
|
|
|
[attrs setObject: [url absoluteString] forKey: @"value"];
|
|
|
|
|
|
|
|
[urls addObject: attrs];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
urls = nil;
|
|
|
|
|
|
|
|
return urls;
|
|
|
|
}
|
|
|
|
|
2014-06-19 21:51:57 +02:00
|
|
|
- (NSArray *) deliveryAddresses
|
|
|
|
{
|
2017-04-21 18:31:18 +02:00
|
|
|
NSString *type, *postoffice, *street, *street2, *locality, *region, *postalcode, *country;
|
2014-06-19 21:51:57 +02:00
|
|
|
NSMutableDictionary *address;
|
2017-04-21 18:31:18 +02:00
|
|
|
NSMutableArray *addresses;
|
2014-06-19 21:51:57 +02:00
|
|
|
NSArray *elements;
|
|
|
|
CardElement *adr;
|
2017-04-21 18:31:18 +02:00
|
|
|
|
2014-06-19 21:51:57 +02:00
|
|
|
NSUInteger count, max;
|
|
|
|
|
|
|
|
elements = [card childrenWithTag: @"adr"];
|
|
|
|
max = [elements count];
|
2017-04-21 18:31:18 +02:00
|
|
|
|
2014-06-19 21:51:57 +02:00
|
|
|
if (max > 0)
|
|
|
|
{
|
|
|
|
addresses = [NSMutableArray arrayWithCapacity: max];
|
2014-08-06 22:06:58 +02:00
|
|
|
for (count = 0; count < max; count++)
|
2014-06-19 21:51:57 +02:00
|
|
|
{
|
|
|
|
adr = [elements objectAtIndex: count];
|
|
|
|
type = [adr value: 0 ofAttribute: @"type"];
|
|
|
|
postoffice = [adr flattenedValueAtIndex: 0 forKey: @""];
|
|
|
|
street2 = [adr flattenedValueAtIndex: 1 forKey: @""];
|
|
|
|
street = [adr flattenedValueAtIndex: 2 forKey: @""];
|
|
|
|
locality = [adr flattenedValueAtIndex: 3 forKey: @""];
|
|
|
|
region = [adr flattenedValueAtIndex: 4 forKey: @""];
|
|
|
|
postalcode = [adr flattenedValueAtIndex: 5 forKey: @""];
|
|
|
|
country = [adr flattenedValueAtIndex: 6 forKey: @""];
|
2017-04-21 18:31:18 +02:00
|
|
|
|
|
|
|
address = [NSMutableDictionary dictionaryWithObject: type forKey: @"type"];
|
2014-06-19 21:51:57 +02:00
|
|
|
if (postoffice) [address setObject: postoffice forKey: @"postoffice"];
|
|
|
|
if (street2) [address setObject: street2 forKey: @"street2"];
|
|
|
|
if (street) [address setObject: street forKey: @"street"];
|
|
|
|
if (locality) [address setObject: locality forKey: @"locality"];
|
|
|
|
if (region) [address setObject: region forKey: @"region"];
|
|
|
|
if (postalcode) [address setObject: postalcode forKey: @"postalcode"];
|
|
|
|
if (country) [address setObject: country forKey: @"country"];
|
|
|
|
if ([[address allKeys] count] > 1) [addresses addObject: address];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
addresses = nil;
|
|
|
|
|
|
|
|
return addresses;
|
|
|
|
}
|
|
|
|
|
2006-06-15 21:34:10 +02:00
|
|
|
/* action */
|
|
|
|
|
2006-09-13 23:30:37 +02:00
|
|
|
- (id <WOActionResults>) defaultAction
|
|
|
|
{
|
|
|
|
card = [[self clientObject] vCard];
|
2006-09-16 00:25:43 +02:00
|
|
|
if (card)
|
|
|
|
{
|
2011-12-30 21:39:07 +01:00
|
|
|
[card retain];
|
2006-09-16 00:25:43 +02:00
|
|
|
phones = nil;
|
|
|
|
homeAdr = nil;
|
|
|
|
workAdr = nil;
|
|
|
|
}
|
|
|
|
else
|
2006-09-19 16:50:11 +02:00
|
|
|
return [NSException exceptionWithHTTPStatus: 404 /* Not Found */
|
|
|
|
reason: @"could not locate contact"];
|
2006-09-13 23:30:37 +02:00
|
|
|
|
2006-06-15 21:34:10 +02:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2015-01-22 15:15:44 +01:00
|
|
|
/**
|
|
|
|
* @api {get} /so/:username/Contacts/:addressbookId/:cardId/view Get card
|
|
|
|
* @apiVersion 1.0.0
|
|
|
|
* @apiName GetData
|
|
|
|
* @apiGroup Contacts
|
|
|
|
* @apiExample {curl} Example usage:
|
|
|
|
* curl -i http://localhost/SOGo/so/sogo1/Contacts/personal/1BC8-52F53F80-1-38C52040.vcf/view
|
|
|
|
*
|
|
|
|
* @apiSuccess (Success 200) {String} id Card ID
|
|
|
|
* @apiSuccess (Success 200) {String} pid Address book ID (card's container)
|
2015-07-27 18:47:40 +02:00
|
|
|
* @apiSuccess (Success 200) {String} c_component Either vcard or vlist
|
|
|
|
* @apiSuccess (Success 200) {String} [c_givenname] Firstname
|
2015-01-22 15:15:44 +01:00
|
|
|
* @apiSuccess (Success 200) {String} [nickname] Nickname
|
2015-07-27 18:47:40 +02:00
|
|
|
* @apiSuccess (Success 200) {String} [c_sn] Lastname
|
|
|
|
* @apiSuccess (Success 200) {String} [c_fn] Fullname
|
2017-03-03 16:35:23 +01:00
|
|
|
* @apiSuccess (Success 200) {String} [title] Title
|
|
|
|
* @apiSuccess (Success 200) {String} [role] Role
|
2015-11-27 16:58:56 +01:00
|
|
|
* @apiSuccess (Success 200) {String} [c_screenname] Screen Name (X-AIM for now)
|
2015-01-22 15:15:44 +01:00
|
|
|
* @apiSuccess (Success 200) {String} [tz] Timezone
|
2017-03-03 16:35:23 +01:00
|
|
|
* @apiSuccess (Success 200) {String} [org] Main organization
|
|
|
|
* @apiSuccess (Success 200) {String[]} [orgs] Additional organizations
|
|
|
|
* @apiSuccess (Success 200) {String[]} [notes] Notes
|
2015-01-22 15:15:44 +01:00
|
|
|
* @apiSuccess (Success 200) {String[]} allCategories All available categories
|
|
|
|
* @apiSuccess (Success 200) {Object[]} [categories] Categories assigned to the card
|
|
|
|
* @apiSuccess (Success 200) {String} categories.value Category name
|
|
|
|
* @apiSuccess (Success 200) {Object[]} [addresses] Postal addresses
|
|
|
|
* @apiSuccess (Success 200) {String} addresses.type Type (e.g., home or work)
|
|
|
|
* @apiSuccess (Success 200) {String} addresses.postoffice Post office box
|
|
|
|
* @apiSuccess (Success 200) {String} addresses.street Street address
|
|
|
|
* @apiSuccess (Success 200) {String} addresses.street2 Extended address (e.g., apartment or suite number)
|
|
|
|
* @apiSuccess (Success 200) {String} addresses.locality Locality (e.g., city)
|
|
|
|
* @apiSuccess (Success 200) {String} addresses.region Region (e.g., state or province)
|
|
|
|
* @apiSuccess (Success 200) {String} addresses.postalcode Postal code
|
|
|
|
* @apiSuccess (Success 200) {String} addresses.country Country name
|
|
|
|
* @apiSuccess (Success 200) {Object[]} [emails] Email addresses
|
|
|
|
* @apiSuccess (Success 200) {String} emails.type Type (e.g., home or work)
|
|
|
|
* @apiSuccess (Success 200) {String} emails.value Email address
|
|
|
|
* @apiSuccess (Success 200) {Object[]} [phones] Phone numbers
|
|
|
|
* @apiSuccess (Success 200) {String} phones.type Type (e.g., mobile or work)
|
|
|
|
* @apiSuccess (Success 200) {String} phones.value Phone number
|
|
|
|
* @apiSuccess (Success 200) {Object[]} [urls] URLs
|
|
|
|
* @apiSuccess (Success 200) {String} urls.type Type (e.g., personal or work)
|
|
|
|
* @apiSuccess (Success 200) {String} urls.value URL
|
|
|
|
*/
|
2014-06-19 21:51:57 +02:00
|
|
|
- (id <WOActionResults>) dataAction
|
|
|
|
{
|
|
|
|
id <WOActionResults> result;
|
|
|
|
id o;
|
|
|
|
SOGoObject <SOGoContactObject> *contact;
|
2017-03-03 16:35:23 +01:00
|
|
|
NSArray *values;
|
2014-06-19 21:51:57 +02:00
|
|
|
NSMutableDictionary *data;
|
|
|
|
|
|
|
|
contact = [self clientObject];
|
|
|
|
card = [contact vCard];
|
|
|
|
if (card)
|
|
|
|
{
|
|
|
|
[card retain];
|
|
|
|
phones = nil;
|
|
|
|
homeAdr = nil;
|
|
|
|
workAdr = nil;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return [NSException exceptionWithHTTPStatus: 404 /* Not Found */
|
|
|
|
reason: @"could not locate contact"];
|
|
|
|
|
|
|
|
data = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
[[contact container] nameInContainer], @"pid",
|
|
|
|
[contact nameInContainer], @"id",
|
2015-07-27 18:47:40 +02:00
|
|
|
[[card tag] lowercaseString], @"c_component",
|
2014-06-19 21:51:57 +02:00
|
|
|
nil];
|
|
|
|
o = [card fn];
|
2015-07-27 18:47:40 +02:00
|
|
|
if (o) [data setObject: o forKey: @"c_cn"];
|
2014-06-19 21:51:57 +02:00
|
|
|
o = [card n];
|
|
|
|
if (o)
|
|
|
|
{
|
|
|
|
NSString *lastName = [o flattenedValueAtIndex: 0 forKey: @""];
|
|
|
|
NSString *firstName = [o flattenedValueAtIndex: 1 forKey: @""];
|
|
|
|
if ([lastName length] > 0)
|
2015-07-27 18:47:40 +02:00
|
|
|
[data setObject: lastName forKey: @"c_sn"];
|
2014-06-19 21:51:57 +02:00
|
|
|
if ([firstName length] > 0)
|
2015-07-27 18:47:40 +02:00
|
|
|
[data setObject: firstName forKey: @"c_givenname"];
|
2014-06-19 21:51:57 +02:00
|
|
|
}
|
2015-11-27 16:58:56 +01:00
|
|
|
|
|
|
|
o = [[card uniqueChildWithTag: @"x-aim"] flattenedValuesForKey: @""];
|
|
|
|
if ([o length]) [data setObject: o forKey: @"c_screenname"];
|
|
|
|
|
2014-06-19 21:51:57 +02:00
|
|
|
o = [card nickname];
|
|
|
|
if (o) [data setObject: o forKey: @"nickname"];
|
|
|
|
o = [card title];
|
|
|
|
if ([o length] > 0)
|
2016-08-01 21:55:50 +02:00
|
|
|
[data setObject: o forKey: @"title"];
|
2014-06-19 21:51:57 +02:00
|
|
|
o = [card role];
|
|
|
|
if ([o length] > 0)
|
2016-08-01 21:55:50 +02:00
|
|
|
[data setObject: o forKey: @"role"];
|
2017-03-03 16:35:23 +01:00
|
|
|
values = [card organizations];
|
|
|
|
if ([values count])
|
|
|
|
{
|
|
|
|
[data setObject: [values objectAtIndex: 0] forKey: @"org"];
|
|
|
|
if ([values count] > 1)
|
|
|
|
[data setObject: [values subarrayWithRange: NSMakeRange(1, [values count] - 1)] forKey: @"orgs"];
|
|
|
|
}
|
2014-06-19 21:51:57 +02:00
|
|
|
|
|
|
|
o = [card birthday];
|
|
|
|
if (o)
|
2016-08-01 21:55:50 +02:00
|
|
|
[data setObject: [o descriptionWithCalendarFormat: @"%Y-%m-%d"]
|
2015-08-20 16:29:47 +02:00
|
|
|
forKey: @"birthday"];
|
|
|
|
|
2014-06-19 21:51:57 +02:00
|
|
|
o = [card tz];
|
|
|
|
if (o) [data setObject: o forKey: @"tz"];
|
|
|
|
|
|
|
|
o = [card childrenWithTag: @"email"];
|
|
|
|
if ([o count]) [data setObject: o forKey: @"emails"];
|
|
|
|
o = [card childrenWithTag: @"tel"];
|
|
|
|
if ([o count]) [data setObject: o forKey: @"phones"];
|
|
|
|
o = [self categories];
|
|
|
|
if ([o count]) [data setObject: o forKey: @"categories"];
|
|
|
|
o = [self deliveryAddresses];
|
|
|
|
if ([o count] > 0) [data setObject: o forKey: @"addresses"];
|
2016-03-01 22:53:08 +01:00
|
|
|
o = [self urls];
|
2014-06-19 21:51:57 +02:00
|
|
|
if ([o count]) [data setObject: o forKey: @"urls"];
|
|
|
|
|
2016-10-21 00:28:58 +02:00
|
|
|
o = [card notes];
|
2016-08-01 21:55:50 +02:00
|
|
|
if (o) [data setObject: o forKey: @"notes"];
|
2014-06-19 21:51:57 +02:00
|
|
|
o = [self _fetchAndCombineCategoriesList];
|
|
|
|
if (o) [data setObject: o forKey: @"allCategories"];
|
|
|
|
if ([contact hasPhoto])
|
|
|
|
[data setObject: [self photoURL] forKey: @"photoURL"];
|
|
|
|
|
|
|
|
result = [self responseWithStatus: 200
|
|
|
|
andString: [data jsonRepresentation]];
|
2017-03-03 16:35:23 +01:00
|
|
|
|
2014-06-19 21:51:57 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-02-13 15:50:00 +01:00
|
|
|
- (BOOL) hasPhoto
|
|
|
|
{
|
|
|
|
return [[self clientObject] hasPhoto];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) photoURL
|
2010-07-16 21:35:25 +02:00
|
|
|
{
|
|
|
|
NSURL *soURL;
|
|
|
|
|
2012-02-13 15:50:00 +01:00
|
|
|
soURL = [[self clientObject] soURL];
|
2010-07-16 21:35:25 +02:00
|
|
|
|
2012-02-13 15:50:00 +01:00
|
|
|
return [NSString stringWithFormat: @"%@/photo", [soURL absoluteString]];
|
2010-07-16 21:35:25 +02:00
|
|
|
}
|
|
|
|
|
2006-06-15 21:34:10 +02:00
|
|
|
@end /* UIxContactView */
|