Monotone-Parent: 5f2a3e7eefe739c0e656450e9cc85846e27c80b8

Monotone-Revision: 3239b46c1626108a2b1a3d6cab30ae4c9bd6a731

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2007-11-13T22:38:05
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2007-11-13 22:38:05 +00:00
parent 8041818572
commit d5d78c5f79
20 changed files with 415 additions and 102 deletions

View File

@ -1,5 +1,27 @@
2007-11-13 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/SOGo/iCalEntityObject+Utilities.m ([iCalEntityObject
-findParticipant:user]): new method based on the one removed from
SOGoCalendarComponent below.
* SoObjects/SOGo/iCalEntityObject+Utilities.[hm]: new category
module for iCalEntityObject.
* SoObjects/Appointments/SOGoCalendarComponent.m
([-findParticipant:user]): removed method.
* SoObjects/SOGo/SOGoContentObject.m ([SOGoContentObject
-setContentString:newContent]): new accessor method.
([SOGoContentObject
-saveContentString:newContentbaseVersion:newBaseVersion]): invoke
-[self setContentString:].
* UI/MailPartViewers/UIxMailPartICalViewer.m
([UIxMailPartICalViewer -authorativeEvent]): returns the most
up-to-date event.
([-isLoggedInUserTheOrganizer]): make use of -[SOGoUser
hasEmail:].
* UI/MailPartViewers/UIxMailPartTextViewer.m ([NSString
-stringByConvertingCRLNToHTML]): fixed crashes due to overflows in
temporary buffer we are handing.

View File

@ -116,6 +116,9 @@ typedef enum
- (NSArray *) alarms;
- (BOOL) hasAlarms;
/* comparisons */
- (NSComparisonResult) compare: (iCalEntityObject *) otherObject;
@end
#endif /* __NGCards_iCalEntityObject_H__ */

View File

@ -425,4 +425,27 @@
return nil; /* not found */
}
- (NSComparisonResult) _compareVersions: (iCalEntityObject *) otherObject
{
NSComparisonResult result;
result = [[self sequence] compare: [otherObject sequence]];
if (result == NSOrderedSame)
result = [[self lastModified] compare: [otherObject lastModified]];
return result;
}
- (NSComparisonResult) compare: (iCalEntityObject *) otherObject
{
NSComparisonResult result;
if ([[self uid] isEqualToString: [otherObject uid]])
result = [self _compareVersions: otherObject];
else
result = [[self created] compare: [otherObject created]];
return result;
}
@end /* iCalEntityObject */

View File

@ -31,6 +31,7 @@
#import <NGCards/iCalPerson.h>
#import <SoObjects/SOGo/LDAPUserManager.h>
#import <SoObjects/SOGo/NSArray+Utilities.h>
#import <SoObjects/SOGo/SOGoObject.h>
#import <SoObjects/SOGo/SOGoPermissions.h>
#import <SoObjects/SOGo/WORequest+SOGo.h>
@ -308,23 +309,33 @@
if ([self sendEMailNotifications]
&& [self _aptIsStillRelevant: newApt])
{
iCalEvent *requestApt;
requestApt = [newApt copy];
[(iCalCalendar *) [requestApt parent] setMethod: @"request"];
attendees
= [NSMutableArray arrayWithArray: [changes insertedAttendees]];
[attendees removePerson: organizer];
[self sendEMailUsingTemplateNamed: @"Invitation"
forOldObject: nil
andNewObject: newApt
andNewObject: requestApt
toAttendees: attendees];
[requestApt release];
if (updateForcesReconsider)
{
iCalEvent *updatedApt;
updatedApt = [newApt copy];
[(iCalCalendar *) [updatedApt parent] setMethod: @"request"];
attendees = [NSMutableArray arrayWithArray:[newApt attendees]];
[attendees removeObjectsInArray:[changes insertedAttendees]];
[attendees removePerson:organizer];
[self sendEMailUsingTemplateNamed: @"Update"
forOldObject: oldApt
andNewObject: newApt
andNewObject: updatedApt
toAttendees: attendees];
[updatedApt release];
}
attendees

View File

@ -57,10 +57,10 @@
forOldObject: (iCalRepeatableEntityObject *) _oldObject
andNewObject: (iCalRepeatableEntityObject *) _newObject
toAttendees: (NSArray *) _attendees;
- (void) sendResponseToOrganizer;
// - (BOOL) isOrganizerOrOwner: (SOGoUser *) user;
- (iCalPerson *) findParticipant: (SOGoUser *) user;
- (iCalPerson *) findParticipantWithUID: (NSString *) uid;
- (iCalPerson *) iCalPersonWithUID: (NSString *) uid;

View File

@ -36,6 +36,7 @@
#import <NGMime/NGMimeMultipartBody.h>
#import <NGMail/NGMimeMessage.h>
#import <SoObjects/SOGo/iCalEntityObject+Utilities.h>
#import <SoObjects/SOGo/LDAPUserManager.h>
#import <SoObjects/SOGo/NSCalendarDate+SOGo.h>
#import <SoObjects/SOGo/SOGoMailer.h>
@ -161,22 +162,29 @@ static BOOL sendEMailNotifications = NO;
return calContent;
}
- (NSException *) saveContentString: (NSString *) contentString
baseVersion: (unsigned int) baseVersion
- (void) setContentString: (NSString *) newContent
{
NSException *result;
result = [super saveContentString: contentString
baseVersion: baseVersion];
if (!result && calContent)
{
[calContent release];
calContent = nil;
}
return result;
[super setContentString: newContent];
ASSIGN (calendar, nil);
ASSIGN (calContent, nil);
}
// - (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: (BOOL) create
{
NSString *iCalString, *componentTag;
@ -445,6 +453,11 @@ static BOOL sendEMailNotifications = NO;
}
}
- (void) sendResponseToOrganizer
{
#warning THIS IS A STUB
}
// - (BOOL) isOrganizerOrOwner: (SOGoUser *) user
// {
// BOOL isOrganizerOrOwner;
@ -464,33 +477,13 @@ static BOOL sendEMailNotifications = NO;
- (iCalPerson *) findParticipantWithUID: (NSString *) uid
{
iCalEntityObject *component;
SOGoUser *user;
user = [SOGoUser userWithLogin: uid roles: nil];
return [self findParticipant: user];
}
- (iCalPerson *) findParticipant: (SOGoUser *) user
{
iCalPerson *participant, *currentParticipant;
iCalEntityObject *component;
NSEnumerator *participants;
participant = nil;
component = [self component: NO];
if (component)
{
participants = [[component participants] objectEnumerator];
currentParticipant = [participants nextObject];
while (currentParticipant && !participant)
if ([user hasEmail: [currentParticipant rfc822Email]])
participant = currentParticipant;
else
currentParticipant = [participants nextObject];
}
return participant;
return [component findParticipant: user];
}
- (iCalPerson *) iCalPersonWithUID: (NSString *) uid

View File

@ -1149,7 +1149,7 @@ static BOOL showTextAttachmentsInline = NO;
dateString = [[NSCalendarDate date] rfc822DateString];
[map addObject: dateString forKey: @"date"];
[map addObject: @"1.0" forKey: @"MIME-Version"];
[map addObject: userAgent forKey: @"X-Mailer"];
[map addObject: userAgent forKey: @"User-Agent"];
/* add custom headers */

View File

@ -34,6 +34,7 @@ libSOGo_HEADER_FILES = \
SOGoDateFormatter.h \
SOGoPermissions.h \
SOGoDAVRendererTypes.h \
iCalEntityObject+Utilities.h \
NSArray+Utilities.h \
NSDictionary+URL.h \
NSDictionary+Utilities.h \
@ -68,6 +69,7 @@ libSOGo_OBJC_FILES = \
LDAPSource.m \
SOGoDAVRendererTypes.m \
AgenorUserDefaults.m \
iCalEntityObject+Utilities.m \
NSArray+Utilities.m \
NSDictionary+URL.m \
NSDictionary+Utilities.m \

View File

@ -49,6 +49,7 @@
/* content */
- (BOOL) isNew;
- (void) setContentString: (NSString *) newContent;
- (NSString *) contentAsString;
- (NSException *) saveContentString: (NSString *) _str
baseVersion: (unsigned int) _baseVersion;

View File

@ -138,6 +138,11 @@
return content;
}
- (void) setContentString: (NSString *) newContent
{
ASSIGN (content, newContent);
}
- (NSException *) saveContentString: (NSString *) newContent
baseVersion: (unsigned int) newBaseVersion
{
@ -147,12 +152,11 @@
ex = nil;
ASSIGN (content, newContent);
[self setContentString: newContent];
folder = [container ocsFolder];
if (folder)
{
ex = [folder writeContent: newContent
toName: nameInContainer
ex = [folder writeContent: content toName: nameInContainer
baseVersion: newBaseVersion];
if (ex)
[self errorWithFormat:@"write failed: %@", ex];

View File

@ -41,7 +41,10 @@
@class NSUserDefaults;
@class NSTimeZone;
@class WOContext;
@class SOGoAppointmentFolder;
@class SOGoAppointmentFolders;
@class SOGoDateFormatter;
@class WOContext;
extern NSString *SOGoWeekStartHideWeekNumbers;
extern NSString *SOGoWeekStartJanuary1;
@ -117,7 +120,10 @@ extern NSString *SOGoWeekStartFirstFullWeek;
/* folders */
- (id) homeFolderInContext: (id) _ctx;
// - (id) schedulingCalendarInContext: (id) _ctx;
- (SOGoAppointmentFolders *) calendarsFolderInContext: (WOContext *) context;
- (SOGoAppointmentFolder *)
personalCalendarFolderInContext: (WOContext *) context;
- (NSArray *) rolesForObject: (NSObject *) object
inContext: (WOContext *) context;

View File

@ -551,6 +551,21 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
return folder;
}
- (SOGoAppointmentFolders *) calendarsFolderInContext: (WOContext *) context
{
return [[self homeFolderInContext: context] lookupName: @"Calendar"
inContext: context
acquire: NO];
}
- (SOGoAppointmentFolder *)
personalCalendarFolderInContext: (WOContext *) context
{
return [[self calendarsFolderInContext: context] lookupName: @"personal"
inContext: context
acquire: NO];
}
// - (id) schedulingCalendarInContext: (id) _ctx
// {
// /* Note: watch out for cyclic references */

View File

@ -0,0 +1,37 @@
/* iCalEntityObject+Utilities.h - this file is part of SOGo
*
* Copyright (C) 2007 Inverse groupe conseil
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef ICALENTITYOBJECT_UTILITIES_H
#define ICALENTITYOBJECT_UTILITIES_H
#import <NGCards/iCalEntityObject.h>
@class iCalPerson;
@class SOGoUser;
@interface iCalEntityObject (SOGoAddition)
- (iCalPerson *) findParticipant: (SOGoUser *) user;
@end
#endif /* ICALENTITYOBJECT_UTILITIES_H */

View File

@ -0,0 +1,51 @@
/* iCalEntityObject+Utilities.m - this file is part of SOGo
*
* Copyright (C) 2007 Inverse groupe conseil
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSEnumerator.h>
#import <NGCards/iCalPerson.h>
#import "SOGoUser.h"
#import "iCalEntityObject+Utilities.h"
@implementation iCalEntityObject (SOGoAddition)
- (iCalPerson *) findParticipant: (SOGoUser *) user
{
iCalPerson *participant, *currentParticipant;
NSEnumerator *participants;
participant = nil;
participants = [[self participants] objectEnumerator];
currentParticipant = [participants nextObject];
while (currentParticipant && !participant)
if ([user hasEmail: [currentParticipant rfc822Email]])
participant = currentParticipant;
else
currentParticipant = [participants nextObject];
return participant;
}
@end

View File

@ -24,7 +24,7 @@ MailPartViewers_OBJC_FILES += \
UIxMailPartMessageViewer.m \
UIxMailPartICalViewer.m \
\
UIxMailPartICalAction.m \
UIxMailPartICalActions.m \
\
UIxKolabPartViewer.m \
UIxKolabPartContactViewer.m \

View File

@ -1,4 +1,4 @@
/* UIxMailPartICalAction.m - this file is part of SOGo
/* UIxMailPartICalActions.h - this file is part of SOGo
*
* Copyright (C) 2007 Inverse groupe conseil
*
@ -20,44 +20,20 @@
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSString.h>
#ifndef UIXMAILPARTICALACTIONS_H
#define UIXMAILPARTICALACTIONS_H
#import <NGObjWeb/WODirectAction.h>
#import <UI/Common/WODirectAction+SOGo.h>
@class iCalCalendar;
@class SOGoMailBodyPart;
@class WOResponse;
@interface UIxMailPartICalActions : WODirectAction
- (WOResponse *) acceptAction;
- (WOResponse *) declineAction;
@interface UIxMailPartICalAction : WODirectAction
@end
@implementation UIxMailPartICalAction
- (WOResponse *) _changePartStatusAction: (NSString *) _newStatus
{
return [self responseWithStatus: 404];
}
- (WOResponse *) markAcceptedAction
{
return [self _changePartStatusAction: @"ACCEPTED"];
}
- (WOResponse *) markDeclinedAction
{
return [self _changePartStatusAction: @"DECLINED"];
}
- (WOResponse *) markTentativeAction
{
return [self _changePartStatusAction: @"TENTATIVE"];
}
- (WOResponse *) addToCalendarAction
{
return [self responseWithStatus: 404];
}
- (WOResponse *) deleteFromCalendarAction
{
return [self responseWithStatus: 404];
}
@end /* UIxMailPartICalAction */
#endif /* UIXMAILPARTICALACTIONS_H */

View File

@ -0,0 +1,164 @@
/* UIxMailPartICalActions.m - this file is part of SOGo
*
* Copyright (C) 2007 Inverse groupe conseil
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSCalendarDate.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WOResponse.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalPerson.h>
#import <UI/Common/WODirectAction+SOGo.h>
#import <SoObjects/Appointments/SOGoAppointmentObject.h>
#import <SoObjects/Appointments/SOGoAppointmentFolder.h>
#import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/SOGo/iCalEntityObject+Utilities.h>
#import <SoObjects/Mailer/SOGoMailBodyPart.h>
#import "UIxMailPartICalActions.h"
@implementation UIxMailPartICalActions
- (iCalEvent *) _emailEvent
{
NSData *content;
NSString *eventString;
iCalCalendar *emailCalendar;
content = [[self clientObject] fetchBLOB];
eventString = [[NSString alloc] initWithData: content
encoding: NSUTF8StringEncoding];
if (!eventString)
eventString = [[NSString alloc] initWithData: content
encoding: NSISOLatin1StringEncoding];
emailCalendar = [iCalCalendar parseSingleFromSource: eventString];
return (iCalEvent *) [emailCalendar firstChildWithTag: @"vevent"];
}
- (SOGoAppointmentObject *) _eventObjectWithUID: (NSString *) uid
{
SOGoAppointmentFolder *personalFolder;
SOGoAppointmentObject *eventObject;
personalFolder
= [[context activeUser] personalCalendarFolderInContext: context];
eventObject = [personalFolder lookupName: uid
inContext: context acquire: NO];
if (![eventObject isKindOfClass: [SOGoAppointmentObject class]])
eventObject = [SOGoAppointmentObject objectWithName: uid
inContainer: personalFolder];
return eventObject;
}
- (iCalEvent *)
_setupChosenEventAndEventObject: (SOGoAppointmentObject **) eventObject
{
iCalEvent *emailEvent, *calendarEvent, *chosenEvent;
emailEvent = [self _emailEvent];
if (emailEvent)
{
*eventObject = [self _eventObjectWithUID: [emailEvent uid]];
if ([*eventObject isNew])
chosenEvent = emailEvent;
else
{
calendarEvent = (iCalEvent *) [*eventObject component: NO];
if ([calendarEvent compare: emailEvent] == NSOrderedAscending)
chosenEvent = emailEvent;
else
chosenEvent = calendarEvent;
}
}
else
chosenEvent = nil;
return chosenEvent;
}
- (WOResponse *) _changePartStatusAction: (NSString *) newStatus
{
WOResponse *response;
SOGoAppointmentObject *eventObject;
iCalEvent *chosenEvent;
iCalPerson *user;
iCalCalendar *calendar;
NSString *rsvp, *method;
chosenEvent = [self _setupChosenEventAndEventObject: &eventObject];
if (chosenEvent)
{
user = [chosenEvent findParticipant: [context activeUser]];
[user setPartStat: newStatus];
calendar = [chosenEvent parent];
method = [[calendar method] lowercaseString];
if ([method isEqualToString: @"request"])
{
[calendar setMethod: @""];
rsvp = [[user rsvp] lowercaseString];
}
else
rsvp = nil;
[eventObject saveContentString: [calendar versitString]];
if (rsvp && [rsvp isEqualToString: @"true"])
[eventObject sendResponseToOrganizer];
response = [self responseWith204];
}
else
{
response = [context response];
[response setStatus: 409];
}
return response;
}
- (WOResponse *) acceptAction
{
return [self _changePartStatusAction: @"ACCEPTED"];
}
- (WOResponse *) declineAction
{
return [self _changePartStatusAction: @"DECLINED"];
}
// - (WOResponse *) markTentativeAction
// {
// return [self _changePartStatusAction: @"TENTATIVE"];
// }
// - (WOResponse *) addToCalendarAction
// {
// return [self responseWithStatus: 404];
// }
// - (WOResponse *) deleteFromCalendarAction
// {
// return [self responseWithStatus: 404];
// }
@end

View File

@ -292,22 +292,24 @@
- (iCalEvent *) authorativeEvent
{
/* DB is considered master, when in DB, ignore mail organizer */
return [self isEventStoredInCalendar]
? [self storedEvent]
: [self inEvent];
iCalEvent *authorativeEvent;
if ([[self storedEvent] compare: [self inEvent]]
== NSOrderedAscending)
authorativeEvent = inEvent;
else
authorativeEvent = storedEventObject;
return authorativeEvent;
}
- (BOOL) isLoggedInUserTheOrganizer
{
NSString *loginEMail;
iCalPerson *organizer;
if ((loginEMail = [self loggedInUserEMail]) == nil) {
[self warnWithFormat:@"Could not determine email of logged in user?"];
return NO;
}
return [[self authorativeEvent] isOrganizer:loginEMail];
organizer = [[self authorativeEvent] organizer];
return [[context activeUser] hasEmail: [organizer rfc822Email]];
}
- (BOOL) isLoggedInUserAnAttendee

View File

@ -1,4 +1,4 @@
{
{ /* -*-java-*- */
requires = ( MAIN );
publicResources = (
@ -12,29 +12,29 @@
methods = {
accept = {
protectedBy = "View";
actionClass = "UIxMailPartICalAction";
actionName = "markAccepted";
actionClass = "UIxMailPartICalActions";
actionName = "accept";
};
decline = {
protectedBy = "View";
actionClass = "UIxMailPartICalAction";
actionName = "markDeclined";
actionClass = "UIxMailPartICalActions";
actionName = "decline";
};
tentative = {
/* tentative = {
protectedBy = "View";
actionClass = "UIxMailPartICalAction";
actionClass = "UIxMailPartICalAction";
actionName = "markTentative";
};
addToCalendar = {
protectedBy = "View";
actionClass = "UIxMailPartICalAction";
actionClass = "UIxMailPartICalAction";
actionName = "addToCalendar";
};
deleteFromCalendar = {
protectedBy = "View";
actionClass = "UIxMailPartICalAction";
actionClass = "UIxMailPartICalAction";
actionName = "deleteFromCalendar";
};
}; */
};
};
};

View File

@ -785,6 +785,9 @@ function ICalendarButtonCallback(http) {
loadMessage(currentMessages[currentMailbox]);
}
}
else {
window.alert("received code: " + http.status);
}
}
function resizeMailContent() {