2 Copyright (C) 2000-2004 SKYRIX Software AG
4 This file is part of OGo
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 #include <Common/UIxComponent.h>
26 #include <SOGoLogic/SOGoAppointment.h>
27 #include <NGiCal/NGiCal.h>
30 /* TODO: CLEAN THIS MESS UP */
33 @interface NSObject (AppointmentHack)
34 - (BOOL)isAppointment;
37 @implementation NSObject (AppointmentHack)
38 - (BOOL)isAppointment {
39 return [self isKindOfClass:NSClassFromString(@"SxAppointment")];
43 @interface iCalPerson (Convenience)
44 - (NSString *)rfc822Email;
47 @implementation iCalPerson (Convenience)
48 - (NSString *)rfc822Email {
49 NSString *_email = [self email];
50 NSRange colon = [_email rangeOfString:@":"];
51 if(colon.location != NSNotFound) {
52 return [_email substringFromIndex:colon.location + 1];
58 @interface UIxAppointmentEditor : UIxComponent
64 - (SOGoAppointment *)appointment;
65 - (NSString *)iCalStringTemplate;
66 - (NSString *)iCalString;
67 - (BOOL)isNewAppointment;
71 @implementation UIxAppointmentEditor
74 [self->appointment release];
75 [self->participants release];
83 - (NSString *)formattedAptStartTime {
86 date = [[self appointment] startDate];
87 /* TODO: convert this into display timeZone! */
88 return [date descriptionWithCalendarFormat:@"%A, %Y-%m-%d %H:%M %Z"];
91 - (BOOL)isNewAppointment {
92 return ! [[self clientObject] isAppointment];
95 - (NSString *)iCalString {
96 if([self isNewAppointment]) {
97 return [self iCalStringTemplate];
100 return [[self clientObject] valueForKey:@"iCalString"];
104 - (NSString *)iCalStringTemplate {
105 static NSString *iCalStringTemplate = \
106 @"BEGIN:VCALENDAR\nMETHOD:REQUEST\nPRODID:OpenGroupware.org ZideStore 1.2\n" \
107 @"VERSION:2.0\nBEGIN:VEVENT\nCLASS:PRIVATE\nSTATUS:CONFIRMED\n" \
108 @"DTSTART:%@\nDTEND:%@\n" \
110 @"END:VEVENT\nEND:VCALENDAR";
111 NSCalendarDate *startDate, *endDate;
114 startDate = [self selectedDate];
115 endDate = [startDate dateByAddingYears:0 months:0 days:0
116 hours:1 minutes:0 seconds:0];
118 template = [NSString stringWithFormat:iCalStringTemplate,
119 [startDate icalString],
120 [endDate icalString]];
129 - (SOGoAppointment *)appointment {
130 if(self->appointment == nil) {
131 self->appointment = [[SOGoAppointment alloc]
132 initWithICalString:[self iCalString]];
134 return self->appointment;
138 if(self->participants == nil) {
140 NSMutableArray *emailAddresses;
143 attendees = [self->appointment attendees];
144 count = [attendees count];
145 emailAddresses = [[NSMutableArray alloc] initWithCapacity:count];
146 for(i = 0; i < count; i++) {
149 email = [[attendees objectAtIndex:i] rfc822Email];
151 [emailAddresses addObject:email];
153 self->participants = [[emailAddresses componentsJoinedByString:@"\n"]
155 [emailAddresses release];
157 return self->participants;
163 - (NSString *)uriAsFormat {
167 uri = [[[self context] request] uri];
169 /* first: identify query parameters */
170 r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
172 uri = [uri substringToIndex:r.location];
173 qp = [uri substringFromIndex:r.location];
179 /* next: strip trailing slash */
180 if([uri hasSuffix:@"/"])
181 uri = [uri substringToIndex:([uri length] - 1)];
182 r = [uri rangeOfString:@"/" options:NSBackwardsSearch];
184 /* then: cut of last path component */
185 if(r.location == NSNotFound) { // no slash? are we at root?
189 uri = [uri substringToIndex:(r.location + 1)];
191 /* next: append format token */
192 uri = [uri stringByAppendingString:@"%@"];
194 uri = [uri stringByAppendingString:qp];
203 SOGoAppointment *apt;
204 NSString *iCalString, *summary, *location, *nextMethod, *uri, *uriFormat;
205 NSCalendarDate *sd, *ed;
211 req = [[self context] request];
213 /* get iCalString from hidden input */
214 iCalString = [req formValueForKey:@"ical"];
215 apt = [[SOGoAppointment alloc] initWithICalString:iCalString];
217 /* merge in form values */
218 sd = [NSCalendarDate dateWithString:[req formValueForKey:@"startDate"]
219 calendarFormat:@"%Y-%m-%d %H:%M"];
220 [apt setStartDate:sd];
221 ed = [NSCalendarDate dateWithString:[req formValueForKey:@"endDate"]
222 calendarFormat:@"%Y-%m-%d %H:%M"];
224 summary = [req formValueForKey:@"summary"];
225 [apt setSummary:title];
226 location = [req formValueForKey:@"location"];
227 [apt setLocation:location];
229 [apt removeAllAttendees]; /* clean up */
230 ps = [[req formValueForKey:@"participants"]
231 componentsSeparatedByString:@"\n"];
233 for(i = 0; i < count; i++) {
236 email = [ps objectAtIndex:i];
237 if([email length] > 0) {
241 p = [[iCalPerson alloc] init];
242 [p setEmail:[NSString stringWithFormat:@"mailto:%@", email]];
243 /* construct a fake CN */
244 cnr = [email rangeOfString:@"@"];
245 if(cnr.location != NSNotFound) {
246 [p setCn:[email substringToIndex:cnr.location]];
248 [apt addToAttendees:p];
253 /* receive current representation for save operation */
254 iCalString = [apt iCalString];
258 /* determine what's to do and where to go next */
259 if([self isNewAppointment]) {
260 nextMethod = @"duhduh";
263 nextMethod = @"view";
266 NSLog(@"%s new iCalString:\n%@", __PRETTY_FUNCTION__, iCalString);
268 uriFormat = [self uriAsFormat];
269 uri = [NSString stringWithFormat:uriFormat, nextMethod];
271 r = [WOResponse responseWithRequest:req];
272 [r setStatus:302 /* moved */];
273 [r setHeader:uri forKey:@"location"];