]> err.no Git - sope/blob - sope-ical/NGiCal/iCalDateHolder.m
numerous memory leaks fixed
[sope] / sope-ical / NGiCal / iCalDateHolder.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE 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
9   later version.
10
11   SOPE 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.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with SOPE; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 #include "iCalDateHolder.h"
23 #include "iCalObject.h"
24 #include "common.h"
25
26 @interface NSTimeZone(iCalTimeZone)
27
28 + (NSTimeZone *)timeZoneWithICalId:(NSString *)_tz;
29
30 @end
31
32 @implementation iCalDateHolder
33
34 static NSTimeZone *gmt = nil;
35
36 + (void)initialize {
37   if (gmt == nil)
38     gmt = [[NSTimeZone timeZoneWithName:@"GMT"] retain];
39 }
40
41 - (void)dealloc {
42   [self->tzid   release];
43   [self->string release];
44   [self->tag    release];
45   [super dealloc];
46 }
47
48 /* accessors */
49
50 - (void)setString:(NSString *)_value {
51   ASSIGNCOPY(self->string, _value);
52 }
53 - (NSString *)string {
54   return self->string;
55 }
56
57 - (void)setTag:(NSString *)_value {
58   ASSIGNCOPY(self->tag, _value);
59 }
60 - (NSString *)tag {
61   return self->tag;
62 }
63
64 - (void)setTzid:(NSString *)_value {
65   ASSIGNCOPY(self->tzid, _value);
66 }
67 - (NSString *)tzid {
68   return self->tzid;
69 }
70
71 /* mapping to Foundation */
72
73 - (NSTimeZone *)timeZone {
74   // TODO: lookup tzid in iCalCalendar !
75   NSString *s;
76
77   s = [self tzid];
78   
79   /* a hack */
80   if ([s hasPrefix:@"/softwarestudio.org"]) {
81     NSRange r;
82     
83     r = [s rangeOfString:@"Europe/"];
84     if (r.length > 0)
85       s = [s substringFromIndex:r.location];
86   }
87   return [NSTimeZone timeZoneWithICalId:s];
88 }
89
90 /* decoding */
91
92 - (id)awakeAfterUsingSaxDecoder:(id)_decoder {
93   NSCalendarDate *date = nil;
94   NSString   *s;
95   NSTimeZone *tz;
96   
97   s = self->string;
98   if ([s length] < 5) {
99     [self logWithFormat:@"tag %@: got an weird date string '%@' ?!", 
100             self->tag, s];
101     return s;
102   }
103   
104   /* calculate timezone */
105   
106   if ([self->string hasSuffix:@"Z"]) {
107     /* zulu time, eg 20021009T094500Z */
108     tz = gmt;
109     s = [s substringToIndex:([s length] - 1)];
110   }
111   else
112     tz = [self timeZone];
113   
114   /* 
115      012345678901234
116      20021009T094500 - 15 chars 
117      20021009T0945   - 13 chars 
118      991009T0945     - 11 chars
119      
120      20031111        - 8 chars
121   */
122   if ([s rangeOfString:@"T"].length == 0 && [s length] == 8) {
123     /* hm, maybe a date without a time? like an allday event! */
124     int year, month, day;
125     unsigned char buf[16];
126     [s getCString:&(buf[0])];
127     
128     buf[9] = '\0';
129     day    = atoi(&(buf[6]));  buf[6] = '\0';
130     month  = atoi(&(buf[4]));  buf[4] = '\0';
131     year   = atoi(&(buf[0]));
132     
133     date = [NSCalendarDate dateWithYear:year month:month day:day
134                            hour:0 minute:0 second:0
135                            timeZone:tz];
136   }
137   else if ([s length] == 15) {
138     int year, month, day, hour, minute, second;
139     unsigned char buf[24];
140     [s getCString:&(buf[0])];
141       
142     second = atoi(&(buf[13])); buf[13] = '\0';
143     minute = atoi(&(buf[11])); buf[11] = '\0';
144     hour   = atoi(&(buf[9]));  buf[9] = '\0';
145     day    = atoi(&(buf[6]));  buf[6] = '\0';
146     month  = atoi(&(buf[4]));  buf[4] = '\0';
147     year   = atoi(&(buf[0]));
148       
149     date = [NSCalendarDate dateWithYear:year month:month day:day
150                            hour:hour minute:minute second:second
151                            timeZone:tz];
152   }
153   else
154     NSLog(@"%s: unknown date format (%@) ???", __PRETTY_FUNCTION__, s);
155     
156   if (date == nil)
157     NSLog(@"couldn't convert string '%@' to date (format '%@') ..", s);
158
159   return date;
160 }
161
162 /* description */
163
164 - (NSString *)description {
165   NSMutableString *ms;
166
167   ms = [NSMutableString stringWithCapacity:128];
168   [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
169   
170   if (self->tag)    [ms appendFormat:@" %@",  self->tag];
171   if (self->string) [ms appendFormat:@" '%@'",  self->string];
172   if (self->tzid)   [ms appendFormat:@" tz=%@", self->tzid];
173   
174   [ms appendString:@">"];
175   return ms;
176 }
177
178 @end /* iCalDateHolder */
179
180 @implementation NSTimeZone(iCalTimeZone)
181
182 static NSMutableDictionary *idToTz = nil; // THREAD
183
184 + (NSTimeZone *)timeZoneWithICalId:(NSString *)_tzid {
185   static NSString *iCalDefaultTZ = nil;
186   NSTimeZone *tz;
187   
188   if (idToTz == nil)
189     idToTz = [[NSMutableDictionary alloc] initWithCapacity:16];
190   
191   if ([_tzid length] == 0) {
192     
193     tz = [iCalObject iCalDefaultTimeZone];
194     if (tz != nil) return tz;
195
196     if (iCalDefaultTZ == nil) {
197       NSString *defTz;
198       NSUserDefaults *ud;
199       // TODO: take a default timeZone
200       ud = [NSUserDefaults standardUserDefaults];
201       defTz = [ud stringForKey:@"iCalTimeZoneName"];
202       if ([defTz length] == 0)
203         defTz = [ud stringForKey:@"TimeZoneName"];
204       if ([defTz length] == 0)
205         defTz = [ud stringForKey:@"TimeZone"];
206       if ([defTz length] == 0)
207         defTz = @"GMT";
208       iCalDefaultTZ = [defTz retain];
209     }
210     
211     _tzid = iCalDefaultTZ;
212     
213   }
214   
215   if ([_tzid length] == 0)
216     _tzid = @"GMT";
217   
218   tz = [idToTz objectForKey:_tzid];
219   if (tz == nil) tz = [NSTimeZone timeZoneWithName:_tzid];
220   if (tz == nil) tz = [NSTimeZone timeZoneWithAbbreviation:_tzid];
221   
222   if (tz == nil) {
223     NSLog(@"couldn't map timezone id %@", _tzid);
224   }
225   
226   if (tz) [idToTz setObject:tz forKey:_tzid];
227   return tz;
228 }
229
230 @end /* NSTimeZone(iCalTimeZone) */