merge of '36df3bcfd6c56f483f2676ceb6b6757a6506dbb7'

and 'f12c75a72aac13edc9728fe5a656c622487836dd'

Monotone-Parent: 36df3bcfd6c56f483f2676ceb6b6757a6506dbb7
Monotone-Parent: f12c75a72aac13edc9728fe5a656c622487836dd
Monotone-Revision: 0c622c14bea584c75539ec4bf9d8ca29899745ef

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2007-09-14T22:05:54
Monotone-Branch: ca.inverse.sogo
This commit is contained in:
Wolfgang Sourdeau 2007-09-14 22:05:54 +00:00
commit d4c43b432e
80 changed files with 1299 additions and 1111 deletions

View file

@ -1,3 +1,22 @@
2007-09-14 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/SOGo/SOGoObject.m ([SOGoObject -labelForKey:key]): new
method that returns translated strings for controller bundles
(same as what UIxComponent does for view bundles).
([SOGoObject -pathArrayToSOGoObject]): new method that returns
the real path to a subscribed folder (if subscribed).
([SOGoObject +globallyUniqueObjectId]): move method from SOGoFolder.
([SOGoObject -globallyUniqueObjectId]): new instance method
calling its class equivalent.
2007-09-12 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* UI/MainUI/SOGoRootPage.m ([SOGoRootPage -defaultAction]): test
whether the user is logged in and if so, redirect to his/her
homepage.
([SOGoRootPage -appendToResponse:inContext:]): removed useless
method.
2007-09-11 Wolfgang Sourdeau <wsourdeau@inverse.ca> 2007-09-11 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/SOGo/SOGoFolder.m ([SOGoFolder * SoObjects/SOGo/SOGoFolder.m ([SOGoFolder

2
NEWS
View file

@ -4,6 +4,8 @@
- fixed a bug where a false positive happening whenever a wrong user login was - fixed a bug where a false positive happening whenever a wrong user login was
given during an indirect bind; given during an indirect bind;
- deleting a message no longer expunges its parent folder; - deleting a message no longer expunges its parent folder;
- implemented support for multiple calendars;
- it is not possible to rename folders;
- fixed search in message content; - fixed search in message content;
- added tooltips for toolbar buttons (English and French); - added tooltips for toolbar buttons (English and French);
- added checkmarks in live search options popup menus; - added checkmarks in live search options popup menus;

View file

@ -0,0 +1 @@
"Personal Calendar" = "Personal Calendar";

View file

@ -0,0 +1 @@
"Personal Calendar" = "Agenda personnel";

View file

@ -6,7 +6,9 @@ WOBUNDLE_NAME = Appointments
Appointments_PRINCIPAL_CLASS = SOGoAppointmentsProduct Appointments_PRINCIPAL_CLASS = SOGoAppointmentsProduct
# Appointments_LANGUAGES = English French Appointments_LANGUAGES = English French German
Appointments_LOCALIZED_RESOURCE_FILES=Localizable.strings
Appointments_OBJC_FILES = \ Appointments_OBJC_FILES = \
Product.m \ Product.m \
@ -17,6 +19,7 @@ Appointments_OBJC_FILES = \
SOGoAppointmentObject.m \ SOGoAppointmentObject.m \
SOGoTaskObject.m \ SOGoTaskObject.m \
SOGoAppointmentFolder.m \ SOGoAppointmentFolder.m \
SOGoAppointmentFolders.m \
SOGoGroupAppointmentFolder.m \ SOGoGroupAppointmentFolder.m \
SOGoFreeBusyObject.m \ SOGoFreeBusyObject.m \
\ \

View file

@ -0,0 +1 @@
"Personal Calendar" = "Personal Calendar";

View file

@ -53,6 +53,8 @@
NSMutableDictionary *uidToFilename; NSMutableDictionary *uidToFilename;
} }
- (BOOL) isActive;
/* selection */ /* selection */
- (NSArray *) calendarUIDs; - (NSArray *) calendarUIDs;
@ -113,8 +115,6 @@
- (NSArray *) fetchAllSOGoAppointments; - (NSArray *) fetchAllSOGoAppointments;
- (NSArray *) calendarFolders;
- (NSString *) roleForComponentsWithAccessClass: (iCalAccessClass) accessClass - (NSString *) roleForComponentsWithAccessClass: (iCalAccessClass) accessClass
forUser: (NSString *) uid; forUser: (NSString *) uid;

View file

@ -125,11 +125,6 @@ static NSNumber *sharedYes = nil;
return logger; return logger;
} }
- (BOOL) folderIsMandatory
{
return YES;
}
/* selection */ /* selection */
- (NSArray *) calendarUIDs - (NSArray *) calendarUIDs
@ -746,7 +741,7 @@ static NSNumber *sharedYes = nil;
privacySqlString = @"and (c_isopaque = 1)"; privacySqlString = @"and (c_isopaque = 1)";
else else
{ {
#warning we do not manage all the user's possible emails #warning we do not manage all the possible user emails
email = [[activeUser primaryIdentity] objectForKey: @"email"]; email = [[activeUser primaryIdentity] objectForKey: @"email"];
privacySqlString privacySqlString
@ -905,7 +900,6 @@ static NSNumber *sharedYes = nil;
component: _component]; component: _component];
} }
- (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) _startDate - (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) _startDate
to: (NSCalendarDate *) _endDate to: (NSCalendarDate *) _endDate
{ {
@ -1041,21 +1035,28 @@ static NSNumber *sharedYes = nil;
/* Note: can return NSNull objects in the array! */ /* Note: can return NSNull objects in the array! */
NSMutableArray *folders; NSMutableArray *folders;
NSEnumerator *e; NSEnumerator *e;
NSString *uid; NSString *uid, *ownerLogin;
id folder;
ownerLogin = [self ownerInContext: context];
if ([_uids count] == 0) return nil; if ([_uids count] == 0) return nil;
folders = [NSMutableArray arrayWithCapacity:16]; folders = [NSMutableArray arrayWithCapacity:16];
e = [_uids objectEnumerator]; e = [_uids objectEnumerator];
while ((uid = [e nextObject])) { while ((uid = [e nextObject]))
id folder; {
if ([uid isEqualToString: ownerLogin])
folder = self;
else
{
folder = [self lookupCalendarFolderForUID: uid];
if (![folder isNotNull])
[self logWithFormat:@"Note: did not find folder for uid: '%@'", uid];
}
folder = [self lookupCalendarFolderForUID: uid]; [folders addObject: folder];
if (![folder isNotNull]) }
[self logWithFormat:@"Note: did not find folder for uid: '%@'", uid];
/* Note: intentionally add 'null' folders to allow a mapping */
[folders addObject:folder ? folder : [NSNull null]];
}
return folders; return folders;
} }
@ -1196,67 +1197,67 @@ static NSNumber *sharedYes = nil;
return events; return events;
} }
#warning We only support ONE calendar per user at this time // #warning We only support ONE calendar per user at this time
- (BOOL) _appendSubscribedFolders: (NSDictionary *) subscribedFolders // - (BOOL) _appendSubscribedFolders: (NSDictionary *) subscribedFolders
toFolderList: (NSMutableArray *) calendarFolders // toFolderList: (NSMutableArray *) calendarFolders
{ // {
NSEnumerator *keys; // NSEnumerator *keys;
NSString *currentKey; // NSString *currentKey;
NSMutableDictionary *currentCalendar; // NSMutableDictionary *currentCalendar;
BOOL firstShouldBeActive; // BOOL firstShouldBeActive;
unsigned int count; // unsigned int count;
firstShouldBeActive = YES; // firstShouldBeActive = YES;
keys = [[subscribedFolders allKeys] objectEnumerator]; // keys = [[subscribedFolders allKeys] objectEnumerator];
currentKey = [keys nextObject]; // currentKey = [keys nextObject];
count = 1; // count = 1;
while (currentKey) // while (currentKey)
{ // {
currentCalendar = [NSMutableDictionary new]; // currentCalendar = [NSMutableDictionary new];
[currentCalendar autorelease]; // [currentCalendar autorelease];
[currentCalendar // [currentCalendar
setDictionary: [subscribedFolders objectForKey: currentKey]]; // setDictionary: [subscribedFolders objectForKey: currentKey]];
[currentCalendar setObject: currentKey forKey: @"folder"]; // [currentCalendar setObject: currentKey forKey: @"folder"];
[calendarFolders addObject: currentCalendar]; // [calendarFolders addObject: currentCalendar];
if ([[currentCalendar objectForKey: @"active"] boolValue]) // if ([[currentCalendar objectForKey: @"active"] boolValue])
firstShouldBeActive = NO; // firstShouldBeActive = NO;
count++; // count++;
currentKey = [keys nextObject]; // currentKey = [keys nextObject];
} // }
return firstShouldBeActive; // return firstShouldBeActive;
} // }
- (NSArray *) calendarFolders // - (NSArray *) calendarFolders
{ // {
NSMutableDictionary *userCalendar, *calendarDict; // NSMutableDictionary *userCalendar, *calendarDict;
NSMutableArray *calendarFolders; // NSMutableArray *calendarFolders;
SOGoUser *calendarUser; // SOGoUser *calendarUser;
BOOL firstActive; // BOOL firstActive;
calendarFolders = [NSMutableArray new]; // calendarFolders = [NSMutableArray new];
[calendarFolders autorelease]; // [calendarFolders autorelease];
calendarUser = [SOGoUser userWithLogin: [self ownerInContext: context] // calendarUser = [SOGoUser userWithLogin: [self ownerInContext: context]
roles: nil]; // roles: nil];
userCalendar = [NSMutableDictionary new]; // userCalendar = [NSMutableDictionary new];
[userCalendar autorelease]; // [userCalendar autorelease];
[userCalendar setObject: @"/" forKey: @"folder"]; // [userCalendar setObject: @"/" forKey: @"folder"];
[userCalendar setObject: @"Calendar" forKey: @"displayName"]; // [userCalendar setObject: @"Calendar" forKey: @"displayName"];
[calendarFolders addObject: userCalendar]; // [calendarFolders addObject: userCalendar];
calendarDict = [[calendarUser userSettings] objectForKey: @"Calendar"]; // calendarDict = [[calendarUser userSettings] objectForKey: @"Calendar"];
firstActive = [[calendarDict objectForKey: @"activateUserFolder"] boolValue]; // firstActive = [[calendarDict objectForKey: @"activateUserFolder"] boolValue];
firstActive = ([self _appendSubscribedFolders: // firstActive = ([self _appendSubscribedFolders:
[calendarDict objectForKey: @"SubscribedFolders"] // [calendarDict objectForKey: @"SubscribedFolders"]
toFolderList: calendarFolders] // toFolderList: calendarFolders]
|| firstActive); // || firstActive);
[userCalendar setObject: [NSNumber numberWithBool: firstActive] // [userCalendar setObject: [NSNumber numberWithBool: firstActive]
forKey: @"active"]; // forKey: @"active"];
return calendarFolders; // return calendarFolders;
} // }
// - (NSArray *) fetchContentObjectNames // - (NSArray *) fetchContentObjectNames
// { // {
@ -1297,49 +1298,16 @@ static NSNumber *sharedYes = nil;
return @"IPF.Appointment"; return @"IPF.Appointment";
} }
/* hack until we permit more than 1 cal per user */ - (BOOL) isActive
- (NSArray *) _fixedPath: (NSArray *) objectPath
{ {
NSMutableArray *newPath; NSUserDefaults *settings;
NSArray *activeFolders;
newPath = [NSMutableArray arrayWithArray: objectPath]; settings = [[context activeUser] userSettings];
if ([newPath count] > 2) activeFolders
{ = [[settings objectForKey: @"Calendar"] objectForKey: @"ActiveFolders"];
if (![[newPath objectAtIndex: 2] isEqualToString: @"personal"])
[newPath insertObject: @"personal" atIndex: 2];
}
else
[newPath addObject: @"personal"];
return newPath; return [activeFolders containsObject: nameInContainer];
}
- (NSArray *) aclUsersForObjectAtPath: (NSArray *) objectPathArray
{
return [super aclUsersForObjectAtPath: [self _fixedPath: objectPathArray]];
}
- (NSArray *) aclsForUser: (NSString *) uid
forObjectAtPath: (NSArray *) objectPathArray
{
return [super aclsForUser: uid
forObjectAtPath: [self _fixedPath: objectPathArray]];
}
- (void) setRoles: (NSArray *) roles
forUser: (NSString *) uid
forObjectAtPath: (NSArray *) objectPathArray
{
[super setRoles: roles
forUser: uid
forObjectAtPath: [self _fixedPath: objectPathArray]];
}
- (void) removeAclsForUsers: (NSArray *) users
forObjectAtPath: (NSArray *) objectPathArray
{
[super removeAclsForUsers: users
forObjectAtPath: [self _fixedPath: objectPathArray]];
} }
@end /* SOGoAppointmentFolder */ @end /* SOGoAppointmentFolder */

View file

@ -46,13 +46,6 @@
@interface SOGoAppointmentObject : SOGoCalendarComponent @interface SOGoAppointmentObject : SOGoCalendarComponent
/* folder management */
- (id) lookupHomeFolderForUID: (NSString *) _uid
inContext: (id) _ctx;
- (NSArray *) lookupCalendarFoldersForUIDs: (NSArray *) _uids
inContext: (id) _ctx;
/* "iCal multifolder saves" */ /* "iCal multifolder saves" */
- (NSException *) saveContentString: (NSString *) _iCal - (NSException *) saveContentString: (NSString *) _iCal

View file

@ -34,6 +34,8 @@
#import <SoObjects/SOGo/SOGoPermissions.h> #import <SoObjects/SOGo/SOGoPermissions.h>
#import "NSArray+Appointments.h" #import "NSArray+Appointments.h"
#import "SOGoAppointmentFolder.h"
#import "SOGoAppointmentObject.h" #import "SOGoAppointmentObject.h"
@implementation SOGoAppointmentObject @implementation SOGoAppointmentObject
@ -96,16 +98,6 @@
return uids; return uids;
} }
/* folder management */
- (id)lookupHomeFolderForUID:(NSString *)_uid inContext:(id)_ctx {
// TODO: what does this do? lookup the home of the organizer?
return [[self container] lookupHomeFolderForUID:_uid inContext:_ctx];
}
- (NSArray *)lookupCalendarFoldersForUIDs:(NSArray *)_uids inContext:(id)_ctx {
return [[self container] lookupCalendarFoldersForUIDs:_uids inContext:_ctx];
}
/* store in all the other folders */ /* store in all the other folders */
- (NSException *) saveContentString: (NSString *) _iCal - (NSException *) saveContentString: (NSString *) _iCal
@ -115,8 +107,8 @@
id folder; id folder;
NSException *allErrors = nil; NSException *allErrors = nil;
e = [[self lookupCalendarFoldersForUIDs:_uids inContext: context] e = [[container lookupCalendarFoldersForUIDs:_uids inContext: context]
objectEnumerator]; objectEnumerator];
while ((folder = [e nextObject]) != nil) { while ((folder = [e nextObject]) != nil) {
NSException *error; NSException *error;
SOGoAppointmentObject *apt; SOGoAppointmentObject *apt;
@ -160,8 +152,8 @@
id folder; id folder;
NSException *allErrors = nil; NSException *allErrors = nil;
e = [[self lookupCalendarFoldersForUIDs:_uids inContext: context] e = [[container lookupCalendarFoldersForUIDs:_uids inContext: context]
objectEnumerator]; objectEnumerator];
while ((folder = [e nextObject])) { while ((folder = [e nextObject])) {
NSException *error; NSException *error;
SOGoAppointmentObject *apt; SOGoAppointmentObject *apt;

View file

@ -44,13 +44,6 @@
@interface SOGoTaskObject : SOGoCalendarComponent @interface SOGoTaskObject : SOGoCalendarComponent
/* folder management */
- (id) lookupHomeFolderForUID: (NSString *) _uid
inContext: (id) _ctx;
- (NSArray *) lookupCalendarFoldersForUIDs: (NSArray *) _uids
inContext: (id) _ctx;
/* "iCal multifolder saves" */ /* "iCal multifolder saves" */
- (NSException *) saveContentString: (NSString *) _iCal - (NSException *) saveContentString: (NSString *) _iCal

View file

@ -34,6 +34,7 @@
#import "NSArray+Appointments.h" #import "NSArray+Appointments.h"
#import "SOGoAptMailNotification.h" #import "SOGoAptMailNotification.h"
#import "SOGoAppointmentFolder.h"
#import "SOGoTaskObject.h" #import "SOGoTaskObject.h"
@ -118,17 +119,6 @@ static NSString *mailTemplateDefaultLanguage = nil;
return uids; return uids;
} }
/* folder management */
- (id)lookupHomeFolderForUID:(NSString *)_uid inContext:(id)_ctx {
// TODO: what does this do? lookup the home of the organizer?
return [[self container] lookupHomeFolderForUID:_uid inContext:_ctx];
}
- (NSArray *)lookupCalendarFoldersForUIDs:(NSArray *)_uids inContext:(id)_ctx {
return [[self container] lookupCalendarFoldersForUIDs:_uids inContext:_ctx];
}
/* store in all the other folders */ /* store in all the other folders */
- (NSException *)saveContentString:(NSString *)_iCal inUIDs:(NSArray *)_uids { - (NSException *)saveContentString:(NSString *)_iCal inUIDs:(NSArray *)_uids {
@ -136,7 +126,7 @@ static NSString *mailTemplateDefaultLanguage = nil;
id folder; id folder;
NSException *allErrors = nil; NSException *allErrors = nil;
e = [[self lookupCalendarFoldersForUIDs: _uids inContext: context] e = [[container lookupCalendarFoldersForUIDs: _uids inContext: context]
objectEnumerator]; objectEnumerator];
while ((folder = [e nextObject]) != nil) { while ((folder = [e nextObject]) != nil) {
NSException *error; NSException *error;
@ -175,7 +165,7 @@ static NSString *mailTemplateDefaultLanguage = nil;
id folder; id folder;
NSException *allErrors = nil; NSException *allErrors = nil;
e = [[self lookupCalendarFoldersForUIDs: _uids inContext: context] e = [[container lookupCalendarFoldersForUIDs: _uids inContext: context]
objectEnumerator]; objectEnumerator];
while ((folder = [e nextObject])) { while ((folder = [e nextObject])) {
NSException *error; NSException *error;

View file

@ -8,6 +8,9 @@
}; };
classes = { classes = {
SOGoAppointmentFolder = {
superclass = "SOGoParentFolder";
};
SOGoAppointmentFolder = { SOGoAppointmentFolder = {
superclass = "SOGoFolder"; superclass = "SOGoFolder";
defaultRoles = { defaultRoles = {

View file

@ -0,0 +1 @@
"Personal Address Book" = "Personal Address Book";

View file

@ -0,0 +1 @@
"Personal Address Book" = "Carnet d'adresses personnel";

View file

@ -0,0 +1 @@
"Personal Calendar" = "Personal Calendar";

View file

@ -27,25 +27,11 @@
TaskItems IPF.Task TaskItems IPF.Task
JournalItems IPF.Journal */ JournalItems IPF.Journal */
// #import <Foundation/NSDictionary.h>
#import <Foundation/NSArray.h> #import <Foundation/NSArray.h>
#import <Foundation/NSString.h> #import <Foundation/NSString.h>
#import <Foundation/NSEnumerator.h> #import <Foundation/NSEnumerator.h>
// #import <NGObjWeb/NSException+HTTP.h>
// #import <NGObjWeb/WOApplication.h>
// #import <NGObjWeb/WOContext.h>
// #import <NGObjWeb/WOContext+SoObjects.h>
// #import <NGObjWeb/WOResponse.h>
// #import <NGObjWeb/SoUser.h>
// #import <GDLContentStore/GCSFolderManager.h>
// #import <GDLContentStore/GCSChannelManager.h>
// #import <GDLAccess/EOAdaptorChannel.h>
// #import <GDLContentStore/NSURL+GCS.h>
#import <SoObjects/SOGo/LDAPUserManager.h> #import <SoObjects/SOGo/LDAPUserManager.h>
// #import <SoObjects/SOGo/SOGoPermissions.h>
#import "SOGoContactGCSFolder.h" #import "SOGoContactGCSFolder.h"
#import "SOGoContactLDAPFolder.h" #import "SOGoContactLDAPFolder.h"
@ -85,4 +71,9 @@
} }
} }
- (NSString *) defaultFolderName
{
return @"Personal Address Book";
}
@end @end

View file

@ -21,6 +21,7 @@
#import <Foundation/NSArray.h> #import <Foundation/NSArray.h>
#import <Foundation/NSString.h> #import <Foundation/NSString.h>
#import <NGObjWeb/NSException+HTTP.h> #import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/SoObject+SoDAV.h> #import <NGObjWeb/SoObject+SoDAV.h>
#import <NGObjWeb/WOContext.h> #import <NGObjWeb/WOContext.h>
@ -41,11 +42,6 @@
@implementation SOGoContactGCSFolder @implementation SOGoContactGCSFolder
- (BOOL) folderIsMandatory
{
return [nameInContainer isEqualToString: @"personal"];
}
/* name lookup */ /* name lookup */
- (id <SOGoContactObject>) lookupContactWithId: (NSString *) recordId - (id <SOGoContactObject>) lookupContactWithId: (NSString *) recordId

View file

@ -257,6 +257,11 @@
} }
/* acls */ /* acls */
- (NSString *) ownerInContext: (WOContext *) noContext
{
return @"nobody";
}
/* TODO: this might change one day when we support LDAP acls */ /* TODO: this might change one day when we support LDAP acls */
- (NSArray *) aclsForUser: (NSString *) uid - (NSArray *) aclsForUser: (NSString *) uid
{ {

View file

@ -9,12 +9,7 @@
classes = { classes = {
SOGoContactFolders = { SOGoContactFolders = {
superclass = "SOGoFolder"; superclass = "SOGoParentFolder";
protectedBy = "Access Contents Information";
defaultRoles = {
"Access Contents Information" = ( "Authenticated" );
"WebDAV Access" = ( "Authenticated" );
};
}; };
SOGoContactGCSFolder = { SOGoContactGCSFolder = {
superclass = "SOGoFolder"; superclass = "SOGoFolder";

View file

@ -29,6 +29,8 @@
@interface NSDictionary (SOGoDictionaryUtilities) @interface NSDictionary (SOGoDictionaryUtilities)
+ (NSDictionary *) dictionaryFromStringsFile: (NSString *) file;
- (NSString *) jsonRepresentation; - (NSString *) jsonRepresentation;
- (NSString *) keysWithFormat: (NSString *) keyFormat; - (NSString *) keysWithFormat: (NSString *) keyFormat;

View file

@ -21,6 +21,7 @@
*/ */
#import <Foundation/NSArray.h> #import <Foundation/NSArray.h>
#import <Foundation/NSData.h>
#import <Foundation/NSString.h> #import <Foundation/NSString.h>
#import "NSArray+Utilities.h" #import "NSArray+Utilities.h"
@ -29,6 +30,25 @@
@implementation NSDictionary (SOGoDictionaryUtilities) @implementation NSDictionary (SOGoDictionaryUtilities)
+ (NSDictionary *) dictionaryFromStringsFile: (NSString *) file
{
NSString *serialized;
NSMutableData *content;
NSDictionary *newDictionary;
content = [NSMutableData new];
[content appendBytes: "{" length: 1];
[content appendData: [NSData dataWithContentsOfFile: file]];
[content appendBytes: "}" length: 1];
serialized = [[NSString alloc] initWithData: content
encoding: NSUTF8StringEncoding];
[content release];
newDictionary = [serialized propertyList];
[serialized release];
return newDictionary;
}
- (NSString *) jsonRepresentation - (NSString *) jsonRepresentation
{ {
NSMutableArray *values; NSMutableArray *values;

View file

@ -231,7 +231,7 @@
needsLocation = NO; needsLocation = NO;
tmp = [[self nameInContainer] stringByDeletingPathExtension]; tmp = [[self nameInContainer] stringByDeletingPathExtension];
if ([tmp isEqualToString:@"new"]) { if ([tmp isEqualToString:@"new"]) {
tmp = [[[self container] class] globallyUniqueObjectId]; tmp = [self globallyUniqueObjectId];
needsLocation = YES; needsLocation = YES;
[self debugWithFormat: [self debugWithFormat:
@ -359,7 +359,7 @@
- (NSArray *) aclUsers - (NSArray *) aclUsers
{ {
return [container aclUsersForObjectAtPath: [self pathArrayToSoObject]]; return [container aclUsersForObjectAtPath: [self pathArrayToSOGoObject]];
} }
- (NSArray *) aclsForUser: (NSString *) uid - (NSArray *) aclsForUser: (NSString *) uid
@ -369,7 +369,7 @@
acls = [NSMutableArray array]; acls = [NSMutableArray array];
ownAcls = [container aclsForUser: uid ownAcls = [container aclsForUser: uid
forObjectAtPath: [self pathArrayToSoObject]]; forObjectAtPath: [self pathArrayToSOGoObject]];
[acls addObjectsFromArray: ownAcls]; [acls addObjectsFromArray: ownAcls];
containerAcls = [container aclsForUser: uid]; containerAcls = [container aclsForUser: uid];
if ([containerAcls count] > 0) if ([containerAcls count] > 0)

View file

@ -43,23 +43,18 @@
@interface SOGoFolder : SOGoObject @interface SOGoFolder : SOGoObject
{ {
NSString *displayName; NSMutableString *displayName;
NSString *ocsPath; NSString *ocsPath;
GCSFolder *ocsFolder; GCSFolder *ocsFolder;
NSMutableDictionary *aclCache; NSMutableDictionary *aclCache;
} }
+ (NSString *) globallyUniqueObjectId; + (id) folderWithSubscriptionReference: (NSString *) reference
inContainer: (id) aContainer;
/* accessors */ /* accessors */
+ (id) folderWithName: (NSString *) aName - (void) setDisplayName: (NSString *) newDisplayName;
andDisplayName: (NSString *) aDisplayName
inContainer: (id) aContainer;
- (id) initWithName: (NSString *) aName
andDisplayName: (NSString *) aDisplayName
inContainer: (id) aContainer;
- (NSString *) displayName; - (NSString *) displayName;
- (void) setOCSPath: (NSString *)_Path; - (void) setOCSPath: (NSString *)_Path;
@ -79,10 +74,11 @@
- (NSString *) outlookFolderClass; - (NSString *) outlookFolderClass;
- (BOOL) folderIsMandatory; - (BOOL) folderIsMandatory;
- (NSString *) folderType;
- (BOOL) create; - (BOOL) create;
- (NSException *) delete; - (NSException *) delete;
- (void) renameTo: (NSString *) newName;
/* dav */ /* dav */
- (NSArray *) davNamespaces; - (NSArray *) davNamespaces;

View file

@ -19,9 +19,6 @@
02111-1307, USA. 02111-1307, USA.
*/ */
#import <unistd.h>
#import <stdlib.h>
#import <Foundation/NSArray.h> #import <Foundation/NSArray.h>
#import <Foundation/NSDate.h> #import <Foundation/NSDate.h>
#import <Foundation/NSDictionary.h> #import <Foundation/NSDictionary.h>
@ -38,9 +35,11 @@
#import <NGExtensions/NSObject+Logs.h> #import <NGExtensions/NSObject+Logs.h>
#import <EOControl/EOQualifier.h> #import <EOControl/EOQualifier.h>
#import <GDLAccess/EOAdaptorChannel.h> #import <GDLAccess/EOAdaptorChannel.h>
#import <GDLContentStore/GCSChannelManager.h>
#import <GDLContentStore/GCSFolderManager.h> #import <GDLContentStore/GCSFolderManager.h>
#import <GDLContentStore/GCSFolder.h> #import <GDLContentStore/GCSFolder.h>
#import <GDLContentStore/GCSFolderType.h> #import <GDLContentStore/GCSFolderType.h>
#import <GDLContentStore/NSURL+GCS.h>
#import <SaxObjC/XMLNamespaces.h> #import <SaxObjC/XMLNamespaces.h>
#import "NSArray+Utilities.h" #import "NSArray+Utilities.h"
@ -67,40 +66,29 @@ static NSString *defaultUserID = @"<default>";
NSStringFromClass([self superclass]), [super version]); NSStringFromClass([self superclass]), [super version]);
} }
+ (NSString *) globallyUniqueObjectId + (id) folderWithSubscriptionReference: (NSString *) reference
{ inContainer: (id) aContainer
/*
4C08AE1A-A808-11D8-AC5A-000393BBAFF6
SOGo-Web-28273-18283-288182
printf( "%x", *(int *) &f);
*/
static int pid = 0;
static int sequence = 0;
static float rndm = 0;
float f;
if (pid == 0)
{ /* break if we fork ;-) */
pid = getpid();
rndm = random();
}
sequence++;
f = [[NSDate date] timeIntervalSince1970];
return [NSString stringWithFormat:@"%0X-%0X-%0X-%0X",
pid, (int) f, sequence++, random];
}
+ (id) folderWithName: (NSString *) aName
andDisplayName: (NSString *) aDisplayName
inContainer: (id) aContainer
{ {
id newFolder; id newFolder;
NSArray *elements, *pathElements;
NSString *ocsPath, *objectPath, *owner, *ocsName, *folderName;
newFolder = [[self alloc] initWithName: aName elements = [reference componentsSeparatedByString: @":"];
andDisplayName: aDisplayName owner = [elements objectAtIndex: 0];
objectPath = [elements objectAtIndex: 1];
pathElements = [objectPath componentsSeparatedByString: @"/"];
if ([pathElements count] > 1)
ocsName = [pathElements objectAtIndex: 1];
else
ocsName = @"personal";
ocsPath = [NSString stringWithFormat: @"/Users/%@/%@/%@",
owner, [pathElements objectAtIndex: 0], ocsName];
folderName = [NSString stringWithFormat: @"%@_%@", owner, ocsName];
newFolder = [[self alloc] initWithName: folderName
inContainer: aContainer]; inContainer: aContainer];
[newFolder autorelease]; [newFolder setOCSPath: ocsPath];
[newFolder setOwner: owner];
return newFolder; return newFolder;
} }
@ -118,17 +106,6 @@ static NSString *defaultUserID = @"<default>";
return self; return self;
} }
- (id) initWithName: (NSString *) aName
andDisplayName: (NSString *) aDisplayName
inContainer: (id) aContainer
{
if ((self = [self initWithName: aName
inContainer: aContainer]))
ASSIGN (displayName, aDisplayName);
return self;
}
- (void) dealloc - (void) dealloc
{ {
[ocsFolder release]; [ocsFolder release];
@ -147,13 +124,12 @@ static NSString *defaultUserID = @"<default>";
- (void) setOCSPath: (NSString *) _path - (void) setOCSPath: (NSString *) _path
{ {
if ([ocsPath isEqualToString:_path]) if (![ocsPath isEqualToString:_path])
return; {
if (ocsPath)
if (ocsPath) [self warnWithFormat: @"GCS path is already set! '%@'", _path];
[self warnWithFormat:@"GCS path is already set! '%@'", _path]; ASSIGN (ocsPath, _path);
}
ASSIGNCOPY(ocsPath, _path);
} }
- (NSString *) ocsPath - (NSString *) ocsPath
@ -178,16 +154,75 @@ static NSString *defaultUserID = @"<default>";
- (BOOL) folderIsMandatory - (BOOL) folderIsMandatory
{ {
[self subclassResponsibility: _cmd]; return [nameInContainer isEqualToString: @"personal"];
}
return NO; - (void) _setDisplayNameFromRow: (NSDictionary *) row
{
NSString *currentLogin, *ownerLogin;
NSDictionary *ownerIdentity;
displayName
= [NSMutableString stringWithString: [row objectForKey: @"c_foldername"]];
currentLogin = [[context activeUser] login];
ownerLogin = [self ownerInContext: context];
if (![currentLogin isEqualToString: ownerLogin])
{
ownerIdentity = [[SOGoUser userWithLogin: ownerLogin roles: nil]
primaryIdentity];
[displayName appendFormat: @" (%@ <%@>)",
[ownerIdentity objectForKey: @"fullName"],
[ownerIdentity objectForKey: @"email"]];
}
}
- (void) _fetchDisplayName
{
GCSChannelManager *cm;
EOAdaptorChannel *fc;
NSURL *folderLocation;
NSString *sql;
NSArray *attrs;
NSDictionary *row;
cm = [GCSChannelManager defaultChannelManager];
folderLocation
= [[GCSFolderManager defaultFolderManager] folderInfoLocation];
fc = [cm acquireOpenChannelForURL: folderLocation];
if (fc)
{
sql
= [NSString stringWithFormat: (@"SELECT c_foldername FROM %@"
@" WHERE c_path = '%@'"),
[folderLocation gcsTableName], ocsPath];
[fc evaluateExpressionX: sql];
attrs = [fc describeResults: NO];
row = [fc fetchAttributes: attrs withZone: NULL];
if (row)
[self _setDisplayNameFromRow: row];
[fc cancelFetch];
[cm releaseChannel: fc];
}
}
- (void) setDisplayName: (NSString *) newDisplayName
{
ASSIGN (displayName, newDisplayName);
} }
- (NSString *) displayName - (NSString *) displayName
{ {
if (!displayName)
[self _fetchDisplayName];
return displayName; return displayName;
} }
- (NSString *) davDisplayName
{
return [self displayName];
}
- (GCSFolder *) ocsFolder - (GCSFolder *) ocsFolder
{ {
GCSFolder *folder; GCSFolder *folder;
@ -222,7 +257,9 @@ static NSString *defaultUserID = @"<default>";
{ {
NSException *result; NSException *result;
// [self dieHard];
result = [[self folderManager] createFolderOfType: [self folderType] result = [[self folderManager] createFolderOfType: [self folderType]
withName: displayName
atPath: ocsPath]; atPath: ocsPath];
return (result == nil); return (result == nil);
@ -234,13 +271,40 @@ static NSString *defaultUserID = @"<default>";
if ([nameInContainer isEqualToString: @"personal"]) if ([nameInContainer isEqualToString: @"personal"])
error = [NSException exceptionWithHTTPStatus: 403 error = [NSException exceptionWithHTTPStatus: 403
reason: @"the 'personal' folder cannot be deleted"]; reason: @"folder 'personal' cannot be deleted"];
else else
error = [[self folderManager] deleteFolderAtPath: ocsPath]; error = [[self folderManager] deleteFolderAtPath: ocsPath];
return error; return error;
} }
- (void) renameTo: (NSString *) newName
{
GCSChannelManager *cm;
EOAdaptorChannel *fc;
NSURL *folderLocation;
NSString *sql;
[displayName release];
displayName = nil;
cm = [GCSChannelManager defaultChannelManager];
folderLocation
= [[GCSFolderManager defaultFolderManager] folderInfoLocation];
fc = [cm acquireOpenChannelForURL: folderLocation];
if (fc)
{
sql
= [NSString stringWithFormat: (@"UPDATE %@ SET c_foldername = '%@'"
@" WHERE c_path = '%@'"),
[folderLocation gcsTableName], newName, ocsPath];
[fc evaluateExpressionX: sql];
[cm releaseChannel: fc];
// sql = [sql stringByAppendingFormat:@" WHERE %@ = '%@'",
// uidColumnName, [self uid]];
}
}
- (NSArray *) fetchContentObjectNames - (NSArray *) fetchContentObjectNames
{ {
NSArray *fields, *records; NSArray *fields, *records;
@ -512,7 +576,7 @@ static NSString *defaultUserID = @"<default>";
/* acls */ /* acls */
- (NSArray *) aclUsers - (NSArray *) aclUsers
{ {
return [self aclUsersForObjectAtPath: [self pathArrayToSoObject]]; return [self aclUsersForObjectAtPath: [self pathArrayToSOGoObject]];
} }
- (NSArray *) aclsForUser: (NSString *) uid - (NSArray *) aclsForUser: (NSString *) uid
@ -522,7 +586,7 @@ static NSString *defaultUserID = @"<default>";
acls = [NSMutableArray array]; acls = [NSMutableArray array];
ownAcls = [self aclsForUser: uid ownAcls = [self aclsForUser: uid
forObjectAtPath: [self pathArrayToSoObject]]; forObjectAtPath: [self pathArrayToSOGoObject]];
[acls addObjectsFromArray: ownAcls]; [acls addObjectsFromArray: ownAcls];
if ([container respondsToSelector: @selector (aclsForUser:)]) if ([container respondsToSelector: @selector (aclsForUser:)])
{ {
@ -545,13 +609,13 @@ static NSString *defaultUserID = @"<default>";
{ {
return [self setRoles: roles return [self setRoles: roles
forUser: uid forUser: uid
forObjectAtPath: [self pathArrayToSoObject]]; forObjectAtPath: [self pathArrayToSOGoObject]];
} }
- (void) removeAclsForUsers: (NSArray *) users - (void) removeAclsForUsers: (NSArray *) users
{ {
return [self removeAclsForUsers: users return [self removeAclsForUsers: users
forObjectAtPath: [self pathArrayToSoObject]]; forObjectAtPath: [self pathArrayToSOGoObject]];
} }
- (NSString *) defaultUserID - (NSString *) defaultUserID

View file

@ -61,6 +61,9 @@
id container; id container;
} }
+ (NSString *) globallyUniqueObjectId;
- (NSString *) globallyUniqueObjectId;
+ (id) objectWithName: (NSString *)_name inContainer:(id)_container; + (id) objectWithName: (NSString *)_name inContainer:(id)_container;
- (id) initWithName: (NSString *) _name inContainer:(id)_container; - (id) initWithName: (NSString *) _name inContainer:(id)_container;
@ -70,11 +73,15 @@
- (NSString *) nameInContainer; - (NSString *) nameInContainer;
- (id) container; - (id) container;
- (NSArray *) pathArrayToSOGoObject;
- (NSURL *) davURL; - (NSURL *) davURL;
- (NSURL *) soURL; - (NSURL *) soURL;
- (NSURL *) soURLToBaseContainerForUser: (NSString *) uid; - (NSURL *) soURLToBaseContainerForUser: (NSString *) uid;
- (NSURL *) soURLToBaseContainerForCurrentUser; - (NSURL *) soURLToBaseContainerForCurrentUser;
- (NSString *) labelForKey: (NSString *) key;
/* ownership */ /* ownership */
- (void) setOwner: (NSString *) newOwner; - (void) setOwner: (NSString *) newOwner;
@ -100,7 +107,7 @@
/* etag support */ /* etag support */
- (NSException *)matchesRequestConditionInContext:(id)_ctx; - (NSException *) matchesRequestConditionInContext:(id)_ctx;
/* acls */ /* acls */

View file

@ -24,6 +24,9 @@
Please use gnustep-base instead. Please use gnustep-base instead.
#endif #endif
#import <unistd.h>
#import <Foundation/NSBundle.h>
#import <Foundation/NSClassDescription.h> #import <Foundation/NSClassDescription.h>
#import <Foundation/NSString.h> #import <Foundation/NSString.h>
#import <Foundation/NSUserDefaults.h> #import <Foundation/NSUserDefaults.h>
@ -35,6 +38,7 @@
#import <NGObjWeb/WEClientCapabilities.h> #import <NGObjWeb/WEClientCapabilities.h>
#import <NGObjWeb/WOApplication.h> #import <NGObjWeb/WOApplication.h>
#import <NGObjWeb/WOContext.h> #import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WOResourceManager.h>
#import <NGObjWeb/WOResponse.h> #import <NGObjWeb/WOResponse.h>
#import <NGObjWeb/WORequest.h> #import <NGObjWeb/WORequest.h>
#import <NGObjWeb/WORequest+So.h> #import <NGObjWeb/WORequest+So.h>
@ -52,6 +56,7 @@
#import "SOGoDAVRendererTypes.h" #import "SOGoDAVRendererTypes.h"
#import "NSArray+Utilities.h" #import "NSArray+Utilities.h"
#import "NSDictionary+Utilities.h"
#import "NSString+Utilities.h" #import "NSString+Utilities.h"
#import "SOGoObject.h" #import "SOGoObject.h"
@ -179,6 +184,35 @@ static BOOL kontactGroupDAV = YES;
// asDefaultForPermission: SoPerm_WebDAVAccess]; // asDefaultForPermission: SoPerm_WebDAVAccess];
} }
+ (NSString *) globallyUniqueObjectId
{
/*
4C08AE1A-A808-11D8-AC5A-000393BBAFF6
SOGo-Web-28273-18283-288182
printf( "%x", *(int *) &f);
*/
static int pid = 0;
static int sequence = 0;
static float rndm = 0;
float f;
if (pid == 0)
{ /* break if we fork ;-) */
pid = getpid();
rndm = random();
}
sequence++;
f = [[NSDate date] timeIntervalSince1970];
return [NSString stringWithFormat:@"%0X-%0X-%0X-%0X",
pid, (int) f, sequence++, random];
}
- (NSString *) globallyUniqueObjectId
{
return [[self class] globallyUniqueObjectId];
}
+ (void) _fillDictionary: (NSMutableDictionary *) dictionary + (void) _fillDictionary: (NSMutableDictionary *) dictionary
withDAVMethods: (NSString *) firstMethod, ... withDAVMethods: (NSString *) firstMethod, ...
{ {
@ -447,6 +481,30 @@ static BOOL kontactGroupDAV = YES;
return container; return container;
} }
- (NSArray *) pathArrayToSOGoObject
{
NSMutableArray *realPathArray;
NSString *objectName;
NSArray *objectDescription;
realPathArray
= [NSMutableArray arrayWithArray: [self pathArrayToSoObject]];
if ([realPathArray count] > 2)
{
objectName = [realPathArray objectAtIndex: 2];
objectDescription = [objectName componentsSeparatedByString: @"_"];
if ([objectDescription count] > 1)
{
[realPathArray replaceObjectAtIndex: 0
withObject: [objectDescription objectAtIndex: 0]];
[realPathArray replaceObjectAtIndex: 2
withObject: [objectDescription objectAtIndex: 1]];
}
}
return realPathArray;
}
/* ownership */ /* ownership */
- (void) setOwner: (NSString *) newOwner - (void) setOwner: (NSString *) newOwner
@ -493,14 +551,16 @@ static BOOL kontactGroupDAV = YES;
/* looking up shared objects */ /* looking up shared objects */
- (SOGoUserFolder *)lookupUserFolder { - (SOGoUserFolder *) lookupUserFolder
{
if (![container respondsToSelector:_cmd]) if (![container respondsToSelector:_cmd])
return nil; return nil;
return [container lookupUserFolder]; return [container lookupUserFolder];
} }
- (SOGoGroupsFolder *)lookupGroupsFolder { - (SOGoGroupsFolder *) lookupGroupsFolder
{
return [[self lookupUserFolder] lookupGroupsFolder]; return [[self lookupUserFolder] lookupGroupsFolder];
} }
@ -905,6 +965,34 @@ static BOOL kontactGroupDAV = YES;
return nil; return nil;
} }
- (NSString *) labelForKey: (NSString *) key
{
NSString *userLanguage, *label;
NSArray *paths;
NSBundle *bundle;
NSDictionary *strings;
bundle = [NSBundle bundleForClass: [self class]];
if (!bundle)
bundle = [NSBundle mainBundle];
userLanguage = [[context activeUser] language];
paths = [bundle pathsForResourcesOfType: @"strings"
inDirectory: [NSString stringWithFormat: @"%@.lproj", userLanguage]
forLocalization: userLanguage];
if ([paths count] > 0)
{
strings = [NSDictionary dictionaryFromStringsFile: [paths objectAtIndex: 0]];
label = [strings objectForKey: key];
if (!label)
label = key;
}
else
label = key;
return label;
}
/* description */ /* description */
- (void)appendAttributesToDescription:(NSMutableString *)_ms { - (void)appendAttributesToDescription:(NSMutableString *)_ms {

View file

@ -43,7 +43,8 @@
- (NSArray *) subFolders; - (NSArray *) subFolders;
- (NSException *) newFolderWithName: (NSString *) name; - (NSException *) newFolderWithName: (NSString *) name
nameInContainer: (NSString **) newNameInContainer;
@end @end

View file

@ -22,14 +22,17 @@
#import <Foundation/NSDictionary.h> #import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h> #import <Foundation/NSString.h>
#import <Foundation/NSUserDefaults.h>
#import <NGObjWeb/NSException+HTTP.h> #import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <GDLContentStore/GCSChannelManager.h> #import <GDLContentStore/GCSChannelManager.h>
#import <GDLContentStore/GCSFolderManager.h> #import <GDLContentStore/GCSFolderManager.h>
#import <GDLContentStore/NSURL+GCS.h> #import <GDLContentStore/NSURL+GCS.h>
#import <GDLAccess/EOAdaptorChannel.h> #import <GDLAccess/EOAdaptorChannel.h>
#import "SOGoFolder.h" #import "SOGoFolder.h"
#import "SOGoUser.h"
#import "SOGoParentFolder.h" #import "SOGoParentFolder.h"
@ -73,6 +76,11 @@
ASSIGN (OCSPath, newOCSPath); ASSIGN (OCSPath, newOCSPath);
} }
- (NSString *) defaultFolderName
{
return @"Personal";
}
- (void) _fetchPersonalFolders: (NSString *) sql - (void) _fetchPersonalFolders: (NSString *) sql
withChannel: (EOAdaptorChannel *) fc withChannel: (EOAdaptorChannel *) fc
{ {
@ -80,7 +88,7 @@
NSDictionary *row; NSDictionary *row;
SOGoFolder *folder; SOGoFolder *folder;
BOOL hasPersonal; BOOL hasPersonal;
NSString *key, *path; NSString *key, *path, *personalName;
if (!subFolderClass) if (!subFolderClass)
subFolderClass = [[self class] subFolderClass]; subFolderClass = [[self class] subFolderClass];
@ -92,8 +100,7 @@
while (row) while (row)
{ {
folder folder
= [subFolderClass folderWithName: [row objectForKey: @"c_path4"] = [subFolderClass objectWithName: [row objectForKey: @"c_path4"]
andDisplayName: [row objectForKey: @"c_foldername"]
inContainer: self]; inContainer: self];
key = [row objectForKey: @"c_path4"]; key = [row objectForKey: @"c_path4"];
hasPersonal = (hasPersonal || [key isEqualToString: @"personal"]); hasPersonal = (hasPersonal || [key isEqualToString: @"personal"]);
@ -105,9 +112,9 @@
if (!hasPersonal) if (!hasPersonal)
{ {
folder = [subFolderClass folderWithName: @"personal" folder = [subFolderClass objectWithName: @"personal" inContainer: self];
andDisplayName: @"personal" personalName = [self labelForKey: [self defaultFolderName]];
inContainer: self]; [folder setDisplayName: personalName];
path = [NSString stringWithFormat: @"/Users/%@/%@/personal", path = [NSString stringWithFormat: @"/Users/%@/%@/personal",
[self ownerInContext: context], [self ownerInContext: context],
nameInContainer]; nameInContainer];
@ -132,7 +139,7 @@
gcsFolderType = [[self class] gcsFolderType]; gcsFolderType = [[self class] gcsFolderType];
sql sql
= [NSString stringWithFormat: (@"SELECT c_path4, c_foldername FROM %@" = [NSString stringWithFormat: (@"SELECT c_path4 FROM %@"
@" WHERE c_path2 = '%@'" @" WHERE c_path2 = '%@'"
@" AND c_folder_type = '%@'"), @" AND c_folder_type = '%@'"),
[folderLocation gcsTableName], [folderLocation gcsTableName],
@ -149,25 +156,58 @@
{ {
} }
- (NSException *) newFolderWithName: (NSString *) name - (void) appendSubscribedSources
{ {
NSArray *subscribedReferences;
NSUserDefaults *settings;
NSEnumerator *allKeys;
NSString *currentKey;
SOGoFolder *subscribedFolder;
settings = [[context activeUser] userSettings];
subscribedReferences = [[settings objectForKey: nameInContainer]
objectForKey: @"SubscribedFolders"];
if ([subscribedReferences isKindOfClass: [NSArray class]])
{
allKeys = [subscribedReferences objectEnumerator];
currentKey = [allKeys nextObject];
while (currentKey)
{
subscribedFolder
= [subFolderClass folderWithSubscriptionReference: currentKey
inContainer: self];
[subFolders setObject: subscribedFolder
forKey: [subscribedFolder nameInContainer]];
currentKey = [allKeys nextObject];
}
}
}
- (NSException *) newFolderWithName: (NSString *) name
nameInContainer: (NSString **) newNameInContainer
{
NSString *newFolderID;
SOGoFolder *newFolder; SOGoFolder *newFolder;
NSException *error; NSException *error;
if (!subFolderClass) if (!subFolderClass)
subFolderClass = [[self class] subFolderClass]; subFolderClass = [[self class] subFolderClass];
newFolder = [subFolderClass folderWithName: name *newNameInContainer = nil;
andDisplayName: name newFolderID = [self globallyUniqueObjectId];
inContainer: self]; newFolder = [subFolderClass objectWithName: newFolderID inContainer: self];
if ([newFolder isKindOfClass: [NSException class]]) if ([newFolder isKindOfClass: [NSException class]])
error = (NSException *) newFolder; error = (NSException *) newFolder;
else else
{ {
[newFolder setDisplayName: name];
[newFolder setOCSPath: [NSString stringWithFormat: @"%@/%@", [newFolder setOCSPath: [NSString stringWithFormat: @"%@/%@",
OCSPath, name]]; OCSPath, newFolderID]];
if ([newFolder create]) if ([newFolder create])
error = nil; {
error = nil;
*newNameInContainer = newFolderID;
}
else else
error = [NSException exceptionWithHTTPStatus: 400 error = [NSException exceptionWithHTTPStatus: 400
reason: @"The new folder could not be created"]; reason: @"The new folder could not be created"];
@ -178,11 +218,16 @@
- (void) initSubFolders - (void) initSubFolders
{ {
NSString *login;
if (!subFolders) if (!subFolders)
{ {
subFolders = [NSMutableDictionary new]; subFolders = [NSMutableDictionary new];
[self appendPersonalSources]; [self appendPersonalSources];
[self appendSystemSources]; [self appendSystemSources];
login = [[context activeUser] login];
if ([login isEqualToString: owner])
[self appendSubscribedSources];
} }
} }

View file

@ -26,7 +26,7 @@
#import <NGObjWeb/SoClassSecurityInfo.h> #import <NGObjWeb/SoClassSecurityInfo.h>
#import <NGExtensions/NSObject+Logs.h> #import <NGExtensions/NSObject+Logs.h>
#import <Appointments/SOGoAppointmentFolder.h> #import <Appointments/SOGoAppointmentFolders.h>
#import <Appointments/SOGoFreeBusyObject.h> #import <Appointments/SOGoFreeBusyObject.h>
#import <Contacts/SOGoContactFolders.h> #import <Contacts/SOGoContactFolders.h>
#import <Mailer/SOGoMailAccounts.h> #import <Mailer/SOGoMailAccounts.h>
@ -117,7 +117,7 @@
- (NSString *) ocsPrivateCalendarPath - (NSString *) ocsPrivateCalendarPath
{ {
return [[self ocsUserPath] stringByAppendingString:@"/Calendar/personal"]; return [[self ocsUserPath] stringByAppendingString:@"/Calendar"];
} }
- (NSString *) ocsPrivateContactsPath - (NSString *) ocsPrivateContactsPath
@ -134,15 +134,15 @@
// : [super permissionForKey: key]); // : [super permissionForKey: key]);
// } // }
- (SOGoAppointmentFolder *) privateCalendar: (NSString *) _key - (SOGoAppointmentFolders *) privateCalendars: (NSString *) _key
inContext: (WOContext *) _ctx inContext: (WOContext *) _ctx
{ {
SOGoAppointmentFolder *calendar; SOGoAppointmentFolders *calendars;
calendar = [$(@"SOGoAppointmentFolder") objectWithName: _key inContainer: self]; calendars = [$(@"SOGoAppointmentFolders") objectWithName: _key inContainer: self];
[calendar setOCSPath: [self ocsPrivateCalendarPath]]; [calendars setBaseOCSPath: [self ocsPrivateCalendarPath]];
return calendar; return calendars;
} }
- (SOGoContactFolders *) privateContacts: (NSString *) _key - (SOGoContactFolders *) privateContacts: (NSString *) _key
@ -185,7 +185,7 @@
if (!obj) if (!obj)
{ {
if ([_key isEqualToString: @"Calendar"]) if ([_key isEqualToString: @"Calendar"])
obj = [self privateCalendar: @"Calendar" inContext: _ctx]; obj = [self privateCalendars: @"Calendar" inContext: _ctx];
// if (![_key isEqualToString: @"Calendar"]) // if (![_key isEqualToString: @"Calendar"])
// obj = [obj lookupName: [_key pathExtension] // obj = [obj lookupName: [_key pathExtension]
// inContext: _ctx acquire: NO]; // inContext: _ctx acquire: NO];

View file

@ -32,3 +32,4 @@
"You cannot subscribe to a folder that you own!" = "You cannot subscribe to a folder that you own!"; "You cannot subscribe to a folder that you own!" = "You cannot subscribe to a folder that you own!";
"Unable to unsubscribe from that folder!" = "Unable to unsubscribe from that folder!"; "Unable to unsubscribe from that folder!" = "Unable to unsubscribe from that folder!";
"You cannot unsubscribe from a folder that you own!" = "You cannot unsubscribe from a folder that you own!"; "You cannot unsubscribe from a folder that you own!" = "You cannot unsubscribe from a folder that you own!";
"Unable to rename that folder!" = "Unable to rename that folder!";

View file

@ -33,3 +33,4 @@
"You cannot subscribe to a folder that you own!" = "Impossible de vous abonner à un dossier qui vous appartient."; "You cannot subscribe to a folder that you own!" = "Impossible de vous abonner à un dossier qui vous appartient.";
"Unable to unsubscribe from that folder!" = "Impossible de se désabonner de ce dossier."; "Unable to unsubscribe from that folder!" = "Impossible de se désabonner de ce dossier.";
"You cannot unsubscribe from a folder that you own!" = "Impossible de vous désabonner d'un dossier qui vous appartient."; "You cannot unsubscribe from a folder that you own!" = "Impossible de vous désabonner d'un dossier qui vous appartient.";
"Unable to rename that folder!" = "Impossible de renommer ce dossier.";

View file

@ -17,6 +17,7 @@ CommonUI_OBJC_FILES += \
UIxAclEditor.m \ UIxAclEditor.m \
UIxObjectActions.m \ UIxObjectActions.m \
UIxFolderActions.m \ UIxFolderActions.m \
UIxParentFolderActions.m \
UIxElemBuilder.m \ UIxElemBuilder.m \
UIxTabView.m \ UIxTabView.m \
UIxTabItem.m \ UIxTabItem.m \

View file

@ -35,3 +35,4 @@
"You cannot subscribe to a folder that you own!" = "Unmöglich sich an einem Ordner zu abonnieren, der Ihnen selbst gehört."; "You cannot subscribe to a folder that you own!" = "Unmöglich sich an einem Ordner zu abonnieren, der Ihnen selbst gehört.";
"Unable to unsubscribe from that folder!" = "Unmöglich sich von diesem Ordner zu des-abonnieren."; "Unable to unsubscribe from that folder!" = "Unmöglich sich von diesem Ordner zu des-abonnieren.";
"You cannot unsubscribe from a folder that you own!" = "Unmöglich sich von einem Ordner zu des-abonnieren, der Ihnen selbst gehört."; "You cannot unsubscribe from a folder that you own!" = "Unmöglich sich von einem Ordner zu des-abonnieren, der Ihnen selbst gehört.";
"Unable to rename that folder!" = "Unable to rename that folder!";

View file

@ -41,7 +41,7 @@
NSString *owner; NSString *owner;
NSString *login; NSString *login;
NSString *baseFolder; NSString *baseFolder;
NSMutableString *subscriptionPointer; NSString *subscriptionPointer;
NSMutableDictionary *moduleSettings; NSMutableDictionary *moduleSettings;
BOOL isMailInvitation; BOOL isMailInvitation;
} }

View file

@ -33,8 +33,9 @@
#import <NGObjWeb/SoSecurityManager.h> #import <NGObjWeb/SoSecurityManager.h>
#import <SoObjects/SOGo/LDAPUserManager.h> #import <SoObjects/SOGo/LDAPUserManager.h>
#import <SoObjects/SOGo/NSArray+Utilities.h>
#import <SoObjects/SOGo/SOGoUser.h> #import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/SOGo/SOGoObject.h> #import <SoObjects/SOGo/SOGoFolder.h>
#import <SoObjects/SOGo/SOGoPermissions.h> #import <SoObjects/SOGo/SOGoPermissions.h>
#import "WODirectAction+SOGo.h" #import "WODirectAction+SOGo.h"
@ -74,21 +75,19 @@
} }
[ud setObject: moduleSettings forKey: baseFolder]; [ud setObject: moduleSettings forKey: baseFolder];
subscriptionPointer = [NSMutableString stringWithFormat: @"%@:%@", subscriptionPointer = [NSString stringWithFormat: @"%@:%@/%@",
owner, baseFolder]; owner, baseFolder,
if ([baseFolder isEqualToString: @"Contacts"]) [clientObject nameInContainer]];
[subscriptionPointer appendFormat: @"/%@",
[clientObject nameInContainer]];
mailInvitationParam mailInvitationParam
= [[context request] formValueForKey: @"mail-invitation"]; = [[context request] formValueForKey: @"mail-invitation"];
isMailInvitation = [mailInvitationParam boolValue]; isMailInvitation = [mailInvitationParam boolValue];
} }
- (WOResponse *) _realActionWithFolderName: (NSDictionary *) folderDict - (WOResponse *) _realSubscribe: (BOOL) reallyDo
{ {
WOResponse *response; WOResponse *response;
NSMutableDictionary *folderSubscription; NSMutableArray *folderSubscription;
NSString *mailInvitationURL; NSString *mailInvitationURL;
if ([owner isEqualToString: login]) if ([owner isEqualToString: login])
@ -101,17 +100,17 @@
{ {
folderSubscription folderSubscription
= [moduleSettings objectForKey: @"SubscribedFolders"]; = [moduleSettings objectForKey: @"SubscribedFolders"];
if (!folderSubscription) if (!(folderSubscription
&& [folderSubscription isKindOfClass: [NSMutableArray class]]))
{ {
folderSubscription = [NSMutableDictionary dictionary]; folderSubscription = [NSMutableArray array];
[moduleSettings setObject: folderSubscription [moduleSettings setObject: folderSubscription
forKey: @"SubscribedFolders"]; forKey: @"SubscribedFolders"];
} }
if (folderDict) if (reallyDo)
[folderSubscription setObject: folderDict [folderSubscription addObjectUniquely: subscriptionPointer];
forKey: subscriptionPointer];
else else
[folderSubscription removeObjectForKey: subscriptionPointer]; [folderSubscription removeObject: subscriptionPointer];
[ud synchronize]; [ud synchronize];
@ -133,32 +132,16 @@
- (WOResponse *) subscribeAction - (WOResponse *) subscribeAction
{ {
NSString *email;
NSMutableDictionary *folderDict;
NSString *folderName;
[self _setupContext]; [self _setupContext];
email = [NSString stringWithFormat: @"%@ <%@>",
[um getCNForUID: owner],
[um getEmailForUID: owner]];
if ([baseFolder isEqualToString: @"Contacts"])
folderName = [NSString stringWithFormat: @"%@ (%@)",
[clientObject nameInContainer], email];
else
folderName = email;
folderDict = [NSMutableDictionary dictionary]; return [self _realSubscribe: YES];
[folderDict setObject: folderName forKey: @"displayName"];
[folderDict setObject: [NSNumber numberWithBool: NO] forKey: @"active"];
return [self _realActionWithFolderName: folderDict];
} }
- (WOResponse *) unsubscribeAction - (WOResponse *) unsubscribeAction
{ {
[self _setupContext]; [self _setupContext];
return [self _realActionWithFolderName: nil]; return [self _realSubscribe: NO];
} }
- (WOResponse *) canAccessContentAction - (WOResponse *) canAccessContentAction
@ -168,26 +151,24 @@
- (WOResponse *) _realFolderActivation: (BOOL) makeActive - (WOResponse *) _realFolderActivation: (BOOL) makeActive
{ {
NSMutableDictionary *folderSubscription, *folderDict; NSMutableArray *folderSubscription;
NSNumber *active; NSString *folderName;
[self _setupContext]; [self _setupContext];
active = [NSNumber numberWithBool: makeActive]; folderSubscription
if ([owner isEqualToString: login]) = [moduleSettings objectForKey: @"ActiveFolders"];
[moduleSettings setObject: active forKey: @"activateUserFolder"]; if (!folderSubscription)
else
{ {
folderSubscription folderSubscription = [NSMutableArray array];
= [moduleSettings objectForKey: @"SubscribedFolders"]; [moduleSettings setObject: folderSubscription forKey: @"ActiveFolders"];
if (folderSubscription)
{
folderDict = [folderSubscription objectForKey: subscriptionPointer];
if (folderDict)
[folderDict setObject: active
forKey: @"active"];
}
} }
folderName = [clientObject nameInContainer];
if (makeActive)
[folderSubscription addObjectUniquely: folderName];
else
[folderSubscription removeObject: folderName];
[ud synchronize]; [ud synchronize];
return [self responseWith204]; return [self responseWith204];
@ -203,4 +184,36 @@
return [self _realFolderActivation: NO]; return [self _realFolderActivation: NO];
} }
- (WOResponse *) deleteFolderAction
{
WOResponse *response;
response = (WOResponse *) [[self clientObject] delete];
if (!response)
response = [self responseWith204];
return response;
}
- (WOResponse *) renameFolderAction
{
WOResponse *response;
NSString *folderName;
folderName = [[context request] formValueForKey: @"name"];
if ([folderName length] > 0)
{
clientObject = [self clientObject];
[clientObject renameTo: folderName];
response = [self responseWith204];
}
else
{
response = [self responseWithStatus: 500];
[response appendContentString: @"Missing 'name' parameter."];
}
return response;
}
@end @end

View file

@ -1,95 +1,114 @@
{ /* -*-javascript-*- */ { /* -*-java-*- */
requires = ( MAIN, Mailer ); requires = ( MAIN, Mailer );
publicResources = (
calendar.css,
uix.css,
menu_logo_top.gif,
line_left.gif,
line_stretch.gif,
line_right.gif,
box_topleft.gif,
box_top.gif,
box_topright.gif,
box_left.gif,
box_right.gif,
box_botleft.gif,
box_bottom.gif,
box_botright.gif,
tab_selected.gif,
tab_.gif,
corner_right.gif,
closewindow.gif,
OGoLogo.gif,
upward_sorted.gif,
downward_sorted.gif,
non_sorted.gif
);
publicResources = ( factories = {
calendar.css, };
uix.css,
menu_logo_top.gif,
line_left.gif,
line_stretch.gif,
line_right.gif,
box_topleft.gif,
box_top.gif,
box_topright.gif,
box_left.gif,
box_right.gif,
box_botleft.gif,
box_bottom.gif,
box_botright.gif,
tab_selected.gif,
tab_.gif,
corner_right.gif,
closewindow.gif,
OGoLogo.gif,
upward_sorted.gif,
downward_sorted.gif,
non_sorted.gif
);
factories = { categories = {
}; SOGoObject = {
methods = {
categories = { addUserInAcls = {
SOGoObject = { protectedBy = "SaveAcls";
methods = { actionClass = "UIxObjectActions";
addUserInAcls = { actionName = "addUserInAcls";
protectedBy = "SaveAcls"; };
actionClass = "UIxObjectActions"; removeUserFromAcls = {
actionName = "addUserInAcls"; protectedBy = "SaveAcls";
}; actionClass = "UIxObjectActions";
removeUserFromAcls = { actionName = "removeUserFromAcls";
protectedBy = "SaveAcls"; };
actionClass = "UIxObjectActions"; acls = {
actionName = "removeUserFromAcls"; protectedBy = "ReadAcls";
}; pageName = "UIxAclEditor";
acls = { };
protectedBy = "ReadAcls"; saveAcls = {
pageName = "UIxAclEditor"; protectedBy = "SaveAcls";
}; pageName = "UIxAclEditor";
saveAcls = { actionName = "saveAcls";
protectedBy = "SaveAcls"; };
pageName = "UIxAclEditor"; userRights = {
actionName = "saveAcls"; protectedBy = "ReadAcls";
}; pageName = "UIxUserRightsEditor";
userRights = { };
protectedBy = "ReadAcls"; saveUserRights = {
pageName = "UIxUserRightsEditor"; protectedBy = "ReadAcls";
}; pageName = "UIxUserRightsEditor";
saveUserRights = { actionName = "saveUserRights";
protectedBy = "ReadAcls"; };
pageName = "UIxUserRightsEditor";
actionName = "saveUserRights";
};
};
}; };
SOGoFolder = { };
methods = { SOGoParentFolder = {
subscribe = { methods = {
protectedBy = "<public>"; createFolder = {
actionClass = "UIxFolderActions"; protectedBy = "View";
actionName = "subscribe"; actionClass = "UIxParentFolderActions";
}; actionName = "createFolder";
unsubscribe = { };
protectedBy = "<public>";
actionClass = "UIxFolderActions";
actionName = "unsubscribe";
};
canAccessContent = {
protectedBy = "<public>";
actionClass = "UIxFolderActions";
actionName = "canAccessContent";
};
activateFolder = {
protectedBy = "<public>";
actionClass = "UIxFolderActions";
actionName = "activateFolder";
};
deactivateFolder = {
protectedBy = "<public>";
actionClass = "UIxFolderActions";
actionName = "deactivateFolder";
};
};
}; };
}; };
SOGoFolder = {
methods = {
subscribe = {
protectedBy = "<public>";
actionClass = "UIxFolderActions";
actionName = "subscribe";
};
unsubscribe = {
protectedBy = "<public>";
actionClass = "UIxFolderActions";
actionName = "unsubscribe";
};
canAccessContent = {
protectedBy = "<public>";
actionClass = "UIxFolderActions";
actionName = "canAccessContent";
};
activateFolder = {
protectedBy = "<public>";
actionClass = "UIxFolderActions";
actionName = "activateFolder";
};
deactivateFolder = {
protectedBy = "<public>";
actionClass = "UIxFolderActions";
actionName = "deactivateFolder";
};
deleteFolder = {
protectedBy = "SaveAcls"; /* a hack to force "owner" */
actionClass = "UIxFolderActions";
actionName = "deleteFolder";
};
renameFolder = {
protectedBy = "SaveAcls";
actionClass = "UIxFolderActions";
actionName = "renameFolder";
};
};
};
};
} }

View file

@ -105,6 +105,8 @@
"Are you sure you want to delete the selected address book?" "Are you sure you want to delete the selected address book?"
= "Are you sure you want to delete the selected address book?"; = "Are you sure you want to delete the selected address book?";
"Address Book Name" = "Address Book Name";
"You cannot subscribe to a folder that you own!" "You cannot subscribe to a folder that you own!"
= "You cannot subscribe to a folder that you own!"; = "You cannot subscribe to a folder that you own!";
"Unable to subscribe to that folder!" "Unable to subscribe to that folder!"
@ -125,4 +127,4 @@
= "This person can erase cards from this addressbook."; = "This person can erase cards from this addressbook.";
"The selected contact has no email address." "The selected contact has no email address."
= "The selected contact has no email address."; = "The selected contact has no email address.";

View file

@ -118,6 +118,8 @@
"Are you sure you want to delete the selected address book?" "Are you sure you want to delete the selected address book?"
= "Voulez-vous vraiment supprimer le carnet d'adresses sélectionné ?"; = "Voulez-vous vraiment supprimer le carnet d'adresses sélectionné ?";
"Address Book Name" = "Nom du carnet d'adresses";
"You cannot subscribe to a folder that you own!" "You cannot subscribe to a folder that you own!"
= "Vous ne pouvez pas vous inscrire à un dossier qui vous appartient!"; = "Vous ne pouvez pas vous inscrire à un dossier qui vous appartient!";
"Unable to subscribe to that folder!" "Unable to subscribe to that folder!"
@ -138,4 +140,4 @@
= "Cette personne peut effacer des fiches de ce carnet d'adresses."; = "Cette personne peut effacer des fiches de ce carnet d'adresses.";
"The selected contact has no email address." "The selected contact has no email address."
= "Cette personne n'a pas d'adresse courriel." = "Cette personne n'a pas d'adresse courriel."

View file

@ -109,6 +109,8 @@
"Are you sure you want to delete the selected address book?" "Are you sure you want to delete the selected address book?"
= "Voulez-vous vraiment supprimer le carnet d'adresses sélectionné ?"; = "Voulez-vous vraiment supprimer le carnet d'adresses sélectionné ?";
"Address Book Name" = "Address Book Name";
"You cannot subscribe to a folder that you own!" "You cannot subscribe to a folder that you own!"
= "Vous ne pouvez pas vous inscrire à un dossier qui vous appartient!"; = "Vous ne pouvez pas vous inscrire à un dossier qui vous appartient!";
"Unable to subscribe to that folder!" "Unable to subscribe to that folder!"

View file

@ -584,8 +584,8 @@
id <SOGoContactFolder> co; id <SOGoContactFolder> co;
co = [self clientObject]; co = [self clientObject];
if ([[co class] respondsToSelector: @selector (globallyUniqueObjectId)]) if ([co respondsToSelector: @selector (globallyUniqueObjectId)])
objectId = [[[self clientObject] class] globallyUniqueObjectId]; objectId = [co globallyUniqueObjectId];
else else
objectId = nil; objectId = nil;

View file

@ -52,8 +52,7 @@
WORequest *request; WORequest *request;
folders = [self clientObject]; folders = [self clientObject];
action = [NSString stringWithFormat: @"../personal/%@", action = [NSString stringWithFormat: @"../personal/%@", actionName];
actionName];
request = [[self context] request]; request = [[self context] request];
@ -74,25 +73,6 @@
return [self _selectActionForApplication: @"new"]; return [self _selectActionForApplication: @"new"];
} }
- (id <WOActionResults>) newAbAction
{
id <WOActionResults> response;
NSString *name;
name = [self queryParameterForKey: @"name"];
if ([name length] > 0)
{
response = [[self clientObject] newFolderWithName: name];
if (!response)
response = [self responseWith204];
}
else
response = [NSException exceptionWithHTTPStatus: 400
reason: @"The name is missing"];
return response;
}
- (id) selectForMailerAction - (id) selectForMailerAction
{ {
return [self _selectActionForApplication: @"mailer-contacts"]; return [self _selectActionForApplication: @"mailer-contacts"];
@ -193,50 +173,55 @@
return result; return result;
} }
- (NSArray *) _gcsFoldersFromFolder: (SOGoContactFolders *) contactFolders - (NSArray *) _subFoldersFromFolder: (SOGoParentFolder *) parentFolder
{ {
NSMutableArray *gcsFolders; NSMutableArray *folders;
NSEnumerator *contactSubfolders; NSEnumerator *subfolders;
SOGoContactGCSFolder *currentContactFolder; SOGoFolder *currentFolder;
NSString *folderName, *displayName; NSString *folderName;
NSMutableDictionary *currentDictionary; NSMutableDictionary *currentDictionary;
SoSecurityManager *securityManager;
gcsFolders = [NSMutableArray new]; securityManager = [SoSecurityManager sharedSecurityManager];
[gcsFolders autorelease];
// return (([securityManager validatePermission: SoPerm_AccessContentsInformation
// onObject: contactFolder
// inContext: context] == nil)
contactSubfolders = [[contactFolders subFolders] objectEnumerator]; folders = [NSMutableArray new];
currentContactFolder = [contactSubfolders nextObject]; [folders autorelease];
while (currentContactFolder)
subfolders = [[parentFolder subFolders] objectEnumerator];
currentFolder = [subfolders nextObject];
while (currentFolder)
{ {
if ([currentContactFolder if (![securityManager validatePermission: SOGoPerm_AccessObject
isKindOfClass: [SOGoContactGCSFolder class]]) onObject: currentFolder inContext: context])
{ {
displayName = [[currentContactFolder ocsFolder] folderName]; folderName = [NSString stringWithFormat: @"/%@/%@",
if (displayName) [parentFolder nameInContainer],
{ [currentFolder nameInContainer]];
folderName = [NSString stringWithFormat: @"/Contacts/%@", currentDictionary
[currentContactFolder nameInContainer]]; = [NSMutableDictionary dictionaryWithCapacity: 3];
currentDictionary [currentDictionary setObject: [currentFolder displayName]
= [NSMutableDictionary dictionaryWithCapacity: 3]; forKey: @"displayName"];
[currentDictionary setObject: displayName forKey: @"displayName"]; [currentDictionary setObject: folderName forKey: @"name"];
[currentDictionary setObject: folderName forKey: @"name"]; [currentDictionary setObject: [currentFolder folderType]
[currentDictionary setObject: @"contact" forKey: @"type"]; forKey: @"type"];
[gcsFolders addObject: currentDictionary]; [folders addObject: currentDictionary];
}
} }
currentContactFolder = [contactSubfolders nextObject]; currentFolder = [subfolders nextObject];
} }
return gcsFolders; return folders;
} }
- (NSArray *) _foldersForUID: (NSString *) uid - (NSArray *) _foldersForUID: (NSString *) uid
ofType: (NSString *) folderType ofType: (NSString *) folderType
{ {
NSObject *topFolder, *userFolder; NSObject *topFolder, *userFolder;
SOGoContactFolders *contactFolders; SOGoParentFolder *parentFolder;
NSMutableArray *folders; NSMutableArray *folders;
NSMutableDictionary *currentDictionary;
folders = [NSMutableArray new]; folders = [NSMutableArray new];
[folders autorelease]; [folders autorelease];
@ -245,23 +230,19 @@
userFolder = [topFolder lookupName: uid inContext: context acquire: NO]; userFolder = [topFolder lookupName: uid inContext: context acquire: NO];
/* FIXME: should be moved in the SOGo* classes. Maybe by having a SOGoFolderManager. */ /* FIXME: should be moved in the SOGo* classes. Maybe by having a SOGoFolderManager. */
#warning this might need adjustments whenever we permit multiple calendar folders per-user
if ([folderType length] == 0 || [folderType isEqualToString: @"calendar"]) if ([folderType length] == 0 || [folderType isEqualToString: @"calendar"])
{ {
currentDictionary = [NSMutableDictionary new]; parentFolder = [userFolder lookupName: @"Calendar"
[currentDictionary autorelease]; inContext: context acquire: NO];
[currentDictionary setObject: [self labelForKey: @"Calendar"] [folders
forKey: @"displayName"]; addObjectsFromArray: [self _subFoldersFromFolder: parentFolder]];
[currentDictionary setObject: @"/Calendar" forKey: @"name"];
[currentDictionary setObject: @"calendar" forKey: @"type"];
[folders addObject: currentDictionary];
} }
if ([folderType length] == 0 || [folderType isEqualToString: @"contact"]) if ([folderType length] == 0 || [folderType isEqualToString: @"contact"])
{ {
contactFolders = [userFolder lookupName: @"Contacts" parentFolder = [userFolder lookupName: @"Contacts"
inContext: context acquire: NO]; inContext: context acquire: NO];
[folders [folders
addObjectsFromArray: [self _gcsFoldersFromFolder: contactFolders]]; addObjectsFromArray: [self _subFoldersFromFolder: parentFolder]];
} }
return folders; return folders;
@ -352,31 +333,30 @@
return result; return result;
} }
- (SOGoContactGCSFolder *) contactFolderForUID: (NSString *) uid // - (SOGoContactGCSFolder *) contactFolderForUID: (NSString *) uid
{ // {
SOGoFolder *upperContainer; // SOGoFolder *upperContainer;
SOGoUserFolder *userFolder; // SOGoUserFolder *userFolder;
SOGoContactFolders *contactFolders; // SOGoContactFolders *contactFolders;
SOGoContactGCSFolder *contactFolder; // SOGoContactGCSFolder *contactFolder;
SoSecurityManager *securityManager; // SoSecurityManager *securityManager;
upperContainer = [[[self clientObject] container] container]; // upperContainer = [[[self clientObject] container] container];
userFolder = [SOGoUserFolder objectWithName: uid // userFolder = [SOGoUserFolder objectWithName: uid
inContainer: upperContainer]; // inContainer: upperContainer];
contactFolders = [SOGoContactFolders objectWithName: @"Contacts" // contactFolders = [SOGoUserFolder lookupName: @"Contacts"
inContainer: userFolder]; // inContext: context
contactFolder = [SOGoContactGCSFolder objectWithName: @"personal" // acquire: NO];
inContainer: contactFolders]; // contactFolder = [contactFolders lookupName: @"personal"
[contactFolder // inContext: context
setOCSPath: [NSString stringWithFormat: @"/Users/%@/Contacts/personal", uid]]; // acquire: NO];
[contactFolder setOwner: uid];
securityManager = [SoSecurityManager sharedSecurityManager]; // securityManager = [SoSecurityManager sharedSecurityManager];
return (([securityManager validatePermission: SoPerm_AccessContentsInformation // return (([securityManager validatePermission: SoPerm_AccessContentsInformation
onObject: contactFolder // onObject: contactFolder
inContext: context] == nil) // inContext: context] == nil)
? contactFolder : nil); // ? contactFolder : nil);
} // }
@end @end

View file

@ -81,25 +81,6 @@
return selectorComponentClass; return selectorComponentClass;
} }
- (id <WOActionResults>) deleteAction
{
id <WOActionResults> result;
NSException <WOActionResults> *ex;
WOResponse *response;
ex = [[self clientObject] delete];
if (ex)
result = ex;
else
{
response = [context response];
[response setStatus: 200];
result = response;
}
return result;
}
- (NSString *) defaultSortKey - (NSString *) defaultSortKey
{ {
return @"displayName"; return @"displayName";

View file

@ -31,28 +31,18 @@
@interface UIxContactsListViewContainer : UIxComponent @interface UIxContactsListViewContainer : UIxComponent
{ {
NSString *foldersPrefix;
NSString *selectorComponentClass; NSString *selectorComponentClass;
NSString *currentAdditionalFolder;
NSDictionary *additionalFolders;
id currentFolder; id currentFolder;
} }
- (void) setCurrentFolder: (id) folder; - (void) setCurrentFolder: (id) folder;
- (NSString *) foldersPrefix;
- (NSArray *) contactFolders; - (NSArray *) contactFolders;
- (NSString *) currentContactFolderId; - (NSString *) currentContactFolderId;
- (NSString *) currentContactFolderOwner;
- (NSString *) currentContactFolderName; - (NSString *) currentContactFolderName;
- (NSArray *) additionalFolders;
- (void) setCurrentAdditionalFolder: (NSString *) newCurrentAdditionalFolder;
- (NSString *) currentAdditionalFolder;
- (NSString *) currentAdditionalFolderName;
@end @end
#endif /* UIXCONTACTSLISTVIEWCONTAINERBASE_H */ #endif /* UIXCONTACTSLISTVIEWCONTAINERBASE_H */

View file

@ -41,20 +41,12 @@
{ {
if ((self = [super init])) if ((self = [super init]))
{ {
foldersPrefix = nil;
selectorComponentClass = nil; selectorComponentClass = nil;
additionalFolders = nil;
} }
return self; return self;
} }
- (void) dealloc
{
[additionalFolders release];
[super dealloc];
}
- (void) setSelectorComponentClass: (NSString *) aComponentClass - (void) setSelectorComponentClass: (NSString *) aComponentClass
{ {
selectorComponentClass = aComponentClass; selectorComponentClass = aComponentClass;
@ -86,30 +78,6 @@
currentFolder = folder; currentFolder = folder;
} }
- (NSString *) foldersPrefix
{
NSMutableArray *folders;
SOGoObject *currentObject;
if (!foldersPrefix)
{
folders = [NSMutableArray new];
[folders autorelease];
currentObject = [[self clientObject] container];
while (![currentObject isKindOfClass: [SOGoContactFolders class]])
{
[folders insertObject: [currentObject nameInContainer] atIndex: 0];
currentObject = [currentObject container];
}
foldersPrefix = [folders componentsJoinedByString: @"/"];
[foldersPrefix retain];
}
return foldersPrefix;
}
- (NSArray *) contactFolders - (NSArray *) contactFolders
{ {
SOGoContactFolders *folderContainer; SOGoContactFolders *folderContainer;
@ -121,8 +89,7 @@
- (NSString *) currentContactFolderId - (NSString *) currentContactFolderId
{ {
return [NSString stringWithFormat: @"%@/%@", return [NSString stringWithFormat: @"/%@",
[self foldersPrefix],
[currentFolder nameInContainer]]; [currentFolder nameInContainer]];
} }
@ -131,35 +98,9 @@
return [currentFolder displayName]; return [currentFolder displayName];
} }
- (NSArray *) additionalFolders - (NSString *) currentContactFolderOwner
{ {
NSUserDefaults *ud; return [currentFolder ownerInContext: context];
if (!additionalFolders)
{
ud = [[context activeUser] userSettings];
additionalFolders
= [[ud objectForKey: @"Contacts"] objectForKey: @"SubscribedFolders"];
[additionalFolders retain];
}
return [additionalFolders allKeys];
}
- (void) setCurrentAdditionalFolder: (NSString *) newCurrentAdditionalFolder
{
currentAdditionalFolder = newCurrentAdditionalFolder;
}
- (NSString *) currentAdditionalFolder
{
return currentAdditionalFolder;
}
- (NSString *) currentAdditionalFolderName
{
return [[additionalFolders objectForKey: currentAdditionalFolder]
objectForKey: @"displayName"];
} }
- (BOOL) hasContactSelectionButtons - (BOOL) hasContactSelectionButtons

View file

@ -17,11 +17,6 @@
pageName = "UIxContactFoldersView"; pageName = "UIxContactFoldersView";
actionName = "new"; actionName = "new";
}; };
newAb = {
protectedBy = "View";
pageName = "UIxContactFoldersView";
actionName = "newAb";
};
mailer-contacts = { mailer-contacts = {
protectedBy = "View"; protectedBy = "View";
pageName = "UIxContactFoldersView"; pageName = "UIxContactFoldersView";
@ -87,11 +82,6 @@
pageName = "UIxContactsListView"; pageName = "UIxContactsListView";
actionName = "mailerContacts"; actionName = "mailerContacts";
}; };
delete = {
protectedBy = "SaveAcls"; /* a hack to force "owner" */
pageName = "UIxContactsListView";
actionName = "delete";
};
userRights = { userRights = {
protectedBy = "ReadAcls"; protectedBy = "ReadAcls";
pageName = "UIxContactsUserRightsEditor"; pageName = "UIxContactsUserRightsEditor";

View file

@ -73,7 +73,7 @@
cookieString = [NSString stringWithFormat: @"%@:%@", cookieString = [NSString stringWithFormat: @"%@:%@",
[self queryParameterForKey: @"userName"], [self queryParameterForKey: @"userName"],
[self queryParameterForKey: @"password"]]; [self queryParameterForKey: @"password"]];
cookieValue = [NSString stringWithFormat: @"basic%@", cookieValue = [NSString stringWithFormat: @"basic %@",
[cookieString stringByEncodingBase64]]; [cookieString stringByEncodingBase64]];
authCookie = [WOCookie cookieWithName: [auth cookieNameInContext: context] authCookie = [WOCookie cookieWithName: [auth cookieNameInContext: context]
value: cookieValue]; value: cookieValue];
@ -83,88 +83,24 @@
return response; return response;
} }
// - (id <WOActionResults>) defaultAction - (id <WOActionResults>) defaultAction
// { {
// WOResponse *r; id <WOActionResults> response;
// NSString *login, *rhk; NSString *login, *oldLocation;
// SOGoWebAuthenticator *auth;
// SOGoUser *user;
// SOGoUserFolder *home;
// WOApplication *base;
// /* login = [[context activeUser] login];
// Note: ctx.activeUser is NOT set here. Don't know why, so we retrieve if ([login isEqualToString: @"anonymous"])
// the user from the authenticator. response = self;
// */ else
{
// auth = [[self clientObject] authenticatorInContext: context]; oldLocation = [[self clientObject] baseURLInContext: context];
// user = [auth userInContext: context]; response
// login = [user login]; = [self redirectToLocation: [NSString stringWithFormat: @"%@/%@",
oldLocation, login]];
}
// if ([login isEqualToString:@"anonymous"]) { return response;
// /* use root page for unauthenticated users */ }
// return self;
// }
// /* check base */
// base = [self application];
// rhk = [[context request] requestHandlerKey];
// if (([rhk length] == 0) || ([base requestHandlerForKey:rhk] == nil)) {
// base = [base lookupName: @"so" inContext: context acquire: NO];
// if (![base isNotNull] || [base isKindOfClass:[NSException class]]) {
// /* use root page if home could not be found */
// [self errorWithFormat:@"Did not find 'so' request handler!"];
// return self;
// }
// }
// /* lookup home-page */
// home = [base lookupName: login inContext: context acquire: NO];
// if (![home isNotNull] || [home isKindOfClass:[NSException class]]) {
// /* use root page if home could not be found */
// return self;
// }
// /* redirect to home-page */
// r = [context response];
// [r setStatus: 302 /* moved */];
// [r setHeader: [home baseURLInContext: context]
// forKey: @"location"];
// return r;
// }
/* response generation */
// - (void) appendToResponse: (WOResponse *) response
// inContext: (WOContext *) ctx
// {
// NSString *rhk;
// // TODO: we might also want to look into the HTTP basic-auth to redirect to
// // the login URL!
// rhk = [[ctx request] requestHandlerKey];
// if ([rhk length] == 0
// || [[self application] requestHandlerForKey: rhk] == nil)
// {
// /* a small hack to redirect to a valid URL */
// NSString *url;
// url = [ctx urlWithRequestHandlerKey: @"so" path: @"/" queryString: nil];
// [response setStatus: 302 /* moved */];
// [response setHeader: url forKey: @"location"];
// [self logWithFormat: @"URL: %@", url];
// return;
// }
// [response setHeader: @"text/html" forKey: @"content-type"];
// [super appendToResponse: response inContext: ctx];
// }
- (BOOL) isPublicInContext: (WOContext *) localContext - (BOOL) isPublicInContext: (WOContext *) localContext
{ {

View file

@ -46,6 +46,14 @@
"Access Contents Information" = ( "Owner", "ObjectViewer" ); "Access Contents Information" = ( "Owner", "ObjectViewer" );
}; };
}; };
SOGoParentFolder = {
superclass = "SOGoObject";
protectedBy = "Access Contents Information";
defaultRoles = {
"Access Contents Information" = ( "Authenticated" );
"WebDAV Access" = ( "Authenticated" );
};
};
SOGoUserFolder = { SOGoUserFolder = {
superclass = "SOGoFolder"; superclass = "SOGoFolder";
protectedBy = "Access Contents Information"; protectedBy = "Access Contents Information";

View file

@ -125,7 +125,8 @@ static BOOL shouldDisplayPasswordChange = NO;
- (NSArray *) timeZonesList - (NSArray *) timeZonesList
{ {
return [NSTimeZone knownTimeZoneNames]; return [[NSTimeZone knownTimeZoneNames]
sortedArrayUsingSelector: @selector (localizedCaseInsensitiveCompare:)];
} }
- (NSString *) userTimeZone - (NSString *) userTimeZone

View file

@ -110,8 +110,11 @@
/* Button Titles */ /* Button Titles */
"Add..." = "Add..."; "New Calendar..." = "New Calendar...";
"Remove" = "Remove"; "Subscribe to a Calendar..." = "Subscribe to a Calendar...";
"Remove the selected Calendar" = "Remove the selected Calendar";
"Name of the Calendar" = "Name of the Calendar";
"new" = "New"; "new" = "New";
"printview" = "Print View"; "printview" = "Print View";

View file

@ -111,8 +111,11 @@
/* Button Titles */ /* Button Titles */
"Add..." = "Ajouter..."; "New Calendar..." = "Nouvel agenda...";
"Remove" = "Enlever"; "Subscribe to a Calendar..." = "S'inscrire à un agenda...";
"Remove the selected Calendar" = "Enlever l'agenda sélectionné";
"Name of the Calendar" = "Nom de l'agenda";
"new" = "Nouveau"; "new" = "Nouveau";
"printview" = "Version imprimable"; "printview" = "Version imprimable";

View file

@ -48,7 +48,7 @@ SchedulerUI_RESOURCE_FILES += \
product.plist product.plist
SchedulerUI_RESOURCE_FILES += \ SchedulerUI_RESOURCE_FILES += \
Toolbars/SOGoAppointmentFolder.toolbar \ Toolbars/SOGoAppointmentFolders.toolbar \
Toolbars/SOGoAppointmentObject.toolbar \ Toolbars/SOGoAppointmentObject.toolbar \
Toolbars/SOGoAppointmentObjectAccept.toolbar \ Toolbars/SOGoAppointmentObjectAccept.toolbar \
Toolbars/SOGoAppointmentObjectDecline.toolbar \ Toolbars/SOGoAppointmentObjectDecline.toolbar \

View file

@ -100,8 +100,11 @@
/* Button Titles */ /* Button Titles */
"Add..." = "Hinzufügen..."; "New Calendar..." = "New Calendar...";
"Remove" = "Löschen"; "Subscribe to a Calendar..." = "Subscribe to a Calendar...";
"Remove the selected Calendar" = "Remove the selected Calendar";
"Name of the Calendar" = "Name of the Calendar";
"new" = "Neu"; "new" = "Neu";
"printview" = "Version imprimable"; "printview" = "Version imprimable";

View file

@ -286,14 +286,14 @@
{ {
NSString *objectId, *method, *uri; NSString *objectId, *method, *uri;
id <WOActionResults> result; id <WOActionResults> result;
Class clientKlazz; SOGoAppointmentFolder *co;
clientKlazz = [[self clientObject] class]; co = [self clientObject];
objectId = [clientKlazz globallyUniqueObjectId]; objectId = [co globallyUniqueObjectId];
if ([objectId length] > 0) if ([objectId length] > 0)
{ {
method = [NSString stringWithFormat:@"%@/Calendar/%@/editAsAppointment", method = [NSString stringWithFormat:@"%@/%@/editAsAppointment",
[self userFolderPath], objectId]; [co soURL], objectId];
uri = [self completeHrefForMethod: method]; uri = [self completeHrefForMethod: method];
result = [self redirectToLocation: uri]; result = [self redirectToLocation: uri];
} }

View file

@ -25,6 +25,7 @@
#import <Foundation/NSEnumerator.h> #import <Foundation/NSEnumerator.h>
#import <Foundation/NSNull.h> #import <Foundation/NSNull.h>
#import <Foundation/NSString.h> #import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#import <NGObjWeb/WOContext.h> #import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WOContext+SoObjects.h> #import <NGObjWeb/WOContext+SoObjects.h>
@ -38,6 +39,7 @@
#import <SoObjects/SOGo/NSArray+Utilities.h> #import <SoObjects/SOGo/NSArray+Utilities.h>
#import <SoObjects/SOGo/NSObject+Utilities.h> #import <SoObjects/SOGo/NSObject+Utilities.h>
#import <SoObjects/Appointments/SOGoAppointmentFolder.h> #import <SoObjects/Appointments/SOGoAppointmentFolder.h>
#import <SoObjects/Appointments/SOGoAppointmentFolders.h>
#import <UI/Common/WODirectAction+SOGo.h> #import <UI/Common/WODirectAction+SOGo.h>
@ -214,36 +216,6 @@
return aptFolder; return aptFolder;
} }
- (NSArray *) _activeCalendarFolders
{
NSMutableArray *activeFolders;
NSEnumerator *folders;
NSDictionary *currentFolderDict;
SOGoAppointmentFolder *currentFolder, *clientObject;
activeFolders = [NSMutableArray new];
[activeFolders autorelease];
clientObject = [self clientObject];
folders = [[clientObject calendarFolders] objectEnumerator];
currentFolderDict = [folders nextObject];
while (currentFolderDict)
{
if ([[currentFolderDict objectForKey: @"active"] boolValue])
{
currentFolder
= [self _aptFolder: [currentFolderDict objectForKey: @"folder"]
withClientObject: clientObject];
[activeFolders addObject: currentFolder];
}
currentFolderDict = [folders nextObject];
}
return activeFolders;
}
- (NSArray *) _fetchFields: (NSArray *) fields - (NSArray *) _fetchFields: (NSArray *) fields
forComponentOfType: (NSString *) component forComponentOfType: (NSString *) component
{ {
@ -252,34 +224,42 @@
NSMutableDictionary *infos, *currentInfo, *newInfo; NSMutableDictionary *infos, *currentInfo, *newInfo;
NSString *owner, *uid; NSString *owner, *uid;
NSNull *marker; NSNull *marker;
SOGoAppointmentFolders *clientObject;
marker = [NSNull null]; marker = [NSNull null];
infos = [NSMutableDictionary dictionary]; infos = [NSMutableDictionary dictionary];
folders = [[self _activeCalendarFolders] objectEnumerator]; clientObject = [self clientObject];
folders = [[clientObject subFolders] objectEnumerator];
currentFolder = [folders nextObject]; currentFolder = [folders nextObject];
while (currentFolder) while (currentFolder)
{ {
owner = [currentFolder ownerInContext: context]; if ([currentFolder isActive])
currentInfos = [[currentFolder fetchCoreInfosFrom: startDate
to: endDate
component: component] objectEnumerator];
newInfo = [currentInfos nextObject];
while (newInfo)
{ {
uid = [newInfo objectForKey: @"c_uid"]; owner = [currentFolder ownerInContext: context];
currentInfo = [infos objectForKey: uid]; currentInfos = [[currentFolder fetchCoreInfosFrom: startDate
if (!currentInfo to: endDate
|| [owner isEqualToString: userLogin]) component: component] objectEnumerator];
{
[self _updatePrivacyInComponent: newInfo
fromFolder: currentFolder];
[newInfo setObject: owner forKey: @"c_owner"];
[infos setObject: [newInfo objectsForKeys: fields
notFoundMarker: marker]
forKey: uid];
}
newInfo = [currentInfos nextObject]; newInfo = [currentInfos nextObject];
while (newInfo)
{
uid = [newInfo objectForKey: @"c_uid"];
currentInfo = [infos objectForKey: uid];
if (!currentInfo
|| [owner isEqualToString: userLogin])
{
[self _updatePrivacyInComponent: newInfo
fromFolder: currentFolder];
[newInfo setObject: [currentFolder nameInContainer]
forKey: @"c_folder"];
// [newInfo setObject: owner forKey: @"c_owner"];
[infos setObject: [newInfo objectsForKeys: fields
notFoundMarker: marker]
forKey: uid];
}
newInfo = [currentInfos nextObject];
}
} }
currentFolder = [folders nextObject]; currentFolder = [folders nextObject];
} }
@ -326,7 +306,7 @@
[self _setupContext]; [self _setupContext];
newEvents = [NSMutableArray array]; newEvents = [NSMutableArray array];
fields = [NSArray arrayWithObjects: @"c_name", @"c_owner", @"c_status", fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status",
@"c_title", @"c_startdate", @"c_enddate", @"c_location", @"c_title", @"c_startdate", @"c_enddate", @"c_location",
@"c_isallday", nil]; @"c_isallday", nil];
events = [[self _fetchFields: fields events = [[self _fetchFields: fields
@ -397,7 +377,7 @@
[self _setupContext]; [self _setupContext];
fields = [NSArray arrayWithObjects: @"c_name", @"c_owner", @"c_status", fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status",
@"c_title", @"c_enddate", nil]; @"c_title", @"c_enddate", nil];
tasks = [[self _fetchFields: fields tasks = [[self _fetchFields: fields

View file

@ -23,6 +23,7 @@
#import <Foundation/NSArray.h> #import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h> #import <Foundation/NSCalendarDate.h>
#import <Foundation/NSString.h> #import <Foundation/NSString.h>
#import <Foundation/NSTimeZone.h>
#import <Foundation/NSUserDefaults.h> #import <Foundation/NSUserDefaults.h>
#import <Foundation/NSValue.h> #import <Foundation/NSValue.h>
@ -41,6 +42,15 @@ static NSMutableArray *yearMenuItems = nil;
@implementation UIxCalMainView @implementation UIxCalMainView
- (NSString *) userUTCOffset
{
NSTimeZone *userTZ;
userTZ = [[context activeUser] timeZone];
return [NSString stringWithFormat: @"%d", [userTZ secondsFromGMT]];
}
- (NSArray *) monthMenuItems - (NSArray *) monthMenuItems
{ {
unsigned int count; unsigned int count;

View file

@ -23,29 +23,23 @@
#ifndef UIXCALENDARSELECTOR_H #ifndef UIXCALENDARSELECTOR_H
#define UIXCALENDARSELECTOR_H #define UIXCALENDARSELECTOR_H
#import <UI/SOGoUI/UIxComponent.h>
@class NSArray; @class NSArray;
@class NSMutableArray; @class NSMutableArray;
@class NSDictionary; @class NSDictionary;
@class NSMutableDictionary;
@class NSString; @class NSString;
@class iCalPerson;
@interface UIxCalendarSelector : UIxComponent @interface UIxCalendarSelector : UIxComponent
{ {
NSMutableDictionary *colors; NSMutableArray *calendars;
NSDictionary *currentCalendar;
NSDictionary *currentCalendarFolder;
NSString *currentCalendarLogin;
} }
- (NSArray *) calendarFolders; - (NSArray *) calendars;
- (void) setCurrentCalendarFolder: (NSDictionary *) newCurrentCalendarFolder; - (void) setCurrentCalendar: (NSDictionary *) newCalendar;
- (NSDictionary *) currentCalendarFolder; - (NSDictionary *) currentCalendar;
- (NSString *) currentCalendarSpanBG;
- (NSString *) currentCalendarLogin;
- (NSString *) currentCalendarStyle;
@end @end

View file

@ -22,34 +22,30 @@
#import <Foundation/NSArray.h> #import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h> #import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h> #import <Foundation/NSValue.h>
#import <Foundation/NSUserDefaults.h>
#import <NGExtensions/NGExtensions.h> #import <SOGo/NSDictionary+Utilities.h>
#import <NGCards/iCalPerson.h>
#import <SOGo/SOGoUser.h>
#import <SOGoUI/UIxComponent.h>
#import <Appointments/SOGoAppointmentFolder.h> #import <Appointments/SOGoAppointmentFolder.h>
#import <Appointments/SOGoAppointmentFolders.h>
#import "UIxCalendarSelector.h" #import "UIxCalendarSelector.h"
static inline char // static inline char
darkenedColor (const char value) // darkenedColor (const char value)
{ // {
char newValue; // char newValue;
if (value >= '0' && value <= '9') // if (value >= '0' && value <= '9')
newValue = ((value - '0') / 2) + '0'; // newValue = ((value - '0') / 2) + '0';
else if (value >= 'a' && value <= 'f') // else if (value >= 'a' && value <= 'f')
newValue = ((value + 10 - 'a') / 2) + '0'; // newValue = ((value + 10 - 'a') / 2) + '0';
else if (value >= 'A' && value <= 'F') // else if (value >= 'A' && value <= 'F')
newValue = ((value + 10 - 'A') / 2) + '0'; // newValue = ((value + 10 - 'A') / 2) + '0';
else // else
newValue = value; // newValue = value;
return newValue; // return newValue;
} // }
static inline NSString * static inline NSString *
colorForNumber (unsigned int number) colorForNumber (unsigned int number)
@ -90,8 +86,8 @@ colorForNumber (unsigned int number)
{ {
if ((self = [super init])) if ((self = [super init]))
{ {
colors = nil; calendars = nil;
currentCalendarFolder = nil; currentCalendar = nil;
} }
return self; return self;
@ -99,82 +95,61 @@ colorForNumber (unsigned int number)
- (void) dealloc - (void) dealloc
{ {
[currentCalendarFolder release]; [calendars release];
[colors release]; [currentCalendar release];
[super dealloc]; [super dealloc];
} }
- (NSArray *) calendarFolders - (NSArray *) calendars
{ {
NSArray *calendarFolders; NSArray *folders;
NSEnumerator *newFolders; SOGoAppointmentFolder *folder;
NSDictionary *currentFolder; NSMutableDictionary *calendar;
unsigned int count; unsigned int count, max;
NSString *folderId, *folderName;
NSNumber *isActive;
calendarFolders = [[self clientObject] calendarFolders]; if (!calendars)
if (!colors)
{ {
colors = [NSMutableDictionary new]; folders = [[self clientObject] subFolders];
count = 0; max = [folders count];
newFolders = [calendarFolders objectEnumerator]; calendars = [[NSMutableArray alloc] initWithCapacity: max];
currentFolder = [newFolders nextObject]; for (count = 0; count < max; count++)
while (currentFolder)
{ {
[colors setObject: colorForNumber (count) folder = [folders objectAtIndex: count];
forKey: [currentFolder objectForKey: @"folder"]]; calendar = [NSMutableDictionary dictionary];
count++; folderName = [folder nameInContainer];
currentFolder = [newFolders nextObject]; [calendar setObject:
[NSString stringWithFormat: @"/%@", folderName]
forKey: @"id"];
[calendar setObject: [folder displayName]
forKey: @"displayName"];
[calendar setObject: folderName forKey: @"folder"];
[calendar setObject: colorForNumber (count)
forKey: @"color"];
isActive = [NSNumber numberWithBool: [folder isActive]];
[calendar setObject: isActive forKey: @"active"];
[calendars addObject: calendar];
} }
} }
return calendarFolders; return calendars;
} }
- (void) setCurrentCalendarFolder: (NSDictionary *) newCurrentCalendarFolder - (void) setCurrentCalendar: (NSDictionary *) newCalendar
{ {
ASSIGN (currentCalendarFolder, newCurrentCalendarFolder); ASSIGN (currentCalendar, newCalendar);
} }
- (NSDictionary *) currentCalendarFolder - (NSDictionary *) currentCalendar
{ {
return currentCalendarFolder; return currentCalendar;
}
- (NSString *) currentCalendarSpanBG
{
NSString *colorKey;
colorKey = [currentCalendarFolder objectForKey: @"folder"];
return [colors objectForKey: colorKey];
}
- (NSString *) currentCalendarLogin
{
NSArray *parts;
NSMutableString *login;
login = [NSMutableString string];
parts = [[currentCalendarFolder objectForKey: @"folder"]
componentsSeparatedByString: @":"];
[login appendString: (([parts count] > 1)
? [parts objectAtIndex: 0]
: [[context activeUser] login])];
[login replaceString: @"." withString: @"_"];
[login replaceString: @"#" withString: @"_"];
[login replaceString: @"@" withString: @"_"];
return login;
} }
- (NSString *) currentCalendarStyle - (NSString *) currentCalendarStyle
{ {
NSString *color; return [currentCalendar
keysWithFormat: @"color: %{color}; background-color: %{color};"];
color = [self currentCalendarSpanBG];
return [NSString stringWithFormat: @"color: %@; background-color: %@;",
color, color];
} }
@end /* UIxCalendarSelector */ @end /* UIxCalendarSelector */

View file

@ -42,6 +42,7 @@
#import <NGExtensions/NSString+misc.h> #import <NGExtensions/NSString+misc.h>
#import <SoObjects/Appointments/SOGoAppointmentFolder.h> #import <SoObjects/Appointments/SOGoAppointmentFolder.h>
#import <SoObjects/Appointments/SOGoAppointmentFolders.h>
#import <SoObjects/Appointments/SOGoAppointmentObject.h> #import <SoObjects/Appointments/SOGoAppointmentObject.h>
#import <SoObjects/Appointments/SOGoTaskObject.h> #import <SoObjects/Appointments/SOGoTaskObject.h>
#import <SoObjects/SOGo/NSString+Utilities.h> #import <SoObjects/SOGo/NSString+Utilities.h>
@ -331,19 +332,20 @@
- (NSArray *) calendarList - (NSArray *) calendarList
{ {
SOGoAppointmentFolder *folder; SOGoAppointmentFolder *calendar, *currentCalendar;
SOGoAppointmentFolders *calendarParent;
NSEnumerator *allCalendars; NSEnumerator *allCalendars;
NSDictionary *currentCalendar;
if (!calendarList) if (!calendarList)
{ {
calendarList = [NSMutableArray new]; calendarList = [NSMutableArray new];
folder = [[self clientObject] container]; calendar = [[self clientObject] container];
allCalendars = [[folder calendarFolders] objectEnumerator]; calendarParent = [calendar container];
allCalendars = [[calendarParent subFolders] objectEnumerator];
currentCalendar = [allCalendars nextObject]; currentCalendar = [allCalendars nextObject];
while (currentCalendar) while (currentCalendar)
{ {
if ([[currentCalendar objectForKey: @"active"] boolValue]) if ([currentCalendar isActive])
[calendarList addObject: currentCalendar]; [calendarList addObject: currentCalendar];
currentCalendar = [allCalendars nextObject]; currentCalendar = [allCalendars nextObject];
} }

View file

@ -324,14 +324,14 @@
{ {
NSString *objectId, *method, *uri; NSString *objectId, *method, *uri;
id <WOActionResults> result; id <WOActionResults> result;
Class clientKlazz; SOGoAppointmentFolder *co;
clientKlazz = [[self clientObject] class]; co = [self clientObject];
objectId = [clientKlazz globallyUniqueObjectId]; objectId = [co globallyUniqueObjectId];
if ([objectId length] > 0) if ([objectId length] > 0)
{ {
method = [NSString stringWithFormat:@"%@/Calendar/%@/editAsTask", method = [NSString stringWithFormat:@"%@/%@/editAsTask",
[self userFolderPath], objectId]; [co soURL], objectId];
uri = [self completeHrefForMethod: method]; uri = [self completeHrefForMethod: method];
result = [self redirectToLocation: uri]; result = [self redirectToLocation: uri];
} }

View file

@ -28,11 +28,11 @@
}; };
categories = { categories = {
SOGoAppointmentFolder = { SOGoAppointmentFolders = {
slots = { slots = {
toolbar = { toolbar = {
protectedBy = "View"; protectedBy = "View";
value = "SOGoAppointmentFolder.toolbar"; value = "SOGoAppointmentFolders.toolbar";
}; };
}; };
methods = { methods = {
@ -70,16 +70,6 @@
protectedBy = "View"; protectedBy = "View";
pageName = "UIxCalMonthView"; pageName = "UIxCalMonthView";
}; };
newevent = {
protectedBy = "Add Documents, Images, and Files";
pageName = "UIxAppointmentEditor";
actionName = "new";
};
newtask = {
protectedBy = "Add Documents, Images, and Files";
pageName = "UIxTaskEditor";
actionName = "new";
};
show = { show = {
protectedBy = "View"; protectedBy = "View";
pageName = "UIxCalView"; pageName = "UIxCalView";
@ -94,15 +84,45 @@
pageName = "UIxAppointmentProposal"; pageName = "UIxAppointmentProposal";
actionName = "proposalSearch"; actionName = "proposalSearch";
}; };
userRights = {
protectedBy = "ReadAcls";
pageName = "UIxCalUserRightsEditor";
};
saveUserRights = {
protectedBy = "SaveAcls";
pageName = "UIxCalUserRightsEditor";
actionName = "saveUserRights";
};
};
};
SOGoAppointmentFolder = {
methods = {
newevent = {
protectedBy = "Add Documents, Images, and Files";
pageName = "UIxAppointmentEditor";
actionName = "new";
};
newtask = {
protectedBy = "Add Documents, Images, and Files";
pageName = "UIxTaskEditor";
actionName = "new";
};
batchDelete = { batchDelete = {
protectedBy = "Delete Objects"; protectedBy = "Delete Objects";
pageName = "UIxCalMainView"; pageName = "UIxCalMainView";
actionName = "batchDelete"; actionName = "batchDelete";
}; };
updateCalendars = {
show = {
protectedBy = "View"; protectedBy = "View";
pageName = "UIxCalView";
actionName = "redirectForUIDs";
};
batchDelete = {
protectedBy = "Delete Objects";
pageName = "UIxCalMainView"; pageName = "UIxCalMainView";
actionName = "updateCalendars"; actionName = "batchDelete";
}; };
editAttendees = { editAttendees = {
protectedBy = "View"; protectedBy = "View";
@ -119,6 +139,7 @@
}; };
}; };
}; };
SOGoCalendarComponent = { SOGoCalendarComponent = {
}; };
@ -158,6 +179,10 @@
pageName = "UIxAppointmentEditor"; pageName = "UIxAppointmentEditor";
actionName = "decline"; actionName = "decline";
}; };
editAttendees = {
protectedBy = "View";
pageName = "UIxAttendeesEditor";
};
}; };
}; };

View file

@ -62,13 +62,10 @@
<ul id="contactFolders"> <ul id="contactFolders">
<var:foreach list="contactFolders" item="currentFolder" <var:foreach list="contactFolders" item="currentFolder"
><li var:id="currentContactFolderId" ><li var:id="currentContactFolderId"
><var:string value="currentContactFolderName" /></li var:owner="currentContactFolderOwner"
><var:string value="currentContactFolderName" /></li
></var:foreach ></var:foreach
><var:foreach list="additionalFolders" >
item="currentAdditionalFolder"
><li var:id="currentAdditionalFolder" class="denied"
><var:string value="currentAdditionalFolderName" /></li
></var:foreach>
</ul> </ul>
<var:if condition="hasContactSelectionButtons"> <var:if condition="hasContactSelectionButtons">

View file

@ -9,6 +9,9 @@
className="UIxPageFrame" className="UIxPageFrame"
title="title" title="title"
> >
<script type="text/javascript">
var UTCOffset = <var:string value="userUTCOffset"/>;
</script>
<div class="preload" style="visibility: hidden;"> <div class="preload" style="visibility: hidden;">
<img rsrc:src="event-gradient.png"/> <img rsrc:src="event-gradient.png"/>
</div> </div>

View file

@ -7,30 +7,34 @@
xmlns:rsrc="OGo:url" xmlns:rsrc="OGo:url"
xmlns:label="OGo:label"> xmlns:label="OGo:label">
<style type="text/css"> <style type="text/css">
<var:foreach list="calendarFolders" item="currentCalendarFolder"> <var:foreach list="calendars" item="currentCalendar">
.ownerIs<var:string value="currentCalendarLogin" /> .calendarFolder<var:string value="currentCalendar.folder" />
{ background-color: <var:string value="currentCalendarSpanBG" /> !important; } { background-color: <var:string value="currentCalendar.color" /> !important; }
</var:foreach> </var:foreach>
</style> </style>
<div id="calendarSelector"> <div id="calendarSelector">
<span id="calendarSelectorButtons"> <span id="calendarSelectorButtons">
<a href="#" class="toolbarButton" <a href="#" class="toolbarButton"
><span class="toolbarButton"><img rsrc:src="add-calendar.png" ><span class="toolbarButton"><img rsrc:src="add-calendar.png"
label:title="Add..." label:title="New Calendar..."
/></span></a>
<a href="#" class="toolbarButton"
><span class="toolbarButton"><img rsrc:src="add-user-calendar.png"
label:title="Subscribe to a Calendar..."
/></span></a> /></span></a>
<a href="#" class="toolbarButton" <a href="#" class="toolbarButton"
><span class="toolbarButton"><img rsrc:src="remove-calendar.png" ><span class="toolbarButton"><img rsrc:src="remove-calendar.png"
label:title="Remove" label:title="Remove the selected Calendar"
/></span></a> /></span></a>
</span> </span>
<ul id="calendarList" multiselect="yes"> <ul id="calendarList" multiselect="yes">
<var:foreach list="calendarFolders" item="currentCalendarFolder" <var:foreach list="calendars" item="currentCalendar"
><li class="denied" var:id="currentCalendarFolder.folder"> ><li class="denied" var:id="currentCalendar.id">
<input type="checkbox" class="checkBox" <input type="checkbox" class="checkBox"
const:disabled="disabled" const:disabled="disabled"
var:checked="currentCalendarFolder.active" /> var:checked="currentCalendar.active" />
<div class="colorBox" var:style="currentCalendarStyle">OO</div> <div class="colorBox" var:style="currentCalendarStyle">OO</div>
<var:string value="currentCalendarFolder.displayName" <var:string value="currentCalendar.displayName"
/></li> /></li>
</var:foreach> </var:foreach>
</ul> </ul>

View file

@ -5,7 +5,7 @@
xmlns:var="http://www.skyrix.com/od/binding" xmlns:var="http://www.skyrix.com/od/binding"
xmlns:const="http://www.skyrix.com/od/constant" xmlns:const="http://www.skyrix.com/od/constant"
xmlns:rsrc="OGo:url" xmlns:rsrc="OGo:url"
xmlns:label="OGo:label" xmlns:label="OGo:label"
><var:string var:value="doctype" const:escapeHTML="NO" /> ><var:string var:value="doctype" const:escapeHTML="NO" />
<var:if condition="hideFrame" const:negate="YES" <var:if condition="hideFrame" const:negate="YES"
><html> ><html>

View file

@ -19,8 +19,8 @@ function validateEditorInput(sender) {
errortext = errortext + labels.error_missingrecipients + "\n"; errortext = errortext + labels.error_missingrecipients + "\n";
if (errortext.length > 0) { if (errortext.length > 0) {
alert(labels.error_validationfailed.decodeEntities() + ":\n" alert(labels.error_validationfailed + ":\n"
+ errortext.decodeEntities()); + errortext);
return false; return false;
} }
return true; return true;
@ -497,28 +497,24 @@ function refreshContacts(contactId) {
} }
function onAddressBookNew(event) { function onAddressBookNew(event) {
var name = window.prompt(labels["Name of the Address Book"].decodeEntities()); createFolder(window.prompt(labels["Name of the Address Book"]),
if (name) { appendAddressBook);
if (document.newAbAjaxRequest) {
document.newAbAjaxRequest.aborted = true;
document.newAbAjaxRequest.abort();
}
var url = ApplicationBaseURL + "/newAb?name=" + name;
document.newAbAjaxRequest
= triggerAjaxRequest(url, newAbCallback, name);
}
preventDefault(event); preventDefault(event);
} }
function appendAddressBook(name, folder) { function appendAddressBook(name, folder) {
var li = document.createElement("li"); if (folder)
$("contactFolders").appendChild(li); folder = accessToSubscribedFolder(folder);
li.setAttribute("id", folder); else
li.appendChild(document.createTextNode(name)); folder = "/" + name;
setEventsOnContactFolder(li); var li = document.createElement("li");
$("contactFolders").appendChild(li);
li.setAttribute("id", folder);
li.appendChild(document.createTextNode(name));
setEventsOnContactFolder(li);
} }
function newAbCallback(http) { function newFolderCallback(http) {
if (http.readyState == 4 if (http.readyState == 4
&& http.status == 201) { && http.status == 201) {
var name = http.callbackData; var name = http.callbackData;
@ -552,60 +548,60 @@ function onAddressBookRemove(event) {
var selector = $("contactFolders"); var selector = $("contactFolders");
var nodes = selector.getSelectedNodes(); var nodes = selector.getSelectedNodes();
if (nodes.length > 0) { if (nodes.length > 0) {
nodes[0].deselect(); nodes[0].deselect();
var folderId = nodes[0].getAttribute("id"); var folderId = nodes[0].getAttribute("id");
var folderIdElements = folderId.split(":"); var folderIdElements = folderId.split("_");
if (folderIdElements.length > 1) if (folderIdElements.length > 1)
unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId); unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId);
else { else {
var abId = folderIdElements[0].substr(1); var abId = folderIdElements[0].substr(1);
deletePersonalAddressBook(abId); deletePersonalAddressBook(abId);
var personal = $("/personal"); var personal = $("/personal");
personal.select(); personal.select();
onFolderSelectionChange(); onFolderSelectionChange();
} }
} }
preventDefault(event); preventDefault(event);
} }
function deletePersonalAddressBook(folderId) { function deletePersonalAddressBook(folderId) {
var label var label
= labels["Are you sure you want to delete the selected address book?"]; = labels["Are you sure you want to delete the selected address book?"];
if (window.confirm(label.decodeEntities())) { if (window.confirm(label)) {
if (document.deletePersonalABAjaxRequest) { if (document.deletePersonalABAjaxRequest) {
document.deletePersonalABAjaxRequest.aborted = true; document.deletePersonalABAjaxRequest.aborted = true;
document.deletePersonalABAjaxRequest.abort(); document.deletePersonalABAjaxRequest.abort();
} }
var url = ApplicationBaseURL + "/" + folderId + "/delete"; var url = ApplicationBaseURL + "/" + folderId + "/deleteFolder";
document.deletePersonalABAjaxRequest document.deletePersonalABAjaxRequest
= triggerAjaxRequest(url, deletePersonalAddressBookCallback, = triggerAjaxRequest(url, deletePersonalAddressBookCallback,
folderId); folderId);
} }
} }
function deletePersonalAddressBookCallback(http) { function deletePersonalAddressBookCallback(http) {
if (http.readyState == 4) { if (http.readyState == 4) {
if (http.status == 200) { if (isHttpStatus204(http.status)) {
var ul = $("contactFolders"); var ul = $("contactFolders");
var children = ul.childNodesWithTag("li"); var children = ul.childNodesWithTag("li");
var i = 0; var i = 0;
var done = false; var done = false;
while (!done && i < children.length) { while (!done && i < children.length) {
var currentFolderId = children[i].getAttribute("id").substr(1); var currentFolderId = children[i].getAttribute("id").substr(1);
if (currentFolderId == http.callbackData) { if (currentFolderId == http.callbackData) {
ul.removeChild(children[i]); ul.removeChild(children[i]);
done = true; done = true;
}
else
i++;
} }
} else
document.deletePersonalABAjaxRequest = null; i++;
}
}
document.deletePersonalABAjaxRequest = null;
} }
else else
log ("ajax problem 5: " + http.status); log ("ajax problem 5: " + http.status);
} }
function configureDragHandles() { function configureDragHandles() {
@ -677,6 +673,34 @@ function setEventsOnContactFolder(node) {
onContactFoldersContextMenu.bindAsEventListener(node), false); onContactFoldersContextMenu.bindAsEventListener(node), false);
} }
function onMenuModify(event) {
var folders = $("contactFolders");
var selected = folders.getSelectedNodes()[0];
if (UserLogin == selected.getAttribute("owner")) {
var currentName = selected.innerHTML;
var newName = window.prompt(labels["Address Book Name"],
currentName);
if (newName && newName.length > 0
&& newName != currentName) {
var url = (URLForFolderID(selected.getAttribute("id"))
+ "/renameFolder?name=" + escape(newName.utf8encode()));
triggerAjaxRequest(url, folderRenameCallback,
{node: selected, name: newName});
}
} else
window.alert(clabels["Unable to rename that folder!"]);
}
function folderRenameCallback(http) {
if (http.readyState == 4) {
if (isHttpStatus204(http.status)) {
var dict = http.callbackData;
dict["node"].innerHTML = dict["name"];
}
}
}
function onMenuSharing(event) { function onMenuSharing(event) {
var folders = $("contactFolders"); var folders = $("contactFolders");
var selected = folders.getSelectedNodes()[0]; var selected = folders.getSelectedNodes()[0];
@ -688,7 +712,7 @@ function onMenuSharing(event) {
function getMenus() { function getMenus() {
var menus = {}; var menus = {};
menus["contactFoldersMenu"] = new Array(null, "-", null, menus["contactFoldersMenu"] = new Array(onMenuModify, "-", null,
null, "-", null, "-", null, "-", null, "-",
onMenuSharing); onMenuSharing);
menus["contactMenu"] = new Array(onMenuEditContact, "-", menus["contactMenu"] = new Array(onMenuEditContact, "-",

View file

@ -207,7 +207,7 @@ function ctxFolderAdd(sender) {
} }
function ctxFolderDelete(sender) { function ctxFolderDelete(sender) {
if (!confirm("Delete current folder?").decodeEntities()) if (!confirm("Delete current folder?"))
return false; return false;
// TODO: should use a form-POST or AJAX // TODO: should use a form-POST or AJAX
@ -306,10 +306,10 @@ function onMenuDeleteMessage(event) {
function onPrintCurrentMessage(event) { function onPrintCurrentMessage(event) {
var rowIds = $("messageList").getSelectedRowsId(); var rowIds = $("messageList").getSelectedRowsId();
if (rowIds.length == 0) { if (rowIds.length == 0) {
window.alert(labels["Please select a message to print."].decodeEntities()); window.alert(labels["Please select a message to print."]);
} }
else if (rowIds.length > 1) { else if (rowIds.length > 1) {
window.alert(labels["Please select only one message to print."].decodeEntities()); window.alert(labels["Please select only one message to print."]);
} }
else else
window.print(); window.print();
@ -492,7 +492,7 @@ function quotasCallback(http) {
var used = mbQuotas["usedSpace"]; var used = mbQuotas["usedSpace"];
var max = mbQuotas["maxQuota"]; var max = mbQuotas["maxQuota"];
var percents = (Math.round(used * 10000 / max) / 100); var percents = (Math.round(used * 10000 / max) / 100);
var format = labels["quotasFormat"].decodeEntities(); var format = labels["quotasFormat"];
var text = format.formatted(used, max, percents); var text = format.formatted(used, max, percents);
window.status = text; window.status = text;
} }
@ -1265,7 +1265,7 @@ function buildMailboxes(accountName, encoded) {
} }
function onMenuCreateFolder(event) { function onMenuCreateFolder(event) {
var name = window.prompt(labels["Name :"].decodeEntities(), ""); var name = window.prompt(labels["Name :"], "");
if (name && name.length > 0) { if (name && name.length > 0) {
var folderID = document.menuTarget.getAttribute("dataname"); var folderID = document.menuTarget.getAttribute("dataname");
var urlstr = URLForFolderID(folderID) + "/createFolder?name=" + name; var urlstr = URLForFolderID(folderID) + "/createFolder?name=" + name;
@ -1275,7 +1275,7 @@ function onMenuCreateFolder(event) {
function onMenuRenameFolder(event) { function onMenuRenameFolder(event) {
var name = window.prompt(labels["Enter the new name of your folder :"] var name = window.prompt(labels["Enter the new name of your folder :"]
.decodeEntities(), ,
""); "");
if (name && name.length > 0) { if (name && name.length > 0) {
var folderID = document.menuTarget.getAttribute("dataname"); var folderID = document.menuTarget.getAttribute("dataname");
@ -1285,7 +1285,7 @@ function onMenuRenameFolder(event) {
} }
function onMenuDeleteFolder(event) { function onMenuDeleteFolder(event) {
var answer = window.confirm(labels["Do you really want to move this folder into the trash ?"].decodeEntities()); var answer = window.confirm(labels["Do you really want to move this folder into the trash ?"]);
if (answer) { if (answer) {
var folderID = document.menuTarget.getAttribute("dataname"); var folderID = document.menuTarget.getAttribute("dataname");
var urlstr = URLForFolderID(folderID) + "/deleteFolder"; var urlstr = URLForFolderID(folderID) + "/deleteFolder";
@ -1320,7 +1320,7 @@ function folderOperationCallback(http) {
&& http.status == 204) && http.status == 204)
initMailboxTree(); initMailboxTree();
else else
window.alert(labels["Operation failed"].decodeEntities()); window.alert(labels["Operation failed"]);
} }
function folderRefreshCallback(http) { function folderRefreshCallback(http) {
@ -1331,7 +1331,7 @@ function folderRefreshCallback(http) {
refreshCurrentFolder(); refreshCurrentFolder();
} }
else else
window.alert(labels["Operation failed"].decodeEntities()); window.alert(labels["Operation failed"]);
} }
function getMenus() { function getMenus() {

View file

@ -12,10 +12,10 @@ DIV#loginScreen
background-color: #d4d0c8; background-color: #d4d0c8;
margin: 0px auto; margin: 0px auto;
margin-top: 5em; margin-top: 5em;
padding: 10px; padding: 5px;
border: 2px solid transparent; border: 2px solid transparent;
width: 197px; width: 200px;
height: 300px; height: 315px;
-moz-border-top-colors: #efebe7 #fff; -moz-border-top-colors: #efebe7 #fff;
-moz-border-left-colors: #efebe7 #fff; -moz-border-left-colors: #efebe7 #fff;
-moz-border-right-colors: #000 #9c9a94 transparent; -moz-border-right-colors: #000 #9c9a94 transparent;
@ -26,8 +26,8 @@ DIV#loginScreen IMG
{ border: 0px; { border: 0px;
margin: 0px; margin: 0px;
padding: 0px; padding: 0px;
height: 192px; height: 200px;
width: 192px; } width: 200px; }
DIV#loginScreen INPUT.textField DIV#loginScreen INPUT.textField
{ width: 187px; } { width: 187px; }

View file

@ -17,7 +17,7 @@ var cachedDateSelectors = new Array();
var contactSelectorAction = 'calendars-contacts'; var contactSelectorAction = 'calendars-contacts';
var eventsToDelete = new Array(); var eventsToDelete = new Array();
var ownersOfEventsToDelete = new Array(); var calendarsOfEventsToDelete = new Array();
var usersRightsWindowHeight = 250; var usersRightsWindowHeight = 250;
var usersRightsWindowWidth = 502; var usersRightsWindowWidth = 502;
@ -27,15 +27,11 @@ function newEvent(sender, type) {
if (!day) if (!day)
day = currentDay; day = currentDay;
var user = UserLogin;
if (sender.parentNode.getAttribute("id") != "toolbar"
&& currentView == "multicolumndayview" && type == "event")
user = sender.parentNode.parentNode.getAttribute("user");
var hour = sender.hour; var hour = sender.hour;
if (!hour) if (!hour)
hour = sender.getAttribute("hour"); hour = sender.getAttribute("hour");
var urlstr = UserFolderURL + "../" + user + "/Calendar/new" + type; var folderID = getSelectedFolder();
var urlstr = ApplicationBaseURL + folderID + "/new" + type;
var params = new Array(); var params = new Array();
if (day) if (day)
params.push("day=" + day); params.push("day=" + day);
@ -49,6 +45,18 @@ function newEvent(sender, type) {
return false; /* stop following the link */ return false; /* stop following the link */
} }
function getSelectedFolder() {
var folder;
var nodes = $("calendarList").getSelectedRows();
if (nodes.length > 0)
folder = nodes[0].getAttribute("id");
else
folder = "/personal";
return folder;
}
function onMenuNewEventClick(event) { function onMenuNewEventClick(event) {
newEvent(this, "event"); newEvent(this, "event");
} }
@ -57,13 +65,8 @@ function onMenuNewTaskClick(event) {
newEvent(this, "task"); newEvent(this, "task");
} }
function _editEventId(id, owner) { function _editEventId(id, calendar) {
var urlBase; var urlstr = ApplicationBaseURL + "/" + calendar + "/" + id + "/edit";
if (owner)
urlBase = UserFolderURL + "../" + owner + "/";
urlBase += "Calendar/"
var urlstr = urlBase + id + "/edit";
var targetname = "SOGo_edit_" + id; var targetname = "SOGo_edit_" + id;
var win = window.open(urlstr, "_blank", var win = window.open(urlstr, "_blank",
"width=490,height=470,resizable=0"); "width=490,height=470,resizable=0");
@ -76,10 +79,10 @@ function editEvent() {
for (var i = 0; i < nodes.length; i++) for (var i = 0; i < nodes.length; i++)
_editEventId(nodes[i].getAttribute("id"), _editEventId(nodes[i].getAttribute("id"),
nodes[i].owner); nodes[i].calendar);
} else if (selectedCalendarCell) { } else if (selectedCalendarCell) {
_editEventId(selectedCalendarCell[0].cname, _editEventId(selectedCalendarCell[0].cname,
selectedCalendarCell[0].owner); selectedCalendarCell[0].calendar);
} }
return false; /* stop following the link */ return false; /* stop following the link */
@ -87,9 +90,9 @@ function editEvent() {
function _batchDeleteEvents() { function _batchDeleteEvents() {
var events = eventsToDelete.shift(); var events = eventsToDelete.shift();
var owner = ownersOfEventsToDelete.shift(); var calendar = calendarsOfEventsToDelete.shift();
var urlstr = (UserFolderURL + "../" + owner + "/Calendar/batchDelete?ids=" var urlstr = (ApplicationBaseURL + "/" + calendar
+ events.join('/')); + "/batchDelete?ids=" + events.join('/'));
document.deleteEventAjaxRequest = triggerAjaxRequest(urlstr, document.deleteEventAjaxRequest = triggerAjaxRequest(urlstr,
deleteEventCallback, deleteEventCallback,
events); events);
@ -102,9 +105,9 @@ function deleteEvent() {
if (nodes.length > 0) { if (nodes.length > 0) {
var label = ""; var label = "";
if (listOfSelection == $("tasksList")) if (listOfSelection == $("tasksList"))
label = labels["taskDeleteConfirmation"].decodeEntities(); label = labels["taskDeleteConfirmation"];
else else
label = labels["eventDeleteConfirmation"].decodeEntities(); label = labels["eventDeleteConfirmation"];
if (confirm(label)) { if (confirm(label)) {
if (document.deleteEventAjaxRequest) { if (document.deleteEventAjaxRequest) {
@ -112,33 +115,33 @@ function deleteEvent() {
document.deleteEventAjaxRequest.abort(); document.deleteEventAjaxRequest.abort();
} }
var sortedNodes = new Array(); var sortedNodes = new Array();
var owners = new Array(); var calendars = new Array();
for (var i = 0; i < nodes.length; i++) { for (var i = 0; i < nodes.length; i++) {
var owner = nodes[i].owner; var calendar = nodes[i].calendar;
if (!sortedNodes[owner]) { if (!sortedNodes[calendar]) {
sortedNodes[owner] = new Array(); sortedNodes[calendar] = new Array();
owners.push(owner); calendars.push(calendar);
} }
sortedNodes[owner].push(nodes[i].cname); sortedNodes[calendar].push(nodes[i].cname);
} }
for (var i = 0; i < owners.length; i++) { for (var i = 0; i < calendars.length; i++) {
ownersOfEventsToDelete.push(owners[i]); calendarsOfEventsToDelete.push(calendars[i]);
eventsToDelete.push(sortedNodes[owners[i]]); eventsToDelete.push(sortedNodes[calendars[i]]);
} }
_batchDeleteEvents(); _batchDeleteEvents();
} }
} }
} }
else if (selectedCalendarCell) { else if (selectedCalendarCell) {
var label = labels["eventDeleteConfirmation"].decodeEntities(); var label = labels["eventDeleteConfirmation"];
if (confirm(label)) { if (confirm(label)) {
if (document.deleteEventAjaxRequest) { if (document.deleteEventAjaxRequest) {
document.deleteEventAjaxRequest.aborted = true; document.deleteEventAjaxRequest.aborted = true;
document.deleteEventAjaxRequest.abort(); document.deleteEventAjaxRequest.abort();
} }
eventsToDelete.push([selectedCalendarCell[0].cname]); eventsToDelete.push([selectedCalendarCell[0].cname]);
ownersOfEventsToDelete.push(selectedCalendarCell[0].owner); calendarsOfEventsToDelete.push(selectedCalendarCell[0].calendar);
_batchDeleteEvents(); _batchDeleteEvents();
} }
} }
@ -168,7 +171,7 @@ function closeInvitationWindow() {
closePseudoWin.style.top = "0px;"; closePseudoWin.style.top = "0px;";
closePseudoWin.style.left = "0px;"; closePseudoWin.style.left = "0px;";
closePseudoWin.style.right = "0px;"; closePseudoWin.style.right = "0px;";
closePseudoWin.appendChild(document.createTextNode(labels["closeThisWindowMessage"].decodeEntities())); closePseudoWin.appendChild(document.createTextNode(labels["closeThisWindowMessage"]));
document.body.appendChild(closeDiv); document.body.appendChild(closeDiv);
document.body.appendChild(closePseudoWin); document.body.appendChild(closePseudoWin);
} }
@ -215,7 +218,7 @@ function deleteEventCallback(http) {
} }
function editDoubleClickedEvent(event) { function editDoubleClickedEvent(event) {
_editEventId(this.cname, this.owner); _editEventId(this.cname, this.calendar);
preventDefault(event); preventDefault(event);
event.cancelBubble = true; event.cancelBubble = true;
@ -316,7 +319,7 @@ function eventsListCallback(http) {
$(row).addClassName("eventRow"); $(row).addClassName("eventRow");
row.setAttribute("id", escape(data[i][0])); row.setAttribute("id", escape(data[i][0]));
row.cname = escape(data[i][0]); row.cname = escape(data[i][0]);
row.owner = data[i][1]; row.calendar = data[i][1];
var startDate = new Date(); var startDate = new Date();
startDate.setTime(data[i][4] * 1000); startDate.setTime(data[i][4] * 1000);
@ -372,9 +375,8 @@ function tasksListCallback(http) {
Event.observe(listItem, "dblclick", editDoubleClickedEvent.bindAsEventListener(listItem)); Event.observe(listItem, "dblclick", editDoubleClickedEvent.bindAsEventListener(listItem));
listItem.setAttribute("id", data[i][0]); listItem.setAttribute("id", data[i][0]);
$(listItem).addClassName(data[i][5]); $(listItem).addClassName(data[i][5]);
var owner = data[i][1]; listItem.calendar = data[i][1];
listItem.owner = owner; $(listItem).addClassName("calendarFolder" + data[i][1]);
$(listItem).addClassName("ownerIs" + owner.cssSafeString());
listItem.cname = escape(data[i][0]); listItem.cname = escape(data[i][0]);
var input = document.createElement("input"); var input = document.createElement("input");
input.setAttribute("type", "checkbox"); input.setAttribute("type", "checkbox");
@ -429,7 +431,7 @@ function restoreCurrentDaySelection(div) {
} }
function changeDateSelectorDisplay(day, keepCurrentDay) { function changeDateSelectorDisplay(day, keepCurrentDay) {
var url = ApplicationBaseURL + "dateselector"; var url = ApplicationBaseURL + "/dateselector";
if (day) if (day)
url += "?day=" + day; url += "?day=" + day;
@ -457,7 +459,7 @@ function changeDateSelectorDisplay(day, keepCurrentDay) {
} }
function changeCalendarDisplay(time, newView) { function changeCalendarDisplay(time, newView) {
var url = ApplicationBaseURL + ((newView) ? newView : currentView); var url = ApplicationBaseURL + "/" + ((newView) ? newView : currentView);
selectedCalendarCell = null; selectedCalendarCell = null;
@ -583,7 +585,7 @@ function refreshCalendarEvents() {
document.refreshCalendarEventsAjaxRequest.aborted = true; document.refreshCalendarEventsAjaxRequest.aborted = true;
document.refreshCalendarEventsAjaxRequest.abort(); document.refreshCalendarEventsAjaxRequest.abort();
} }
var url = ApplicationBaseURL + "eventslist?sd=" + sd + "&ed=" + ed; var url = ApplicationBaseURL + "/eventslist?sd=" + sd + "&ed=" + ed;
document.refreshCalendarEventsAjaxRequest document.refreshCalendarEventsAjaxRequest
= triggerAjaxRequest(url, refreshCalendarEventsCallback, = triggerAjaxRequest(url, refreshCalendarEventsCallback,
{"startDate": sd, "endDate": ed}); {"startDate": sd, "endDate": ed});
@ -608,9 +610,9 @@ function drawCalendarEvent(eventData, sd, ed) {
var viewEndDate = ed.asDate(); var viewEndDate = ed.asDate();
var startDate = new Date(); var startDate = new Date();
startDate.setTime(eventData[4] * 1000); startDate.setTime(eventData[4] * 1000 + (1000 * UTCOffset));
var endDate = new Date(); var endDate = new Date();
endDate.setTime(eventData[5] * 1000); endDate.setTime(eventData[5] * 1000 + (1000 * UTCOffset));
var days = startDate.daysUpTo(endDate); var days = startDate.daysUpTo(endDate);
@ -636,8 +638,8 @@ function drawCalendarEvent(eventData, sd, ed) {
// log("day: " + days[i]); // log("day: " + days[i]);
if (i == 0) { if (i == 0) {
var quarters = (startDate.getHours() * 4 var quarters = (startDate.getUTCHours() * 4
+ Math.floor(startDate.getMinutes() / 15)); + Math.floor(startDate.getUTCMinutes() / 15));
starts = quarters; starts = quarters;
startHour = startDate.getDisplayHoursString(); startHour = startDate.getDisplayHoursString();
endHour = endDate.getDisplayHoursString(); endHour = endDate.getDisplayHoursString();
@ -648,8 +650,8 @@ function drawCalendarEvent(eventData, sd, ed) {
var ends; var ends;
var lasts; var lasts;
if (i == days.length - 1) { if (i == days.length - 1) {
var quarters = (endDate.getHours() * 4 var quarters = (endDate.getUTCHours() * 4
+ Math.ceil(endDate.getMinutes() / 15)); + Math.ceil(endDate.getUTCMinutes() / 15));
ends = quarters; ends = quarters;
} }
else else
@ -706,11 +708,11 @@ function drawCalendarEvent(eventData, sd, ed) {
} }
} }
function newEventDIV(cname, owner, starts, lasts, function newEventDIV(cname, calendar, starts, lasts,
startHour, endHour, title) { startHour, endHour, title) {
var eventDiv = document.createElement("div"); var eventDiv = document.createElement("div");
eventDiv.cname = escape(cname); eventDiv.cname = escape(cname);
eventDiv.owner = owner; eventDiv.calendar = calendar;
$(eventDiv).addClassName("event"); $(eventDiv).addClassName("event");
$(eventDiv).addClassName("starts" + starts); $(eventDiv).addClassName("starts" + starts);
$(eventDiv).addClassName("lasts" + lasts); $(eventDiv).addClassName("lasts" + lasts);
@ -723,7 +725,7 @@ function newEventDIV(cname, owner, starts, lasts,
var innerDiv = document.createElement("div"); var innerDiv = document.createElement("div");
eventDiv.appendChild(innerDiv); eventDiv.appendChild(innerDiv);
$(innerDiv).addClassName("eventInside"); $(innerDiv).addClassName("eventInside");
$(innerDiv).addClassName("ownerIs" + owner.cssSafeString()); $(innerDiv).addClassName("calendarFolder" + calendar);
var gradientDiv = document.createElement("div"); var gradientDiv = document.createElement("div");
innerDiv.appendChild(gradientDiv); innerDiv.appendChild(gradientDiv);
@ -881,7 +883,7 @@ function _loadEventHref(href) {
document.eventsListAjaxRequest.aborted = true; document.eventsListAjaxRequest.aborted = true;
document.eventsListAjaxRequest.abort(); document.eventsListAjaxRequest.abort();
} }
var url = ApplicationBaseURL + href; var url = ApplicationBaseURL + "/" + href;
document.eventsListAjaxRequest document.eventsListAjaxRequest
= triggerAjaxRequest(url, eventsListCallback, href); = triggerAjaxRequest(url, eventsListCallback, href);
@ -897,7 +899,7 @@ function _loadTasksHref(href) {
document.tasksListAjaxRequest.aborted = true; document.tasksListAjaxRequest.aborted = true;
document.tasksListAjaxRequest.abort(); document.tasksListAjaxRequest.abort();
} }
url = ApplicationBaseURL + href; url = ApplicationBaseURL + "/" + href;
var tasksList = $("tasksList"); var tasksList = $("tasksList");
var selectedIds; var selectedIds;
@ -1119,7 +1121,6 @@ function onShowCompletedTasks(event) {
function updateTaskStatus(event) { function updateTaskStatus(event) {
var taskId = this.parentNode.getAttribute("id"); var taskId = this.parentNode.getAttribute("id");
var taskOwner = this.parentNode.owner;
var newStatus = (this.checked ? 1 : 0); var newStatus = (this.checked ? 1 : 0);
var http = createHTTPClient(); var http = createHTTPClient();
@ -1128,9 +1129,8 @@ function updateTaskStatus(event) {
//log("update task status: " + taskId + " to " + this.checked); //log("update task status: " + taskId + " to " + this.checked);
event.cancelBubble = true; event.cancelBubble = true;
url = (UserFolderURL + "../" + taskOwner url = (ApplicationBaseURL + "/" + this.parentNode.calendar
+ "/Calendar/" + taskId + "/" + taskId + "/changeStatus?status=" + newStatus);
+ "/changeStatus?status=" + newStatus);
if (http) { if (http) {
// log ("url: " + url); // log ("url: " + url);
@ -1162,10 +1162,11 @@ function updateCalendarStatus(event) {
} }
} }
if (!list.length) { // if (!list.length) {
list.push(UserLogin); // list.push(UserLogin);
nodes[0].childNodesWithTag("input")[0].checked = true; // nodes[0].childNodesWithTag("input")[0].checked = true;
} // }
// ApplicationBaseURL = (UserFolderURL + "Groups/_custom_" // ApplicationBaseURL = (UserFolderURL + "Groups/_custom_"
// + list.join(",") + "/Calendar/"); // + list.join(",") + "/Calendar/");
@ -1207,7 +1208,7 @@ function calendarStatusCallback(http) {
} }
function calendarEntryCallback(http) { function calendarEntryCallback(http) {
if (http.readyState == 4) { if (http.readyState == 4) {
var denied = !isHttpStatus204(http.status); var denied = !isHttpStatus204(http.status);
var entry = $(http.callbackData); var entry = $(http.callbackData);
if (denied) if (denied)
@ -1339,79 +1340,94 @@ function initCalendarSelector() {
} }
var links = $("calendarSelectorButtons").childNodesWithTag("a"); var links = $("calendarSelectorButtons").childNodesWithTag("a");
Event.observe(links[0], "click", onCalendarAdd); Event.observe(links[0], "click", onCalendarNew);
Event.observe(links[1], "click", onCalendarRemove); Event.observe(links[1], "click", onCalendarAdd);
Event.observe(links[2], "click", onCalendarRemove);
}
function onCalendarNew(event) {
createFolder(window.prompt(labels["Name of the Calendar"]),
appendCalendar);
preventDefault(event);
} }
function onCalendarAdd(event) { function onCalendarAdd(event) {
openUserFolderSelector(onFolderSubscribeCB, "calendar"); openUserFolderSelector(onFolderSubscribeCB, "calendar");
preventDefault(event);
preventDefault(event);
} }
function appendCalendar(folderName, folder) { function appendCalendar(folderName, folder) {
var calendarList = $("calendarList"); if (folder)
var lis = calendarList.childNodesWithTag("li"); folder = accessToSubscribedFolder(folder);
var color = indexColor(lis.length); else
//log ("color: " + color); folder = "/" + folderName;
var li = document.createElement("li"); // log ("append: " + folderName + "; folder: " + folder);
calendarList.appendChild(li);
var checkBox = document.createElement("input"); var calendarList = $("calendarList");
checkBox.setAttribute("type", "checkbox"); var lis = calendarList.childNodesWithTag("li");
li.appendChild(checkBox); var color = indexColor(lis.length + 100);
//log ("color: " + color);
var li = document.createElement("li");
calendarList.appendChild(li);
var checkBox = document.createElement("input");
checkBox.setAttribute("type", "checkbox");
li.appendChild(checkBox);
li.appendChild(document.createTextNode(" ")); li.appendChild(document.createTextNode(" "));
var colorBox = document.createElement("div"); var colorBox = document.createElement("div");
li.appendChild(colorBox); li.appendChild(colorBox);
li.appendChild(document.createTextNode(" " + folderName)); li.appendChild(document.createTextNode(" " + folderName));
colorBox.appendChild(document.createTextNode("OO")); colorBox.appendChild(document.createTextNode("OO"));
li.setAttribute("id", folder); li.setAttribute("id", folder);
Event.observe(li, "mousedown", listRowMouseDownHandler); Event.observe(li, "mousedown", listRowMouseDownHandler);
Event.observe(li, "click", onRowClick); Event.observe(li, "click", onRowClick);
$(checkBox).addClassName("checkBox"); $(checkBox).addClassName("checkBox");
Event.observe(checkBox, "click", updateCalendarStatus.bindAsEventListener(checkBox)); Event.observe(checkBox, "click",
updateCalendarStatus.bindAsEventListener(checkBox));
$(colorBox).addClassName("colorBox"); $(colorBox).addClassName("colorBox");
if (color) { if (color)
$(colorBox).setStyle({ color: color, $(colorBox).setStyle({color: color,
backgroundColor: color }); backgroundColor: color});
}
var contactId = folder.split(":")[0]; var url = URLForFolderID(folder) + "/canAccessContent";
var url = URLForFolderID(folder) + "/canAccessContent"; triggerAjaxRequest(url, calendarEntryCallback, folder);
triggerAjaxRequest(url, calendarEntryCallback, folder);
if (!document.styleSheets) return; if (!document.styleSheets) return;
var theRules = new Array(); var theRules = new Array();
var lastSheet = document.styleSheets[document.styleSheets.length - 1]; var lastSheet = document.styleSheets[document.styleSheets.length - 1];
if (lastSheet.insertRule) { // Mozilla if (lastSheet.insertRule) { // Mozilla
lastSheet.insertRule('.ownerIs' + contactId.cssSafeString() + ' {' lastSheet.insertRule('.calendarFolder' + folder.substr(1) + ' {'
+ ' background-color: ' + ' background-color: '
+ color + color
+ ' !important; }', 0); + ' !important; }', 0);
} }
else { // IE else { // IE
lastSheet.addRule('.ownerIs' + contactId.cssSafeString(), lastSheet.addRule('.calendarFolder' + folder.substr(1),
' background-color: ' ' background-color: '
+ color + color
+ ' !important; }'); + ' !important; }');
} }
} }
function onFolderSubscribeCB(folderData) { function onFolderSubscribeCB(folderData) {
var folder = $(folderData["folder"]); var folder = $(folderData["folder"]);
if (!folder) if (!folder)
appendCalendar(folderData["folderName"], folderData["folder"]); appendCalendar(folderData["folderName"], folderData["folder"]);
} }
function onFolderUnsubscribeCB(folderId) { function onFolderUnsubscribeCB(folderId) {
var node = $(folderId); var node = $(folderId);
node.parentNode.removeChild(node); node.parentNode.removeChild(node);
refreshEvents();
refreshTasks();
changeCalendarDisplay();
} }
function onCalendarRemove(event) { function onCalendarRemove(event) {
@ -1419,15 +1435,59 @@ function onCalendarRemove(event) {
if (nodes.length > 0) { if (nodes.length > 0) {
nodes[0].deselect(); nodes[0].deselect();
var folderId = nodes[0].getAttribute("id"); var folderId = nodes[0].getAttribute("id");
var folderIdElements = folderId.split(":"); var folderIdElements = folderId.split("_");
if (folderIdElements.length > 1) { if (folderIdElements.length > 1) {
unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId); unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId);
}
else {
var calId = folderIdElements[0].substr(1);
deletePersonalCalendar(calId);
} }
} }
preventDefault(event); preventDefault(event);
} }
function deletePersonalCalendar(folderId) {
var label
= labels["Are you sure you want to delete the selected calendar?"];
if (window.confirm(label)) {
if (document.deletePersonalCalendarAjaxRequest) {
document.deletePersonalCalendarAjaxRequest.aborted = true;
document.deletePersonalCalendarAjaxRequest.abort();
}
var url = ApplicationBaseURL + "/" + folderId + "/deleteFolder";
document.deletePersonalCalendarAjaxRequest
= triggerAjaxRequest(url, deletePersonalCalendarCallback, folderId);
}
}
function deletePersonalCalendarCallback(http) {
if (http.readyState == 4) {
if (isHttpStatus204(http.status)) {
var ul = $("calendarList");
var children = ul.childNodesWithTag("li");
var i = 0;
var done = false;
while (!done && i < children.length) {
var currentFolderId = children[i].getAttribute("id").substr(1);
if (currentFolderId == http.callbackData) {
ul.removeChild(children[i]);
done = true;
}
else
i++;
}
refreshEvents();
refreshTasks();
changeCalendarDisplay();
}
document.deletePersonalCalendarAjaxRequest = null;
}
else
log ("ajax problem 5: " + http.status);
}
function configureLists() { function configureLists() {
var list = $("tasksList"); var list = $("tasksList");
list.multiselect = true; list.multiselect = true;

View file

@ -88,8 +88,7 @@ function subscribeToFolder(refreshCallback, refreshCallbackData) {
refreshCallbackData["folder"]); refreshCallbackData["folder"]);
} }
else else
refreshCallbackData["window"].alert(clabels["You cannot subscribe to a folder that you own!"] refreshCallbackData["window"].alert(clabels["You cannot subscribe to a folder that you own!"]);
.decodeEntities());
} }
function openRightsForUserID(userID) { function openRightsForUserID(userID) {

View file

@ -43,36 +43,36 @@ function validateAptEditor() {
e = $('summary'); e = $('summary');
if (e.value.length == 0) { if (e.value.length == 0) {
if (!confirm(labels.validate_notitle.decodeEntities())) if (!confirm(labels.validate_notitle))
return false; return false;
} }
e = $('startTime_date'); e = $('startTime_date');
if (e.value.length != 10) { if (e.value.length != 10) {
alert(labels.validate_invalid_startdate.decodeEntities()); alert(labels.validate_invalid_startdate);
return false; return false;
} }
startdate = e.calendar.prs_date(e.value); startdate = e.calendar.prs_date(e.value);
if (startdate == null) { if (startdate == null) {
alert(labels.validate_invalid_startdate.decodeEntities()); alert(labels.validate_invalid_startdate);
return false; return false;
} }
e = $('endTime_date'); e = $('endTime_date');
if (e.value.length != 10) { if (e.value.length != 10) {
alert(labels.validate_invalid_enddate.decodeEntities()); alert(labels.validate_invalid_enddate);
return false; return false;
} }
enddate = e.calendar.prs_date(e.value); enddate = e.calendar.prs_date(e.value);
if (enddate == null) { if (enddate == null) {
alert(labels.validate_invalid_enddate.decodeEntities()); alert(labels.validate_invalid_enddate);
return false; return false;
} }
// cuicui = ''; // cuicui = '';
tmpdate = uixEarlierDate(startdate, enddate); tmpdate = uixEarlierDate(startdate, enddate);
if (tmpdate == enddate) { if (tmpdate == enddate) {
// window.alert(cuicui); // window.alert(cuicui);
alert(labels.validate_endbeforestart.decodeEntities()); alert(labels.validate_endbeforestart);
return false; return false;
} }
else if (tmpdate == null /* means: same date */) { else if (tmpdate == null /* means: same date */) {
@ -83,14 +83,14 @@ function validateAptEditor() {
end = parseInt(document.forms[0]['endTime_time_hour'].value); end = parseInt(document.forms[0]['endTime_time_hour'].value);
if (start > end) { if (start > end) {
alert(labels.validate_endbeforestart.decodeEntities()); alert(labels.validate_endbeforestart);
return false; return false;
} }
else if (start == end) { else if (start == end) {
start = parseInt(document.forms[0]['startTime_time_minute'].value); start = parseInt(document.forms[0]['startTime_time_minute'].value);
end = parseInt(document.forms[0]['endTime_time_minute'].value); end = parseInt(document.forms[0]['endTime_time_minute'].value);
if (start > end) { if (start > end) {
alert(labels.validate_endbeforestart.decodeEntities()); alert(labels.validate_endbeforestart);
return false; return false;
} }
} }

View file

@ -24,7 +24,7 @@ function onPopupUrlWindow(event) {
preventDefault(event); preventDefault(event);
var urlInput = document.getElementById("url"); var urlInput = document.getElementById("url");
var newUrl = window.prompt(labels["Target:"].decodeEntities(), urlInput.value); var newUrl = window.prompt(labels["Target:"], urlInput.value);
if (newUrl != null) { if (newUrl != null) {
var documentHref = $("documentHref"); var documentHref = $("documentHref");
var documentLabel = $("documentLabel"); var documentLabel = $("documentLabel");

View file

@ -84,13 +84,13 @@ function validateContactEditor() {
if (e.value.length == 0) if (e.value.length == 0)
return true; return true;
if (uixEmailRegex.test(e.value) != true) if (uixEmailRegex.test(e.value) != true)
return confirm(labels.invalidemailwarn.decodeEntities()); return confirm(labels.invalidemailwarn);
e = $('homeMail'); e = $('homeMail');
if (e.value.length == 0) if (e.value.length == 0)
return true; return true;
if (uixEmailRegex.test(e.value) != true) if (uixEmailRegex.test(e.value) != true)
return confirm(labels.invalidemailwarn.decodeEntities()); return confirm(labels.invalidemailwarn);
return true; return true;
} }

View file

@ -30,7 +30,7 @@ function addLineToTree(tree, parent, line) {
for (var i = 1; i < nodes.length; i++) { for (var i = 1; i < nodes.length; i++) {
var folderInfos = nodes[i].split(":"); var folderInfos = nodes[i].split(":");
var icon = ResourcesURL + '/'; var icon = ResourcesURL + '/';
if (folderInfos[2] == 'contact') if (folderInfos[2] == 'Contacts')
icon += 'tb-mail-addressbook-flat-16x16.png'; icon += 'tb-mail-addressbook-flat-16x16.png';
else else
icon += 'calendar-folder-16x16.png'; icon += 'calendar-folder-16x16.png';

View file

@ -133,8 +133,7 @@ function validateEditorInput(sender) {
errortext = errortext + labels.error_missingrecipients + "\n"; errortext = errortext + labels.error_missingrecipients + "\n";
if (errortext.length > 0) { if (errortext.length > 0) {
alert(labels.error_validationfailed.decodeEntities() + ":\n" alert(labels.error_validationfailed + ":\n" + errortext);
+ errortext.decodeEntities());
return false; return false;
} }
return true; return true;

View file

@ -24,7 +24,7 @@ function validateDate(date, label) {
dateValue = date.calendar.prs_date(date.value); dateValue = date.calendar.prs_date(date.value);
if (date.value.length != 10 || !dateValue) { if (date.value.length != 10 || !dateValue) {
alert(label.decodeEntities()); alert(label);
result = false; result = false;
} else } else
result = dateValue; result = dateValue;
@ -37,7 +37,7 @@ function validateTaskEditor() {
e = document.getElementById('summary'); e = document.getElementById('summary');
if (e.value.length == 0 if (e.value.length == 0
&& !confirm(labels.validate_notitle.decodeEntities())) && !confirm(labels.validate_notitle))
return false; return false;
e = document.getElementById('startTime_date'); e = document.getElementById('startTime_date');
@ -58,7 +58,7 @@ function validateTaskEditor() {
tmpdate = uixEarlierDate(startdate, enddate); tmpdate = uixEarlierDate(startdate, enddate);
if (tmpdate == enddate) { if (tmpdate == enddate) {
// window.alert(cuicui); // window.alert(cuicui);
alert(labels.validate_endbeforestart.decodeEntities()); alert(labels.validate_endbeforestart);
return false; return false;
} }
else if (tmpdate == null /* means: same date */) { else if (tmpdate == null /* means: same date */) {
@ -69,14 +69,14 @@ function validateTaskEditor() {
end = parseInt(document.forms[0]['dueTime_time_hour'].value); end = parseInt(document.forms[0]['dueTime_time_hour'].value);
if (start > end) { if (start > end) {
alert(labels.validate_endbeforestart.decodeEntities()); alert(labels.validate_endbeforestart);
return false; return false;
} }
else if (start == end) { else if (start == end) {
start = parseInt(document.forms[0]['startTime_time_minute'].value); start = parseInt(document.forms[0]['startTime_time_minute'].value);
end = parseInt(document.forms[0]['dueTime_time_minute'].value); end = parseInt(document.forms[0]['dueTime_time_minute'].value);
if (start > end) { if (start > end) {
alert(labels.validate_endbeforestart.decodeEntities()); alert(labels.validate_endbeforestart);
return false; return false;
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -983,6 +983,7 @@ function subscribeToFolder(refreshCallback, refreshCallbackData) {
document.subscriptionAjaxRequest.aborted = true; document.subscriptionAjaxRequest.aborted = true;
document.subscriptionAjaxRequest.abort(); document.subscriptionAjaxRequest.abort();
} }
var rfCbData = { method: refreshCallback, data: refreshCallbackData }; var rfCbData = { method: refreshCallback, data: refreshCallbackData };
document.subscriptionAjaxRequest = triggerAjaxRequest(url, document.subscriptionAjaxRequest = triggerAjaxRequest(url,
folderSubscriptionCallback, folderSubscriptionCallback,
@ -1006,29 +1007,42 @@ function folderUnsubscriptionCallback(http) {
} }
function unsubscribeFromFolder(folder, refreshCallback, refreshCallbackData) { function unsubscribeFromFolder(folder, refreshCallback, refreshCallbackData) {
if (document.body.hasClassName("popup")) { if (document.body.hasClassName("popup")) {
window.opener.unsubscribeFromFolder(folder, refreshCallback, window.opener.unsubscribeFromFolder(folder, refreshCallback,
refreshCallbackData); refreshCallbackData);
} }
else { else {
var folderData = folder.split(":"); var folderData = folder.split("+");
var username = folderData[0]; var username = folderData[0];
var folderPath = folderData[1]; var folderPath = folderData[1];
if (username != UserLogin) { if (username != UserLogin) {
var url = (UserFolderURL + "../" + username var url = (ApplicationBaseURL + folder + "/unsubscribe");
+ "/" + folderPath + "/unsubscribe"); if (document.unsubscriptionAjaxRequest) {
if (document.unsubscriptionAjaxRequest) { document.unsubscriptionAjaxRequest.aborted = true;
document.unsubscriptionAjaxRequest.aborted = true; document.unsubscriptionAjaxRequest.abort();
document.unsubscriptionAjaxRequest.abort();
}
var rfCbData = { method: refreshCallback, data: refreshCallbackData };
document.unsubscriptionAjaxRequest
= triggerAjaxRequest(url, folderUnsubscriptionCallback,
rfCbData);
} }
else var rfCbData = { method: refreshCallback, data: refreshCallbackData };
window.alert(clabels["You cannot unsubscribe from a folder that you own!"].decodeEntities()); document.unsubscriptionAjaxRequest
} = triggerAjaxRequest(url, folderUnsubscriptionCallback,
rfCbData);
}
else
window.alert(clabels["You cannot unsubscribe from a folder that you own!"].decodeEntities());
}
}
function accessToSubscribedFolder(serverFolder) {
var folder;
var parts = serverFolder.split(":");
if (parts.length > 1) {
var paths = parts[1].split("/");
folder = "/" + parts[0] + "_" + paths[2];
}
else
folder = serverFolder;
return folder;
} }
function listRowMouseDownHandler(event) { function listRowMouseDownHandler(event) {
@ -1289,12 +1303,25 @@ function onLoadHandler(event) {
configureDragHandles(); configureDragHandles();
configureSortableTableHeaders(); configureSortableTableHeaders();
configureLinkBanner(); configureLinkBanner();
translateLabels();
var progressImage = $("progressIndicator"); var progressImage = $("progressIndicator");
if (progressImage) if (progressImage)
progressImage.parentNode.removeChild(progressImage); progressImage.parentNode.removeChild(progressImage);
Event.observe(document.body, "contextmenu", onBodyClickContextMenu); Event.observe(document.body, "contextmenu", onBodyClickContextMenu);
} }
function translateLabels() {
if (typeof labels != "undefined") {
for (var key in labels)
labels[key] = labels[key].decodeEntities();
}
if (typeof clabels != "undefined") {
for (var key in clabels)
clabels[key] = clabels[key].decodeEntities();
}
}
function onBodyClickContextMenu(event) { function onBodyClickContextMenu(event) {
preventDefault(event); preventDefault(event);
} }
@ -1340,6 +1367,38 @@ function configureLinkBanner() {
} }
} }
/* folder creation */
function createFolder(name, okCB, notOkCB) {
if (name) {
if (document.newFolderAjaxRequest) {
document.newFolderAjaxRequest.aborted = true;
document.newFolderAjaxRequest.abort();
}
var url = ApplicationBaseURL + "/createFolder?name=" + name;
document.newFolderAjaxRequest
= triggerAjaxRequest(url, createFolderCallback,
{name: name,
okCB: okCB,
notOkCB: notOkCB});
}
}
function createFolderCallback(http) {
if (http.readyState == 4) {
var data = http.callbackData;
if (http.status == 201) {
if (data.okCB)
data.okCB(data.name, "/" + http.responseText);
}
else {
if (data.notOkCB)
data.notOkCB(name);
else
log("ajax problem:" + http.status);
}
}
}
addEvent(window, 'load', onLoadHandler); addEvent(window, 'load', onLoadHandler);
function parent$(element) { function parent$(element) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB