see ChangeLog

Monotone-Revision: 9054022ef1ca8aeba6e34842d27d9b94ce002b89

Monotone-Author: dev-unix.inverse.qc.ca
Monotone-Date: 2006-06-15T19:34:10
Monotone-Branch: ca.inverse.sogo
This commit is contained in:
dev-unix.inverse.qc.ca
2006-06-15 19:34:10 +00:00
commit f18c764ffa
965 changed files with 99196 additions and 0 deletions
+84
View File
@@ -0,0 +1,84 @@
/*
Copyright (C) 2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#ifndef __AgenorUserDefaults_H_
#define __AgenorUserDefaults_H_
#import <Foundation/NSObject.h>
/*
AgenorUserDefaults
An object with the same API like NSUserDefaults which retrieves profile
information for users in the database.
*/
@class NSString, NSURL, NSUserDefaults, NSArray, NSDictionary, NSData;
@class NSCalendarDate, NSMutableDictionary;
@interface AgenorUserDefaults : NSObject
{
NSUserDefaults *parent;
NSURL *url;
NSString *uid;
NSArray *fieldNames;
NSDictionary *attributes;
NSMutableDictionary *values;
NSCalendarDate *lastFetch;
struct {
int modified:1;
int isNew:1;
int reserved:30;
} defFlags;
}
- (id)initWithTableURL:(NSURL *)_url uid:(NSString *)_uid;
/* value access */
- (void)setObject:(id)_value forKey:(NSString *)_key;
- (id)objectForKey:(NSString *)_key;
- (void)removeObjectForKey:(NSString *)_key;
/* typed accessors */
- (NSArray *)arrayForKey:(NSString *)_key;
- (NSDictionary *)dictionaryForKey:(NSString *)_key;
- (NSData *)dataForKey:(NSString *)_key;
- (NSArray *)stringArrayForKey:(NSString *)_key;
- (NSString *)stringForKey:(NSString *)_key;
- (BOOL)boolForKey:(NSString *)_key;
- (float)floatForKey:(NSString *)_key;
- (int)integerForKey:(NSString *)_key;
- (void)setBool:(BOOL)value forKey:(NSString *)_key;
- (void)setFloat:(float)value forKey:(NSString *)_key;
- (void)setInteger:(int)value forKey:(NSString *)_key;
/* saving changes */
- (BOOL)synchronize;
@end
#endif /* __AgenorUserDefaults_H_ */
+472
View File
@@ -0,0 +1,472 @@
/*
Copyright (C) 2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "AgenorUserDefaults.h"
#include <GDLContentStore/GCSChannelManager.h>
#include <GDLContentStore/NSURL+GCS.h>
#include <GDLAccess/EOAdaptorChannel.h>
#include <GDLAccess/EOAdaptorContext.h>
#include <GDLAccess/EOAttribute.h>
#include "common.h"
@implementation AgenorUserDefaults
static NSString *uidColumnName = @"uid";
- (id)initWithTableURL:(NSURL *)_url uid:(NSString *)_uid {
if ((self = [super init])) {
if (_url == nil || [_uid length] < 1) {
[self errorWithFormat:@"tried to create AgenorUserDefaults w/o args!"];
[self release];
return nil;
}
self->parent = [[NSUserDefaults standardUserDefaults] retain];
self->url = [_url copy];
self->uid = [_uid copy];
}
return self;
}
- (id)init {
return [self initWithTableURL:nil uid:nil];
}
- (void)dealloc {
[self->attributes release];
[self->lastFetch release];
[self->parent release];
[self->url release];
[self->uid release];
[super dealloc];
}
/* accessors */
- (NSURL *)tableURL {
return self->url;
}
- (NSString *)uid {
return self->uid;
}
- (NSUserDefaults *)parentDefaults {
return self->parent;
}
/* operation */
- (void)_loadAttributes:(NSArray *)_attrs {
NSMutableArray *fields;
NSMutableDictionary *attrmap;
unsigned i, count;
fields = [[NSMutableArray alloc] initWithCapacity:16];
attrmap = [[NSMutableDictionary alloc] initWithCapacity:16];
for (i = 0, count = [_attrs count]; i < count; i++) {
EOAttribute *attr;
NSString *name;
attr = [_attrs objectAtIndex:i];
name = [attr valueForKey:@"name"];
[attrmap setObject:attr forKey:name];
if (![name isEqual:uidColumnName])
[fields addObject:name];
}
ASSIGNCOPY(self->fieldNames, fields);
ASSIGNCOPY(self->attributes, attrmap);
[attrmap release];
[fields release];
}
- (BOOL)primaryFetchProfile {
GCSChannelManager *cm;
EOAdaptorChannel *channel;
NSDictionary *row;
NSException *ex;
NSString *sql;
NSArray *attrs;
cm = [GCSChannelManager defaultChannelManager];
if ((channel = [cm acquireOpenChannelForURL:[self tableURL]]) == nil) {
[self errorWithFormat:@"failed to acquire channel for URL: %@",
[self tableURL]];
return NO;
}
/* generate SQL */
sql = [[self tableURL] gcsTableName];
sql = [@"SELECT * FROM " stringByAppendingString:sql];
sql = [sql stringByAppendingFormat:@" WHERE %@ = '%@'",
uidColumnName, [self uid]];
/* run SQL */
if ((ex = [channel evaluateExpressionX:sql]) != nil) {
[self errorWithFormat:@"could not run SQL '%@': %@", sql, ex];
[cm releaseChannel:channel];
return NO;
}
/* fetch schema */
attrs = [channel describeResults:NO /* don't beautify */];
[self _loadAttributes:attrs];
/* fetch values */
row = [channel fetchAttributes:attrs withZone:NULL];
self->defFlags.isNew = (row != nil) ? 0 : 1;
[channel cancelFetch];
/* remember values */
[self->values release]; self->values = nil;
self->values = (row != nil)
? [row mutableCopy]
: [[NSMutableDictionary alloc] initWithCapacity:8];
[self->values removeObjectForKey:uidColumnName];
ASSIGN(self->lastFetch, [NSCalendarDate date]);
self->defFlags.modified = 0;
[cm releaseChannel:channel];
return YES;
}
- (NSString *)formatValue:(id)_value forAttribute:(EOAttribute *)_attribute {
NSString *s;
if (![_value isNotNull])
return @"NULL";
if ([[_attribute externalType] hasPrefix:@"int"])
return [_value stringValue];
s = [_value stringValue];
s = [s stringByReplacingString:@"'" withString:@"''"];
s = [[@"'" stringByAppendingString:s] stringByAppendingString:@"'"];
return s;
}
- (NSString *)generateSQLForInsert {
NSMutableString *sql;
unsigned i, count;
if ([self->values count] == 0)
return nil;
sql = [NSMutableString stringWithCapacity:2048];
[sql appendString:@"INSERT INTO "];
[sql appendString:[[self tableURL] gcsTableName]];
[sql appendString:@" ( uid"];
for (i = 0, count = [self->fieldNames count]; i < count; i++) {
EOAttribute *attr;
attr = [self->attributes objectForKey:[self->fieldNames objectAtIndex:i]];
[sql appendString:@", "];
[sql appendString:[attr columnName]];
}
[sql appendString:@") VALUES ("];
[sql appendString:@"'"];
[sql appendString:[self uid]]; // TODO: escaping necessary?
[sql appendString:@"'"];
for (i = 0, count = [self->fieldNames count]; i < count; i++) {
EOAttribute *attr;
id value;
attr = [self->attributes objectForKey:[self->fieldNames objectAtIndex:i]];
value = [self->values objectForKey:[self->fieldNames objectAtIndex:i]];
[sql appendString:@", "];
[sql appendString:[self formatValue:value forAttribute:attr]];
}
[sql appendString:@")"];
return sql;
}
- (NSString *)generateSQLForUpdate {
NSMutableString *sql;
unsigned i, count;
if ([self->values count] == 0)
return nil;
sql = [NSMutableString stringWithCapacity:2048];
[sql appendString:@"UPDATE "];
[sql appendString:[[self tableURL] gcsTableName]];
[sql appendString:@" SET "];
for (i = 0, count = [self->fieldNames count]; i < count; i++) {
EOAttribute *attr;
NSString *name;
id value;
name = [self->fieldNames objectAtIndex:i];
value = [self->values objectForKey:name];
attr = [self->attributes objectForKey:name];
if (i != 0) [sql appendString:@", "];
[sql appendString:[attr columnName]];
[sql appendString:@" = "];
[sql appendString:[self formatValue:value forAttribute:attr]];
}
[sql appendString:@" WHERE "];
[sql appendString:uidColumnName];
[sql appendString:@" = '"];
[sql appendString:[self uid]];
[sql appendString:@"'"];
return sql;
}
- (BOOL)primaryStoreProfile {
GCSChannelManager *cm;
EOAdaptorChannel *channel;
NSException *ex;
NSString *sql;
cm = [GCSChannelManager defaultChannelManager];
if ((channel = [cm acquireOpenChannelForURL:[self tableURL]]) == nil) {
[self errorWithFormat:@"failed to acquire channel for URL: %@",
[self tableURL]];
return NO;
}
/* run SQL */
sql = self->defFlags.isNew
? [self generateSQLForInsert]
: [self generateSQLForUpdate];
if ((ex = [channel evaluateExpressionX:sql]) != nil) {
[self errorWithFormat:@"could not run SQL '%@': %@", sql, ex];
[cm releaseChannel:channel];
return NO;
}
/* commit */
ex = nil;
if ([[channel adaptorContext] hasOpenTransaction])
ex = [channel evaluateExpressionX:@"COMMIT TRANSACTION"];
[cm releaseChannel:channel];
if (ex != nil) {
[self errorWithFormat:@"could not commit transaction for update: %@", ex];
return NO;
}
self->defFlags.modified = 0;
self->defFlags.isNew = 0;
return YES;
}
- (BOOL)fetchProfile {
if (self->values != nil)
return YES;
return [self primaryFetchProfile];
}
- (NSArray *)primaryDefaultNames {
if (![self fetchProfile])
return nil;
return self->fieldNames;
}
/* value access */
- (void)setObject:(id)_value forKey:(NSString *)_key {
if (![self fetchProfile])
return;
if (![self->fieldNames containsObject:_key]) {
[self errorWithFormat:@"tried to write key: '%@'", _key];
return;
}
/* check whether the value is actually modified */
if (!self->defFlags.modified) {
id old;
old = [self->values objectForKey:_key];
if (old == _value || [old isEqual:_value]) /* value didn't change */
return;
/* we need to this because our typed accessors convert to strings */
// TODO: especially problematic with bools
if ([_value isKindOfClass:[NSString class]]) {
if (![old isKindOfClass:[NSString class]])
if ([[old description] isEqualToString:_value])
return;
}
}
/* set in hash and mark as modified */
[self->values setObject:(_value ? _value : [NSNull null]) forKey:_key];
self->defFlags.modified = 1;
}
- (id)objectForKey:(NSString *)_key {
id value;
if (![self fetchProfile])
return nil;
if (![self->fieldNames containsObject:_key])
return [self->parent objectForKey:_key];
value = [self->values objectForKey:_key];
return [value isNotNull] ? value : nil;
}
- (void)removeObjectForKey:(NSString *)_key {
[self setObject:nil forKey:_key];
}
/* saving changes */
- (BOOL)synchronize {
if (!self->defFlags.modified) /* was not modified */
return YES;
/* ensure fetched data (more or less guaranteed by modified!=0) */
if (![self fetchProfile])
return NO;
/* store */
if (![self primaryStoreProfile]) {
[self primaryFetchProfile];
return NO;
}
/* refetch */
return [self primaryFetchProfile];
}
- (void)flush {
[self->values release]; self->values = nil;
[self->fieldNames release]; self->fieldNames = nil;
[self->attributes release]; self->attributes = nil;
[self->lastFetch release]; self->lastFetch = nil;
self->defFlags.modified = 0;
self->defFlags.isNew = 0;
}
/* typed accessors */
- (NSArray *)arrayForKey:(NSString *)_key {
id obj = [self objectForKey:_key];
return [obj isKindOfClass:[NSArray class]] ? obj : nil;
}
- (NSDictionary *)dictionaryForKey:(NSString *)_key {
id obj = [self objectForKey:_key];
return [obj isKindOfClass:[NSDictionary class]] ? obj : nil;
}
- (NSData *)dataForKey:(NSString *)_key {
id obj = [self objectForKey:_key];
return [obj isKindOfClass:[NSData class]] ? obj : nil;
}
- (NSArray *)stringArrayForKey:(NSString *)_key {
id obj = [self objectForKey:_key];
int n;
Class strClass = [NSString class];
if (![obj isKindOfClass:[NSArray class]])
return nil;
for (n = [obj count]-1; n >= 0; n--) {
if (![[obj objectAtIndex:n] isKindOfClass:strClass])
return nil;
}
return obj;
}
- (NSString *)stringForKey:(NSString *)_key {
id obj = [self objectForKey:_key];
return [obj isKindOfClass:[NSString class]] ? obj : nil;
}
- (BOOL)boolForKey:(NSString *)_key {
// TODO: need special support here for int-DB fields
id obj;
if ((obj = [self objectForKey:_key]) == nil)
return NO;
if ([obj isKindOfClass:[NSString class]]) {
if ([obj compare:@"YES" options:NSCaseInsensitiveSearch] == NSOrderedSame)
return YES;
}
if ([obj respondsToSelector:@selector(intValue)])
return [obj intValue] ? YES : NO;
return NO;
}
- (float)floatForKey:(NSString *)_key {
id obj = [self stringForKey:_key];
return (obj != nil) ? [obj floatValue] : 0.0;
}
- (int)integerForKey:(NSString *)_key {
id obj = [self stringForKey:_key];
return (obj != nil) ? [obj intValue] : 0;
}
- (void)setBool:(BOOL)value forKey:(NSString *)_key {
// TODO: need special support here for int-DB fields
[self setObject:(value ? @"YES" : @"NO") forKey:_key];
}
- (void)setFloat:(float)value forKey:(NSString *)_key {
[self setObject:[NSString stringWithFormat:@"%f", value] forKey:_key];
}
- (void)setInteger:(int)value forKey:(NSString *)_key {
[self setObject:[NSString stringWithFormat:@"%d", value] forKey:_key];
}
/* description */
- (NSString *)description {
NSMutableString *ms;
ms = [NSMutableString stringWithCapacity:16];
[ms appendFormat:@"<0x%08X[%@]>", self, NSStringFromClass([self class])];
[ms appendFormat:@" uid=%@", self->uid];
[ms appendFormat:@" url=%@", [self->url absoluteString]];
[ms appendFormat:@" parent=0x%08X", self->parent];
[ms appendString:@">"];
return ms;
}
@end /* AgenorUserDefaults */
+85
View File
@@ -0,0 +1,85 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#ifndef __AgenorUserManager_H_
#define __AgenorUserManager_H_
#import <Foundation/NSObject.h>
/*
AgenorUserManager
TODO: document
*/
@class NSString, NSArray, NSURL, NSUserDefaults, NSMutableDictionary, NSTimer;
@class NSDictionary;
@class iCalPerson;
@interface AgenorUserManager : NSObject
{
NSMutableDictionary *cnCache;
NSMutableDictionary *serverCache;
NSMutableDictionary *uidCache;
NSMutableDictionary *emailCache;
NSMutableDictionary *shareStoreCache;
NSMutableDictionary *shareEMailCache;
NSMutableDictionary *changeInternetAccessCache;
NSMutableDictionary *internetAutoresponderFlagCache;
NSMutableDictionary *intranetAutoresponderFlagCache;
NSTimer *gcTimer;
}
+ (id)sharedUserManager;
- (NSString *)getUIDForEmail:(NSString *)_email;
- (NSString *)getEmailForUID:(NSString *)_uid;
- (NSString *)getUIDForICalPerson:(iCalPerson *)_person;
/* may insert NSNulls into returned array if _mapStrictly -> YES */
- (NSArray *)getUIDsForICalPersons:(NSArray *)_persons
applyStrictMapping:(BOOL)_mapStrictly;
/* i.e. BUTTO Hercule, CETE Lyon/DI/ET/TEST */
- (NSString *)getCNForUID:(NSString *)_uid;
/* i.e. hercule.butto@amelie-ida01.melanie2.i2 */
- (NSString *)getIMAPAccountStringForUID:(NSString *)_uid;
/* i.e. amelie-ida01.melanie2.i2 */
- (NSString *)getServerForUID:(NSString *)_uid;
- (NSArray *)getSharedMailboxAccountStringsForUID:(NSString *)_uid;
- (NSArray *)getSharedMailboxEMailsForUID:(NSString *)_uid;
- (NSDictionary *)getSharedMailboxesAndEMailsForUID:(NSString *)_uid;
- (NSURL *)getFreeBusyURLForUID:(NSString *)_uid;
- (NSUserDefaults *)getUserDefaultsForUID:(NSString *)_uid;
- (BOOL)isUserAllowedToChangeSOGoInternetAccess:(NSString *)_uid;
- (BOOL)isInternetAutoresponderEnabledForUser:(NSString *)_uid;
- (BOOL)isIntranetAutoresponderEnabledForUser:(NSString *)_uid;
@end
#endif /* __AgenorUserManager_H_ */
File diff suppressed because it is too large Load Diff
+374
View File
@@ -0,0 +1,374 @@
2005-08-01 Helge Hess <helge.hess@skyrix.com>
* added FHS installation (v0.9.70)
* SOGoObject.m: added class security declarations (previously in
product.plist of MainUI) (v0.9.69)
2005-07-21 Helge Hess <helge.hess@opengroupware.org>
* SOGoUser.m: added a method to fetch share/emitter address pairs from
the AgenorUserManager (v0.9.68)
* AgenorUserManager.m: rewrote to use NSMutableDictionary instead of
SOGoLRUCache. Flush caches every hour (configurable using
'AgenorCacheCheckInterval' default). Added method to retrieve the
shares and the emitter emails in one step. (v0.9.67)
2005-07-20 Helge Hess <helge.hess@opengroupware.org>
* v0.9.66
* SOGoContentObject.m: properly quote etag
* SOGoObject.m: changed to check etag when the content is accessed in
WebDAV mode and return a 304 if the tag stayed the same.
Do not strip quotes from etags in if-*match headers.
Properly implement if-none-match for GET requests.
* SOGoContentObject.m: moved generic etag checking to SOGoObject (to
share implementation with Mailer) (v0.9.65)
2005-07-19 Marcus Mueller <znek@mulle-kybernetik.com>
* AgenorUserManager.m: properly implemented internet/intranet vacation
message status detection (v0.9.64)
2005-07-14 Marcus Mueller <znek@mulle-kybernetik.com>
* v0.9.63
* SOGoAppointment.[hm]: new API to cancel appointments, NSCopying
support
2005-07-15 Helge Hess <helge.hess@opengroupware.org>
* v0.9.62
* SOGoGroupFolder.m, SOGoUser.m: fixed a gcc 4.0 warning
* GNUmakefile.preamble: properly use SYSTEM_LIB_DIR
* v0.9.61
* SOGoContentObject.m: fixed a Cocoa warning
* GNUmakefile.preamble: added proper linking flags for OSX
2005-07-14 Marcus Mueller <znek@mulle-kybernetik.com>
* v0.9.60
* SOGoAppointment.[hm]: added 'method' and 'userComment' accessors
* SOGoAppointmentICalRenderer.m: properly render 'method' of
appointment if it's set - otherwise assume 'REQUEST'
2005-07-14 Helge Hess <helge.hess@opengroupware.org>
* SOGoUser.m: added -homeFolderInContext: and
-schedulingCalendarInContext: methods (v0.9.59)
* moved in SOGoUser and SOGoAuthenticator from Main (v0.9.58)
2005-07-14 Marcus Mueller <znek@mulle-kybernetik.com>
* AgenorUserManager.[hm]: added accessors and cache for the
'mineqMelReponse' flag. Please note that the implementation isn't
fully fleshed out because the technical specification isn't correct.
(v0.9.57)
* AgenorUserManager.[hm]: added accessors and cache for the
'mineqOgoAccesInternet' flag (v0.9.56)
2005-07-14 Helge Hess <helge.hess@opengroupware.org>
* SOGoContentObject.m: added empty davCopy/davMove methods (v0.9.55)
* v0.9.54
* SOGoContentObject.m: added support for special 'new' key (server will
assign a name and add the new location in a special response header)
* SOGoFolder.m: added +globallyUniqueObjectId (previously the method
was duplicated in each subclass)
* SOGoContentObject.m: added transactionally save etag-checks in PUT
(use the etag value as the baseVersion in the content store)
(v0.9.53)
2005-07-13 Helge Hess <helge.hess@opengroupware.org>
* v0.9.52
* SOGoObject.m: properly add etag during a GET (if available)
* SOGoContentObject.m: generate etag from content object version, added
methods to check request preconditions, check preconditions prior
running a PUT, added new etag after running a PUT
* SOGoObject.m, SOGoFolder.m: added +version methods to detect fragile
base class issues (v0.9.51)
* SOGoFolder.m: changed to use plain column names (v0.9.50)
2005-07-12 Marcus Mueller <znek@mulle-kybernetik.com>
* SOGoUserFolder.m: forbid access (403) to SOGoGroupFolders if access
is not from the Intranet (v0.9.49)
2005-07-12 Helge Hess <helge.hess@opengroupware.org>
* AgenorUserDefaults.m: added automagic profile row creation (v0.9.48)
* AgenorUserDefaults.m: implemented saving of changed profiles
(v0.9.47)
2005-07-12 Marcus Mueller <znek@mulle-kybernetik.com>
* AgenorUserManager.[hm]: new API for extracting UIDs from iCalPersons
(v0.9.46)
2005-07-12 Helge Hess <helge.hess@opengroupware.org>
* v0.9.45
* AgenorUserDefaults.m: properly fetch profile contents
* agenor_defaults.m: read operation can now return all defined keys
* v0.9.44
* AgenorUserDefaults.m: added typed value accessors and proper
initializers
* AgenorUserManager.m: added 'AgenorProfileURL' default to configure
the database location of the user profile table
* finished agenor_defaults tool
2005-07-12 Helge Hess <helge.hess@opengroupware.org>
* v0.9.43
* added agenor_defaults tool to test defaults functionality
* AgenorUserManager.[hm]: added -getUserDefaultsForUID: method to
retrieve the profile of a user (incomplete)
* added AgenorUserDefaults class (incomplete) as a wrapper for the
profile data of Agenor users
2005-07-08 Helge Hess <helge.hess@opengroupware.org>
* v0.9.42
* added agenor_emails4uid tool to check whether the
uid=>allowed-from-mails discovery in AgenorUserManager works
* AgenorUserManager.m: added -getSharedMailboxEMailsForUID: method to
discover the shared emails the user is allowed to post from,
added caching of shared emails and Cyrus-logins
* WOContext+Agenor.m: use SOGoInternetDetectQualifier for detecting
Internet access level (v0.9.41)
2005-07-08 Marcus Mueller <znek@mulle-kybernetik.com>
* WOContext+Agenor.[hm]: new category for discovering if the current
context is via access from the intranet. (v0.9.40)
2005-07-07 Helge Hess <helge.hess@opengroupware.org>
* added agenor_shares4uid tool to check whether the uid=>shared mailbox
discovery in AgenorUserManager works
* AgenorUserManager.m: fixed a major string scanning bug in
_serverCandidatesForMineqMelRoutage: method,
added -getSharedMailboxAccountStringsForUID: method to discover
shared IMAP4 accounts (v0.9.39)
2005-07-07 Helge Hess <helge.hess@opengroupware.org>
* AgenorUserManager.m: added a simple -description method (v0.9.38)
* added agenor_email2uid.m tool to check whether the email=>uid mapping
in AgenorUserManager works
2005-07-06 Marcus Mueller <znek@mulle-kybernetik.com>
* v0.9.37
* SOGoUserFolder.m: added 'freebusy.ifb' as an object to the
collection for proper display via DAV.
* SOGoAppointmentICalRenderer.m: fixed header inclusion
* AgenorUserManager.[hm]: added proposed future API for discovering
URLs for free/busy information (implementation currently returns
nil)
2005-07-05 Marcus Mueller <znek@mulle-kybernetik.com>
* SOGoAppointment.m: fixed a wrong -release (v0.9.36)
2005-03-25 Helge Hess <helge.hess@opengroupware.org>
* SOGoObject.m: fixed DELETEAction to return a boolean if the delete
was successful (required by SoObjectRequestHandler) (v0.9.35)
2005-03-20 Helge Hess <helge.hess@opengroupware.org>
* changed to use GDLContentStore (v0.9.34)
2005-03-03 Marcus Mueller <znek@mulle-kybernetik.com>
* SOGoGroupFolder.m: switched logging to NGLogging (v0.9.33)
2005-03-02 Marcus Mueller <znek@mulle-kybernetik.com>
* NSObject+AptComparison.[hm]: new comparison method. This is used
in SOGoAppointmentFolder currently. (v0.9.32)
2005-02-20 Helge Hess <helge.hess@opengroupware.org>
* AgenorUserManager.m: refactoring of the LDAP fetch code, added the
'SOGoFallbackIMAP4Server' default to configure the IMAP4 server when
LDAP is disabled (v0.9.31)
2005-02-17 Helge Hess <helge.hess@opengroupware.org>
* moved in code from libSOGoLogic (unnecessarily a separate library)
(v0.9.30)
2005-02-10 Helge Hess <helge.hess@opengroupware.org>
* SOGoObject.m: fixed a warning on MacOSX (v0.9.29)
2005-02-07 Helge Hess <helge.hess@opengroupware.org>
* SOGoObject.h: added prototype for GETAction (v0.9.28)
2005-02-06 Helge Hess <helge.hess@opengroupware.org>
* added -outlookMessageClass / -outlookFolderClass (v0.9.27)
2004-10-19 Helge Hess <helge.hess@opengroupware.org>
* SOGoFolder: added method -fetchContentStringsAndNamesOfAllObjects
which fetches the contents of all folders objects (avoid to use this
high overhead method!). Required for iCalendar file generation.
(v0.9.26)
2004-10-08 Helge Hess <helge.hess@opengroupware.org>
* SOGoUserFolder.m: enhanced object lookup so that when a Calendar
is opened with an extensions (eg "Calendar.ics") (v0.9.25)
* SOGoFolder.m: added facility to define default extensions (v0.9.24)
* SOGoObject.m: fixed not implemented return status (501, not 502)
(v0.9.23)
* SOGoUserFolder.m: do not try to fetch file names in this folder
(v0.9.22)
* v0.9.21
* SOGoContentObject.m: added PUTAction:
* SOGoObject.m: implemented special WebDAV support in GETAction:
* SOGoFolder.m: added -toOneRelationshipKeys method (enables listing of
contained objects in WebDAV), added container name to logging prefix,
explicitly mark as WebDAV collection
* SOGoContentObject.m: mark as WebDAV non-collection
2004-10-07 Helge Hess <helge.hess@opengroupware.org>
* SOGoUserFolder.m: added toManyRelationshipKeys, marked as WebDAV
collection (v0.9.20)
2004-09-29 Helge Hess <helge.hess@opengroupware.org>
* SOGoObject.m: added -fetchSubfolders method to resolve all
toManyRelationshipKeys to SOPE objects (v0.9.19)
2004-09-20 Helge Hess <helge.hess@skyrix.com>
* SOGoObject.m: added a default GET method which redirects to
url + "/view" (v0.9.18)
* SOGoObject.m(-description): added name of container (v0.9.17)
2004-09-08 Helge Hess <helge.hess@skyrix.com>
* SOGoGroupFolder.m: separate -resetFolderCaches method from -sleep
(v0.9.16)
2004-09-08 Helge Hess <helge.hess@skyrix.com>
* SOGoUserFolder.m: map "Mail" key to SOGoMailAccounts object (v0.9.15)
2004-09-01 Marcus Mueller <znek@mulle-kybernetik.com>
* v0.9.14
* GNUmakefile.preamble: fixed for gsmake 1.9.2 build
* GNUmakefile: include ../../Version also
2004-08-26 Helge Hess <helge.hess@skyrix.com>
* SOGoUserFolder.m: added ability to create Contacts folder (v0.9.13)
2004-08-24 Maxime Wacker <mwacker@linagora.com>
* GNUmakefile.preamble: fixes for the build process (v0.9.12)
2004-08-16 Helge Hess <helge.hess@skyrix.com>
* SOGoCustomGroupFolder.m: added -initWithUIDs:inContainer: for using
the groups folder for internal group fetches (v0.9.11)
* SOGoContentObject.m: updated multi-save things (which belong into the
SOGoAppointmentObject class), implement -sleep to release the content
(v0.9.10)
2004-08-15 Helge Hess <helge.hess@skyrix.com>
* SOGoContentObject.m: implement first version of -delete (v0.9.9)
* SOGoObject.[hm], SOGoUserFolder.[hm]: implemented SOPE
-ownerInContext: (v0.9.8)
2004-08-14 Helge Hess <helge.hess@skyrix.com>
* v0.9.7
* SOGoGroupFolder.m: renamed -reset method to -sleep (called by SOPE)
* SOGoObject.m: added SOPE -sleep method (resets container and can be
called by subclasses)
* SOGoGroupFolder.m: made the folder found note log a debug log
2004-08-11 Helge Hess <helge.hess@skyrix.com>
* v0.9.6
* SOGoUserFolder.m: added "Groups" folder name and lookup
* added: SOGoGroupsFolder, SOGoGroupFolder, SOGoCustomGroupFolder
2004-07-02 Helge Hess <helge.hess@opengroupware.org>
* SOGoObject.m: added -delete method (but not yet implemented)
2004-06-30 Helge Hess <helge.hess@opengroupware.org>
* SOGoContentObject.m: added -contentAsString method
* created ChangeLog
+78
View File
@@ -0,0 +1,78 @@
# GNUstep makefile
-include ../../config.make
include $(GNUSTEP_MAKEFILES)/common.make
-include ../../Version
-include ./Version
LIBRARY_NAME = libSOGo
TOOL_NAME = \
agenor_email2uid \
agenor_shares4uid \
agenor_emails4uid \
agenor_defaults
libSOGo_SOVERSION=$(MAJOR_VERSION).$(MINOR_VERSION)
libSOGo_HEADER_FILES_DIR = .
libSOGo_HEADER_FILES_INSTALL_DIR = /SOGo
FHS_HEADER_DIRS = SOGo
libSOGo_HEADER_FILES = \
SOGoObject.h \
SOGoFolder.h \
SOGoContentObject.h \
SOGoUserFolder.h \
SOGoGroupsFolder.h \
SOGoGroupFolder.h \
SOGoCustomGroupFolder.h \
\
SOGoAppointment.h \
AgenorUserManager.h \
SOGoLRUCache.h \
NSString+iCal.h \
NSObject+AptComparison.h \
WOContext+Agenor.h \
\
SOGoAuthenticator.h \
SOGoUser.h \
libSOGo_OBJC_FILES = \
SOGoObject.m \
SOGoFolder.m \
SOGoContentObject.m \
SOGoUserFolder.m \
SOGoGroupsFolder.m \
SOGoGroupFolder.m \
SOGoCustomGroupFolder.m \
\
SOGoAppointment.m \
SOGoAppointmentICalRenderer.m \
SOGoLRUCache.m \
AgenorUserManager.m \
NSObject+AptComparison.m \
WOContext+Agenor.m \
AgenorUserDefaults.m \
\
SOGoAuthenticator.m \
SOGoUser.m \
# tools
COMMON_TOOL_FILES = \
AgenorUserManager.m \
AgenorUserDefaults.m \
SOGoLRUCache.m \
agenor_email2uid_OBJC_FILES += agenor_email2uid.m $(COMMON_TOOL_FILES)
agenor_shares4uid_OBJC_FILES += agenor_shares4uid.m $(COMMON_TOOL_FILES)
agenor_emails4uid_OBJC_FILES += agenor_emails4uid.m $(COMMON_TOOL_FILES)
agenor_defaults_OBJC_FILES += agenor_defaults.m $(COMMON_TOOL_FILES)
-include GNUmakefile.preamble
include $(GNUSTEP_MAKEFILES)/library.make
include $(GNUSTEP_MAKEFILES)/tool.make
-include GNUmakefile.postamble
-include ../../fhslib.make
-include ../../fhstools.make
+33
View File
@@ -0,0 +1,33 @@
# compilation settings
libSOGo_INCLUDE_DIRS += -I.. -I../../..
ifneq ($(GNUSTEP_BUILD_DIR),)
RELBUILD_DIR_libOGoContentStore = \
$(GNUSTEP_BUILD_DIR)/../../OGoContentStore/$(GNUSTEP_OBJ_DIR_NAME)
else
RELBUILD_DIR_libOGoContentStore = \
../../OGoContentStore/$(GNUSTEP_OBJ_DIR)
endif
SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib
libSOGo_LIB_DIRS += \
-L$(RELBUILD_DIR_libOGoContentStore)
libSOGo_LIBRARIES_DEPEND_UPON += \
-lOGoContentStore \
-lGDLAccess \
-lNGObjWeb \
-lNGiCal \
-lNGMime \
-lNGStreams -lNGExtensions -lEOControl \
-lXmlRpc -lDOM -lSaxObjC \
-lNGLdap
ADDITIONAL_TOOL_LIBS += \
-lGDLContentStore -lGDLAccess \
-lNGLdap \
-lNGExtensions -lEOControl \
-lDOM -lSaxObjC
+34
View File
@@ -0,0 +1,34 @@
/*
Copyright (C) 2004 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
// $Id: NSObject+AptComparison.h 620 2005-03-02 19:57:10Z znek $
#ifndef __SOGo_NSObject_AptComparison_H_
#define __SOGo_NSObject_AptComparison_H_
#import <Foundation/NSObject.h>
@interface NSObject (SOGoAptComparison)
- (NSComparisonResult)compareAptsAscending:(id)_other;
@end
#endif /* __SOGo_NSObject_AptComparison_H_ */
+58
View File
@@ -0,0 +1,58 @@
/*
Copyright (C) 2004 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
// $Id: NSObject+AptComparison.m 620 2005-03-02 19:57:10Z znek $
#include "NSObject+AptComparison.h"
#include <NGExtensions/NGCalendarDateRange.h>
#include "common.h"
@implementation NSObject (SOGoAptComparison)
- (NSComparisonResult)compareAptsAscending:(id)_other {
NSCalendarDate *sd, *ed;
NGCalendarDateRange *r1, *r2;
NSComparisonResult result;
NSTimeInterval t1, t2;
sd = [self valueForKey:@"startDate"];
ed = [self valueForKey:@"endDate"];
r1 = [NGCalendarDateRange calendarDateRangeWithStartDate:sd
endDate:ed];
sd = [_other valueForKey:@"startDate"];
ed = [_other valueForKey:@"endDate"];
r2 = [NGCalendarDateRange calendarDateRangeWithStartDate:sd
endDate:ed];
result = [r1 compare:r2];
if (result != NSOrderedSame)
return result;
t1 = [r1 duration];
t2 = [r2 duration];
if (t1 == t2)
return NSOrderedSame;
if (t1 > t2)
return NSOrderedDescending;
return NSOrderedAscending;
}
@end
+32
View File
@@ -0,0 +1,32 @@
/*
Copyright (C) 2000-2004 SKYRIX Software AG
This file is part of OGo
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
// $Id: NSString+iCal.h 577 2005-02-17 14:38:14Z helge $
#ifndef __NSString_iCal_H_
#define __NSString_iCal_H_
// DEPRECATED
#import <Foundation/Foundation.h>
#include <NGiCal/iCalRenderer.h>
#endif /* __NSString_iCal_H_ */
+29
View File
@@ -0,0 +1,29 @@
libSOGo
=======
Common SOGo objects.
NOTE: the SOPE objects are registered by the Main bundle products.plist.
Class Hierarchy
===============
[NSObject]
SOGoObject
SOGoContentObject
SOGoFolder
SOGoUserFolder - the "home" directory
SOGoGroupsFolder - intermediate folder
SOGoGroupFolder - a folder representing a set of people
SOGoCustomGroupFolder - a custom group (eg '_custom_helge,znek')
TODO
====
- why is SOGoUserFolder an OCS folder?
Defaults
========
AgenorCacheCheckInterval - int (default: 1 hour == 3600s)
- how often to flush the LDAP caches
+145
View File
@@ -0,0 +1,145 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#ifndef __SOGoAppointment_H_
#define __SOGoAppointment_H_
#import <Foundation/NSObject.h>
#import <Foundation/NSDate.h>
/*
SOGoAppointment
Wrapper around the iCalendar content of appointments stored in the
OGoContentStore.
*/
@class NSString, NSArray, NSCalendarDate, NGCalendarDateRange;
@class iCalPerson, iCalEvent, iCalRecurrenceRule;
@interface SOGoAppointment : NSObject <NSCopying>
{
id calendar;
iCalEvent *event;
id participants;
}
- (id)initWithICalString:(NSString *)_iCal;
- (void)setUid:(NSString *)_value;
- (NSString *)uid;
- (void)setSummary:(NSString *)_value;
- (NSString *)summary;
- (void)setLocation:(NSString *)_value;
- (NSString *)location;
- (BOOL)hasLocation;
- (void)setComment:(NSString *)_value;
- (NSString *)comment;
- (BOOL)hasComment;
- (void)setUserComment:(NSString *)_userComment;
- (NSString *)userComment;
- (void)setPriority:(NSString *)_value;
- (NSString *)priority;
- (BOOL)hasPriority;
- (void)setCategories:(NSArray *)_value;
- (NSArray *)categories;
- (BOOL)hasCategories;
- (void)setStatus:(NSString *)_value;
- (NSString *)status;
- (void)setStartDate:(NSCalendarDate *)_date;
- (NSCalendarDate *)startDate;
- (void)setEndDate:(NSCalendarDate *)_date;
- (NSCalendarDate *)endDate;
- (BOOL)hasEndDate;
- (BOOL)hasDuration;
- (void)setDuration:(NSTimeInterval)_duration;
- (NSTimeInterval)duration;
- (void)setOrganizer:(iCalPerson *)_organizer;
- (iCalPerson *)organizer;
- (void)setAccessClass:(NSString *)_value;
- (NSString *)accessClass;
- (BOOL)isPublic;
- (void)setTransparency:(NSString *)_value;
- (NSString *)transparency;
- (BOOL)isTransparent;
- (void)setMethod:(NSString *)_method;
- (NSString *)method;
- (void)removeAllAttendees;
- (void)addToAttendees:(iCalPerson *)_person;
- (void)appendAttendees:(NSArray *)_persons;
- (void)setAttendees:(NSArray *)_persons;
- (NSArray *)attendees;
/* attendees -> role != NON-PART */
- (NSArray *)participants;
/* attendees -> role == NON-PART */
- (NSArray *)resources;
/* simplified recurrence API */
- (void)setRecurrenceRule:(iCalRecurrenceRule *)_rrule;
- (iCalRecurrenceRule *)recurrenceRule;
- (BOOL)hasRecurrenceRule;
- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r;
/* iCal generation */
- (NSString *)iCalString;
- (NSString *)vEventString;
/* raw entity objects */
- (id)calendar;
- (id)event;
/* checking */
- (BOOL)isOrganizer:(id)_email;
- (BOOL)isParticipant:(id)_email;
/* searching */
- (iCalPerson *)findParticipantWithEmail:(id)_email;
/* actions */
- (void)increaseSequence;
- (void)cancelWithoutIncreasingSequence;
- (void)cancelAndIncreaseSequence;
@end
#endif /* __SOGoAppointment_H_ */
+486
View File
@@ -0,0 +1,486 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "SOGoAppointment.h"
#include <SaxObjC/SaxObjC.h>
#include <NGiCal/NGiCal.h>
#include <EOControl/EOControl.h>
#include "SOGoAppointmentICalRenderer.h"
#include "common.h"
@interface SOGoAppointment (PrivateAPI)
- (NSArray *)_filteredAttendeesThinkingOfPersons:(BOOL)_persons;
@end
@implementation SOGoAppointment
static id<NSObject,SaxXMLReader> parser = nil;
static SaxObjectDecoder *sax = nil;
static NGLogger *logger = nil;
+ (void)initialize {
NGLoggerManager *lm;
SaxXMLReaderFactory *factory;
static BOOL didInit = NO;
if (didInit) return;
didInit = YES;
lm = [NGLoggerManager defaultLoggerManager];
logger = [lm loggerForClass:self];
factory = [SaxXMLReaderFactory standardXMLReaderFactory];
parser = [[factory createXMLReaderForMimeType:@"text/calendar"]
retain];
if (parser == nil)
[logger fatalWithFormat:@"did not find a parser for text/calendar!"];
sax = [[SaxObjectDecoder alloc] initWithMappingNamed:@"NGiCal"];
if (sax == nil)
[logger fatalWithFormat:@"could not create the iCal SAX handler!"];
[parser setContentHandler:sax];
[parser setErrorHandler:sax];
}
- (id)initWithICalRootObject:(id)_root {
if ((self = [super init])) {
#if 0
[self logWithFormat:@"root is: %@", root];
#endif
if ([_root isKindOfClass:[iCalEvent class]]) {
self->event = [_root retain];
}
else if ([_root isKindOfClass:[NSDictionary class]]) {
/* multiple vevents in the calendar */
[self errorWithFormat:
@"(%s): tried to initialize with multiple records: %@",
__PRETTY_FUNCTION__, _root];
[self release];
return nil;
}
else {
self->calendar = [_root retain];
self->event = [[[self->calendar events] lastObject] retain];
}
}
return self;
}
- (id)initWithICalString:(NSString *)_iCal {
id root;
if ([_iCal length] == 0) {
[self errorWithFormat:@"tried to init SOGoAppointment without iCal"];
[self release];
return nil;
}
if (parser == nil || sax == nil) {
[self errorWithFormat:@"iCal parser not properly set up!"];
[self release];
return nil;
}
if ([_iCal length] > 0) {
[parser parseFromSource:_iCal];
root = [[sax rootObject] retain]; /* retain to keep it around */
[sax reset];
}
else
root = nil;
self = [self initWithICalRootObject:root];
[root release];
return self;
}
- (void)dealloc {
[self->calendar release];
[self->event release];
[self->participants release];
[super dealloc];
}
/* NSCopying */
- (id)copyWithZone:(NSZone *)_zone {
SOGoAppointment *new;
new = [[[self class] allocWithZone:_zone] init];
new->calendar = [self->calendar copyWithZone:_zone];
new->event = [self->event copyWithZone:_zone];
new->participants = [self->participants copyWithZone:_zone];
return new;
}
/* accessors */
- (id)calendar {
return self->calendar;
}
- (id)event {
return self->event;
}
- (NSString *)iCalString {
return [[SOGoAppointmentICalRenderer sharedAppointmentRenderer]
stringForAppointment:self];
}
- (NSString *)vEventString {
return [[SOGoAppointmentICalRenderer sharedAppointmentRenderer]
vEventStringForAppointment:self];
}
/* forwarded methods */
- (void)setUid:(NSString *)_value {
[self->event setUid:_value];
}
- (NSString *)uid {
return [self->event uid];
}
- (void)setSummary:(NSString *)_value {
[self->event setSummary:_value];
}
- (NSString *)summary {
return [self->event summary];
}
- (void)setLocation:(NSString *)_value {
[self->event setLocation:_value];
}
- (NSString *)location {
return [self->event location];
}
- (BOOL)hasLocation {
if (![[self location] isNotNull])
return NO;
return [[self location] length] > 0 ? YES : NO;
}
- (void)setComment:(NSString *)_value {
if([_value length] == 0)
_value = nil;
[self->event setComment:_value];
}
- (NSString *)comment {
return [self->event comment];
}
- (BOOL)hasComment {
NSString *s = [self comment];
if(!s || [s length] == 0)
return NO;
return YES;
}
- (void)setUserComment:(NSString *)_userComment {
[self->event setUserComment:_userComment];
}
- (NSString *)userComment {
return [self->event userComment];
}
- (void)setPriority:(NSString *)_value {
[self->event setPriority:_value];
}
- (NSString *)priority {
return [self->event priority];
}
- (BOOL)hasPriority {
NSString *prio = [self priority];
NSRange r;
if(!prio)
return NO;
r = [prio rangeOfString:@";"];
if(r.length > 0) {
prio = [prio substringToIndex:r.location];
}
return [prio isEqualToString:@"0"] ? NO : YES;
}
- (void)setCategories:(NSArray *)_value {
NSString *catString;
if(!_value || [_value count] == 0) {
[self->event setCategories:nil];
return;
}
_value = [_value sortedArrayUsingSelector:@selector(compareAscending:)];
catString = [_value componentsJoinedByString:@","];
[self->event setCategories:catString];
}
- (NSArray *)categories {
NSString *catString;
NSArray *cats;
NSRange r;
catString = [self->event categories];
if (![catString isNotNull])
return [NSArray array];
r = [[catString stringValue] rangeOfString:@";"];
if(r.length > 0) {
catString = [catString substringToIndex:r.location];
}
cats = [catString componentsSeparatedByString:@","];
return cats;
}
- (BOOL)hasCategories {
return [self->event categories] != nil ? YES : NO;
}
- (void)setStatus:(NSString *)_value {
[self->event setStatus:_value];
}
- (NSString *)status {
return [self->event status];
}
- (void)setStartDate:(NSCalendarDate *)_date {
[self->event setStartDate:_date];
}
- (NSCalendarDate *)startDate {
return [self->event startDate];
}
- (void)setEndDate:(NSCalendarDate *)_date {
[self->event setEndDate:_date];
}
- (NSCalendarDate *)endDate {
return [self->event endDate];
}
- (BOOL)hasEndDate {
return [self->event hasEndDate];
}
- (void)setDuration:(NSTimeInterval)_duration {
// TODO
[self warnWithFormat:@"could not apply duration!"];
}
- (BOOL)hasDuration {
return [self->event hasDuration];
}
- (NSTimeInterval)duration {
return [self->event durationAsTimeInterval];
}
- (void)setAccessClass:(NSString *)_value {
[self->event setAccessClass:_value];
}
- (NSString *)accessClass {
NSString *s;
s = [self->event accessClass];
if(!s)
s = @"PUBLIC"; /* default for agenor */
return s;
}
- (BOOL)isPublic {
return [[self accessClass] isEqualToString:@"PUBLIC"];
}
- (void)setTransparency:(NSString *)_value {
[self->event setTransparency:_value];
}
- (NSString *)transparency {
return [self->event transparency];
}
- (BOOL)isTransparent {
return [[self transparency] isEqualToString:@"TRANSPARENT"];
}
- (void)setMethod:(NSString *)_method {
[self->calendar setMethod:_method];
}
- (NSString *)method {
return [self->calendar method];
}
- (void)setOrganizer:(iCalPerson *)_organizer {
[self->event setOrganizer:_organizer];
}
- (iCalPerson *)organizer {
return [self->event organizer];
}
- (void)removeAllAttendees {
[self setAttendees:nil];
}
- (void)addToAttendees:(iCalPerson *)_person {
[self->event addToAttendees:_person];
}
- (void)appendAttendees:(NSArray *)_persons {
unsigned i, count;
count = [_persons count];
for (i = 0; i < count; i++)
[self addToAttendees:[_persons objectAtIndex:i]];
}
- (void)setAttendees:(NSArray *)_persons {
[self->event removeAllAttendees];
if ([_persons count] > 0)
[self appendAttendees:_persons];
}
- (NSArray *)attendees {
return [self->event attendees];
}
- (NSArray *)participants {
if (self->participants != nil)
return self->participants;
self->participants = [[self _filteredAttendeesThinkingOfPersons:YES] retain];
return self->participants;
}
- (BOOL)hasParticipants {
return [[self participants] count] != 0;
}
- (NSArray *)resources {
return [self _filteredAttendeesThinkingOfPersons:NO];
}
- (NSArray *)_filteredAttendeesThinkingOfPersons:(BOOL)_persons {
NSArray *list;
NSMutableArray *filtered;
unsigned i, count;
list = [self attendees];
count = [list count];
filtered = [NSMutableArray arrayWithCapacity:count];
for (i = 0; i < count; i++) {
iCalPerson *p;
NSString *role;
p = [list objectAtIndex:i];
role = [p role];
if (_persons) {
if (role == nil || ![role hasPrefix:@"NON-PART"])
[filtered addObject:p];
}
else {
if ([role hasPrefix:@"NON-PART"])
[filtered addObject:p];
}
}
return filtered;
}
- (BOOL)isOrganizer:(id)_email {
return [[[self organizer] rfc822Email] isEqualToString:_email];
}
- (BOOL)isParticipant:(id)_email {
NSArray *partEmails;
_email = [_email lowercaseString];
partEmails = [[self participants] valueForKey:@"rfc822Email"];
partEmails = [partEmails valueForKey:@"lowercaseString"];
return [partEmails containsObject:_email];
}
- (iCalPerson *)findParticipantWithEmail:(id)_email {
NSArray *ps;
unsigned i, count;
_email = [_email lowercaseString];
ps = [self participants];
count = [ps count];
for (i = 0; i < count; i++) {
iCalPerson *p;
p = [ps objectAtIndex:i];
if ([[[p rfc822Email] lowercaseString] isEqualToString:_email])
return p;
}
return nil; /* not found */
}
/*
NOTE: this is not the same API as used by NGiCal!
SOGo/OGo cannot deal with the complete NGiCal API properly, although
SOGo COULD do so in the future
*/
- (void)setRecurrenceRule:(iCalRecurrenceRule *)_rrule {
[_rrule retain];
[self->event removeAllRecurrenceRules];
if (_rrule)
[self->event addToRecurrenceRules:_rrule];
[_rrule release];
}
- (iCalRecurrenceRule *)recurrenceRule {
if ([self->event hasRecurrenceRules])
return [[self->event recurrenceRules] objectAtIndex:0];
return nil;
}
- (BOOL)hasRecurrenceRule {
return [self recurrenceRule] != nil;
}
- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r {
return [self->event recurrenceRangesWithinCalendarDateRange:_r];
}
/* actions */
- (void)increaseSequence {
[self->event increaseSequence];
}
- (void)cancelWithoutIncreasingSequence {
[self setMethod:@"CANCEL"];
}
- (void)cancelAndIncreaseSequence {
[self cancelWithoutIncreasingSequence];
[self increaseSequence];
}
/* description */
- (void)appendAttributesToDescription:(NSMutableString *)_ms {
[_ms appendFormat:@" uid=%@", [self uid]];
[_ms appendFormat:@" date=%@", [self startDate]];
}
- (NSString *)description {
NSMutableString *ms;
ms = [NSMutableString stringWithCapacity:64];
[ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
[self appendAttributesToDescription:ms];
[ms appendString:@">"];
return ms;
}
/* logging */
- (id)logger {
return logger;
}
@end /* SOGoAppointment */
@@ -0,0 +1,46 @@
/*
Copyright (C) 2004 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
// $Id: SOGoAppointment.h 207 2004-08-14 15:37:04Z znek $
#ifndef __SOGoAppointmentICalRenderer_H_
#define __SOGoAppointmentICalRenderer_H_
#import <Foundation/NSObject.h>
/*
SOGoAppointmentICalRenderer
Transform an SOGoAppointment into an iCalendar formatted string.
*/
@class NSString;
@class SOGoAppointment;
@interface SOGoAppointmentICalRenderer : NSObject
+ (id)sharedAppointmentRenderer;
- (NSString *)vEventStringForAppointment:(SOGoAppointment *)_apt;
- (NSString *)stringForAppointment:(SOGoAppointment *)_apt;
@end
#endif /* __SOGoAppointmentICalRenderer_H_ */
@@ -0,0 +1,257 @@
/*
Copyright (C) 2004 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "SOGoAppointmentICalRenderer.h"
#include "SOGoAppointment.h"
#include <NGiCal/NGiCal.h>
#include <NGiCal/iCalRenderer.h>
#include "common.h"
// TODO: the basic renderer should be part of NGiCal
@interface NSDate(UsedPrivates)
- (NSString *)icalString; // declared in NGiCal
@end
@implementation SOGoAppointmentICalRenderer
static SOGoAppointmentICalRenderer *renderer = nil;
/* assume length of 1K - reasonable ? */
static unsigned DefaultICalStringCapacity = 1024;
+ (id)sharedAppointmentRenderer {
if (renderer == nil)
renderer = [[self alloc] init];
return renderer;
}
/* renderer */
- (void)addPreambleForAppointment:(SOGoAppointment *)_apt
toString:(NSMutableString *)s
{
iCalCalendar *calendar;
NSString *x;
calendar = [_apt calendar];
[s appendString:@"BEGIN:VCALENDAR\r\n"];
[s appendString:@"METHOD:"];
if((x = [calendar method]))
[s appendString:[x iCalSafeString]];
else
[s appendString:@"REQUEST"];
[s appendString:@"\r\n"];
[s appendString:@"PRODID:"];
[s appendString:[calendar isNotNull] ? [calendar prodId] : @"SOGo/0.9"];
[s appendString:@"\r\n"];
[s appendString:@"VERSION:"];
[s appendString:[calendar isNotNull] ? [calendar version] : @"2.0"];
[s appendString:@"\r\n"];
}
- (void)addPostambleForAppointment:(SOGoAppointment *)_apt
toString:(NSMutableString *)s
{
[s appendString:@"END:VCALENDAR\r\n"];
}
- (void)addOrganizer:(iCalPerson *)p toString:(NSMutableString *)s {
NSString *x;
if (![p isNotNull]) return;
[s appendString:@"ORGANIZER;CN=\""];
if ((x = [p cn]))
[s appendString:[x iCalDQUOTESafeString]];
[s appendString:@"\""];
if ((x = [p email])) {
[s appendString:@":"]; /* sic! */
[s appendString:[x iCalSafeString]];
}
[s appendString:@"\r\n"];
}
- (void)addAttendees:(NSArray *)persons toString:(NSMutableString *)s {
unsigned i, count;
iCalPerson *p;
count = [persons count];
for (i = 0; i < count; i++) {
NSString *x;
p = [persons objectAtIndex:i];
[s appendString:@"ATTENDEE;"];
if ((x = [p role])) {
[s appendString:@"ROLE="];
[s appendString:[x iCalSafeString]];
[s appendString:@";"];
}
if ((x = [p partStat])) {
if ([p participationStatus] != iCalPersonPartStatNeedsAction) {
[s appendString:@"PARTSTAT="];
[s appendString:[x iCalSafeString]];
[s appendString:@";"];
}
}
[s appendString:@"CN=\""];
if ((x = [p cnWithoutQuotes])) {
[s appendString:[x iCalDQUOTESafeString]];
}
[s appendString:@"\""];
if ([(x = [p email]) isNotNull]) {
[s appendString:@":"]; /* sic! */
[s appendString:[x iCalSafeString]];
}
[s appendString:@"\r\n"];
}
}
- (void)addVEventForAppointment:(SOGoAppointment *)_apt
toString:(NSMutableString *)s
{
iCalEvent *event;
event = [_apt event];
[s appendString:@"BEGIN:VEVENT\r\n"];
[s appendString:@"SUMMARY:"];
[s appendString:[[_apt summary] iCalSafeString]];
[s appendString:@"\r\n"];
if ([_apt hasLocation]) {
[s appendString:@"LOCATION:"];
[s appendString:[[_apt location] iCalSafeString]];
[s appendString:@"\r\n"];
}
[s appendString:@"UID:"];
[s appendString:[_apt uid]];
[s appendString:@"\r\n"];
[s appendString:@"DTSTART:"];
[s appendString:[[_apt startDate] icalString]];
[s appendString:@"\r\n"];
if ([_apt hasEndDate]) {
[s appendString:@"DTEND:"];
[s appendString:[[_apt endDate] icalString]];
[s appendString:@"\r\n"];
}
if ([_apt hasDuration]) {
[s appendString:@"DURATION:"];
[s appendString:[event duration]];
[s appendString:@"\r\n"];
}
if([_apt hasPriority]) {
[s appendString:@"PRIORITY:"];
[s appendString:[_apt priority]];
[s appendString:@"\r\n"];
}
if([_apt hasCategories]) {
NSString *catString;
catString = [[_apt categories] componentsJoinedByString:@","];
[s appendString:@"CATEGORIES:"];
[s appendString:catString];
[s appendString:@"\r\n"];
}
if([_apt hasComment]) {
[s appendString:@"DESCRIPTION:"]; /* this is what iCal.app does */
[s appendString:[[_apt comment] iCalSafeString]];
[s appendString:@"\r\n"];
}
[s appendString:@"STATUS:"];
[s appendString:[_apt status]];
[s appendString:@"\r\n"];
[s appendString:@"TRANSP:"];
[s appendString:[_apt transparency]];
[s appendString:@"\r\n"];
[s appendString:@"CLASS:"];
[s appendString:[_apt accessClass]];
[s appendString:@"\r\n"];
/* recurrence rules */
if ([_apt hasRecurrenceRule]) {
[s appendString:@"RRULE:"];
[s appendString:[[_apt recurrenceRule] iCalRepresentation]];
[s appendString:@"\r\n"];
}
[self addOrganizer:[_apt organizer] toString:s];
[self addAttendees:[_apt attendees] toString:s];
/* postamble */
[s appendString:@"END:VEVENT\r\n"];
}
- (BOOL)isValidAppointment:(SOGoAppointment *)_apt {
if (![_apt isNotNull])
return NO;
if ([[_apt uid] length] == 0) {
[self warnWithFormat:@"got apt without uid, rejecting iCal generation: %@",
_apt];
return NO;
}
if ([[[_apt startDate] icalString] length] == 0) {
[self warnWithFormat:@"got apt without start date, "
@"rejecting iCal generation: %@",
_apt];
return NO;
}
return YES;
}
- (NSString *)vEventStringForAppointment:(SOGoAppointment *)_apt {
NSMutableString *s;
if (![self isValidAppointment:_apt])
return nil;
s = [NSMutableString stringWithCapacity:DefaultICalStringCapacity];
[self addVEventForAppointment:_apt toString:s];
return s;
}
- (NSString *)stringForAppointment:(SOGoAppointment *)_apt {
NSMutableString *s;
if (![self isValidAppointment:_apt])
return nil;
s = [NSMutableString stringWithCapacity:DefaultICalStringCapacity];
[self addPreambleForAppointment:_apt toString:s];
[self addVEventForAppointment:_apt toString:s];
[self addPostambleForAppointment:_apt toString:s];
return s;
}
@end /* SOGoAppointmentICalRenderer */
+42
View File
@@ -0,0 +1,42 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#ifndef __Main_SOGoAuthenticator_H__
#define __Main_SOGoAuthenticator_H__
#include <NGObjWeb/SoHTTPAuthenticator.h>
/*
SOGoAuthenticator
This just overrides the login/pwd check method and always returns YES since
the password is already checked in Apache.
*/
@interface SOGoAuthenticator : SoHTTPAuthenticator
{
}
+ (id)sharedSOGoAuthenticator;
@end
#endif /* __Main_SOGoAuthenticator_H__ */
+69
View File
@@ -0,0 +1,69 @@
/*
Copyright (C) 2004 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "SOGoAuthenticator.h"
#include "SOGoUser.h"
#include "common.h"
@implementation SOGoAuthenticator
static SOGoAuthenticator *auth = nil; // THREAD
+ (id)sharedSOGoAuthenticator {
if (auth == nil)
auth = [[self alloc] init];
return auth;
}
/* check credentials */
- (BOOL)checkLogin:(NSString *)_login password:(NSString *)_pwd {
if ([_login length] == 0)
return NO;
/* we accept any password since it is checked by Apache in front */
return YES;
}
/* create SOGoUser */
- (SoUser *)userInContext:(WOContext *)_ctx {
static SoUser *anonymous = nil;
NSString *login;
NSArray *uroles;
if (anonymous == nil) {
NSArray *ar = [NSArray arrayWithObject:SoRole_Anonymous];
anonymous = [[SOGoUser alloc] initWithLogin:@"anonymous" roles:ar];
}
if ((login = [self checkCredentialsInContext:_ctx]) == nil)
/* some error (otherwise result would have been anonymous */
return nil;
if ([login isEqualToString:@"anonymous"])
return anonymous;
uroles = [self rolesForLogin:login];
return [[[SOGoUser alloc] initWithLogin:login roles:uroles] autorelease];
}
@end /* SOGoAuthenticator */
+64
View File
@@ -0,0 +1,64 @@
/*
Copyright (C) 2004 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
// $Id: SOGoContentObject.h 851 2005-07-20 14:51:39Z helge $
#ifndef __SOGo_SOGoContentObject_H__
#define __SOGo_SOGoContentObject_H__
#include <SOGo/SOGoObject.h>
@class NSString, NSException;
@interface SOGoContentObject : SOGoObject
{
NSString *ocsPath;
NSString *content;
}
/* accessors */
- (void)setOCSPath:(NSString *)_path;
- (NSString *)ocsPath;
/* folder */
- (NSString *)ocsPathOfContainer;
- (GCSFolder *)ocsFolder;
/* content */
- (NSString *)contentAsString;
- (NSException *)saveContentString:(NSString *)_str
baseVersion:(unsigned int)_baseVersion;
- (NSException *)saveContentString:(NSString *)_str;
- (NSException *)delete;
/* etag support */
- (id)davEntityTag;
/* message type */
- (NSString *)outlookMessageClass;
@end
#endif /* __SOGo_SOGoContentObject_H__ */
+305
View File
@@ -0,0 +1,305 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "SOGoContentObject.h"
#include "SOGoFolder.h"
#include "common.h"
#include <GDLContentStore/GCSFolder.h>
@interface SOGoContentObject(ETag)
- (NSArray *)parseETagList:(NSString *)_c;
@end
@implementation SOGoContentObject
// TODO: check superclass version
- (void)dealloc {
[self->content release];
[self->ocsPath release];
[super dealloc];
}
/* notifications */
- (void)sleep {
[self->content release]; self->content = nil;
[super sleep];
}
/* accessors */
- (BOOL)isFolderish {
return NO;
}
- (void)setOCSPath:(NSString *)_path {
if ([self->ocsPath isEqualToString:_path])
return;
if (self->ocsPath)
[self warnWithFormat:@"GCS path is already set! '%@'", _path];
ASSIGNCOPY(self->ocsPath, _path);
}
- (NSString *)ocsPath {
if (self->ocsPath == nil) {
NSString *p;
if ((p = [self ocsPathOfContainer]) != nil) {
if (![p hasSuffix:@"/"]) p = [p stringByAppendingString:@"/"];
p = [p stringByAppendingString:[self nameInContainer]];
self->ocsPath = [p copy];
}
}
return self->ocsPath;
}
- (NSString *)ocsPathOfContainer {
if (![[self container] respondsToSelector:@selector(ocsPath)])
return nil;
return [[self container] ocsPath];
}
- (GCSFolder *)ocsFolder {
if (![[self container] respondsToSelector:@selector(ocsFolder)])
return nil;
return [[self container] ocsFolder];
}
/* content */
- (NSString *)contentAsString {
GCSFolder *folder;
if (self->content != nil)
return self->content;
if ((folder = [self ocsFolder]) == nil) {
[self errorWithFormat:@"Did not find folder of content object."];
return nil;
}
self->content = [[folder fetchContentWithName:[self nameInContainer]] copy];
return self->content;
}
- (NSException *)saveContentString:(NSString *)_str
baseVersion:(unsigned int)_baseVersion
{
/* Note: "iCal multifolder saves" are implemented in the apt subclass! */
GCSFolder *folder;
NSException *ex;
if ((folder = [self ocsFolder]) == nil) {
[self errorWithFormat:@"Did not find folder of content object."];
return nil;
}
ex = [folder writeContent:_str toName:[self nameInContainer]
baseVersion:_baseVersion];
if (ex != nil) {
[self errorWithFormat:@"write failed: %@", ex];
return ex;
}
return nil;
}
- (NSException *)saveContentString:(NSString *)_str {
return [self saveContentString:_str baseVersion:0 /* don't check */];
}
- (NSException *)delete {
/* Note: "iCal multifolder saves" are implemented in the apt subclass! */
GCSFolder *folder;
NSException *ex;
// TODO: add precondition check? (or add DELETEAction?)
if ((folder = [self ocsFolder]) == nil) {
[self errorWithFormat:@"Did not find folder of content object."];
return nil;
}
if ((ex = [folder deleteContentWithName:[self nameInContainer]])) {
[self errorWithFormat:@"delete failed: %@", ex];
return ex;
}
return nil;
}
/* actions */
- (id)PUTAction:(WOContext *)_ctx {
WORequest *rq;
NSException *error;
unsigned int baseVersion;
id etag, tmp;
BOOL needsLocation;
if ((error = [self matchesRequestConditionInContext:_ctx]) != nil)
return error;
rq = [_ctx request];
/* check whether its a request to the 'special' 'new' location */
/*
Note: this is kinda hack. The OGo ZideStore detects writes to 'new' as
object creations and will assign a server side identifier. Most
current GroupDAV clients rely on this behaviour, so we reproduce it
here.
A correct client would loop until it has a name which doesn't not
yet exist (by using if-none-match).
*/
needsLocation = NO;
tmp = [[self nameInContainer] stringByDeletingPathExtension];
if ([tmp isEqualToString:@"new"]) {
tmp = [[[self container] class] globallyUniqueObjectId];
needsLocation = YES;
[self debugWithFormat:
@"reassigned a new location for special new-location: %@", tmp];
/* kinda dangerous */
ASSIGNCOPY(self->nameInContainer, tmp);
ASSIGN(self->ocsPath, nil);
}
/* determine base version from etag in if-match header */
/*
Note: The -matchesRequestConditionInContext: already checks whether the
etag matches and returns an HTTP exception in case it doesn't.
We retrieve the etag again here to _ensure_ a transactionally save
commit.
(between the check and the update a change could have been done)
*/
tmp = [rq headerForKey:@"if-match"];
tmp = [self parseETagList:tmp];
etag = nil;
if ([tmp count] > 0) {
if ([tmp count] > 1) {
/*
Note: we would have to attempt a save for _each_ of the etags being
passed in! In practice most WebDAV clients submit exactly one
etag.
*/
[self warnWithFormat:
@"Got multiple if-match etags from client, only attempting to "
@"save with the first: %@", tmp];
}
etag = [tmp objectAtIndex:0];
}
baseVersion = ([etag length] > 0)
? [etag unsignedIntValue]
: 0 /* 0 means 'do not check' */;
/* attempt a save */
if ((error = [self saveContentString:[rq contentAsString]
baseVersion:baseVersion]) != nil)
return error;
/* setup response */
// TODO: this should be automatic in the SoDispatcher if we return nil?
[[_ctx response] setStatus:201 /* Created */];
if ((etag = [self davEntityTag]) != nil)
[[_ctx response] setHeader:etag forKey:@"etag"];
if (needsLocation) {
[[_ctx response] setHeader:[self baseURLInContext:_ctx]
forKey:@"location"];
}
return [_ctx response];
}
/* E-Tags */
- (id)davEntityTag {
// TODO: cache tag in ivar? => if you do, remember to flush after PUT
GCSFolder *folder;
char buf[64];
if ((folder = [self ocsFolder]) == nil) {
[self errorWithFormat:@"Did not find folder of content object."];
return nil;
}
sprintf(buf, "\"gcs%08d\"",
[[folder versionOfContentWithName:[self nameInContainer]]
unsignedIntValue]);
return [NSString stringWithCString:buf];
}
/* WebDAV */
- (NSException *)davMoveToTargetObject:(id)_target newName:(NSString *)_name
inContext:(id)_ctx
{
/*
Note: even for new objects we won't get a new name but a preinstantiated
object representing the new one.
*/
[self logWithFormat:
@"TODO: move not implemented:\n target: %@\n new name: %@",
_target, _name];
return [NSException exceptionWithHTTPStatus:405 /* not allowed */
reason:@"this object cannot be copied via WebDAV"];
}
- (NSException *)davCopyToTargetObject:(id)_target newName:(NSString *)_name
inContext:(id)_ctx
{
/*
Note: even for new objects we won't get a new name but a preinstantiated
object representing the new one.
*/
[self logWithFormat:
@"TODO: copy not implemented:\n target: %@\n new name: %@",
_target, _name];
return [NSException exceptionWithHTTPStatus:405 /* not allowed */
reason:@"this object cannot be copied via WebDAV"];
}
- (BOOL)davIsCollection {
return [self isFolderish];
}
/* message type */
- (NSString *)outlookMessageClass {
return nil;
}
/* description */
- (void)appendAttributesToDescription:(NSMutableString *)_ms {
[super appendAttributesToDescription:_ms];
[_ms appendFormat:@" ocs=%@", [self ocsPath]];
}
@end /* SOGoContentObject */
+59
View File
@@ -0,0 +1,59 @@
/*
Copyright (C) 2004 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
// $Id: SOGoCustomGroupFolder.h 107 2004-06-30 10:26:46Z helge $
#ifndef __SOGo_SOGoCustomGroupFolder_H__
#define __SOGo_SOGoCustomGroupFolder_H__
#include <SOGo/SOGoGroupFolder.h>
/*
SOGoCustomGroupFolder
same parent/child like SOGoGroupFolder
Note: parent folder can be different if instantiated for internal use.
Note: you can use this folder for internal handling of groups! Eg aggregate
Calendar fetches.
This is a specific group folder for 'custom' groups. Group members are
currently encoded as the folder name in the URL like
_custom_znek,helge
*/
@class NSArray;
@interface SOGoCustomGroupFolder : SOGoGroupFolder
{
NSArray *uids;
}
- (id)initWithUIDs:(NSArray *)_uids inContainer:(id)_container;
/* accessors */
- (NSArray *)uids;
/* pathes */
@end
#endif /* __SOGo_SOGoCustomGroupFolder_H__ */
+108
View File
@@ -0,0 +1,108 @@
/*
Copyright (C) 2004 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
// $Id: SOGoCustomGroupFolder.m 115 2004-06-30 11:57:37Z helge $
#include "SOGoCustomGroupFolder.h"
#include "common.h"
@implementation SOGoCustomGroupFolder
static NSString *SOGoUIDSeparator = @",";
- (id)initWithUIDs:(NSArray *)_uids inContainer:(id)_container {
if ((self = [self initWithName:nil inContainer:_container])) {
self->uids = [_uids copy];
}
return self;
}
- (void)dealloc {
[self->uids release];
[super dealloc];
}
/* accessors */
- (NSArray *)unescapeURLComponents:(NSArray *)_parts {
#warning TODO: implement URL UID unescaping if necessary
// TODO: who calls this for what?
// Note: remember URL encoding!
return _parts;
}
- (NSArray *)uids {
NSArray *a;
NSString *s;
if (self->uids != nil)
return self->uids;
s = [self nameInContainer];
if (![s hasPrefix:@"_custom_"]) {
[self logWithFormat:@"WARNING: incorrect custom group folder name: '%@'",
s];
return nil;
}
s = [s substringFromIndex:8];
a = [s componentsSeparatedByString:SOGoUIDSeparator];
a = [self unescapeURLComponents:a];
self->uids = [a copy];
if ([self->uids count] < 2)
[self debugWithFormat:@"Note: less than two custom group members!"];
return self->uids;
}
/* display name */
- (NSString *)davDisplayName {
NSArray *a;
unsigned count;
a = [self uids];
if ((count = [a count]) == 0)
return @"empty";
if (count == 1)
return [a objectAtIndex:0];
if (count < 6) {
NSMutableString *ms;
unsigned i;
ms = [NSMutableString stringWithCapacity:64];
for (i = 0; i < count; i++) {
if (i != 0) [ms appendString:@"|"];
[ms appendString:[a objectAtIndex:i]];
if ([ms length] > 60) {
ms = nil;
break;
}
}
if (ms != nil) return ms;
}
// TODO: localize 'members' (UI component task?)
return [NSString stringWithFormat:@"Members: %d", count];
}
@end /* SOGoCustomGroupFolder */
+67
View File
@@ -0,0 +1,67 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#ifndef __SOGo_SOGoFolder_H__
#define __SOGo_SOGoFolder_H__
#include <SOGo/SOGoObject.h>
@class NSString, NSArray, NSDictionary;
@class GCSFolder;
/*
SOGoFolder
A common superclass for folders stored in GCS. Already deals with all GCS
folder specific things.
Important: folders should NOT retain the context! Otherwise you might get
cyclic references.
*/
@interface SOGoFolder : SOGoObject
{
NSString *ocsPath;
GCSFolder *ocsFolder;
}
+ (NSString *)globallyUniqueObjectId;
/* accessors */
- (void)setOCSPath:(NSString *)_Path;
- (NSString *)ocsPath;
- (GCSFolder *)ocsFolderForPath:(NSString *)_path;
- (GCSFolder *)ocsFolder;
/* lower level fetches */
- (NSArray *)fetchContentObjectNames;
- (NSDictionary *)fetchContentStringsAndNamesOfAllObjects;
/* folder type */
- (NSString *)outlookFolderClass;
@end
#endif /* __SOGo_SOGoFolder_H__ */
+194
View File
@@ -0,0 +1,194 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "SOGoFolder.h"
#include "common.h"
#include <GDLContentStore/GCSFolderManager.h>
#include <GDLContentStore/GCSFolder.h>
#include <unistd.h>
#include <stdlib.h>
@implementation SOGoFolder
+ (int)version {
return [super version] + 0 /* v0 */;
}
+ (void)initialize {
NSAssert2([super version] == 0,
@"invalid superclass (%@) version %i !",
NSStringFromClass([self superclass]), [super version]);
}
+ (NSString *)globallyUniqueObjectId {
/*
4C08AE1A-A808-11D8-AC5A-000393BBAFF6
SOGo-Web-28273-18283-288182
printf( "%x", *(int *) &f);
*/
static int pid = 0;
static int sequence = 0;
static float rndm = 0;
float f;
if (pid == 0) { /* break if we fork ;-) */
pid = getpid();
rndm = random();
}
sequence++;
f = [[NSDate date] timeIntervalSince1970];
return [NSString stringWithFormat:@"%0X-%0X-%0X-%0X",
pid, *(int *)&f, sequence++, random];
}
- (void)dealloc {
[self->ocsFolder release];
[self->ocsPath release];
[super dealloc];
}
/* accessors */
- (BOOL)isFolderish {
return YES;
}
- (void)setOCSPath:(NSString *)_path {
if ([self->ocsPath isEqualToString:_path])
return;
if (self->ocsPath)
[self warnWithFormat:@"GCS path is already set! '%@'", _path];
ASSIGNCOPY(self->ocsPath, _path);
}
- (NSString *)ocsPath {
return self->ocsPath;
}
- (GCSFolderManager *)folderManager {
return [GCSFolderManager defaultFolderManager];
}
- (GCSFolder *)ocsFolderForPath:(NSString *)_path {
return [[self folderManager] folderAtPath:_path];
}
- (GCSFolder *)ocsFolder {
if (self->ocsFolder != nil)
return [self->ocsFolder isNotNull] ? self->ocsFolder : nil;
self->ocsFolder = [[self ocsFolderForPath:[self ocsPath]] retain];
return self->ocsFolder;
}
- (NSArray *)fetchContentObjectNames {
NSArray *fields, *records;
fields = [NSArray arrayWithObject:@"c_name"];
records = [[self ocsFolder] fetchFields:fields matchingQualifier:nil];
if (![records isNotNull]) {
[self errorWithFormat:@"(%s): fetch failed!", __PRETTY_FUNCTION__];
return nil;
}
if ([records isKindOfClass:[NSException class]])
return records;
return [records valueForKey:@"c_name"];
}
- (NSDictionary *)fetchContentStringsAndNamesOfAllObjects {
NSDictionary *files;
files = [[self ocsFolder] fetchContentsOfAllFiles];
if (![files isNotNull]) {
[self errorWithFormat:@"(%s): fetch failed!", __PRETTY_FUNCTION__];
return nil;
}
if ([files isKindOfClass:[NSException class]])
return files;
return files;
}
/* reflection */
- (NSString *)defaultFilenameExtension {
/*
Override to add an extension to a filename
Note: be careful with that, needs to be consistent with object lookup!
*/
return nil;
}
- (NSArray *)toOneRelationshipKeys {
/* toOneRelationshipKeys are the 'files' contained in a folder */
NSMutableArray *ma;
NSArray *names;
NSString *ext;
unsigned i, count;
if ((names = [self fetchContentObjectNames]) == nil)
return names;
if ((count = [names count]) == 0)
return names;
if ((ext = [self defaultFilenameExtension]) == nil)
return names;
ma = [NSMutableArray arrayWithCapacity:count];
for (i = 0; i < count; i++) {
NSRange r;
NSString *name;
name = [names objectAtIndex:i];
r = [name rangeOfString:@"."];
if (r.length == 0)
name = [[name stringByAppendingString:@"."] stringByAppendingString:ext];
[ma addObject:name];
}
return ma;
}
/* WebDAV */
- (BOOL)davIsCollection {
return [self isFolderish];
}
/* folder type */
- (NSString *)outlookFolderClass {
return nil;
}
/* description */
- (void)appendAttributesToDescription:(NSMutableString *)_ms {
[super appendAttributesToDescription:_ms];
[_ms appendFormat:@" ocs=%@", [self ocsPath]];
}
- (NSString *)loggingPrefix {
return [NSString stringWithFormat:@"<0x%08X[%@]:%@>",
self, NSStringFromClass([self class]),
[self nameInContainer]];
}
@end /* SOGoFolder */
+58
View File
@@ -0,0 +1,58 @@
/*
Copyright (C) 2004 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
// $Id: SOGoGroupFolder.h 107 2004-06-30 10:26:46Z helge $
#ifndef __SOGo_SOGoGroupFolder_H__
#define __SOGo_SOGoGroupFolder_H__
#include <SOGo/SOGoObject.h>
/*
SOGoGroupFolder
Parent object: the SOGoGroupsFolder
Child objects:
*/
@class NSArray, NSDictionary;
@interface SOGoGroupFolder : SOGoObject
{
NSDictionary *uidToFolder;
NSArray *folders;
}
/* accessors */
- (NSArray *)uids;
/* folder management */
- (NSArray *)memberFolders;
- (id)folderForUID:(NSString *)_uid;
- (void)resetFolderCaches;
- (void)sleep;
/* pathes */
@end
#endif /* __SOGo_SOGoGroupFolder_H__ */
+204
View File
@@ -0,0 +1,204 @@
/*
Copyright (C) 2004 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
// $Id: SOGoGroupFolder.m 115 2004-06-30 11:57:37Z helge $
#include "SOGoGroupFolder.h"
#include "common.h"
@implementation SOGoGroupFolder
static NGLogger *logger = nil;
+ (void)initialize {
NGLoggerManager *lm;
static BOOL didInit = NO;
if (didInit) return;
didInit = YES;
lm = [NGLoggerManager defaultLoggerManager];
logger = [lm loggerForDefaultKey:@"SOGoGroupFolderDebugEnabled"];
}
- (void)dealloc {
[self->uidToFolder release];
[self->folders release];
[super dealloc];
}
/* logging */
- (id)debugLogger {
return logger;
}
/* accessors */
- (NSArray *)uids {
[self errorWithFormat:@"instantiated abstract Group folder class!"];
return nil;
}
/* folder management */
- (id)_primaryLookupFolderForUID:(NSString *)_uid inContext:(id)_ctx {
NSException *error = nil;
NSArray *path;
id ctx, result;
/* create subcontext, so that we don't destroy our environment */
if ((ctx = [_ctx createSubContext]) == nil) {
[self errorWithFormat:@"could not create SOPE subcontext!"];
return nil;
}
/* build path */
path = _uid != nil ? [NSArray arrayWithObjects:&_uid count:1] : nil;
/* traverse path */
result = [[ctx application] traversePathArray:path inContext:ctx
error:&error acquire:NO];
if (error != nil) {
[self errorWithFormat:@"folder lookup failed (uid=%@): %@",
_uid, error];
return nil;
}
if (logger)
[self debugWithFormat:@"Note: got folder for uid %@ path %@: %@",
_uid, [path componentsJoinedByString:@"=>"], result];
return result;
}
- (void)_setupFolders {
WOContext *ctx;
NSMutableDictionary *md;
NSMutableArray *ma;
NSArray *luids;
unsigned i, count;
if (self->uidToFolder != nil)
return;
if ((luids = [self uids]) == nil)
return;
ctx = [[WOApplication application] context];
count = [luids count];
ma = [NSMutableArray arrayWithCapacity:count + 1];
md = [NSMutableDictionary dictionaryWithCapacity:count];
for (i = 0; i < count; i++) {
NSString *uid;
id folder;
uid = [luids objectAtIndex:i];
folder = [self _primaryLookupFolderForUID:uid inContext:ctx];
if ([folder isNotNull]) {
[md setObject:folder forKey:uid];
[ma addObject:folder];
}
else
[ma addObject:[NSNull null]];
}
/* fix results */
self->uidToFolder = [md copy];
self->folders = [[NSArray alloc] initWithArray:ma];
}
- (NSArray *)memberFolders {
[self _setupFolders];
return self->folders;
}
- (id)folderForUID:(NSString *)_uid {
[self _setupFolders];
if ([_uid length] == 0)
return nil;
return [self->uidToFolder objectForKey:_uid];
}
- (void)resetFolderCaches {
[self->uidToFolder release]; self->uidToFolder = nil;
[self->folders release]; self->folders = nil;
}
- (void)sleep {
[self resetFolderCaches];
[super sleep];
}
/* SOPE */
- (BOOL)isFolderish {
return YES;
}
/* looking up shared objects */
- (SOGoGroupsFolder *)lookupGroupsFolder {
return [[self container] lookupGroupsFolder];
}
/* pathes */
/* name lookup */
- (id)groupCalendar:(NSString *)_key inContext:(id)_ctx {
static Class calClass = Nil;
id calendar;
if (calClass == Nil)
calClass = NSClassFromString(@"SOGoGroupAppointmentFolder");
if (calClass == Nil) {
[self errorWithFormat:@"missing SOGoGroupAppointmentFolder class!"];
return nil;
}
calendar = [[calClass alloc] initWithName:_key inContainer:self];
// TODO: should we pass over the uids in questions or should the
// appointment folder query its container for that info?
return [calendar autorelease];
}
- (id)lookupName:(NSString *)_key inContext:(id)_ctx acquire:(BOOL)_flag {
id obj;
/* first check attributes directly bound to the application */
if ((obj = [super lookupName:_key inContext:_ctx acquire:NO]))
return obj;
if ([_key isEqualToString:@"Calendar"])
return [self groupCalendar:_key inContext:_ctx];
/* return 404 to stop acquisition */
return [NSException exceptionWithHTTPStatus:404 /* Not Found */];
}
@end /* SOGoGroupFolder */
+59
View File
@@ -0,0 +1,59 @@
/*
Copyright (C) 2004 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
// $Id: SOGoGroupsFolder.h 107 2004-06-30 10:26:46Z helge $
#ifndef __SOGo_SOGoGroupsFolder_H__
#define __SOGo_SOGoGroupsFolder_H__
#include <SOGo/SOGoObject.h>
/*
SOGoGroupsFolder
Parent object: the SOGoUserFolder
Child objects: SOGoGroupFolder objects
'_custom_*': SOGoCustomGroupFolder
This object represents a collection of groups, its the "Groups" in such a
path:
/SOGo/so/znek/Groups/sales
It also acts as a factory for the proper group folders, eg "custom" groups
(arbitary person collections) or later on cookie based configured groups or
groups stored in LDAP.
*/
@class NSString;
@interface SOGoGroupsFolder : SOGoObject
{
}
/* accessors */
/* looking up shared objects */
- (SOGoGroupsFolder *)lookupGroupsFolder;
/* pathes */
@end
#endif /* __SOGo_SOGoGroupsFolder_H__ */
+79
View File
@@ -0,0 +1,79 @@
/*
Copyright (C) 2004 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
// $Id: SOGoGroupsFolder.m 115 2004-06-30 11:57:37Z helge $
#include "SOGoGroupsFolder.h"
#include "common.h"
@implementation SOGoGroupsFolder
- (void)dealloc {
[super dealloc];
}
/* accessors */
/* SOPE */
- (BOOL)isFolderish {
return YES;
}
/* looking up shared objects */
- (SOGoGroupsFolder *)lookupGroupsFolder {
return self;
}
/* pathes */
/* name lookup */
- (id)customGroup:(NSString *)_key inContext:(id)_ctx {
static Class groupClass = Nil;
id group;
if (groupClass == Nil)
groupClass = NSClassFromString(@"SOGoCustomGroupFolder");
if (groupClass == Nil) {
[self logWithFormat:@"ERROR: missing SOGoCustomGroupFolder class!"];
return nil;
}
group = [[groupClass alloc] initWithName:_key inContainer:self];
return [group autorelease];
}
- (id)lookupName:(NSString *)_key inContext:(id)_ctx acquire:(BOOL)_flag {
id obj;
/* first check attributes directly bound to the application */
if ((obj = [super lookupName:_key inContext:_ctx acquire:NO]))
return obj;
if ([_key hasPrefix:@"_custom_"])
return [self customGroup:_key inContext:_ctx];
/* return 404 to stop acquisition */
return [NSException exceptionWithHTTPStatus:404 /* Not Found */];
}
@end /* SOGoGroupsFolder */
+40
View File
@@ -0,0 +1,40 @@
/*
Copyright (C) 2000-2004 SKYRIX Software AG
This file is part of OGo
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#ifndef __SOGoLRUCache_H_
#define __SOGoLRUCache_H_
#import <Foundation/Foundation.h>
@interface SOGoLRUCache : NSObject
{
unsigned size;
NSMutableDictionary *entries;
}
- (id)initWithCacheSize:(unsigned)_size;
- (void)addObject:(id)_obj forKey:(id)_key;
- (id)objectForKey:(id)_key;
@end
#endif /* __SOGoLRUCache_H_ */
+112
View File
@@ -0,0 +1,112 @@
/*
Copyright (C) 2000-2004 SKYRIX Software AG
This file is part of OGo
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "SOGoLRUCache.h"
#include "common.h"
@interface SOGoLRUCacheItem : NSObject
{
id object;
unsigned useCount;
}
- (id)initWithObject:(id)_obj;
- (id)object;
- (unsigned)useCount;
@end
@implementation SOGoLRUCacheItem
- (id)initWithObject:(id)_obj {
self = [super init];
if(self) {
ASSIGN(self->object, _obj);
self->useCount = 1;
}
return self;
}
- (id)object {
self->useCount++;
return self->object;
}
- (unsigned)useCount {
return self->useCount;
}
@end
@implementation SOGoLRUCache
- (id)initWithCacheSize:(unsigned)_size {
self = [super init];
if(self) {
self->size = _size;
self->entries = [[NSMutableDictionary alloc] initWithCapacity:_size];
}
return self;
}
- (void)dealloc {
[self->entries release];
[super dealloc];
}
- (void)addObject:(id)_obj forKey:(id)_key {
SOGoLRUCacheItem *item;
NSAssert(_obj, @"Attempt to insert nil object!");
if([self->entries count] >= self->size) {
/* need to find minimum and get rid of it */
NSEnumerator *keyEnum;
SOGoLRUCacheItem *item;
id key, leastUsedItemKey;
unsigned minimumUseCount = INT_MAX;
keyEnum = [self->entries keyEnumerator];
while((key = [keyEnum nextObject])) {
item = [self->entries objectForKey:key];
if([item useCount] < minimumUseCount) {
minimumUseCount = [item useCount];
leastUsedItemKey = key;
}
}
[self->entries removeObjectForKey:leastUsedItemKey];
}
item = [[SOGoLRUCacheItem alloc] initWithObject:_obj];
[self->entries setObject:item forKey:_key];
[item release];
}
- (id)objectForKey:(id)_key {
SOGoLRUCacheItem *item;
item = [self->entries objectForKey:_key];
if(!item)
return nil;
return [item object];
}
@end
+84
View File
@@ -0,0 +1,84 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#ifndef __SoObjects_SOGoObject_H__
#define __SoObjects_SOGoObject_H__
#import <Foundation/NSObject.h>
/*
SOGoObject
This is the abstract class used by all SOGo SoObjects. It contains the
ability to track a container as well as the key the object was invoked with.
In addition it provides some generic methods like user or group folder
lookup.
*/
@class NSString, NSArray, NSMutableString, NSException;
@class GCSFolderManager, GCSFolder;
@class SOGoUserFolder, SOGoGroupsFolder;
@interface SOGoObject : NSObject
{
NSString *nameInContainer;
id container;
}
- (id)initWithName:(NSString *)_name inContainer:(id)_container;
/* accessors */
- (NSString *)nameInContainer;
- (id)container;
/* ownership */
- (NSString *)ownerInContext:(id)_ctx;
/* looking up shared objects */
- (SOGoUserFolder *)lookupUserFolder;
- (SOGoGroupsFolder *)lookupGroupsFolder;
- (void)sleep;
/* hierarchy */
- (NSArray *)fetchSubfolders; /* uses toManyRelationshipKeys */
/* operations */
- (NSException *)delete;
- (id)GETAction:(id)_ctx;
/* etag support */
- (NSException *)matchesRequestConditionInContext:(id)_ctx;
/* description */
- (void)appendAttributesToDescription:(NSMutableString *)_ms;
@end
#endif /* __SoObjects_SOGoObject_H__ */
+381
View File
@@ -0,0 +1,381 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "SOGoObject.h"
#include "SOGoUserFolder.h"
#include <NGObjWeb/WEClientCapabilities.h>
#include <NGObjWeb/SoObject+SoDAV.h>
#include "common.h"
@interface SOGoObject(Content)
- (NSString *)contentAsString;
@end
@implementation SOGoObject
static BOOL kontactGroupDAV = YES;
+ (int)version {
return 0;
}
+ (void)initialize {
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
kontactGroupDAV =
[ud boolForKey:@"SOGoDisableKontact34GroupDAVHack"] ? NO : YES;
/* SoClass security declarations */
/* require View permission to access the root (bound to authenticated ...) */
[[self soClassSecurityInfo] declareObjectProtected:SoPerm_View];
/* to allow public access to all contained objects (subkeys) */
[[self soClassSecurityInfo] setDefaultAccess:@"allow"];
/* require Authenticated role for View and WebDAV */
[[self soClassSecurityInfo] declareRole:SoRole_Authenticated
asDefaultForPermission:SoPerm_View];
[[self soClassSecurityInfo] declareRole:SoRole_Authenticated
asDefaultForPermission:SoPerm_WebDAVAccess];
}
/* containment */
- (BOOL)doesRetainContainer {
return YES;
}
- (id)initWithName:(NSString *)_name inContainer:(id)_container {
if ((self = [super init])) {
self->nameInContainer = [_name copy];
self->container =
[self doesRetainContainer] ? [_container retain] : _container;
}
return self;
}
- (id)init {
return [self initWithName:nil inContainer:nil];
}
- (void)dealloc {
if ([self doesRetainContainer])
[self->container release];
[self->nameInContainer release];
[super dealloc];
}
/* accessors */
- (NSString *)nameInContainer {
return self->nameInContainer;
}
- (id)container {
return self->container;
}
/* ownership */
- (NSString *)ownerInContext:(id)_ctx {
return [[self container] ownerInContext:_ctx];
}
/* hierarchy */
- (NSArray *)fetchSubfolders {
NSMutableArray *ma;
NSArray *names;
unsigned i, count;
if ((names = [self toManyRelationshipKeys]) == nil)
return nil;
count = [names count];
ma = [NSMutableArray arrayWithCapacity:count + 1];
for (i = 0; i < count; i++) {
id folder;
folder = [self lookupName:[names objectAtIndex:i] inContext:nil
acquire:NO];
if (folder == nil)
continue;
if ([folder isKindOfClass:[NSException class]])
continue;
[ma addObject:folder];
}
return ma;
}
/* looking up shared objects */
- (SOGoUserFolder *)lookupUserFolder {
if (![self->container respondsToSelector:_cmd])
return nil;
return [self->container lookupUserFolder];
}
- (SOGoGroupsFolder *)lookupGroupsFolder {
return [[self lookupUserFolder] lookupGroupsFolder];
}
- (void)sleep {
if ([self doesRetainContainer])
[self->container release];
self->container = nil;
}
/* operations */
- (NSException *)delete {
return [NSException exceptionWithHTTPStatus:501 /* not implemented */
reason:@"delete not yet implemented, sorry ..."];
}
/* KVC hacks */
- (id)valueForUndefinedKey:(NSString *)_key {
return nil;
}
/* WebDAV */
- (NSString *)davDisplayName {
return [self nameInContainer];
}
/* actions */
- (id)DELETEAction:(id)_ctx {
NSException *error;
if ((error = [self delete]) != nil)
return error;
/* Note: returning 'nil' breaks in SoObjectRequestHandler */
return [NSNumber numberWithBool:YES]; /* delete worked out ... */
}
- (id)GETAction:(id)_ctx {
// TODO: I guess this should really be done by SOPE (redirect to
// default method)
WORequest *rq;
WOResponse *r;
NSString *uri;
r = [(WOContext *)_ctx response];
rq = [(WOContext *)_ctx request];
if ([rq isSoWebDAVRequest]) {
if ([self respondsToSelector:@selector(contentAsString)]) {
NSException *error;
id etag;
if ((error = [self matchesRequestConditionInContext:_ctx]) != nil)
return error;
[r appendContentString:[self contentAsString]];
if ((etag = [self davEntityTag]) != nil)
[r setHeader:etag forKey:@"etag"];
return r;
}
return [NSException exceptionWithHTTPStatus:501 /* not implemented */
reason:@"no WebDAV GET support?!"];
}
uri = [rq uri];
if (![uri hasSuffix:@"/"]) uri = [uri stringByAppendingString:@"/"];
uri = [uri stringByAppendingString:@"view"];
[r setStatus:302 /* moved */];
[r setHeader:uri forKey:@"location"];
return r;
}
/* etag support */
- (NSArray *)parseETagList:(NSString *)_c {
NSMutableArray *ma;
NSArray *etags;
unsigned i, count;
if ([_c length] == 0)
return nil;
if ([_c isEqualToString:@"*"])
return nil;
etags = [_c componentsSeparatedByString:@","];
count = [etags count];
ma = [NSMutableArray arrayWithCapacity:count];
for (i = 0; i < count; i++) {
NSString *etag;
etag = [[etags objectAtIndex:i] stringByTrimmingSpaces];
#if 0 /* this is non-sense, right? */
if ([etag hasPrefix:@"\""] && [etag hasSuffix:@"\""])
etag = [etag substringWithRange:NSMakeRange(1, [etag length] - 2)];
#endif
if (etag != nil) [ma addObject:etag];
}
return ma;
}
- (NSException *)checkIfMatchCondition:(NSString *)_c inContext:(id)_ctx {
/*
Only run the request if one of the etags matches the resource etag,
usually used to ensure consistent PUTs.
*/
NSArray *etags;
NSString *etag;
if ([_c isEqualToString:@"*"])
/* to ensure that the resource exists! */
return nil;
if ((etags = [self parseETagList:_c]) == nil)
return nil;
if ([etags count] == 0) /* no etags to check for? */
return nil;
etag = [self davEntityTag];
if ([etag length] == 0) /* has no etag, ignore */
return nil;
if ([etags containsObject:etag]) {
[self debugWithFormat:@"etag '%@' matches: %@", etag,
[etags componentsJoinedByString:@","]];
return nil; /* one etag matches, so continue with request */
}
/* hack for Kontact 3.4 */
if (kontactGroupDAV) {
WEClientCapabilities *cc;
cc = [[(WOContext *)_ctx request] clientCapabilities];
if ([[cc userAgentType] isEqualToString:@"Konqueror"]) {
if ([cc majorVersion] == 3 && [cc minorVersion] == 4) {
[self logWithFormat:
@"WARNING: applying Kontact 3.4 GroupDAV hack"
@" - etag check is disabled!"
@" (can be enabled using 'ZSDisableKontact34GroupDAVHack')"];
return nil;
}
}
}
// TODO: we might want to return the davEntityTag in the response
[self debugWithFormat:@"etag '%@' does not match: %@", etag,
[etags componentsJoinedByString:@","]];
return [NSException exceptionWithHTTPStatus:412 /* Precondition Failed */
reason:@"Precondition Failed"];
}
- (NSException *)checkIfNoneMatchCondition:(NSString *)_c inContext:(id)_ctx {
/*
If one of the etags is still the same, we can ignore the request.
Can be used for PUT to ensure that the object does not exist in the store
and for GET to retrieve the content only if if the etag changed.
*/
if (![_c isEqualToString:@"*"] &&
[[[_ctx request] method] isEqualToString:@"GET"]) {
NSString *etag;
NSArray *etags;
if ((etags = [self parseETagList:_c]) == nil)
return nil;
if ([etags count] == 0) /* no etags to check for? */
return nil;
etag = [self davEntityTag];
if ([etag length] == 0) /* has no etag, ignore */
return nil;
if ([etags containsObject:etag]) {
[self debugWithFormat:@"etag '%@' matches: %@", etag,
[etags componentsJoinedByString:@","]];
/* one etag matches, so stop the request */
return [NSException exceptionWithHTTPStatus:304 /* Not Modified */
reason:@"object was not modified"];
}
return nil;
}
#if 0
if ([_c isEqualToString:@"*"])
return nil;
if ((a = [self parseETagList:_c]) == nil)
return nil;
#else
[self logWithFormat:@"TODO: implement if-none-match for etag: '%@'", _c];
#endif
return nil;
}
- (NSException *)matchesRequestConditionInContext:(id)_ctx {
NSException *error;
WORequest *rq;
NSString *c;
if ((rq = [(WOContext *)_ctx request]) == nil)
return nil; /* be tolerant - no request, no condition */
if ((c = [rq headerForKey:@"if-match"]) != nil) {
if ((error = [self checkIfMatchCondition:c inContext:_ctx]) != nil)
return error;
}
if ((c = [rq headerForKey:@"if-none-match"]) != nil) {
if ((error = [self checkIfNoneMatchCondition:c inContext:_ctx]) != nil)
return error;
}
return nil;
}
/* description */
- (void)appendAttributesToDescription:(NSMutableString *)_ms {
if (self->nameInContainer != nil)
[_ms appendFormat:@" name=%@", self->nameInContainer];
if (self->container != nil) {
[_ms appendFormat:@" container=0x%08X/%@",
self->container, [self->container valueForKey:@"nameInContainer"]];
}
}
- (NSString *)description {
NSMutableString *ms;
ms = [NSMutableString stringWithCapacity:64];
[ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
[self appendAttributesToDescription:ms];
[ms appendString:@">"];
return ms;
}
@end /* SOGoObject */
+73
View File
@@ -0,0 +1,73 @@
/*
Copyright (C) 2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#ifndef __SOGoUser_H__
#define __SOGoUser_H__
#include <NGObjWeb/SoUser.h>
/*
SOGoUser
This adds some additional SOGo properties to the SoUser object. The
properties are (currently) looked up using the AgenorUserManager.
You have access to this object from the WOContext:
context.activeUser
*/
@class NSString, NSArray, NSDictionary, NSUserDefaults;
@class NSString, NSArray, NSURL, NSUserDefaults;
@interface SOGoUser : SoUser
{
NSString *cn;
NSString *email;
NSUserDefaults *userDefaults;
}
/* properties */
- (NSString *)email;
- (NSString *)cn;
- (NSURL *)freeBusyURL;
/* shares and identities */
- (NSString *)primaryIMAP4AccountString;
- (NSString *)primaryMailServer;
- (NSArray *)additionalIMAP4AccountStrings;
- (NSArray *)additionalEMailAddresses;
- (NSDictionary *)additionalIMAP4AccountsAndEMails;
/* defaults */
- (NSUserDefaults *)userDefaults;
/* folders */
- (id)homeFolderInContext:(id)_ctx;
- (id)schedulingCalendarInContext:(id)_ctx;
@end
#endif /* __SOGoUser_H__ */
+134
View File
@@ -0,0 +1,134 @@
/*
Copyright (C) 2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "SOGoUser.h"
#include <SOGo/AgenorUserManager.h>
#include "common.h"
@implementation SOGoUser
- (void)dealloc {
[self->userDefaults release];
[self->cn release];
[self->email release];
[super dealloc];
}
/* internals */
- (AgenorUserManager *)userManager {
static AgenorUserManager *um = nil;
if (um == nil) um = [[AgenorUserManager sharedUserManager] retain];
return um;
}
/* properties */
- (NSString *)email {
if (self->email == nil)
self->email = [[[self userManager] getEmailForUID:[self login]] copy];
return self->email;
}
- (NSString *)cn {
if (self->cn == nil)
self->cn = [[[self userManager] getCNForUID:[self login]] copy];
return self->cn;
}
- (NSString *)primaryIMAP4AccountString {
return [[self userManager] getIMAPAccountStringForUID:[self login]];
}
- (NSString *)primaryMailServer {
return [[self userManager] getServerForUID:[self login]];
}
- (NSArray *)additionalIMAP4AccountStrings {
return [[self userManager]getSharedMailboxAccountStringsForUID:[self login]];
}
- (NSArray *)additionalEMailAddresses {
return [[self userManager] getSharedMailboxEMailsForUID:[self login]];
}
- (NSDictionary *)additionalIMAP4AccountsAndEMails {
return [[self userManager] getSharedMailboxesAndEMailsForUID:[self login]];
}
- (NSURL *)freeBusyURL {
return [[self userManager] getFreeBusyURLForUID:[self login]];
}
/* defaults */
- (NSUserDefaults *)userDefaults {
if (self->userDefaults == nil) {
self->userDefaults =
[[[self userManager] getUserDefaultsForUID:[self login]] retain];
}
return self->userDefaults;
}
/* folders */
// TODO: those methods should check whether the traversal stack in the context
// already contains proper folders to improve caching behaviour
- (id)homeFolderInContext:(id)_ctx {
/* Note: watch out for cyclic references */
// TODO: maybe we should add an [activeUser reset] method to SOPE
id folder;
folder = [(WOContext *)_ctx objectForKey:@"ActiveUserHomeFolder"];
if (folder != nil)
return [folder isNotNull] ? folder : nil;
folder = [[WOApplication application] lookupName:[self login]
inContext:_ctx acquire:NO];
if ([folder isKindOfClass:[NSException class]])
return folder;
[(WOContext *)_ctx setObject:folder ? folder : [NSNull null]
forKey:@"ActiveUserHomeFolder"];
return folder;
}
- (id)schedulingCalendarInContext:(id)_ctx {
/* Note: watch out for cyclic references */
id folder;
folder = [(WOContext *)_ctx objectForKey:@"ActiveUserCalendar"];
if (folder != nil)
return [folder isNotNull] ? folder : nil;
folder = [self homeFolderInContext:_ctx];
if ([folder isKindOfClass:[NSException class]])
return folder;
folder = [folder lookupName:@"Calendar" inContext:_ctx acquire:NO];
if ([folder isKindOfClass:[NSException class]])
return folder;
[(WOContext *)_ctx setObject:folder ? folder : [NSNull null]
forKey:@"ActiveUserCalendar"];
return folder;
}
@end /* SOGoUser */
+62
View File
@@ -0,0 +1,62 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#ifndef __SOGo_SOGoUserFolder_H__
#define __SOGo_SOGoUserFolder_H__
#include <SOGo/SOGoFolder.h>
/*
SOGoUserFolder
Parent object: the root object (SoApplication object)
Child objects:
'Groups': SOGoGroupsFolder
'Calendar': SOGoAppointmentFolder
The SOGoUserFolder is the "home directory" of the user where all his
processing starts. It is the 'znek' in such a path:
/SOGo/so/znek/Calendar
*/
@class NSString;
@interface SOGoUserFolder : SOGoFolder
{
}
/* accessors */
- (NSString *)login;
/* ownership */
- (NSString *)ownerInContext:(id)_ctx;
/* pathes */
- (NSString *)ocsUserPath;
- (NSString *)ocsPrivateCalendarPath;
- (id)lookupFreeBusyObject;
@end
#endif /* __SOGo_SOGoUserFolder_H__ */
+214
View File
@@ -0,0 +1,214 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "SOGoUserFolder.h"
#include "WOContext+Agenor.h"
#include "common.h"
@implementation SOGoUserFolder
/* accessors */
- (NSString *)login {
return [self nameInContainer];
}
/* hierarchy */
- (NSArray *)toManyRelationshipKeys {
static NSArray *children = nil;
if (children == nil) {
children = [[NSArray alloc] initWithObjects:
@"Calendar", @"Contacts", @"Mail", nil];
}
return children;
}
/* ownership */
- (NSString *)ownerInContext:(id)_ctx {
return [self login];
}
/* looking up shared objects */
- (SOGoUserFolder *)lookupUserFolder {
return self;
}
- (SOGoGroupsFolder *)lookupGroupsFolder {
return [self lookupName:@"Groups" inContext:nil acquire:NO];
}
/* pathes */
- (void)setOCSPath:(NSString *)_path {
[self warnWithFormat:
@"rejected attempt to reset user-folder path: '%@'", _path];
}
- (NSString *)ocsPath {
return [@"/Users/" stringByAppendingString:[self login]];
}
- (NSString *)ocsUserPath {
return [self ocsPath];
}
- (NSString *)ocsPrivateCalendarPath {
return [[self ocsUserPath] stringByAppendingString:@"/Calendar"];
}
- (NSString *)ocsPrivateContactsPath {
return [[self ocsUserPath] stringByAppendingString:@"/Contacts"];
}
/* name lookup */
- (id)privateCalendar:(NSString *)_key inContext:(id)_ctx {
static Class calClass = Nil;
id calendar;
if (calClass == Nil)
calClass = NSClassFromString(@"SOGoAppointmentFolder");
if (calClass == Nil) {
[self errorWithFormat:@"missing SOGoAppointmentFolder class!"];
return nil;
}
calendar = [[calClass alloc] initWithName:_key inContainer:self];
[calendar setOCSPath:[self ocsPrivateCalendarPath]];
return [calendar autorelease];
}
- (id)privateContacts:(NSString *)_key inContext:(id)_ctx {
static Class calClass = Nil;
id calendar;
if (calClass == Nil)
calClass = NSClassFromString(@"SOGoContactFolder");
if (calClass == Nil) {
[self errorWithFormat:@"missing SOGoContactFolder class!"];
return nil;
}
calendar = [[calClass alloc] initWithName:_key inContainer:self];
[calendar setOCSPath:[self ocsPrivateContactsPath]];
return [calendar autorelease];
}
- (id)groupsFolder:(NSString *)_key inContext:(id)_ctx {
static Class fldClass = Nil;
id folder;
if (fldClass == Nil)
fldClass = NSClassFromString(@"SOGoGroupsFolder");
if (fldClass == Nil) {
[self errorWithFormat:@"missing SOGoGroupsFolder class!"];
return nil;
}
folder = [[fldClass alloc] initWithName:_key inContainer:self];
return [folder autorelease];
}
- (id)mailAccountsFolder:(NSString *)_key inContext:(id)_ctx {
static Class fldClass = Nil;
id folder;
if (fldClass == Nil)
fldClass = NSClassFromString(@"SOGoMailAccounts");
if (fldClass == Nil) {
[self errorWithFormat:@"missing SOGoMailAccounts class!"];
return nil;
}
folder = [[fldClass alloc] initWithName:_key inContainer:self];
return [folder autorelease];
}
- (id)freeBusyObject:(NSString *)_key inContext:(id)_ctx {
static Class fbClass = Nil;
id fb;
if (fbClass == Nil)
fbClass = NSClassFromString(@"SOGoFreeBusyObject");
if (fbClass == Nil) {
[self errorWithFormat:@"missing SOGoFreeBusyObject class!"];
return nil;
}
fb = [[fbClass alloc] initWithName:_key inContainer:self];
return [fb autorelease];
}
- (id)lookupName:(NSString *)_key inContext:(id)_ctx acquire:(BOOL)_flag {
id obj;
/* first check attributes directly bound to the application */
if ((obj = [super lookupName:_key inContext:_ctx acquire:NO]))
return obj;
if ([_key hasPrefix:@"Calendar"]) {
id calendar;
calendar = [self privateCalendar:@"Calendar" inContext:_ctx];
if ([_key isEqualToString:@"Calendar"])
return calendar;
return [calendar lookupName:[_key pathExtension]
inContext:_ctx acquire:NO];
}
if ([_key isEqualToString:@"Contacts"])
return [self privateContacts:_key inContext:_ctx];
if ([_key isEqualToString:@"Groups"]) {
/* Agenor requirement, return 403 to stop acquisition */
if (![_ctx isAccessFromIntranet]) {
return [NSException exceptionWithHTTPStatus:403 /* Forbidden */];
}
return [self groupsFolder:_key inContext:_ctx];
}
if ([_key isEqualToString:@"Mail"])
return [self mailAccountsFolder:_key inContext:_ctx];
if ([_key isEqualToString:@"freebusy.ifb"])
return [self freeBusyObject:_key inContext:_ctx];
/* return 404 to stop acquisition */
return [NSException exceptionWithHTTPStatus:404 /* Not Found */];
}
/* WebDAV */
- (NSArray *)fetchContentObjectNames {
static NSArray *cos = nil;
if (!cos) {
cos = [[NSArray alloc] initWithObjects:@"freebusy.ifb", nil];
}
return cos;
}
- (BOOL)davIsCollection {
return YES;
}
@end /* SOGoUserFolder */
+9
View File
@@ -0,0 +1,9 @@
# version file
SUBMINOR_VERSION:=70
# v0.9.63 requires libNGiCal v4.5.54
# v0.9.60 requires libNGiCal v4.5.49
# v0.9.50 requires libGDLContentStore v4.5.30
# v0.9.34 requires libGDLContentStore v4.5.26
# v0.9.26 requires libOGoContentStore v0.9.13
+33
View File
@@ -0,0 +1,33 @@
/*
Copyright (C) 2000-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#ifndef __SOGo_WOContext_Agenor_H_
#define __SOGo_WOContext_Agenor_H_
#include <NGObjWeb/WOContext.h>
@interface WOContext (Agenor)
- (BOOL)isAccessFromIntranet;
@end
#endif /* __SOGo_WOContext_Agenor_H_ */
+82
View File
@@ -0,0 +1,82 @@
/*
Copyright (C) 2000-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "WOContext+Agenor.h"
#include "common.h"
@implementation WOContext(Agenor)
static EOQualifier *internetDetectQualifier = nil;
static EOQualifier *getInternetDetectQualifier(void) {
static BOOL didCheck = NO;
NSUserDefaults *ud;
NSString *s;
if (didCheck) return internetDetectQualifier;
ud = [NSUserDefaults standardUserDefaults];
if ((s = [ud stringForKey:@"SOGoInternetDetectQualifier"]) != nil) {
internetDetectQualifier =
[[EOQualifier qualifierWithQualifierFormat:s] retain];
if (internetDetectQualifier == nil)
NSLog(@"ERROR: could not parse qualifier: '%@'", s);
}
if (internetDetectQualifier == nil)
NSLog(@"Note: no 'SOGoInternetDetectQualifier' configured.");
else {
NSLog(@"Note: detect Internet access using: %@",
internetDetectQualifier);
}
didCheck = YES;
return internetDetectQualifier;
}
- (BOOL)isAccessFromIntranet {
id<EOQualifierEvaluation> q;
NSNumber *bv;
WORequest *rq;
BOOL ok;
if ((bv = [self objectForKey:@"_agenorUnrestricedAccess"]) != nil)
return [bv boolValue];
if ((rq = [self request]) == nil) {
[self logWithFormat:@"ERROR: got no request for context!"];
return NO;
}
if ((q = (id)getInternetDetectQualifier()) == nil)
/* if no qualifier is set, allow access */
ok = YES;
else
/* is Internet request? */
ok = [q evaluateWithObject:[rq headers]] ? NO : YES;
bv = [NSNumber numberWithBool:ok];
[self setObject:bv forKey:@"_agenorUnrestricedAccess"];
return ok;
}
@end /* WOContext(Agenor) */
+134
View File
@@ -0,0 +1,134 @@
/*
Copyright (C) 2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "AgenorUserManager.h"
#include "common.h"
static void usage(NSArray *args) {
fprintf(stderr, "usage: %s <uid> read|write|info [<key>] [<value>]\n",
[[args objectAtIndex:0] cString]);
}
static void doInfo(NSUserDefaults *defaults) {
printf("defaults for: '%s'\n", [[defaults valueForKey:@"uid"] cString]);
printf(" profile table: '%s'\n",
[[[defaults valueForKey:@"tableURL"] absoluteString] cString]);
}
static void doRead(NSUserDefaults *defaults, NSString *key) {
id value;
if (key == nil) {
NSArray *defNames;
unsigned i, count;
defNames = [defaults valueForKey:@"primaryDefaultNames"];
if ((count = [defNames count]) == 0) {
fprintf(stderr, "There are no keys in the Agenor profile!\n");
return;
}
for (i = 0; i < count; i++) {
printf("%s: %s\n",
[[defNames objectAtIndex:i] cString],
[[[defaults objectForKey:[defNames objectAtIndex:i]]
description] cString]);
}
}
else if ((value = [defaults objectForKey:key]) == nil) {
fprintf(stderr, "There is no key '%s' in the Agenor profile!\n",
[key cString]);
}
else
printf("%s\n", [[value description] cString]);
}
static void doWrite(NSUserDefaults *defaults, NSString *key, NSString *value) {
[defaults setObject:value forKey:key];
if (![defaults synchronize]) {
fprintf(stderr, "Failed to synchronize defaults with profile!\n");
return;
}
}
static void doIt(NSArray *args) {
AgenorUserManager *userManager;
NSUserDefaults *defaults;
NSString *uid, *op, *key, *value;
/* extract arguments */
if ([args count] < 3) {
usage(args);
return;
}
uid = [args objectAtIndex:1];
op = [args objectAtIndex:2];
key = nil;
value = nil;
if ([args count] > 3)
key = [args objectAtIndex:3];
if ([op isEqualToString:@"write"]) {
if ([args count] < 5) {
usage(args);
return;
}
value = [args objectAtIndex:4];
}
/* run */
userManager = [AgenorUserManager sharedUserManager];
defaults = [userManager getUserDefaultsForUID:uid];
if (![defaults isNotNull]) {
fprintf(stderr, "Error: found no userdefaults for UID: '%s'\n",
[uid cString]);
exit(1);
}
if ([op isEqualToString:@"read"])
doRead(defaults, key);
else if ([op isEqualToString:@"write"])
doWrite(defaults, key, value);
else if ([op isEqualToString:@"info"])
doInfo(defaults);
else
usage(args);
}
int main(int argc, char **argv, char **env) {
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
#if LIB_FOUNDATION_LIBRARY
[NSProcessInfo initializeWithArguments:argv count:argc environment:env];
#endif
doIt([[NSProcessInfo processInfo] argumentsWithoutDefaults]);
[pool release];
return 0;
}
+71
View File
@@ -0,0 +1,71 @@
/*
Copyright (C) 2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "AgenorUserManager.h"
#include "common.h"
static void usage(NSArray *args) {
fprintf(stderr, "usage: %s <email1> <email2> <email3>\n",
[[args objectAtIndex:0] cString]);
}
static void doIt(NSArray *args) {
AgenorUserManager *userManager;
NSEnumerator *e;
NSString *email;
if ([args count] < 2) {
usage(args);
return;
}
userManager = [AgenorUserManager sharedUserManager];
e = [args objectEnumerator];
[e nextObject]; /* consume the command name */
while ((email = [e nextObject]) != nil) {
NSString *uid;
uid = [userManager getUIDForEmail:email];
if ([uid isNotNull])
printf("%s: %s\n", [email cString], [uid cString]);
else {
fprintf(stderr, "ERROR: did not find uid for email: '%s'\n",
[email cString]);
}
}
}
int main(int argc, char **argv, char **env) {
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
#if LIB_FOUNDATION_LIBRARY
[NSProcessInfo initializeWithArguments:argv count:argc environment:env];
#endif
doIt([[NSProcessInfo processInfo] argumentsWithoutDefaults]);
[pool release];
return 0;
}
+85
View File
@@ -0,0 +1,85 @@
/*
Copyright (C) 2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "AgenorUserManager.h"
#include "common.h"
static void usage(NSArray *args) {
fprintf(stderr, "usage: %s <uid1> <uid2> <uid3>\n",
[[args objectAtIndex:0] cString]);
}
static void handleUID(NSString *uid, AgenorUserManager *userManager) {
NSArray *emails;
NSString *primary;
unsigned i, count;
primary = [userManager getEmailForUID:uid];
emails = [userManager getSharedMailboxEMailsForUID:uid];
printf("%s:", [uid cString]);
if ([primary length] > 0)
printf(" %s\n", [primary cString]);
else
printf(" <no primary email found>\n");
if ((count = [emails count]) == 0) {
printf(" <no shares with emitter access>\n");
return;
}
for (i = 0; i < count; i++)
printf(" %s\n", [[emails objectAtIndex:i] cString]);
}
static void doIt(NSArray *args) {
AgenorUserManager *userManager;
NSEnumerator *e;
NSString *uid;
if ([args count] < 2) {
usage(args);
return;
}
userManager = [AgenorUserManager sharedUserManager];
e = [args objectEnumerator];
[e nextObject]; /* consume the command name */
while ((uid = [e nextObject]) != nil)
handleUID(uid, userManager);
}
int main(int argc, char **argv, char **env) {
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
#if LIB_FOUNDATION_LIBRARY
[NSProcessInfo initializeWithArguments:argv count:argc environment:env];
#endif
doIt([[NSProcessInfo processInfo] argumentsWithoutDefaults]);
[pool release];
return 0;
}
+79
View File
@@ -0,0 +1,79 @@
/*
Copyright (C) 2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "AgenorUserManager.h"
#include "common.h"
static void usage(NSArray *args) {
fprintf(stderr, "usage: %s <uid1> <uid2> <uid3>\n",
[[args objectAtIndex:0] cString]);
}
static void handleUID(NSString *uid, AgenorUserManager *userManager) {
NSArray *shares;
unsigned i, count;
shares = [userManager getSharedMailboxAccountStringsForUID:uid];
printf("%s:", [uid cString]);
if ((count = [shares count]) == 0) {
printf(" <no shares>\n");
return;
}
puts("");
for (i = 0; i < count; i++)
printf(" %s\n", [[shares objectAtIndex:i] cString]);
}
static void doIt(NSArray *args) {
AgenorUserManager *userManager;
NSEnumerator *e;
NSString *uid;
if ([args count] < 2) {
usage(args);
return;
}
userManager = [AgenorUserManager sharedUserManager];
e = [args objectEnumerator];
[e nextObject]; /* consume the command name */
while ((uid = [e nextObject]) != nil)
handleUID(uid, userManager);
}
int main(int argc, char **argv, char **env) {
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
#if LIB_FOUNDATION_LIBRARY
[NSProcessInfo initializeWithArguments:argv count:argc environment:env];
#endif
doIt([[NSProcessInfo processInfo] argumentsWithoutDefaults]);
[pool release];
return 0;
}
+32
View File
@@ -0,0 +1,32 @@
/*
Copyright (C) 2002-2004 SKYRIX Software AG
This file is part of OpenGroupware.org.
OGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
// $Id: common.h 96 2004-06-30 08:35:34Z helge $
#import <Foundation/Foundation.h>
#if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY
# include <NGExtensions/NGObjectMacros.h>
# include <NGExtensions/NSString+Ext.h>
#endif
#include <NGExtensions/NGExtensions.h>
#include <NGObjWeb/NGObjWeb.h>
#include <NGObjWeb/SoObjects.h>