]> err.no Git - scalable-opengroupware.org/blobdiff - UI/SOGoUI/UIxComponent.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1287 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / UI / SOGoUI / UIxComponent.m
index 1e4f65f69a8b02e99a425af96ae1173f8bade4a2..50e6bf253c28cc32521870927b9aae8003c7bafd 100644 (file)
   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;
@@ -31,9 +54,6 @@
 
 @implementation UIxComponent
 
-static NSTimeZone *MET = nil;
-static NSTimeZone *GMT = nil;
-
 static NSMutableArray *dayLabelKeys       = nil;
 static NSMutableArray *abbrDayLabelKeys   = nil;
 static NSMutableArray *monthLabelKeys     = nil;
@@ -54,10 +74,6 @@ static BOOL uixDebugEnabled = NO;
   
   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"];
@@ -107,85 +123,110 @@ static BOOL uixDebugEnabled = NO;
   }
 }
 
-- (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];
@@ -193,37 +234,43 @@ static BOOL uixDebugEnabled = NO;
   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 */
     
@@ -232,137 +279,181 @@ static BOOL uixDebugEnabled = NO;
     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)
@@ -370,11 +461,11 @@ static BOOL uixDebugEnabled = NO;
   
   /* 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!"];
@@ -398,20 +489,14 @@ static BOOL uixDebugEnabled = NO;
   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];
 }
@@ -437,7 +522,7 @@ static BOOL uixDebugEnabled = NO;
   // 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;
@@ -447,7 +532,66 @@ static BOOL uixDebugEnabled = 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 */