02111-1307, USA.
*/
-#include "UIxComponent.h"
-#include "SOGoJSStringFormatter.h"
-#include "common.h"
-#include <NGObjWeb/SoHTTPAuthenticator.h>
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSException.h>
+#import <Foundation/NSUserDefaults.h>
+#import <Foundation/NSKeyValueCoding.h>
+#import <Foundation/NSPathUtilities.h>
+
+#import <NGObjWeb/SoHTTPAuthenticator.h>
+#import <NGObjWeb/SoObjects.h>
+#import <NGObjWeb/WOResourceManager.h>
+#import <NGObjWeb/WORequest.h>
+#import <NGObjWeb/WOResponse.h>
+#import <NGObjWeb/WOContext+SoObjects.h>
+#import <NGExtensions/NSObject+Logs.h>
+#import <NGExtensions/NSString+misc.h>
+#import <NGExtensions/NSURL+misc.h>
+
+#import <SoObjects/SOGo/NSCalendarDate+SOGo.h>
+#import <SoObjects/SOGo/NSString+Utilities.h>
+#import <SoObjects/SOGo/SOGoUser.h>
+#import <SoObjects/SOGo/SOGoObject.h>
+#import <SoObjects/SOGo/SOGoContentObject.h>
+#import <SoObjects/SOGo/SOGoCustomGroupFolder.h>
+#import <SoObjects/SOGo/SOGoPermissions.h>
+
+#import "UIxJSClose.h"
+
+#import "UIxComponent.h"
@interface UIxComponent (PrivateAPI)
- (void)_parseQueryString:(NSString *)_s;
@implementation UIxComponent
-static NSTimeZone *MET = nil;
-static NSTimeZone *GMT = nil;
-
static NSMutableArray *dayLabelKeys = nil;
static NSMutableArray *abbrDayLabelKeys = nil;
static NSMutableArray *monthLabelKeys = nil;
uixDebugEnabled = [ud boolForKey:@"SOGoUIxDebugEnabled"];
- if (MET == nil) {
- MET = [[NSTimeZone timeZoneWithAbbreviation:@"MET"] retain];
- GMT = [[NSTimeZone timeZoneWithAbbreviation:@"GMT"] retain];
- }
if (dayLabelKeys == nil) {
dayLabelKeys = [[NSMutableArray alloc] initWithCapacity:7];
[dayLabelKeys addObject:@"Sunday"];
}
}
-- (void)dealloc {
- [self->queryParameters release];
+- (id) init
+{
+ if ((self = [super init]))
+ {
+ _selectedDate = nil;
+ }
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [queryParameters release];
+ [_selectedDate release];
[super dealloc];
}
/* query parameters */
-- (void)_parseQueryString:(NSString *)_s {
+- (void) _parseQueryString: (NSString *) _s
+{
NSEnumerator *e;
NSString *part;
-
+ NSRange r;
+ NSString *key, *value;
+
e = [[_s componentsSeparatedByString:@"&"] objectEnumerator];
- while ((part = [e nextObject]) != nil) {
- NSRange r;
- NSString *key, *value;
-
- r = [part rangeOfString:@"="];
- if (r.length == 0) {
+ part = [e nextObject];
+ while (part)
+ {
+ r = [part rangeOfString:@"="];
+ if (r.length == 0)
+ {
/* missing value of query parameter */
- key = [part stringByUnescapingURL];
- value = @"1";
- }
- else {
- key = [[part substringToIndex:r.location] stringByUnescapingURL];
- value = [[part substringFromIndex:(r.location + r.length)]
- stringByUnescapingURL];
+ key = [part stringByUnescapingURL];
+ value = @"1";
+ }
+ else
+ {
+ key = [[part substringToIndex:r.location] stringByUnescapingURL];
+ value = [[part substringFromIndex:(r.location + r.length)]
+ stringByUnescapingURL];
+ }
+ [queryParameters setObject:value forKey:key];
+ part = [e nextObject];
}
- [self->queryParameters setObject:value forKey:key];
- }
}
-- (void)addKeepAliveFormValuesToQueryParameters {
+
+- (void) addKeepAliveFormValuesToQueryParameters
+{
}
-- (NSString *)queryParameterForKey:(NSString *)_key {
+- (NSString *) queryParameterForKey: (NSString *) _key
+{
return [[self _queryParameters] objectForKey:_key];
}
-- (void)setQueryParameter:(NSString *)_param forKey:(NSString *)_key {
- if(_key == nil)
- return;
-
- if(_param != nil)
- [[self _queryParameters] setObject:_param forKey:_key];
- else
- [[self _queryParameters] removeObjectForKey:_key];
+- (void) setQueryParameter: (NSString *) _param
+ forKey: (NSString *) _key
+{
+ if (_key)
+ {
+ if (_param)
+ [[self _queryParameters] setObject: _param forKey: _key];
+ else
+ [[self _queryParameters] removeObjectForKey: _key];
+ }
}
-- (NSMutableDictionary *)_queryParameters {
+- (NSMutableDictionary *) _queryParameters
+{
// TODO: this code is weird, should use WORequest methods for parsing
WORequest *req;
NSString *uri;
NSRange r;
+ NSString *qs;
- if (self->queryParameters)
- return self->queryParameters;
+ if (queryParameters)
+ return queryParameters;
- self->queryParameters = [[NSMutableDictionary alloc] initWithCapacity:8];
-
- req = [[self context] request];
+ queryParameters = [[NSMutableDictionary alloc] initWithCapacity:8];
+
+ req = [context request];
uri = [req uri];
r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
- if (r.length > 0) {
- NSString *qs;
-
- qs = [uri substringFromIndex:NSMaxRange(r)];
- [self _parseQueryString:qs];
- }
+ if (r.length > 0)
+ {
+ qs = [uri substringFromIndex:NSMaxRange(r)];
+ [self _parseQueryString:qs];
+ }
/* add form values */
[self addKeepAliveFormValuesToQueryParameters];
- return self->queryParameters;
+ return queryParameters;
}
-- (NSDictionary *)queryParameters {
+- (NSDictionary *) queryParameters
+{
return [self _queryParameters];
}
-- (NSDictionary *)queryParametersBySettingSelectedDate:(NSCalendarDate *)_date{
+- (NSDictionary *) queryParametersBySettingSelectedDate: (NSCalendarDate *) _date
+{
NSMutableDictionary *qp;
qp = [[self queryParameters] mutableCopy];
return [qp autorelease];
}
-- (void)setSelectedDateQueryParameter:(NSCalendarDate *)_newDate
- inDictionary:(NSMutableDictionary *)_qp;
+- (void) setSelectedDateQueryParameter: (NSCalendarDate *) _newDate
+ inDictionary: (NSMutableDictionary *) _qp
{
- if(_newDate != nil)
- [_qp setObject:[self dateStringForDate:_newDate] forKey:@"day"];
+ if (_newDate)
+ [_qp setObject: [self dateStringForDate: _newDate] forKey: @"day"];
else
[_qp removeObjectForKey:@"day"];
}
-- (NSString *)completeHrefForMethod:(NSString *)_method {
- WOContext *ctx;
+- (NSString *) completeHrefForMethod: (NSString *) _method
+{
+ WOContext *ctx;
NSDictionary *qp;
- NSString *qs, *qps;
+ NSString *qs, *qps, *href;
qp = [self queryParameters];
- if([qp count] == 0)
- return _method;
+ if ([qp count] > 0)
+ {
+ ctx = context;
+ qps = [ctx queryPathSeparator];
+ [ctx setQueryPathSeparator: @"&"];
+ qs = [ctx queryStringFromDictionary: qp];
+ [ctx setQueryPathSeparator: qps];
+ href = [_method stringByAppendingFormat:@"?%@", qs];
+ }
+ else
+ href = _method;
- ctx = [self context];
- qps = [ctx queryPathSeparator];
- [ctx setQueryPathSeparator:@"&"];
- qs = [ctx queryStringFromDictionary:qp];
- [ctx setQueryPathSeparator:qps];
- return [_method stringByAppendingFormat:@"?%@", qs];
+ return href;
}
-- (NSString *)ownMethodName {
+- (NSString *) ownMethodName
+{
NSString *uri;
NSRange r;
- uri = [[[self context] request] uri];
+ uri = [[context request] uri];
/* first: cut off query parameters */
uri = [uri substringToIndex:r.location];
/* next: strip trailing slash */
-
- if ([uri hasSuffix:@"/"]) uri = [uri substringToIndex:([uri length] - 1)];
- r = [uri rangeOfString:@"/" options:NSBackwardsSearch];
+
+ if ([uri hasSuffix: @"/"])
+ uri = [uri substringToIndex: ([uri length] - 1)];
+ r = [uri rangeOfString:@"/" options: NSBackwardsSearch];
/* then: cut of last path component */
if (r.length == 0) // no slash? are we at root?
return @"/";
- return [uri substringFromIndex:(r.location + 1)];
+ return [uri substringFromIndex: (r.location + 1)];
}
-- (NSString *)userFolderPath {
+- (NSString *) userFolderPath
+{
WOContext *ctx;
- NSArray *traversalObjects;
- NSString *url;
- NSString *path;
+ NSEnumerator *objects;
+ SOGoObject *currentObject;
+ BOOL found;
+
+ ctx = context;
+ objects = [[ctx objectTraversalStack] objectEnumerator];
+ currentObject = [objects nextObject];
+ found = NO;
+ while (currentObject
+ && !found)
+ if ([currentObject isKindOfClass: [SOGoUserFolder class]])
+ found = YES;
+ else
+ currentObject = [objects nextObject];
+
+ return [[currentObject baseURLInContext:ctx] hostlessURL];
+}
- ctx = [self context];
- traversalObjects = [ctx objectTraversalStack];
- url = [[traversalObjects objectAtIndex:0]
- baseURLInContext:ctx];
- path = [[NSURL URLWithString:url] path];
- path = [path stringByAppendingPathComponent:[[ctx activeUser] login]];
- return path;
+- (NSString *) applicationPath
+{
+ SOGoObject *currentClient, *parent;
+ BOOL found;
+ Class objectClass, groupFolderClass, userFolderClass;
+
+ currentClient = [self clientObject];
+ if (currentClient
+ && [currentClient isKindOfClass: [SOGoObject class]])
+ {
+ groupFolderClass = [SOGoCustomGroupFolder class];
+ userFolderClass = [SOGoUserFolder class];
+
+ objectClass = [currentClient class];
+ found = (objectClass == groupFolderClass || objectClass == userFolderClass);
+ while (!found && currentClient)
+ {
+ parent = [currentClient container];
+ objectClass = [parent class];
+ if (objectClass == groupFolderClass
+ || objectClass == userFolderClass)
+ found = YES;
+ else
+ currentClient = parent;
+ }
+ }
+ else
+ currentClient = [WOApplication application];
+
+ return [[currentClient baseURLInContext: context] hostlessURL];
}
-- (NSString *)ownPath {
+- (NSString *) resourcesPath
+{
+ WOResourceManager *rm;
+
+ if ((rm = [self resourceManager]) == nil)
+ rm = [[WOApplication application] resourceManager];
+
+ return [rm webServerResourcesPath];
+}
+
+- (NSString *) ownPath
+{
NSString *uri;
NSRange r;
- uri = [[[self context] request] uri];
+ uri = [[context request] uri];
/* first: cut off query parameters */
r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
if (r.length > 0)
uri = [uri substringToIndex:r.location];
+
return uri;
}
-- (NSString *)relativePathToUserFolderSubPath:(NSString *)_sub {
+- (NSString *) relativePathToUserFolderSubPath: (NSString *) _sub
+{
NSString *dst, *rel;
- dst = [[self userFolderPath] stringByAppendingPathComponent:_sub];
+ dst = [[self userFolderPath] stringByAppendingPathComponent: _sub];
rel = [dst urlPathRelativeToPath:[self ownPath]];
+
return rel;
}
-
-/* date */
-- (NSTimeZone *)viewTimeZone {
- // Note: also in the folder, should be based on a cookie?
- return MET;
-}
+- (NSCalendarDate *) selectedDate
+{
+ NSTimeZone *userTimeZone;
+
+ if (!_selectedDate)
+ {
+ userTimeZone = [[context activeUser] timeZone];
+ _selectedDate
+ = [NSCalendarDate
+ dateFromShortDateString: [self queryParameterForKey: @"day"]
+ andShortTimeString: [self queryParameterForKey: @"hm"]
+ inTimeZone: userTimeZone];
+ [_selectedDate retain];
+ }
-- (NSTimeZone *)backendTimeZone {
- return GMT;
+ return _selectedDate;
}
-- (NSCalendarDate *)selectedDate {
- NSString *s;
- NSCalendarDate *cdate;
+- (NSString *) dateStringForDate: (NSCalendarDate *) _date
+{
+ NSTimeZone *userTimeZone;
+
+ userTimeZone = [[context activeUser] timeZone];
+ [_date setTimeZone: userTimeZone];
- s = [self queryParameterForKey:@"day"];
- cdate = ([s length] > 0)
- ? [self dateForDateString:s]
- : [NSCalendarDate date];
- [cdate setTimeZone:[self viewTimeZone]];
- s = [self queryParameterForKey:@"hm"];
- if([s length] == 4) {
- unsigned hour, minute;
-
- hour = [[s substringToIndex:2] unsignedIntValue];
- minute = [[s substringFromIndex:2] unsignedIntValue];
- cdate = [cdate hour:hour minute:minute];
- }
- else {
- cdate = [cdate hour:12 minute:0];
- }
- return cdate;
+ return [_date descriptionWithCalendarFormat: @"%Y%m%d"];
}
-- (NSString *)dateStringForDate:(NSCalendarDate *)_date {
- [_date setTimeZone:[self viewTimeZone]];
- return [_date descriptionWithCalendarFormat:@"%Y%m%d"];
+- (BOOL) hideFrame
+{
+ return ([[self queryParameterForKey: @"noframe"] boolValue]);
}
-- (NSCalendarDate *)dateForDateString:(NSString *)_dateString {
- return [NSCalendarDate dateWithString:_dateString
- calendarFormat:@"%Y%m%d"];
+- (UIxComponent *) jsCloseWithRefreshMethod: (NSString *) methodName
+{
+ UIxJSClose *jsClose;
+
+ jsClose = [UIxJSClose new];
+ [jsClose autorelease];
+ [jsClose setRefreshMethod: methodName];
+
+ return jsClose;
}
+/* common conditions */
+- (BOOL) canCreateOrModify
+{
+ SoSecurityManager *sm;
-/* SoUser */
+ sm = [SoSecurityManager sharedSecurityManager];
-- (SoUser *)user {
- WOContext *ctx;
-
- ctx = [self context];
- return [[[self clientObject] authenticatorInContext:ctx] userInContext:ctx];
+ return (![sm validatePermission: SoPerm_ChangeImagesAndFiles
+ onObject: [self clientObject]
+ inContext: context]);
}
-- (NSString *)shortUserNameForDisplay {
- // TODO: better use a SoUser formatter?
- // TODO: who calls that?
- NSString *s;
- NSRange r;
-
- // TODO: USE USER MANAGER INSTEAD!
-
- s = [[self user] login];
- if ([s length] < 10)
- return s;
-
- // TODO: algorithm might be inappropriate, depends on the actual UID
-
- r = [s rangeOfString:@"."];
- if (r.length == 0)
- return s;
-
- return [s substringToIndex:r.location];
+/* SoUser */
+
+- (NSString *) shortUserNameForDisplay
+{
+ if ([context activeUser] == nil)
+ return @"wrongusernamepassword";
+
+ return [[context activeUser] login];
}
/* labels */
-- (NSString *)labelForKey:(NSString *)_str {
+- (NSString *) labelForKey: (NSString *) _str
+{
WOResourceManager *rm;
- NSArray *languages;
- NSString *label;
- NSString *lKey, *lTable, *lVal;
+ NSArray *languages;
+ NSString *lKey, *lTable, *lVal;
NSRange r;
if ([_str length] == 0)
/* lookup languages */
- languages = [[self context] resourceLookupLanguages];
+ languages = [context resourceLookupLanguages];
/* find resource manager */
- if ((rm = [self resourceManager]) == nil)
+ if ((rm = [self pageResourceManager]) == nil)
rm = [[WOApplication application] resourceManager];
if (rm == nil)
[self warnWithFormat:@"missing resource manager!"];
if ([lTable hasPrefix:@"$"])
lTable = [self valueForKeyPath:[lTable substringFromIndex:1]];
-#if 0
- if ([lVal hasPrefix:@"$"])
- lVal = [self valueForKeyPath:[lVal substringFromIndex:1]];
-
-#endif
-
/* lookup string */
-
- label = [rm stringForKey:lKey inTableNamed:lTable withDefaultValue:lVal
- languages:languages];
- return label;
+ return [rm stringForKey: lKey
+ inTableNamed: lTable
+ withDefaultValue: lVal
+ languages: languages];
}
-- (NSString *)localizedNameForDayOfWeek:(unsigned)_dayOfWeek {
+- (NSString *) localizedNameForDayOfWeek:(unsigned)_dayOfWeek {
NSString *key = [dayLabelKeys objectAtIndex:_dayOfWeek % 7];
return [self labelForKey:key];
}
// TODO: move to WORequest?
NSString *m;
- m = [[[self context] request] method];
+ m = [[context request] method];
if ([m isEqualToString:@"GET"]) return YES;
if ([m isEqualToString:@"HEAD"]) return YES;
return NO;
- (NSDictionary *)locale {
/* we need no fallback here, as locale is guaranteed to be set by sogod */
- return [[self context] valueForKey:@"locale"];
+ return [context valueForKey: @"locale"];
+}
+
+- (WOResourceManager *) pageResourceManager
+{
+ WOResourceManager *rm;
+
+ if ((rm = [[context page] resourceManager]) == nil)
+ rm = [[WOApplication application] resourceManager];
+
+ return rm;
+}
+
+- (NSString *) urlForResourceFilename: (NSString *) filename
+{
+ static NSMutableDictionary *pageToURL = nil;
+ NSString *url;
+ WOComponent *page;
+ WOResourceManager *rm;
+ NSBundle *pageBundle;
+
+ if (filename)
+ {
+ if (!pageToURL)
+ pageToURL = [[NSMutableDictionary alloc] initWithCapacity: 32];
+
+ url = [pageToURL objectForKey: filename];
+ if (!url)
+ {
+ rm = [self pageResourceManager];
+ page = [context page];
+ pageBundle = [NSBundle bundleForClass: [page class]];
+ url = [rm urlForResourceNamed: filename
+ inFramework: [pageBundle bundlePath]
+ languages: nil
+ request: [context request]];
+ if (!url)
+ url = @"";
+ else
+ if ([url hasPrefix: @"http"])
+ url = [url hostlessURL];
+ [pageToURL setObject: url forKey: filename];
+ }
+
+// NSLog (@"url for '%@': '%@'", filename, url);
+ }
+ else
+ url = @"";
+
+ return url;
+}
+
+- (WOResponse *) responseWith204
+{
+ WOResponse *response;
+
+ response = [context response];
+ [response setStatus: 204];
+
+ return response;
}
/* debugging */