JSON-based operations on contacts

pull/91/head
Francis Lachapelle 2014-06-19 15:51:57 -04:00
parent 29e147ee86
commit 0a49031b01
13 changed files with 815 additions and 105 deletions

View File

@ -34,6 +34,9 @@
- (void) updateFromLDIFRecord: (NSDictionary *) ldifRecord; - (void) updateFromLDIFRecord: (NSDictionary *) ldifRecord;
- (NSMutableDictionary *) asLDIFRecord; - (NSMutableDictionary *) asLDIFRecord;
- (void) setAttributes: (NSDictionary *) attributes;
//- (NSDictionary *) attributes;
- (NSString *) workCompany; - (NSString *) workCompany;
- (NSString *) fullName; - (NSString *) fullName;
- (NSArray *) secondaryEmails; - (NSArray *) secondaryEmails;

View File

@ -642,6 +642,237 @@ convention:
return ldifRecord; return ldifRecord;
} }
- (void) setAttributes: (NSDictionary *) attributes
{
NSInteger year, yearOfToday, month, day;
CardElement *element;
NSCalendarDate *now;
NSArray *elements, *values;
NSMutableArray *addresses, *units, *categories;
NSString *ou;
id o;
unsigned int i;
NSLog(@"setAttributes: %@", attributes);
[self setNWithFamily: [attributes objectForKey: @"sn"]
given: [attributes objectForKey: @"givenname"]
additional: nil prefixes: nil suffixes: nil];
[self setNickname: [attributes objectForKey: @"nickname"]];
[self setFn: [attributes objectForKey: @"fn"]];
[self setTitle: [attributes objectForKey: @"title"]];
// element = [self elementWithTag: @"adr" ofType: @"home"];
// [element setSingleValue: [ldifRecord objectForKey: @"mozillahomestreet2"]
// atIndex: 1 forKey: @""];
// [element setSingleValue: [ldifRecord objectForKey: @"mozillahomestreet"]
// atIndex: 2 forKey: @""];
// [element setSingleValue: [ldifRecord objectForKey: @"mozillahomelocalityname"]
// atIndex: 3 forKey: @""];
// [element setSingleValue: [ldifRecord objectForKey: @"mozillahomestate"]
// atIndex: 4 forKey: @""];
// [element setSingleValue: [ldifRecord objectForKey: @"mozillahomepostalcode"]
// atIndex: 5 forKey: @""];
// [element setSingleValue: [ldifRecord objectForKey: @"mozillahomecountryname"]
// atIndex: 6 forKey: @""];
// element = [self elementWithTag: @"adr" ofType: @"work"];
// [element setSingleValue: [ldifRecord objectForKey: @"mozillaworkstreet2"]
// atIndex: 1 forKey: @""];
// [element setSingleValue: [ldifRecord objectForKey: @"street"]
// atIndex: 2 forKey: @""];
// [element setSingleValue: [ldifRecord objectForKey: @"l"]
// atIndex: 3 forKey: @""];
// [element setSingleValue: [ldifRecord objectForKey: @"st"]
// atIndex: 4 forKey: @""];
// [element setSingleValue: [ldifRecord objectForKey: @"postalcode"]
// atIndex: 5 forKey: @""];
// [element setSingleValue: [ldifRecord objectForKey: @"c"]
// atIndex: 6 forKey: @""];
if ([[attributes objectForKey: @"addresses"] isKindOfClass: [NSArray class]])
{
elements = [self childrenWithTag: @"adr"];
[self removeChildren: elements];
values = [attributes objectForKey: @"addresses"];
addresses = [NSMutableArray arrayWithCapacity: [values count]];
for (i = 0; i < [values count]; i++)
{
o = [values objectAtIndex: i];
if ([o isKindOfClass: [NSDictionary class]])
{
element = [self elementWithTag: @"adr" ofType: [o objectForKey: @"type"]];
[element setSingleValue: [o objectForKey: @"postoffice"]
atIndex: 0 forKey: @""];
[element setSingleValue: [o objectForKey: @"street2"]
atIndex: 1 forKey: @""];
[element setSingleValue: [o objectForKey: @"street"]
atIndex: 2 forKey: @""];
[element setSingleValue: [o objectForKey: @"locality"]
atIndex: 3 forKey: @""];
[element setSingleValue: [o objectForKey: @"region"]
atIndex: 4 forKey: @""];
[element setSingleValue: [o objectForKey: @"postalcode"]
atIndex: 5 forKey: @""];
[element setSingleValue: [o objectForKey: @"country"]
atIndex: 6 forKey: @""];
}
}
}
// ou = [ldifRecord objectForKey: @"ou"];
// if (ou)
// units = [NSArray arrayWithObject: ou];
// else
// units = nil;
// [self setOrg: [ldifRecord objectForKey: @"o"]
// units: units];
if ([[attributes objectForKey: @"orgUnits"] isKindOfClass: [NSArray class]])
{
elements = [self childrenWithTag: @"org"];
[self removeChildren: elements];
values = [attributes objectForKey: @"orgUnits"];
units = [NSMutableArray arrayWithCapacity: [values count]];
for (i = 0; i < [values count]; i++)
{
o = [values objectAtIndex: i];
if ([o isKindOfClass: [NSDictionary class]])
{
[units addObject: [o objectForKey: @"value"]];
}
}
}
else
{
units = nil;
}
[self setOrg: [attributes objectForKey: @"org"]
units: units];
// [self _setPhoneValues: ldifRecord];
elements = [self childrenWithTag: @"tel"];
[self removeChildren: elements];
values = [attributes objectForKey: @"phones"];
if ([values isKindOfClass: [NSArray class]])
{
NSEnumerator *list = [values objectEnumerator];
id attrs;
while ((attrs = [list nextObject]))
{
if ([attrs isKindOfClass: [NSDictionary class]])
{
element = [self elementWithTag: @"tel" ofType: [attrs objectForKey: @"type"]];
[element setSingleValue: [attrs objectForKey: @"value"] forKey: @""];
}
}
}
// [self _setEmails: ldifRecord];
if ([[attributes objectForKey: @"emails"] isKindOfClass: [NSArray class]])
{
elements = [self childrenWithTag: @"email"];
[self removeChildren: elements];
values = [attributes objectForKey: @"emails"];
if (values)
{
NSEnumerator *list = [values objectEnumerator];
//NSDictionary *attrs;
while ((o = [list nextObject]))
{
if ([o isKindOfClass: [NSDictionary class]])
{
element = [self elementWithTag: @"email" ofType: [o objectForKey: @"type"]];
[element setSingleValue: [o objectForKey: @"value"] forKey: @""];
}
}
}
}
// [[self elementWithTag: @"url" ofType: @"home"]
// setSingleValue: [ldifRecord objectForKey: @"mozillahomeurl"] forKey: @""];
// [[self elementWithTag: @"url" ofType: @"work"]
// setSingleValue: [ldifRecord objectForKey: @"mozillaworkurl"] forKey: @""];
elements = [self childrenWithTag: @"url"];
[self removeChildren: elements];
values = [attributes objectForKey: @"urls"];
if ([values isKindOfClass: [NSArray class]])
{
NSEnumerator *list = [values objectEnumerator];
id attrs;
while ((attrs = [list nextObject]))
{
if ([attrs isKindOfClass: [NSDictionary class]])
{
element = [self elementWithTag: @"url" ofType: [attrs objectForKey: @"type"]];
[element setSingleValue: [attrs objectForKey: @"value"] forKey: @""];
}
}
}
// [[self uniqueChildWithTag: @"x-aim"]
// setSingleValue: [ldifRecord objectForKey: @"nsaimid"]
// forKey: @""];
// now = [NSCalendarDate date];
// year = [[ldifRecord objectForKey: @"birthyear"] intValue];
// if (year < 100)
// {
// yearOfToday = [now yearOfCommonEra];
// if (year == 0)
// year = yearOfToday;
// else if (yearOfToday < (year + 2000))
// year += 1900;
// else
// year += 2000;
// }
// month = [[ldifRecord objectForKey: @"birthmonth"] intValue];
// day = [[ldifRecord objectForKey: @"birthday"] intValue];
// if (year && month && day)
// [self setBday: [NSString stringWithFormat: @"%.4d-%.2d-%.2d",
// year, month, day]];
// else
// [self setBday: @""];
// /* hack to carry SOGoLDAPContactInfo to vcards */
// [[self uniqueChildWithTag: @"x-sogo-contactinfo"]
// setSingleValue: [ldifRecord objectForKey: @"c_info"]
// forKey: @""];
[self setNote: [attributes objectForKey: @"note"]];
// o = [ldifRecord objectForKey: @"vcardcategories"];
if ([[attributes objectForKey: @"categories"] isKindOfClass: [NSArray class]])
{
elements = [self childrenWithTag: @"categories"];
[self removeChildren: elements];
values = [attributes objectForKey: @"categories"];
categories = [NSMutableArray arrayWithCapacity: [values count]];
for (i = 0; i < [values count]; i++)
{
o = [values objectAtIndex: i];
if ([o isKindOfClass: [NSDictionary class]])
{
[categories addObject: [o objectForKey: @"value"]];
}
}
[self setCategories: categories];
}
// We can either have an array (from SOGo's web gui) or a
// string (from a LDIF import) as the value here.
// if ([o isKindOfClass: [NSArray class]])
// [self setCategories: o];
// else
// [self setCategories: [o componentsSeparatedByString: @","]];
[self cleanupEmptyChildren];
NSLog(@"%@", [self versitString]);
}
- (NSString *) workCompany - (NSString *) workCompany
{ {
CardElement *org; CardElement *org;

View File

@ -84,6 +84,11 @@
return [self ldifRecord]; return [self ldifRecord];
} }
- (void) setAttributes: (NSDictionary *) newAttributes
{
[[self vCard] setAttributes: newAttributes];
}
- (BOOL) hasPhoto - (BOOL) hasPhoto
{ {
return ([[self vCard] firstChildWithTag: @"photo"] != nil); return ([[self vCard] firstChildWithTag: @"photo"] != nil);

View File

@ -37,6 +37,8 @@
- (NSDictionary *) ldifRecord; - (NSDictionary *) ldifRecord;
- (NSDictionary *) simplifiedLDIFRecord; - (NSDictionary *) simplifiedLDIFRecord;
- (void) setAttributes: (NSDictionary *) newAttributes;
- (NSException *) save; - (NSException *) save;
- (NSException *) delete; - (NSException *) delete;

View File

@ -303,15 +303,15 @@ static Class SOGoContactGCSEntryK = Nil;
/* actions */ /* actions */
- (BOOL) shouldTakeValuesFromRequest: (WORequest *) request // - (BOOL) shouldTakeValuesFromRequest: (WORequest *) request
inContext: (WOContext*) context // inContext: (WOContext*) context
{ // {
NSString *actionName; // NSString *actionName;
//
actionName = [[request requestHandlerPath] lastPathComponent]; // actionName = [[request requestHandlerPath] lastPathComponent];
//
return ([actionName hasPrefix: @"save"]); // return ([actionName hasPrefix: @"save"]);
} // }
- (NSString *) viewActionName - (NSString *) viewActionName
{ {
@ -347,43 +347,80 @@ static Class SOGoContactGCSEntryK = Nil;
- (id <WOActionResults>) saveAction - (id <WOActionResults>) saveAction
{ {
SOGoObject <SOGoContactObject> *contact; SOGoObject <SOGoContactObject> *contact;
id result; WORequest *request;
NSString *jsRefreshMethod; WOResponse *response;
//id result;
NSDictionary *params;
//NSString *jsRefreshMethod;
SoSecurityManager *sm; SoSecurityManager *sm;
contact = [self clientObject]; contact = [self clientObject];
[contact setLDIFRecord: ldifRecord]; request = [context request];
[self _fetchAndCombineCategoriesList]; NSLog(@"%@", [request contentAsString]);
params = [[request contentAsString] objectFromJSONString];
// LDIF NSDictionary (vCard)
// ---------------------------------------------
// sn familyname
// givenname givenname
// mozillanickname nickname
// displayname fullname
// title title
// o organization
// ou[] units[]
// telephonenumber tel;work
// homephone tel;home
// mobile tel;cell
// facsimiletelephonenumber tel;fax
// pager tel;pager
// mail email;work
// mozillasecondemail email;home
// mozillausehtmlmail x-mozilla-html
// mozillahomeurl url;home
// mozillaworkurl url;work
// nsaimid x-aim
// birth(year/month/day) bday
// c_info x-sogo-contactinfo
// description note
// vcardcategories categories
[contact setAttributes: params];
response = [self responseWithStatus: 204];
//[contact setLDIFRecord: ldifRecord];
//[self _fetchAndCombineCategoriesList];
[contact save]; [contact save];
if (componentAddressBook && componentAddressBook != [self componentAddressBook]) // if (componentAddressBook && componentAddressBook != [self componentAddressBook])
{ // {
if ([contact isKindOfClass: SOGoContactGCSEntryK]) // if ([contact isKindOfClass: SOGoContactGCSEntryK])
{ // {
sm = [SoSecurityManager sharedSecurityManager]; // sm = [SoSecurityManager sharedSecurityManager];
if (![sm validatePermission: SoPerm_DeleteObjects // if (![sm validatePermission: SoPerm_DeleteObjects
onObject: componentAddressBook // onObject: componentAddressBook
inContext: context] // inContext: context]
&& ![sm validatePermission: SoPerm_AddDocumentsImagesAndFiles // && ![sm validatePermission: SoPerm_AddDocumentsImagesAndFiles
onObject: componentAddressBook // onObject: componentAddressBook
inContext: context]) // inContext: context])
[(SOGoContactGCSEntry *) contact // [(SOGoContactGCSEntry *) contact
moveToFolder: (SOGoGCSFolder *)componentAddressBook]; // TODO: // moveToFolder: (SOGoGCSFolder *)componentAddressBook]; // TODO:
// handle // // handle
// exception // // exception
} // }
} // }
if ([[[[self context] request] formValueForKey: @"nojs"] intValue]) // if ([[[[self context] request] formValueForKey: @"nojs"] intValue])
result = [self redirectToLocation: [self modulePath]]; // result = [self redirectToLocation: [self modulePath]];
else // else
{ // {
jsRefreshMethod = [NSString stringWithFormat: @"refreshContacts('%@')", // jsRefreshMethod
[contact nameInContainer]]; // = [NSString stringWithFormat: @"refreshContacts(\"%@\")",
result = [self jsCloseWithRefreshMethod: jsRefreshMethod]; // [contact nameInContainer]];
} // result = [self jsCloseWithRefreshMethod: jsRefreshMethod];
// }
return result; return response;
} }
- (id) writeAction - (id) writeAction

View File

@ -36,6 +36,7 @@
#import <Contacts/SOGoContactObject.h> #import <Contacts/SOGoContactObject.h>
#import <Contacts/SOGoContactFolder.h> #import <Contacts/SOGoContactFolder.h>
#import <Contacts/SOGoContactFolders.h> #import <Contacts/SOGoContactFolders.h>
#import <Contacts/SOGoContactGCSFolder.h>
#import <Contacts/NSDictionary+LDIF.h> #import <Contacts/NSDictionary+LDIF.h>
#import <SoObjects/Contacts/NGVCard+SOGo.h> #import <SoObjects/Contacts/NGVCard+SOGo.h>
@ -46,6 +47,8 @@
#import <SoObjects/Contacts/SOGoContactGCSFolder.h> #import <SoObjects/Contacts/SOGoContactGCSFolder.h>
#import <GDLContentStore/GCSFolder.h> #import <GDLContentStore/GCSFolder.h>
#import <SOGo/NSString+Utilities.h>
#import "UIxContactFolderActions.h" #import "UIxContactFolderActions.h"
@implementation UIxContactFolderActions @implementation UIxContactFolderActions
@ -276,6 +279,7 @@
uid = [folder globallyUniqueObjectId]; uid = [folder globallyUniqueObjectId];
[card setUid: uid]; [card setUid: uid];
// TODO: shall we add .vcf as in [SOGoContactGCSEntry copyToFolder:]
contact = [SOGoContactGCSEntry objectWithName: uid contact = [SOGoContactGCSEntry objectWithName: uid
inContainer: folder]; inContainer: folder];
[contact setIsNew: YES]; [contact setIsNew: YES];
@ -288,4 +292,33 @@
return rc; return rc;
} }
- (id <WOActionResults>) saveAction
{
SOGoContactGCSFolder *folder;
WORequest *request;
WOResponse *response;
NSDictionary *params, *message;
NSString *folderName;
request = [context request];
NSLog(@"%@", [request contentAsString]);
params = [[request contentAsString] objectFromJSONString];
folderName = [params objectForKey: @"name"];
if ([folderName length] > 0)
{
folder = [self clientObject];
[folder renameTo: folderName];
response = [self responseWith204];
}
else
{
message = [NSDictionary dictionaryWithObject: @"Missing name parameter" forKey: @"error"];
response = [self responseWithStatus: 500
andString: [message jsonRepresentation]];
}
return response;
}
@end /* UIxContactFolderActions */ @end /* UIxContactFolderActions */

View File

@ -32,18 +32,18 @@
NSDictionary *currentContact; NSDictionary *currentContact;
NSString *selectorComponentClass; NSString *selectorComponentClass;
NSMutableDictionary *moduleSettings; NSMutableDictionary *moduleSettings;
id currentFolder; //id currentFolder;
BOOL contextIsSetup; BOOL contextIsSetup;
} }
- (NSArray *) contactFolders; - (NSString *) contactFolders;
- (NSArray *) personalContactInfos; - (NSArray *) personalContactInfos;
- (NSString *) currentContactFolderId; // - (NSString *) currentContactFolderId;
- (NSString *) currentContactFolderOwner; // - (NSString *) currentContactFolderOwner;
- (NSString *) currentContactFolderName; // - (NSString *) currentContactFolderName;
- (NSString *) currentContactFolderClass; // - (NSString *) currentContactFolderClass;
- (WOResponse *) saveDragHandleStateAction; - (WOResponse *) saveDragHandleStateAction;

View File

@ -22,6 +22,7 @@
#import <Foundation/NSDictionary.h> #import <Foundation/NSDictionary.h>
#import <Foundation/NSEnumerator.h> #import <Foundation/NSEnumerator.h>
#import <Foundation/NSString.h> #import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#import <NGObjWeb/NSException+HTTP.h> #import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/SoObject.h> #import <NGObjWeb/SoObject.h>
@ -158,23 +159,88 @@ Class SOGoContactSourceFolderK, SOGoGCSFolderK;
- (id <WOActionResults>) allContactSearchAction - (id <WOActionResults>) allContactSearchAction
{ {
id <WOActionResults> result; id <WOActionResults> result;
NSString *searchText; SOGoFolder <SOGoContactFolder> *folder;
NSString *searchText, *mail, *domain;
NSDictionary *data; NSDictionary *data;
NSArray *sortedContacts; NSArray *folders, *contacts, *descriptors, *sortedContacts;
NSMutableArray *sortedFolders;
NSMutableDictionary *contact, *uniqueContacts;
unsigned int i, j, max;
NSSortDescriptor *commonNameDescriptor;
BOOL excludeGroups, excludeLists; BOOL excludeGroups, excludeLists;
searchText = [self queryParameterForKey: @"search"]; searchText = [self queryParameterForKey: @"search"];
if ([searchText length] > 0) if ([searchText length] > 0)
{ {
// NSLog(@"Search all contacts: %@", searchText);
excludeGroups = [[self queryParameterForKey: @"excludeGroups"] boolValue]; excludeGroups = [[self queryParameterForKey: @"excludeGroups"] boolValue];
excludeLists = [[self queryParameterForKey: @"excludeLists"] boolValue]; excludeLists = [[self queryParameterForKey: @"excludeLists"] boolValue];
domain = [[context activeUser] domain];
sortedContacts = [[self clientObject] allContactsFromFilter: searchText folders = nil;
excludeGroups: excludeGroups NS_DURING
excludeLists: excludeLists]; folders = [[self clientObject] subFolders];
NS_HANDLER
/* We need to specifically test for @"SOGoDBException", which is
raised explicitly in SOGoParentFolder. Any other exception should
be re-raised. */
if ([[localException name] isEqualToString: @"SOGoDBException"])
folders = nil;
else
[localException raise];
NS_ENDHANDLER;
max = [folders count];
sortedFolders = [NSMutableArray arrayWithCapacity: max];
uniqueContacts = [NSMutableDictionary dictionary];
for (i = 0; i < max; i++)
{
folder = [folders objectAtIndex: i];
/* We first search in LDAP folders (in case of duplicated entries in GCS folders) */
if ([folder isKindOfClass: SOGoContactSourceFolderK])
[sortedFolders insertObject: folder atIndex: 0];
else
[sortedFolders addObject: folder];
}
for (i = 0; i < max; i++)
{
folder = [sortedFolders objectAtIndex: i];
//NSLog(@" Address book: %@ (%@)", [folder displayName], [folder class]);
contacts = [folder lookupContactsWithFilter: searchText
onCriteria: @"name_or_address"
sortBy: @"c_cn"
ordering: NSOrderedAscending
inDomain: domain];
for (j = 0; j < [contacts count]; j++)
{
contact = [contacts objectAtIndex: j];
mail = [contact objectForKey: @"c_mail"];
//NSLog(@" found %@ (%@) ? %@", [contact objectForKey: @"c_name"], mail,
// [contact description]);
if (!excludeLists && [[contact objectForKey: @"c_component"]
isEqualToString: @"vlist"])
{
[contact setObject: [folder nameInContainer]
forKey: @"container"];
[uniqueContacts setObject: contact
forKey: [contact objectForKey: @"c_name"]];
}
else if ([mail length]
&& [uniqueContacts objectForKey: mail] == nil
&& !(excludeGroups && [contact objectForKey: @"isGroup"]))
[uniqueContacts setObject: contact forKey: mail];
}
}
if ([uniqueContacts count] > 0)
{
// Sort the contacts by display name
commonNameDescriptor = [[NSSortDescriptor alloc] initWithKey: @"c_cn"
ascending:YES];
descriptors = [NSArray arrayWithObjects: commonNameDescriptor, nil];
[commonNameDescriptor release];
sortedContacts = [[uniqueContacts allValues]
sortedArrayUsingDescriptors: descriptors];
}
else
sortedContacts = [NSArray array];
data = [NSDictionary dictionaryWithObjectsAndKeys: searchText, @"searchText", data = [NSDictionary dictionaryWithObjectsAndKeys: searchText, @"searchText",
sortedContacts, @"contacts", sortedContacts, @"contacts",
nil]; nil];
@ -208,48 +274,72 @@ Class SOGoContactSourceFolderK, SOGoGCSFolderK;
return [[self queryParameterForKey: @"popup"] boolValue]; return [[self queryParameterForKey: @"popup"] boolValue];
} }
- (NSArray *) contactFolders - (NSString *) contactFolders
{ {
SOGoContactFolders *folderContainer; SOGoContactFolders *folderContainer;
NSArray *folders;
NSMutableArray *foldersAttrs;
NSDictionary *folderAttrs;
id currentFolder;
int max, i;
folderContainer = [self clientObject]; folderContainer = [self clientObject];
return [folderContainer subFolders]; // return [folderContainer subFolders];
folders = [folderContainer subFolders];
max = [folders count];
foldersAttrs = [NSMutableArray arrayWithCapacity: max];
for (i = 0; i < max; i++)
{
currentFolder = [folders objectAtIndex: i];
folderAttrs = [NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat: @"%@", [currentFolder nameInContainer]], @"id",
[currentFolder displayName], @"name",
[currentFolder ownerInContext: context], @"owner",
[NSNumber numberWithBool: [currentFolder isKindOfClass: SOGoGCSFolderK]], @"isEditable",
[NSNumber numberWithBool: [currentFolder isKindOfClass: SOGoContactSourceFolderK]
&& ![currentFolder isPersonalSource]], @"isRemote",
nil];
[foldersAttrs addObject: folderAttrs];
}
return [foldersAttrs jsonRepresentation];
} }
- (NSString *) currentContactFolderId // - (NSString *) currentContactFolderId
{ // {
return [NSString stringWithFormat: @"/%@", [currentFolder nameInContainer]]; // return [NSString stringWithFormat: @"/%@", [currentFolder nameInContainer]];
} // }
- (NSString *) currentContactFolderName // - (NSString *) currentContactFolderName
{ // {
return [currentFolder displayName]; // return [currentFolder displayName];
} // }
- (NSString *) currentContactFolderOwner // - (NSString *) currentContactFolderOwner
{ // {
return [currentFolder ownerInContext: context]; // return [currentFolder ownerInContext: context];
} //}
- (NSString *) currentContactFolderClass // - (NSString *) currentContactFolderClass
{ // {
return (([currentFolder isKindOfClass: SOGoContactSourceFolderK] // return (([currentFolder isKindOfClass: SOGoContactSourceFolderK]
&& ![currentFolder isPersonalSource]) // && ![currentFolder isPersonalSource])
? @"remote" : @"local"); // ? @"remote" : @"local");
} // }
- (NSString *) currentContactFolderAclEditing // - (NSString *) currentContactFolderAclEditing
{ // {
return ([currentFolder isKindOfClass: SOGoGCSFolderK] // return ([currentFolder isKindOfClass: SOGoGCSFolderK]
? @"available": @"unavailable"); // ? @"available": @"unavailable");
} // }
- (NSString *) currentContactFolderListEditing // - (NSString *) currentContactFolderListEditing
{ // {
return ([currentFolder isKindOfClass: SOGoGCSFolderK] // return ([currentFolder isKindOfClass: SOGoGCSFolderK]
? @"available": @"unavailable"); // ? @"available": @"unavailable");
} //}
- (NSString *) verticalDragHandleStyle - (NSString *) verticalDragHandleStyle
{ {

View File

@ -36,6 +36,8 @@
} }
- (NSString *) fullName; - (NSString *) fullName;
- (NSArray *) orgUnits;
- (NSString *) photoURL;
@end @end

View File

@ -21,6 +21,7 @@
*/ */
#import <Foundation/NSURL.h> #import <Foundation/NSURL.h>
#import <Foundation/NSValue.h>
#import <NGObjWeb/NSException+HTTP.h> #import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/WOResponse.h> #import <NGObjWeb/WOResponse.h>
@ -31,9 +32,13 @@
#import <NGExtensions/NSString+Ext.h> #import <NGExtensions/NSString+Ext.h>
#import <NGExtensions/NSString+misc.h> #import <NGExtensions/NSString+misc.h>
#import <SOGo/CardElement+SOGo.h>
#import <SOGo/NSArray+Utilities.h>
#import <SOGo/NSCalendarDate+SOGo.h> #import <SOGo/NSCalendarDate+SOGo.h>
#import <SOGo/NSDictionary+Utilities.h>
#import <SOGo/SOGoDateFormatter.h> #import <SOGo/SOGoDateFormatter.h>
#import <SOGo/SOGoUser.h> #import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserDefaults.h>
#import <Contacts/NGVCard+SOGo.h> #import <Contacts/NGVCard+SOGo.h>
#import <Contacts/SOGoContactObject.h> #import <Contacts/SOGoContactObject.h>
@ -130,6 +135,45 @@
return [card fullName]; return [card fullName];
} }
- (NSArray *) _languageContactsCategories
{
NSArray *categoryLabels;
categoryLabels = [[self labelForKey: @"contacts_category_labels"] componentsSeparatedByString: @","];
if (!categoryLabels)
categoryLabels = [NSArray array];
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)
{
newCats = [cats mergedArrayWithArray: contactCategories];
if ([newCats count] != [cats count])
{
cats = [newCats sortedArrayUsingSelector:
@selector (localizedCaseInsensitiveCompare:)];
[ud setContactsCategories: cats];
[ud synchronize];
}
}
return cats;
}
- (NSString *) primaryEmail - (NSString *) primaryEmail
{ {
NSString *email, *fn, *attrs; NSString *email, *fn, *attrs;
@ -236,14 +280,14 @@
return @""; return @"";
} }
- (NSString *) categories // - (NSString *) categories
{ // {
NSString *categories; // NSString *categories;
categories = [[card categories] componentsJoinedByString: @", "]; // categories = [[card categories] componentsJoinedByString: @", "];
return [self _cardStringWithLabel: @"Categories:" // return [self _cardStringWithLabel: @"Categories:"
value: categories]; // value: categories];
} // }
- (BOOL) hasTelephones - (BOOL) hasTelephones
{ {
@ -479,6 +523,101 @@
return [self _cardStringWithLabel: nil value: [card title]]; return [self _cardStringWithLabel: nil value: [card title]];
} }
- (NSArray *) orgUnits
{
NSMutableArray *orgUnits;
NSArray *values;
CardElement *org;
NSString *service;
NSUInteger count, max;
org = [card org];
values = [org valuesForKey: @""];
max = [values count];
if (max > 1)
{
orgUnits = [NSMutableArray arrayWithCapacity: max];
for (count = 1; count < max; count++)
{
service = [org flattenedValueAtIndex: count forKey: @""];
if ([service length] > 0)
[orgUnits addObject: [NSDictionary dictionaryWithObject: service forKey: @"value"]];
}
}
else
orgUnits = nil;
return orgUnits;
}
- (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;
}
- (NSArray *) deliveryAddresses
{
NSMutableArray *addresses;
NSMutableDictionary *address;
NSArray *elements;
NSString *type, *postoffice, *street, *street2, *locality, *region, *postalcode, *country;
CardElement *adr;
NSUInteger count, max;
elements = [card childrenWithTag: @"adr"];
//values = [org valuesForKey: @""];
max = [elements count];
if (max > 0)
{
addresses = [NSMutableArray arrayWithCapacity: max];
for (count = 1; count < max; count++)
{
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: @""];
address = [NSMutableDictionary dictionaryWithObject: type forKey: @"type"];
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;
}
- (NSString *) workService - (NSString *) workService
{ {
NSMutableArray *orgServices; NSMutableArray *orgServices;
@ -595,13 +734,14 @@
bday = [dateFormatter formattedDate: date]; bday = [dateFormatter formattedDate: date];
} }
return [self _cardStringWithLabel: @"Birthday:" value: bday]; return bday;
//return [self _cardStringWithLabel: @"Birthday:" value: bday];
} }
- (NSString *) tz // - (NSString *) tz
{ // {
return [self _cardStringWithLabel: @"Timezone:" value: [card tz]]; // return [self _cardStringWithLabel: @"Timezone:" value: [card tz]];
} // }
- (NSString *) note - (NSString *) note
{ {
@ -617,11 +757,8 @@
withString: @"<br />"]; withString: @"<br />"];
} }
return [self _cardStringWithLabel: @"Note:" return note;
value: note //return [self _cardStringWithLabel: @"Note:" value: note];
byEscapingHTMLString: NO
asLinkScheme: nil
withLinkAttributes: nil];
} }
/* hrefs */ /* hrefs */
@ -669,6 +806,111 @@
return self; return self;
} }
- (id <WOActionResults>) dataAction
{
id <WOActionResults> result;
id o;
SOGoObject <SOGoContactObject> *contact;
// NSMutableArray *description;
NSMutableDictionary *data;
contact = [self clientObject];
card = [contact vCard];
if (card)
{
[card retain];
phones = nil;
homeAdr = nil;
workAdr = nil;
NSLog(@"%@", [card versitString]);
}
else
return [NSException exceptionWithHTTPStatus: 404 /* Not Found */
reason: @"could not locate contact"];
// description = [NSMutableArray array];
data = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[[contact container] nameInContainer], @"pid",
[contact nameInContainer], @"id",
[card tag], @"tag",
nil];
o = [card fn];
if (o) [data setObject: o forKey: @"fn"];
o = [card n];
if (o)
{
NSString *lastName = [o flattenedValueAtIndex: 0 forKey: @""];
NSString *firstName = [o flattenedValueAtIndex: 1 forKey: @""];
if ([lastName length] > 0)
[data setObject: lastName forKey: @"sn"];
if ([firstName length] > 0)
[data setObject: firstName forKey: @"givenname"];
}
o = [card nickname];
if (o) [data setObject: o forKey: @"nickname"];
// o = [card fullName];
// if (o) [data setObject: o forKey: @"fullname"];
o = [card title];
if ([o length] > 0)
{
[data setObject: o forKey: @"title"];
// [description addObject: o];
}
o = [card role];
if ([o length] > 0)
{
[data setObject: o forKey: @"role"];
// [description addObject: o];
}
o = [self orgUnits];
if ([o count] > 0)
{
[data setObject: o forKey: @"orgUnits"];
// [description addObjectsFromArray: o];
}
o = [card workCompany];
if ([o length] > 0)
{
[data setObject: o forKey: @"org"];
// [description addObject: o];
}
// if ([description count]) [data setObject: description forKey: @"description"];
o = [card birthday];
if (o)
{
NSNumber *time = [NSNumber numberWithInt: [o timeIntervalSince1970]];
[data setObject: time forKey: @"birthday"];
}
// o = [card source];
// if (o) [data setObject: o forKey: @"source"];
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"];
o = [card childrenWithTag: @"url"];
if ([o count]) [data setObject: o forKey: @"urls"];
o = [self note];
if (o) [data setObject: o forKey: @"note"];
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]];
return result;
}
- (BOOL) hasPhoto - (BOOL) hasPhoto
{ {
return [[self clientObject] hasPhoto]; return [[self clientObject] hasPhoto];

View File

@ -128,6 +128,7 @@
{ {
id <WOActionResults> result; id <WOActionResults> result;
id currentInfo; id currentInfo;
NSDictionary *data;
NSArray *contactsList; NSArray *contactsList;
NSEnumerator *contactsListEnumerator, *keysEnumerator; NSEnumerator *contactsListEnumerator, *keysEnumerator;
NSMutableArray *newContactsList; NSMutableArray *newContactsList;
@ -151,8 +152,13 @@
[newContactsList addObject: currentContactDictionary]; [newContactsList addObject: currentContactDictionary];
} }
data = [NSDictionary dictionaryWithObjectsAndKeys:
[[self clientObject] nameInContainer], @"id",
newContactsList, @"contacts",
nil];
result = [self responseWithStatus: 200 result = [self responseWithStatus: 200
andString: [newContactsList jsonRepresentation]]; andString: [data jsonRepresentation]];
return result; return result;
} }

View File

@ -1,8 +1,6 @@
/* UIxListView.m - this file is part of SOGo /* UIxListView.m - this file is part of SOGo
* *
* Copyright (C) 2008-2009 Inverse inc. * Copyright (C) 2008-2014 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* *
* This file is free software; you can redistribute it and/or modify * This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -27,6 +25,7 @@
#import <NGCards/NGVCardReference.h> #import <NGCards/NGVCardReference.h>
#import <SOGo/NSArray+Utilities.h> #import <SOGo/NSArray+Utilities.h>
#import <SOGo/NSDictionary+Utilities.h>
#import "UIxListView.h" #import "UIxListView.h"
@ -141,6 +140,54 @@
return rc; return rc;
} }
- (id <WOActionResults>) dataAction
{
id <WOActionResults> result;
NSMutableDictionary *data;
NSMutableArray *cards;
NGVCardReference *card;
int i, count;
co = [self clientObject];
list = [co vList];
if (list)
{
[self checkListReferences];
}
else
return [NSException exceptionWithHTTPStatus: 404 /* Not Found */
reason: @"could not locate contact"];
count = [[list cardReferences] count];
cards = [NSMutableArray arrayWithCapacity: count];
for (i = 0; i < count; i++)
{
card = [[list cardReferences] objectAtIndex: i];
[cards addObject: [NSDictionary dictionaryWithObjectsAndKeys:
[card reference], @"reference",
[card fn], @"fn",
[card email], @"email",
nil]];
}
data = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[[co container] nameInContainer], @"pid",
[co nameInContainer], @"id",
[list tag], @"tag",
[list fn], @"fn",
[list description], @"description",
cards, @"refs",
nil];
// [list cardReferences]
result = [self responseWithStatus: 200
andString: [data jsonRepresentation]];
return result;
}
- (WOResponse *) propertiesAction - (WOResponse *) propertiesAction
{ {
NSArray *references; NSArray *references;

View File

@ -74,6 +74,11 @@
actionClass = "UIxContactsListActions"; actionClass = "UIxContactsListActions";
actionName = "contactsList"; actionName = "contactsList";
}; };
// contacts = {
// protectedBy = "View";
// actionClass = "UIxContactsListActions";
// actionName = "contactsList";
// };
contactSearch = { contactSearch = {
protectedBy = "<public>"; protectedBy = "<public>";
actionClass = "UIxContactsListActions"; actionClass = "UIxContactsListActions";
@ -109,6 +114,11 @@
actionClass = "UIxContactFolderActions"; actionClass = "UIxContactFolderActions";
actionName = "import"; actionName = "import";
}; };
save = {
protectedBy = "Change Permissions";
actionClass = "UIxContactFolderActions";
actionName = "save";
};
userRights = { userRights = {
protectedBy = "ReadAcls"; protectedBy = "ReadAcls";
pageName = "UIxContactsUserRightsEditor"; pageName = "UIxContactsUserRightsEditor";
@ -171,6 +181,7 @@
view = { view = {
protectedBy = "Access Contents Information"; protectedBy = "Access Contents Information";
pageName = "UIxContactView"; pageName = "UIxContactView";
actionName = "data";
}; };
edit = { edit = {
protectedBy = "Access Contents Information"; protectedBy = "Access Contents Information";
@ -218,6 +229,7 @@
view = { view = {
protectedBy = "Access Contents Information"; protectedBy = "Access Contents Information";
pageName = "UIxListView"; pageName = "UIxListView";
actionName = "data";
}; };
properties = { properties = {
protectedBy = "Access Contents Information"; protectedBy = "Access Contents Information";