]> err.no Git - scalable-opengroupware.org/blob - SOGo/UI/SOGoUI/UIxComponent.m
lots of improvements
[scalable-opengroupware.org] / SOGo / UI / SOGoUI / UIxComponent.m
1 /*
2   Copyright (C) 2004 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
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
9   later version.
10
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.
15
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
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #include "UIxComponent.h"
24 #include "common.h"
25 #include <NGObjWeb/SoHTTPAuthenticator.h>
26
27 @interface UIxComponent (PrivateAPI)
28 - (void)_parseQueryString:(NSString *)_s;
29 @end
30
31 @implementation UIxComponent
32
33 static NSTimeZone *MET = nil;
34 static NSTimeZone *GMT = nil;
35
36 static NSMutableArray *dayLabelKeys       = nil;
37 static NSMutableArray *abbrDayLabelKeys   = nil;
38 static NSMutableArray *monthLabelKeys     = nil;
39 static NSMutableArray *abbrMonthLabelKeys = nil;
40
41 static BOOL uixDebugEnabled = NO;
42
43 + (void)initialize {
44   NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
45     
46   uixDebugEnabled = [ud boolForKey:@"SOGoUIxDebugEnabled"];
47
48   if (MET == nil) {
49     MET = [[NSTimeZone timeZoneWithAbbreviation:@"MET"] retain];
50     GMT = [[NSTimeZone timeZoneWithAbbreviation:@"GMT"] retain];
51   }
52   if (dayLabelKeys == nil) {
53     dayLabelKeys = [[NSMutableArray alloc] initWithCapacity:7];
54     [dayLabelKeys addObject:@"Sunday"];
55     [dayLabelKeys addObject:@"Monday"];
56     [dayLabelKeys addObject:@"Tuesday"];
57     [dayLabelKeys addObject:@"Wednesday"];
58     [dayLabelKeys addObject:@"Thursday"];
59     [dayLabelKeys addObject:@"Friday"];
60     [dayLabelKeys addObject:@"Saturday"];
61
62     abbrDayLabelKeys = [[NSMutableArray alloc] initWithCapacity:7];
63     [abbrDayLabelKeys addObject:@"a2_Sunday"];
64     [abbrDayLabelKeys addObject:@"a2_Monday"];
65     [abbrDayLabelKeys addObject:@"a2_Tuesday"];
66     [abbrDayLabelKeys addObject:@"a2_Wednesday"];
67     [abbrDayLabelKeys addObject:@"a2_Thursday"];
68     [abbrDayLabelKeys addObject:@"a2_Friday"];
69     [abbrDayLabelKeys addObject:@"a2_Saturday"];
70
71     monthLabelKeys = [[NSMutableArray alloc] initWithCapacity:12];
72     [monthLabelKeys addObject:@"January"];
73     [monthLabelKeys addObject:@"February"];
74     [monthLabelKeys addObject:@"March"];
75     [monthLabelKeys addObject:@"April"];
76     [monthLabelKeys addObject:@"May"];
77     [monthLabelKeys addObject:@"June"];
78     [monthLabelKeys addObject:@"July"];
79     [monthLabelKeys addObject:@"August"];
80     [monthLabelKeys addObject:@"September"];
81     [monthLabelKeys addObject:@"October"];
82     [monthLabelKeys addObject:@"November"];
83     [monthLabelKeys addObject:@"December"];
84
85     abbrMonthLabelKeys = [[NSMutableArray alloc] initWithCapacity:12];
86     [abbrMonthLabelKeys addObject:@"a3_January"];
87     [abbrMonthLabelKeys addObject:@"a3_February"];
88     [abbrMonthLabelKeys addObject:@"a3_March"];
89     [abbrMonthLabelKeys addObject:@"a3_April"];
90     [abbrMonthLabelKeys addObject:@"a3_May"];
91     [abbrMonthLabelKeys addObject:@"a3_June"];
92     [abbrMonthLabelKeys addObject:@"a3_July"];
93     [abbrMonthLabelKeys addObject:@"a3_August"];
94     [abbrMonthLabelKeys addObject:@"a3_September"];
95     [abbrMonthLabelKeys addObject:@"a3_October"];
96     [abbrMonthLabelKeys addObject:@"a3_November"];
97     [abbrMonthLabelKeys addObject:@"a3_December"];
98   }
99 }
100
101 - (id)init {
102   if ((self = [super init])) {
103     self->queryParameters = [[NSMutableDictionary alloc] initWithCapacity:8];
104   }
105   return self;
106 }
107
108 - (void)dealloc {
109   [self->queryParameters release];
110   [super dealloc];
111 }
112
113 /* notifications */
114
115 - (void)awake {
116   WORequest *req;
117   NSString  *uri;
118   NSRange   r;
119
120   [super awake];
121
122   req = [[self context] request];
123   uri = [req uri];
124   r   = [uri rangeOfString:@"?"];
125   if (r.length > 0) {
126     NSString *qs;
127     
128     qs = [uri substringFromIndex:(r.location + r.length)];
129     [self->queryParameters removeAllObjects];
130     [self _parseQueryString:qs];
131   }    
132 }
133
134 /* query parameters */
135
136 - (void)_parseQueryString:(NSString *)_s {
137   NSEnumerator *e;
138   NSString *part;
139     
140   e = [[_s componentsSeparatedByString:@"&"] objectEnumerator];
141   while ((part = [e nextObject])) {
142     NSRange  r;
143     NSString *key, *value;
144         
145     r = [part rangeOfString:@"="];
146     if (r.length == 0) {
147       /* missing value of query parameter */
148       key   = [part stringByUnescapingURL];
149       value = @"1";
150     }
151     else {
152       key   = [[part substringToIndex:r.location] stringByUnescapingURL];
153       value = [[part substringFromIndex:(r.location + r.length)] 
154                 stringByUnescapingURL];
155     }
156     [self->queryParameters setObject:value forKey:key];
157   }
158 }
159
160 - (NSString *)queryParameterForKey:(NSString *)_key {
161   return [self->queryParameters objectForKey:_key];
162 }
163
164 - (void)setQueryParameter:(NSString *)_param forKey:(NSString *)_key {
165   if(_key == nil)
166     return;
167
168   if(_param != nil)
169     [self->queryParameters setObject:_param forKey:_key];
170   else
171     [self->queryParameters removeObjectForKey:_key];
172 }
173
174 - (NSDictionary *)queryParameters {
175   return self->queryParameters;
176 }
177
178 - (NSDictionary *)queryParametersBySettingSelectedDate:(NSCalendarDate *)_date{
179   NSMutableDictionary *qp;
180     
181   qp = [[self queryParameters] mutableCopy];
182   [self setSelectedDateQueryParameter:_date inDictionary:qp];
183   return [qp autorelease];
184 }
185
186 - (void)setSelectedDateQueryParameter:(NSCalendarDate *)_newDate
187                          inDictionary:(NSMutableDictionary *)_qp;
188 {
189   if(_newDate != nil)
190     [_qp setObject:[self dateStringForDate:_newDate] forKey:@"day"];
191   else
192     [_qp removeObjectForKey:@"day"];
193 }
194
195 - (NSString *)completeHrefForMethod:(NSString *)_method {
196   NSDictionary *qp;
197   NSString *qs;
198     
199   qp = [self queryParameters];
200   if([qp count] == 0)
201     return _method;
202     
203   qs = [[self context] queryStringFromDictionary:qp];
204   return [_method stringByAppendingFormat:@"?%@", qs];
205 }
206
207 - (NSString *)ownMethodName {
208   NSString *uri;
209   NSRange  r;
210     
211   uri = [[[self context] request] uri];
212     
213   /* first: cut off query parameters */
214     
215   r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
216   if (r.length > 0)
217     uri = [uri substringToIndex:r.location];
218     
219   /* next: strip trailing slash */
220     
221   if ([uri hasSuffix:@"/"]) uri = [uri substringToIndex:([uri length] - 1)];
222   r = [uri rangeOfString:@"/" options:NSBackwardsSearch];
223     
224   /* then: cut of last path component */
225     
226   if (r.length == 0) // no slash? are we at root?
227     return @"/";
228     
229   return [uri substringFromIndex:(r.location + 1)];
230 }
231
232 - (NSString *)userFolderPath {
233   WOContext *ctx;
234   NSArray   *traversalObjects;
235   NSString  *url;
236   
237   ctx = [self context];
238   traversalObjects = [ctx objectTraversalStack];
239   url = [[traversalObjects objectAtIndex:1]
240                            baseURLInContext:ctx];
241   return [[NSURL URLWithString:url] path];
242 }
243
244 - (NSString *)ownPath {
245   NSString *uri;
246   NSRange  r;
247   
248   uri = [[[self context] request] uri];
249   
250   /* first: cut off query parameters */
251   
252   r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
253   if (r.length > 0)
254     uri = [uri substringToIndex:r.location];
255   return uri;
256 }
257
258 - (NSString *)relativePathToUserFolderSubPath:(NSString *)_sub {
259   NSString *dst, *rel;
260
261   dst = [[self userFolderPath] stringByAppendingPathComponent:_sub];
262   rel = [dst urlPathRelativeToPath:[self ownPath]];
263   return rel;
264 }
265   
266 /* date */
267
268 - (NSTimeZone *)viewTimeZone {
269   // Note: also in the folder, should be based on a cookie?
270   return MET;
271 }
272
273 - (NSTimeZone *)backendTimeZone {
274   return GMT;
275 }
276
277 - (NSCalendarDate *)selectedDate {
278   NSString       *s;
279   NSCalendarDate *cdate;
280
281   s = [self queryParameterForKey:@"day"];
282   cdate = ([s length] > 0)
283     ? [self dateForDateString:s]
284     : [NSCalendarDate date];
285   [cdate setTimeZone:[self viewTimeZone]];
286   s = [self queryParameterForKey:@"hm"];
287   if([s length] == 4) {
288     unsigned hour, minute;
289       
290     hour = [[s substringToIndex:2] unsignedIntValue];
291     minute = [[s substringFromIndex:2] unsignedIntValue];
292     cdate = [cdate hour:hour minute:minute];
293   }
294   else {
295     cdate = [cdate hour:12 minute:0];
296   }
297   return cdate;
298 }
299
300 - (NSString *)dateStringForDate:(NSCalendarDate *)_date {
301   [_date setTimeZone:[self viewTimeZone]];
302   return [_date descriptionWithCalendarFormat:@"%Y%m%d"];
303 }
304
305 - (NSCalendarDate *)dateForDateString:(NSString *)_dateString {
306   return [NSCalendarDate dateWithString:_dateString 
307                          calendarFormat:@"%Y%m%d"];
308 }
309
310
311 /* SoUser */
312
313 - (SoUser *)user {
314   WOContext *ctx;
315   
316   ctx = [self context];
317   return [[[self clientObject] authenticatorInContext:ctx] userInContext:ctx];
318 }
319
320 - (NSString *)shortUserNameForDisplay {
321   // TODO: better use a SoUser formatter?
322   NSString *s;
323   NSRange  r;
324
325 #warning !! USE USER MANAGER INSTEAD!
326
327   s = [[self user] login];
328   if ([s length] < 10)
329     return s;
330     
331   // TODO: algorithm might be inappropriate, depends on the actual UID
332     
333   r = [s rangeOfString:@"."];
334   if (r.length == 0)
335     return s;
336     
337   return [s substringToIndex:r.location];
338 }
339
340 /* labels */
341
342 - (NSString *)labelForKey:(NSString *)_str {
343   WOResourceManager *rm;
344   NSArray           *languages;
345   WOContext         *ctx;
346   NSString          *label;
347   NSString          *lKey, *lTable, *lVal;
348   NSRange r;
349
350   if ([_str length] == 0) {
351     return nil;
352   }
353     
354   /* lookup languages */
355     
356   ctx = [self context];
357   languages = [ctx hasSession]
358     ? [[ctx session] languages]
359     : [[ctx request] browserLanguages];
360     
361   /* find resource manager */
362     
363   if ((rm = [self resourceManager]) == nil)
364     rm = [[WOApplication application] resourceManager];
365   if (rm == nil)
366     [self debugWithFormat:@"WARNING: missing resource manager!"];
367     
368   /* get parameters */
369     
370   r = [_str rangeOfString:@"/"];
371   if (r.length > 0) {
372     lTable = [_str substringToIndex:r.location];
373     lKey   = [_str substringFromIndex:(r.location + r.length)];
374   }
375   else {
376     lTable = nil;
377     lKey   = _str;
378   }
379   lVal = lKey;
380
381   if([lKey hasPrefix:@"$"]) {
382     lKey = [self valueForKeyPath:[lKey substringFromIndex:1]];
383   }
384   if([lTable hasPrefix:@"$"]) {
385     lTable = [self valueForKeyPath:[lTable substringFromIndex:1]];
386   }
387 #if 0
388   if([lVal hasPrefix:@"$"]) {
389     lVal = [self valueForKeyPath:[lVal substringFromIndex:1]];
390   }
391 #endif
392   /* lookup string */
393     
394   label = [rm stringForKey:lKey inTableNamed:lTable withDefaultValue:lVal
395               languages:languages];
396   return label;
397 }
398
399 - (NSString *)localizedNameForDayOfWeek:(unsigned)_dayOfWeek {
400   NSString *key =  [dayLabelKeys objectAtIndex:_dayOfWeek % 7];
401   return [self labelForKey:key];
402 }
403
404 - (NSString *)localizedAbbreviatedNameForDayOfWeek:(unsigned)_dayOfWeek {
405   NSString *key =  [abbrDayLabelKeys objectAtIndex:_dayOfWeek % 7];
406   return [self labelForKey:key];
407 }
408
409 - (NSString *)localizedNameForMonthOfYear:(unsigned)_monthOfYear {
410   NSString *key =  [monthLabelKeys objectAtIndex:(_monthOfYear - 1) % 12];
411   return [self labelForKey:key];
412 }
413
414 - (NSString *)localizedAbbreviatedNameForMonthOfYear:(unsigned)_monthOfYear {
415   NSString *key =  [abbrMonthLabelKeys objectAtIndex:(_monthOfYear - 1) % 12];
416   return [self labelForKey:key];
417 }
418
419 /* locale */
420
421 - (NSDictionary *)locale {
422   /* we need no fallback here, as locale is guaranteed to be set by sogod */
423   return [[self context] valueForKey:@"locale"];
424 }
425
426 /* debugging */
427
428 - (BOOL)isUIxDebugEnabled {
429   return uixDebugEnabled;
430 }
431
432 @end /* UIxComponent */