2 Copyright (C) 2004 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
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
22 #include "UIxComponent.h"
23 #include "SOGoJSStringFormatter.h"
25 #include <NGObjWeb/SoHTTPAuthenticator.h>
27 @interface UIxComponent (PrivateAPI)
28 - (void)_parseQueryString:(NSString *)_s;
29 - (NSMutableDictionary *)_queryParameters;
32 @implementation UIxComponent
34 static NSTimeZone *MET = nil;
35 static NSTimeZone *GMT = nil;
37 static NSMutableArray *dayLabelKeys = nil;
38 static NSMutableArray *abbrDayLabelKeys = nil;
39 static NSMutableArray *monthLabelKeys = nil;
40 static NSMutableArray *abbrMonthLabelKeys = nil;
42 static BOOL uixDebugEnabled = NO;
45 return [super version] + 0 /* v2 */;
49 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
51 NSAssert2([super version] == 2,
52 @"invalid superclass (%@) version %i !",
53 NSStringFromClass([self superclass]), [super version]);
55 uixDebugEnabled = [ud boolForKey:@"SOGoUIxDebugEnabled"];
58 MET = [[NSTimeZone timeZoneWithAbbreviation:@"MET"] retain];
59 GMT = [[NSTimeZone timeZoneWithAbbreviation:@"GMT"] retain];
61 if (dayLabelKeys == nil) {
62 dayLabelKeys = [[NSMutableArray alloc] initWithCapacity:7];
63 [dayLabelKeys addObject:@"Sunday"];
64 [dayLabelKeys addObject:@"Monday"];
65 [dayLabelKeys addObject:@"Tuesday"];
66 [dayLabelKeys addObject:@"Wednesday"];
67 [dayLabelKeys addObject:@"Thursday"];
68 [dayLabelKeys addObject:@"Friday"];
69 [dayLabelKeys addObject:@"Saturday"];
71 abbrDayLabelKeys = [[NSMutableArray alloc] initWithCapacity:7];
72 [abbrDayLabelKeys addObject:@"a2_Sunday"];
73 [abbrDayLabelKeys addObject:@"a2_Monday"];
74 [abbrDayLabelKeys addObject:@"a2_Tuesday"];
75 [abbrDayLabelKeys addObject:@"a2_Wednesday"];
76 [abbrDayLabelKeys addObject:@"a2_Thursday"];
77 [abbrDayLabelKeys addObject:@"a2_Friday"];
78 [abbrDayLabelKeys addObject:@"a2_Saturday"];
80 monthLabelKeys = [[NSMutableArray alloc] initWithCapacity:12];
81 [monthLabelKeys addObject:@"January"];
82 [monthLabelKeys addObject:@"February"];
83 [monthLabelKeys addObject:@"March"];
84 [monthLabelKeys addObject:@"April"];
85 [monthLabelKeys addObject:@"May"];
86 [monthLabelKeys addObject:@"June"];
87 [monthLabelKeys addObject:@"July"];
88 [monthLabelKeys addObject:@"August"];
89 [monthLabelKeys addObject:@"September"];
90 [monthLabelKeys addObject:@"October"];
91 [monthLabelKeys addObject:@"November"];
92 [monthLabelKeys addObject:@"December"];
94 abbrMonthLabelKeys = [[NSMutableArray alloc] initWithCapacity:12];
95 [abbrMonthLabelKeys addObject:@"a3_January"];
96 [abbrMonthLabelKeys addObject:@"a3_February"];
97 [abbrMonthLabelKeys addObject:@"a3_March"];
98 [abbrMonthLabelKeys addObject:@"a3_April"];
99 [abbrMonthLabelKeys addObject:@"a3_May"];
100 [abbrMonthLabelKeys addObject:@"a3_June"];
101 [abbrMonthLabelKeys addObject:@"a3_July"];
102 [abbrMonthLabelKeys addObject:@"a3_August"];
103 [abbrMonthLabelKeys addObject:@"a3_September"];
104 [abbrMonthLabelKeys addObject:@"a3_October"];
105 [abbrMonthLabelKeys addObject:@"a3_November"];
106 [abbrMonthLabelKeys addObject:@"a3_December"];
111 [self->queryParameters release];
115 /* query parameters */
117 - (void)_parseQueryString:(NSString *)_s {
121 e = [[_s componentsSeparatedByString:@"&"] objectEnumerator];
122 while ((part = [e nextObject]) != nil) {
124 NSString *key, *value;
126 r = [part rangeOfString:@"="];
128 /* missing value of query parameter */
129 key = [part stringByUnescapingURL];
133 key = [[part substringToIndex:r.location] stringByUnescapingURL];
134 value = [[part substringFromIndex:(r.location + r.length)]
135 stringByUnescapingURL];
137 [self->queryParameters setObject:value forKey:key];
140 - (void)addKeepAliveFormValuesToQueryParameters {
143 - (NSString *)queryParameterForKey:(NSString *)_key {
144 return [[self _queryParameters] objectForKey:_key];
147 - (void)setQueryParameter:(NSString *)_param forKey:(NSString *)_key {
152 [[self _queryParameters] setObject:_param forKey:_key];
154 [[self _queryParameters] removeObjectForKey:_key];
157 - (NSMutableDictionary *)_queryParameters {
158 // TODO: this code is weird, should use WORequest methods for parsing
163 if (self->queryParameters)
164 return self->queryParameters;
166 self->queryParameters = [[NSMutableDictionary alloc] initWithCapacity:8];
168 req = [[self context] request];
170 r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
174 qs = [uri substringFromIndex:NSMaxRange(r)];
175 [self _parseQueryString:qs];
178 /* add form values */
179 [self addKeepAliveFormValuesToQueryParameters];
181 return self->queryParameters;
184 - (NSDictionary *)queryParameters {
185 return [self _queryParameters];
188 - (NSDictionary *)queryParametersBySettingSelectedDate:(NSCalendarDate *)_date{
189 NSMutableDictionary *qp;
191 qp = [[self queryParameters] mutableCopy];
192 [self setSelectedDateQueryParameter:_date inDictionary:qp];
193 return [qp autorelease];
196 - (void)setSelectedDateQueryParameter:(NSCalendarDate *)_newDate
197 inDictionary:(NSMutableDictionary *)_qp;
200 [_qp setObject:[self dateStringForDate:_newDate] forKey:@"day"];
202 [_qp removeObjectForKey:@"day"];
205 - (NSString *)completeHrefForMethod:(NSString *)_method {
210 qp = [self queryParameters];
214 ctx = [self context];
215 qps = [ctx queryPathSeparator];
216 [ctx setQueryPathSeparator:@"&"];
217 qs = [ctx queryStringFromDictionary:qp];
218 [ctx setQueryPathSeparator:qps];
219 return [_method stringByAppendingFormat:@"?%@", qs];
222 - (NSString *)ownMethodName {
226 uri = [[[self context] request] uri];
228 /* first: cut off query parameters */
230 r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
232 uri = [uri substringToIndex:r.location];
234 /* next: strip trailing slash */
236 if ([uri hasSuffix:@"/"]) uri = [uri substringToIndex:([uri length] - 1)];
237 r = [uri rangeOfString:@"/" options:NSBackwardsSearch];
239 /* then: cut of last path component */
241 if (r.length == 0) // no slash? are we at root?
244 return [uri substringFromIndex:(r.location + 1)];
247 - (NSString *)userFolderPath {
249 NSArray *traversalObjects;
253 ctx = [self context];
254 traversalObjects = [ctx objectTraversalStack];
255 url = [[traversalObjects objectAtIndex:0]
256 baseURLInContext:ctx];
257 path = [[NSURL URLWithString:url] path];
258 path = [path stringByAppendingPathComponent:[[ctx activeUser] login]];
262 - (NSString *)ownPath {
266 uri = [[[self context] request] uri];
268 /* first: cut off query parameters */
270 r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
272 uri = [uri substringToIndex:r.location];
276 - (NSString *)relativePathToUserFolderSubPath:(NSString *)_sub {
279 dst = [[self userFolderPath] stringByAppendingPathComponent:_sub];
280 rel = [dst urlPathRelativeToPath:[self ownPath]];
286 - (NSTimeZone *)viewTimeZone {
287 // Note: also in the folder, should be based on a cookie?
291 - (NSTimeZone *)backendTimeZone {
295 - (NSCalendarDate *)selectedDate {
297 NSCalendarDate *cdate;
299 s = [self queryParameterForKey:@"day"];
300 cdate = ([s length] > 0)
301 ? [self dateForDateString:s]
302 : [NSCalendarDate date];
303 [cdate setTimeZone:[self viewTimeZone]];
304 s = [self queryParameterForKey:@"hm"];
305 if([s length] == 4) {
306 unsigned hour, minute;
308 hour = [[s substringToIndex:2] unsignedIntValue];
309 minute = [[s substringFromIndex:2] unsignedIntValue];
310 cdate = [cdate hour:hour minute:minute];
313 cdate = [cdate hour:12 minute:0];
318 - (NSString *)dateStringForDate:(NSCalendarDate *)_date {
319 [_date setTimeZone:[self viewTimeZone]];
320 return [_date descriptionWithCalendarFormat:@"%Y%m%d"];
323 - (NSCalendarDate *)dateForDateString:(NSString *)_dateString {
324 return [NSCalendarDate dateWithString:_dateString
325 calendarFormat:@"%Y%m%d"];
334 ctx = [self context];
335 return [[[self clientObject] authenticatorInContext:ctx] userInContext:ctx];
338 - (NSString *)shortUserNameForDisplay {
339 // TODO: better use a SoUser formatter?
340 // TODO: who calls that?
344 // TODO: USE USER MANAGER INSTEAD!
346 s = [[self user] login];
350 // TODO: algorithm might be inappropriate, depends on the actual UID
352 r = [s rangeOfString:@"."];
356 return [s substringToIndex:r.location];
361 - (NSString *)labelForKey:(NSString *)_str {
362 WOResourceManager *rm;
365 NSString *lKey, *lTable, *lVal;
368 if ([_str length] == 0)
371 /* lookup languages */
373 languages = [[self context] resourceLookupLanguages];
375 /* find resource manager */
377 if ((rm = [self resourceManager]) == nil)
378 rm = [[WOApplication application] resourceManager];
380 [self warnWithFormat:@"missing resource manager!"];
384 r = [_str rangeOfString:@"/"];
386 lTable = [_str substringToIndex:r.location];
387 lKey = [_str substringFromIndex:(r.location + r.length)];
395 if ([lKey hasPrefix:@"$"])
396 lKey = [self valueForKeyPath:[lKey substringFromIndex:1]];
398 if ([lTable hasPrefix:@"$"])
399 lTable = [self valueForKeyPath:[lTable substringFromIndex:1]];
402 if ([lVal hasPrefix:@"$"])
403 lVal = [self valueForKeyPath:[lVal substringFromIndex:1]];
409 label = [rm stringForKey:lKey inTableNamed:lTable withDefaultValue:lVal
410 languages:languages];
414 - (NSString *)localizedNameForDayOfWeek:(unsigned)_dayOfWeek {
415 NSString *key = [dayLabelKeys objectAtIndex:_dayOfWeek % 7];
416 return [self labelForKey:key];
419 - (NSString *)localizedAbbreviatedNameForDayOfWeek:(unsigned)_dayOfWeek {
420 NSString *key = [abbrDayLabelKeys objectAtIndex:_dayOfWeek % 7];
421 return [self labelForKey:key];
424 - (NSString *)localizedNameForMonthOfYear:(unsigned)_monthOfYear {
425 NSString *key = [monthLabelKeys objectAtIndex:(_monthOfYear - 1) % 12];
426 return [self labelForKey:key];
429 - (NSString *)localizedAbbreviatedNameForMonthOfYear:(unsigned)_monthOfYear {
430 NSString *key = [abbrMonthLabelKeys objectAtIndex:(_monthOfYear - 1) % 12];
431 return [self labelForKey:key];
434 /* HTTP method safety */
436 - (BOOL)isInvokedBySafeMethod {
437 // TODO: move to WORequest?
440 m = [[[self context] request] method];
441 if ([m isEqualToString:@"GET"]) return YES;
442 if ([m isEqualToString:@"HEAD"]) return YES;
448 - (NSDictionary *)locale {
449 /* we need no fallback here, as locale is guaranteed to be set by sogod */
450 return [[self context] valueForKey:@"locale"];
455 - (BOOL)isUIxDebugEnabled {
456 return uixDebugEnabled;
459 @end /* UIxComponent */