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 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
47 uixDebugEnabled = [ud boolForKey:@"SOGoUIxDebugEnabled"];
50 MET = [[NSTimeZone timeZoneWithAbbreviation:@"MET"] retain];
51 GMT = [[NSTimeZone timeZoneWithAbbreviation:@"GMT"] retain];
53 if (dayLabelKeys == nil) {
54 dayLabelKeys = [[NSMutableArray alloc] initWithCapacity:7];
55 [dayLabelKeys addObject:@"Sunday"];
56 [dayLabelKeys addObject:@"Monday"];
57 [dayLabelKeys addObject:@"Tuesday"];
58 [dayLabelKeys addObject:@"Wednesday"];
59 [dayLabelKeys addObject:@"Thursday"];
60 [dayLabelKeys addObject:@"Friday"];
61 [dayLabelKeys addObject:@"Saturday"];
63 abbrDayLabelKeys = [[NSMutableArray alloc] initWithCapacity:7];
64 [abbrDayLabelKeys addObject:@"a2_Sunday"];
65 [abbrDayLabelKeys addObject:@"a2_Monday"];
66 [abbrDayLabelKeys addObject:@"a2_Tuesday"];
67 [abbrDayLabelKeys addObject:@"a2_Wednesday"];
68 [abbrDayLabelKeys addObject:@"a2_Thursday"];
69 [abbrDayLabelKeys addObject:@"a2_Friday"];
70 [abbrDayLabelKeys addObject:@"a2_Saturday"];
72 monthLabelKeys = [[NSMutableArray alloc] initWithCapacity:12];
73 [monthLabelKeys addObject:@"January"];
74 [monthLabelKeys addObject:@"February"];
75 [monthLabelKeys addObject:@"March"];
76 [monthLabelKeys addObject:@"April"];
77 [monthLabelKeys addObject:@"May"];
78 [monthLabelKeys addObject:@"June"];
79 [monthLabelKeys addObject:@"July"];
80 [monthLabelKeys addObject:@"August"];
81 [monthLabelKeys addObject:@"September"];
82 [monthLabelKeys addObject:@"October"];
83 [monthLabelKeys addObject:@"November"];
84 [monthLabelKeys addObject:@"December"];
86 abbrMonthLabelKeys = [[NSMutableArray alloc] initWithCapacity:12];
87 [abbrMonthLabelKeys addObject:@"a3_January"];
88 [abbrMonthLabelKeys addObject:@"a3_February"];
89 [abbrMonthLabelKeys addObject:@"a3_March"];
90 [abbrMonthLabelKeys addObject:@"a3_April"];
91 [abbrMonthLabelKeys addObject:@"a3_May"];
92 [abbrMonthLabelKeys addObject:@"a3_June"];
93 [abbrMonthLabelKeys addObject:@"a3_July"];
94 [abbrMonthLabelKeys addObject:@"a3_August"];
95 [abbrMonthLabelKeys addObject:@"a3_September"];
96 [abbrMonthLabelKeys addObject:@"a3_October"];
97 [abbrMonthLabelKeys addObject:@"a3_November"];
98 [abbrMonthLabelKeys addObject:@"a3_December"];
103 [self->queryParameters release];
107 /* query parameters */
109 - (void)_parseQueryString:(NSString *)_s {
113 e = [[_s componentsSeparatedByString:@"&"] objectEnumerator];
114 while ((part = [e nextObject])) {
116 NSString *key, *value;
118 r = [part rangeOfString:@"="];
120 /* missing value of query parameter */
121 key = [part stringByUnescapingURL];
125 key = [[part substringToIndex:r.location] stringByUnescapingURL];
126 value = [[part substringFromIndex:(r.location + r.length)]
127 stringByUnescapingURL];
129 [self->queryParameters setObject:value forKey:key];
133 - (NSString *)queryParameterForKey:(NSString *)_key {
134 return [[self _queryParameters] objectForKey:_key];
137 - (void)setQueryParameter:(NSString *)_param forKey:(NSString *)_key {
142 [[self _queryParameters] setObject:_param forKey:_key];
144 [[self _queryParameters] removeObjectForKey:_key];
147 - (NSMutableDictionary *)_queryParameters {
148 if(!self->queryParameters) {
153 self->queryParameters = [[NSMutableDictionary alloc] initWithCapacity:8];
155 req = [[self context] request];
157 r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
161 qs = [uri substringFromIndex:NSMaxRange(r)];
162 [self _parseQueryString:qs];
165 return self->queryParameters;
168 - (NSDictionary *)queryParameters {
169 return [self _queryParameters];
172 - (NSDictionary *)queryParametersBySettingSelectedDate:(NSCalendarDate *)_date{
173 NSMutableDictionary *qp;
175 qp = [[self queryParameters] mutableCopy];
176 [self setSelectedDateQueryParameter:_date inDictionary:qp];
177 return [qp autorelease];
180 - (void)setSelectedDateQueryParameter:(NSCalendarDate *)_newDate
181 inDictionary:(NSMutableDictionary *)_qp;
184 [_qp setObject:[self dateStringForDate:_newDate] forKey:@"day"];
186 [_qp removeObjectForKey:@"day"];
189 - (NSString *)completeHrefForMethod:(NSString *)_method {
194 qp = [self queryParameters];
198 ctx = [self context];
199 qps = [ctx queryPathSeparator];
200 [ctx setQueryPathSeparator:@"&"];
201 qs = [ctx queryStringFromDictionary:qp];
202 [ctx setQueryPathSeparator:qps];
203 return [_method stringByAppendingFormat:@"?%@", qs];
206 - (NSString *)ownMethodName {
210 uri = [[[self context] request] uri];
212 /* first: cut off query parameters */
214 r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
216 uri = [uri substringToIndex:r.location];
218 /* next: strip trailing slash */
220 if ([uri hasSuffix:@"/"]) uri = [uri substringToIndex:([uri length] - 1)];
221 r = [uri rangeOfString:@"/" options:NSBackwardsSearch];
223 /* then: cut of last path component */
225 if (r.length == 0) // no slash? are we at root?
228 return [uri substringFromIndex:(r.location + 1)];
231 - (NSString *)userFolderPath {
233 NSArray *traversalObjects;
236 ctx = [self context];
237 traversalObjects = [ctx objectTraversalStack];
238 url = [[traversalObjects objectAtIndex:1]
239 baseURLInContext:ctx];
240 return [[NSURL URLWithString:url] path];
243 - (NSString *)ownPath {
247 uri = [[[self context] request] uri];
249 /* first: cut off query parameters */
251 r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
253 uri = [uri substringToIndex:r.location];
257 - (NSString *)relativePathToUserFolderSubPath:(NSString *)_sub {
260 dst = [[self userFolderPath] stringByAppendingPathComponent:_sub];
261 rel = [dst urlPathRelativeToPath:[self ownPath]];
267 - (NSTimeZone *)viewTimeZone {
268 // Note: also in the folder, should be based on a cookie?
272 - (NSTimeZone *)backendTimeZone {
276 - (NSCalendarDate *)selectedDate {
278 NSCalendarDate *cdate;
280 s = [self queryParameterForKey:@"day"];
281 cdate = ([s length] > 0)
282 ? [self dateForDateString:s]
283 : [NSCalendarDate date];
284 [cdate setTimeZone:[self viewTimeZone]];
285 s = [self queryParameterForKey:@"hm"];
286 if([s length] == 4) {
287 unsigned hour, minute;
289 hour = [[s substringToIndex:2] unsignedIntValue];
290 minute = [[s substringFromIndex:2] unsignedIntValue];
291 cdate = [cdate hour:hour minute:minute];
294 cdate = [cdate hour:12 minute:0];
299 - (NSString *)dateStringForDate:(NSCalendarDate *)_date {
300 [_date setTimeZone:[self viewTimeZone]];
301 return [_date descriptionWithCalendarFormat:@"%Y%m%d"];
304 - (NSCalendarDate *)dateForDateString:(NSString *)_dateString {
305 return [NSCalendarDate dateWithString:_dateString
306 calendarFormat:@"%Y%m%d"];
315 ctx = [self context];
316 return [[[self clientObject] authenticatorInContext:ctx] userInContext:ctx];
319 - (NSString *)shortUserNameForDisplay {
320 // TODO: better use a SoUser formatter?
321 // TODO: who calls that?
325 // TODO: USE USER MANAGER INSTEAD!
327 s = [[self user] login];
331 // TODO: algorithm might be inappropriate, depends on the actual UID
333 r = [s rangeOfString:@"."];
337 return [s substringToIndex:r.location];
342 - (NSString *)labelForKey:(NSString *)_str {
343 WOResourceManager *rm;
347 NSString *lKey, *lTable, *lVal;
350 if ([_str length] == 0)
353 /* lookup languages */
355 ctx = [self context];
356 languages = [ctx hasSession]
357 ? [[ctx session] languages]
358 : [[ctx request] browserLanguages];
360 /* find resource manager */
362 if ((rm = [self resourceManager]) == nil)
363 rm = [[WOApplication application] resourceManager];
365 [self warnWithFormat:@"missing resource manager!"];
369 r = [_str rangeOfString:@"/"];
371 lTable = [_str substringToIndex:r.location];
372 lKey = [_str substringFromIndex:(r.location + r.length)];
380 if ([lKey hasPrefix:@"$"])
381 lKey = [self valueForKeyPath:[lKey substringFromIndex:1]];
383 if ([lTable hasPrefix:@"$"])
384 lTable = [self valueForKeyPath:[lTable substringFromIndex:1]];
387 if ([lVal hasPrefix:@"$"])
388 lVal = [self valueForKeyPath:[lVal substringFromIndex:1]];
394 label = [rm stringForKey:lKey inTableNamed:lTable withDefaultValue:lVal
395 languages:languages];
399 - (NSString *)localizedNameForDayOfWeek:(unsigned)_dayOfWeek {
400 NSString *key = [dayLabelKeys objectAtIndex:_dayOfWeek % 7];
401 return [self labelForKey:key];
404 - (NSString *)localizedAbbreviatedNameForDayOfWeek:(unsigned)_dayOfWeek {
405 NSString *key = [abbrDayLabelKeys objectAtIndex:_dayOfWeek % 7];
406 return [self labelForKey:key];
409 - (NSString *)localizedNameForMonthOfYear:(unsigned)_monthOfYear {
410 NSString *key = [monthLabelKeys objectAtIndex:(_monthOfYear - 1) % 12];
411 return [self labelForKey:key];
414 - (NSString *)localizedAbbreviatedNameForMonthOfYear:(unsigned)_monthOfYear {
415 NSString *key = [abbrMonthLabelKeys objectAtIndex:(_monthOfYear - 1) % 12];
416 return [self labelForKey:key];
419 /* HTTP method safety */
421 - (BOOL)isInvokedBySafeMethod {
422 // TODO: move to WORequest?
425 m = [[[self context] request] method];
426 if ([m isEqualToString:@"GET"]) return YES;
427 if ([m isEqualToString:@"HEAD"]) return YES;
433 - (NSDictionary *)locale {
434 /* we need no fallback here, as locale is guaranteed to be set by sogod */
435 return [[self context] valueForKey:@"locale"];
438 /* Access is in several ways restricted if request is not coming from the
442 - (BOOL)isAccessRestricted {
443 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
445 return [ud boolForKey:@"SOGoAccessIsRestricted"];
450 - (BOOL)isUIxDebugEnabled {
451 return uixDebugEnabled;
454 @end /* UIxComponent */