From b9f2845bc4388ad944a3975d3268f410ee24dac0 Mon Sep 17 00:00:00 2001 From: wolfgang Date: Wed, 7 Mar 2007 22:52:32 +0000 Subject: [PATCH] git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1031 d1b88da0-ebda-0310-925b-ed51d893ca5b --- ChangeLog | 57 +++++++++++ Main/SOGo.m | 95 ++++++++++++++++++ OGoContentStore/OCSiCalFieldExtractor.m | 30 +++--- OGoContentStore/appointment.ocs | 2 +- OGoContentStore/sql/appointment-create.psql | 2 +- .../sql/generate-folderinfo-sql-for-users.sh | 2 +- SOPE/NGCards/CardElement.m | 2 +- SOPE/NGCards/CardGroup.m | 12 +-- SOPE/NGCards/CardVersitRenderer.m | 2 +- SOPE/NGCards/ChangeLog | 21 ++++ SOPE/NGCards/NSString+NGCards.m | 13 +-- SOPE/NGCards/iCalEntityObject.h | 8 ++ SOPE/NGCards/iCalEntityObject.m | 18 +++- .../Appointments/SOGoAppointmentFolder.m | 61 ++++++++--- .../Appointments/SOGoCalendarComponent.h | 1 + .../Appointments/SOGoCalendarComponent.m | 66 ++++++++++++ SoObjects/Appointments/product.plist | 1 + SoObjects/SOGo/SOGoAuthenticator.h | 4 + SoObjects/SOGo/SOGoAuthenticator.m | 4 +- UI/MailerUI/UIxMailReplyAction.m | 14 +-- UI/Scheduler/UIxCalInlineAptView.m | 83 ++++++++++++--- UI/Scheduler/UIxCalView.m | 91 +++++++++-------- UI/Scheduler/UIxComponent+Agenor.h | 7 +- UI/Scheduler/UIxComponent+Agenor.m | 14 ++- .../SchedulerUI/UIxCalInlineAptView.wox | 53 ++++++---- UI/WebServerResources/SchedulerUI.js | 9 ++ .../add-user-addressbook.png | Bin 0 -> 1671 bytes UI/WebServerResources/alarm.png | Bin 0 -> 865 bytes UI/WebServerResources/repeat-16.png | Bin 0 -> 404 bytes 29 files changed, 519 insertions(+), 153 deletions(-) create mode 100644 UI/WebServerResources/add-user-addressbook.png create mode 100644 UI/WebServerResources/alarm.png create mode 100644 UI/WebServerResources/repeat-16.png diff --git a/ChangeLog b/ChangeLog index f9685041..331f0414 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,60 @@ +2007-03-07 Wolfgang Sourdeau + + * SoObjects/SOGo/SOGoAuthenticator.m ([SOGoAuthenticator + -userInContext:]): returns "SOGoUser". + + * SoObjects/Appointments/SOGoCalendarComponent.m + ([SOGoCalendarComponent -contentAsString]): overriden method that + takes the privacy into account and discard the relevant fields if + needed by generating a new content string and caching it. + ([SOGoCalendarComponent + -saveContentString:contentStringbaseVersion:baseVersion]): if the + new method above has cached a content string, release it and set + it to nil so that it will have to be regenerated in the case it is + requested further. + ([SOGoCalendarComponent -_filterPrivateComponent:component]): + discard the fields that have to be hidden when the card is + private. + + * SoObjects/Appointments/SOGoAppointmentFolder.m + ([SOGoAppointmentFolder + -appendObject:objectwithBaseURL:baseURLtoREPORTResponse:r]): make + sure the cards are now handled as instances of + SOGoCalendarComponent instead of SOGoContentObject so that their + content string is taking the privacy classifiction into account. + ([SOGoAppointmentFolder -_privacySqlString]): new method that + generates a query to determine what information can be given and + if the card itself has to be shown. + + * UI/Scheduler/UIxComponent+Agenor.m ([UIxComponent + -getICalPersonsFromValue:selectorValue]): removed useless + "isAccessRestricted" method. + + * UI/Scheduler/UIxCalInlineAptView.m ([UIxCalInlineAptView + -setStyle:_style]): test whether the values of orgmail and + partmails are null before manipulating them, otherwise SOGo sends + a "rangeOfString:" message to an NSNull, which makes it crashes. + + * OGoContentStore/OCSiCalFieldExtractor.m ([OCSiCalFieldExtractor + -extractQuickFieldsFromEvent:_event]): we now use the new + "symbolicAccessClass" method from iCalEntity to determine the + value of the "classifiction" field. + ([OCSiCalFieldExtractor -extractQuickFieldsFromTodo:_task]): same + as above. + +2007-03-05 Wolfgang Sourdeau + + * SoObjects/Appointments/SOGoAppointmentFolder.m + ([SOGoAppointmentFolder + -fetchCoreInfosFrom:_startDateto:_endDatecomponent:_component]): + see below, the query is adapted consequently. + + * OGoContentStore/OCSiCalFieldExtractor.m ([OCSiCalFieldExtractor + -extractQuickFieldsFromTodo:_task]): the field "ispublic" was + renamed to "classification" and can any integer as value. + ([OCSiCalFieldExtractor -extractQuickFieldsFromEvent:_event]): + idem. + 2007-02-26 Wolfgang Sourdeau * UI/MailPartViewers/UIxMailPartHTMLViewer.m diff --git a/Main/SOGo.m b/Main/SOGo.m index 0f10c984..a427bd78 100644 --- a/Main/SOGo.m +++ b/Main/SOGo.m @@ -21,6 +21,92 @@ #include +// @interface classtree : NSObject +// { +// Class topClass; +// int indentLevel; +// } + +// - (id) initWithTopClass: (Class) newTopClass; +// - (void) dumpSiblings: (Class) node; + +// @end + +// @implementation classtree + +// + (id) newWithTopClass: (Class) newTopClass +// { +// id newTree; + +// newTree = [[self alloc] initWithTopClass: newTopClass]; +// [newTree autorelease]; + +// return newTree; +// } + +// - (id) initWithTopClass: (Class) newTopClass +// { +// if ((self = [self init])) +// topClass = newTopClass; + +// return self; +// } + +// #define indentGap 2 + +// - (NSString *) indentSpaces +// { +// char *spaceString; + +// spaceString = malloc(sizeof (char *) * indentGap * indentLevel + 1); +// *(spaceString + indentGap * indentLevel) = 0; +// memset (spaceString, ' ', indentGap * indentLevel); + +// return [[NSString alloc] initWithCStringNoCopy: spaceString +// length: indentGap * indentLevel +// freeWhenDone: YES]; +// } + +// - (void) dumpNode: (Class) node +// { +// Class currentSubclass; +// unsigned int count; + +// count = 0; +// currentSubclass = node->subclass_list; +// if (currentSubclass) +// { +// NSLog(@"%@%@:", +// [[self indentSpaces] autorelease], NSStringFromClass(node)); +// indentLevel++; +// [self dumpSiblings: currentSubclass]; +// indentLevel--; +// } +// else +// NSLog(@"%@%@", [self indentSpaces], NSStringFromClass(node)); +// } + +// - (void) dumpSiblings: (Class) node +// { +// Class currentNode; + +// currentNode = node; +// while (currentNode && currentNode->instance_size) +// { +// [self dumpNode: currentNode]; +// currentNode = currentNode->sibling_class; +// } +// } + +// - (void) dumpTree +// { +// indentLevel = 0; + +// [self dumpSiblings: topClass]; +// } + +// @end + @interface SOGo : SoApplication { NSMutableDictionary *localeLUT; @@ -189,6 +275,14 @@ static BOOL doCrashOnSessionCreate = NO; /* runtime maintenance */ +// - (void) _dumpClassAllocation +// { +// classtree *ct; + +// ct = [classtree newWithTopClass: [NSObject class]]; +// [ct dumpTree]; +// } + - (void)checkIfDaemonHasToBeShutdown { unsigned int limit, vmem; @@ -202,6 +296,7 @@ static BOOL doCrashOnSessionCreate = NO; @"terminating app, vMem size limit (%d MB) has been reached" @" (currently %d MB)", limit, vmem]; +// [self _dumpClassAllocation]; [self terminate]; } } diff --git a/OGoContentStore/OCSiCalFieldExtractor.m b/OGoContentStore/OCSiCalFieldExtractor.m index 09cbe20e..264893c7 100644 --- a/OGoContentStore/OCSiCalFieldExtractor.m +++ b/OGoContentStore/OCSiCalFieldExtractor.m @@ -66,12 +66,13 @@ static NSNumber *distantFutureNumber = nil; NSMutableDictionary *row; NSCalendarDate *startDate, *endDate; NSArray *attendees; - NSString *uid, *title, *location, *status, *accessClass; + NSString *uid, *title, *location, *status; NSNumber *sequence; id organizer; id participants, partmails; NSMutableString *partstates; unsigned i, count; + iCalAccessClass accessClass; if (_event == nil) return nil; @@ -84,7 +85,7 @@ static NSNumber *distantFutureNumber = nil; title = [_event summary]; location = [_event location]; sequence = [_event sequence]; - accessClass = [[_event accessClass] uppercaseString]; + accessClass = [_event symbolicAccessClass]; status = [[_event status] uppercaseString]; attendees = [_event attendees]; @@ -117,9 +118,9 @@ static NSNumber *distantFutureNumber = nil; if ([location isNotNull]) [row setObject: location forKey:@"location"]; if ([sequence isNotNull]) [row setObject: sequence forKey:@"sequence"]; - if ([startDate isNotNull]) + if ([startDate isNotNull]) [row setObject: [self numberForDate: startDate] forKey:@"startdate"]; - if ([endDate isNotNull]) + if ([endDate isNotNull]) [row setObject: [self numberForDate: endDate] forKey:@"enddate"]; if ([_event isRecurrent]) { NSCalendarDate *date; @@ -153,12 +154,8 @@ static NSNumber *distantFutureNumber = nil; [row setObject: [NSNumber numberWithInt:1] forKey: @"status"]; } - if([accessClass isNotNull] && ![accessClass isEqualToString:@"PUBLIC"]) { - [row setObject:[NSNumber numberWithBool:NO] forKey:@"ispublic"]; - } - else { - [row setObject:[NSNumber numberWithBool:YES] forKey:@"ispublic"]; - } + [row setObject: [NSNumber numberWithUnsignedInt: accessClass] + forKey: @"classification"]; organizer = [_event organizer]; if (organizer) { @@ -192,12 +189,13 @@ static NSNumber *distantFutureNumber = nil; NSMutableDictionary *row; NSCalendarDate *startDate, *dueDate; NSArray *attendees; - NSString *uid, *title, *location, *status, *accessClass; + NSString *uid, *title, *location, *status; NSNumber *sequence; id organizer, date; id participants, partmails; NSMutableString *partstates; unsigned i, count, code; + iCalAccessClass accessClass; if (_task == nil) return nil; @@ -210,7 +208,7 @@ static NSNumber *distantFutureNumber = nil; title = [_task summary]; location = [_task location]; sequence = [_task sequence]; - accessClass = [[_task accessClass] uppercaseString]; + accessClass = [_task symbolicAccessClass]; status = [[_task status] uppercaseString]; attendees = [_task attendees]; @@ -271,12 +269,8 @@ static NSNumber *distantFutureNumber = nil; [row setObject:[NSNumber numberWithInt:1] forKey:@"status"]; } - if([accessClass isNotNull] && ![accessClass isEqualToString:@"PUBLIC"]) { - [row setObject:[NSNumber numberWithBool:NO] forKey:@"ispublic"]; - } - else { - [row setObject:[NSNumber numberWithBool:YES] forKey:@"ispublic"]; - } + [row setObject: [NSNumber numberWithUnsignedInt: accessClass] + forKey: @"classification"]; organizer = [_task organizer]; if (organizer) { diff --git a/OGoContentStore/appointment.ocs b/OGoContentStore/appointment.ocs index 8e014e4a..966680e4 100644 --- a/OGoContentStore/appointment.ocs +++ b/OGoContentStore/appointment.ocs @@ -55,7 +55,7 @@ allowsNull = YES; }, { - columnName = ispublic; + columnName = classification; sqlType = "INT"; allowsNull = NO; }, diff --git a/OGoContentStore/sql/appointment-create.psql b/OGoContentStore/sql/appointment-create.psql index 94c370c6..8ec45160 100644 --- a/OGoContentStore/sql/appointment-create.psql +++ b/OGoContentStore/sql/appointment-create.psql @@ -11,7 +11,7 @@ CREATE TABLE %s_quick ( participants VARCHAR(100000) NOT NULL, -- the CNs of the participants isallday INT NULL, iscycle INT NULL, -- client needs to fetch to resolve - ispublic INT NOT NULL, + classification INT NOT NULL, status INT NOT NULL, isopaque INT NOT NULL, location VARCHAR(256) NULL, diff --git a/OGoContentStore/sql/generate-folderinfo-sql-for-users.sh b/OGoContentStore/sql/generate-folderinfo-sql-for-users.sh index ed2e0183..e8ba9c59 100755 --- a/OGoContentStore/sql/generate-folderinfo-sql-for-users.sh +++ b/OGoContentStore/sql/generate-folderinfo-sql-for-users.sh @@ -82,7 +82,7 @@ CREATE TABLE SOGo_${USER_TABLE}_privcal_quick ( participants VARCHAR(100000) NULL, -- the CNs of the participants isallday INT NULL, iscycle INT NULL, -- client needs to fetch to resolve - ispublic INT NOT NULL, + classification INT NOT NULL, status INT NOT NULL, priority INT NOT NULL, -- for marking high prio apts isopaque INT NULL, diff --git a/SOPE/NGCards/CardElement.m b/SOPE/NGCards/CardElement.m index cf4c489a..7af7e19b 100644 --- a/SOPE/NGCards/CardElement.m +++ b/SOPE/NGCards/CardElement.m @@ -417,8 +417,8 @@ - (NSString *) versitString { - CardVersitRenderer *renderer; NSString *string; + CardVersitRenderer *renderer; renderer = [CardVersitRenderer new]; string = [renderer render: self]; diff --git a/SOPE/NGCards/CardGroup.m b/SOPE/NGCards/CardGroup.m index ae375d46..be1c71e0 100644 --- a/SOPE/NGCards/CardGroup.m +++ b/SOPE/NGCards/CardGroup.m @@ -112,13 +112,7 @@ static NGCardsSaxHandler *sax = nil; + (id) groupWithTag: (NSString *) aTag { - id newGroup; - - newGroup = [self new]; - [newGroup autorelease]; - [newGroup setTag: aTag]; - - return newGroup; + return [self elementWithTag: aTag]; } + (id) groupWithTag: (NSString *) aTag @@ -126,9 +120,7 @@ static NGCardsSaxHandler *sax = nil; { id newGroup; - newGroup = [self new]; - [newGroup autorelease]; - [newGroup setTag: aTag]; + newGroup = [self elementWithTag: aTag]; [newGroup addChildren: someChildren]; return newGroup; diff --git a/SOPE/NGCards/CardVersitRenderer.m b/SOPE/NGCards/CardVersitRenderer.m index 0643bbdc..523fddde 100644 --- a/SOPE/NGCards/CardVersitRenderer.m +++ b/SOPE/NGCards/CardVersitRenderer.m @@ -61,7 +61,6 @@ if (![anElement isVoid]) { rendering = [NSMutableString new]; - [rendering autorelease]; if ([anElement group]) [rendering appendFormat: @"%@.", [anElement group]]; tag = [anElement tag]; @@ -94,6 +93,7 @@ [rendering appendString: @"\r\n"]; finalRendering = [rendering foldedForVersitCards]; + [rendering release]; } else finalRendering = @""; diff --git a/SOPE/NGCards/ChangeLog b/SOPE/NGCards/ChangeLog index 6b01b649..c8f0df09 100644 --- a/SOPE/NGCards/ChangeLog +++ b/SOPE/NGCards/ChangeLog @@ -1,3 +1,24 @@ +2007-03-07 Wolfgang Sourdeau + + * iCalEntityObject.m ([iCalEntityObject -symbolicAccessClass]): + new method that parses the "CLASS" element of the card and returns + an enum value. + + * NSString+NGCards.m ([NSString -foldedForVersitCards]): + simplified method by initializing and returning folderString + unconditionnally. If length < 76, the original string is appended + to it. + + * CardGroup.m ([CardGroup +groupWithTag:aTag]): simply invoke + [self elementWithTag:]. + ([CardGroup +groupWithTag:aTagchildren:someChildren]): same as + above. + +2007-03-05 Wolfgang Sourdeau + + * iCalEntityObject.h (enum): added an enum with iCalAccessPublic, + iCalAccessPrivate and iCalAccessConfidential values. + 2007-02-15 Wolfgang Sourdeau * CardGroup.m ([CardGroup -firstChildWithTag:aTag]): new method. diff --git a/SOPE/NGCards/NSString+NGCards.m b/SOPE/NGCards/NSString+NGCards.m index eb0c4e42..21cee5b5 100644 --- a/SOPE/NGCards/NSString+NGCards.m +++ b/SOPE/NGCards/NSString+NGCards.m @@ -42,19 +42,18 @@ static NSString *commaSeparator = nil; - (NSString *) foldedForVersitCards { - NSString *newString; NSMutableString *foldedString; unsigned int length; NSRange subStringRange; + foldedString = [NSMutableString new]; + [foldedString autorelease]; + length = [self length]; if (length < 76) - newString = self; + [foldedString appendString: self]; else { - foldedString = [NSMutableString new]; - [foldedString autorelease]; - subStringRange = NSMakeRange (0, 75); [foldedString appendFormat: @"%@\r\n", [self substringWithRange: subStringRange]]; @@ -68,11 +67,9 @@ static NSString *commaSeparator = nil; subStringRange.length = length - subStringRange.location; [foldedString appendFormat: @" %@", [self substringWithRange: subStringRange]]; - - newString = foldedString; } - return newString; + return foldedString; } - (NSArray *) asCardAttributeValues diff --git a/SOPE/NGCards/iCalEntityObject.h b/SOPE/NGCards/iCalEntityObject.h index 0f748939..954c8f66 100644 --- a/SOPE/NGCards/iCalEntityObject.h +++ b/SOPE/NGCards/iCalEntityObject.h @@ -35,6 +35,13 @@ @class iCalPerson; @class NSURL; +typedef enum +{ + iCalAccessPublic = 0, + iCalAccessPrivate = 1, + iCalAccessConfidential = 2, +} iCalAccessClass; + @interface iCalEntityObject : CardGroup /* accessors */ @@ -53,6 +60,7 @@ - (void) setAccessClass:(NSString *) _value; - (NSString *) accessClass; +- (iCalAccessClass) symbolicAccessClass; - (BOOL) isPublic; - (void) setPriority: (NSString *) _value; diff --git a/SOPE/NGCards/iCalEntityObject.m b/SOPE/NGCards/iCalEntityObject.m index d45de9d0..1239e233 100644 --- a/SOPE/NGCards/iCalEntityObject.m +++ b/SOPE/NGCards/iCalEntityObject.m @@ -118,9 +118,25 @@ return [[self uniqueChildWithTag: @"class"] value: 0]; } +- (iCalAccessClass) symbolicAccessClass +{ + iCalAccessClass symbolicAccessClass; + NSString *accessClass; + + accessClass = [[self accessClass] uppercaseString]; + if ([accessClass isEqualToString: @"PRIVATE"]) + symbolicAccessClass = iCalAccessPrivate; + else if ([accessClass isEqualToString: @"CONFIDENTIAL"]) + symbolicAccessClass = iCalAccessConfidential; + else + symbolicAccessClass = iCalAccessPublic; + + return symbolicAccessClass; +} + - (BOOL) isPublic { - return [[[self accessClass] uppercaseString] isEqualToString: @"PUBLIC"]; + return ([self symbolicAccessClass] == iCalAccessPublic); } - (void) setPriority: (NSString *) _value diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index 6772e5e9..dc901a3a 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -32,6 +32,7 @@ #import #import #import +#import #import "common.h" @@ -135,13 +136,18 @@ static NSNumber *sharedYes = nil; withBaseURL: (NSString *) baseURL toREPORTResponse: (WOResponse *) r { - SOGoContentObject *ocsObject; + SOGoCalendarComponent *component; + Class componentClass; NSString *c_name, *etagLine, *calString; c_name = [object objectForKey: @"c_name"]; - ocsObject = [SOGoContentObject objectWithName: c_name - inContainer: self]; + if ([[object objectForKey: @"component"] isEqualToString: @"vevent"]) + componentClass = [SOGoAppointmentObject class]; + else + componentClass = [SOGoTaskObject class]; + + component = [componentClass objectWithName: c_name inContainer: self]; [r appendContentString: @" \r\n"]; [r appendContentString: @" "]; @@ -154,13 +160,13 @@ static NSNumber *sharedYes = nil; [r appendContentString: @" \r\n"]; [r appendContentString: @" \r\n"]; etagLine = [NSString stringWithFormat: @" %@\r\n", - [ocsObject davEntityTag]]; + [component davEntityTag]]; [r appendContentString: etagLine]; [r appendContentString: @" \r\n"]; [r appendContentString: @" HTTP/1.1 200 OK\r\n"]; [r appendContentString: @" \r\n"]; [r appendContentString: @" "]; - calString = [[ocsObject contentAsString] stringByEscapingXMLString]; + calString = [[component contentAsString] stringByEscapingXMLString]; [r appendContentString: calString]; [r appendContentString: @"\r\n"]; [r appendContentString: @" \r\n"]; @@ -658,10 +664,37 @@ static NSNumber *sharedYes = nil; end = (unsigned int) [_endDate timeIntervalSince1970]; return [NSString stringWithFormat: - @" AND (startdate <= %d) AND (enddate >= %d)", + @" AND (startdate <= %u) AND (enddate >= %u)", end, start]; } +- (NSString *) _privacySqlString +{ + NSString *privacySqlString, *owner, *currentUser, *email; + WOContext *context; + SOGoUser *activeUser; + + context = [[WOApplication application] context]; + activeUser = [context activeUser]; + currentUser = [activeUser login]; + owner = [self ownerInContext: context]; + + if ([currentUser isEqualToString: owner]) + privacySqlString = @""; + else + { + email = [activeUser email]; + privacySqlString + = [NSString stringWithFormat: + @"(classification != %d or (orgmail = '%@')" + @" or ((partmails caseInsensitiveLike '%@%%'" + @" or partmails caseInsensitiveLike '%%\\n%@%%')))", + iCalAccessPrivate, email, email, email]; + } + + return privacySqlString; +} + - (NSArray *) fetchFields: (NSArray *) _fields fromFolder: (GCSFolder *) _folder from: (NSCalendarDate *) _startDate @@ -671,7 +704,7 @@ static NSNumber *sharedYes = nil; EOQualifier *qualifier; NSMutableArray *fields, *ma = nil; NSArray *records; - NSString *sql, *dateSqlString, *componentSqlString; /* , *owner; */ + NSString *sql, *dateSqlString, *componentSqlString, *privacySqlString; /* , *owner; */ NGCalendarDateRange *r; if (_folder == nil) { @@ -693,6 +726,7 @@ static NSNumber *sharedYes = nil; } componentSqlString = [self _sqlStringForComponent: _component]; + privacySqlString = [self _privacySqlString]; /* prepare mandatory fields */ @@ -704,8 +738,8 @@ static NSNumber *sharedYes = nil; if (logger) [self debugWithFormat:@"should fetch (%@=>%@) ...", _startDate, _endDate]; - sql = [NSString stringWithFormat: @"(iscycle = 0)%@%@", - dateSqlString, componentSqlString]; + sql = [NSString stringWithFormat: @"(iscycle = 0)%@%@%@", + dateSqlString, componentSqlString, privacySqlString]; /* fetch non-recurrent apts first */ qualifier = [EOQualifier qualifierWithQualifierFormat: sql]; @@ -722,8 +756,8 @@ static NSNumber *sharedYes = nil; } /* fetch recurrent apts now */ - sql = [NSString stringWithFormat: @"(iscycle = 1)%@%@", - dateSqlString, componentSqlString]; + sql = [NSString stringWithFormat: @"(iscycle = 1)%@%@%@", + dateSqlString, componentSqlString, privacySqlString]; qualifier = [EOQualifier qualifierWithQualifierFormat: sql]; [fields addObject: @"cycleinfo"]; @@ -807,12 +841,13 @@ static NSNumber *sharedYes = nil; infos = [[NSArray alloc] initWithObjects: @"c_name", @"component", @"title", @"location", @"orgmail", - @"status", @"ispublic", + @"status", @"classification", @"isallday", @"isopaque", @"participants", @"partmails", @"partstates", @"sequence", @"priority", nil]; - return [self fetchFields: infos from: _startDate to: _endDate component: _component]; + return [self fetchFields: infos from: _startDate to: _endDate + component: _component]; } - (void) deleteEntriesWithIds: (NSArray *) ids diff --git a/SoObjects/Appointments/SOGoCalendarComponent.h b/SoObjects/Appointments/SOGoCalendarComponent.h index 50e069ee..589b7dbb 100644 --- a/SoObjects/Appointments/SOGoCalendarComponent.h +++ b/SoObjects/Appointments/SOGoCalendarComponent.h @@ -34,6 +34,7 @@ @interface SOGoCalendarComponent : SOGoContentObject { iCalCalendar *calendar; + NSString *calContent; } - (NSString *) componentTag; diff --git a/SoObjects/Appointments/SOGoCalendarComponent.m b/SoObjects/Appointments/SOGoCalendarComponent.m index c5e6e311..c79091a7 100644 --- a/SoObjects/Appointments/SOGoCalendarComponent.m +++ b/SoObjects/Appointments/SOGoCalendarComponent.m @@ -68,6 +68,7 @@ static BOOL sendEMailNotifications = NO; if ((self = [super init])) { calendar = nil; + calContent = nil; } return self; @@ -77,6 +78,8 @@ static BOOL sendEMailNotifications = NO; { if (calendar) [calendar release]; + if (calContent) + [calContent release]; [super dealloc]; } @@ -92,6 +95,69 @@ static BOOL sendEMailNotifications = NO; return nil; } +- (void) _filterPrivateComponent: (iCalEntityObject *) component +{ + [component setSummary: @""]; + [component setComment: @""]; + [component setUserComment: @""]; + [component setLocation: @""]; + [component setCategories: @""]; + [component setUrl: @""]; + [component removeAllAttendees]; + [component removeAllAlarms]; +} + +- (NSString *) contentAsString +{ + NSString *tmpContent, *email; + iCalCalendar *tmpCalendar; + iCalRepeatableEntityObject *tmpComponent; + WOContext *context; + + if (!calContent) + { + tmpContent = [super contentAsString]; + calContent = tmpContent; + if ([tmpContent length] > 0) + { + tmpCalendar = [iCalCalendar parseSingleFromSource: tmpContent]; + tmpComponent = (iCalRepeatableEntityObject *) [tmpCalendar firstChildWithTag: [self componentTag]]; + if (![tmpComponent isPublic]) + { + context = [[WOApplication application] context]; + email = [[context activeUser] email]; + if (!([tmpComponent isOrganizer: email] + || [tmpComponent isParticipant: email])) + { + // content = tmpContent; + [self _filterPrivateComponent: tmpComponent]; + calContent = [tmpCalendar versitString]; + } + } + } + + [calContent retain]; + } + + return calContent; +} + +- (NSException *) saveContentString: (NSString *) contentString + baseVersion: (unsigned int) baseVersion +{ + NSException *result; + + result = [super saveContentString: contentString + baseVersion: baseVersion]; + if (!result && calContent) + { + [calContent release]; + calContent = nil; + } + + return result; +} + - (iCalCalendar *) calendar { NSString *iCalString; diff --git a/SoObjects/Appointments/product.plist b/SoObjects/Appointments/product.plist index 3213aac5..a45e744d 100644 --- a/SoObjects/Appointments/product.plist +++ b/SoObjects/Appointments/product.plist @@ -15,6 +15,7 @@ "FreeBusyLookup" = ( "Owner", "Delegate", "Assistant", "FreeBusy" ); "Add Documents, Images, and Files" = ( "Owner", "Delegate" ); "Access Contents Information" = ( "Owner", "Delegate", "Assistant" ); + "Delete Objects" = ( "Owner", "Organizer", "Delegate" ); }; }; diff --git a/SoObjects/SOGo/SOGoAuthenticator.h b/SoObjects/SOGo/SOGoAuthenticator.h index 1a5549e5..a56ac426 100644 --- a/SoObjects/SOGo/SOGoAuthenticator.h +++ b/SoObjects/SOGo/SOGoAuthenticator.h @@ -34,6 +34,8 @@ @class NSUserDefaults; @class NSString; +@class SOGoUser; + @interface SOGoAuthenticator : SoHTTPAuthenticator { NSUserDefaults *ud; @@ -47,6 +49,8 @@ - (BOOL) LDAPCheckLogin: (NSString *) _login password: (NSString *) _pwd; +- (SOGoUser *) userInContext: (WOContext *) _ctx; + @end #endif /* __Main_SOGoAuthenticator_H__ */ diff --git a/SoObjects/SOGo/SOGoAuthenticator.m b/SoObjects/SOGo/SOGoAuthenticator.m index 18c00d27..2c276e06 100644 --- a/SoObjects/SOGo/SOGoAuthenticator.m +++ b/SoObjects/SOGo/SOGoAuthenticator.m @@ -96,9 +96,9 @@ static SOGoAuthenticator *auth = nil; /* create SOGoUser */ -- (SoUser *) userInContext:(WOContext *)_ctx +- (SOGoUser *) userInContext: (WOContext *)_ctx { - static SoUser *anonymous = nil, *freebusy; + static SOGoUser *anonymous = nil, *freebusy; SoUser *user; NSArray *traversalPath; NSString *login; diff --git a/UI/MailerUI/UIxMailReplyAction.m b/UI/MailerUI/UIxMailReplyAction.m index 40f0abf0..5d278097 100644 --- a/UI/MailerUI/UIxMailReplyAction.m +++ b/UI/MailerUI/UIxMailReplyAction.m @@ -148,13 +148,15 @@ - (NSString *)contentForReply { NSArray *keys, *partInfos; NSDictionary *parts, *infos; - SOGoMailObject *co; - co = [self clientObject]; - keys = [co plainTextContentFetchKeys]; - infos = [co fetchCoreInfos]; - partInfos = [infos objectForKey: keys]; - NSLog (@"infos: '%@'", infos); + keys = [[self clientObject] plainTextContentFetchKeys]; +// SOGoMailObject *co; + +// co = [self clientObject]; +// keys = [co plainTextContentFetchKeys]; +// infos = [co fetchCoreInfos]; +// partInfos = [infos objectForKey: keys]; +// NSLog (@"infos: '%@'", infos); if ([keys count] == 0) return nil; diff --git a/UI/Scheduler/UIxCalInlineAptView.m b/UI/Scheduler/UIxCalInlineAptView.m index 1e83db2f..b989711f 100644 --- a/UI/Scheduler/UIxCalInlineAptView.m +++ b/UI/Scheduler/UIxCalInlineAptView.m @@ -25,6 +25,8 @@ #import #import +#import +#import @interface UIxCalInlineAptView : WOComponent { @@ -139,22 +141,22 @@ [ms appendFormat:@" apt_prio%@", prio]; } email = [[[self context] activeUser] email]; - if ((s = [appointment valueForKey:@"orgmail"])) { - if ([s rangeOfString:email].length > 0) { - [ms appendString:@" apt_organizer"]; - } - else { - [ms appendString:@" apt_other"]; - } - } - if ((s = [appointment valueForKey:@"partmails"])) { - if ([s rangeOfString:email].length > 0) { - [ms appendString:@" apt_participant"]; + s = [appointment valueForKey:@"orgmail"]; + if ([s isNotNull]) + { + if ([s rangeOfString: email].length > 0) + [ms appendString:@" apt_organizer"]; + else + [ms appendString:@" apt_other"]; } - else { - [ms appendString:@" apt_nonparticipant"]; + s = [appointment valueForKey:@"partmails"]; + if ([s isNotNull]) + { + if ([s rangeOfString:email].length > 0) + [ms appendString:@" apt_participant"]; + else + [ms appendString:@" apt_nonparticipant"]; } - } ASSIGNCOPY(style, ms); } @@ -250,6 +252,16 @@ /* helpers */ +- (NSString *) startHour +{ + NSCalendarDate *start; + + start = [appointment objectForKey: @"startDate"]; + + return [NSString stringWithFormat: @"%.2d:%.2d", + [start hourOfDay], [start minuteOfHour]]; +} + - (NSString *) title { return [formatter stringForObjectValue: appointment @@ -262,4 +274,47 @@ referenceDate: [self referenceDate]]; } +- (BOOL) _userIsInTheCard: (NSString *) email +{ + NSString *orgMailString, *partMailsString; + NSArray *partMails; + BOOL userIsInTheCard; + + orgMailString = [appointment objectForKey: @"orgmail"]; + if ([orgMailString isNotNull] && [orgMailString isEqualToString: email]) + userIsInTheCard = YES; + else + { + partMailsString = [appointment objectForKey: @"partmails"]; + if ([partMailsString isNotNull]) + { + partMails = [partMailsString componentsSeparatedByString: @"\n"]; + userIsInTheCard = [partMails containsObject: email]; + } + else + userIsInTheCard = NO; + } + + return userIsInTheCard; +} + +- (BOOL) titleShouldBeHidden +{ + BOOL shouldBeHidden; + SOGoUser *user; + SOGoAuthenticator *sAuth; + + sAuth = [SOGoAuthenticator sharedSOGoAuthenticator]; + user = [sAuth userInContext: context]; + + if ([[appointment objectForKey: @"owner"] isEqualToString: [user login]] + || ([[appointment objectForKey: @"classification"] intValue] + != iCalAccessConfidential)) + shouldBeHidden = NO; + else + shouldBeHidden = ![self _userIsInTheCard: [user email]]; + + return shouldBeHidden; +} + @end diff --git a/UI/Scheduler/UIxCalView.m b/UI/Scheduler/UIxCalView.m index adf89919..74b68328 100644 --- a/UI/Scheduler/UIxCalView.m +++ b/UI/Scheduler/UIxCalView.m @@ -96,49 +96,52 @@ static BOOL shouldDisplayWeekend = NO; - (NSArray *) filterAppointments:(NSArray *) _apts { NSMutableArray *filtered; - unsigned i, count; - NSString *email; - - count = [_apts count]; - if (!count) return _apts; - if ([self shouldDisplayRejectedAppointments]) return _apts; - - filtered = [[[NSMutableArray alloc] initWithCapacity: count] autorelease]; - email = [self emailForUser]; + unsigned i, count; + NSString *email; + NSDictionary *info; + NSArray *partmails; + unsigned p, pCount; + BOOL shouldAdd; + NSString *partmailsString; + NSArray *partstates; + NSString *state; + NSString *pEmail; + + if ([self shouldDisplayRejectedAppointments]) + return _apts; + { + count = [_apts count]; + filtered = [[[NSMutableArray alloc] initWithCapacity: count] autorelease]; + email = [self emailForUser]; + + for (i = 0; i < count; i++) + { + shouldAdd = YES; + info = [_apts objectAtIndex: i]; + partmailsString = [info objectForKey: @"partmails"]; + if ([partmailsString isNotNull]) + { + partmails = [partmailsString componentsSeparatedByString: @"\n"]; + pCount = [partmails count]; + for (p = 0; p < pCount; p++) + { + pEmail = [partmails objectAtIndex: p]; + if ([pEmail isEqualToString: email]) + { + partstates = [[info objectForKey: @"partstates"] + componentsSeparatedByString: @"\n"]; + state = [partstates objectAtIndex: p]; + if ([state intValue] == iCalPersonPartStatDeclined) + shouldAdd = NO; + break; + } + } + } + if (shouldAdd) + [filtered addObject: info]; + } + } - for (i = 0; i < count; i++) - { - NSDictionary *info; - NSArray *partmails; - unsigned p, pCount; - BOOL shouldAdd; - - shouldAdd = YES; - info = [_apts objectAtIndex: i]; - partmails = [[info objectForKey: @"partmails"] - componentsSeparatedByString: @"\n"]; - pCount = [partmails count]; - for (p = 0; p < pCount; p++) - { - NSString *pEmail; - - pEmail = [partmails objectAtIndex: p]; - if ([pEmail isEqualToString: email]) - { - NSArray *partstates; - NSString *state; - - partstates = [[info objectForKey: @"partstates"] - componentsSeparatedByString: @"\n"]; - state = [partstates objectAtIndex: p]; - if ([state intValue] == iCalPersonPartStatDeclined) - shouldAdd = NO; - break; - } - } - if (shouldAdd) - [filtered addObject: info]; - } return filtered; } @@ -181,7 +184,9 @@ static BOOL shouldDisplayWeekend = NO; if ([partmails rangeOfString: myEmail].length) aptFlags.canAccessApt = YES; else - aptFlags.canAccessApt = [[_apt valueForKey: @"ispublic"] boolValue]; + aptFlags.canAccessApt + = ([[_apt valueForKey: @"classification"] intValue] + == iCalAccessPublic); } } diff --git a/UI/Scheduler/UIxComponent+Agenor.h b/UI/Scheduler/UIxComponent+Agenor.h index 89544ede..7db79e75 100644 --- a/UI/Scheduler/UIxComponent+Agenor.h +++ b/UI/Scheduler/UIxComponent+Agenor.h @@ -31,11 +31,8 @@ - (NSArray *) getICalPersonsFromValue: (NSString *) selectorValue; /* email, cn */ -- (NSString *)emailForUser; -- (NSString *)cnForUser; - -/* restrictions */ -- (BOOL)isAccessRestricted; +- (NSString *) emailForUser; +- (NSString *) cnForUser; @end diff --git a/UI/Scheduler/UIxComponent+Agenor.m b/UI/Scheduler/UIxComponent+Agenor.m index 08320032..20aa370d 100644 --- a/UI/Scheduler/UIxComponent+Agenor.m +++ b/UI/Scheduler/UIxComponent+Agenor.m @@ -54,16 +54,14 @@ return persons; } -- (NSString *)emailForUser { - return [[[self context] activeUser] email]; -} - -- (NSString *)cnForUser { - return [[[self context] activeUser] cn]; +- (NSString *) emailForUser +{ + return [[context activeUser] email]; } -- (BOOL)isAccessRestricted { - return [[self context] isAccessFromIntranet] ? NO : YES; +- (NSString *) cnForUser +{ + return [[context activeUser] cn]; } @end /* UIxComponent(Agenor) */ diff --git a/UI/Templates/SchedulerUI/UIxCalInlineAptView.wox b/UI/Templates/SchedulerUI/UIxCalInlineAptView.wox index 64d5c6f2..929a66ca 100644 --- a/UI/Templates/SchedulerUI/UIxCalInlineAptView.wox +++ b/UI/Templates/SchedulerUI/UIxCalInlineAptView.wox @@ -1,22 +1,35 @@ -
-
-
+ +
+

+
diff --git a/UI/WebServerResources/SchedulerUI.js b/UI/WebServerResources/SchedulerUI.js index d0f858b2..9d5daf1f 100644 --- a/UI/WebServerResources/SchedulerUI.js +++ b/UI/WebServerResources/SchedulerUI.js @@ -1162,4 +1162,13 @@ function initCalendars() { initCalendarContactsSelector(); } +function onSchedulerBodyKeyUp(event) { + if (event.which == 46) { + window.alert("coucou"); + deleteEvent(); + event.cancelBubble = true; + } +} + window.addEventListener("load", initCalendars, false); +// document.body.addEventListener("keyup", onSchedulerBodyKeyUp, false); diff --git a/UI/WebServerResources/add-user-addressbook.png b/UI/WebServerResources/add-user-addressbook.png new file mode 100644 index 0000000000000000000000000000000000000000..68e7a88b6684b10b46ffc4a14b664f3c417f5601 GIT binary patch literal 1671 zcmV;226*|2P)ViJi1bNpp{#`Z}KR%-Az?ZZl`!cnC3s zaw$t%+R~Et|E;z6*4oSBL)vT4e=}j}_!<$(gw}dD@Dru=sP6{fd*=A7^Z#j|^DI z#9)nJtP#&jep;tHJK8$hn3FQS?-*@HEXx{BcCPBkd>-h2Gfe>QT(W6K605(9}PP~%t?AW#G3kS)pU5kyvgmp|cWK!2Z0w>07}Y{ zm=UCcDY$(Lp*0vV#vp4hQM1A1?PX#u7F#|s#G2LZG^&eqb#{^K?WT7iNor}4My+Cc zdU`Bi=-v^<0Ho4)63IBr({pGkF-oD8!YDjXL9r-gSe7 z;UG5xo4y@s8p)sW#6z19H1I`+dQ>OS0V7|^;YRcL%K?jS<&hYGb@Zs#N}X?QwJGH* zD;J!(`Fk$C^%kA0`w2q`8<6VQ%Aeke6NG|L`1r!ZmmaG;UdOJlDr4g)s(<;i)xOc>Q8X$=OPxr5z;TZ*dor&|fNOI{)sT@^U7rzJi)teK+*Y|8bV2tT9 z$|l>M!f1`r8nmI!(e!6D8?%c3jHbOs6EhmiK#Q_CGckvrj@X~>!*P9FU!+7#+_3+- zjcTpVB@^+%VquBC{#7g4-(Bxkvl8QOOf(_}8x}tf`)LFrjbedNYm}5kQm?)bAcP#Z ztk}VN)kRCi-<4Lxqec_I?%}&0q3aQN0a6IGfiN=nc}rWCT#wmtA3#YpW?6=2BgCt^ zG<+YgTF0xocy$laj4(hXp(!mI0vZCelOokONP6=CUAX~Ta~~m9pJe&eFCM=SFy&S* z_oq68L^75-`T8g+TO*A{q+>+NqN!p;#wN9PJ#B*zvU=Sn(tVpqtX_*TptZ&{>ZtM^ zK4-W0>=}OMFdZ9)NOY{i7=zXtRWB0FUL-6|AQo>E zm8X=E;)Z20W(?;oWya&p^H-jH6?ISV0{|)13CD^**R$>8RwAJyjvx5VrD^_8`x|5FmCaD< Rs@ebm002ovPDHLkV1lsTEh7K` literal 0 HcmV?d00001 diff --git a/UI/WebServerResources/alarm.png b/UI/WebServerResources/alarm.png new file mode 100644 index 0000000000000000000000000000000000000000..ae4234de71880a6dabc49f9f16096e3c01176e9b GIT binary patch literal 865 zcmV-n1D^beP)5~!^)xyL@6v-ux7)e zWzj!@C5yr$o322LC@RX-JW?p3LJ&oj02}AwM;uQadpfc2y)!J32a0-^SNHsM&iCD; zl}aT5?1kLwvDrzx=LuHsHkSa0hmU>f6>AmX&&I&1{MuOph>yh|luy~a9iR5W5i56_ z09XG9aNfLdTnQP*_WMJ-|3I$Z`{Q6qd#`*h64%?Fv+`4m#S=63yRXg>1R+WVr~p2> zS>^kU{pAlYo;v3F%I@|@e0rmal%myY(QdaR zP_Ngc*X!{ZNrK>?>^gu_AtSFxKA(Tc!P?py<#IW)KRG#xX_^fELu3&C3#hjrI9~fc zuIu8uE$(DerP>3gUkBnU&o5N`jrM@-Xsv6Qtp>;32>Y2!Lu rg>*QVPg8Aq)S905h&En*#2fwwK3JM-JiFAv00000NkvXXu0mjfxPY9B literal 0 HcmV?d00001 diff --git a/UI/WebServerResources/repeat-16.png b/UI/WebServerResources/repeat-16.png new file mode 100644 index 0000000000000000000000000000000000000000..44a100b949614b54ee44107610b4d7b9fdaa7fec GIT binary patch literal 404 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP`Gb_KoR$3_qi&a&P5yA_iDTHF4M)$N+iQL1&O>vvixV5a zKB?<4p7WR^^+LPMWF35n(CqFKY#N9?tr}*WB}rzsdNx_%2DNyAO1H6s3(D)4v#1?0xVj zUN}8j=IVrBhPRa5_8Pb)_Ib`&>TxeBab4z&wK3bc^KTpuz43k9qrb5^Ezopr0ID&eSO5S3 literal 0 HcmV?d00001 -- 2.39.5