From fb18e6ec8d5baaf33ff04b751772fe5daa2c87f9 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Fri, 15 May 2009 20:26:25 +0000 Subject: [PATCH] See ChangeLog Monotone-Parent: bab59e2cce32327be3e5571e6b50d880dffdd253 Monotone-Revision: f00d778f8af0801dcc730f04b0149cc2f3292501 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2009-05-15T20:26:25 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 13 + SOPE/sope-patchset-r1632.diff | 905 +++++++++--------- SoObjects/Mailer/SOGoMailAccount.m | 5 +- UI/PreferencesUI/UIxPreferences.m | 13 + UI/Templates/PreferencesUI/UIxPreferences.wox | 5 + UI/WebServerResources/UIxPreferences.js | 2 +- 6 files changed, 510 insertions(+), 433 deletions(-) diff --git a/ChangeLog b/ChangeLog index 50d7e01a1..290f02de1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,22 @@ 2009-05-15 Francis Lachapelle + * SOPE/sope-ldap/NGLdap/NGLdapConnection.m: added methods + primaryFetchMailboxHierarchyForURL:onlySubscribedFolders: and + allFoldersForURL:onlySubscribedFolders: to offer the possibility + to use the IMAP command LSUB instead of LIST. + + * SoObjects/Mailer/SOGoMailAccount.m ([SOGoMailAccount + -allFolderPaths]): return only subscribed folders if user default + "showSubscribedFoldersOnly" is true. + * SoObjects/SOGo/SOGoUserDefaults.m ([SOGoUserDefaults -setObject:forKey:]): fix an issue when calling removeObjectForKey and value is nil. + * UI/PreferencesUI/UIxPreferences.m ([UIxPreferences + -setShowSubscribedFoldersOnly:]): setter for the user default + "showSubscribedFoldersOnly". + 2009-05-12 Francis Lachapelle * SoObjects/SOGo/LDAPSource.m ([LDAPSource -initFromSource:]): diff --git a/SOPE/sope-patchset-r1632.diff b/SOPE/sope-patchset-r1632.diff index a51141f9f..7afb9dc5b 100644 --- a/SOPE/sope-patchset-r1632.diff +++ b/SOPE/sope-patchset-r1632.diff @@ -60,419 +60,6 @@ Index: sope-ldap/NGLdap/NGLdapConnection.h /* binding */ - (BOOL)isBound; -Index: sope-gdl1/PostgreSQL/PostgreSQL72Channel.m -=================================================================== ---- sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (revision 1632) -+++ sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (working copy) -@@ -713,6 +713,39 @@ - return ms; - } - -+/* GCSEOAdaptorChannel protocol */ -+static NSString *sqlFolderFormat = (@"CREATE TABLE %@ (\n" \ -+ @" c_name VARCHAR (256) NOT NULL PRIMARY KEY,\n" -+ @" c_content VARCHAR (100000) NOT NULL,\n" -+ @" c_creationdate INT4 NOT NULL,\n" -+ @" c_lastmodified INT4 NOT NULL,\n" -+ @" c_version INT4 NOT NULL,\n" -+ @" c_deleted INT4 NULL\n" -+ @")"); -+static NSString *sqlFolderACLFormat = (@"CREATE TABLE %@ (\n" \ -+ @" c_uid VARCHAR (256) NOT NULL,\n" -+ @" c_object VARCHAR (256) NOT NULL,\n" -+ @" c_role VARCHAR (80) NOT NULL\n" -+ @")"); -+ -+- (NSException *) createGCSFolderTableWithName: (NSString *) tableName -+{ -+ NSString *sql; -+ -+ sql = [NSString stringWithFormat: sqlFolderFormat, tableName]; -+ -+ return [self evaluateExpressionX: sql]; -+} -+ -+- (NSException *) createGCSFolderACLTableWithName: (NSString *) tableName -+{ -+ NSString *sql; -+ -+ sql = [NSString stringWithFormat: sqlFolderACLFormat, tableName]; -+ -+ return [self evaluateExpressionX: sql]; -+} -+ - @end /* PostgreSQL72Channel */ - - @implementation PostgreSQL72Channel(PrimaryKeyGeneration) -Index: sope-gdl1/MySQL/MySQL4Channel.m -=================================================================== ---- sope-gdl1/MySQL/MySQL4Channel.m (revision 1632) -+++ sope-gdl1/MySQL/MySQL4Channel.m (working copy) -@@ -755,6 +755,39 @@ - return pkey; - } - -+/* GCSEOAdaptorChannel protocol */ -+static NSString *sqlFolderFormat = (@"CREATE TABLE %@ (\n" \ -+ @" c_name VARCHAR (256) NOT NULL PRIMARY KEY,\n" -+ @" c_content VARCHAR (100000) NOT NULL,\n" -+ @" c_creationdate INT NOT NULL,\n" -+ @" c_lastmodified INT NOT NULL,\n" -+ @" c_version INT NOT NULL,\n" -+ @" c_deleted INT NULL\n" -+ @")"); -+static NSString *sqlFolderACLFormat = (@"CREATE TABLE %@ (\n" \ -+ @" c_uid VARCHAR (256) NOT NULL,\n" -+ @" c_object VARCHAR (256) NOT NULL,\n" -+ @" c_role VARCHAR (80) NOT NULL\n" -+ @")"); -+ -+- (NSException *) createGCSFolderTableWithName: (NSString *) tableName -+{ -+ NSString *sql; -+ -+ sql = [NSString stringWithFormat: sqlFolderFormat, tableName]; -+ -+ return [self evaluateExpressionX: sql]; -+} -+ -+- (NSException *) createGCSFolderACLTableWithName: (NSString *) tableName -+{ -+ NSString *sql; -+ -+ sql = [NSString stringWithFormat: sqlFolderACLFormat, tableName]; -+ -+ return [self evaluateExpressionX: sql]; -+} -+ - @end /* MySQL4Channel */ - - void __link_MySQL4Channel() { -Index: sope-gdl1/GDLAccess/EOAdaptor.m -=================================================================== ---- sope-gdl1/GDLAccess/EOAdaptor.m (revision 1632) -+++ sope-gdl1/GDLAccess/EOAdaptor.m (working copy) -@@ -202,6 +202,7 @@ - if ([_scheme isEqualToString:@"sybase"]) return @"Sybase10"; - if ([_scheme isEqualToString:@"sqlite"]) return @"SQLite3"; - if ([_scheme isEqualToString:@"oracle"]) return @"Oracle8"; -+ if ([_scheme isEqualToString:@"mysql"]) return @"MySQL"; - - if ([_scheme isEqualToString:@"http"]) { - NSLog(@"WARNING(%s): asked for 'http' URL, " -Index: sope-gdl1/Oracle8/OracleAdaptorChannel.m -=================================================================== ---- sope-gdl1/Oracle8/OracleAdaptorChannel.m (revision 1632) -+++ sope-gdl1/Oracle8/OracleAdaptorChannel.m (working copy) -@@ -1,7 +1,7 @@ - /* - ** OracleAdaptorChannel.m - ** --** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte -+** Copyright (c) 2007-2009 Inverse inc. and Ludovic Marcotte - ** - ** Author: Ludovic Marcotte - ** -@@ -30,6 +30,11 @@ - - #import - -+#include -+ -+static BOOL debugOn = NO; -+static int maxTry = 3; -+static int maxSleep = 500; - // - // - // -@@ -41,10 +46,11 @@ - - @implementation OracleAdaptorChannel (Private) - --- (void) _cleanup -+- (void) _cleanup - { - column_info *info; - int c; -+ sword result; - - [_resultSetProperties removeAllObjects]; - -@@ -58,11 +64,29 @@ - // so we just free the value instead. - if (info->value) - { -- if (OCIDescriptorFree((dvoid *)info->value, (ub4)OCI_DTYPE_LOB) != OCI_SUCCESS) -+ if (info->type == SQLT_CLOB -+ || info->type == SQLT_BLOB -+ || info->type == SQLT_BFILEE -+ || info->type == SQLT_CFILEE) -+ { -+ result = OCIDescriptorFree((dvoid *)info->value, (ub4) OCI_DTYPE_LOB); -+ if (result != OCI_SUCCESS) -+ { -+ NSLog (@"value was not a LOB descriptor"); -+ abort(); -+ } -+ } -+ else - free(info->value); - info->value = NULL; - } -- free(info); -+ else -+ { -+ NSLog (@"trying to free an already freed value!"); -+ abort(); -+ } -+ free(info); -+ - [_row_buffer removeObjectAtIndex: c]; - } - -@@ -78,8 +102,7 @@ - // - @implementation OracleAdaptorChannel - --static void --DBTerminate() -+static void DBTerminate() - { - if (OCITerminate(OCI_DEFAULT)) - NSLog(@"FAILED: OCITerminate()"); -@@ -89,6 +112,11 @@ - - + (void) initialize - { -+ NSUserDefaults *ud; -+ -+ ud = [NSUserDefaults standardUserDefaults]; -+ debugOn = [ud boolForKey: @"OracleAdaptorDebug"]; -+ - // We Initialize the OCI process environment. - if (OCIInitialize((ub4)OCI_DEFAULT, (dvoid *)0, - (dvoid * (*)(dvoid *, size_t)) 0, -@@ -156,14 +184,17 @@ - [super closeChannel]; - - // We logoff from the database. -- if (OCILogoff(_oci_ctx, _oci_err)) -+ if (!_oci_ctx || !_oci_err || OCILogoff(_oci_ctx, _oci_err)) - { - NSLog(@"FAILED: OCILogoff()"); - } - -+ if (_oci_ctx) -+ OCIHandleFree(_oci_ctx, OCI_HTYPE_SVCCTX); - -- OCIHandleFree(_oci_ctx, OCI_HTYPE_SVCCTX); -- OCIHandleFree(_oci_err, OCI_HTYPE_ERROR); -+ if (_oci_err) -+ OCIHandleFree(_oci_err, OCI_HTYPE_ERROR); -+ - // OCIHandleFree(_oci_env, OCI_HTYPE_ENV); - - _oci_ctx = (OCISvcCtx *)0; -@@ -177,7 +208,8 @@ - // - - (void) dealloc - { -- //NSLog(@"OracleAdaptorChannel: -dealloc"); -+ if (debugOn) -+ NSLog(@"OracleAdaptorChannel: -dealloc"); - - [self _cleanup]; - -@@ -222,7 +254,7 @@ - { - EOAttribute *attribute; - OCIParam *param; -- -+ int rCount; - column_info *info; - ub4 i, clen, count; - text *sql, *cname; -@@ -231,6 +263,9 @@ - - [self _cleanup]; - -+ if (debugOn) -+ [self logWithFormat: @"expression: %@", theExpression]; -+ - if (!theExpression || ![theExpression length]) - { - [NSException raise: @"OracleInvalidExpressionException" -@@ -244,7 +279,9 @@ - } - - sql = (text *)[theExpression UTF8String]; -- -+ -+ rCount = 0; -+ retry: - // We alloc our statement handle - if ((status = OCIHandleAlloc((dvoid *)_oci_env, (dvoid **)&_current_stm, (ub4)OCI_HTYPE_STMT, (CONST size_t) 0, (dvoid **) 0))) - { -@@ -264,13 +301,39 @@ - // We check if we're doing a SELECT and if so, we're fetching data! - OCIAttrGet(_current_stm, OCI_HTYPE_STMT, &type, 0, OCI_ATTR_STMT_TYPE, _oci_err); - self->isFetchInProgress = (type == OCI_STMT_SELECT ? YES : NO); -- -+ - // We execute our statement. Not that we _MUST_ set iter to 0 for non-SELECT statements. - if ((status = OCIStmtExecute(_oci_ctx, _current_stm, _oci_err, (self->isFetchInProgress ? (ub4)0 : (ub4)1), (ub4)0, (CONST OCISnapshot *)NULL, (OCISnapshot *)NULL, - ([(OracleAdaptorContext *)[self adaptorContext] autoCommit] ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT)))) - { -+ ub4 serverStatus; -+ - checkerr(_oci_err, status); - NSLog(@"Statement execute failed (OCI_ERROR): %@", theExpression); -+ -+ // We check to see if we lost connection and need to reconnect. -+ serverStatus = 0; -+ OCIAttrGet((dvoid *)_oci_env, OCI_HTYPE_SERVER, (dvoid *)&serverStatus, (ub4 *)0, OCI_ATTR_SERVER_STATUS, _oci_err); -+ -+ if (serverStatus == OCI_SERVER_NOT_CONNECTED) -+ { -+ // We cleanup our previous handles -+ [self cancelFetch]; -+ [self closeChannel]; -+ -+ // We try to reconnect a couple of times before giving up... -+ while (rCount < maxTry) -+ { -+ usleep(maxSleep); -+ rCount++; -+ -+ if ([self openChannel]) -+ { -+ NSLog(@"Connection re-established to Oracle - retrying to process the statement."); -+ goto retry; -+ } -+ } -+ } - return NO; - } - -@@ -302,7 +365,9 @@ - // We read the maximum width of a column - info->max_width = 0; - status = OCIAttrGet((dvoid*)param, (ub4)OCI_DTYPE_PARAM, (dvoid*)&(info->max_width), (ub4 *)0, (ub4)OCI_ATTR_DATA_SIZE, (OCIError *)_oci_err); -- -+ -+ if (debugOn) -+ NSLog(@"name: %s, type: %d", cname, info->type); - attribute = [EOAttribute attributeWithOracleType: info->type name: cname length: clen width: info->max_width]; - [_resultSetProperties addObject: attribute]; - -@@ -394,16 +459,17 @@ - return NO; - } - -- - if (OCIEnvInit((OCIEnv **)&_oci_env, (ub4)OCI_DEFAULT, (size_t)0, (dvoid **)0)) - { - NSLog(@"FAILED: OCIEnvInit()"); -+ [self closeChannel]; - return NO; - } - - if (OCIHandleAlloc((dvoid *)_oci_env, (dvoid *)&_oci_err, (ub4)OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0)) - { - NSLog(@"FAILED: OCIHandleAlloc() on errhp"); -+ [self closeChannel]; - return NO; - } - -@@ -414,7 +480,10 @@ - // Under Oracle 10g, the third parameter of OCILogon() has the form: [//]host[:port][/service_name] - // See http://download-west.oracle.com/docs/cd/B12037_01/network.101/b10775/naming.htm#i498306 for - // all juicy details. -- database = [[NSString stringWithFormat:@"%@:%@", [o serverName], [o port]] UTF8String]; -+ if ([o serverName] && [o port]) -+ database = [[NSString stringWithFormat:@"%@:%@/%@", [o serverName], [o port], [o databaseName]] UTF8String]; -+ else -+ database = [[o databaseName] UTF8String]; - - // We logon to the database. - if (OCILogon(_oci_env, _oci_err, &_oci_ctx, (const OraText*)username, strlen(username), -@@ -422,6 +491,7 @@ - { - NSLog(@"FAILED: OCILogon(). username = %s password = %s" - @" database = %s", username, password, database); -+ [self closeChannel]; - return NO; - } - -@@ -438,6 +508,11 @@ - { - sword status; - -+ // We check if our connection is open prior to trying to fetch any data. OCIStmtFetch2() returns -+ // NO error code if the OCI environment is set up but the OCILogon() has failed. -+ if (![self isOpen]) -+ return nil; -+ - status = OCIStmtFetch2(_current_stm, _oci_err, (ub4)1, (ub4)OCI_FETCH_NEXT, (sb4)0, (ub4)OCI_DEFAULT); - - if (status == OCI_NO_DATA) -@@ -609,7 +684,7 @@ - - /* GCSEOAdaptorChannel protocol */ - static NSString *sqlFolderFormat = (@"CREATE TABLE %@ (\n" \ -- @" c_name VARCHAR2 (256) NOT NULL,\n" -+ @" c_name VARCHAR2 (256) NOT NULL PRIMARY KEY,\n" - @" c_content CLOB NOT NULL,\n" - @" c_creationdate INTEGER NOT NULL,\n" - @" c_lastmodified INTEGER NOT NULL,\n" -Index: sope-gdl1/Oracle8/OracleAdaptorChannelController.m -=================================================================== ---- sope-gdl1/Oracle8/OracleAdaptorChannelController.m (revision 1632) -+++ sope-gdl1/Oracle8/OracleAdaptorChannelController.m (working copy) -@@ -31,6 +31,8 @@ - #import - #import - -+static BOOL debugOn = NO; -+ - // - // - // -@@ -48,6 +50,14 @@ - // - @implementation OracleAdaptorChannelController - -++ (void) initialize -+{ -+ NSUserDefaults *ud; -+ -+ ud = [NSUserDefaults standardUserDefaults]; -+ debugOn = [ud boolForKey: @"OracleAdaptorDebug"]; -+} -+ - - (EODelegateResponse) adaptorChannel: (id) theChannel - willInsertRow: (NSMutableDictionary *) theRow - forEntity: (EOEntity *) theEntity -@@ -56,7 +66,8 @@ - NSArray *keys; - int i, c; - -- NSLog(@"willInsertRow: %@ %@", [theRow description], [theEntity description]); -+ if (debugOn) -+ NSLog(@"willInsertRow: %@ %@", [theRow description], [theEntity description]); - - s = AUTORELEASE([[NSMutableString alloc] init]); - -@@ -101,7 +112,8 @@ - NSArray *keys; - int i, c; - -- NSLog(@"willUpdatetRow: %@ %@", [theRow description], [theQualifier description]); -+ if (debugOn) -+ NSLog(@"willUpdateRow: %@ %@", [theRow description], [theQualifier description]); - - s = AUTORELEASE([[NSMutableString alloc] init]); - Index: sope-mime/NGImap4/NGImap4Client.h =================================================================== --- sope-mime/NGImap4/NGImap4Client.h (revision 1632) @@ -864,16 +451,59 @@ Index: sope-mime/NGImap4/NGImap4Connection.m =================================================================== --- sope-mime/NGImap4/NGImap4Connection.m (revision 1632) +++ sope-mime/NGImap4/NGImap4Connection.m (working copy) -@@ -381,7 +381,7 @@ +@@ -373,7 +373,14 @@ + + /* folder operations */ + +-- (NSDictionary *)primaryFetchMailboxHierarchyForURL:(NSURL *)_url { ++- (NSDictionary *)primaryFetchMailboxHierarchyForURL:(NSURL *)_url ++{ ++ return [self primaryFetchMailboxHierarchyForURL: _url onlySubscribedFolders: NO]; ++} ++ ++- (NSDictionary *)primaryFetchMailboxHierarchyForURL:(NSURL *)_url ++ onlySubscribedFolders: (BOOL) subscribedFoldersOnly ++{ + NSDictionary *result; + + if ((result = [self cachedHierarchyResults]) != nil) +@@ -381,8 +388,12 @@ if (debugCache) [self logWithFormat:@" no folders cached yet .."]; - result = [[self client] list:(onlyFetchInbox ? @"INBOX" : @"*") -+ result = [[self client] list:(onlyFetchInbox ? @"INBOX" : @"") - pattern:@"*"]; +- pattern:@"*"]; ++ if (subscribedFoldersOnly) ++ result = [[self client] lsub:(onlyFetchInbox ? @"INBOX" : @"") ++ pattern:@"*"]; ++ else ++ result = [[self client] list:(onlyFetchInbox ? @"INBOX" : @"") ++ pattern:@"*"]; if (![[result valueForKey:@"result"] boolValue]) { [self errorWithFormat:@"Could not list mailbox hierarchy!"]; -@@ -646,7 +646,7 @@ + return nil; +@@ -413,10 +424,18 @@ + return [self extractSubfoldersForURL:_url fromResultSet:result]; + } + +-- (NSArray *)allFoldersForURL:(NSURL *)_url { ++- (NSArray *)allFoldersForURL:(NSURL *)_url ++{ ++ return [self allFoldersForURL: _url onlySubscribedFolders: NO]; ++} ++ ++- (NSArray *)allFoldersForURL:(NSURL *)_url ++ onlySubscribedFolders: (BOOL) subscribedFoldersOnly ++{ + NSDictionary *result; + +- if ((result = [self primaryFetchMailboxHierarchyForURL:_url]) == nil) ++ if ((result = [self primaryFetchMailboxHierarchyForURL:_url ++ onlySubscribedFolders: subscribedFoldersOnly]) == nil) + return nil; + if ([result isKindOfClass:[NSException class]]) { + [self errorWithFormat:@"failed to retrieve hierarchy: %@", result]; +@@ -646,7 +665,7 @@ /* store flags */ @@ -882,7 +512,7 @@ Index: sope-mime/NGImap4/NGImap4Connection.m if (![[result valueForKey:@"result"] boolValue]) { return [self errorForResult:result text:@"Failed to change flags of IMAP4 message"]; -@@ -736,7 +736,7 @@ +@@ -736,7 +755,7 @@ /* managing folders */ - (BOOL)doesMailboxExistAtURL:(NSURL *)_url { @@ -891,7 +521,7 @@ Index: sope-mime/NGImap4/NGImap4Connection.m id result; /* check in hierarchy cache */ -@@ -760,11 +760,11 @@ +@@ -760,11 +779,11 @@ // TODO: we should probably just fetch the whole hierarchy? folderName = [self imap4FolderNameForURL:_url]; @@ -3577,6 +3207,419 @@ Index: sope-mime/NGMime/NGMimeContentDispositionHeaderFieldGenerator.m } return data; } +Index: sope-gdl1/PostgreSQL/PostgreSQL72Channel.m +=================================================================== +--- sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (revision 1632) ++++ sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (working copy) +@@ -713,6 +713,39 @@ + return ms; + } + ++/* GCSEOAdaptorChannel protocol */ ++static NSString *sqlFolderFormat = (@"CREATE TABLE %@ (\n" \ ++ @" c_name VARCHAR (256) NOT NULL PRIMARY KEY,\n" ++ @" c_content VARCHAR (100000) NOT NULL,\n" ++ @" c_creationdate INT4 NOT NULL,\n" ++ @" c_lastmodified INT4 NOT NULL,\n" ++ @" c_version INT4 NOT NULL,\n" ++ @" c_deleted INT4 NULL\n" ++ @")"); ++static NSString *sqlFolderACLFormat = (@"CREATE TABLE %@ (\n" \ ++ @" c_uid VARCHAR (256) NOT NULL,\n" ++ @" c_object VARCHAR (256) NOT NULL,\n" ++ @" c_role VARCHAR (80) NOT NULL\n" ++ @")"); ++ ++- (NSException *) createGCSFolderTableWithName: (NSString *) tableName ++{ ++ NSString *sql; ++ ++ sql = [NSString stringWithFormat: sqlFolderFormat, tableName]; ++ ++ return [self evaluateExpressionX: sql]; ++} ++ ++- (NSException *) createGCSFolderACLTableWithName: (NSString *) tableName ++{ ++ NSString *sql; ++ ++ sql = [NSString stringWithFormat: sqlFolderACLFormat, tableName]; ++ ++ return [self evaluateExpressionX: sql]; ++} ++ + @end /* PostgreSQL72Channel */ + + @implementation PostgreSQL72Channel(PrimaryKeyGeneration) +Index: sope-gdl1/MySQL/MySQL4Channel.m +=================================================================== +--- sope-gdl1/MySQL/MySQL4Channel.m (revision 1632) ++++ sope-gdl1/MySQL/MySQL4Channel.m (working copy) +@@ -755,6 +755,39 @@ + return pkey; + } + ++/* GCSEOAdaptorChannel protocol */ ++static NSString *sqlFolderFormat = (@"CREATE TABLE %@ (\n" \ ++ @" c_name VARCHAR (256) NOT NULL PRIMARY KEY,\n" ++ @" c_content VARCHAR (100000) NOT NULL,\n" ++ @" c_creationdate INT NOT NULL,\n" ++ @" c_lastmodified INT NOT NULL,\n" ++ @" c_version INT NOT NULL,\n" ++ @" c_deleted INT NULL\n" ++ @")"); ++static NSString *sqlFolderACLFormat = (@"CREATE TABLE %@ (\n" \ ++ @" c_uid VARCHAR (256) NOT NULL,\n" ++ @" c_object VARCHAR (256) NOT NULL,\n" ++ @" c_role VARCHAR (80) NOT NULL\n" ++ @")"); ++ ++- (NSException *) createGCSFolderTableWithName: (NSString *) tableName ++{ ++ NSString *sql; ++ ++ sql = [NSString stringWithFormat: sqlFolderFormat, tableName]; ++ ++ return [self evaluateExpressionX: sql]; ++} ++ ++- (NSException *) createGCSFolderACLTableWithName: (NSString *) tableName ++{ ++ NSString *sql; ++ ++ sql = [NSString stringWithFormat: sqlFolderACLFormat, tableName]; ++ ++ return [self evaluateExpressionX: sql]; ++} ++ + @end /* MySQL4Channel */ + + void __link_MySQL4Channel() { +Index: sope-gdl1/GDLAccess/EOAdaptor.m +=================================================================== +--- sope-gdl1/GDLAccess/EOAdaptor.m (revision 1632) ++++ sope-gdl1/GDLAccess/EOAdaptor.m (working copy) +@@ -202,6 +202,7 @@ + if ([_scheme isEqualToString:@"sybase"]) return @"Sybase10"; + if ([_scheme isEqualToString:@"sqlite"]) return @"SQLite3"; + if ([_scheme isEqualToString:@"oracle"]) return @"Oracle8"; ++ if ([_scheme isEqualToString:@"mysql"]) return @"MySQL"; + + if ([_scheme isEqualToString:@"http"]) { + NSLog(@"WARNING(%s): asked for 'http' URL, " +Index: sope-gdl1/Oracle8/OracleAdaptorChannel.m +=================================================================== +--- sope-gdl1/Oracle8/OracleAdaptorChannel.m (revision 1632) ++++ sope-gdl1/Oracle8/OracleAdaptorChannel.m (working copy) +@@ -1,7 +1,7 @@ + /* + ** OracleAdaptorChannel.m + ** +-** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ++** Copyright (c) 2007-2009 Inverse inc. and Ludovic Marcotte + ** + ** Author: Ludovic Marcotte + ** +@@ -30,6 +30,11 @@ + + #import + ++#include ++ ++static BOOL debugOn = NO; ++static int maxTry = 3; ++static int maxSleep = 500; + // + // + // +@@ -41,10 +46,11 @@ + + @implementation OracleAdaptorChannel (Private) + +-- (void) _cleanup ++- (void) _cleanup + { + column_info *info; + int c; ++ sword result; + + [_resultSetProperties removeAllObjects]; + +@@ -58,11 +64,29 @@ + // so we just free the value instead. + if (info->value) + { +- if (OCIDescriptorFree((dvoid *)info->value, (ub4)OCI_DTYPE_LOB) != OCI_SUCCESS) ++ if (info->type == SQLT_CLOB ++ || info->type == SQLT_BLOB ++ || info->type == SQLT_BFILEE ++ || info->type == SQLT_CFILEE) ++ { ++ result = OCIDescriptorFree((dvoid *)info->value, (ub4) OCI_DTYPE_LOB); ++ if (result != OCI_SUCCESS) ++ { ++ NSLog (@"value was not a LOB descriptor"); ++ abort(); ++ } ++ } ++ else + free(info->value); + info->value = NULL; + } +- free(info); ++ else ++ { ++ NSLog (@"trying to free an already freed value!"); ++ abort(); ++ } ++ free(info); ++ + [_row_buffer removeObjectAtIndex: c]; + } + +@@ -78,8 +102,7 @@ + // + @implementation OracleAdaptorChannel + +-static void +-DBTerminate() ++static void DBTerminate() + { + if (OCITerminate(OCI_DEFAULT)) + NSLog(@"FAILED: OCITerminate()"); +@@ -89,6 +112,11 @@ + + + (void) initialize + { ++ NSUserDefaults *ud; ++ ++ ud = [NSUserDefaults standardUserDefaults]; ++ debugOn = [ud boolForKey: @"OracleAdaptorDebug"]; ++ + // We Initialize the OCI process environment. + if (OCIInitialize((ub4)OCI_DEFAULT, (dvoid *)0, + (dvoid * (*)(dvoid *, size_t)) 0, +@@ -156,14 +184,17 @@ + [super closeChannel]; + + // We logoff from the database. +- if (OCILogoff(_oci_ctx, _oci_err)) ++ if (!_oci_ctx || !_oci_err || OCILogoff(_oci_ctx, _oci_err)) + { + NSLog(@"FAILED: OCILogoff()"); + } + ++ if (_oci_ctx) ++ OCIHandleFree(_oci_ctx, OCI_HTYPE_SVCCTX); + +- OCIHandleFree(_oci_ctx, OCI_HTYPE_SVCCTX); +- OCIHandleFree(_oci_err, OCI_HTYPE_ERROR); ++ if (_oci_err) ++ OCIHandleFree(_oci_err, OCI_HTYPE_ERROR); ++ + // OCIHandleFree(_oci_env, OCI_HTYPE_ENV); + + _oci_ctx = (OCISvcCtx *)0; +@@ -177,7 +208,8 @@ + // + - (void) dealloc + { +- //NSLog(@"OracleAdaptorChannel: -dealloc"); ++ if (debugOn) ++ NSLog(@"OracleAdaptorChannel: -dealloc"); + + [self _cleanup]; + +@@ -222,7 +254,7 @@ + { + EOAttribute *attribute; + OCIParam *param; +- ++ int rCount; + column_info *info; + ub4 i, clen, count; + text *sql, *cname; +@@ -231,6 +263,9 @@ + + [self _cleanup]; + ++ if (debugOn) ++ [self logWithFormat: @"expression: %@", theExpression]; ++ + if (!theExpression || ![theExpression length]) + { + [NSException raise: @"OracleInvalidExpressionException" +@@ -244,7 +279,9 @@ + } + + sql = (text *)[theExpression UTF8String]; +- ++ ++ rCount = 0; ++ retry: + // We alloc our statement handle + if ((status = OCIHandleAlloc((dvoid *)_oci_env, (dvoid **)&_current_stm, (ub4)OCI_HTYPE_STMT, (CONST size_t) 0, (dvoid **) 0))) + { +@@ -264,13 +301,39 @@ + // We check if we're doing a SELECT and if so, we're fetching data! + OCIAttrGet(_current_stm, OCI_HTYPE_STMT, &type, 0, OCI_ATTR_STMT_TYPE, _oci_err); + self->isFetchInProgress = (type == OCI_STMT_SELECT ? YES : NO); +- ++ + // We execute our statement. Not that we _MUST_ set iter to 0 for non-SELECT statements. + if ((status = OCIStmtExecute(_oci_ctx, _current_stm, _oci_err, (self->isFetchInProgress ? (ub4)0 : (ub4)1), (ub4)0, (CONST OCISnapshot *)NULL, (OCISnapshot *)NULL, + ([(OracleAdaptorContext *)[self adaptorContext] autoCommit] ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT)))) + { ++ ub4 serverStatus; ++ + checkerr(_oci_err, status); + NSLog(@"Statement execute failed (OCI_ERROR): %@", theExpression); ++ ++ // We check to see if we lost connection and need to reconnect. ++ serverStatus = 0; ++ OCIAttrGet((dvoid *)_oci_env, OCI_HTYPE_SERVER, (dvoid *)&serverStatus, (ub4 *)0, OCI_ATTR_SERVER_STATUS, _oci_err); ++ ++ if (serverStatus == OCI_SERVER_NOT_CONNECTED) ++ { ++ // We cleanup our previous handles ++ [self cancelFetch]; ++ [self closeChannel]; ++ ++ // We try to reconnect a couple of times before giving up... ++ while (rCount < maxTry) ++ { ++ usleep(maxSleep); ++ rCount++; ++ ++ if ([self openChannel]) ++ { ++ NSLog(@"Connection re-established to Oracle - retrying to process the statement."); ++ goto retry; ++ } ++ } ++ } + return NO; + } + +@@ -302,7 +365,9 @@ + // We read the maximum width of a column + info->max_width = 0; + status = OCIAttrGet((dvoid*)param, (ub4)OCI_DTYPE_PARAM, (dvoid*)&(info->max_width), (ub4 *)0, (ub4)OCI_ATTR_DATA_SIZE, (OCIError *)_oci_err); +- ++ ++ if (debugOn) ++ NSLog(@"name: %s, type: %d", cname, info->type); + attribute = [EOAttribute attributeWithOracleType: info->type name: cname length: clen width: info->max_width]; + [_resultSetProperties addObject: attribute]; + +@@ -394,16 +459,17 @@ + return NO; + } + +- + if (OCIEnvInit((OCIEnv **)&_oci_env, (ub4)OCI_DEFAULT, (size_t)0, (dvoid **)0)) + { + NSLog(@"FAILED: OCIEnvInit()"); ++ [self closeChannel]; + return NO; + } + + if (OCIHandleAlloc((dvoid *)_oci_env, (dvoid *)&_oci_err, (ub4)OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0)) + { + NSLog(@"FAILED: OCIHandleAlloc() on errhp"); ++ [self closeChannel]; + return NO; + } + +@@ -414,7 +480,10 @@ + // Under Oracle 10g, the third parameter of OCILogon() has the form: [//]host[:port][/service_name] + // See http://download-west.oracle.com/docs/cd/B12037_01/network.101/b10775/naming.htm#i498306 for + // all juicy details. +- database = [[NSString stringWithFormat:@"%@:%@", [o serverName], [o port]] UTF8String]; ++ if ([o serverName] && [o port]) ++ database = [[NSString stringWithFormat:@"%@:%@/%@", [o serverName], [o port], [o databaseName]] UTF8String]; ++ else ++ database = [[o databaseName] UTF8String]; + + // We logon to the database. + if (OCILogon(_oci_env, _oci_err, &_oci_ctx, (const OraText*)username, strlen(username), +@@ -422,6 +491,7 @@ + { + NSLog(@"FAILED: OCILogon(). username = %s password = %s" + @" database = %s", username, password, database); ++ [self closeChannel]; + return NO; + } + +@@ -438,6 +508,11 @@ + { + sword status; + ++ // We check if our connection is open prior to trying to fetch any data. OCIStmtFetch2() returns ++ // NO error code if the OCI environment is set up but the OCILogon() has failed. ++ if (![self isOpen]) ++ return nil; ++ + status = OCIStmtFetch2(_current_stm, _oci_err, (ub4)1, (ub4)OCI_FETCH_NEXT, (sb4)0, (ub4)OCI_DEFAULT); + + if (status == OCI_NO_DATA) +@@ -609,7 +684,7 @@ + + /* GCSEOAdaptorChannel protocol */ + static NSString *sqlFolderFormat = (@"CREATE TABLE %@ (\n" \ +- @" c_name VARCHAR2 (256) NOT NULL,\n" ++ @" c_name VARCHAR2 (256) NOT NULL PRIMARY KEY,\n" + @" c_content CLOB NOT NULL,\n" + @" c_creationdate INTEGER NOT NULL,\n" + @" c_lastmodified INTEGER NOT NULL,\n" +Index: sope-gdl1/Oracle8/OracleAdaptorChannelController.m +=================================================================== +--- sope-gdl1/Oracle8/OracleAdaptorChannelController.m (revision 1632) ++++ sope-gdl1/Oracle8/OracleAdaptorChannelController.m (working copy) +@@ -31,6 +31,8 @@ + #import + #import + ++static BOOL debugOn = NO; ++ + // + // + // +@@ -48,6 +50,14 @@ + // + @implementation OracleAdaptorChannelController + +++ (void) initialize ++{ ++ NSUserDefaults *ud; ++ ++ ud = [NSUserDefaults standardUserDefaults]; ++ debugOn = [ud boolForKey: @"OracleAdaptorDebug"]; ++} ++ + - (EODelegateResponse) adaptorChannel: (id) theChannel + willInsertRow: (NSMutableDictionary *) theRow + forEntity: (EOEntity *) theEntity +@@ -56,7 +66,8 @@ + NSArray *keys; + int i, c; + +- NSLog(@"willInsertRow: %@ %@", [theRow description], [theEntity description]); ++ if (debugOn) ++ NSLog(@"willInsertRow: %@ %@", [theRow description], [theEntity description]); + + s = AUTORELEASE([[NSMutableString alloc] init]); + +@@ -101,7 +112,8 @@ + NSArray *keys; + int i, c; + +- NSLog(@"willUpdatetRow: %@ %@", [theRow description], [theQualifier description]); ++ if (debugOn) ++ NSLog(@"willUpdateRow: %@ %@", [theRow description], [theQualifier description]); + + s = AUTORELEASE([[NSMutableString alloc] init]); + Index: sope-core/NGExtensions/NGExtensions/NSString+Ext.h =================================================================== --- sope-core/NGExtensions/NGExtensions/NSString+Ext.h (revision 1632) @@ -3960,18 +4003,6 @@ Index: sope-appserver/mod_ngobjweb/config.c static char *_makeString(char *buf, char *str, int max) { if (buf == NULL) -Index: sope-appserver/mod_ngobjweb/NGBufferedDescriptor.c -=================================================================== ---- sope-appserver/mod_ngobjweb/NGBufferedDescriptor.c (revision 1632) -+++ sope-appserver/mod_ngobjweb/NGBufferedDescriptor.c (working copy) -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include "common.h" - #include "NGBufferedDescriptor.h" - - // returns the number of bytes which where read from the buffer Index: sope-appserver/mod_ngobjweb/GNUmakefile =================================================================== --- sope-appserver/mod_ngobjweb/GNUmakefile (revision 1632) @@ -3995,6 +4026,18 @@ Index: sope-appserver/mod_ngobjweb/GNUmakefile install-usr-libexec :: all $(INSTALL_PROGRAM) $(product) /usr/libexec/httpd/ +Index: sope-appserver/mod_ngobjweb/NGBufferedDescriptor.c +=================================================================== +--- sope-appserver/mod_ngobjweb/NGBufferedDescriptor.c (revision 1632) ++++ sope-appserver/mod_ngobjweb/NGBufferedDescriptor.c (working copy) +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include "common.h" + #include "NGBufferedDescriptor.h" + + // returns the number of bytes which where read from the buffer Index: sope-appserver/NGObjWeb/GNUmakefile.postamble =================================================================== --- sope-appserver/NGObjWeb/GNUmakefile.postamble (revision 1632) diff --git a/SoObjects/Mailer/SOGoMailAccount.m b/SoObjects/Mailer/SOGoMailAccount.m index a7731fbae..f994892eb 100644 --- a/SoObjects/Mailer/SOGoMailAccount.m +++ b/SoObjects/Mailer/SOGoMailAccount.m @@ -208,8 +208,11 @@ static NSString *fallbackIMAP4Server = nil; { NSMutableArray *folderPaths; NSArray *rawFolders, *mainFolders; + NSUserDefaults *ud; - rawFolders = [[self imap4Connection] allFoldersForURL: [self imap4URL]]; + ud = [[context activeUser] userDefaults]; + rawFolders = [[self imap4Connection] allFoldersForURL: [self imap4URL] + onlySubscribedFolders: [ud boolForKey: @"showSubscribedFoldersOnly"]]; mainFolders = [[NSArray arrayWithObjects: [self inboxFolderNameInContext: context], diff --git a/UI/PreferencesUI/UIxPreferences.m b/UI/PreferencesUI/UIxPreferences.m index 2be3d112f..d8522d0a4 100644 --- a/UI/PreferencesUI/UIxPreferences.m +++ b/UI/PreferencesUI/UIxPreferences.m @@ -447,6 +447,19 @@ static BOOL shouldDisplayAdditionalPreferences = NO; } /* Mailer */ +- (void) setShowSubscribedFoldersOnly: (BOOL) showSubscribedFoldersOnly +{ + if (showSubscribedFoldersOnly) + [userDefaults setBool: YES forKey: @"showSubscribedFoldersOnly"]; + else + [userDefaults removeObjectForKey: @"showSubscribedFoldersOnly"]; +} + +- (BOOL) showSubscribedFoldersOnly +{ + return [userDefaults boolForKey: @"showSubscribedFoldersOnly"]; +} + - (NSArray *) messageCheckList { return [NSArray arrayWithObjects: @"manually", @"every_minute", diff --git a/UI/Templates/PreferencesUI/UIxPreferences.wox b/UI/Templates/PreferencesUI/UIxPreferences.wox index b8f4d9ba4..914ab996b 100644 --- a/UI/Templates/PreferencesUI/UIxPreferences.wox +++ b/UI/Templates/PreferencesUI/UIxPreferences.wox @@ -95,6 +95,11 @@
+