491 lines
13 KiB
Objective-C
491 lines
13 KiB
Objective-C
/*
|
|
Copyright (C) 2004-2005 SKYRIX Software AG
|
|
Copyright (C) 2005-2015 Inverse inc.
|
|
|
|
This file is part of SOGo
|
|
|
|
SOGo is free software; you can redistribute it and/or modify it under
|
|
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.
|
|
|
|
SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
|
License for more details.
|
|
|
|
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.
|
|
*/
|
|
|
|
#import <Foundation/NSDictionary.h>
|
|
#import <Foundation/NSString.h>
|
|
#import <Foundation/NSURL.h>
|
|
#import <Foundation/NSEnumerator.h>
|
|
|
|
#import <NGObjWeb/NSException+HTTP.h>
|
|
#import <NGObjWeb/SoPermissions.h>
|
|
#import <NGObjWeb/SoSecurityManager.h>
|
|
#import <NGObjWeb/SoObject.h>
|
|
#import <NGObjWeb/WORequest.h>
|
|
#import <NGObjWeb/WOResponse.h>
|
|
#import <NGExtensions/NSNull+misc.h>
|
|
|
|
#import <NGCards/NGVCard.h>
|
|
|
|
#import <SOGo/NSArray+Utilities.h>
|
|
#import <SOGo/NSString+Utilities.h>
|
|
#import <SOGo/SOGoUser.h>
|
|
#import <SOGo/SOGoUserDefaults.h>
|
|
|
|
#import <Contacts/SOGoContactFolder.h>
|
|
#import <Contacts/SOGoContactFolders.h>
|
|
#import <Contacts/SOGoContactObject.h>
|
|
#import <Contacts/SOGoContactGCSEntry.h>
|
|
#import <Contacts/SOGoContactGCSFolder.h>
|
|
|
|
#import "UIxContactEditor.h"
|
|
|
|
static Class SOGoContactGCSEntryK = Nil;
|
|
|
|
@implementation UIxContactEditor
|
|
|
|
+ (void) initialize
|
|
{
|
|
SOGoContactGCSEntryK = [SOGoContactGCSEntry class];
|
|
}
|
|
|
|
- (id) init
|
|
{
|
|
if ((self = [super init]))
|
|
{
|
|
ldifRecord = nil;
|
|
addressBookItem = nil;
|
|
item = nil;
|
|
componentAddressBook = nil;
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void) dealloc
|
|
{
|
|
[ldifRecord release];
|
|
[addressBookItem release];
|
|
[item release];
|
|
[componentAddressBook release];
|
|
[super dealloc];
|
|
}
|
|
|
|
/* accessors */
|
|
|
|
- (NSMutableDictionary *) ldifRecord
|
|
{
|
|
NSDictionary *clientLDIFRecord;
|
|
NSString *queryValue;
|
|
|
|
if (!ldifRecord)
|
|
{
|
|
clientLDIFRecord = [[self clientObject] simplifiedLDIFRecord];
|
|
ldifRecord = [clientLDIFRecord mutableCopy];
|
|
queryValue = [self queryParameterForKey: @"contactEmail"];
|
|
if ([queryValue length] > 0)
|
|
[ldifRecord setObject: queryValue forKey: @"mail"];
|
|
queryValue = [self queryParameterForKey: @"contactFN"];
|
|
if ([queryValue length] > 0)
|
|
[ldifRecord setObject: queryValue forKey: @"displayname"];
|
|
}
|
|
|
|
return ldifRecord;
|
|
}
|
|
|
|
- (void) setAddressBookItem: (id) _item
|
|
{
|
|
ASSIGN (addressBookItem, _item);
|
|
}
|
|
|
|
- (id) addressBookItem
|
|
{
|
|
return addressBookItem;
|
|
}
|
|
|
|
- (NSString *) saveURL
|
|
{
|
|
return [NSString stringWithFormat: @"%@/saveAsContact",
|
|
[[self clientObject] baseURL]];
|
|
}
|
|
|
|
- (NSArray *) htmlMailFormatList
|
|
{
|
|
static NSArray *htmlMailFormatItems = nil;
|
|
|
|
if (!htmlMailFormatItems)
|
|
{
|
|
htmlMailFormatItems = [NSArray arrayWithObjects: @"FALSE", @"TRUE", nil];
|
|
[htmlMailFormatItems retain];
|
|
}
|
|
|
|
return htmlMailFormatItems;
|
|
}
|
|
|
|
- (NSString *) itemHtmlMailFormatText
|
|
{
|
|
return [self labelForKey:
|
|
[NSString stringWithFormat: @"htmlMailFormat_%@", item]];
|
|
}
|
|
|
|
- (void) setItem: (NSString *) newItem
|
|
{
|
|
item = newItem;
|
|
}
|
|
|
|
- (NSString *) item
|
|
{
|
|
return item;
|
|
}
|
|
|
|
/* load/store content format */
|
|
|
|
/* helper */
|
|
|
|
- (NSString *) _completeURIForMethod: (NSString *) _method
|
|
{
|
|
// TODO: this is a DUP of UIxAppointmentEditor
|
|
NSString *uri;
|
|
NSRange r;
|
|
|
|
uri = [[[self context] request] uri];
|
|
|
|
/* first: identify query parameters */
|
|
r = [uri rangeOfString: @"?" options:NSBackwardsSearch];
|
|
if (r.length > 0)
|
|
uri = [uri substringToIndex:r.location];
|
|
|
|
/* next: append trailing slash */
|
|
if (![uri hasSuffix: @"/"])
|
|
uri = [uri stringByAppendingString: @"/"];
|
|
|
|
/* next: append method */
|
|
uri = [uri stringByAppendingString:_method];
|
|
|
|
/* next: append query parameters */
|
|
return [self completeHrefForMethod:uri];
|
|
}
|
|
|
|
- (BOOL) isNew
|
|
{
|
|
return ([[self clientObject] isNew]);
|
|
}
|
|
|
|
- (NSArray *) addressBooksList
|
|
{
|
|
NSEnumerator *folders;
|
|
NSMutableArray *addressBooksList;
|
|
SoSecurityManager *sm;
|
|
SOGoContactFolders *folderContainer;
|
|
id <SOGoContactFolder> folder, currentFolder;
|
|
|
|
addressBooksList = [NSMutableArray array];
|
|
sm = [SoSecurityManager sharedSecurityManager];
|
|
folderContainer = [[[self clientObject] container] container];
|
|
folders = [[folderContainer subFolders] objectEnumerator];
|
|
folder = [self componentAddressBook];
|
|
currentFolder = [folders nextObject];
|
|
|
|
while (currentFolder)
|
|
{
|
|
if ([currentFolder isEqual: folder] ||
|
|
![sm validatePermission: SoPerm_AddDocumentsImagesAndFiles
|
|
onObject: currentFolder
|
|
inContext: context])
|
|
[addressBooksList addObject: currentFolder];
|
|
currentFolder = [folders nextObject];
|
|
}
|
|
|
|
return addressBooksList;
|
|
}
|
|
|
|
- (id <SOGoContactFolder>) componentAddressBook
|
|
{
|
|
return [[self clientObject] container];
|
|
}
|
|
|
|
- (void) setComponentAddressBook: (id <SOGoContactFolder>) _componentAddressBook
|
|
{
|
|
ASSIGN (componentAddressBook, _componentAddressBook);
|
|
}
|
|
|
|
- (NSString *) addressBookDisplayName
|
|
{
|
|
return [addressBookItem displayName];
|
|
}
|
|
|
|
- (BOOL) supportCategories
|
|
{
|
|
return [[self clientObject] isKindOfClass: SOGoContactGCSEntryK];
|
|
}
|
|
|
|
- (void) setJsonContactCategories: (NSString *) jsonCategories
|
|
{
|
|
NSArray *newCategories;
|
|
|
|
newCategories = [jsonCategories objectFromJSONString];
|
|
if ([newCategories isKindOfClass: [NSArray class]])
|
|
[[self ldifRecord] setObject: newCategories
|
|
forKey: @"vcardcategories"];
|
|
else
|
|
[[self ldifRecord] removeObjectForKey: @"vcardcategories"];
|
|
}
|
|
|
|
- (NSString *) jsonContactCategories
|
|
{
|
|
NSArray *categories;
|
|
|
|
categories = [[self ldifRecord] objectForKey: @"vcardcategories"];
|
|
|
|
return [categories jsonRepresentation];
|
|
}
|
|
|
|
- (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 = [[self ldifRecord] objectForKey: @"vcardcategories"];
|
|
if (contactCategories)
|
|
{
|
|
newCats = [cats mergedArrayWithArray: contactCategories];
|
|
if ([newCats count] != [cats count])
|
|
{
|
|
cats = [newCats sortedArrayUsingSelector:
|
|
@selector (localizedCaseInsensitiveCompare:)];
|
|
[ud setContactsCategories: cats];
|
|
[ud synchronize];
|
|
}
|
|
}
|
|
|
|
return cats;
|
|
}
|
|
|
|
- (NSString *) contactCategoriesList
|
|
{
|
|
NSArray *cats;
|
|
NSString *list;
|
|
|
|
cats = [self _fetchAndCombineCategoriesList];
|
|
list = [cats jsonRepresentation];
|
|
if (!list)
|
|
list = @"[]";
|
|
|
|
return list;
|
|
}
|
|
|
|
/* actions */
|
|
|
|
// - (BOOL) shouldTakeValuesFromRequest: (WORequest *) request
|
|
// inContext: (WOContext*) context
|
|
// {
|
|
// NSString *actionName;
|
|
//
|
|
// actionName = [[request requestHandlerPath] lastPathComponent];
|
|
//
|
|
// return ([actionName hasPrefix: @"save"]);
|
|
// }
|
|
|
|
- (NSString *) viewActionName
|
|
{
|
|
/* this is overridden in the mail based contacts UI to redirect to tb.edit */
|
|
return @"";
|
|
}
|
|
|
|
- (NSString *) editActionName
|
|
{
|
|
/* this is overridden in the mail based contacts UI to redirect to tb.edit */
|
|
return @"editAsContact";
|
|
}
|
|
|
|
- (BOOL) supportPhotos
|
|
{
|
|
return [[self clientObject] isKindOfClass: SOGoContactGCSEntryK];
|
|
}
|
|
|
|
- (BOOL) hasPhoto
|
|
{
|
|
return [[self clientObject] hasPhoto];
|
|
}
|
|
|
|
- (NSString *) photoURL
|
|
{
|
|
NSURL *soURL;
|
|
|
|
soURL = [[self clientObject] soURL];
|
|
|
|
return [NSString stringWithFormat: @"%@/photo", [soURL absoluteString]];
|
|
}
|
|
|
|
- (id <WOActionResults>) saveAction
|
|
{
|
|
SOGoObject <SOGoContactObject> *contact;
|
|
WORequest *request;
|
|
WOResponse *response;
|
|
//id result;
|
|
NSDictionary *params;
|
|
//NSString *jsRefreshMethod;
|
|
SoSecurityManager *sm;
|
|
|
|
contact = [self clientObject];
|
|
request = [context request];
|
|
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];
|
|
|
|
// if (componentAddressBook && componentAddressBook != [self componentAddressBook])
|
|
// {
|
|
// if ([contact isKindOfClass: SOGoContactGCSEntryK])
|
|
// {
|
|
// sm = [SoSecurityManager sharedSecurityManager];
|
|
// if (![sm validatePermission: SoPerm_DeleteObjects
|
|
// onObject: componentAddressBook
|
|
// inContext: context]
|
|
// && ![sm validatePermission: SoPerm_AddDocumentsImagesAndFiles
|
|
// onObject: componentAddressBook
|
|
// inContext: context])
|
|
// [(SOGoContactGCSEntry *) contact
|
|
// moveToFolder: (SOGoGCSFolder *)componentAddressBook]; // TODO:
|
|
// // handle
|
|
// // exception
|
|
// }
|
|
// }
|
|
|
|
// if ([[[[self context] request] formValueForKey: @"nojs"] intValue])
|
|
// result = [self redirectToLocation: [self modulePath]];
|
|
// else
|
|
// {
|
|
// jsRefreshMethod
|
|
// = [NSString stringWithFormat: @"refreshContacts(\"%@\")",
|
|
// [contact nameInContainer]];
|
|
// result = [self jsCloseWithRefreshMethod: jsRefreshMethod];
|
|
// }
|
|
|
|
return response;
|
|
}
|
|
|
|
- (id) writeAction
|
|
{
|
|
NSString *email, *cn, *url;
|
|
NSMutableString *address;
|
|
|
|
[self ldifRecord];
|
|
email = [ldifRecord objectForKey: @"mail"];
|
|
if ([email length] == 0)
|
|
email = [ldifRecord objectForKey: @"mozillasecondemail"];
|
|
|
|
if (email)
|
|
{
|
|
address = [NSMutableString string];
|
|
cn = [ldifRecord objectForKey: @"cn"];
|
|
if ([cn length] > 0)
|
|
[address appendFormat: @"%@ <%@>", cn, email];
|
|
else
|
|
[address appendString: email];
|
|
|
|
url = [NSString stringWithFormat: @"%@/Mail/compose?mailto=%@",
|
|
[self userFolderPath], address];
|
|
}
|
|
else
|
|
url = [NSString stringWithFormat: @"%@/Mail/compose", [self userFolderPath]];
|
|
|
|
return [self redirectToLocation: url];
|
|
}
|
|
|
|
#warning Could this be part of a common parent with UIxAppointment/UIxTaskEditor/UIxListEditor ?
|
|
- (id) newAction
|
|
{
|
|
NSString *objectId, *method, *uri;
|
|
id <WOActionResults> result;
|
|
SOGoContactGCSFolder *co;
|
|
SoSecurityManager *sm;
|
|
|
|
co = [self clientObject];
|
|
objectId = [co globallyUniqueObjectId];
|
|
if ([objectId length] > 0)
|
|
{
|
|
sm = [SoSecurityManager sharedSecurityManager];
|
|
if (![sm validatePermission: SoPerm_AddDocumentsImagesAndFiles
|
|
onObject: co
|
|
inContext: context])
|
|
{
|
|
method = [NSString stringWithFormat: @"%@/%@.vcf/editAsContact",
|
|
[co soURL], objectId];
|
|
}
|
|
else
|
|
{
|
|
method = [NSString stringWithFormat: @"%@/Contacts/personal/%@.vcf/editAsContact",
|
|
[self userFolderPath], objectId];
|
|
}
|
|
uri = [self completeHrefForMethod: method];
|
|
result = [self redirectToLocation: uri];
|
|
}
|
|
else
|
|
result = [NSException exceptionWithHTTPStatus: 500 /* Internal Error */
|
|
reason: @"could not create a unique ID"];
|
|
|
|
return result;
|
|
}
|
|
|
|
@end /* UIxContactEditor */
|
|
|