From b53a8118e7e9aa785ecd46ed2f986ce358fb82c6 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Mon, 1 Sep 2008 13:21:27 +0000 Subject: [PATCH 01/17] Monotone-Parent: e273e1fc79bb27da2ab8838b78616c5fb161fd58 Monotone-Revision: 9fdb601e5aa4a2aafb9385ddc6c395ea29630d7c Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-01T13:21:27 Monotone-Branch: ca.inverse.sogo --- SOPE/sope-patchset-r1626.diff | 440 +++++++++++++++++++--------------- 1 file changed, 253 insertions(+), 187 deletions(-) diff --git a/SOPE/sope-patchset-r1626.diff b/SOPE/sope-patchset-r1626.diff index e04e72ce1..4df2cd334 100644 --- a/SOPE/sope-patchset-r1626.diff +++ b/SOPE/sope-patchset-r1626.diff @@ -1,190 +1,3 @@ -Index: sope-gdl1/PostgreSQL/PostgreSQL72Channel.m -=================================================================== ---- sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (révision 1626) -+++ sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (copie de travail) -@@ -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/Oracle8/OracleAdaptorChannel.m -=================================================================== ---- sope-gdl1/Oracle8/OracleAdaptorChannel.m (révision 1626) -+++ sope-gdl1/Oracle8/OracleAdaptorChannel.m (copie de travail) -@@ -30,6 +30,7 @@ - - #import - -+static BOOL debugOn = NO; - // - // - // -@@ -41,10 +42,19 @@ - - @implementation OracleAdaptorChannel (Private) - --- (void) _cleanup -++ (void) initialize - { -+ NSUserDefaults *ud; -+ -+ ud = [NSUserDefaults standardUserDefaults]; -+ debugOn = [ud boolForKey: @"OracleAdaptorDebug"]; -+} -+ -+- (void) _cleanup -+{ - column_info *info; - int c; -+ sword result; - - [_resultSetProperties removeAllObjects]; - -@@ -58,11 +68,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]; - } - -@@ -231,6 +259,9 @@ - - [self _cleanup]; - -+ if (debugOn) -+ [self logWithFormat: @"expression: %@", theExpression]; -+ - if (!theExpression || ![theExpression length]) - { - [NSException raise: @"OracleInvalidExpressionException" -@@ -302,7 +333,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]; - -@@ -609,7 +642,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 (révision 1626) -+++ sope-gdl1/Oracle8/OracleAdaptorChannelController.m (copie de travail) -@@ -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 (révision 1626) @@ -776,6 +589,46 @@ Index: sope-mime/NGImap4/ChangeLog 2007-08-24 Wolfgang Sourdeau * NGImap4Connection.m: some fix for folders ending with a slash (OGo +Index: sope-mime/NGImap4/NGImap4ConnectionManager.m +=================================================================== +--- sope-mime/NGImap4/NGImap4ConnectionManager.m (révision 1626) ++++ sope-mime/NGImap4/NGImap4ConnectionManager.m (copie de travail) +@@ -38,6 +38,9 @@ + debugCache = [ud boolForKey:@"NGImap4EnableIMAP4CacheDebug"]; + poolingOff = [ud boolForKey:@"NGImap4DisableIMAP4Pooling"]; + ++ if ([ud objectForKey:@"NGImap4PoolingCleanupInterval"]) ++ PoolScanInterval = [[ud objectForKey:@"NGImap4PoolingCleanupInterval"] doubleValue]; ++ + if (debugOn) NSLog(@"Note: NGImap4EnableIMAP4Debug is enabled!"); + if (poolingOff) NSLog(@"WARNING: IMAP4 connection pooling is disabled!"); + } +@@ -91,6 +94,25 @@ + + - (void)_garbageCollect:(NSTimer *)_timer { + // TODO: scan for old IMAP4 channels ++ NGImap4Connection *entry; ++ NSDate *now; ++ NSArray *a; ++ int i; ++ ++ a = [self->urlToEntry allKeys]; ++ now = [NSDate date]; ++ ++ for (i = 0; i < [a count]; i++) ++ { ++ entry = [self->urlToEntry objectForKey: [a objectAtIndex: i]]; ++ ++ if ([now timeIntervalSinceDate: [entry creationTime]] > PoolScanInterval) ++ { ++ [[entry client] logout]; ++ [self->urlToEntry removeObjectForKey: [a objectAtIndex: i]]; ++ } ++ } ++ + [self debugWithFormat:@"should collect IMAP4 channels (%d active)", + [self->urlToEntry count]]; + } Index: sope-mime/NGMail/NGSmtpClient.m =================================================================== --- sope-mime/NGMail/NGSmtpClient.m (révision 1626) @@ -1924,6 +1777,193 @@ Index: sope-mime/NGMime/NGMimeContentDispositionHeaderFieldGenerator.m } return data; } +Index: sope-gdl1/PostgreSQL/PostgreSQL72Channel.m +=================================================================== +--- sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (révision 1626) ++++ sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (copie de travail) +@@ -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/Oracle8/OracleAdaptorChannel.m +=================================================================== +--- sope-gdl1/Oracle8/OracleAdaptorChannel.m (révision 1626) ++++ sope-gdl1/Oracle8/OracleAdaptorChannel.m (copie de travail) +@@ -30,6 +30,7 @@ + + #import + ++static BOOL debugOn = NO; + // + // + // +@@ -41,10 +42,19 @@ + + @implementation OracleAdaptorChannel (Private) + +-- (void) _cleanup +++ (void) initialize + { ++ NSUserDefaults *ud; ++ ++ ud = [NSUserDefaults standardUserDefaults]; ++ debugOn = [ud boolForKey: @"OracleAdaptorDebug"]; ++} ++ ++- (void) _cleanup ++{ + column_info *info; + int c; ++ sword result; + + [_resultSetProperties removeAllObjects]; + +@@ -58,11 +68,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]; + } + +@@ -231,6 +259,9 @@ + + [self _cleanup]; + ++ if (debugOn) ++ [self logWithFormat: @"expression: %@", theExpression]; ++ + if (!theExpression || ![theExpression length]) + { + [NSException raise: @"OracleInvalidExpressionException" +@@ -302,7 +333,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]; + +@@ -609,7 +642,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 (révision 1626) ++++ sope-gdl1/Oracle8/OracleAdaptorChannelController.m (copie de travail) +@@ -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 (révision 1626) @@ -2363,6 +2403,19 @@ Index: sope-appserver/NGObjWeb/WOContext.m if ((serverURL = [rq headerForKey:@"x-webobjects-server-url"]) == nil) { if ((host = [rq headerForKey:@"host"])) serverURL = [@"http://" stringByAppendingString:host]; +Index: sope-appserver/NGObjWeb/ChangeLog +=================================================================== +--- sope-appserver/NGObjWeb/ChangeLog (révision 1626) ++++ sope-appserver/NGObjWeb/ChangeLog (copie de travail) +@@ -1,3 +1,8 @@ ++2008-09-01 Ludovic Marcotte ++ ++ * WORequest.m ([WORequest -browserLanguages]): we ensure ++ "language" never is an empty string, otherwise we ignore it. ++ + 2008-05-21 Sebastian Reitenbach + + * WOHTTPURLHandle.m: add 'query' component of URL to request path Index: sope-appserver/NGObjWeb/DAVPropMap.plist =================================================================== --- sope-appserver/NGObjWeb/DAVPropMap.plist (révision 1626) @@ -2842,6 +2895,19 @@ Index: sope-appserver/NGObjWeb/Defaults.plist PROPFIND, PROPPATCH, DELETE, +Index: sope-appserver/NGObjWeb/WORequest.m +=================================================================== +--- sope-appserver/NGObjWeb/WORequest.m (révision 1626) ++++ sope-appserver/NGObjWeb/WORequest.m (copie de travail) +@@ -597,6 +597,8 @@ + if (r.length > 0) + language = [language substringToIndex:r.location]; + language = [language stringByTrimmingSpaces]; ++ ++ if (![language length]) continue; + + /* check in map */ + if ((tmp = [self languageForBrowserLanguageCode:language])) Index: sope-appserver/NGObjWeb/NGHttp/NGHttpRequest.h =================================================================== --- sope-appserver/NGObjWeb/NGHttp/NGHttpRequest.h (révision 1626) From 3d986a1fdf5534c849edfbf3f98b323d9d443857 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Mon, 1 Sep 2008 13:38:36 +0000 Subject: [PATCH 02/17] Monotone-Parent: 9fdb601e5aa4a2aafb9385ddc6c395ea29630d7c Monotone-Revision: b06af30d92e12a7505221842044947bace0edc08 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-01T13:38:36 Monotone-Branch: ca.inverse.sogo --- SOPE/sope-patchset-r1626.diff | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SOPE/sope-patchset-r1626.diff b/SOPE/sope-patchset-r1626.diff index 4df2cd334..52134c39b 100644 --- a/SOPE/sope-patchset-r1626.diff +++ b/SOPE/sope-patchset-r1626.diff @@ -580,7 +580,11 @@ Index: sope-mime/NGImap4/ChangeLog =================================================================== --- sope-mime/NGImap4/ChangeLog (révision 1626) +++ sope-mime/NGImap4/ChangeLog (copie de travail) -@@ -1,3 +1,8 @@ +@@ -1,3 +1,12 @@ ++2008-09-01 Ludovic Marcotte ++ ++ * NGImap4ConnectionManager.m: implemented _garbageCollect. ++ +2008-08-28 Wolfgang Sourdeau + + * NGImap4Client.m ([NGImap -unselect]): new method to send From 3353a468cc950de80c666e9f26934a30aa6b36e4 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Mon, 1 Sep 2008 16:49:13 +0000 Subject: [PATCH 03/17] Monotone-Parent: b06af30d92e12a7505221842044947bace0edc08 Monotone-Revision: a822829663fdf41f5ab083e6fb2ca305b833454f Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-01T16:49:13 Monotone-Branch: ca.inverse.sogo --- SOPE/sope-patchset-r1626.diff | 432 +++++++++++++++++++--------------- 1 file changed, 236 insertions(+), 196 deletions(-) diff --git a/SOPE/sope-patchset-r1626.diff b/SOPE/sope-patchset-r1626.diff index 52134c39b..ef1c41a61 100644 --- a/SOPE/sope-patchset-r1626.diff +++ b/SOPE/sope-patchset-r1626.diff @@ -1,3 +1,190 @@ +Index: sope-gdl1/PostgreSQL/PostgreSQL72Channel.m +=================================================================== +--- sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (révision 1626) ++++ sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (copie de travail) +@@ -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/Oracle8/OracleAdaptorChannel.m +=================================================================== +--- sope-gdl1/Oracle8/OracleAdaptorChannel.m (révision 1626) ++++ sope-gdl1/Oracle8/OracleAdaptorChannel.m (copie de travail) +@@ -30,6 +30,7 @@ + + #import + ++static BOOL debugOn = NO; + // + // + // +@@ -41,10 +42,19 @@ + + @implementation OracleAdaptorChannel (Private) + +-- (void) _cleanup +++ (void) initialize + { ++ NSUserDefaults *ud; ++ ++ ud = [NSUserDefaults standardUserDefaults]; ++ debugOn = [ud boolForKey: @"OracleAdaptorDebug"]; ++} ++ ++- (void) _cleanup ++{ + column_info *info; + int c; ++ sword result; + + [_resultSetProperties removeAllObjects]; + +@@ -58,11 +68,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]; + } + +@@ -231,6 +259,9 @@ + + [self _cleanup]; + ++ if (debugOn) ++ [self logWithFormat: @"expression: %@", theExpression]; ++ + if (!theExpression || ![theExpression length]) + { + [NSException raise: @"OracleInvalidExpressionException" +@@ -302,7 +333,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]; + +@@ -609,7 +642,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 (révision 1626) ++++ sope-gdl1/Oracle8/OracleAdaptorChannelController.m (copie de travail) +@@ -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 (révision 1626) @@ -1169,7 +1356,7 @@ Index: sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m + length++; + abbreviation = [[NSString alloc] initWithBytes: *p + length: length - 1 -+ encoding: NSASCIIStringEncoding]; ++ encoding: NSISOLatin1StringEncoding]; + offsetTZ = [NSTimeZone timeZoneWithAbbreviation: abbreviation]; + [abbreviation release]; + *p += length; @@ -1396,8 +1583,8 @@ Index: sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m - buf[length] = '\0'; - + -+ length = [_data lengthOfBytesUsingEncoding: NSASCIIStringEncoding]; -+ bytes = [_data cStringUsingEncoding: NSASCIIStringEncoding]; ++ length = [_data lengthOfBytesUsingEncoding: NSISOLatin1StringEncoding]; ++ bytes = [_data cStringUsingEncoding: NSISOLatin1StringEncoding]; + /* remove leading chars (skip to first digit, the day of the month) */ while (length > 0 && (!isdigit(*bytes))) { @@ -1445,6 +1632,19 @@ Index: sope-mime/NGMime/NGMimeHeaderFieldGeneratorSet.m [rfc822Set setGenerator:gen forField:@"Disposition-Notification-To"]; } +Index: sope-mime/NGMime/NGMimeType.m +=================================================================== +--- sope-mime/NGMime/NGMimeType.m (révision 1626) ++++ sope-mime/NGMime/NGMimeType.m (copie de travail) +@@ -152,7 +152,7 @@ + } + else if ([charset isEqualToString:@"x-unknown"] || + [charset isEqualToString:@"unknown"]) { +- encoding = NSASCIIStringEncoding; ++ encoding = NSISOLatin1StringEncoding; + } + /* ISO Latin 9 */ + #if !(NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY) Index: sope-mime/NGMime/NGMimeBodyPart.m =================================================================== --- sope-mime/NGMime/NGMimeBodyPart.m (révision 1626) @@ -1499,6 +1699,30 @@ Index: sope-mime/NGMime/GNUmakefile.preamble NGMime_INCLUDE_DIRS += \ -I.. -I../.. \ -I../../sope-core/NGStreams/ \ +Index: sope-mime/NGMime/ChangeLog +=================================================================== +--- sope-mime/NGMime/ChangeLog (révision 1626) ++++ sope-mime/NGMime/ChangeLog (copie de travail) +@@ -1,3 +1,19 @@ ++2008-09-01 Wolfgang Sourdeau ++ ++ * NGMimeRFC822DateHeaderFieldParser.m ([NGMimeRFC ++ -parseValue:ofHeaderField:]): use an 8-bit safe encoding when ++ parsing dates. Since we only consider 7-bits characters, we ensure ++ that bad user-agents can be handled more properly. ++ ++ * NGMimeType.m ([NGMimeType +stringEncodingForCharset:]): ++ x-unknown encoding is now translated to an 8-bit safe encoding ++ (NSISOLatin1StringEncoding). ++ ++ * NGMimeAddressHeaderFieldGenerator.m ++ ([NGMimeAddressHeaderFieldGenerator ++ -generateDataForHeaderFieldNamed:value:]): encode resulting string ++ in an 8-bit safe encoding (NSISOLatin1StringEncoding). ++ + 2008-01-29 Albrecht Dress + + * fixes for OGo bug #789 (reply-to QP encoding) Index: sope-mime/NGMime/NGMimeBodyParser.m =================================================================== --- sope-mime/NGMime/NGMimeBodyParser.m (révision 1626) @@ -1631,20 +1855,23 @@ Index: sope-mime/NGMime/NGMimeAddressHeaderFieldGenerator.m - tmp = [NSString stringWithCString:(char *)des - length:(isoLen + desLen + isoEndLen)]; + tmp = [[NSString alloc] initWithData: [NSData dataWithBytes:(char *)des length:(isoLen + desLen + isoEndLen)] -+ encoding: NSASCIIStringEncoding]; ++ encoding: NSISOLatin1StringEncoding]; + [tmp autorelease]; } else { [self warnWithFormat: -@@ -193,7 +199,7 @@ - #if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY +@@ -190,11 +196,7 @@ + } + } + +-#if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY data = [result dataUsingEncoding:NSISOLatin1StringEncoding]; - #else +-#else - data = [result dataUsingEncoding:NSISOLatin9StringEncoding]; -+ data = [result dataUsingEncoding:NSASCIIStringEncoding]; - #endif +-#endif [result release]; + return data; Index: sope-mime/NGMime/NGMimeContentDispositionHeaderFieldGenerator.m =================================================================== --- sope-mime/NGMime/NGMimeContentDispositionHeaderFieldGenerator.m (révision 1626) @@ -1781,193 +2008,6 @@ Index: sope-mime/NGMime/NGMimeContentDispositionHeaderFieldGenerator.m } return data; } -Index: sope-gdl1/PostgreSQL/PostgreSQL72Channel.m -=================================================================== ---- sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (révision 1626) -+++ sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (copie de travail) -@@ -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/Oracle8/OracleAdaptorChannel.m -=================================================================== ---- sope-gdl1/Oracle8/OracleAdaptorChannel.m (révision 1626) -+++ sope-gdl1/Oracle8/OracleAdaptorChannel.m (copie de travail) -@@ -30,6 +30,7 @@ - - #import - -+static BOOL debugOn = NO; - // - // - // -@@ -41,10 +42,19 @@ - - @implementation OracleAdaptorChannel (Private) - --- (void) _cleanup -++ (void) initialize - { -+ NSUserDefaults *ud; -+ -+ ud = [NSUserDefaults standardUserDefaults]; -+ debugOn = [ud boolForKey: @"OracleAdaptorDebug"]; -+} -+ -+- (void) _cleanup -+{ - column_info *info; - int c; -+ sword result; - - [_resultSetProperties removeAllObjects]; - -@@ -58,11 +68,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]; - } - -@@ -231,6 +259,9 @@ - - [self _cleanup]; - -+ if (debugOn) -+ [self logWithFormat: @"expression: %@", theExpression]; -+ - if (!theExpression || ![theExpression length]) - { - [NSException raise: @"OracleInvalidExpressionException" -@@ -302,7 +333,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]; - -@@ -609,7 +642,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 (révision 1626) -+++ sope-gdl1/Oracle8/OracleAdaptorChannelController.m (copie de travail) -@@ -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 (révision 1626) From 95643f0e3a26dc36a5410038a5dfdf599030e873 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Mon, 1 Sep 2008 17:31:40 +0000 Subject: [PATCH 04/17] Monotone-Parent: a822829663fdf41f5ab083e6fb2ca305b833454f Monotone-Revision: fc73a7910531c479a442d9feae0af3acaaebaa52 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-01T17:31:40 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 11 +++++++++++ SoObjects/Mailer/SOGoMailAccount.m | 20 +++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 2fa3c237f..afbaff01e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2008-09-01 Wolfgang Sourdeau + + * SoObjects/Mailer/SOGoMailAccount.m ([SOGoMailAccount + +initialize]): use the user default "SOGoFallbackIMAP4Server" to + override the value of "serverName" from the actual user settings. + Fallback to "localhost" if value is unset. + + * SoObjects/Mailer/SOGoMailAccount.m ([SOGoMailAccount + -imap4URLString]): use the value of SOGoFallbackIMAP4Server, as + mentionne above. + 2008-08-29 Wolfgang Sourdeau * UI/MailerUI/UIxMailView.m ([UIxMailView diff --git a/SoObjects/Mailer/SOGoMailAccount.m b/SoObjects/Mailer/SOGoMailAccount.m index 976f3f98d..6d6274c05 100644 --- a/SoObjects/Mailer/SOGoMailAccount.m +++ b/SoObjects/Mailer/SOGoMailAccount.m @@ -57,6 +57,9 @@ static NSString *trashFolderName = nil; static NSString *sharedFolderName = @""; // TODO: add English default static NSString *otherUsersFolderName = @""; // TODO: add English default +// this is temporary, until we allow users to manage their own accounts +static NSString *fallbackIMAP4Server = nil; + + (void) initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; @@ -95,7 +98,16 @@ static NSString *otherUsersFolderName = @""; // TODO: add English default else rootFolderNames = [[NSArray alloc] initWithObjects: draftsFolderName, - nil]; + nil]; + + if (!fallbackIMAP4Server) + { + fallbackIMAP4Server = [ud stringForKey: @"SOGoFallbackIMAP4Server"]; + if (fallbackIMAP4Server) + [fallbackIMAP4Server retain]; + else + fallbackIMAP4Server = @"localhost"; + } } - (id) init @@ -258,8 +270,14 @@ static NSString *otherUsersFolderName = @""; // TODO: add English default escUsername = [[username stringByEscapingURL] stringByReplacingString: @"@" withString: @"%40"]; +#if 0 + // see comment about fallbackIMAP4Server above hostString = [NSString stringWithFormat: @"%@@%@", escUsername, [mailAccount objectForKey: @"serverName"]]; +#else + hostString = [NSString stringWithFormat: @"%@@%@", escUsername, + fallbackIMAP4Server]; +#endif } else hostString = @"localhost"; From 95ec0e4a19876f304ba115379474e2b8d153ffdf Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Tue, 2 Sep 2008 02:48:18 +0000 Subject: [PATCH 05/17] Monotone-Parent: fc73a7910531c479a442d9feae0af3acaaebaa52 Monotone-Revision: a74b906d58327f02724a366df126c83b4bdcc4c9 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-02T02:48:18 Monotone-Branch: ca.inverse.sogo --- SoObjects/SOGo/LDAPUserManager.m | 52 +++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/SoObjects/SOGo/LDAPUserManager.m b/SoObjects/SOGo/LDAPUserManager.m index 80ea9a1b2..3250e79a2 100644 --- a/SoObjects/SOGo/LDAPUserManager.m +++ b/SoObjects/SOGo/LDAPUserManager.m @@ -87,7 +87,8 @@ static BOOL forceImapLoginWithEmail = NO; if (sourceID) [sources setObject: ldapSource forKey: sourceID]; else - NSLog(@"LDAPUserManager.m: WARNING: id field missing in a LDAP source, check the SOGoLDAPSources default"); + [self errorWithFormat: @"id field missing in a LDAP source," + @" check the SOGoLDAPSources defaults"]; metadata = [NSMutableDictionary dictionary]; value = [udSource objectForKey: @"canAuthenticate"]; if (value) @@ -121,6 +122,7 @@ static BOOL forceImapLoginWithEmail = NO; - (id) init { NSUserDefaults *ud; + NSString *cleanupSetting; if ((self = [super init])) { @@ -129,14 +131,24 @@ static BOOL forceImapLoginWithEmail = NO; sources = nil; sourcesMetadata = nil; users = [NSMutableDictionary new]; - cleanupInterval - = [ud integerForKey: @"SOGoLDAPUserManagerCleanupInterval"]; - if (cleanupInterval) - cleanupTimer = [NSTimer scheduledTimerWithTimeInterval: cleanupInterval - target: self - selector: @selector(cleanupSources) - userInfo: nil - repeats: YES]; + cleanupSetting + = [ud objectForKey: @"SOGoLDAPUserManagerCleanupInterval"]; + if (cleanupSetting) + cleanupInterval = [cleanupSetting doubleValue]; + else + cleanupInterval = 0.0; + if (cleanupInterval > 0.0) + { + cleanupTimer = [NSTimer scheduledTimerWithTimeInterval: cleanupInterval + target: self + selector: @selector (_cleanupSources) + userInfo: nil + repeats: YES]; + [self logWithFormat: @"cleanup interval set every %f seconds", + cleanupInterval]; + } + else + [self logWithFormat: @"no cleanup interval set: memory usage will grow"]; [self _prepareLDAPSourcesWithDefaults: ud]; } @@ -384,12 +396,8 @@ static BOOL forceImapLoginWithEmail = NO; if (key) [users setObject: newUser forKey: key]; emails = [[newUser objectForKey: @"emails"] objectEnumerator]; - key = [emails nextObject]; - while (key) - { - [users setObject: newUser forKey: key]; - key = [emails nextObject]; - } + while ((key = [emails nextObject])) + [users setObject: newUser forKey: key]; } - (NSDictionary *) contactInfosForUserWithUIDorEmail: (NSString *) uid @@ -532,22 +540,32 @@ static BOOL forceImapLoginWithEmail = NO; matching: filter]; } -- (void) cleanupSources +- (void) _cleanupSources { NSEnumerator *userIDs; NSString *currentID; NSDictionary *currentUser; NSDate *now; + unsigned int count; now = [NSDate date]; + + count = 0; + userIDs = [[users allKeys] objectEnumerator]; while ((currentID = [userIDs nextObject])) { currentUser = [users objectForKey: currentID]; if ([now earlierDate: [currentUser objectForKey: @"cleanupDate"]] == now) - [users removeObjectForKey: currentID]; + { + [users removeObjectForKey: currentID]; + count++; + } } + + if (count) + [self logWithFormat: @"cleaned %d users records from cache", count]; } @end From c7e40104a9beaeb770615e1d8c235cc9c92973a0 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Tue, 2 Sep 2008 02:52:55 +0000 Subject: [PATCH 06/17] Monotone-Parent: a74b906d58327f02724a366df126c83b4bdcc4c9 Monotone-Revision: efd9ade13655768d4cae7605de1142d71a2b3e0c Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-02T02:52:55 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 12 ++++-------- SoObjects/SOGo/SOGoUser.m | 37 ++++++++++++++++--------------------- 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/ChangeLog b/ChangeLog index afbaff01e..79e2151a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,13 +1,9 @@ 2008-09-01 Wolfgang Sourdeau - * SoObjects/Mailer/SOGoMailAccount.m ([SOGoMailAccount - +initialize]): use the user default "SOGoFallbackIMAP4Server" to - override the value of "serverName" from the actual user settings. - Fallback to "localhost" if value is unset. - - * SoObjects/Mailer/SOGoMailAccount.m ([SOGoMailAccount - -imap4URLString]): use the value of SOGoFallbackIMAP4Server, as - mentionne above. + * SoObjects/SOGo/SOGoUser.m ([SOGoUser + -initWithLogin:newLoginroles:newRoles]): moved the core from init + here. + ([-init]): removed method. 2008-08-29 Wolfgang Sourdeau diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index 3a5d7dfb3..de657f149 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -201,7 +201,7 @@ _timeValue (NSString *key) if (user) { [user autorelease]; - [cache registerUser: user]; + [cache registerUser: user]; } } [user setPrimaryRoles: newRoles]; @@ -209,25 +209,6 @@ _timeValue (NSString *key) return user; } -- (id) init -{ - if ((self = [super init])) - { - userDefaults = nil; - userSettings = nil; - allEmails = nil; - language = nil; - currentPassword = nil; - dateFormatter = nil; - homeFolder = nil; - cn = nil; - userTimeZone = nil; - mailAccounts = nil; - } - - return self; -} - - (id) initWithLogin: (NSString *) newLogin roles: (NSArray *) newRoles { @@ -247,7 +228,21 @@ _timeValue (NSString *key) } if ([realUID length]) - self = [super initWithLogin: realUID roles: newRoles]; + { + if ((self = [super initWithLogin: realUID roles: newRoles])) + { + userDefaults = nil; + userSettings = nil; + allEmails = nil; + language = nil; + currentPassword = nil; + dateFormatter = nil; + homeFolder = nil; + cn = nil; + userTimeZone = nil; + mailAccounts = nil; + } + } else { [self release]; From 5b5a642ef6e09bc4b97608c246f3cdf52147b8e4 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Tue, 2 Sep 2008 02:53:08 +0000 Subject: [PATCH 07/17] Monotone-Parent: efd9ade13655768d4cae7605de1142d71a2b3e0c Monotone-Revision: 5391b9be06e00255b931f3a5c6535e3527ebd405 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-02T02:53:08 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 4 ++++ SoObjects/SOGo/SOGoObject.m | 4 +--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 79e2151a9..ba30454ba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2008-09-01 Wolfgang Sourdeau + * SoObjects/SOGo/SOGoObject.m ([SOGoObject + -initWithName:_nameinContainer:_container]): we no longer retain + the context, to avoid making a circular reference. + * SoObjects/SOGo/SOGoUser.m ([SOGoUser -initWithLogin:newLoginroles:newRoles]): moved the core from init here. diff --git a/SoObjects/SOGo/SOGoObject.m b/SoObjects/SOGo/SOGoObject.m index 2e8e526fe..580efdc11 100644 --- a/SoObjects/SOGo/SOGoObject.m +++ b/SoObjects/SOGo/SOGoObject.m @@ -270,7 +270,6 @@ SEL SOGoSelectorForPropertySetter (NSString *property) if ((self = [self init])) { context = [[WOApplication application] context]; - [context retain]; nameInContainer = [_name copy]; container = _container; if ([self doesRetainContainer]) @@ -285,7 +284,6 @@ SEL SOGoSelectorForPropertySetter (NSString *property) - (void) dealloc { - [context release]; [owner release]; if ([self doesRetainContainer]) [container release]; @@ -402,7 +400,7 @@ SEL SOGoSelectorForPropertySetter (NSString *property) { obj = [[self soClass] lookupKey: lookupName inContext: localContext]; if (obj) - [obj bindToObject: self inContext: localContext]; + obj = [obj bindToObject: self inContext: localContext]; } if (obj) From 6300e629377797722e808a258404f4c47fccdc0a Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Tue, 2 Sep 2008 02:53:34 +0000 Subject: [PATCH 08/17] Monotone-Parent: 5391b9be06e00255b931f3a5c6535e3527ebd405 Monotone-Revision: 2d2d47c8c2a7874ff16e8677d2bb7c3607c56d5c Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-02T02:53:34 Monotone-Branch: ca.inverse.sogo --- UI/SOGoUI/UIxComponent.m | 1 + 1 file changed, 1 insertion(+) diff --git a/UI/SOGoUI/UIxComponent.m b/UI/SOGoUI/UIxComponent.m index 0417b4f0e..105209673 100644 --- a/UI/SOGoUI/UIxComponent.m +++ b/UI/SOGoUI/UIxComponent.m @@ -130,6 +130,7 @@ static BOOL uixDebugEnabled = NO; if ((self = [super init])) { _selectedDate = nil; + queryParameters = nil; } return self; From ad5221ed0e5217fa7d9e79a15cbdd1daf8241bd0 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Tue, 2 Sep 2008 02:57:01 +0000 Subject: [PATCH 09/17] Monotone-Parent: 2d2d47c8c2a7874ff16e8677d2bb7c3607c56d5c Monotone-Revision: 7b5f08442cc8a464b29abb66c14ba679da84d277 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-02T02:57:01 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 3 +++ UI/MailerUI/UIxMailView.m | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index ba30454ba..50baf93d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2008-09-01 Wolfgang Sourdeau + * UI/MailerUI/UIxMailEditor.m ([UIxMailEditor -from]): retain the + initialized value of from, otherwise we create a future zombie. + * SoObjects/SOGo/SOGoObject.m ([SOGoObject -initWithName:_nameinContainer:_container]): we no longer retain the context, to avoid making a circular reference. diff --git a/UI/MailerUI/UIxMailView.m b/UI/MailerUI/UIxMailView.m index eaf7bb234..ae248ce1f 100644 --- a/UI/MailerUI/UIxMailView.m +++ b/UI/MailerUI/UIxMailView.m @@ -211,7 +211,6 @@ static NSString *mailETag = nil; inContext: (WOContext *) _ctx { UIxMailRenderingContext *mctx; - NGImap4Connection *conn; if (mailETag != nil) [[_ctx response] setHeader:mailETag forKey:@"etag"]; @@ -225,9 +224,6 @@ static NSString *mailETag = nil; [super appendToResponse: _response inContext: _ctx]; [[_ctx popMailRenderingContext] reset]; - - conn = [[self clientObject] imap4Connection]; - [[conn client] logout]; } @end /* UIxMailView */ From 2a6198780392e14a3151ec86fc24eec13874330b Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Tue, 2 Sep 2008 02:57:12 +0000 Subject: [PATCH 10/17] Monotone-Parent: 7b5f08442cc8a464b29abb66c14ba679da84d277 Monotone-Revision: 504efed918c1affc532bdcc00196349809e53460 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-02T02:57:12 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 26 ++++++++++++++++++++++++++ SoObjects/Mailer/SOGoMailBaseObject.m | 3 ++- SoObjects/Mailer/SOGoMailFolder.h | 1 - SoObjects/Mailer/SOGoMailFolder.m | 10 ---------- UI/MailerUI/UIxMailActions.m | 2 -- UI/MailerUI/UIxMailEditor.m | 1 + 6 files changed, 29 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 50baf93d2..8a101a8ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,31 @@ 2008-09-01 Wolfgang Sourdeau + * UI/MailerUI/UIxMailView.m ([UIxMailView + -appendToResponse:_responseinContext:_ctx]): no longer invoke + [NGImap4Client logout], since this is now handled by the + NGImap4Connection manager (or not). + + * UI/MailerUI/UIxMailActions.m ([UIxMailActions + -markMessageUnreadAction]): no longer make use of [SOGoMailFolder + unselect]. + ([UIxMailActions -markMessageReadAction]): idem. + + * SoObjects/Mailer/SOGoMailFolder.m ([-unselect]): removed method + since we no longer need it. + + * SoObjects/Mailer/SOGoMailBaseObject.m ([SOGoMailBaseObject + -dealloc]): release "imap4". If the IMAP4 connection pooling is + disabled, the object will otherwise never be released. + + * SoObjects/Mailer/SOGoMailAccount.m ([SOGoMailAccount + +initialize]): use the user default "SOGoFallbackIMAP4Server" to + override the value of "serverName" from the actual user settings. + Fallback to "localhost" if value is unset. + + * SoObjects/Mailer/SOGoMailAccount.m ([SOGoMailAccount + -imap4URLString]): use the value of SOGoFallbackIMAP4Server, as + mentionne above. + * UI/MailerUI/UIxMailEditor.m ([UIxMailEditor -from]): retain the initialized value of from, otherwise we create a future zombie. diff --git a/SoObjects/Mailer/SOGoMailBaseObject.m b/SoObjects/Mailer/SOGoMailBaseObject.m index 7c5ec4e78..909b67640 100644 --- a/SoObjects/Mailer/SOGoMailBaseObject.m +++ b/SoObjects/Mailer/SOGoMailBaseObject.m @@ -57,6 +57,7 @@ static BOOL debugOn = YES; - (void) dealloc { [imap4URL release]; + [imap4 release]; [super dealloc]; } @@ -121,7 +122,7 @@ static BOOL debugOn = YES; imap4 = [[self mailManager] connectionForURL: [self imap4URL] password: [self imap4Password]]; if (imap4) - [imap4 retain]; + [imap4 retain]; else [self errorWithFormat:@"Could not connect IMAP4."]; } diff --git a/SoObjects/Mailer/SOGoMailFolder.h b/SoObjects/Mailer/SOGoMailFolder.h index a269f8b44..49e1fe654 100644 --- a/SoObjects/Mailer/SOGoMailFolder.h +++ b/SoObjects/Mailer/SOGoMailFolder.h @@ -64,7 +64,6 @@ typedef enum { - (void) expungeLastMarkedFolder; - (NSException *) expunge; -- (NSException *) unselect; /* flags */ diff --git a/SoObjects/Mailer/SOGoMailFolder.m b/SoObjects/Mailer/SOGoMailFolder.m index fb3f4133f..43886de3e 100644 --- a/SoObjects/Mailer/SOGoMailFolder.m +++ b/SoObjects/Mailer/SOGoMailFolder.m @@ -283,16 +283,6 @@ static BOOL aclConformsToIMAPExt = NO; return [[self imap4Connection] expungeAtURL: [self imap4URL]]; } -- (NSException *) unselect -{ - NGImap4Client *client; - - client = [[self imap4Connection] client]; - [client unselect]; - - return nil; -} - - (void) markForExpunge { NSUserDefaults *ud; diff --git a/UI/MailerUI/UIxMailActions.m b/UI/MailerUI/UIxMailActions.m index d24b68a0b..c421815e9 100644 --- a/UI/MailerUI/UIxMailActions.m +++ b/UI/MailerUI/UIxMailActions.m @@ -151,7 +151,6 @@ if (!response) { mailFolder = [[self clientObject] container]; - [mailFolder unselect]; response = [self responseWith204]; } @@ -167,7 +166,6 @@ if (!response) { mailFolder = [[self clientObject] container]; - [mailFolder unselect]; response = [self responseWith204]; } diff --git a/UI/MailerUI/UIxMailEditor.m b/UI/MailerUI/UIxMailEditor.m index 01b740043..dc9f2dedd 100644 --- a/UI/MailerUI/UIxMailEditor.m +++ b/UI/MailerUI/UIxMailEditor.m @@ -135,6 +135,7 @@ static NSArray *infoKeys = nil; { identity = [[context activeUser] primaryIdentity]; from = [identity keysWithFormat: @"%{fullName} <%{email}>"]; + [from retain]; } return from; From 8c92eb542c1446b459e13226e090c5529eca275c Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Tue, 2 Sep 2008 03:00:05 +0000 Subject: [PATCH 11/17] Monotone-Parent: 504efed918c1affc532bdcc00196349809e53460 Monotone-Revision: 21a302eed46e49a91844145380dabdd1cd40ed4b Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-02T03:00:05 Monotone-Branch: ca.inverse.sogo --- SOPE/sope-patchset-r1626.diff | 218 ++++++++++++++++++++++++++++++++-- 1 file changed, 207 insertions(+), 11 deletions(-) diff --git a/SOPE/sope-patchset-r1626.diff b/SOPE/sope-patchset-r1626.diff index ef1c41a61..d2845989f 100644 --- a/SOPE/sope-patchset-r1626.diff +++ b/SOPE/sope-patchset-r1626.diff @@ -189,7 +189,16 @@ Index: sope-mime/NGImap4/NGImap4Client.h =================================================================== --- sope-mime/NGImap4/NGImap4Client.h (révision 1626) +++ sope-mime/NGImap4/NGImap4Client.h (copie de travail) -@@ -120,6 +120,7 @@ +@@ -62,6 +62,8 @@ + NGImap4ResponseNormalizer *normer; + NSMutableArray *responseReceiver; + ++ BOOL loggedIn; ++ + BOOL isLogin; + unsigned tagId; + +@@ -120,6 +122,7 @@ - (NSDictionary *)list:(NSString *)_folder pattern:(NSString *)_pattern; - (NSDictionary *)lsub:(NSString *)_folder pattern:(NSString *)_pattern; - (NSDictionary *)select:(NSString *)_folder; @@ -197,7 +206,7 @@ Index: sope-mime/NGImap4/NGImap4Client.h - (NSDictionary *)status:(NSString *)_folder flags:(NSArray *)_flags; - (NSDictionary *)rename:(NSString *)_folder to:(NSString *)_newName; - (NSDictionary *)delete:(NSString *)_folder; -@@ -138,7 +139,7 @@ +@@ -138,7 +141,7 @@ flags:(NSArray *)_flags; - (NSDictionary *)storeFrom:(unsigned)_from to:(unsigned)_to add:(NSNumber *)_add flags:(NSArray *)_flags; @@ -255,15 +264,63 @@ Index: sope-mime/NGImap4/NGImap4Client.m @end /* -@@ -508,6 +512,7 @@ +@@ -195,11 +199,14 @@ + self->debug = ImapDebugEnabled; + self->responseReceiver = [[NSMutableArray alloc] initWithCapacity:128]; + self->normer = [[NGImap4ResponseNormalizer alloc] initWithClient:self]; ++ self->loggedIn = NO; ++ self->context = nil; + } + return self; + } + + - (void)dealloc { ++ if (self->loggedIn) [self logout]; + [self removeFromConnectionRegister]; + [self->normer release]; + [self->text release]; +@@ -457,8 +464,8 @@ + - (void)reconnect { + if ([self->context lastException] != nil) + return; +- +- [self closeConnection]; ++ ++ [self closeConnection]; + self->tagId = 0; + [self openConnection]; + +@@ -481,6 +488,7 @@ + */ + NGHashMap *map; + NSString *s, *log; ++ NSDictionary *response; + + if (self->isLogin ) + return nil; +@@ -499,7 +507,11 @@ + + self->isLogin = NO; + +- return [self->normer normalizeResponse:map]; ++ response = [self->normer normalizeResponse:map]; ++ ++ self->loggedIn = [[response valueForKey:@"result"] boolValue]; ++ ++ return response; + } + + - (NSDictionary *)logout { +@@ -508,6 +520,8 @@ map = [self processCommand:@"logout"]; [self closeConnection]; + [self->selectedFolder release]; self->selectedFolder = nil; ++ self->loggedIn = NO; return [self->normer normalizeResponse:map]; } -@@ -635,6 +640,10 @@ +@@ -635,6 +649,10 @@ return [self->normer normalizeSelectResponse:[self processCommand:s]]; } @@ -274,7 +331,7 @@ Index: sope-mime/NGImap4/NGImap4Client.m - (NSDictionary *)status:(NSString *)_folder flags:(NSArray *)_flags { NSString *cmd; -@@ -820,23 +829,23 @@ +@@ -820,23 +838,23 @@ return [self->normer normalizeResponse:[self processCommand:cmd]]; } @@ -304,7 +361,7 @@ Index: sope-mime/NGImap4/NGImap4Client.m seqstr, _flag ? '+' : '-', flagstr]; return [self->normer normalizeResponse:[self processCommand:cmd]]; -@@ -967,11 +976,12 @@ +@@ -967,11 +985,12 @@ descr = @"Could not process qualifier for imap search "; descr = [descr stringByAppendingString:reason]; @@ -320,7 +377,7 @@ Index: sope-mime/NGImap4/NGImap4Client.m } - (NSString *)_searchExprForQual:(EOQualifier *)_qualifier { -@@ -1093,7 +1103,18 @@ +@@ -1093,7 +1112,18 @@ Eg: UID SORT ( DATE REVERSE SUBJECT ) UTF-8 TODO */ NSString *tmp; @@ -339,7 +396,7 @@ Index: sope-mime/NGImap4/NGImap4Client.m if ([_sortSpec isKindOfClass:[NSArray class]]) tmp = [self _generateIMAP4SortOrderings:_sortSpec]; else if ([_sortSpec isKindOfClass:[EOSortOrdering class]]) -@@ -1107,9 +1128,10 @@ +@@ -1107,9 +1137,10 @@ tmp = @"DATE"; } @@ -352,7 +409,7 @@ Index: sope-mime/NGImap4/NGImap4Client.m } - (NSDictionary *)sort:(NSArray *)_sortOrderings qualifier:(EOQualifier *)_qual -@@ -1130,7 +1152,7 @@ +@@ -1130,7 +1161,7 @@ return nil; } @@ -361,7 +418,7 @@ Index: sope-mime/NGImap4/NGImap4Client.m return [self->normer normalizeSearchResponse:[self processCommand:s]]; } -@@ -1193,6 +1215,79 @@ +@@ -1193,6 +1224,79 @@ /* Private Methods */ @@ -463,6 +520,23 @@ Index: sope-mime/NGImap4/NGImap4Connection.m if (![[result valueForKey:@"result"] boolValue]) { return [self errorForResult:result text:@"Failed to change flags of IMAP4 message"]; +@@ -911,4 +911,16 @@ + return ms; + } + ++- (id) retain ++{ ++ NSLog (@"connection (%Lx) retained: %d", self, [self retainCount] + 1); ++ return [super retain]; ++} ++ ++- (void) release ++{ ++ NSLog (@"connection (%Lx) released: %d", self, [self retainCount] - 1); ++ [super release]; ++} ++ + @end /* NGImap4Connection */ Index: sope-mime/NGImap4/NGImap4ResponseNormalizer.m =================================================================== --- sope-mime/NGImap4/NGImap4ResponseNormalizer.m (révision 1626) @@ -794,7 +868,31 @@ Index: sope-mime/NGImap4/NGImap4ConnectionManager.m if (debugOn) NSLog(@"Note: NGImap4EnableIMAP4Debug is enabled!"); if (poolingOff) NSLog(@"WARNING: IMAP4 connection pooling is disabled!"); } -@@ -91,6 +94,25 @@ +@@ -53,18 +56,17 @@ + if ((self = [super init])) { + if (!poolingOff) { + self->urlToEntry = [[NSMutableDictionary alloc] initWithCapacity:256]; ++ self->gcTimer = [[NSTimer scheduledTimerWithTimeInterval: ++ PoolScanInterval ++ target:self selector:@selector(_garbageCollect:) ++ userInfo:nil repeats:YES] retain]; + } +- +- self->gcTimer = [[NSTimer scheduledTimerWithTimeInterval: +- PoolScanInterval +- target:self selector:@selector(_garbageCollect:) +- userInfo:nil repeats:YES] retain]; + } + return self; + } + + - (void)dealloc { +- if (self->gcTimer) [self->gcTimer invalidate]; ++ [self->gcTimer invalidate]; + [self->urlToEntry release]; + [self->gcTimer release]; + [super dealloc]; +@@ -91,6 +93,25 @@ - (void)_garbageCollect:(NSTimer *)_timer { // TODO: scan for old IMAP4 channels @@ -820,6 +918,69 @@ Index: sope-mime/NGImap4/NGImap4ConnectionManager.m [self debugWithFormat:@"should collect IMAP4 channels (%d active)", [self->urlToEntry count]]; } +@@ -105,34 +126,42 @@ + NGImap4Connection *entry; + NGImap4Client *client; + ++ if (poolingOff) { ++ client = [self imap4ClientForURL:_url password:_p]; ++ entry = [[NGImap4Connection alloc] initWithClient:client ++ password:_p]; ++ return [entry autorelease]; ++ } ++ else { + /* check cache */ + +- if ((entry = [self entryForURL:_url]) != nil) { +- if ([entry isValidPassword:_p]) { ++ if ((entry = [self entryForURL:_url]) != nil) { ++ if ([entry isValidPassword:_p]) { ++ if (debugCache) ++ [self logWithFormat:@"valid password, reusing cache entry ..."]; ++ return entry; ++ } ++ ++ /* different password, password could have changed! */ + if (debugCache) +- [self logWithFormat:@"valid password, reusing cache entry ..."]; +- return entry; ++ [self logWithFormat:@"different password than cached entry: %@", _url]; ++ entry = nil; + } +- +- /* different password, password could have changed! */ +- if (debugCache) +- [self logWithFormat:@"different password than cached entry: %@", _url]; +- entry = nil; +- } +- else +- [self debugWithFormat:@"no connection cached yet for url: %@", _url]; ++ else ++ [self debugWithFormat:@"no connection cached yet for url: %@", _url]; + +- /* try to login */ ++ /* try to login */ + +- client = [entry isValidPassword:_p] +- ? [entry client] +- : [self imap4ClientForURL:_url password:_p]; ++ client = [entry isValidPassword:_p] ++ ? [entry client] ++ : [self imap4ClientForURL:_url password:_p]; ++ ++ if (client == nil) ++ return nil; + +- if (client == nil) +- return nil; +- + /* sideeffect of -imap4ClientForURL:password: is to create a cache entry */ +- return [self entryForURL:_url]; ++ return [self entryForURL:_url]; ++ } + } + + /* client object */ Index: sope-mime/NGMail/NGSmtpClient.m =================================================================== --- sope-mime/NGMail/NGSmtpClient.m (révision 1626) @@ -2664,6 +2825,41 @@ Index: sope-appserver/NGObjWeb/WebDAV/SoObject+SoDAV.h - (NSException *)davMoveToTargetObject:(id)_target newName:(NSString *)_name inContext:(id)_ctx; +Index: sope-appserver/NGObjWeb/WODirectAction.m +=================================================================== +--- sope-appserver/NGObjWeb/WODirectAction.m (révision 1626) ++++ sope-appserver/NGObjWeb/WODirectAction.m (copie de travail) +@@ -46,7 +46,7 @@ + } + - (id)initWithContext:(WOContext *)_ctx { + if ((self = [self initWithRequest:[_ctx request]])) { +- self->context = [_ctx retain]; ++ self->context = _ctx; + } + return self; + } +@@ -54,16 +54,16 @@ + return [self initWithRequest:nil]; + } + +-- (void)dealloc { +- [self->context release]; +- [super dealloc]; +-} ++// - (void)dealloc { ++// [self->context release]; ++// [super dealloc]; ++// } + + /* accessors */ + + - (WOContext *)context { + if (self->context == nil) +- self->context = [[[WOApplication application] context] retain]; ++ self->context = [[WOApplication application] context]; + return self->context; + } + Index: sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m =================================================================== --- sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m (révision 1626) From 5f355f57770540d29992c7f3cdca90d72f534bb2 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Tue, 2 Sep 2008 03:01:54 +0000 Subject: [PATCH 12/17] Monotone-Parent: 21a302eed46e49a91844145380dabdd1cd40ed4b Monotone-Revision: dcceb57e8e6ee4fbdfba1d9ff1f44cb1c59b56f5 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-02T03:01:54 Monotone-Branch: ca.inverse.sogo --- SOPE/sope-patchset-r1626.diff | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/SOPE/sope-patchset-r1626.diff b/SOPE/sope-patchset-r1626.diff index d2845989f..cf84f7457 100644 --- a/SOPE/sope-patchset-r1626.diff +++ b/SOPE/sope-patchset-r1626.diff @@ -320,18 +320,19 @@ Index: sope-mime/NGImap4/NGImap4Client.m return [self->normer normalizeResponse:map]; } -@@ -635,6 +649,10 @@ +@@ -635,6 +649,11 @@ return [self->normer normalizeSelectResponse:[self processCommand:s]]; } +- (NSDictionary *)unselect { ++ [self->selectedFolder release]; self->selectedFolder = nil; + return [self->normer normalizeResponse:[self processCommand:@"unselect"]]; +} + - (NSDictionary *)status:(NSString *)_folder flags:(NSArray *)_flags { NSString *cmd; -@@ -820,23 +838,23 @@ +@@ -820,23 +839,23 @@ return [self->normer normalizeResponse:[self processCommand:cmd]]; } @@ -361,7 +362,7 @@ Index: sope-mime/NGImap4/NGImap4Client.m seqstr, _flag ? '+' : '-', flagstr]; return [self->normer normalizeResponse:[self processCommand:cmd]]; -@@ -967,11 +985,12 @@ +@@ -967,11 +986,12 @@ descr = @"Could not process qualifier for imap search "; descr = [descr stringByAppendingString:reason]; @@ -377,7 +378,7 @@ Index: sope-mime/NGImap4/NGImap4Client.m } - (NSString *)_searchExprForQual:(EOQualifier *)_qualifier { -@@ -1093,7 +1112,18 @@ +@@ -1093,7 +1113,18 @@ Eg: UID SORT ( DATE REVERSE SUBJECT ) UTF-8 TODO */ NSString *tmp; @@ -396,7 +397,7 @@ Index: sope-mime/NGImap4/NGImap4Client.m if ([_sortSpec isKindOfClass:[NSArray class]]) tmp = [self _generateIMAP4SortOrderings:_sortSpec]; else if ([_sortSpec isKindOfClass:[EOSortOrdering class]]) -@@ -1107,9 +1137,10 @@ +@@ -1107,9 +1138,10 @@ tmp = @"DATE"; } @@ -409,7 +410,7 @@ Index: sope-mime/NGImap4/NGImap4Client.m } - (NSDictionary *)sort:(NSArray *)_sortOrderings qualifier:(EOQualifier *)_qual -@@ -1130,7 +1161,7 @@ +@@ -1130,7 +1162,7 @@ return nil; } @@ -418,7 +419,7 @@ Index: sope-mime/NGImap4/NGImap4Client.m return [self->normer normalizeSearchResponse:[self processCommand:s]]; } -@@ -1193,6 +1224,79 @@ +@@ -1193,6 +1225,79 @@ /* Private Methods */ @@ -520,23 +521,6 @@ Index: sope-mime/NGImap4/NGImap4Connection.m if (![[result valueForKey:@"result"] boolValue]) { return [self errorForResult:result text:@"Failed to change flags of IMAP4 message"]; -@@ -911,4 +911,16 @@ - return ms; - } - -+- (id) retain -+{ -+ NSLog (@"connection (%Lx) retained: %d", self, [self retainCount] + 1); -+ return [super retain]; -+} -+ -+- (void) release -+{ -+ NSLog (@"connection (%Lx) released: %d", self, [self retainCount] - 1); -+ [super release]; -+} -+ - @end /* NGImap4Connection */ Index: sope-mime/NGImap4/NGImap4ResponseNormalizer.m =================================================================== --- sope-mime/NGImap4/NGImap4ResponseNormalizer.m (révision 1626) From 8a2f70f210b6f6a82eea881a83b16b7fe577c36b Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Tue, 2 Sep 2008 04:02:46 +0000 Subject: [PATCH 13/17] Monotone-Parent: dcceb57e8e6ee4fbdfba1d9ff1f44cb1c59b56f5 Monotone-Revision: b9fb860f8f7838df1fa7d5d3aa5503299b0ca08a Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-02T04:02:46 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 8 ++++++++ SoObjects/Mailer/SOGoMailManager.m | 17 ++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8a101a8ae..7258ed874 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-09-02 Wolfgang Sourdeau + + * SoObjects/Mailer/SOGoMailManager.m ([NGImap + -copyMailURL:toFolderURL:password:]): do not compare the urls + based on the instance that NGImap4ConnectionManager returns, + because disabling the pooling will generate a bad result, even + though the host:port pairs are the same. + 2008-09-01 Wolfgang Sourdeau * UI/MailerUI/UIxMailView.m ([UIxMailView diff --git a/SoObjects/Mailer/SOGoMailManager.m b/SoObjects/Mailer/SOGoMailManager.m index 59c1f4c0b..b9b42e23f 100644 --- a/SoObjects/Mailer/SOGoMailManager.m +++ b/SoObjects/Mailer/SOGoMailManager.m @@ -20,6 +20,8 @@ */ #import +#import +#import #import #import @@ -194,20 +196,25 @@ password:(NSString *)_pwd { NGImap4Connection *entry; - + NSNumber *destPort, *srcPort; + /* check connection cache */ if ((entry = [self connectionForURL:_srcurl password:_pwd]) == nil) return [self errorForMissingEntryAtURL:_srcurl]; /* check whether URLs are on different servers */ - - if ([self connectionForURL:_desturl password:_pwd] != entry) { + srcPort = [_srcurl port]; + destPort = [_desturl port]; + + if (!([[_desturl host] isEqualToString: [_srcurl host]] + && (srcPort == destPort + || [destPort isEqualToNumber: srcPort]))) { // TODO: find a better error code return [NSException exceptionWithHTTPStatus:502 /* Bad Gateway */ reason:@"source and destination on different servers"]; - } - + } + return [entry copyMailURL:_srcurl toFolderURL:_desturl]; } From 6fa5b84ecd2383cf0088ef338cbc280ee47739e8 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Tue, 2 Sep 2008 18:44:48 +0000 Subject: [PATCH 14/17] Monotone-Parent: b9fb860f8f7838df1fa7d5d3aa5503299b0ca08a Monotone-Revision: 69df71bbd74fc7ccbfdfda4d8e386bd2d00ce08a Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2008-09-02T18:44:48 Monotone-Branch: ca.inverse.sogo --- UI/WebServerResources/MailerUI.js | 2 +- UI/WebServerResources/UIxMailEditor.css | 2 +- UI/WebServerResources/UIxMailEditor.js | 28 ++++++++++++----------- UI/WebServerResources/UIxMailPopupView.js | 3 ++- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index d674c7a73..ff08ee3bc 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -262,7 +262,7 @@ function deleteSelectedMessagesCallback(http) { if (!nextRow) nextRow = row.previous("tr"); // row.addClassName("deleted"); // when we'll offer "mark as deleted" - + if (deleteMessageRequestCount == 0) { if (nextRow) { Mailer.currentMessages[Mailer.currentMailbox] = nextRow.getAttribute("id").substr(4); diff --git a/UI/WebServerResources/UIxMailEditor.css b/UI/WebServerResources/UIxMailEditor.css index cd3ead518..1dabfa79e 100644 --- a/UI/WebServerResources/UIxMailEditor.css +++ b/UI/WebServerResources/UIxMailEditor.css @@ -153,5 +153,5 @@ UL#attachments LI IMG left: 0em; right: 0em; bottom: 0em; - top: 13em; + top: 999em; width: 99%; } diff --git a/UI/WebServerResources/UIxMailEditor.js b/UI/WebServerResources/UIxMailEditor.js index 63ae37732..228b9a291 100644 --- a/UI/WebServerResources/UIxMailEditor.js +++ b/UI/WebServerResources/UIxMailEditor.js @@ -8,7 +8,7 @@ var MailEditor = { addressBook: null, currentField: null, selectedIndex: -1, - delay: 500, + delay: 750, delayedSearch: false }; @@ -273,7 +273,7 @@ function onTextFocus() { } function onTextKeyDown(event) { - if (event.keyCode == 9) { + if (event.keyCode == Event.KEY_TAB) { if (event.shiftKey) { var nodes = $("subjectRow").childNodesWithTag("input"); var objectInput = $(nodes[0]); @@ -341,20 +341,20 @@ function onContactKeydown(event) { this.focussed = true; return; } - if (event.keyCode == 9) { // Tab + if (event.keyCode == Event.KEY_TAB) { if (this.confirmedValue) this.value = this.confirmedValue; if (document.currentPopupMenu) hideMenu(document.currentPopupMenu); } else if (event.keyCode == 0 - || event.keyCode == 8 // Backspace + || event.keyCode == Event.KEY_BACKSPACE || event.keyCode == 32 // Space || event.keyCode > 47) { this.confirmedValue = null; MailEditor.selectedIndex = -1; MailEditor.currentField = this; - if (this.value.length > 0 && !MailEditor.delayedSearch) { + if (this.value.length > 1 && MailEditor.delayedSearch == false) { MailEditor.delayedSearch = true; setTimeout("performSearch()", MailEditor.delay); } @@ -363,17 +363,17 @@ function onContactKeydown(event) { hideMenu(document.currentPopupMenu); } } - else if (event.keyCode == 13) { + else if (event.keyCode == Event.KEY_RETURN) { preventDefault(event); if (this.confirmedValue) this.value = this.confirmedValue; - $(this).selectText(0, this.value.length); + $(this).select(); if (document.currentPopupMenu) hideMenu(document.currentPopupMenu); MailEditor.selectedIndex = -1; } else if ($('contactsMenu').getStyle('visibility') == 'visible') { - if (event.keyCode == 38) { // Up arrow + if (event.keyCode == Event.KEY_UP) { // Up arrow if (MailEditor.selectedIndex > 0) { var contacts = $('contactsMenu').select("li"); contacts[MailEditor.selectedIndex--].removeClassName("selected"); @@ -381,7 +381,7 @@ function onContactKeydown(event) { contacts[MailEditor.selectedIndex].addClassName("selected"); } } - else if (event.keyCode == 40) { // Down arrow + else if (event.keyCode == Event.KEY_DOWN) { // Down arrow var contacts = $('contactsMenu').select("li"); if (contacts.size() - 1 > MailEditor.selectedIndex) { if (MailEditor.selectedIndex >= 0) @@ -402,7 +402,7 @@ function performSearch() { document.contactLookupAjaxRequest.aborted = true; document.contactLookupAjaxRequest.abort(); } - if (MailEditor.currentField.value.trim().length > 0) { + if (MailEditor.currentField.value.trim().length > 1) { var urlstr = ( UserFolderURL + "Contacts/allContactSearch?search=" + MailEditor.currentField.value ); document.contactLookupAjaxRequest = @@ -543,7 +543,8 @@ function initMailEditor() { textarea.observe(ieEvents[i], onTextIEUpdateCursorPos, false); } - initTabIndex($("addressList"), $$("div#subjectRow input").first(), textarea); + var subjectField = $$("div#subjectRow input").first(); + initTabIndex($("addressList"), subjectField, textarea); onWindowResize(null); Event.observe(window, "resize", onWindowResize); @@ -632,10 +633,11 @@ function onWindowResize(event) { addresslist.setStyle({ width: ($(this).width() - attachmentswidth - 10) + 'px' }); // Set textarea position - textarea.setStyle({ 'top': headerarea.select("hr").first().offsetTop + 'px' }); + var hr = headerarea.select("hr").first(); + textarea.setStyle({ 'top': hr.offsetTop + 'px' }); // Resize the textarea (message content) - textarea.rows = Math.round((window.height() - textarea.offsetTop) / rowheight); + textarea.rows = Math.floor((window.height() - textarea.offsetTop) / rowheight); } function onMailEditorClose(event) { diff --git a/UI/WebServerResources/UIxMailPopupView.js b/UI/WebServerResources/UIxMailPopupView.js index 9ea40ffaa..5443d7b77 100644 --- a/UI/WebServerResources/UIxMailPopupView.js +++ b/UI/WebServerResources/UIxMailPopupView.js @@ -29,7 +29,8 @@ function onICalendarButtonClick(event) { function onMenuDeleteMessage(event) { if (window.opener && window.opener.open && !window.opener.closed) { - var rowId = window.name.substr(9); + var rowId_index = window.name.search(/[0-9]+$/); + var rowId = window.name.substr(rowId_index); var messageId = window.opener.Mailer.currentMailbox + "/" + rowId; var url = ApplicationBaseURL + messageId + "/trash"; From cc1bd1abe5844e619eeaaef76ed0f94b5a0e479d Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Tue, 2 Sep 2008 19:15:58 +0000 Subject: [PATCH 15/17] Fix for bug #2878 Monotone-Parent: 69df71bbd74fc7ccbfdfda4d8e386bd2d00ce08a Monotone-Revision: 2d32d54f3ab29efb615ba64c54fb4714a8cbd0a1 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2008-09-02T19:15:58 Monotone-Branch: ca.inverse.sogo --- UI/WebServerResources/UIxMailEditor.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/UI/WebServerResources/UIxMailEditor.js b/UI/WebServerResources/UIxMailEditor.js index 228b9a291..02c108709 100644 --- a/UI/WebServerResources/UIxMailEditor.js +++ b/UI/WebServerResources/UIxMailEditor.js @@ -354,11 +354,11 @@ function onContactKeydown(event) { this.confirmedValue = null; MailEditor.selectedIndex = -1; MailEditor.currentField = this; - if (this.value.length > 1 && MailEditor.delayedSearch == false) { - MailEditor.delayedSearch = true; - setTimeout("performSearch()", MailEditor.delay); + if (this.value.length > 1) { + if (MailEditor.delayedSearch) window.clearTimeout(MailEditor.delayedSearch); + MailEditor.delayedSearch = window.setTimeout("performSearch()", MailEditor.delay); } - else if (this.value.length == 0) { + else if (this.value.length <= 1) { if (document.currentPopupMenu) hideMenu(document.currentPopupMenu); } @@ -409,7 +409,6 @@ function performSearch() { triggerAjaxRequest(urlstr, performSearchCallback, MailEditor.currentField); } } - MailEditor.delayedSearch = false; } function performSearchCallback(http) { From 5eadf6a93691280e75277bc74ea88b6d753a5cc3 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Tue, 2 Sep 2008 20:52:09 +0000 Subject: [PATCH 16/17] Fix for bug #2889 Monotone-Parent: 2d32d54f3ab29efb615ba64c54fb4714a8cbd0a1 Monotone-Revision: bf785cb3c555f8f6753cf915bc53455b1fb08004 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2008-09-02T20:52:09 Monotone-Branch: ca.inverse.sogo --- UI/WebServerResources/MailerUI.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index ff08ee3bc..6face0a55 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -1567,8 +1567,12 @@ function getFoldersStateCallback(http) { function saveFoldersState() { if (mailAccounts.length > 0) { var foldersState = mailboxTree.getFoldersState(); - var urlstr = ApplicationBaseURL + "saveFoldersState" + "?expandedFolders=" + foldersState; - triggerAjaxRequest(urlstr, saveFoldersStateCallback); + var urlstr = ApplicationBaseURL + "saveFoldersState"; + var parameters = "expandedFolders=" + foldersState; + triggerAjaxRequest(urlstr, saveFoldersStateCallback, null, parameters, + { "Content-type": "application/x-www-form-urlencoded", + "Content-length": parameters.length, + "Connection": "close" }); } } From 6eab6532b713803cadf7398ea6c9621b377acadb Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Tue, 2 Sep 2008 20:57:23 +0000 Subject: [PATCH 17/17] Monotone-Parent: bf785cb3c555f8f6753cf915bc53455b1fb08004 Monotone-Revision: 99cc1bb593f4002d820b712345f3e8c1c9ba44ba Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-02T20:57:23 Monotone-Branch: ca.inverse.sogo --- SOPE/sope-patchset-r1626.diff | 847 +++++++++++++++++++++++++++++++++- 1 file changed, 846 insertions(+), 1 deletion(-) diff --git a/SOPE/sope-patchset-r1626.diff b/SOPE/sope-patchset-r1626.diff index cf84f7457..faa243b64 100644 --- a/SOPE/sope-patchset-r1626.diff +++ b/SOPE/sope-patchset-r1626.diff @@ -499,6 +499,42 @@ Index: sope-mime/NGImap4/NGImap4Client.m - (NSException *)_processCommandParserException:(NSException *)_exception { [self logWithFormat:@"ERROR(%s): catched IMAP4 parser exception %@: %@", __PRETTY_FUNCTION__, [_exception name], [_exception reason]]; +Index: sope-mime/NGImap4/NGSieveClient.m +=================================================================== +--- sope-mime/NGImap4/NGSieveClient.m (révision 1626) ++++ sope-mime/NGImap4/NGSieveClient.m (copie de travail) +@@ -294,8 +294,8 @@ + return con; + } + +- logLen = [self->login cStringLength]; +- bufLen = (logLen * 2) + [self->password cStringLength] +2; ++ logLen = [self->login lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; ++ bufLen = (logLen * 2) + [self->password lengthOfBytesUsingEncoding: NSUTF8StringEncoding] +2; + + buf = calloc(bufLen + 2, sizeof(char)); + +@@ -306,8 +306,9 @@ + password + */ + sprintf(buf, "%s %s %s", +- [self->login cString], [self->login cString], +- [self->password cString]); ++ [self->login cStringUsingEncoding:NSUTF8StringEncoding], ++ [self->login cStringUsingEncoding:NSUTF8StringEncoding], ++ [self->password cStringUsingEncoding:NSUTF8StringEncoding]); + + buf[logLen] = '\0'; + buf[logLen * 2 + 1] = '\0'; +@@ -656,7 +657,7 @@ + fputc('\n', stderr); + } + else +- fprintf(stderr, "C: %s\n", [_txt cString]); ++ fprintf(stderr, "C: %s\n", [_txt cStringUsingEncoding:NSUTF8StringEncoding]); + } + + /* write */ Index: sope-mime/NGImap4/NGImap4Connection.m =================================================================== --- sope-mime/NGImap4/NGImap4Connection.m (révision 1626) @@ -821,6 +857,18 @@ Index: sope-mime/NGImap4/NGImap4ResponseParser.m - (NSException *)exceptionForFailedMatch:(unsigned char)_match got:(unsigned char)_avail { +@@ -2225,9 +2297,9 @@ + [s release]; + + if (c == '\n') { +- if ([self->serverResponseDebug cStringLength] > 2) { ++ if ([self->serverResponseDebug lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding] > 2) { + fprintf(stderr, "S[%p]: %s", self, +- [self->serverResponseDebug cString]); ++ [self->serverResponseDebug cStringUsingEncoding:NSISOLatin1StringEncoding]); + } + [self->serverResponseDebug release]; + self->serverResponseDebug = Index: sope-mime/NGImap4/ChangeLog =================================================================== --- sope-mime/NGImap4/ChangeLog (révision 1626) @@ -965,6 +1013,528 @@ Index: sope-mime/NGImap4/NGImap4ConnectionManager.m } /* client object */ +Index: sope-mime/NGImap4/NSString+Imap4.m +=================================================================== +--- sope-mime/NGImap4/NSString+Imap4.m (révision 1626) ++++ sope-mime/NGImap4/NSString+Imap4.m (copie de travail) +@@ -20,11 +20,56 @@ + 02111-1307, USA. + */ + ++#import ++ + #include + #include "imCommon.h" + + /* TODO: NOT UNICODE SAFE (uses cString) */ + ++#ifndef __APPLE__ ++ ++@interface NSMutableData (PantomimeExtensions) ++ ++- (void) appendCFormat: (NSString *) theFormat, ...; ++- (void) appendCString: (const char *) theCString; ++ ++@end ++ ++@implementation NSMutableData (PantomimeExtensions) ++ ++- (void) appendCFormat: (NSString *) theFormat, ... ++{ ++ NSString *aString; ++ va_list args; ++ ++ va_start(args, theFormat); ++ aString = [[NSString alloc] initWithFormat: theFormat arguments: args]; ++ va_end(args); ++ ++ // We allow lossy conversion to not lose any information / raise an exception ++ [self appendData: [aString dataUsingEncoding: NSASCIIStringEncoding allowLossyConversion: YES]]; ++ ++ RELEASE(aString); ++} ++ ++ ++// ++// ++// ++- (void) appendCString: (const char *) theCString ++{ ++ [self appendBytes: theCString length: strlen(theCString)]; ++} ++ ++@end ++ ++#endif ++ ++@implementation NSString(Imap4) ++ ++#if __APPLE__ ++ + static void _encodeToModifiedUTF7(unsigned char *_buf, int encLen, + unsigned char **result_, + unsigned int *cntRes_); +@@ -33,8 +78,6 @@ + unsigned char **buffer_, + int *bufLen_, int maxBuf); + +-@implementation NSString(Imap4) +- + - (NSString *)stringByEncodingImap4FolderName { + // TBD: this is restricted to Latin1, should be fixed to UTF-8 + /* dude.d& --> dude.d&- */ +@@ -46,12 +89,15 @@ + NSString *result = nil; + NSData *data; + +- len = [self cStringLength]; +- buf = calloc(len + 3, sizeof(char)); +- res = calloc((len * 6) + 3, sizeof(char)); +- buf[len] = '\0'; +- res[len * 6] = '\0'; +- [self getCString:(char *)buf]; ++ len = [self lengthOfBytesUsingEncoding: NSISOLatin1StringEncoding] + 1; ++ buf = calloc(len + 3, sizeof(char)); ++ res = calloc((len * 6) + 3, sizeof(char)); ++ [self getCString:(char *)buf maxLength: len ++ encoding: NSISOLatin1StringEncoding]; ++ buf[len-1] = 0; ++ buf[len] = 0; ++ buf[len+1] = 0; ++ buf[len+2] = 0; + + while (cnt < len) { + int c = buf[cnt]; +@@ -185,70 +231,6 @@ + return [result autorelease]; + } + +-- (NSString *)stringByEscapingImap4Password { +- // TODO: perf +- unichar *buffer; +- unichar *chars; +- unsigned len, i, j; +- NSString *s; +- +- len = [self length]; +- chars = calloc(len + 2, sizeof(unichar)); +- [self getCharacters:chars]; +- +- buffer = calloc(len * 2 + 2, sizeof(unichar)); +- buffer[len * 2] = '\0'; +- +- for (i = 0, j = 0; i < len; i++, j++) { +- BOOL conv = NO; +- +- if (chars[i] <= 0x1F || chars[i] > 0x7F) { +- conv = YES; +- } +- else switch (chars[i]) { +- case '(': +- case ')': +- case '{': +- case ' ': +- case '%': +- case '*': +- case '"': +- case '\\': +- conv = YES; +- break; +- } +- +- if (conv) { +- buffer[j] = '\\'; +- j++; +- } +- buffer[j] = chars[i]; +- } +- if (chars != NULL) free(chars); chars = NULL; +- +- s = [NSString stringWithCharacters:buffer length:j]; +- if (buffer != NULL) free(buffer); buffer = NULL; +- return s; +-} +- +-@end /* NSString(Imap4) */ +- +-static void writeChunk(int _c1, int _c2, int _c3, int _pads, +- unsigned char **result_, +- unsigned int *cntRes_); +- +-static int getChar(int _cnt, int *cnt_, unsigned char *_buf) { +- int result; +- +- if ((_cnt % 2)) { +- result = _buf[*cnt_]; +- (*cnt_)++; +- } +- else { +- result = 0; +- } +- return result; +-} + static void _encodeToModifiedUTF7(unsigned char *_buf, int encLen, + unsigned char **result_, unsigned int *cntRes_) + { +@@ -276,58 +258,6 @@ + } + } + +-/* check metamail output for correctness */ +- +-static unsigned char basis_64[] = +- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +- +-static void writeChunk(int c1, int c2, int c3, int pads, unsigned char **result_, +- unsigned int *cntRes_) { +- unsigned char c; +- +- c = basis_64[c1>>2]; +- (*result_)[*cntRes_] = c; +- (*cntRes_)++; +- +- c = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)]; +- +- (*result_)[*cntRes_] = c; +- (*cntRes_)++; +- +- +- if (pads == 2) { +- ; +- } +- else if (pads) { +- c = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)]; +- (*result_)[*cntRes_] = c; +- (*cntRes_)++; +- } +- else { +- c = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)]; +- +- (*result_)[*cntRes_] = c; +- (*cntRes_)++; +- +- c = basis_64[c3 & 0x3F]; +- (*result_)[*cntRes_] = c; +- (*cntRes_)++; +- } +-} +- +-static char index_64[128] = { +- -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, +- -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, +- -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, +- 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, +- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, +- 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, +- -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, +- 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 +-}; +- +-#define char64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) +- + static int _decodeOfModifiedUTF7(unsigned char *_target, unsigned _targetLen, + unsigned *usedBytes_ , unsigned char **buffer_, + int *bufLen_, int maxBuf) +@@ -430,3 +360,299 @@ + } + return 0; + } ++ ++static void writeChunk(int _c1, int _c2, int _c3, int _pads, ++ unsigned char **result_, ++ unsigned int *cntRes_); ++ ++static int getChar(int _cnt, int *cnt_, unsigned char *_buf) { ++ int result; ++ ++ if ((_cnt % 2)) { ++ result = _buf[*cnt_]; ++ (*cnt_)++; ++ } ++ else { ++ result = 0; ++ } ++ return result; ++} ++ ++/* check metamail output for correctness */ ++ ++static unsigned char basis_64[] = ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ++ ++static void writeChunk(int c1, int c2, int c3, int pads, unsigned char **result_, ++ unsigned int *cntRes_) { ++ unsigned char c; ++ ++ c = basis_64[c1>>2]; ++ (*result_)[*cntRes_] = c; ++ (*cntRes_)++; ++ ++ c = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)]; ++ ++ (*result_)[*cntRes_] = c; ++ (*cntRes_)++; ++ ++ ++ if (pads == 2) { ++ ; ++ } ++ else if (pads) { ++ c = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)]; ++ (*result_)[*cntRes_] = c; ++ (*cntRes_)++; ++ } ++ else { ++ c = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)]; ++ ++ (*result_)[*cntRes_] = c; ++ (*cntRes_)++; ++ ++ c = basis_64[c3 & 0x3F]; ++ (*result_)[*cntRes_] = c; ++ (*cntRes_)++; ++ } ++} ++ ++static char index_64[128] = { ++ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, ++ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, ++ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, ++ 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, ++ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, ++ 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, ++ -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, ++ 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 ++}; ++ ++#define char64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) ++ ++#else // __APPLE__ ++ ++#define IS_PRINTABLE(c) (isascii(c) && isprint(c)) ++ ++- (NSString *)stringByEncodingImap4FolderName { ++ NSMutableData *aMutableData, *modifiedData; ++ NSString *aString; ++ ++ const char *b; ++ BOOL escaped; ++ unichar ch; ++ int i, len; ++ ++ // ++ // We UTF-7 encode _only_ the non-ASCII parts. ++ // ++ aMutableData = [[NSMutableData alloc] init]; ++ AUTORELEASE(aMutableData); ++ len = [self length]; ++ ++ for (i = 0; i < len; i++) ++ { ++ ch = [self characterAtIndex: i]; ++ ++ if (IS_PRINTABLE(ch)) ++ { ++ [aMutableData appendCFormat: @"%c", ch]; ++ } ++ else ++ { ++ int j; ++ ++ j = i+1; ++ // We got a non-ASCII character, let's get the substring and encode it using UTF-7. ++ while (j < len && !IS_PRINTABLE([self characterAtIndex: j])) ++ { ++ j++; ++ } ++ ++ // Get the substring. ++ [aMutableData appendData: [[self substringWithRange: NSMakeRange(i,j-i)] dataUsingEncoding: NSUTF7StringEncoding]]; ++ i = j-1; ++ } ++ } ++ ++ b = [aMutableData bytes]; ++ len = [aMutableData length]; ++ escaped = NO; ++ ++ // ++ // We replace: ++ // ++ // & -> &- ++ // + -> & ++ // +- -> + ++ // / -> , ++ // ++ // in order to produce our modified UTF-7 string. ++ // ++ modifiedData = [[NSMutableData alloc] init]; ++ AUTORELEASE(modifiedData); ++ ++ for (i = 0; i < len; i++, b++) ++ { ++ if (!escaped && *b == '&') ++ { ++ [modifiedData appendCString: "&-"]; ++ } ++ else if (!escaped && *b == '+') ++ { ++ if (*(b+1) == '-') ++ { ++ [modifiedData appendCString: "+"]; ++ } ++ else ++ { ++ [modifiedData appendCString: "&"]; ++ ++ // We enter the escaped mode. ++ escaped = YES; ++ } ++ } ++ else if (escaped && *b == '/') ++ { ++ [modifiedData appendCString: ","]; ++ } ++ else if (escaped && *b == '-') ++ { ++ [modifiedData appendCString: "-"]; ++ ++ // We leave the escaped mode. ++ escaped = NO; ++ } ++ else ++ { ++ [modifiedData appendCFormat: @"%c", *b]; ++ } ++ } ++ ++ // If we're still in the escaped mode we haven't added our trailing -, ++ // let's add it right now. ++ if (escaped) ++ { ++ [modifiedData appendCString: "-"]; ++ } ++ ++ aString = AUTORELEASE([[NSString alloc] initWithData: modifiedData encoding: NSASCIIStringEncoding]); ++ ++ return (aString != nil ? aString : self); ++} ++ ++// ++// ++// ++- (NSString *)stringByDecodingImap4FolderName { ++ NSMutableData *aMutableData; ++ ++ BOOL escaped; ++ unichar ch; ++ int i, len; ++ ++ aMutableData = [[NSMutableData alloc] init]; ++ AUTORELEASE(aMutableData); ++ ++ len = [self length]; ++ escaped = NO; ++ ++ // ++ // We replace: ++ // ++ // & -> + ++ // &- -> & ++ // , -> / ++ // ++ // If we are in escaped mode. That is, between a &....- ++ // ++ for (i = 0; i < len; i++) ++ { ++ ch = [self characterAtIndex: i]; ++ ++ if (!escaped && ch == '&') ++ { ++ if ( (i+1) < len && [self characterAtIndex: (i+1)] != '-' ) ++ { ++ [aMutableData appendCString: "+"]; ++ ++ // We enter the escaped mode. ++ escaped = YES; ++ } ++ else ++ { ++ // We replace &- by & ++ [aMutableData appendCString: "&"]; ++ i++; ++ } ++ } ++ else if (escaped && ch == ',') ++ { ++ [aMutableData appendCString: "/"]; ++ } ++ else if (escaped && ch == '-') ++ { ++ [aMutableData appendCString: "-"]; ++ ++ // We leave the escaped mode. ++ escaped = NO; ++ } ++ else ++ { ++ [aMutableData appendCFormat: @"%c", ch]; ++ } ++ } ++ ++ return AUTORELEASE([[NSString alloc] initWithData: aMutableData encoding: NSUTF7StringEncoding]); ++} ++ ++ ++#endif // __APPLE__ ++ ++- (NSString *)stringByEscapingImap4Password { ++ // TODO: perf ++ unichar *buffer; ++ unichar *chars; ++ unsigned len, i, j; ++ NSString *s; ++ ++ len = [self length]; ++ chars = calloc(len + 2, sizeof(unichar)); ++ [self getCharacters:chars]; ++ ++ buffer = calloc(len * 2 + 2, sizeof(unichar)); ++ buffer[len * 2] = '\0'; ++ ++ for (i = 0, j = 0; i < len; i++, j++) { ++ BOOL conv = NO; ++ ++ if (chars[i] <= 0x1F || chars[i] > 0x7F) { ++ conv = YES; ++ } ++ else switch (chars[i]) { ++ case '(': ++ case ')': ++ case '{': ++ case ' ': ++ case '%': ++ case '*': ++ case '"': ++ case '\\': ++ conv = YES; ++ break; ++ } ++ ++ if (conv) { ++ buffer[j] = '\\'; ++ j++; ++ } ++ buffer[j] = chars[i]; ++ } ++ if (chars != NULL) free(chars); chars = NULL; ++ ++ s = [NSString stringWithCharacters:buffer length:j]; ++ if (buffer != NULL) free(buffer); buffer = NULL; ++ return s; ++} ++ ++@end /* NSString(Imap4) */ Index: sope-mime/NGMail/NGSmtpClient.m =================================================================== --- sope-mime/NGMail/NGSmtpClient.m (révision 1626) @@ -1765,6 +2335,31 @@ Index: sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m if (date == nil) goto failed; #if 0 +Index: sope-mime/NGMime/NGMimeMultipartBodyParser.m +=================================================================== +--- sope-mime/NGMime/NGMimeMultipartBodyParser.m (révision 1626) ++++ sope-mime/NGMime/NGMimeMultipartBodyParser.m (copie de travail) +@@ -428,6 +428,7 @@ + NSString *boundary = nil; + NSArray *rawBodyParts = nil; + BOOL foundError = NO; ++ NSData *boundaryBytes; + + contentType = [_part contentType]; + boundary = [contentType valueOfParameter:@"boundary"]; +@@ -437,9 +438,10 @@ + + *(&foundError) = NO; + ++ boundaryBytes = [boundary dataUsingEncoding:NSISOLatin1StringEncoding]; + *(&rawBodyParts) = [self _parseBody:_body part:_part data:_data +- boundary:[boundary cString] +- length:[boundary cStringLength] ++ boundary:[boundaryBytes bytes] ++ length:[boundary length] + delegate:_d]; + + if (rawBodyParts) { Index: sope-mime/NGMime/NGMimeHeaderFieldGeneratorSet.m =================================================================== --- sope-mime/NGMime/NGMimeHeaderFieldGeneratorSet.m (révision 1626) @@ -1781,7 +2376,42 @@ Index: sope-mime/NGMime/NGMimeType.m =================================================================== --- sope-mime/NGMime/NGMimeType.m (révision 1626) +++ sope-mime/NGMime/NGMimeType.m (copie de travail) -@@ -152,7 +152,7 @@ +@@ -120,28 +120,23 @@ + + /* some unsupported, but known encoding */ + else if ([charset isEqualToString:@"ks_c_5601-1987"]) { +- encoding = [NSString defaultCStringEncoding]; ++ encoding = NSISOLatin1StringEncoding; + foundUnsupported = YES; + } + else if ([charset isEqualToString:@"euc-kr"]) { +- encoding = [NSString defaultCStringEncoding]; +- foundUnsupported = YES; ++ encoding = NSKoreanEUCStringEncoding; + } + else if ([charset isEqualToString:@"big5"]) { +- encoding = [NSString defaultCStringEncoding]; +- foundUnsupported = YES; ++ encoding = NSBIG5StringEncoding; + } + else if ([charset isEqualToString:@"iso-2022-jp"]) { +- encoding = [NSString defaultCStringEncoding]; +- foundUnsupported = YES; ++ encoding = NSISO2022JPStringEncoding; + } + else if ([charset isEqualToString:@"gb2312"]) { +- encoding = [NSString defaultCStringEncoding]; +- foundUnsupported = YES; ++ encoding = NSGB2312StringEncoding; + } + else if ([charset isEqualToString:@"koi8-r"]) { +- encoding = [NSString defaultCStringEncoding]; +- foundUnsupported = YES; ++ encoding = NSKOI8RStringEncoding; + } + + else if ([charset isEqualToString:@"windows-1252"]) { +@@ -152,7 +147,7 @@ } else if ([charset isEqualToString:@"x-unknown"] || [charset isEqualToString:@"unknown"]) { @@ -1790,6 +2420,56 @@ Index: sope-mime/NGMime/NGMimeType.m } /* ISO Latin 9 */ #if !(NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY) +@@ -166,7 +161,7 @@ + else { + [self logWithFormat:@"%s: unknown charset '%@'", + __PRETTY_FUNCTION__, _s]; +- encoding = [NSString defaultCStringEncoding]; ++ encoding = NSISOLatin1StringEncoding; + } + return encoding; + } +@@ -385,23 +380,26 @@ + } + + - (BOOL)valueNeedsQuotes:(NSString *)_parameterValue { +- unsigned len = [_parameterValue cStringLength]; +- char buf[len + 15]; +- char *cstr; ++ NSData *stringData; ++ const char *cstr; ++ unsigned int count, max; ++ BOOL needsQuote; + +- cstr = &(buf[0]); ++ needsQuote = NO; + +- [_parameterValue getCString:cstr]; cstr[len] = '\0'; +- while (*cstr) { +- if (isMime_SpecialByte(*cstr)) +- return YES; +- +- if (*cstr == 32) +- return YES; +- +- cstr++; ++ stringData = [_parameterValue dataUsingEncoding:NSUTF8StringEncoding]; ++ cstr = [stringData bytes]; ++ max = [stringData length]; ++ count = 0; ++ while (!needsQuote && count < max) { ++ if (isMime_SpecialByte(*(cstr + count)) ++ || *(cstr + count) == 32) ++ needsQuote = YES; ++ else ++ count++; + } +- return NO; ++ ++ return needsQuote; + } + + - (NSString *)stringValue { Index: sope-mime/NGMime/NGMimeBodyPart.m =================================================================== --- sope-mime/NGMime/NGMimeBodyPart.m (révision 1626) @@ -1868,6 +2548,171 @@ Index: sope-mime/NGMime/ChangeLog 2008-01-29 Albrecht Dress * fixes for OGo bug #789 (reply-to QP encoding) +Index: sope-mime/NGMime/NGMimeContentTypeHeaderFieldGenerator.m +=================================================================== +--- sope-mime/NGMime/NGMimeContentTypeHeaderFieldGenerator.m (révision 1626) ++++ sope-mime/NGMime/NGMimeContentTypeHeaderFieldGenerator.m (copie de travail) +@@ -36,8 +36,7 @@ + NGMimeType *type = nil; // only one content-type field + NSString *tmp = nil; + NSMutableData *data = nil; +- unsigned char *ctmp = NULL; +- unsigned len = 0; ++ NSData *valueData; + + type = _value; + +@@ -59,21 +58,15 @@ + + tmp = [type type]; + NSAssert(tmp, @"type should not be nil"); +- len = [tmp length]; +- ctmp = malloc(len + 4); +- [tmp getCString:(char *)ctmp]; ctmp[len] = '\0'; +- [data appendBytes:ctmp length:len]; +- free(ctmp); ++ valueData = [tmp dataUsingEncoding: NSISOLatin1StringEncoding]; ++ [data appendData: valueData]; ++ ++ [data appendBytes:"/" length:1]; + +- [data appendBytes:"//" length:1]; +- + tmp = [type subType]; + if (tmp != nil) { +- len = [tmp length]; +- ctmp = malloc(len + 4); +- [tmp getCString:(char *)ctmp]; ctmp[len] = '\0'; +- [data appendBytes:ctmp length:len]; +- free(ctmp); ++ valueData = [tmp dataUsingEncoding: NSISOLatin1StringEncoding]; ++ [data appendData:valueData]; + } + else + [data appendBytes:"*" length:1]; +@@ -91,12 +84,9 @@ + continue; + } + [data appendBytes:"; " length:2]; +- +- len = [name cStringLength]; +- ctmp = malloc(len + 1); +- [name getCString:(char *)ctmp]; ctmp[len] = '\0'; +- [data appendBytes:ctmp length:len]; +- free(ctmp); ++ ++ valueData = [name dataUsingEncoding: NSUTF8StringEncoding]; ++ [data appendData: valueData]; + + /* + this confuses GroupWise: "= \"" (a space) +@@ -105,66 +95,30 @@ + + /* check for encoding */ + { +- unsigned cnt; ++ unsigned cnt, max; ++ const char *dataBytes; + BOOL doEnc; + +- len = [value cStringLength]; +- ctmp = malloc(len + 4); +- [value getCString:(char *)ctmp]; ctmp[len] = '\0'; +- cnt = 0; ++ valueData = [value dataUsingEncoding:NSUTF8StringEncoding]; ++ dataBytes = [valueData bytes]; ++ max = [valueData length]; ++ + doEnc = NO; +- while (cnt < len) { +- if ((unsigned char)ctmp[cnt] > 127) { ++ cnt = 0; ++ while (!doEnc && cnt < max) { ++ if ((unsigned char)dataBytes[cnt] > 127) + doEnc = YES; +- break; +- } +- cnt++; ++ else ++ cnt++; + } + if (doEnc) { +- unsigned char iso[] = "=?iso-8859-15?q?"; +- unsigned isoLen = 16; +- unsigned char isoEnd[] = "?="; +- unsigned isoEndLen = 2; +- unsigned desLen; +- unsigned char *des; +- +- if (ctmp) free(ctmp); +- { +- NSData *data; +- +-#if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY +- data = [value dataUsingEncoding:NSISOLatin1StringEncoding]; +-#else +- data = [value dataUsingEncoding:NSISOLatin9StringEncoding]; +-#endif +- +- len = [data length]; +- ctmp = malloc(len + 10); +- [data getBytes:ctmp]; ctmp[len] = '\0'; +- } +- +- desLen = len * 3 + 20; +- des = calloc(desLen + 10, sizeof(char)); +- +- memcpy(des, ctmp, cnt); +- memcpy(des + cnt, iso, isoLen); +- desLen = +- NGEncodeQuotedPrintableMime(ctmp + cnt, len - cnt, +- des + cnt + isoLen, +- desLen - cnt - isoLen); +- if ((int)desLen != -1) { +- memcpy(des + cnt + isoLen + desLen, isoEnd, isoEndLen); +- [data appendBytes:des length:(cnt + isoLen + desLen + isoEndLen)]; +- } +- else { +- NSLog(@"WARNING: An error occour during quoted-printable decoding"); +- } +- if (des) free(des); ++ [data appendBytes:"=?utf-8?q?" length:10]; ++ [data appendData: [valueData dataByEncodingQuotedPrintable]]; ++ [data appendBytes:"?=" length:2]; + } + else { +- [data appendBytes:ctmp length:len]; ++ [data appendData: valueData]; + } +- free(ctmp); + } + [data appendBytes:"\"" length:1]; + } +Index: sope-mime/NGMime/NGMimePartGenerator.m +=================================================================== +--- sope-mime/NGMime/NGMimePartGenerator.m (révision 1626) ++++ sope-mime/NGMime/NGMimePartGenerator.m (copie de travail) +@@ -155,8 +155,9 @@ + BOOL isMultiValue, isFirst; + + /* get field name and strip leading spaces */ +- fcname = (const unsigned char *)[_field cString]; +- for (len = [_field cStringLength]; len > 0; fcname++, len--) { ++ fcname = (const unsigned char *)[_field cStringUsingEncoding:NSISOLatin1StringEncoding]; ++ for (len = [_field lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding]; ++ len > 0; fcname++, len--) { + if (*fcname != ' ') + break; + } +@@ -328,7 +329,7 @@ + if ([body isKindOfClass:[NSData class]]) + data = body; + else if ([body isKindOfClass:[NSString class]]) +- data = [body dataUsingEncoding:[NSString defaultCStringEncoding]]; ++ data = [body dataUsingEncoding: NSISOLatin1StringEncoding]; + else + data = nil; + Index: sope-mime/NGMime/NGMimeBodyParser.m =================================================================== --- sope-mime/NGMime/NGMimeBodyParser.m (révision 1626)