-# $Id$
+# GNUstep makefile
include $(GNUSTEP_MAKEFILES)/common.make
#include "SOGoICalHTTPHandler.h"
#include <SoObjects/Appointments/SOGoAppointmentFolder.h>
-#include <SOGoLogic/SOGoAppointment.h>
+#include <SOGo/SOGoAppointment.h>
#include "common.h"
@implementation SOGoICalFileFetch
#include "SOGoICalHTTPHandler.h"
#include <SoObjects/Appointments/SOGoAppointmentFolder.h>
#include <SoObjects/Appointments/SOGoAppointmentObject.h>
-#include <SOGoLogic/SOGoAppointment.h>
+#include <SOGo/SOGoAppointment.h>
#include <NGiCal/NGiCal.h>
#include <NGiCal/iCalRenderer.h>
#include <SaxObjC/SaxObjC.h>
+2005-02-17 Helge Hess <helge.hess@opengroupware.org>
+
+ * fixed for removal of SOGoLogic (v0.9.26)
+
2005-02-06 Helge Hess <helge.hess@opengroupware.org>
* SOGoAppointmentObject.m, SOGoAppointmentFolder.m: added proper
-# $Id: GNUmakefile,v 1.3 2004/04/06 13:01:10 helge Exp $
+# GNUstep makefile
include ../common.make
/*
- Copyright (C) 2004 SKYRIX Software AG
+ Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
-// $Id$
#include "SOGoAppointmentFolder.h"
#include <SOGo/SOGoCustomGroupFolder.h>
-#include <SOGoLogic/AgenorUserManager.h>
+#include <SOGo/SOGoAppointment.h>
+#include <SOGo/AgenorUserManager.h>
#include <OGoContentStore/OCSFolder.h>
#include <SaxObjC/SaxObjC.h>
#include <NGiCal/NGiCal.h>
/*
- Copyright (C) 2004 SKYRIX Software AG
+ Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
-// $Id$
#include "SOGoAppointmentObject.h"
-#include <SOGoLogic/AgenorUserManager.h>
+#include <SOGo/AgenorUserManager.h>
+#include <SOGo/SOGoAppointment.h>
#include <SaxObjC/SaxObjC.h>
#include <NGiCal/NGiCal.h>
#include "common.h"
# Version file
-SUBMINOR_VERSION:=25
+SUBMINOR_VERSION:=26
+# v0.9.26 requires libSOGo v0.9.30
# v0.9.19 requires NGiCal v4.5.36
# v0.9.13 requires libSOGo v0.9.26
/*
- Copyright (C) 2002-2004 SKYRIX Software AG
+ Copyright (C) 2002-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
-// $Id$
#import <Foundation/Foundation.h>
#include <NGExtensions/NGExtensions.h>
#include <NGObjWeb/NGObjWeb.h>
#include <NGObjWeb/SoObjects.h>
-
-#include <SOGoLogic/SOGoAppointment.h>
-
/*
- Copyright (C) 2004 SKYRIX Software AG
+ Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
-// $Id$
#include "SOGoContactFolder.h"
#include <SOGo/SOGoCustomGroupFolder.h>
-#include <SOGoLogic/AgenorUserManager.h>
+#include <SOGo/AgenorUserManager.h>
#include <OGoContentStore/OCSFolder.h>
#include <NGiCal/NGiCal.h>
#include "common.h"
#include <NGObjWeb/NGObjWeb.h>
#include <NGObjWeb/SoObjects.h>
-#include <SOGoLogic/SOGoAppointment.h>
-
#include "SOGoMailAccounts.h"
#include "common.h"
#include <NGObjWeb/SoObject+SoDAV.h>
-#include <SOGoLogic/AgenorUserManager.h>
+#include <SOGo/AgenorUserManager.h>
@implementation SOGoMailAccounts
/*
- Copyright (C) 2002-2004 SKYRIX Software AG
+ Copyright (C) 2002-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
-// $Id$
#import <Foundation/Foundation.h>
#import <Foundation/NSObjCRuntime.h>
#include <NGObjWeb/NGObjWeb.h>
#include <NGObjWeb/SoObjects.h>
-#include <SOGoLogic/SOGoAppointment.h>
-
#include <NGImap4/NGImap4Client.h>
--- /dev/null
+/*
+ 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/Foundation.h>
+
+@class SOGoLRUCache;
+
+@interface AgenorUserManager : NSObject
+{
+ SOGoLRUCache *cnCache;
+ SOGoLRUCache *serverCache;
+ SOGoLRUCache *uidCache;
+ SOGoLRUCache *emailCache;
+}
+
++ (id)sharedUserManager;
+
+- (NSString *)getUIDForEmail:(NSString *)_email;
+- (NSString *)getEmailForUID:(NSString *)_uid;
+
+/* 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;
+
+@end
+
+#endif /* __AgenorUserManager_H_ */
--- /dev/null
+/*
+ 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$
+
+
+#include "AgenorUserManager.h"
+#include <NGExtensions/NGExtensions.h>
+#include <NGLdap/NGLdap.h>
+#include "SOGoLRUCache.h"
+
+@interface AgenorUserManager (PrivateAPI)
+- (NGLdapConnection *)ldapConnection;
+
+- (void)_cacheCN:(NSString *)_cn forUID:(NSString *)_uid;
+- (NSString *)_cachedCNForUID:(NSString *)_uid;
+- (void)_cacheServer:(NSString *)_server forUID:(NSString *)_uid;
+- (NSString *)_cachedServerForUID:(NSString *)_uid;
+- (void)_cacheEmail:(NSString *)_email forUID:(NSString *)_uid;
+- (NSString *)_cachedEmailForUID:(NSString *)_uid;
+- (void)_cacheUID:(NSString *)_uid forEmail:(NSString *)_email;
+- (NSString *)_cachedUIDForEmail:(NSString *)_email;
+
+@end
+
+
+@implementation AgenorUserManager
+
+static BOOL debugOn = NO;
+static BOOL useLDAP = NO;
+static NSString *ldapHost = nil;
+static NSString *ldapBaseDN = nil;
+
++ (void)initialize {
+ static BOOL didInit = NO;
+ NSUserDefaults *ud;
+
+ if(didInit)
+ return;
+ didInit = YES;
+ ud = [NSUserDefaults standardUserDefaults];
+ debugOn = [ud boolForKey:@"SOGoUserManagerDebugEnabled"];
+ useLDAP = [ud boolForKey:@"SOGoUserManagerUsesLDAP"];
+ if(useLDAP) {
+ ldapHost = [[ud stringForKey:@"SOGoLDAPHost"] retain];
+ ldapBaseDN = [[ud stringForKey:@"SOGoLDAPBaseDN"] retain];
+ }
+}
+
++ (id)sharedUserManager {
+ static id mgr = nil;
+ if(mgr == nil) {
+ mgr = [[self alloc] init];
+ }
+ return mgr;
+}
+
+- (id)init {
+ self = [super init];
+ if(self) {
+ self->serverCache = [[SOGoLRUCache alloc] initWithCacheSize:10000];
+ self->cnCache = [[SOGoLRUCache alloc] initWithCacheSize:10000];
+ self->uidCache = [[SOGoLRUCache alloc] initWithCacheSize:10000];
+ self->emailCache = [[SOGoLRUCache alloc] initWithCacheSize:10000];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [self->serverCache release];
+ [self->cnCache release];
+ [self->uidCache release];
+ [self->emailCache release];
+ [super dealloc];
+}
+
+- (NGLdapConnection *)ldapConnection {
+ static NGLdapConnection *ldapConnection = nil;
+ if(!ldapConnection) {
+ ldapConnection = [[NGLdapConnection alloc] initWithHostName:ldapHost];
+#if 0
+ [ldapConnection setUseCache:YES];
+#endif
+ }
+ return ldapConnection;
+}
+
+
+/* private cache helpers */
+
+- (void)_cacheCN:(NSString *)_cn forUID:(NSString *)_uid {
+ [self->cnCache addObject:_cn forKey:_uid];
+}
+
+- (NSString *)_cachedCNForUID:(NSString *)_uid {
+ return [self->cnCache objectForKey:_uid];
+}
+
+- (void)_cacheServer:(NSString *)_server forUID:(NSString *)_uid {
+ [self->serverCache addObject:_server forKey:_uid];
+}
+
+- (NSString *)_cachedServerForUID:(NSString *)_uid {
+ return [self->serverCache objectForKey:_uid];
+}
+
+- (void)_cacheEmail:(NSString *)_email forUID:(NSString *)_uid {
+ [self->emailCache addObject:_email forKey:_uid];
+}
+
+- (NSString *)_cachedEmailForUID:(NSString *)_uid {
+ return [self->emailCache objectForKey:_uid];
+}
+
+- (void)_cacheUID:(NSString *)_uid forEmail:(NSString *)_email {
+ [self->uidCache addObject:_uid forKey:_email];
+}
+
+- (NSString *)_cachedUIDForEmail:(NSString *)_email {
+ return [self->uidCache objectForKey:_email];
+}
+
+
+/* uid <-> email mapping */
+
+/*
+ UPDATE: the email excerpt below has been marked by Maxime as being
+ wrong. This algorithm can not be expected to work, thus
+ the mapping has been replaced with an LDAP query.
+
+ --- snip ---
+ The uid field is in bijection this the email adress :
+ this field can be construct from the email. Email are uniques.
+
+ So, we can use email adresse from identifier.
+ The field is made like this :
+ _ if the email is equipement.gouv.fr then the login
+ is the part before the @
+ for example : fisrtName.lastName
+ _ if the email is not equipement.gouv.fr then the login
+ is the full email adress where @ is change to . (dot)
+ for example : fisrtName.lastName.subDomain.domain.tld
+ --- snap ---
+
+ NOTE: mapping email -> uid is easy, but can also generate uid's not known
+ to the system (i.e. for private addressbook entries, obvious).
+ The reverse mapping can work _only_ if "firstName.lastname." is
+ guaranteed, because the second dot would be mapped to '@'. This
+ is probably error prone.
+ Only LDAP fetches would guarantee correctness in both cases.
+*/
+
+- (NSString *)getUIDForEmail:(NSString *)_email {
+ if(useLDAP) {
+ static NSArray *uidAttrs = nil;
+ NGLdapConnection *conn;
+ EOQualifier *q;
+ NSEnumerator *resultEnum;
+ NGLdapEntry *entry;
+ NGLdapAttribute *uidAttr;
+ NSString *uid;
+
+ if(!uidAttrs) {
+ uidAttrs = [[NSArray alloc] initWithObjects:@"uid", nil];
+ }
+
+ if((uid = [self _cachedUIDForEmail:_email]))
+ return uid;
+
+ q = [EOQualifier qualifierWithQualifierFormat:@"mail = %@", _email];
+
+ conn = [self ldapConnection];
+ resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
+ qualifier:q
+ attributes:uidAttrs];
+ entry = [resultEnum nextObject];
+ if(!entry) {
+ if(debugOn) {
+ [self logWithFormat:@"%s Didn't find LDAP entry for email '%@'!",
+ __PRETTY_FUNCTION__,
+ _email];
+ }
+ return nil;
+ }
+ uidAttr = [entry attributeWithName:@"uid"];
+ if (!uidAttr)
+ return nil; /* can happen, not unlikely */
+ uid = [uidAttr stringValueAtIndex:0];
+ [self _cacheUID:uid forEmail:_email];
+ return uid;
+ }
+ else {
+ NSRange r;
+ NSString *domain;
+
+ if(!_email || [_email length] == 0)
+ return nil;
+
+ r = [_email rangeOfString:@"@"];
+ if(r.length == 0)
+ return nil;
+ domain = [_email substringFromIndex:NSMaxRange(r)];
+ if(![domain isEqualToString:@"equipement.gouv.fr"])
+ return _email;
+ return [_email substringToIndex:r.location];
+ }
+}
+
+- (NSString *)getEmailForUID:(NSString *)_uid {
+ if(useLDAP) {
+ static NSArray *emailAttrs = nil;
+ NGLdapConnection *conn;
+ EOQualifier *q;
+ NSEnumerator *resultEnum;
+ NGLdapEntry *entry;
+ NGLdapAttribute *emailAttr;
+ NSString *email;
+
+ if(!emailAttrs) {
+ emailAttrs = [[NSArray alloc] initWithObjects:@"mineqMelmailEmission", nil];
+ }
+
+ if((email = [self _cachedEmailForUID:_uid]))
+ return email;
+
+ q = [EOQualifier qualifierWithQualifierFormat:@"uid = %@", _uid];
+
+ conn = [self ldapConnection];
+ resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
+ qualifier:q
+ attributes:emailAttrs];
+ entry = [resultEnum nextObject];
+ if(!entry) {
+ if(debugOn) {
+ [self logWithFormat:@"%s Didn't find LDAP entry for uid '%@'!",
+ __PRETTY_FUNCTION__,
+ _uid];
+ }
+ return nil;
+ }
+ emailAttr = [entry attributeWithName:@"mineqMelmailEmission"];
+ if (!emailAttr) {
+ return nil; /* shit happens */
+ }
+ else {
+ unsigned count;
+
+ email = nil;
+ count = [emailAttr count];
+#if 0
+ if (count > 1) {
+ unsigned i;
+
+ /* in case there are multiple email addresses, select the first
+ which doesn't have '@equipement.gouv.fr' in it */
+ for (i = 0; i < count; i++) {
+ NSString *candidate;
+
+ candidate = [emailAttr stringValueAtIndex:i];
+ if (![candidate hasSuffix:@"@equipement.gouv.fr"]) {
+ email = candidate;
+ break;
+ }
+ }
+ }
+#endif
+ if (email == nil && count > 0) {
+ email = [emailAttr stringValueAtIndex:0];
+ }
+ [self _cacheEmail:email forUID:_uid];
+ return email;
+ }
+ }
+ else {
+ NSRange r;
+
+ if(!_uid || [_uid length] == 0)
+ return nil;
+ r = [_uid rangeOfString:@"@"];
+ if(r.length > 0)
+ return _uid;
+ return [NSString stringWithFormat:@"%@@equipement.gouv.fr", _uid];
+ }
+}
+
+
+/* CN */
+
+- (NSString *)getCNForUID:(NSString *)_uid {
+ if(useLDAP) {
+ static NSArray *cnAttrs = nil;
+ NGLdapConnection *conn;
+ EOQualifier *q;
+ NSEnumerator *resultEnum;
+ NGLdapEntry *entry;
+ NGLdapAttribute *cnAttr;
+ NSString *cn;
+
+ if(!cnAttrs) {
+ cnAttrs = [[NSArray alloc] initWithObjects:@"cn", nil];
+ }
+
+ if((cn = [self _cachedCNForUID:_uid]))
+ return cn;
+
+ q = [EOQualifier qualifierWithQualifierFormat:@"uid = %@", _uid];
+
+ conn = [self ldapConnection];
+ resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
+ qualifier:q
+ attributes:cnAttrs];
+ entry = [resultEnum nextObject];
+ if(!entry) {
+ if(debugOn) {
+ [self logWithFormat:@"%s Didn't find LDAP entry for uid '%@'!",
+ __PRETTY_FUNCTION__,
+ _uid];
+ }
+ return nil;
+ }
+ cnAttr = [entry attributeWithName:@"cn"];
+ if(!cnAttr && debugOn) {
+ [self logWithFormat:@"%s LDAP entry for uid '%@' has no common name?",
+ __PRETTY_FUNCTION__,
+ _uid];
+ return nil; /* nothing we can do about it */
+ }
+ cn = [cnAttr stringValueAtIndex:0];
+ [self _cacheCN:cn forUID:_uid];
+ return cn;
+ }
+ else {
+ NSString *s;
+ NSRange r;
+
+ s = _uid;
+ if ([s length] < 10)
+ return s;
+
+ // TODO: algorithm might be inappropriate, depends on the actual UID
+ r = [s rangeOfString:@"."];
+ if (r.length == 0)
+ return s;
+
+ return [s substringToIndex:r.location];
+ }
+}
+
+
+/* Servers, IMAP */
+
+- (NSString *)getIMAPAccountStringForUID:(NSString *)_uid {
+ NSString *server;
+
+ server = [self getServerForUID:_uid];
+ if(!server)
+ return nil;
+ return [NSString stringWithFormat:@"%@@%@", _uid, server];
+}
+
+- (NSString *)getServerForUID:(NSString *)_uid {
+ /*
+ First of all : for a particular user IMAP and SMTP are served on the same
+ host.
+
+ The name of the machine is determined by applying a regex on every values of
+ the mineqMelRoutage LDAP attribute.
+ The regex is : .*%.*@(.*\.melanie2\.i2$)
+ It extracts the substring that follows '@', ends with 'melanie2', on
+ adresses which have a '%' before the '@'
+
+ Example: helge.hesse%opengroupware.org@servername1.melanie2.i2
+ -> servername1.melanie2.i2
+
+ If only one server name is found by applying the regex on every value of the
+ attribute, then this name is the IMAP/SMTP server for that user.
+ Note that this is the case when we got a unique (well formed) value for the
+ attribute.
+ If the regex finds more than one servername when applied to the differents
+ values, then the IMAP/SMTP server name is to be found in the
+ mineqMelServeurPrincipal attribute of the user.
+ */
+ if(useLDAP) {
+ static NSArray *attrs = nil;
+ NGLdapConnection *conn;
+ EOQualifier *q;
+ NSEnumerator *resultEnum;
+ NGLdapEntry *entry;
+ NGLdapAttribute *attr;
+ NSMutableArray *serverCandidates;
+ NSString *server;
+
+ if(!attrs) {
+ attrs = [[NSArray alloc] initWithObjects:@"mineqMelRoutage",
+ @"mineqMelServeurPrincipal",
+ nil];
+ }
+
+ if((server = [self _cachedServerForUID:_uid]))
+ return server;
+
+ q = [EOQualifier qualifierWithQualifierFormat:@"uid = %@", _uid];
+
+ conn = [self ldapConnection];
+ resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
+ qualifier:q
+ attributes:attrs];
+ /* we just expect one entry, thus drop the rest */
+ entry = [resultEnum nextObject];
+ if(!entry) {
+ if(debugOn) {
+ NSLog(@"%s Didn't find LDAP entry for uid '%@'!",
+ __PRETTY_FUNCTION__,
+ _uid);
+ }
+ return nil;
+ }
+ attr = [entry attributeWithName:@"mineqMelRoutage"];
+ if(attr) {
+ unsigned i, count;
+
+ count = [attr count];
+ serverCandidates = [NSMutableArray arrayWithCapacity:count];
+ for(i = 0; i < count; i++) {
+ NSRange r;
+ NSString *route;
+
+ route = [attr stringValueAtIndex:i];
+ r = [route rangeOfString:@".melanie2.i2" options:NSBackwardsSearch];
+ if(r.length > 0) {
+ unsigned length;
+
+ /* be clever */
+ length = [route length];
+ r = NSMakeRange(0, length - r.length);
+ r = [route rangeOfString:@"@" options:NSBackwardsSearch range:r];
+ if(r.length > 0) {
+ unsigned start;
+ NSRange serverNameRange;
+
+ start = NSMaxRange(r);
+ serverNameRange = NSMakeRange(start, length - start);
+ r = NSMakeRange(0, length - start);
+ r = [route rangeOfString:@"%" options:NSBackwardsSearch range:r];
+ if(r.length > 0) {
+ NSString *serverName;
+
+ serverName = [route substringWithRange:serverNameRange];
+ [serverCandidates addObject:serverName];
+ }
+ }
+ }
+ }
+ }
+ else {
+ if(debugOn) {
+ NSLog(@"%s LDAP entry for uid '%@' has no mineqMelRoutage entry?",
+ __PRETTY_FUNCTION__,
+ _uid);
+ }
+ serverCandidates = nil;
+ }
+ if([serverCandidates count] == 1) {
+ server = [serverCandidates objectAtIndex:0];
+ }
+
+ /* last resort */
+ if(!server) {
+ attr = [entry attributeWithName:@"mineqMelServeurPrincipal"];
+ if([attr count] > 0)
+ server = [attr stringValueAtIndex:0];
+ }
+
+ if(!server) {
+ if(debugOn) {
+ NSLog(@"%s no chance of getting at server info for user '%@', "
+ @"tried everything. Sorry.",
+ __PRETTY_FUNCTION__,
+ _uid);
+ }
+ return nil;
+ }
+
+ [self _cacheServer:server forUID:_uid];
+ return server;
+ }
+ else {
+ return @"mail.opengroupware.org";
+ }
+}
+
+@end
+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)
SOGoGroupsFolder.h \
SOGoGroupFolder.h \
SOGoCustomGroupFolder.h \
+ \
+ SOGoAppointment.h \
+ AgenorUserManager.h \
+ SOGoLRUCache.h \
+ NSString+iCal.h
libSOGo_OBJC_FILES = \
SOGoObject.m \
SOGoGroupsFolder.m \
SOGoGroupFolder.m \
SOGoCustomGroupFolder.m \
+ \
+ SOGoAppointment.m \
+ SOGoAppointmentICalRenderer.m \
+ SOGoLRUCache.m \
+ AgenorUserManager.m \
-include GNUmakefile.preamble
include $(GNUSTEP_MAKEFILES)/library.make
--- /dev/null
+/*
+ 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$
+
+
+#ifndef __NSString_iCal_H_
+#define __NSString_iCal_H_
+
+// DEPRECATED
+
+#import <Foundation/Foundation.h>
+#include <NGiCal/iCalRenderer.h>
+
+#endif /* __NSString_iCal_H_ */
--- /dev/null
+/*
+ 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$
+
+#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
+{
+ 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)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)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;
+
+@end
+
+#endif /* __SOGoAppointment_H_ */
--- /dev/null
+/*
+ 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];
+ [super dealloc];
+}
+
+/* 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)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];
+ [catString release];
+}
+- (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)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;
+
+ partEmails = [[self participants] valueForKey:@"rfc822Email"];
+ return [partEmails containsObject:_email];
+}
+
+- (iCalPerson *)findParticipantWithEmail:(id)_email {
+ NSArray *ps;
+ unsigned i, count;
+
+ ps = [self participants];
+ count = [ps count];
+
+ for (i = 0; i < count; i++) {
+ iCalPerson *p;
+
+ p = [ps objectAtIndex:i];
+ if ([[p rfc822Email] 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];
+}
+
+
+/* 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 */
--- /dev/null
+/*
+ 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_ */
--- /dev/null
+/*
+ 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 "NSString+iCal.h"
+#include <NGiCal/NGiCal.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;
+
+ calendar = [_apt calendar];
+
+ [s appendString:@"BEGIN:VCALENDAR\r\nMETHOD:REQUEST\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 */
--- /dev/null
+/*
+ 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$
+
+
+#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_ */
--- /dev/null
+/*
+ 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$
+
+
+#import "SOGoLRUCache.h"
+#import "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
# version file
-SUBMINOR_VERSION:=29
+SUBMINOR_VERSION:=30
# v0.9.26 requires libOGoContentStore v0.9.13
/*
- Copyright (C) 2002-2004 SKYRIX Software AG
+ Copyright (C) 2002-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
-// $Id: common.h 335 2004-09-29 23:24:45Z helge $
#import <Foundation/Foundation.h>
#import <Foundation/NSObjCRuntime.h>
#include <NGObjWeb/NGObjWeb.h>
#include <NGObjWeb/SoObjects.h>
-#include <SOGoLogic/SOGoAppointment.h>
-
#include <NGImap4/NGImap4Client.h>
@end
#include <NGiCal/NGiCal.h>
-#include <SOGoLogic/AgenorUserManager.h>
+#include <SOGo/AgenorUserManager.h>
#include <Scheduler/iCalPerson+UIx.h>
#include <NGObjWeb/WOContext.h>
#include <NGObjWeb/WORequest.h>
@end
#include "common.h"
-#include <SOGoLogic/AgenorUserManager.h>
+#include <SOGo/AgenorUserManager.h>
@implementation UIxContactsSelectionView
-2005-02-15 Marcus Mueller <znek@mulle-kybernetik.com>
+2005-02-17 Helge Hess <helge.hess@opengroupware.org>
+
+ * fixed for removal of SOGoLogic (v0.9.114)
- * v0.9.113
+2005-02-15 Marcus Mueller <znek@mulle-kybernetik.com>
- * UIxCalView.m: removed dead code
+ * UIxCalView.m: removed dead code (v0.9.113)
2005-02-12 Marcus Mueller <znek@mulle-kybernetik.com>
/*
- Copyright (C) 2000-2004 SKYRIX Software AG
+ Copyright (C) 2000-2005 SKYRIX Software AG
- This file is part of OGo
+ 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, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
-// $Id$
-
#ifndef __SOGoAppointment_UIx_H_
#define __SOGoAppointment_UIx_H_
-
-#include <SOGoLogic/SOGoAppointment.h>
-
+#include <SOGo/SOGoAppointment.h>
@interface SOGoAppointment (UIx)
- (NSString *)priorityLabelKey;
#include <NGiCal/NGiCal.h>
#include <NGExtensions/NGCalendarDateRange.h>
#include <SOGoUI/SOGoDateFormatter.h>
-#include <SOGoLogic/SOGoAppointment.h>
+#include <SOGo/SOGoAppointment.h>
+#include <SOGo/AgenorUserManager.h>
#include <Appointments/SOGoAppointmentFolder.h>
#include <Appointments/SOGoAppointmentObject.h>
-#include <SOGoLogic/AgenorUserManager.h>
#include "iCalPerson+UIx.h"
#include "UIxComponent+Agenor.h"
#include "common.h"
#include <SOGo/UI/SOGoUI/SOGoDateFormatter.h>
-#include <SOGoLogic/SOGoAppointment.h>
+#include <SOGo/SOGoAppointment.h>
#include "UIxComponent+Agenor.h"
@implementation UIxAppointmentPrintview
-// $Id$
+/*
+ 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 "UIxAppointmentView.h"
#include <NGiCal/NGiCal.h>
-#include <SOGoLogic/SOGoAppointment.h>
+#include <SOGo/SOGoAppointment.h>
#include <Appointments/SOGoAppointmentObject.h>
#include <SOGoUI/SOGoDateFormatter.h>
#include "UIxComponent+Agenor.h"
@end
#include "common.h"
-#include <SOGoLogic/AgenorUserManager.h>
+#include <SOGo/AgenorUserManager.h>
@implementation UIxCalDayListview
#include "SoObjects/Appointments/SOGoAppointmentFolder.h"
#include <NGObjWeb/SoUser.h>
#include <SOGoUI/SOGoAptFormatter.h>
-#include <SOGoLogic/AgenorUserManager.h>
-#include <SOGoLogic/SOGoAppointment.h>
#include <NGExtensions/NGCalendarDateRange.h>
#include "UIxComponent+Agenor.h"
#include "common.h"
#include <NGExtensions/NGCalendarDateRange.h>
-#include <SOGoLogic/AgenorUserManager.h>
#include <sys/param.h> // MIN, MAX
#include <SOGoUI/SOGoAptFormatter.h>
#include "common.h"
#include <NGExtensions/NGCalendarDateRange.h>
-#include <SOGoLogic/AgenorUserManager.h>
+#include <SOGo/AgenorUserManager.h>
#include <SOGoUI/SOGoAptFormatter.h>
@implementation UIxCalWeekListview
/*
- Copyright (C) 2000-2004 SKYRIX Software AG
+ Copyright (C) 2000-2005 SKYRIX Software AG
- This file is part of OGo
+ 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, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
-// $Id$
-
#include "UIxComponent+Agenor.h"
-#include <SOGoLogic/AgenorUserManager.h>
+#include <SOGo/AgenorUserManager.h>
#include "common.h"
-@implementation UIxComponent (Agenor)
+@implementation UIxComponent(Agenor)
- (NSString *)emailForUser {
- NSString *uid;
+ NSString *uid;
- uid = [[self user] login];
- return [[AgenorUserManager sharedUserManager] getEmailForUID:uid];
+ uid = [[self user] login];
+ return [[AgenorUserManager sharedUserManager] getEmailForUID:uid];
}
- (NSString *)cnForUser {
- NSString *uid;
+ NSString *uid;
- uid = [[self user] login];
- return [[AgenorUserManager sharedUserManager] getCNForUID:uid];
+ uid = [[self user] login];
+ return [[AgenorUserManager sharedUserManager] getCNForUID:uid];
}
-@end
+@end /* UIxComponent(Agenor) */
-# $Id$
+# Version file
-SUBMINOR_VERSION:=112
+SUBMINOR_VERSION:=113
+# v0.9.113 requires libSOGo v0.9.30
# v0.9.112 requires SOGoLogic v0.9.12
# v0.9.107 requires WOExtensions v4.5.21
# v0.9.105 requires NGObjWeb v4.5.102