Index: sope-gdl1/PostgreSQL/PostgreSQL72Channel.m =================================================================== --- sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (révision 1546) +++ 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,\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/GNUmakefile =================================================================== --- sope-gdl1/Oracle8/GNUmakefile (révision 1546) +++ sope-gdl1/Oracle8/GNUmakefile (copie de travail) @@ -28,15 +28,23 @@ SOPE_ROOT=../.. ORACLE_VERSION=10.2.0.3 #ORACLE_VERSION=11.1.0.1 -ADDITIONAL_INCLUDE_DIRS += -I../GDLAccess -I.. -I/usr/include/oracle/$(ORACLE_VERSION)/client +ADDITIONAL_INCLUDE_DIRS += -I../../sope-core -I../../sope-core/NGExtensions -I../GDLAccess -I.. -I/usr/include/oracle/$(ORACLE_VERSION)/client +local_arch = $(subst 64,,$(shell uname -m)) + +ifeq ($(local_arch),ppc) +PPC_LDFLAGS=-L/opt/ibmcmp/lib -libmc++ +else +PPC_LDFLAGS= +endif + ifneq ($(frameworks),yes) -Oracle8_BUNDLE_LIBS += -L/usr/lib/oracle/$(ORACLE_VERSION)/client/lib/ -locci -lociei -lclntsh -lnnz10 -lGDLAccess -lEOControl -otest_TOOL_LIBS += -L/usr/lib/oracle/$(ORACLE_VERSION)/client/lib/ -locci -lociei -lclntsh -lnnz10 -lGDLAccess -lEOControl +common_LIBS = -L/usr/lib/oracle/$(ORACLE_VERSION)/client/lib/ -locci -lociei -lclntsh -lnnz10 -L../GDLAccess/obj -lGDLAccess -L../../sope-core/EOControl/obj -lEOControl $(PPC_LDFLAGS) else -Oracle8_BUNDLE_LIBS += -L/usr/lib/oracle/$(ORACLE_VERSION)/client/lib/ -locci -lociei -lclntsh -lnnz10 -framework GDLAccess -framework EOControl -otest_TOOL_LIBS += -L/usr/lib/oracle/$(ORACLE_VERSION)/client/lib/ -locci -lociei -lclntsh -lnnz10 -framework GDLAccess -framework EOControl +common_LIBS = -L/usr/lib/oracle/$(ORACLE_VERSION)/client/lib/ -locci -lociei -lclntsh -lnnz10 -framework GDLAccess -framework EOControl $(PPC_LDFLAGS) endif +Oracle8_BUNDLE_LIBS += $(common_LIBS) +otest_TOOL_LIBS += $(common_LIBS) # Bundle BUNDLE_NAME = Oracle8 Index: sope-gdl1/Oracle8/OracleAdaptorChannel.m =================================================================== --- sope-gdl1/Oracle8/OracleAdaptorChannel.m (révision 1546) +++ sope-gdl1/Oracle8/OracleAdaptorChannel.m (copie de travail) @@ -53,14 +53,17 @@ while (c--) { info = [[_row_buffer objectAtIndex: c] pointerValue]; - [_row_buffer removeObjectAtIndex: c]; // We free our LOB object. If it fails, it likely mean it isn't a LOB // so we just free the value instead. - if (OCIDescriptorFree((dvoid *)info->value, (ub4)OCI_DTYPE_LOB) != OCI_SUCCESS) - { - free(info->value); - } + if (info->value) + { + if (OCIDescriptorFree((dvoid *)info->value, (ub4)OCI_DTYPE_LOB) != OCI_SUCCESS) + free(info->value); + info->value = NULL; + } + free(info); + [_row_buffer removeObjectAtIndex: c]; } OCIHandleFree(_current_stm, OCI_HTYPE_STMT); @@ -75,6 +78,30 @@ // @implementation OracleAdaptorChannel +static void +DBTerminate() +{ + if (OCITerminate(OCI_DEFAULT)) + NSLog(@"FAILED: OCITerminate()"); + else + NSLog(@"Oracle8: environment shut down"); +} + ++ (void) initialize +{ + // We Initialize the OCI process environment. + if (OCIInitialize((ub4)OCI_DEFAULT, (dvoid *)0, + (dvoid * (*)(dvoid *, size_t)) 0, + (dvoid * (*)(dvoid *, dvoid *, size_t))0, + (void (*)(dvoid *, dvoid *)) 0 )) + NSLog(@"FAILED: OCIInitialize()"); + else + { + NSLog(@"Oracle8: environment initialized"); + atexit(DBTerminate); + } +} + - (id) initWithAdaptorContext: (EOAdaptorContext *) theAdaptorContext { if ((self = [super initWithAdaptorContext: theAdaptorContext])) @@ -134,10 +161,14 @@ NSLog(@"FAILED: OCILogoff()"); } - if (OCITerminate(OCI_DEFAULT)) - { - NSLog(@"FAILED: OCITerminate()"); - } + + OCIHandleFree(_oci_ctx, OCI_HTYPE_SVCCTX); + OCIHandleFree(_oci_err, OCI_HTYPE_ERROR); + // OCIHandleFree(_oci_env, OCI_HTYPE_ENV); + + _oci_ctx = (OCISvcCtx *)0; + _oci_err = (OCIError *)0; + _oci_env = (OCIEnv *)0; } } @@ -151,11 +182,6 @@ [self _cleanup]; RELEASE(_resultSetProperties); - - OCIHandleFree(_oci_ctx, OCI_HTYPE_SVCCTX); - OCIHandleFree(_oci_err, OCI_HTYPE_ERROR); - OCIHandleFree(_oci_env, OCI_HTYPE_ENV); - RELEASE(delegate); [super dealloc]; @@ -368,16 +394,7 @@ return NO; } - // We Initialize the OCI process environment. - if (OCIInitialize((ub4)OCI_DEFAULT, (dvoid *)0, - (dvoid * (*)(dvoid *, size_t)) 0, - (dvoid * (*)(dvoid *, dvoid *, size_t))0, - (void (*)(dvoid *, dvoid *)) 0 )) - { - NSLog(@"FAILED: OCIInitialize()"); - return NO; - } - + if (OCIEnvInit((OCIEnv **)&_oci_env, (ub4)OCI_DEFAULT, (size_t)0, (dvoid **)0)) { NSLog(@"FAILED: OCIEnvInit()"); Index: sope-gdl1/Oracle8/OracleAdaptorChannelController.m =================================================================== --- sope-gdl1/Oracle8/OracleAdaptorChannelController.m (révision 1546) +++ sope-gdl1/Oracle8/OracleAdaptorChannelController.m (copie de travail) @@ -155,7 +155,9 @@ OCILobFreeTemporary([theChannel serviceContext], [theChannel errorHandle], info->value); OCIDescriptorFree((dvoid *)info->value, (ub4)OCI_DTYPE_LOB); } + free(info); } + [theColumns release]; OCIHandleFree(theStatement, OCI_HTYPE_STMT); } Index: sope-mime/NGImap4/NGImap4Connection.m =================================================================== --- sope-mime/NGImap4/NGImap4Connection.m (révision 1546) +++ sope-mime/NGImap4/NGImap4Connection.m (copie de travail) @@ -381,7 +381,7 @@ if (debugCache) [self logWithFormat:@" no folders cached yet .."]; - result = [[self client] list:(onlyFetchInbox ? @"INBOX" : @"*") + result = [[self client] list:(onlyFetchInbox ? @"INBOX" : @"") pattern:@"*"]; if (![[result valueForKey:@"result"] boolValue]) { [self errorWithFormat:@"Could not list mailbox hierarchy!"]; Index: sope-mime/NGImap4/NGImap4ResponseNormalizer.m =================================================================== --- sope-mime/NGImap4/NGImap4ResponseNormalizer.m (révision 1546) +++ sope-mime/NGImap4/NGImap4ResponseNormalizer.m (copie de travail) @@ -648,14 +648,13 @@ enumerator = [_flags objectEnumerator]; cnt = 0; while ((obj = [enumerator nextObject])) { - if (![obj isNotEmpty]) - continue; - - if (![[obj substringToIndex:1] isEqualToString:@"\\"]) - continue; - - objs[cnt] = [obj substringFromIndex:1]; - cnt++; + if ([obj isNotEmpty]) { + if ([obj hasPrefix:@"\\"]) + objs[cnt] = [obj substringFromIndex:1]; + else + objs[cnt] = obj; + cnt++; + } } result = [NSArray arrayWithObjects:objs count:cnt]; if (objs) free(objs); Index: sope-mime/NGImap4/NGImap4ResponseParser.m =================================================================== --- sope-mime/NGImap4/NGImap4ResponseParser.m (révision 1546) +++ sope-mime/NGImap4/NGImap4ResponseParser.m (copie de travail) @@ -84,6 +84,8 @@ static NSDictionary *_parseMultipartBody(NGImap4ResponseParser *self, BOOL isBodyStructure); +static NSArray *_parseLanguages(); + static NSString *_parseBodyString(NGImap4ResponseParser *self, BOOL _convertString); static NSString *_parseBodyDecodeString(NGImap4ResponseParser *self, @@ -111,6 +113,7 @@ static NSNumber *_parseUnsigned(NGImap4ResponseParser *self); static NSString *_parseUntil(NGImap4ResponseParser *self, char _c); static NSString *_parseUntil2(NGImap4ResponseParser *self, char _c1, char _c2); +static BOOL _endsWithCQuote(NSString *_string); static __inline__ NSException *_consumeIfMatch (NGImap4ResponseParser *self, unsigned char _m); @@ -649,12 +652,31 @@ } - (NSString *)_parseQuotedString { + NSMutableString *quotedString; + NSString *tmpString; + BOOL stop; + /* parse a quoted string, eg '"' */ if (_la(self, 0) == '"') { _consume(self, 1); - return _parseUntil(self, '"'); + quotedString = [NSMutableString string]; + stop = NO; + while (!stop) { + tmpString = _parseUntil(self, '"'); + [quotedString appendString: tmpString]; + if(_endsWithCQuote(tmpString)) { + [quotedString deleteSuffix: @"\\"]; + [quotedString appendString: @"\""]; + } + else { + stop = YES; + } + } } - return nil; + else { + quotedString = nil; + } + return quotedString; } - (void)_consumeOptionalSpace { if (_la(self, 0) == ' ') _consume(self, 1); @@ -1185,7 +1207,7 @@ route = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace]; mailbox = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace]; host = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace]; - + if (_la(self, 0) != ')') { [self logWithFormat:@"WARNING: IMAP4 envelope " @"address not properly closed (c0=%c,c1=%c): %@", @@ -1197,6 +1219,7 @@ address = [[NGImap4EnvelopeAddress alloc] initWithPersonalName:pname sourceRoute:route mailbox:mailbox host:host]; + return address; } @@ -1627,6 +1650,29 @@ return _parseBodyDecodeString(self, _convertString, NO /* no decode */); } +static NSArray *_parseLanguages(NGImap4ResponseParser *self) { + NSMutableArray *languages; + NSString *language; + + languages = [NSMutableArray array]; + if (_la(self, 0) == '(') { + while (_la(self, 0) != ')') { + _consume(self,1); + language = _parseBodyString(self, YES); + if ([language length]) + [languages addObject: language]; + } + _consume(self,1); + } + else { + language = _parseBodyString(self, YES); + if ([language length]) + [languages addObject: language]; + } + + return languages; +} + static NSDictionary *_parseBodyParameterList(NGImap4ResponseParser *self) { NSMutableDictionary *list; @@ -1734,10 +1780,11 @@ *encoding, *bodysize; NSDictionary *parameterList; NSMutableDictionary *dict; + NSArray *languages; type = [_parseBodyString(self, YES) lowercaseString]; _consumeIfMatch(self, ' '); - subtype = _parseBodyString(self, YES); + subtype = [_parseBodyString(self, YES) lowercaseString]; _consumeIfMatch(self, ' '); parameterList = _parseBodyParameterList(self); _consumeIfMatch(self, ' '); @@ -1762,7 +1809,8 @@ _consumeIfMatch(self, ' '); [dict setObject:_parseBodyString(self, YES) forKey:@"lines"]; } - else if ([type isEqualToString:@"message"]) { + else if ([type isEqualToString:@"message"] + && [subtype isEqualToString:@"rfc822"]) { if (_la(self, 0) != ')') { _consumeIfMatch(self, ' '); _consumeIfMatch(self, '('); @@ -1805,14 +1853,9 @@ forKey: @"disposition"]; if (_la(self, 0) != ')') { _consume(self,1); - if (_la(self, 0) == '(') { - [dict setObject: _parseBodyParameterList(self) - forKey: @"language"]; - } - else { - [dict setObject: _parseBodyString(self, YES) - forKey: @"language"]; - } + languages = _parseLanguages(self); + if ([languages count]) + [dict setObject: languages forKey: @"languages"]; if (_la(self, 0) != ')') { _consume(self,1); [dict setObject: _parseBodyString(self, YES) @@ -1829,6 +1872,7 @@ static NSDictionary *_parseMultipartBody(NGImap4ResponseParser *self, BOOL isBodyStructure) { NSMutableArray *parts; + NSArray *languages; NSString *kind; NSMutableDictionary *dict; @@ -1854,14 +1898,9 @@ forKey: @"disposition"]; if (_la(self, 0) != ')') { _consume(self,1); - if (_la(self, 0) == '(') { - [dict setObject: _parseBodyParameterList(self) - forKey: @"language"]; - } - else { - [dict setObject: _parseBodyString(self, YES) - forKey: @"language"]; - } + languages = _parseLanguages(self); + if ([languages count]) + [dict setObject: languages forKey: @"languages"]; if (_la(self, 0) != ')') { _consume(self,1); [dict setObject: _parseBodyString(self, YES) @@ -2170,6 +2209,21 @@ } } +static BOOL _endsWithCQuote(NSString *_string){ + unsigned int quoteSlashes; + int pos; + + quoteSlashes = 0; + pos = [_string length] - 1; + while (pos > -1 + && [_string characterAtIndex: pos] == '\\') { + quoteSlashes++; + pos--; + } + + return ((quoteSlashes % 2) == 1); +} + - (NSException *)exceptionForFailedMatch:(unsigned char)_match got:(unsigned char)_avail { Index: sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m =================================================================== --- sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m (révision 1546) +++ sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m (copie de travail) @@ -285,24 +285,16 @@ - (id)parseValue:(id)_data ofHeaderField:(NSString *)_field { // TODO: use UNICODE NSCalendarDate *date = nil; - unsigned char buf[256]; - unsigned char *bytes = buf, *pe; + unsigned char *bytes, *pe; unsigned length = 0; NSTimeZone *tz = nil; char dayOfMonth, monthOfYear, hour, minute, second; short year; BOOL flag; - - if ((length = [_data cStringLength]) > 254) { - [self logWithFormat: - @"header field value to large for date parsing: '%@'(%i)", - _data, length]; - length = 254; - } - - [_data getCString:(char *)buf maxLength:length]; - buf[length] = '\0'; - + + length = [_data length]; + bytes = [_data cStringUsingEncoding: NSASCIIStringEncoding]; + /* remove leading chars (skip to first digit, the day of the month) */ while (length > 0 && (!isdigit(*bytes))) { bytes++; Index: sope-mime/NGMime/NGMimeBodyPart.m =================================================================== --- sope-mime/NGMime/NGMimeBodyPart.m (révision 1546) +++ sope-mime/NGMime/NGMimeBodyPart.m (copie de travail) @@ -31,18 +31,6 @@ return 2; } -static NGMimeType *defaultType = nil; - -+ (void)initialize { - static BOOL isInitialized = NO; - if (!isInitialized) { - isInitialized = YES; - - defaultType = - [[NGMimeType mimeType:@"text/plain; charset=us-ascii"] retain]; - } -} - + (id)bodyPartWithHeader:(NGHashMap *)_header { return [[[self alloc] initWithHeader:_header] autorelease]; } @@ -156,13 +144,12 @@ if (!Fields) Fields = (NGMimeHeaderNames *)[NGMimePartParser headerFieldNames]; - type = [self->header objectForKey:Fields->contentType]; if (![type isKindOfClass:[NGMimeType class]]) type = [NGMimeType mimeType:[type stringValue]]; - return (type != nil ? type : (id)defaultType); + return type; } - (NSString *)contentId { Index: sope-mime/NGMime/NGMimeBodyParser.m =================================================================== --- sope-mime/NGMime/NGMimeBodyParser.m (révision 1546) +++ sope-mime/NGMime/NGMimeBodyParser.m (copie de travail) @@ -67,7 +67,10 @@ if (_data == nil) return nil; ctype = [_part contentType]; - + if (!ctype + && [_d respondsToSelector: @selector(parser:contentTypeOfPart:)]) + ctype = [_d parser: self contentTypeOfPart: _part]; + if (![ctype isKindOfClass:[NGMimeType class]]) ctype = [NGMimeType mimeType:[ctype stringValue]]; Index: sope-mime/NGMime/NGMimePartParser.h =================================================================== --- sope-mime/NGMime/NGMimePartParser.h (révision 1546) +++ sope-mime/NGMime/NGMimePartParser.h (copie de travail) @@ -117,6 +117,7 @@ BOOL parserParseRawBodyDataOfPart:1; BOOL parserBodyParserForPart:1; BOOL parserDecodeBodyOfPart:1; + BOOL parserContentTypeOfPart:1; } delegateRespondsTo; @@ -275,6 +276,9 @@ - (id)parser:(NGMimePartParser *)_parser bodyParserForPart:(id)_part; +- (NGMimeType *)parser:(id)_parser + contentTypeOfPart:(id)_part; + @end /* NSObject(NGMimePartParserDelegate) */ @interface NSObject(NGMimePartParser) Index: sope-mime/NGMime/NGMimePartParser.m =================================================================== --- sope-mime/NGMime/NGMimePartParser.m (révision 1546) +++ sope-mime/NGMime/NGMimePartParser.m (copie de travail) @@ -1091,7 +1091,10 @@ id bodyParser = nil; ctype = [_p contentType]; - + if (!ctype + && self->delegateRespondsTo.parserContentTypeOfPart) + ctype = [self->delegate parser: self contentTypeOfPart: _p]; + contentType = ([ctype isKindOfClass:[NGMimeType class]]) ? ctype : [NGMimeType mimeType:[ctype stringValue]]; Index: sope-core/NGExtensions/FdExt.subproj/NSString+Encoding.m =================================================================== --- sope-core/NGExtensions/FdExt.subproj/NSString+Encoding.m (révision 1546) +++ sope-core/NGExtensions/FdExt.subproj/NSString+Encoding.m (copie de travail) @@ -20,6 +20,8 @@ 02111-1307, USA. */ +#include + #include #include #include "common.h" @@ -81,7 +83,6 @@ #else /* ! NeXT_Foundation_LIBRARY */ - @implementation NSString(Encoding) #if GNUSTEP_BASE_LIBRARY @@ -192,17 +193,17 @@ memcpy(outbuf, _src, _srcLen); *outLen_ = outlen; - + return outbuf; } result = nil; fromEncode = [_fromEncode cString]; toEncode = [_toEncode cString]; - + type = iconv_open(toEncode, fromEncode); inbuf = NULL; outbuf = NULL; - + if ((type == (iconv_t)-1)) { [self logWithFormat:@"%s: Could not handle iconv encoding. FromEncoding:%@" @" to encoding:%@", __PRETTY_FUNCTION__, _fromEncode, _toEncode]; @@ -228,25 +229,25 @@ } else if (errno == EINVAL) { [self logWithFormat:@"Got incomplete multibyte sequence. ToEncode: %@" - @" FromEncode: %@", _toEncode, _fromEncode]; + @" FromEncode: %@", _toEncode, _fromEncode]; if (IconvLogEnabled) [self logWithFormat:@"ByteSequence:\n%s\n", _src]; - + } else if (errno == E2BIG) { [self logWithFormat: - @"Got to small outputbuffer (inbytesleft=%d, outbytesleft=%d, " - @"outlen=%d). ToEncode: %@ FromEncode: %@", - inbytesleft, outbytesleft, outlen, - _toEncode, _fromEncode]; + @"Got to small outputbuffer (inbytesleft=%d, outbytesleft=%d, " + @"outlen=%d). ToEncode: %@ FromEncode: %@", + inbytesleft, outbytesleft, outlen, + _toEncode, _fromEncode]; if (IconvLogEnabled) [self logWithFormat:@"ByteSequence:\n%s\n", _src]; - + goto CLEAR_AND_RETURN; } else { [self logWithFormat:@"Got unexpected error. ToEncode: %@" - @" FromEncode: %@", _toEncode, _fromEncode]; + @" FromEncode: %@", _toEncode, _fromEncode]; goto CLEAR_AND_RETURN; } } @@ -255,45 +256,224 @@ #endif if (type) iconv_close(type); - + *outLen_ = outlen - outbytesleft; - + return outbuf; - + CLEAR_AND_RETURN: if (type) iconv_close(type); - + if (outbuf) { free(outbuf); outbuf = NULL; } return NULL; } -+ (NSString *)stringWithData:(NSData *)_data - usingEncodingNamed:(NSString *)_encoding ++ (int) encodingForCharset: (NSString *) theCharset + convertToNSStringEncoding: (BOOL) shouldConvert { - void *inbuf, *res; - unsigned len, inbufLen; - NSString *result; + // We define some aliases for the string encoding. + static struct { NSString *name; int encoding; BOOL fromCoreFoundation; } encodings[] = { + {@"ascii" ,NSASCIIStringEncoding ,NO}, + {@"us-ascii" ,NSASCIIStringEncoding ,NO}, + {@"default" ,NSASCIIStringEncoding ,NO}, // Ah... spammers. + {@"utf-8" ,NSUTF8StringEncoding ,NO}, + {@"iso-8859-1" ,NSISOLatin1StringEncoding ,NO}, + {@"x-user-defined",NSISOLatin1StringEncoding ,NO}, // To prevent a lame bug in Outlook. + {@"unknown" ,NSISOLatin1StringEncoding ,NO}, // Once more, blame Outlook. + {@"x-unknown" ,NSISOLatin1StringEncoding ,NO}, // To prevent a lame bug in Pine 4.21. + {@"unknown-8bit" ,NSISOLatin1StringEncoding ,NO}, // To prevent a lame bug in Mutt/1.3.28i + {@"0" ,NSISOLatin1StringEncoding ,NO}, // To prevent a lame bug in QUALCOMM Windows Eudora Version 6.0.1.1 + {@"" ,NSISOLatin1StringEncoding ,NO}, // To prevent a lame bug in Ximian Evolution + {@"iso8859_1" ,NSISOLatin1StringEncoding ,NO}, // To prevent a lame bug in Openwave WebEngine + {@"iso-8859-2" ,NSISOLatin2StringEncoding ,NO}, +#ifndef MACOSX + {@"iso-8859-3" ,NSISOLatin3StringEncoding ,NO}, + {@"iso-8859-4" ,NSISOLatin4StringEncoding ,NO}, + {@"iso-8859-5" ,NSISOCyrillicStringEncoding ,NO}, + {@"iso-8859-6" ,NSISOArabicStringEncoding ,NO}, + {@"iso-8859-7" ,NSISOGreekStringEncoding ,NO}, + {@"iso-8859-8" ,NSISOHebrewStringEncoding ,NO}, + {@"iso-8859-9" ,NSISOLatin5StringEncoding ,NO}, + {@"iso-8859-10" ,NSISOLatin6StringEncoding ,NO}, + {@"iso-8859-11" ,NSISOThaiStringEncoding ,NO}, + {@"iso-8859-13" ,NSISOLatin7StringEncoding ,NO}, + {@"iso-8859-14" ,NSISOLatin8StringEncoding ,NO}, + {@"iso-8859-15" ,NSISOLatin9StringEncoding ,NO}, + {@"koi8-r" ,NSKOI8RStringEncoding ,NO}, + {@"big5" ,NSBIG5StringEncoding ,NO}, + {@"gb2312" ,NSGB2312StringEncoding ,NO}, + {@"utf-7" ,NSUTF7StringEncoding ,NO}, + {@"unicode-1-1-utf-7", NSUTF7StringEncoding ,NO}, // To prever a bug (sort of) in MS Hotmail +#endif + {@"windows-1250" ,NSWindowsCP1250StringEncoding ,NO}, + {@"windows-1251" ,NSWindowsCP1251StringEncoding ,NO}, + {@"cyrillic (windows-1251)", NSWindowsCP1251StringEncoding ,NO}, // To prevent a bug in MS Hotmail + {@"windows-1252" ,NSWindowsCP1252StringEncoding ,NO}, + {@"windows-1253" ,NSWindowsCP1253StringEncoding ,NO}, + {@"windows-1254" ,NSWindowsCP1254StringEncoding ,NO}, + {@"iso-2022-jp" ,NSISO2022JPStringEncoding ,NO}, + {@"euc-jp" ,NSJapaneseEUCStringEncoding ,NO}, + }; + + NSString *name; + int i; - if (![_encoding length]) - return nil; + name = [theCharset lowercaseString]; - inbufLen = [_data length]; - inbuf = calloc(sizeof(char), inbufLen + 4); - [_data getBytes:inbuf]; + for (i = 0; i < sizeof(encodings)/sizeof(encodings[0]); i++) + { + if ([name isEqualToString: encodings[i].name]) + { + int enc = encodings[i].encoding; + // Under OS X, we use CoreFoundation if necessary to convert the encoding + // to a NSString encoding. +#ifdef MACOSX + if (encodings[i].fromCoreFoundation) + { + if (shouldConvert) + { + return CFStringConvertEncodingToNSStringEncoding(enc); + } + else + { + return enc; + } + } + else + { + if (!shouldConvert) + { + return CFStringConvertNSStringEncodingToEncoding(enc); + } + else + { + return enc; + } + } +#else + return enc; +#endif + } + } - result = nil; - res = iconv_wrapper(self, inbuf, inbufLen, _encoding, unicharEncoding, &len); - if (res) { - result = [[NSString alloc] initWithCharacters:res length:(len / 2)]; - free(res); res = NULL; - } - if (inbuf) free(inbuf); inbuf = NULL; - return [result autorelease]; +#ifdef MACOSX + // Last resort: try using CoreFoundation... + CFStringEncoding enc; + + enc = CFStringConvertIANACharSetNameToEncoding((CFStringRef)name); + if (kCFStringEncodingInvalidId != enc) + { + if (shouldConvert) + { + return CFStringConvertEncodingToNSStringEncoding(enc); + } + else + { + return enc; + } + } +#endif + + return -1; } ++ (int) encodingForCharset: (NSString *) theCharset +{ + return [self encodingForCharset: theCharset convertToNSStringEncoding: YES]; +} + ++ (NSString *) stringWithData: (NSData *) theData + usingEncodingNamed: (NSString *) theCharset +{ + int encoding; + + if (theData == nil) + { + return nil; + } + +#ifdef MACOSX + encoding = [NSString encodingForCharset: theCharset + convertToNSStringEncoding: NO]; +#else + encoding = [NSString encodingForCharset: theCharset]; +#endif + + if (encoding == -1) + { + NSString *aString; + const char *i_bytes; + char *o_bytes; + + size_t i_length, o_length; + int total_length, ret; + iconv_t conv; + + // Instead of calling cString directly on theCharset, we first try + // to obtain the ASCII string of the data object. + if (!theCharset) + { + return nil; + } + + conv = iconv_open("UTF-8", [[theCharset uppercaseString] cStringUsingEncoding: NSISOLatin1StringEncoding]); + + if ((int)conv < 0) + { + // Let's assume we got US-ASCII here. + return AUTORELEASE([[NSString alloc] initWithData: theData encoding: NSASCIIStringEncoding]); + } + + i_bytes = [theData bytes]; + i_length = [theData length]; + + total_length = o_length = sizeof(unichar)*i_length; + o_bytes = (char *)malloc(o_length); + + if (o_bytes == NULL) return nil; + + while (i_length > 0) + { + ret = iconv(conv, (char **)&i_bytes, &i_length, &o_bytes, &o_length); + + if (ret == (size_t)-1) + { + iconv_close(conv); + + total_length = total_length - o_length; + o_bytes -= total_length; + free(o_bytes); + return nil; + } + } + + total_length = total_length - o_length; + o_bytes -= total_length; + + // If we haven't used all our allocated buffer, we shrink it. + if (o_length > 0) + { + o_bytes = realloc(o_bytes, total_length); + } + + aString = [[NSString alloc] initWithData: [NSData dataWithBytesNoCopy: o_bytes + length: total_length] + encoding: NSUTF8StringEncoding]; + iconv_close(conv); + + return AUTORELEASE(aString); + } + +#ifdef MACOSX + return AUTORELEASE((NSString *)CFStringCreateFromExternalRepresentation(NULL, (CFDataRef)theData, encoding)); +#else + return AUTORELEASE([[NSString alloc] initWithData: theData encoding: encoding]); +#endif +} + - (NSData *)dataUsingEncodingNamed:(NSString *)_encoding { unichar *chars; char *res; Index: sope-core/NGExtensions/ChangeLog =================================================================== --- sope-core/NGExtensions/ChangeLog (révision 1546) +++ sope-core/NGExtensions/ChangeLog (copie de travail) @@ -1,3 +1,10 @@ +2007-11-04 Wolfgang Sourdeau + + * FdExt.subproj/NSString+Encoding.m: replaced the code of + stringWithData:usingEncodingNamed: with the code from + Pantomime/NSString+Extensions.m/stringWithData:charset:, which in + turn was adapted to take the same argument types. + 2007-07-31 Marcus Mueller * FdExt.subproj/NSMethodSignature+misc.m: added warning and bogus Index: sope-appserver/NGObjWeb/GNUmakefile.postamble =================================================================== --- sope-appserver/NGObjWeb/GNUmakefile.postamble (révision 1546) +++ sope-appserver/NGObjWeb/GNUmakefile.postamble (copie de travail) @@ -23,14 +23,20 @@ # install makefiles -after-install :: +after-install :: $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make + +ifneq ($(GNUSTEP_MAKE_VERSION),1.3.0) +after-install :: $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/woapp.make $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/wobundle.make +endif + +$(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make: ngobjweb.make $(MKDIRS) $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/ $(INSTALL_DATA) ngobjweb.make $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make -ifneq ($(GNUSTEP_MAKE_VERSION),1.3.0) -after-install :: +$(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/woapp.make: woapp-gs.make $(INSTALL_DATA) woapp-gs.make \ $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/woapp.make + +$(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/wobundle.make: wobundle-gs.make $(INSTALL_DATA) wobundle-gs.make \ $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/wobundle.make -endif Index: sope-appserver/NGObjWeb/WOContext.m =================================================================== --- sope-appserver/NGObjWeb/WOContext.m (révision 1546) +++ sope-appserver/NGObjWeb/WOContext.m (copie de travail) @@ -64,11 +64,13 @@ static BOOL testNSURLs = NO; static BOOL newCURLStyle = NO; static NSString *WOApplicationSuffix = nil; +static NSURL *redirectURL = nil; + (void)initialize { static BOOL didInit = NO; NSUserDefaults *ud; NSString *cn; + NSString *url; if (didInit) return; @@ -91,6 +93,9 @@ debugCursor = [ud boolForKey:@"WODebugCursor"] ? 1 : 0; debugComponentAwake = [ud boolForKey:@"WODebugComponentAwake"]; WOApplicationSuffix = [[ud stringForKey:@"WOApplicationSuffix"] copy]; + url = [ud stringForKey:@"WOApplicationRedirectURL"]; + if (url != nil) + redirectURL = [NSURL URLWithString: url]; } + (id)contextWithRequest:(WORequest *)_r { @@ -503,6 +508,11 @@ return nil; } + if (redirectURL) { + // Use URL from user defaults (WOApplicationRedirectURL) + return redirectURL; + } + if ((serverURL = [rq headerForKey:@"x-webobjects-server-url"]) == nil) { if ((host = [rq headerForKey:@"host"])) serverURL = [@"http://" stringByAppendingString:host]; Index: sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m =================================================================== --- sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m (révision 1546) +++ sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m (copie de travail) @@ -216,6 +216,12 @@ assocCount++; } } + if (count > 0) { + if ((self->isAbsolute = OWGetProperty(_config, @"absolute"))) { + count--; + assocCount++; + } + } self->rest = _config; Index: sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m =================================================================== --- sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m (révision 1546) +++ sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m (copie de travail) @@ -40,6 +40,7 @@ WOAssociation *string; WOAssociation *target; WOAssociation *disabled; + WOAssociation *isAbsolute; WOElement *template; /* new in WO4: */ @@ -359,6 +360,7 @@ { if ((self = [super initWithName:_name hyperlinkInfo:_info template:_t])) { self->href = _info->href; + self->isAbsolute = _info->isAbsolute; } return self; } @@ -374,6 +376,9 @@ // TODO: we need a binding to disable rewriting! NSRange r; + if ([[self->isAbsolute valueInContext:_ctx] boolValue] == YES) + return NO; + r = [_s rangeOfString:@":"]; if (r.length == 0) return YES; Index: sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.h =================================================================== --- sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.h (révision 1546) +++ sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.h (copie de travail) @@ -41,7 +41,8 @@ WOAssociation *pageName; WOAssociation *actionClass; WOAssociation *directActionName; - + WOAssociation *isAbsolute; + BOOL sidInUrl; /* 'ivar' associations */ Index: sope-appserver/NGObjWeb/SoObjects/SoObject.m =================================================================== --- sope-appserver/NGObjWeb/SoObjects/SoObject.m (révision 1546) +++ sope-appserver/NGObjWeb/SoObjects/SoObject.m (copie de travail) @@ -39,22 +39,34 @@ static int debugLookup = -1; static int debugBaseURL = -1; static int useRelativeURLs = -1; +static int redirectInitted = -1; +static NSURL *redirectURL = nil; + static void _initialize(void) { + NSString *url; + NSUserDefaults *ud; + + ud = [NSUserDefaults standardUserDefaults]; + if (debugLookup == -1) { - debugLookup = [[NSUserDefaults standardUserDefaults] - boolForKey:@"SoDebugKeyLookup"] ? 1 : 0; + debugLookup = [ud boolForKey:@"SoDebugKeyLookup"] ? 1 : 0; NSLog(@"Note(SoObject): SoDebugKeyLookup is enabled!"); } if (debugBaseURL == -1) { - debugBaseURL = [[NSUserDefaults standardUserDefaults] - boolForKey:@"SoDebugBaseURL"] ? 1 : 0; + debugBaseURL = [ud boolForKey:@"SoDebugBaseURL"] ? 1 : 0; NSLog(@"Note(SoObject): SoDebugBaseURL is enabled!"); } if (useRelativeURLs == -1) { - useRelativeURLs = [[NSUserDefaults standardUserDefaults] - boolForKey:@"WOUseRelativeURLs"] ?1:0; + useRelativeURLs = [ud boolForKey:@"WOUseRelativeURLs"] ?1:0; NSLog(@"Note(SoObject): relative base URLs are enabled."); } + if (redirectInitted == -1) { + url = [ud stringForKey:@"WOApplicationRedirectURL"]; + if ([url length]) { + redirectURL = [[NSURL alloc] initWithString: url]; + } + redirectInitted = 1; + } } /* classes */ @@ -318,56 +330,61 @@ rq = [_ctx request]; ms = [[NSMutableString alloc] initWithCapacity:128]; + + if (redirectURL) { + [ms appendString: [redirectURL absoluteString]]; + } + else { + if (!useRelativeURLs) { + port = [[rq headerForKey:@"x-webobjects-server-port"] intValue]; - if (!useRelativeURLs) { - port = [[rq headerForKey:@"x-webobjects-server-port"] intValue]; - - /* this is actually a bug in Apache */ - if (port == 0) { - static BOOL didWarn = NO; - if (!didWarn) { - [self warnWithFormat:@"(%s:%i): got an empty port from Apache!", - __PRETTY_FUNCTION__, __LINE__]; - didWarn = YES; + /* this is actually a bug in Apache */ + if (port == 0) { + static BOOL didWarn = NO; + if (!didWarn) { + [self warnWithFormat:@"(%s:%i): got an empty port from Apache!", + __PRETTY_FUNCTION__, __LINE__]; + didWarn = YES; + } + port = 80; } - port = 80; - } - if ((tmp = [rq headerForKey:@"host"]) != nil) { - /* check whether we have a host header with port */ - if ([tmp rangeOfString:@":"].length == 0) - tmp = nil; - } - if (tmp != nil) { /* we have a host header with port */ - isHTTPS = - [[rq headerForKey:@"x-webobjects-server-url"] hasPrefix:@"https"]; - [ms appendString:isHTTPS ? @"https://" : @"http://"]; - [ms appendString:tmp]; - } - else if ((tmp = [rq headerForKey:@"x-webobjects-server-url"]) != nil) { - /* sometimes the URL is just wrong! (suggests port 80) */ - if ([tmp hasSuffix:@":0"] && [tmp length] > 2) { // TODO: bad bad bad - [self warnWithFormat:@"%s: got incorrect URL from Apache: '%@'", - __PRETTY_FUNCTION__, tmp]; - tmp = [tmp substringToIndex:([tmp length] - 2)]; + if ((tmp = [rq headerForKey:@"host"]) != nil) { + /* check whether we have a host header with port */ + if ([tmp rangeOfString:@":"].length == 0) + tmp = nil; } - else if ([tmp hasSuffix:@":443"] && [tmp hasPrefix:@"http://"]) { - /* see OGo bug #1435, Debian Apache hack */ - [self warnWithFormat:@"%s: got 'http' protocol but 443 port, " - @"assuming Debian/Apache bug (OGo #1435): '%@'", - __PRETTY_FUNCTION__, tmp]; - tmp = [tmp substringWithRange:NSMakeRange(4, [tmp length] - 4 - 4)]; - tmp = [@"https" stringByAppendingString:tmp]; + if (tmp != nil) { /* we have a host header with port */ + isHTTPS = + [[rq headerForKey:@"x-webobjects-server-url"] hasPrefix:@"https"]; + [ms appendString:isHTTPS ? @"https://" : @"http://"]; + [ms appendString:tmp]; } - [ms appendString:tmp]; - } - else { - // TODO: isHTTPS always no in this case? - [ms appendString:isHTTPS ? @"https://" : @"http://"]; + else if ((tmp = [rq headerForKey:@"x-webobjects-server-url"]) != nil) { + /* sometimes the URL is just wrong! (suggests port 80) */ + if ([tmp hasSuffix:@":0"] && [tmp length] > 2) { // TODO: bad bad bad + [self warnWithFormat:@"%s: got incorrect URL from Apache: '%@'", + __PRETTY_FUNCTION__, tmp]; + tmp = [tmp substringToIndex:([tmp length] - 2)]; + } + else if ([tmp hasSuffix:@":443"] && [tmp hasPrefix:@"http://"]) { + /* see OGo bug #1435, Debian Apache hack */ + [self warnWithFormat:@"%s: got 'http' protocol but 443 port, " + @"assuming Debian/Apache bug (OGo #1435): '%@'", + __PRETTY_FUNCTION__, tmp]; + tmp = [tmp substringWithRange:NSMakeRange(4, [tmp length] - 4 - 4)]; + tmp = [@"https" stringByAppendingString:tmp]; + } + [ms appendString:tmp]; + } + else { + // TODO: isHTTPS always no in this case? + [ms appendString:isHTTPS ? @"https://" : @"http://"]; - [ms appendString:[rq headerForKey:@"x-webobjects-server-name"]]; - if ((isHTTPS ? (port != 443) : (port != 80)) && port != 0) - [ms appendFormat:@":%i", port]; + [ms appendString:[rq headerForKey:@"x-webobjects-server-name"]]; + if ((isHTTPS ? (port != 443) : (port != 80)) && port != 0) + [ms appendFormat:@":%i", port]; + } } } Index: sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m =================================================================== --- sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m (révision 1546) +++ sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m (copie de travail) @@ -31,6 +31,7 @@ #include #include #include +#include #include "common.h" #include @@ -1016,6 +1017,12 @@ - (void)parser:(NGMimePartParser *)_parser didParseHeader:(NGHashMap *)_header { } +- (NGMimeType *)parser:(id)_parser + contentTypeOfPart:(id)_part +{ + return [NGMimeType mimeType: @"text/plain; charset=utf-8"]; +} + @end /* WOHttpAdaptor */ @implementation WOCoreApplication(SimpleParserSelection)