diff --git a/PantomimeFramework/PantomimeFramework/CWPart.h b/PantomimeFramework/PantomimeFramework/CWPart.h index 0dfeab9..53581bc 100644 --- a/PantomimeFramework/PantomimeFramework/CWPart.h +++ b/PantomimeFramework/PantomimeFramework/CWPart.h @@ -1,24 +1,24 @@ /* -** CWPart.h -** -** Copyright (c) 2001-2007 -** -** Author: Ludovic Marcotte -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ + ** CWPart.h + ** + ** Copyright (c) 2001-2007 + ** + ** Author: Ludovic Marcotte + ** + ** This library is free software; you can redistribute it and/or + ** modify it under the terms of the GNU Lesser General Public + ** License as published by the Free Software Foundation; either + ** version 2.1 of the License, or (at your option) any later version. + ** + ** This library is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + ** Lesser General Public License for more details. + ** + ** You should have received a copy of the GNU Lesser General Public + ** License along with this library; if not, write to the Free Software + ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ #ifndef _Pantomime_H_CWPart #define _Pantomime_H_CWPart @@ -32,16 +32,16 @@ #import /*! - @class CWPart - @discussion This class defines what Internet messages are composed of. - An Internet message is composed of various parts which can - be text parts, images, PDF documents and so on. Even a message - is a part, with additional headers (like "From:", "Subject:" - and so on). CWMessage is a superclass of CWPart. -*/ + @class CWPart + @discussion This class defines what Internet messages are composed of. + An Internet message is composed of various parts which can + be text parts, images, PDF documents and so on. Even a message + is a part, with additional headers (like "From:", "Subject:" + and so on). CWMessage is a superclass of CWPart. + */ @interface CWPart : NSObject { - @protected +@protected NSMutableDictionary *_parameters; NSMutableDictionary *_headers; NSString *_defaultCharset; @@ -52,127 +52,127 @@ } /*! - @method initWithData: - @discussion This method is used to initialize the CWPart instance - with the specified data. It splits the header - part with the content part and calls -setHeadersFromData: - with the header part and CWMIMEUtility: +setContentFromRawSource: inPart: - with the content part. This method will recursively go in - sub-parts (if needed) and initilize them also. - @param theData The bytes to use. - @result A CWPart instance, nil on error. -*/ + @method initWithData: + @discussion This method is used to initialize the CWPart instance + with the specified data. It splits the header + part with the content part and calls -setHeadersFromData: + with the header part and CWMIMEUtility: +setContentFromRawSource: inPart: + with the content part. This method will recursively go in + sub-parts (if needed) and initilize them also. + @param theData The bytes to use. + @result A CWPart instance, nil on error. + */ - (id _Nullable) initWithData: (NSData * _Nonnull) theData; /*! - @method initWithData: charset: - @discussion This method acts like -initWithData: but it uses - theCharset instead of the Part's charset - (found in theData). - @param theData The bytes to use. - @param theCharset The charset to force. - @result A CWPart instance, nil on error. -*/ + @method initWithData: charset: + @discussion This method acts like -initWithData: but it uses + theCharset instead of the Part's charset + (found in theData). + @param theData The bytes to use. + @param theCharset The charset to force. + @result A CWPart instance, nil on error. + */ - (id _Nullable) initWithData: (NSData * _Nonnull) theData - charset: (NSString * _Nonnull) theCharset; + charset: (NSString * _Nonnull) theCharset; /*! - @method setHeadersFromData: - @discussion This method initalize all the headers of a part - from the raw data source. It replaces previously - defined values of headers found in theHeaders. - @param theHeaders The bytes to use. -*/ + @method setHeadersFromData: + @discussion This method initalize all the headers of a part + from the raw data source. It replaces previously + defined values of headers found in theHeaders. + @param theHeaders The bytes to use. + */ - (void) setHeadersFromData: (NSData * _Nonnull) theHeaders; /*! - @method contentType - @discussion This method is used to get the value of the - receiver's "Content-Type" header. If none is - specified, nil will be returned. It's up to the - callee to use whatever charset it wants. Section - 5.2 or RFC2045 recommends to use "text/plain" in - this case. - @result The value. If none was set, nil will - be returned. -*/ + @method contentType + @discussion This method is used to get the value of the + receiver's "Content-Type" header. If none is + specified, nil will be returned. It's up to the + callee to use whatever charset it wants. Section + 5.2 or RFC2045 recommends to use "text/plain" in + this case. + @result The value. If none was set, nil will + be returned. + */ - (NSString * _Nullable) contentType; /*! - @method setContentType: - @discussion This method is used to set the value of - the receiver's "Content-Type" header. - @param theContentType The "Content-Type" value. -*/ + @method setContentType: + @discussion This method is used to set the value of + the receiver's "Content-Type" header. + @param theContentType The "Content-Type" value. + */ - (void) setContentType: (NSString * _Nullable) theContentType; /*! - @method contentID - @discussion This method is used to get the value of the - receiver's "Content-ID" header. - @result The value. If none was set, nil will - be returned. -*/ + @method contentID + @discussion This method is used to get the value of the + receiver's "Content-ID" header. + @result The value. If none was set, nil will + be returned. + */ - (NSString * _Nullable) contentID; /*! - @method setContentID: - @discussion This method is used to set the value of - the receiver's "Content-ID" header. - @param theContentID The "Content-ID" value. -*/ + @method setContentID: + @discussion This method is used to set the value of + the receiver's "Content-ID" header. + @param theContentID The "Content-ID" value. + */ - (void) setContentID: (NSString * _Nullable) theContentID; - -/*! - @method contentDescription - @discussion This method is used to get the value of the - receiver's "Content-Description" header. - @result The value. If none was set, nil will - be returned. -*/ + +/*! + @method contentDescription + @discussion This method is used to get the value of the + receiver's "Content-Description" header. + @result The value. If none was set, nil will + be returned. + */ - (NSString * _Nullable) contentDescription; /*! - @method setContentDescription: - @discussion This method is used to set the value of - the receiver's "Content-Description" header. - @param theContentDescription The "Content-Description" value. -*/ + @method setContentDescription: + @discussion This method is used to set the value of + the receiver's "Content-Description" header. + @param theContentDescription The "Content-Description" value. + */ - (void) setContentDescription: (NSString * _Nullable) theContentDescription; /*! - @method contentDisposition - @discussion This method is used to get the value of the - receiver's "Content-Disposition" header. - @result The value. If none was set, PantomimeInlineDisposition - will be returned. -*/ + @method contentDisposition + @discussion This method is used to get the value of the + receiver's "Content-Disposition" header. + @result The value. If none was set, PantomimeInlineDisposition + will be returned. + */ - (PantomimeContentDisposition) contentDisposition; /*! - @method setContentDisposition: - @discussion This method is used to set the value of - the receiver's "Content-Disposition" header. - @param theContentDisposition The "Content-Disposition" value. -*/ + @method setContentDisposition: + @discussion This method is used to set the value of + the receiver's "Content-Disposition" header. + @param theContentDisposition The "Content-Disposition" value. + */ - (void) setContentDisposition: (PantomimeContentDisposition) theContentDisposition; /*! - @method contentTransferEncoding - @discussion This method is used to get the value of the - receiver's "Content-Transfer-Encoding" header. - @result The value. If none was set, PantomimeEncodingNone - will be returned. -*/ + @method contentTransferEncoding + @discussion This method is used to get the value of the + receiver's "Content-Transfer-Encoding" header. + @result The value. If none was set, PantomimeEncodingNone + will be returned. + */ - (PantomimeEncoding) contentTransferEncoding; /*! - @method setContentTransferEndocing: - @discussion This method is used to set the value of - the receiver's "Content-Transfer-Encoding" header. - @param theEncoding The "Content-Transfer-Encoding" value. Accepted - values are part of the PantomimeEncoding enum. -*/ + @method setContentTransferEndocing: + @discussion This method is used to set the value of + the receiver's "Content-Transfer-Encoding" header. + @param theEncoding The "Content-Transfer-Encoding" value. Accepted + values are part of the PantomimeEncoding enum. + */ - (void) setContentTransferEncoding: (PantomimeEncoding) theEncoding; /** @@ -191,215 +191,215 @@ - (void)setFilename:(NSString *_Nullable)theFilename; /*! - @method format - @discussion This method is used to obtain the format of the receiver. - Possible values are part of the PantomimeMessageFormat. - See RFC 2646 for a detailed description of the "flowed" format. - @result The format, PantomimeFormatUnknown if no value was previously set. -*/ + @method format + @discussion This method is used to obtain the format of the receiver. + Possible values are part of the PantomimeMessageFormat. + See RFC 2646 for a detailed description of the "flowed" format. + @result The format, PantomimeFormatUnknown if no value was previously set. + */ - (PantomimeMessageFormat) format; /*! - @method setFormat: - @discussion This method is used to set the format of the receiver. - Accepted values are part of the PantomimeMessageFormat enum. - @param theFormat The format to use. -*/ + @method setFormat: + @discussion This method is used to set the format of the receiver. + Accepted values are part of the PantomimeMessageFormat enum. + @param theFormat The format to use. + */ - (void) setFormat: (PantomimeMessageFormat) theFormat; /*! - @method lineLength - @discussion This method is used to return the maximum length that - a line can use in a text part. - @result The length, 0 if not defined. -*/ + @method lineLength + @discussion This method is used to return the maximum length that + a line can use in a text part. + @result The length, 0 if not defined. + */ - (NSUInteger) lineLength; /*! - @method setLineLength: - @discussion This method is used to set the maximum length of a - line that can be used for a text part. - @param theLineLength The length. -*/ + @method setLineLength: + @discussion This method is used to set the maximum length of a + line that can be used for a text part. + @param theLineLength The length. + */ - (void) setLineLength: (int) theLineLength; /*! - @method isMIMEType: subType: - @discussion This method is used to verify if the receiver matches - a specific MIME type. The "*" wildcard can be used - for the sub-type. - @param thePrimaryType The left part of the MIME type. - @param theSubType The right part of the MIME type. - @result YES if it matches, NO otherwise. -*/ + @method isMIMEType: subType: + @discussion This method is used to verify if the receiver matches + a specific MIME type. The "*" wildcard can be used + for the sub-type. + @param thePrimaryType The left part of the MIME type. + @param theSubType The right part of the MIME type. + @result YES if it matches, NO otherwise. + */ - (BOOL) isMIMEType: (NSString * _Nonnull) thePrimaryType subType: (NSString * _Nonnull) theSubType; /*! - @method content - @discussion This method is used to obtain the decoded content - of the receiver. The returned value can be a NSString - instance, a NSData instance, a CWMIMEMultipart instance - or a CWMessage instance. - @result The decoded content of the part. -*/ + @method content + @discussion This method is used to obtain the decoded content + of the receiver. The returned value can be a NSString + instance, a NSData instance, a CWMIMEMultipart instance + or a CWMessage instance. + @result The decoded content of the part. + */ - (NSObject * _Nullable) content; /*! - @method setContent: - @discussion This method is used to set the content of the receiver. - The content will later be correctly encoded before the - message is submitted or saved on disk (using -dataValue). - Accepted values are instances of NSData, CWMIMEMultipart - or CWMessage otherwise, a NSInvalidArgumentException - will be thrown. - @param theContent The content of the part. -*/ + @method setContent: + @discussion This method is used to set the content of the receiver. + The content will later be correctly encoded before the + message is submitted or saved on disk (using -dataValue). + Accepted values are instances of NSData, CWMIMEMultipart + or CWMessage otherwise, a NSInvalidArgumentException + will be thrown. + @param theContent The content of the part. + */ - (void) setContent: (NSObject * _Nullable) theContent; /*! - @method size - @discussion This method is used to obtain the receiver's size - (total number of bytes of its raw representation). - @result The size of the receiver. -*/ + @method size + @discussion This method is used to obtain the receiver's size + (total number of bytes of its raw representation). + @result The size of the receiver. + */ - (long) size; /*! - @method setSize: - @discussion This method is used to set the receiver's size. - @param theSize The value of the size. -*/ + @method setSize: + @discussion This method is used to set the receiver's size. + @param theSize The value of the size. + */ - (void) setSize: (NSInteger) theSize; /*! - @method dataValue - @discussion This method is used to encoded the receiver's using - the MIME standard before it is ready for submisssion - (using a Transport method) or being saved on disk. - The CWMessage class overwrites this method in order - to add Message-specific headers such as "From", - "Subject" and so on. - @result The encoded CWPart instance, as a NSData instance. -*/ + @method dataValue + @discussion This method is used to encoded the receiver's using + the MIME standard before it is ready for submisssion + (using a Transport method) or being saved on disk. + The CWMessage class overwrites this method in order + to add Message-specific headers such as "From", + "Subject" and so on. + @result The encoded CWPart instance, as a NSData instance. + */ - (NSData * _Nullable)dataValue; /*! - @method boundary - @discussion This method is used to get the boundary that separates - parts that compose a multipart composite part. - @result The boundary as a NSData instance, nil if none was set. -*/ + @method boundary + @discussion This method is used to get the boundary that separates + parts that compose a multipart composite part. + @result The boundary as a NSData instance, nil if none was set. + */ - (NSData * _Nullable) boundary; /*! - @method setBoundary: - @discussion This method is used to set the boundary used to separate - parts that compose a multipart composite part message. - @param theBoundary The value of the boundary. -*/ + @method setBoundary: + @discussion This method is used to set the boundary used to separate + parts that compose a multipart composite part message. + @param theBoundary The value of the boundary. + */ - (void) setBoundary: (NSData * _Nullable) theBoundary; /*! - @method protocol - @discussion This method is used to obtain the value of the "protocol" - parameter found in some Content-Type headers. This parameter - is often present in PGP encoded messages. - @result The value of the "protocol" parameter, nil if none was set. -*/ + @method protocol + @discussion This method is used to obtain the value of the "protocol" + parameter found in some Content-Type headers. This parameter + is often present in PGP encoded messages. + @result The value of the "protocol" parameter, nil if none was set. + */ - (NSData * _Nullable) protocol; /*! - @method setProtocol: - @discussion This method is used to set the value of the "protocol" - parameter. This parameter will be added to the ones - found in the Content-Type header in -dataValue. - @param theProtocol The value of the "protocol" parameter. -*/ + @method setProtocol: + @discussion This method is used to set the value of the "protocol" + parameter. This parameter will be added to the ones + found in the Content-Type header in -dataValue. + @param theProtocol The value of the "protocol" parameter. + */ - (void) setProtocol: (NSData * _Nullable) theProtocol; /*! - @method charset - @discussion This method is used to obtain the value of the "charset" - parameter found in the Content-Type header. - @result The value of the "charset" parameter, "us-ascii" if none was set. -*/ + @method charset + @discussion This method is used to obtain the value of the "charset" + parameter found in the Content-Type header. + @result The value of the "charset" parameter, "us-ascii" if none was set. + */ - (NSString * _Nullable) charset; /*! - @method setCharset: - @discussion This method is used to set the value of the "charset" parameter - found in the Content-Type header. - @param theCharset The charset to use. -*/ + @method setCharset: + @discussion This method is used to set the value of the "charset" parameter + found in the Content-Type header. + @param theCharset The charset to use. + */ - (void) setCharset: (NSString * _Nullable) theCharset; /*! - @method defaultCharset - @discussion This method is used to get the charset that will be - enforced for usage when decoding the part. - @result The enforced charset. -*/ + @method defaultCharset + @discussion This method is used to get the charset that will be + enforced for usage when decoding the part. + @result The enforced charset. + */ - (NSString * _Nullable) defaultCharset; /*! - @method setDefaultCharset: - @discussion This method is used to set the charset that will be - enforced for usage when the part is being decoded. - @param theCharset The charset to force. -*/ + @method setDefaultCharset: + @discussion This method is used to set the charset that will be + enforced for usage when the part is being decoded. + @param theCharset The charset to force. + */ - (void) setDefaultCharset: (NSString * _Nullable) theCharset; /*! - @method parameterForKey: - @discussion This method is used to obtain a parameter value - based on its name. The name serves as the key. - Parameters are only part of the Content-Type - header field.They are NOT part of the - Content-Disposition header. - @param theKey The key for which the value will be returned. - @result The parameter value, nil if non-existent. -*/ + @method parameterForKey: + @discussion This method is used to obtain a parameter value + based on its name. The name serves as the key. + Parameters are only part of the Content-Type + header field.They are NOT part of the + Content-Disposition header. + @param theKey The key for which the value will be returned. + @result The parameter value, nil if non-existent. + */ - (id _Nullable) parameterForKey: (NSString * _Nullable) theKey; /*! - @method setPrameter:forKey: - @discussion This method is used to set a parameter value - based on its name. The name serves as the key. - Parameters are only part of the Content-Type - header field. They are NOT part of the - Content-Disposition header. - @param theParameter The value of the parameter. A nil value - will remove any existing defined value - for the specified key, - @param theKey The key for which the value will be set. -*/ + @method setPrameter:forKey: + @discussion This method is used to set a parameter value + based on its name. The name serves as the key. + Parameters are only part of the Content-Type + header field. They are NOT part of the + Content-Disposition header. + @param theParameter The value of the parameter. A nil value + will remove any existing defined value + for the specified key, + @param theKey The key for which the value will be set. + */ - (void) setParameter: (NSString * _Nullable) theParameter forKey: (NSString * _Nonnull) theKey; /*! - @method allHeaders - @discussion This method is used to return all header names / values. - @result The NSDictionary holding everything. -*/ + @method allHeaders + @discussion This method is used to return all header names / values. + @result The NSDictionary holding everything. + */ - (NSDictionary * _Nonnull) allHeaders; /*! - @method headerValueForName: - @discussion This method is used to obtain the value - of the header specified by theName. The search - is performed in a case-insensitive way. - @param theName The name of the header. For example, it could be "Date". - @result The value of the header or nil if not found. -*/ + @method headerValueForName: + @discussion This method is used to obtain the value + of the header specified by theName. The search + is performed in a case-insensitive way. + @param theName The name of the header. For example, it could be "Date". + @result The value of the header or nil if not found. + */ - (id _Nullable) headerValueForName: (NSString * _Nonnull) theName; /*! - @method setHeaders: - @discussion This method is used to add the headers of - theHeaders to the list of headers - of the receiver. - @param theHeaders The headers to add. -*/ + @method setHeaders: + @discussion This method is used to add the headers of + theHeaders to the list of headers + of the receiver. + @param theHeaders The headers to add. + */ - (void) setHeaders: (NSDictionary * _Nonnull) theHeaders; @end diff --git a/pantomime-lib/Framework/Pantomime/CWIMAPStore+Protected.m b/pantomime-lib/Framework/Pantomime/CWIMAPStore+Protected.m index 8036dca..e2d781c 100644 --- a/pantomime-lib/Framework/Pantomime/CWIMAPStore+Protected.m +++ b/pantomime-lib/Framework/Pantomime/CWIMAPStore+Protected.m @@ -205,7 +205,7 @@ [self bulkWriteData:@[self.currentQueueObject.tag, [NSData dataWithBytes: " " length: 1], - [self.currentQueueObject.arguments dataUsingEncoding: _defaultCStringEncoding], + [self.currentQueueObject.arguments dataUsingEncoding: _defaultStringEncoding], _crlf]]; PERFORM_SELECTOR_2(_delegate, @selector(commandSent:), @"PantomimeCommandSent", [NSNumber numberWithInt: _lastCommand], @"Command"); diff --git a/pantomime-lib/Framework/Pantomime/CWIMAPStore.m b/pantomime-lib/Framework/Pantomime/CWIMAPStore.m index c6af348..d812769 100644 --- a/pantomime-lib/Framework/Pantomime/CWIMAPStore.m +++ b/pantomime-lib/Framework/Pantomime/CWIMAPStore.m @@ -1490,7 +1490,7 @@ static inline int has_literal(char *buf, NSUInteger c) aString = [[NSString alloc] initWithData: [[aString dataUsingEncoding: NSASCIIStringEncoding] encodeBase64WithLineLength: 0] encoding: NSASCIIStringEncoding]; - [self bulkWriteData:@[[aString dataUsingEncoding: _defaultCStringEncoding], + [self bulkWriteData:@[[aString dataUsingEncoding: _defaultStringEncoding], _crlf]]; RELEASE(aMD5); RELEASE(aString); @@ -1634,7 +1634,7 @@ static inline int has_literal(char *buf, NSUInteger c) NSData *aData; aData = [_responsesFromServer objectAtIndex: 0]; - aString = [[NSString alloc] initWithData: aData encoding: _defaultCStringEncoding]; + aString = [[NSString alloc] initWithData: aData encoding: _defaultStringEncoding]; [_capabilities addObjectsFromArray: [[aString substringFromIndex: 13] componentsSeparatedByString: @" "]]; RELEASE(aString); @@ -2405,7 +2405,7 @@ static inline int has_literal(char *buf, NSUInteger c) NSUInteger len; aString = [[NSString alloc] initWithData: [_responsesFromServer lastObject] - encoding: _defaultCStringEncoding]; + encoding: _defaultStringEncoding]; if (!aString) { diff --git a/pantomime-lib/Framework/Pantomime/CWMessage.m b/pantomime-lib/Framework/Pantomime/CWMessage.m index a59a809..2d6e166 100644 --- a/pantomime-lib/Framework/Pantomime/CWMessage.m +++ b/pantomime-lib/Framework/Pantomime/CWMessage.m @@ -1,24 +1,24 @@ /* -** CWMessage.m -** -** Copyright (c) 2001-2007 -** -** Author: Ludovic Marcotte -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ + ** CWMessage.m + ** + ** Copyright (c) 2001-2007 + ** + ** Author: Ludovic Marcotte + ** + ** This library is free software; you can redistribute it and/or + ** modify it under the terms of the GNU Lesser General Public + ** License as published by the Free Software Foundation; either + ** version 2.1 of the License, or (at your option) any later version. + ** + ** This library is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + ** Lesser General Public License for more details. + ** + ** You should have received a copy of the GNU Lesser General Public + ** License along with this library; if not, write to the Free Software + ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ #import @@ -66,8 +66,8 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; - (NSString *) _computeBaseSubject; - (void) _extractText: (NSMutableData *) theMutableData - part: (id) thePart - quote: (BOOL *) theBOOL; + part: (id) thePart + quote: (BOOL *) theBOOL; - (NSData *) _formatRecipientsWithType: (int) theType; @end @@ -83,26 +83,26 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // + (void) initialize { - if (atLeastOneSpaceRegex == nil) + if (atLeastOneSpaceRegex == nil) { - NSString *blobChar = @"[^][]"; - NSString *subjTrailer = @"(\\(fwd\\))| "; - NSString *subjFwdHdr = @"\\[fwd:"; - NSString *subjFwdTrl = @"\\]"; - NSString *subjBlob = [NSString stringWithFormat:@"\\[(%@)*\\] *", blobChar]; - NSString *subjReFwd = [NSString stringWithFormat:@"((re)|(fwd?)) *(%@)?:", subjBlob]; - NSString *subjLeader = [NSString stringWithFormat:@"((%@)*%@)| ", subjBlob, subjReFwd]; - - atLeastOneSpaceRegex = [[CWRegEx alloc] initWithPattern: @"[[:space:]]+" - flags: REG_EXTENDED|REG_ICASE]; - suffixSubjTrailerRegex = [[CWRegEx alloc] initWithPattern: [NSString stringWithFormat:@"(%@)*$", subjTrailer] - flags: REG_EXTENDED|REG_ICASE]; - prefixSubjLeaderRegex = [[CWRegEx alloc] initWithPattern: [NSString stringWithFormat:@"^(%@)", subjLeader] - flags: REG_EXTENDED|REG_ICASE]; - prefixSubjBlobRegex = [[CWRegEx alloc] initWithPattern: [NSString stringWithFormat:@"^(%@)", subjBlob] - flags: REG_EXTENDED|REG_ICASE]; - prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = [[CWRegEx alloc] initWithPattern: [NSString stringWithFormat:@"^(%@)(.*)(%@)$", subjFwdHdr, subjFwdTrl] - flags: REG_EXTENDED|REG_ICASE]; + NSString *blobChar = @"[^][]"; + NSString *subjTrailer = @"(\\(fwd\\))| "; + NSString *subjFwdHdr = @"\\[fwd:"; + NSString *subjFwdTrl = @"\\]"; + NSString *subjBlob = [NSString stringWithFormat:@"\\[(%@)*\\] *", blobChar]; + NSString *subjReFwd = [NSString stringWithFormat:@"((re)|(fwd?)) *(%@)?:", subjBlob]; + NSString *subjLeader = [NSString stringWithFormat:@"((%@)*%@)| ", subjBlob, subjReFwd]; + + atLeastOneSpaceRegex = [[CWRegEx alloc] initWithPattern: @"[[:space:]]+" + flags: REG_EXTENDED|REG_ICASE]; + suffixSubjTrailerRegex = [[CWRegEx alloc] initWithPattern: [NSString stringWithFormat:@"(%@)*$", subjTrailer] + flags: REG_EXTENDED|REG_ICASE]; + prefixSubjLeaderRegex = [[CWRegEx alloc] initWithPattern: [NSString stringWithFormat:@"^(%@)", subjLeader] + flags: REG_EXTENDED|REG_ICASE]; + prefixSubjBlobRegex = [[CWRegEx alloc] initWithPattern: [NSString stringWithFormat:@"^(%@)", subjBlob] + flags: REG_EXTENDED|REG_ICASE]; + prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = [[CWRegEx alloc] initWithPattern: [NSString stringWithFormat:@"^(%@)(.*)(%@)$", subjFwdHdr, subjFwdTrl] + flags: REG_EXTENDED|REG_ICASE]; } } @@ -112,25 +112,25 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (id) init { - self = [super init]; + self = [super init]; + + [CWMessage setVersion: currentMessageVersion]; - [CWMessage setVersion: currentMessageVersion]; - - _recipients = [[NSMutableArray alloc] init]; - _flags = [[CWFlags alloc] init]; - _initialized = NO; - _references = nil; - _folder = nil; + _recipients = [[NSMutableArray alloc] init]; + _flags = [[CWFlags alloc] init]; + _initialized = NO; + _references = nil; + _folder = nil; - // By default, we want the subclass's rawSource method to be called so we set our - // rawSource ivar to nil. If it's not nil (ONLY set in initWithData) it'll be returned, - // for performances improvements. - _rawSource = nil; + // By default, we want the subclass's rawSource method to be called so we set our + // rawSource ivar to nil. If it's not nil (ONLY set in initWithData) it'll be returned, + // for performances improvements. + _rawSource = nil; - // We initialize our dictionary holding all extra properties a message might have - _properties = [[NSMutableDictionary alloc] init]; - - return self; + // We initialize our dictionary holding all extra properties a message might have + _properties = [[NSMutableDictionary alloc] init]; + + return self; } @@ -139,25 +139,25 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (id) initWithData: (NSData *) theData { - self = [super initWithData: theData]; + self = [super initWithData: theData]; - // Part: -initWithData could fail. We return nil if it does. - if (!self) + // Part: -initWithData could fail. We return nil if it does. + if (!self) { - return nil; + return nil; } - // - // We can tell now that this message is fully initialized - // NOTE: We must NOT call [self setInitialized: YES] since - // it will call the method from the subclass and may do - // extremely weird things. - _initialized = YES; + // + // We can tell now that this message is fully initialized + // NOTE: We must NOT call [self setInitialized: YES] since + // it will call the method from the subclass and may do + // extremely weird things. + _initialized = YES; - // We set our rawSource ivar for performance reasons - [self setRawSource: theData]; + // We set our rawSource ivar for performance reasons + [self setRawSource: theData]; - return self; + return self; } @@ -165,10 +165,10 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // // - (id) initWithData: (NSData *) theData - charset: (NSString *) theCharset + charset: (NSString *) theCharset { - [self setDefaultCharset: theCharset]; - return [self initWithData: theData]; + [self setDefaultCharset: theCharset]; + return [self initWithData: theData]; } @@ -177,9 +177,9 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (id) initWithHeadersFromData: (NSData *) theHeaders { - self = [self init]; - [self setHeadersFromData: theHeaders]; - return self; + self = [self init]; + [self setHeadersFromData: theHeaders]; + return self; } @@ -188,9 +188,9 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (id) initWithHeaders: (NSDictionary *) theHeaders { - self = [self init]; - [self setHeaders: theHeaders]; - return self; + self = [self init]; + [self setHeaders: theHeaders]; + return self; } @@ -199,13 +199,13 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) dealloc { - RELEASE(_recipients); - RELEASE(_properties); - RELEASE(_references); - RELEASE(_rawSource); - RELEASE(_flags); - - //[super dealloc]; + RELEASE(_recipients); + RELEASE(_properties); + RELEASE(_references); + RELEASE(_rawSource); + RELEASE(_flags); + + //[super dealloc]; } @@ -214,22 +214,22 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) encodeWithCoder: (NSCoder *) theCoder { - // Must also encode Part's superclass - [super encodeWithCoder: theCoder]; + // Must also encode Part's superclass + [super encodeWithCoder: theCoder]; - [CWMessage setVersion: currentMessageVersion]; + [CWMessage setVersion: currentMessageVersion]; - [theCoder encodeObject: [self originationDate]]; // Date - [theCoder encodeObject: [self from]]; // From - [theCoder encodeObject: _recipients]; // To and Cc (Bcc, at worst) - [theCoder encodeObject: [self subject]]; // Subject - [theCoder encodeObject: [self messageID]]; // Message-ID - [theCoder encodeObject: [self MIMEVersion]]; // MIME-Version - [theCoder encodeObject: _references]; // References - [theCoder encodeObject: [self inReplyTo]]; // In-Reply-To - - [theCoder encodeObject: [NSNumber numberWithInteger: _message_number]]; // Message number - [theCoder encodeObject: _flags]; // Message flags + [theCoder encodeObject: [self originationDate]]; // Date + [theCoder encodeObject: [self from]]; // From + [theCoder encodeObject: _recipients]; // To and Cc (Bcc, at worst) + [theCoder encodeObject: [self subject]]; // Subject + [theCoder encodeObject: [self messageID]]; // Message-ID + [theCoder encodeObject: [self MIMEVersion]]; // MIME-Version + [theCoder encodeObject: _references]; // References + [theCoder encodeObject: [self inReplyTo]]; // In-Reply-To + + [theCoder encodeObject: [NSNumber numberWithInteger: _message_number]]; // Message number + [theCoder encodeObject: _flags]; // Message flags } @@ -238,38 +238,38 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (id) initWithCoder: (NSCoder *) theCoder { - // Must also decode Part's superclass - self = [super initWithCoder: theCoder]; - - _properties = [[NSMutableDictionary alloc] init]; - _recipients = [[NSMutableArray alloc] init]; - - [self setOriginationDate: [theCoder decodeObject]]; // Date - [self setFrom: [theCoder decodeObject]]; // From - [self setRecipients: [theCoder decodeObject]]; // To and Cc (Bcc, at worst) - [self setSubject: [theCoder decodeObject]]; // Subject - [self setMessageID: [theCoder decodeObject]]; // Message-ID - [self setMIMEVersion: [theCoder decodeObject]]; // MIME-Version - [self setReferences: [theCoder decodeObject]]; // References - - [self setInReplyTo: [theCoder decodeObject]]; // In-Reply-To - [self setMessageNumber: [[theCoder decodeObject] intValue]]; // Message number - - // We decode our flags. We must not simply call [self setFlags: [theCoder decodeObject]] - // since IMAPMessage is re-implementing flags and that would cause problems when - // unarchiving IMAP caches. - _flags = [[CWFlags alloc] init]; - [_flags replaceWithFlags: [theCoder decodeObject]]; - - // It's very important to set the "initialized" ivar to NO since we didn't serialize the content. - // or our message. - _initialized = NO; - - // We initialize the rest of our ivars - _rawSource = nil; - _folder = nil; - - return self; + // Must also decode Part's superclass + self = [super initWithCoder: theCoder]; + + _properties = [[NSMutableDictionary alloc] init]; + _recipients = [[NSMutableArray alloc] init]; + + [self setOriginationDate: [theCoder decodeObject]]; // Date + [self setFrom: [theCoder decodeObject]]; // From + [self setRecipients: [theCoder decodeObject]]; // To and Cc (Bcc, at worst) + [self setSubject: [theCoder decodeObject]]; // Subject + [self setMessageID: [theCoder decodeObject]]; // Message-ID + [self setMIMEVersion: [theCoder decodeObject]]; // MIME-Version + [self setReferences: [theCoder decodeObject]]; // References + + [self setInReplyTo: [theCoder decodeObject]]; // In-Reply-To + [self setMessageNumber: [[theCoder decodeObject] intValue]]; // Message number + + // We decode our flags. We must not simply call [self setFlags: [theCoder decodeObject]] + // since IMAPMessage is re-implementing flags and that would cause problems when + // unarchiving IMAP caches. + _flags = [[CWFlags alloc] init]; + [_flags replaceWithFlags: [theCoder decodeObject]]; + + // It's very important to set the "initialized" ivar to NO since we didn't serialize the content. + // or our message. + _initialized = NO; + + // We initialize the rest of our ivars + _rawSource = nil; + _folder = nil; + + return self; } @@ -278,7 +278,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (id) copyWithZone: (NSZone *) zone { - return RETAIN(self); + return RETAIN(self); } @@ -287,7 +287,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (CWInternetAddress *) from { - return [_headers objectForKey: @"From"]; + return [_headers objectForKey: @"From"]; } @@ -296,9 +296,9 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setFrom: (CWInternetAddress *) theInternetAddress { - if (theInternetAddress) + if (theInternetAddress) { - [_headers setObject: theInternetAddress forKey: @"From"]; + [_headers setObject: theInternetAddress forKey: @"From"]; } } @@ -308,7 +308,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSUInteger) messageNumber { - return _message_number; + return _message_number; } @@ -317,7 +317,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setMessageNumber: (NSUInteger) theMessageNumber { - _message_number = theMessageNumber; + _message_number = theMessageNumber; } @@ -326,17 +326,17 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSString *) messageID { - NSString *aString; + NSString *aString; - aString = [_headers objectForKey: @"Message-ID"]; - - if (!aString) + aString = [_headers objectForKey: @"Message-ID"]; + + if (!aString) { - aString = [[CWMIMEUtility globallyUniqueID] asciiString]; - [self setMessageID: aString]; + aString = [[CWMIMEUtility globallyUniqueID] asciiString]; + [self setMessageID: aString]; } - return aString; + return aString; } @@ -345,9 +345,9 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setMessageID: (NSString *) theMessageID { - if (theMessageID) + if (theMessageID) { - [_headers setObject: theMessageID forKey: @"Message-ID"]; + [_headers setObject: theMessageID forKey: @"Message-ID"]; } } @@ -357,7 +357,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSString *) inReplyTo { - return [_headers objectForKey: @"In-Reply-To"]; + return [_headers objectForKey: @"In-Reply-To"]; } @@ -366,9 +366,9 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setInReplyTo: (NSString *) theInReplyTo { - if (theInReplyTo) + if (theInReplyTo) { - [_headers setObject: theInReplyTo forKey: @"In-Reply-To"]; + [_headers setObject: theInReplyTo forKey: @"In-Reply-To"]; } } @@ -378,7 +378,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSDate *) originationDate { - return [_headers objectForKey: @"Date"]; + return [_headers objectForKey: @"Date"]; } @@ -387,9 +387,9 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setOriginationDate: (NSDate*) theDate { - if (theDate) + if (theDate) { - [_headers setObject: theDate forKey: @"Date"]; + [_headers setObject: theDate forKey: @"Date"]; } } @@ -399,9 +399,9 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) addRecipient: (CWInternetAddress *) theAddress { - if (theAddress) + if (theAddress) { - [_recipients addObject: theAddress]; + [_recipients addObject: theAddress]; } } @@ -411,9 +411,9 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) removeRecipient: (CWInternetAddress *) theAddress { - if (theAddress) + if (theAddress) { - [_recipients removeObject: theAddress]; + [_recipients removeObject: theAddress]; } } @@ -423,7 +423,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSArray *) recipients { - return _recipients; + return _recipients; } @@ -432,11 +432,11 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setRecipients: (NSArray *) theRecipients { - [_recipients removeAllObjects]; + [_recipients removeAllObjects]; - if (theRecipients) + if (theRecipients) { - [_recipients addObjectsFromArray: theRecipients]; + [_recipients addObjectsFromArray: theRecipients]; } } @@ -446,7 +446,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSUInteger) recipientsCount { - return [_recipients count]; + return [_recipients count]; } @@ -455,7 +455,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) removeAllRecipients { - [_recipients removeAllObjects]; + [_recipients removeAllObjects]; } @@ -464,7 +464,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSArray *) replyTo { - return [_headers objectForKey: @"Reply-To"]; + return [_headers objectForKey: @"Reply-To"]; } @@ -473,13 +473,13 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setReplyTo: (NSArray *) theAddressList { - if (theAddressList && [theAddressList count]) + if (theAddressList && [theAddressList count]) { - [_headers setObject: theAddressList forKey: @"Reply-To"]; + [_headers setObject: theAddressList forKey: @"Reply-To"]; } - else + else { - [_headers removeObjectForKey: @"Reply-To"]; + [_headers removeObjectForKey: @"Reply-To"]; } } @@ -498,12 +498,12 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setSubject: (NSString *) theSubject { - if (theSubject) + if (theSubject) { - [_headers setObject: theSubject forKey: @"Subject"]; - - // We invalidate our previous base subject. - [self setBaseSubject: nil]; + [_headers setObject: theSubject forKey: @"Subject"]; + + // We invalidate our previous base subject. + [self setBaseSubject: nil]; } } @@ -513,17 +513,17 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSString *) baseSubject { - NSString *baseSubject; - - baseSubject = [self propertyForKey: @"baseSubject"]; - - if (!baseSubject) + NSString *baseSubject; + + baseSubject = [self propertyForKey: @"baseSubject"]; + + if (!baseSubject) { - baseSubject = [self _computeBaseSubject]; - [self setBaseSubject: baseSubject]; + baseSubject = [self _computeBaseSubject]; + [self setBaseSubject: baseSubject]; } - - return baseSubject; + + return baseSubject; } @@ -532,7 +532,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setBaseSubject: (NSString *) theBaseSubject { - [self setProperty: theBaseSubject forKey: @"baseSubject"]; + [self setProperty: theBaseSubject forKey: @"baseSubject"]; } @@ -541,7 +541,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (BOOL) isInitialized { - return _initialized; + return _initialized; } @@ -550,7 +550,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setInitialized: (BOOL) theBOOL { - _initialized = theBOOL; + _initialized = theBOOL; } @@ -559,7 +559,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSString *) organization { - return [_headers objectForKey: @"Organization"]; + return [_headers objectForKey: @"Organization"]; } @@ -568,7 +568,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setOrganization: (NSString *) theOrganization { - [_headers setObject: theOrganization forKey: @"Organization"]; + [_headers setObject: theOrganization forKey: @"Organization"]; } @@ -577,7 +577,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (id) propertyForKey: (id) theKey { - return [_properties objectForKey: theKey]; + return [_properties objectForKey: theKey]; } @@ -585,15 +585,15 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // // - (void) setProperty: (id) theProperty - forKey: (id) theKey + forKey: (id) theKey { - if (theProperty) + if (theProperty) { - [_properties setObject: theProperty forKey: theKey]; + [_properties setObject: theProperty forKey: theKey]; } - else + else { - [_properties removeObjectForKey: theKey]; + [_properties removeObjectForKey: theKey]; } } @@ -603,7 +603,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSArray *) allReferences { - return _references; + return _references; } @@ -621,7 +621,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (CWFlags *) flags { - return _flags; + return _flags; } @@ -630,7 +630,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setFlags: (CWFlags *) theFlags { - ASSIGN(_flags, theFlags); + ASSIGN(_flags, theFlags); } @@ -639,7 +639,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSString *) MIMEVersion { - return [_headers objectForKey: @"MIME-Version"]; + return [_headers objectForKey: @"MIME-Version"]; } @@ -648,9 +648,9 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setMIMEVersion: (NSString *) theMIMEVersion { - if (theMIMEVersion) + if (theMIMEVersion) { - [_headers setObject: theMIMEVersion forKey: @"MIME-Version"]; + [_headers setObject: theMIMEVersion forKey: @"MIME-Version"]; } } @@ -660,134 +660,134 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (CWMessage *) reply: (PantomimeReplyMode) theMode { - CWInternetAddress *anInternetAddress; - NSMutableData *aMutableData; - CWMessage *theMessage; - BOOL needsToQuote; - - theMessage = [[CWMessage alloc] init]; - [theMessage setContentType: @"text/plain"]; - [theMessage setCharset: @"utf-8"]; + CWInternetAddress *anInternetAddress; + NSMutableData *aMutableData; + CWMessage *theMessage; + BOOL needsToQuote; + + theMessage = [[CWMessage alloc] init]; + [theMessage setContentType: @"text/plain"]; + [theMessage setCharset: @"utf-8"]; - // We set the subject of our message - if (![self subject]) + // We set the subject of our message + if (![self subject]) { - [theMessage setSubject: _(@"Re: your mail")]; + [theMessage setSubject: _(@"Re: your mail")]; } - else if ([[[self subject] stringByTrimmingWhiteSpaces] hasREPrefix]) + else if ([[[self subject] stringByTrimmingWhiteSpaces] hasREPrefix]) { - [theMessage setSubject: [self subject]]; + [theMessage setSubject: [self subject]]; } - else + else { - [theMessage setSubject: [NSString stringWithFormat: _(@"Re: %@"), [[self subject] stringByTrimmingWhiteSpaces]]]; + [theMessage setSubject: [NSString stringWithFormat: _(@"Re: %@"), [[self subject] stringByTrimmingWhiteSpaces]]]; } - // If Reply-To is defined, we use it. Otherwise, we use From: - if ([self replyTo] == nil) + // If Reply-To is defined, we use it. Otherwise, we use From: + if ([self replyTo] == nil) { - anInternetAddress = [self from]; - [anInternetAddress setType: PantomimeToRecipient]; - [theMessage addRecipient: anInternetAddress]; + anInternetAddress = [self from]; + [anInternetAddress setType: PantomimeToRecipient]; + [theMessage addRecipient: anInternetAddress]; } - else + else { - int i; + int i; - for (i = 0; i < [[self replyTo] count]; i++) - { - anInternetAddress = [[self replyTo] objectAtIndex: i]; - [anInternetAddress setType: PantomimeToRecipient]; - [theMessage addRecipient: anInternetAddress]; - } + for (i = 0; i < [[self replyTo] count]; i++) + { + anInternetAddress = [[self replyTo] objectAtIndex: i]; + [anInternetAddress setType: PantomimeToRecipient]; + [theMessage addRecipient: anInternetAddress]; + } } - // We add our In-Reply-To header - if ([self messageID]) + // We add our In-Reply-To header + if ([self messageID]) { - [theMessage setInReplyTo: [self messageID]]; + [theMessage setInReplyTo: [self messageID]]; } - - // If we reply to all, we add the other recipients - if ((theMode&PantomimeReplyAllMode) == PantomimeReplyAllMode) + + // If we reply to all, we add the other recipients + if ((theMode&PantomimeReplyAllMode) == PantomimeReplyAllMode) { - NSEnumerator *anEnumerator; + NSEnumerator *anEnumerator; - anEnumerator = [_recipients objectEnumerator]; - - while ((anInternetAddress = [anEnumerator nextObject])) - { - [anInternetAddress setType: PantomimeCcRecipient]; - [theMessage addRecipient: anInternetAddress]; - } + anEnumerator = [_recipients objectEnumerator]; + + while ((anInternetAddress = [anEnumerator nextObject])) + { + [anInternetAddress setType: PantomimeCcRecipient]; + [theMessage addRecipient: anInternetAddress]; + } } - // If it's a "simple" reply, we don't compute a content. - if ((theMode&PantomimeSimpleReplyMode) == PantomimeSimpleReplyMode) + // If it's a "simple" reply, we don't compute a content. + if ((theMode&PantomimeSimpleReplyMode) == PantomimeSimpleReplyMode) { - [theMessage setContent: [NSData data]]; - return AUTORELEASE(theMessage); + [theMessage setContent: [NSData data]]; + return AUTORELEASE(theMessage); } - - // We finally work on the content of the message - aMutableData = [[NSMutableData alloc] init]; - needsToQuote = NO; - [self _extractText: aMutableData part: self quote: &needsToQuote]; - - // - // It was impossible for use to find a text/plain part. Let's - // inform our user that we can't do anything with this message. - // - if (![aMutableData length]) + // We finally work on the content of the message + aMutableData = [[NSMutableData alloc] init]; + needsToQuote = NO; + + [self _extractText: aMutableData part: self quote: &needsToQuote]; + + // + // It was impossible for use to find a text/plain part. Let's + // inform our user that we can't do anything with this message. + // + if (![aMutableData length]) { - [aMutableData appendData: [@"\t[NON-Text Body part not included]" dataUsingEncoding: NSUTF8StringEncoding]]; - needsToQuote = NO; + [aMutableData appendData: [@"\t[NON-Text Body part not included]" dataUsingEncoding: NSUTF8StringEncoding]]; + needsToQuote = NO; } - else + else { - // We remove the signature - NSRange aRange; - - aRange = [aMutableData rangeOfCString: "\n-- " options: NSBackwardsSearch]; - - if (aRange.length) - { - [aMutableData replaceBytesInRange: NSMakeRange(aRange.location, [aMutableData length]-aRange.location) - withBytes: NULL - length: 0]; - } + // We remove the signature + NSRange aRange; + + aRange = [aMutableData rangeOfCString: "\n-- " options: NSBackwardsSearch]; + + if (aRange.length) + { + [aMutableData replaceBytesInRange: NSMakeRange(aRange.location, [aMutableData length]-aRange.location) + withBytes: NULL + length: 0]; + } } - - // We now have our content as string, let's 'quote' it - if (needsToQuote) + + // We now have our content as string, let's 'quote' it + if (needsToQuote) { - NSData *aData; - - aData = [aMutableData unwrapWithLimit: 78]; - [aMutableData setData: [aData quoteWithLevel: 1 wrappingLimit: 80]]; + NSData *aData; + + aData = [aMutableData unwrapWithLimit: 78]; + [aMutableData setData: [aData quoteWithLevel: 1 wrappingLimit: 80]]; } - [aMutableData insertCString: [[NSString stringWithFormat: @"%@ wrote:\n\n", [[self from] stringValue]] UTF8String] - atIndex: 0]; - - - // We verify if we have a Date value. We might receive messages w/o this field - // (Yes, I know, it's borken but it's happening). - if ([self originationDate]) + [aMutableData insertCString: [[NSString stringWithFormat: @"%@ wrote:\n\n", [[self from] stringValue]] UTF8String] + atIndex: 0]; + + + // We verify if we have a Date value. We might receive messages w/o this field + // (Yes, I know, it's borken but it's happening). + if ([self originationDate]) { - [aMutableData insertCString: [[NSString stringWithFormat: @"On %@ ", [[self originationDate] description]] UTF8String] - atIndex: 0]; + [aMutableData insertCString: [[NSString stringWithFormat: @"On %@ ", [[self originationDate] description]] UTF8String] + atIndex: 0]; } - [theMessage setContent: aMutableData]; - RELEASE(aMutableData); - - return AUTORELEASE(theMessage); + [theMessage setContent: aMutableData]; + RELEASE(aMutableData); + + return AUTORELEASE(theMessage); } @@ -796,261 +796,261 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (CWMessage *) forward: (PantomimeForwardMode) theMode; { - CWMessage *theMessage; - - theMessage = [[CWMessage alloc] init]; - - // We set the subject of our message - if ([self subject]) - { - [theMessage setSubject: [NSString stringWithFormat: @"%@ (fwd)", [self subject]]]; - } - else - { - [theMessage setSubject: @"Forwarded mail..."]; - } - - if (theMode == PantomimeAttachmentForwardMode) - { - CWMIMEMultipart *aMimeMultipart; - CWPart *aPart; - - aMimeMultipart = [[CWMIMEMultipart alloc] init]; - - aPart = [[CWPart alloc] init]; - [aMimeMultipart addPart: aPart]; - RELEASE(aPart); - - aPart = [[CWPart alloc] init]; - [aPart setContentType: @"message/rfc822"]; - [aPart setContentDisposition: PantomimeAttachmentDisposition]; - [aPart setSize: [self size]]; - [aPart setContent: self]; - [aMimeMultipart addPart: aPart]; - RELEASE(aPart); - - [theMessage setContentType: @"multipart/mixed"]; - [theMessage setContent: aMimeMultipart]; - RELEASE(aMimeMultipart); - } - else - { - NSMutableData *aMutableData; - - // We create our generic forward message header - aMutableData = AUTORELEASE([[NSMutableData alloc] init]); - [aMutableData appendCString: "---------- Forwarded message ----------"]; - - // We verify if we have a Date value. We might receive messages w/o this field - // (Yes, I know, it's borken but it's happening). - if ([self originationDate]) - { - [aMutableData appendCString: "\nDate: "]; - [aMutableData appendData: [[[self originationDate] description] dataUsingEncoding: NSASCIIStringEncoding]]; - } - - [aMutableData appendCString: "\nFrom: "]; - [aMutableData appendData: [[[self from] stringValue] dataUsingEncoding: [NSString encodingForPart: self]]]; - - if ([self subject]) - { - [aMutableData appendCString: "\nSubject: "]; - } - - [aMutableData appendData: [[NSString stringWithFormat: @"%@\n\n", [self subject]] - dataUsingEncoding: [NSString encodingForPart: self]]]; - - // - // If our Content-Type is text/plain, we represent it as a it is, otherwise, - // we currently create a new body part representing the forwarded message. - // - if ([self isMIMEType: @"text" subType: @"*"]) - { - // We set the content of our message - [aMutableData appendData: [CWMIMEUtility plainTextContentFromPart: self]]; - - // We set the Content-Transfer-Encoding and the Charset to the previous one - [theMessage setContentTransferEncoding: [self contentTransferEncoding]]; - [theMessage setCharset: [self charset]]; - - - [theMessage setContentType: @"text/plain"]; - [theMessage setContent: aMutableData]; - [theMessage setSize: [aMutableData length]]; - } - // - // If our Content-Type is a message/rfc822 or any other type like - // application/*, audio/*, image/* or video/* - // - else if ([self isMIMEType: @"application" subType: @"*"] || - [self isMIMEType: @"audio" subType: @"*"] || - [self isMIMEType: @"image" subType: @"*"] || - [self isMIMEType: @"message" subType: @"*"] || - [self isMIMEType: @"video" subType: @"*"]) - { - CWMIMEMultipart *aMimeMultipart; - CWPart *aPart; - - aMimeMultipart = [[CWMIMEMultipart alloc] init]; - - // We add our text/plain part. - aPart = [[CWPart alloc] init]; - [aPart setContentType: @"text/plain"]; - [aPart setContent: aMutableData]; - [aPart setContentDisposition: PantomimeInlineDisposition]; - [aPart setSize: [aMutableData length]]; - [aMimeMultipart addPart: aPart]; - RELEASE(aPart); - - // We add our content as an attachment - aPart = [[CWPart alloc] init]; - [aPart setContentType: [self contentType]]; - [aPart setContent: [self content]]; - [aPart setContentTransferEncoding: [self contentTransferEncoding]]; - [aPart setContentDisposition: PantomimeAttachmentDisposition]; - [aPart setCharset: [self charset]]; - [aPart setFilename: [self filename]]; - [aPart setSize: [self size]]; - [aMimeMultipart addPart: aPart]; - RELEASE(aPart); - - [theMessage setContentType: @"multipart/mixed"]; - [theMessage setContent: aMimeMultipart]; - RELEASE(aMimeMultipart); - } - // - // We have a multipart object. We must treat multipart/alternative - // parts differently since we don't want to include multipart parts in the forward. - // - else if ([self isMIMEType: @"multipart" subType: @"*"]) - { - // - // If we have multipart/alternative part, we only keep one part from it. - // - if ([self isMIMEType: @"multipart" subType: @"alternative"]) - { - CWMIMEMultipart *aMimeMultipart; - CWPart *aPart; - int i; - - aMimeMultipart = (CWMIMEMultipart *)[self content]; - aPart = nil; - - // We search for our text/plain part - for (i = 0; i < [aMimeMultipart count]; i++) - { - aPart = [aMimeMultipart partAtIndex: i]; - - if ([aPart isMIMEType: @"text" subType: @"plain"]) - { - break; - } - else - { - aPart = nil; - } - } - - // We found one - if (aPart) - { - // We set the content of our message - [aMutableData appendData: (NSData *)[aPart content]]; - - // We set the Content-Transfer-Encoding and the Charset to our text part - [theMessage setContentTransferEncoding: [aPart contentTransferEncoding]]; - [theMessage setCharset: [aPart charset]]; - - [theMessage setContentType: @"text/plain"]; - [theMessage setContent: aMutableData]; - [theMessage setSize: [aMutableData length]]; - } - // We haven't found one! Inform the user that it happened. - else - { - [aMutableData appendCString: "No text/plain part from this multipart/alternative part has been found"]; - [aMutableData appendCString: "\nNo parts have been included as attachments with this mail during the forward operation."]; - [aMutableData appendCString: "\n\nPlease report this as a bug."]; - - [theMessage setContent: aMutableData]; - [theMessage setSize: [aMutableData length]]; - } - } - // - // We surely have a multipart/mixed or multipart/related. - // We search for a text/plain part inside our multipart object. - // We 'keep' the other parts in a separate new multipart object too - // that will become our new content. - // - else - { - CWMIMEMultipart *aMimeMultipart, *newMimeMultipart; - CWPart *aPart; - BOOL hasFoundTextPlain = NO; - int i; - - // We get our current mutipart object - aMimeMultipart = (CWMIMEMultipart *)[self content]; - - // We create our new multipart object for holding all our parts. - newMimeMultipart = [[CWMIMEMultipart alloc] init]; - - for (i = 0; i < [aMimeMultipart count]; i++) - { - aPart = [aMimeMultipart partAtIndex: i]; - - if ([aPart isMIMEType: @"text" subType: @"plain"] && !hasFoundTextPlain) - { - CWPart *newPart; - - newPart = [[CWPart alloc] init]; - - // We set the content of our new part - [aMutableData appendData: (NSData *)[aPart content]]; - [newPart setContentType: @"text/plain"]; - [newPart setContent: aMutableData]; - [newPart setSize: [aMutableData length]]; - - // We set the Content-Transfer-Encoding and the Charset to the previous one - [newPart setContentTransferEncoding: [aPart contentTransferEncoding]]; - [newPart setCharset: [aPart charset]]; - - // We finally add our new part to our MIME multipart object - [newMimeMultipart addPart: newPart]; - RELEASE(newPart); - - hasFoundTextPlain = YES; - } - // We set the Content-Disposition to "attachment" - // all the time. - else - { - [aPart setContentDisposition: PantomimeAttachmentDisposition]; - [newMimeMultipart addPart: aPart]; - } - } - - [theMessage setContentType: @"multipart/mixed"]; - [theMessage setContent: newMimeMultipart]; - RELEASE(newMimeMultipart); - } - } - // - // We got an unknown part. Let's inform the user about this situation. - // - else - { - // We set the content of our message - [aMutableData appendCString: "The original message contained an unknown part that was not included in this forwarded message."]; - [aMutableData appendCString: "\n\nPlease report this as a bug."]; - - [theMessage setContentType: @"text/plain"]; - [theMessage setContent: aMutableData]; - [theMessage setSize: [aMutableData length]]; - } - } - - return AUTORELEASE(theMessage); + CWMessage *theMessage; + + theMessage = [[CWMessage alloc] init]; + + // We set the subject of our message + if ([self subject]) + { + [theMessage setSubject: [NSString stringWithFormat: @"%@ (fwd)", [self subject]]]; + } + else + { + [theMessage setSubject: @"Forwarded mail..."]; + } + + if (theMode == PantomimeAttachmentForwardMode) + { + CWMIMEMultipart *aMimeMultipart; + CWPart *aPart; + + aMimeMultipart = [[CWMIMEMultipart alloc] init]; + + aPart = [[CWPart alloc] init]; + [aMimeMultipart addPart: aPart]; + RELEASE(aPart); + + aPart = [[CWPart alloc] init]; + [aPart setContentType: @"message/rfc822"]; + [aPart setContentDisposition: PantomimeAttachmentDisposition]; + [aPart setSize: [self size]]; + [aPart setContent: self]; + [aMimeMultipart addPart: aPart]; + RELEASE(aPart); + + [theMessage setContentType: @"multipart/mixed"]; + [theMessage setContent: aMimeMultipart]; + RELEASE(aMimeMultipart); + } + else + { + NSMutableData *aMutableData; + + // We create our generic forward message header + aMutableData = AUTORELEASE([[NSMutableData alloc] init]); + [aMutableData appendCString: "---------- Forwarded message ----------"]; + + // We verify if we have a Date value. We might receive messages w/o this field + // (Yes, I know, it's borken but it's happening). + if ([self originationDate]) + { + [aMutableData appendCString: "\nDate: "]; + [aMutableData appendData: [[[self originationDate] description] dataUsingEncoding: NSASCIIStringEncoding]]; + } + + [aMutableData appendCString: "\nFrom: "]; + [aMutableData appendData: [[[self from] stringValue] dataUsingEncoding: [NSString encodingForPart: self]]]; + + if ([self subject]) + { + [aMutableData appendCString: "\nSubject: "]; + } + + [aMutableData appendData: [[NSString stringWithFormat: @"%@\n\n", [self subject]] + dataUsingEncoding: [NSString encodingForPart: self]]]; + + // + // If our Content-Type is text/plain, we represent it as a it is, otherwise, + // we currently create a new body part representing the forwarded message. + // + if ([self isMIMEType: @"text" subType: @"*"]) + { + // We set the content of our message + [aMutableData appendData: [CWMIMEUtility plainTextContentFromPart: self]]; + + // We set the Content-Transfer-Encoding and the Charset to the previous one + [theMessage setContentTransferEncoding: [self contentTransferEncoding]]; + [theMessage setCharset: [self charset]]; + + + [theMessage setContentType: @"text/plain"]; + [theMessage setContent: aMutableData]; + [theMessage setSize: [aMutableData length]]; + } + // + // If our Content-Type is a message/rfc822 or any other type like + // application/*, audio/*, image/* or video/* + // + else if ([self isMIMEType: @"application" subType: @"*"] || + [self isMIMEType: @"audio" subType: @"*"] || + [self isMIMEType: @"image" subType: @"*"] || + [self isMIMEType: @"message" subType: @"*"] || + [self isMIMEType: @"video" subType: @"*"]) + { + CWMIMEMultipart *aMimeMultipart; + CWPart *aPart; + + aMimeMultipart = [[CWMIMEMultipart alloc] init]; + + // We add our text/plain part. + aPart = [[CWPart alloc] init]; + [aPart setContentType: @"text/plain"]; + [aPart setContent: aMutableData]; + [aPart setContentDisposition: PantomimeInlineDisposition]; + [aPart setSize: [aMutableData length]]; + [aMimeMultipart addPart: aPart]; + RELEASE(aPart); + + // We add our content as an attachment + aPart = [[CWPart alloc] init]; + [aPart setContentType: [self contentType]]; + [aPart setContent: [self content]]; + [aPart setContentTransferEncoding: [self contentTransferEncoding]]; + [aPart setContentDisposition: PantomimeAttachmentDisposition]; + [aPart setCharset: [self charset]]; + [aPart setFilename: [self filename]]; + [aPart setSize: [self size]]; + [aMimeMultipart addPart: aPart]; + RELEASE(aPart); + + [theMessage setContentType: @"multipart/mixed"]; + [theMessage setContent: aMimeMultipart]; + RELEASE(aMimeMultipart); + } + // + // We have a multipart object. We must treat multipart/alternative + // parts differently since we don't want to include multipart parts in the forward. + // + else if ([self isMIMEType: @"multipart" subType: @"*"]) + { + // + // If we have multipart/alternative part, we only keep one part from it. + // + if ([self isMIMEType: @"multipart" subType: @"alternative"]) + { + CWMIMEMultipart *aMimeMultipart; + CWPart *aPart; + int i; + + aMimeMultipart = (CWMIMEMultipart *)[self content]; + aPart = nil; + + // We search for our text/plain part + for (i = 0; i < [aMimeMultipart count]; i++) + { + aPart = [aMimeMultipart partAtIndex: i]; + + if ([aPart isMIMEType: @"text" subType: @"plain"]) + { + break; + } + else + { + aPart = nil; + } + } + + // We found one + if (aPart) + { + // We set the content of our message + [aMutableData appendData: (NSData *)[aPart content]]; + + // We set the Content-Transfer-Encoding and the Charset to our text part + [theMessage setContentTransferEncoding: [aPart contentTransferEncoding]]; + [theMessage setCharset: [aPart charset]]; + + [theMessage setContentType: @"text/plain"]; + [theMessage setContent: aMutableData]; + [theMessage setSize: [aMutableData length]]; + } + // We haven't found one! Inform the user that it happened. + else + { + [aMutableData appendCString: "No text/plain part from this multipart/alternative part has been found"]; + [aMutableData appendCString: "\nNo parts have been included as attachments with this mail during the forward operation."]; + [aMutableData appendCString: "\n\nPlease report this as a bug."]; + + [theMessage setContent: aMutableData]; + [theMessage setSize: [aMutableData length]]; + } + } + // + // We surely have a multipart/mixed or multipart/related. + // We search for a text/plain part inside our multipart object. + // We 'keep' the other parts in a separate new multipart object too + // that will become our new content. + // + else + { + CWMIMEMultipart *aMimeMultipart, *newMimeMultipart; + CWPart *aPart; + BOOL hasFoundTextPlain = NO; + int i; + + // We get our current mutipart object + aMimeMultipart = (CWMIMEMultipart *)[self content]; + + // We create our new multipart object for holding all our parts. + newMimeMultipart = [[CWMIMEMultipart alloc] init]; + + for (i = 0; i < [aMimeMultipart count]; i++) + { + aPart = [aMimeMultipart partAtIndex: i]; + + if ([aPart isMIMEType: @"text" subType: @"plain"] && !hasFoundTextPlain) + { + CWPart *newPart; + + newPart = [[CWPart alloc] init]; + + // We set the content of our new part + [aMutableData appendData: (NSData *)[aPart content]]; + [newPart setContentType: @"text/plain"]; + [newPart setContent: aMutableData]; + [newPart setSize: [aMutableData length]]; + + // We set the Content-Transfer-Encoding and the Charset to the previous one + [newPart setContentTransferEncoding: [aPart contentTransferEncoding]]; + [newPart setCharset: [aPart charset]]; + + // We finally add our new part to our MIME multipart object + [newMimeMultipart addPart: newPart]; + RELEASE(newPart); + + hasFoundTextPlain = YES; + } + // We set the Content-Disposition to "attachment" + // all the time. + else + { + [aPart setContentDisposition: PantomimeAttachmentDisposition]; + [newMimeMultipart addPart: aPart]; + } + } + + [theMessage setContentType: @"multipart/mixed"]; + [theMessage setContent: newMimeMultipart]; + RELEASE(newMimeMultipart); + } + } + // + // We got an unknown part. Let's inform the user about this situation. + // + else + { + // We set the content of our message + [aMutableData appendCString: "The original message contained an unknown part that was not included in this forwarded message."]; + [aMutableData appendCString: "\n\nPlease report this as a bug."]; + + [theMessage setContentType: @"text/plain"]; + [theMessage setContent: aMutableData]; + [theMessage setSize: [aMutableData length]]; + } + } + + return AUTORELEASE(theMessage); } - (NSData *)dataValue @@ -1189,12 +1189,12 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (CWFolder *) folder { - return _folder; + return _folder; } - (void) setFolder: (CWFolder *) theFolder { - _folder = theFolder; + _folder = theFolder; } // @@ -1207,13 +1207,13 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSData *) rawSource { - if (!_rawSource) + if (!_rawSource) { - [self subclassResponsibility: _cmd]; - return nil; + [self subclassResponsibility: _cmd]; + return nil; } - - return _rawSource; + + return _rawSource; } @@ -1222,7 +1222,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setRawSource: (NSData *) theRawSource { - ASSIGN(_rawSource, theRawSource); + ASSIGN(_rawSource, theRawSource); } @@ -1231,7 +1231,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSDate *) resentDate { - return [_headers objectForKey: @"Resent-Date"]; + return [_headers objectForKey: @"Resent-Date"]; } @@ -1240,7 +1240,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setResentDate: (NSDate *) theResentDate { - [_headers setObject: theResentDate forKey: @"Resent-Date"]; + [_headers setObject: theResentDate forKey: @"Resent-Date"]; } @@ -1249,7 +1249,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (CWInternetAddress *) resentFrom { - return [_headers objectForKey: @"Resent-From"]; + return [_headers objectForKey: @"Resent-From"]; } @@ -1258,7 +1258,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setResentFrom: (CWInternetAddress *) theInternetAddress { - [_headers setObject: theInternetAddress forKey: @"Resent-From"]; + [_headers setObject: theInternetAddress forKey: @"Resent-From"]; } @@ -1267,7 +1267,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSString *) resentMessageID { - return [_headers objectForKey: @"Resent-Message-ID"]; + return [_headers objectForKey: @"Resent-Message-ID"]; } @@ -1276,7 +1276,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setResentMessageID: (NSString *) theResentMessageID { - [_headers setObject: theResentMessageID forKey: @"Resent-Message-ID"]; + [_headers setObject: theResentMessageID forKey: @"Resent-Message-ID"]; } @@ -1285,7 +1285,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSString *) resentSubject { - return [_headers objectForKey: @"Resent-Subject"]; + return [_headers objectForKey: @"Resent-Subject"]; } @@ -1294,7 +1294,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setResentSubject: (NSString *) theResentSubject { - [_headers setObject: theResentSubject forKey: @"Resent-Subject"]; + [_headers setObject: theResentSubject forKey: @"Resent-Subject"]; } @@ -1303,144 +1303,144 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) addHeadersFromData: (NSData *) theHeaders record: (CWCacheRecord *) theRecord { - NSArray *allLines; - NSData *aData; - NSUInteger i, count; - - [super setHeadersFromData: theHeaders]; - - // We MUST be sure to unfold all headers properly before - // decoding the headers - theHeaders = [theHeaders unfoldLines]; - - allLines = [theHeaders componentsSeparatedByCString: "\n"]; - count = [allLines count]; - - for (i = 0; i < count; i++) - { - NSData *aLine = [allLines objectAtIndex: i]; - - // We stop if we found the header separator. (\n\n) since someone could - // have called this method with the entire rawsource of a message. - if ([aLine length] == 0) - { - break; - } - - if ([aLine hasCaseInsensitiveCPrefix: "Bcc"]) - { - [CWParser parseDestination: aLine - forType: PantomimeBccRecipient - inMessage: self - quick: NO]; - } - else if ([aLine hasCaseInsensitiveCPrefix: "Cc"]) - { - aData = [CWParser parseDestination: aLine - forType: PantomimeCcRecipient - inMessage: self - quick: NO]; - if (theRecord) theRecord.cc = aData; - } - else if ([aLine hasCaseInsensitiveCPrefix: "Date"]) - { - [CWParser parseDate: aLine inMessage: self]; - if (theRecord && [self originationDate]) theRecord.date = [[self originationDate] timeIntervalSince1970]; - } - else if ([aLine hasCaseInsensitiveCPrefix: "From"] && - ![aLine hasCaseInsensitiveCPrefix: "From "] && - ![aLine hasCaseInsensitiveCPrefix: "From-"]) //ignore: from-name: from-address: - { - aData = [CWParser parseFrom: aLine inMessage: self quick: NO]; - if (theRecord) theRecord.from = aData; - } - else if ([aLine hasCaseInsensitiveCPrefix: "In-Reply-To"]) - { - aData = [CWParser parseInReplyTo: aLine inMessage: self quick: NO]; - if (theRecord) theRecord.in_reply_to = aData; - } - else if ([aLine hasCaseInsensitiveCPrefix: "Message-ID"]) - { - aData = [CWParser parseMessageID: aLine inMessage: self quick: NO]; - if (theRecord) theRecord.message_id = aData; - } - else if ([aLine hasCaseInsensitiveCPrefix: "MIME-Version"]) - { - [CWParser parseMIMEVersion: aLine inMessage: self]; - } - else if ([aLine hasCaseInsensitiveCPrefix: "Organization"]) - { - [CWParser parseOrganization: aLine inMessage: self]; - } - else if ([aLine hasCaseInsensitiveCPrefix: "References"]) - { - aData = [CWParser parseReferences: aLine inMessage: self quick: NO]; - if (theRecord) theRecord.references = aData; - } - else if ([aLine hasCaseInsensitiveCPrefix: "Reply-To"]) - { - [CWParser parseReplyTo: aLine inMessage: self]; - } - else if ([aLine hasCaseInsensitiveCPrefix: "Resent-From"]) - { - [CWParser parseResentFrom: aLine inMessage: self]; - } - else if ([aLine hasCaseInsensitiveCPrefix: "Resent-Bcc"]) - { - [CWParser parseDestination: aLine - forType: PantomimeResentBccRecipient - inMessage: self - quick: NO]; - } - else if ([aLine hasCaseInsensitiveCPrefix: "Resent-Cc"]) - { - [CWParser parseDestination: aLine - forType: PantomimeResentCcRecipient - inMessage: self - quick: NO]; - } - else if ([aLine hasCaseInsensitiveCPrefix: "Resent-To"]) - { - [CWParser parseDestination: aLine - forType: PantomimeResentToRecipient - inMessage: self - quick: NO]; - } - else if ([aLine hasCaseInsensitiveCPrefix: "Status"]) - { - [CWParser parseStatus: aLine inMessage: self]; - } - else if ([aLine hasCaseInsensitiveCPrefix: "To"]) - { - aData = [CWParser parseDestination: aLine - forType: PantomimeToRecipient - inMessage: self - quick: NO]; - if (theRecord) theRecord.to = aData; - } - else if ([aLine hasCaseInsensitiveCPrefix: "X-Status"]) - { - [CWParser parseXStatus: aLine inMessage: self]; - } - else if ([aLine hasCaseInsensitiveCPrefix: "Subject"]) - { - aData = [CWParser parseSubject: aLine inMessage: self quick: NO]; - if (theRecord) theRecord.subject = aData; - } - else - { - // We MUST NOT parse the headers that we already parsed in - // Part as "unknown". - if (![aLine hasCaseInsensitiveCPrefix: "Content-Description"] && - ![aLine hasCaseInsensitiveCPrefix: "Content-Disposition"] && - ![aLine hasCaseInsensitiveCPrefix: "Content-ID"] && - ![aLine hasCaseInsensitiveCPrefix: "Content-Length"] && - ![aLine hasCaseInsensitiveCPrefix: "Content-Transfer-Encoding"] && - ![aLine hasCaseInsensitiveCPrefix: "Content-Type"]) - { - [CWParser parseUnknownHeader: aLine inMessage: self]; - } - } + NSArray *allLines; + NSData *aData; + NSUInteger i, count; + + [super setHeadersFromData: theHeaders]; + + // We MUST be sure to unfold all headers properly before + // decoding the headers + theHeaders = [theHeaders unfoldLines]; + + allLines = [theHeaders componentsSeparatedByCString: "\n"]; + count = [allLines count]; + + for (i = 0; i < count; i++) + { + NSData *aLine = [allLines objectAtIndex: i]; + + // We stop if we found the header separator. (\n\n) since someone could + // have called this method with the entire rawsource of a message. + if ([aLine length] == 0) + { + break; + } + + if ([aLine hasCaseInsensitiveCPrefix: "Bcc"]) + { + [CWParser parseDestination: aLine + forType: PantomimeBccRecipient + inMessage: self + quick: NO]; + } + else if ([aLine hasCaseInsensitiveCPrefix: "Cc"]) + { + aData = [CWParser parseDestination: aLine + forType: PantomimeCcRecipient + inMessage: self + quick: NO]; + if (theRecord) theRecord.cc = aData; + } + else if ([aLine hasCaseInsensitiveCPrefix: "Date"]) + { + [CWParser parseDate: aLine inMessage: self]; + if (theRecord && [self originationDate]) theRecord.date = [[self originationDate] timeIntervalSince1970]; + } + else if ([aLine hasCaseInsensitiveCPrefix: "From"] && + ![aLine hasCaseInsensitiveCPrefix: "From "] && + ![aLine hasCaseInsensitiveCPrefix: "From-"]) //ignore: from-name: from-address: + { + aData = [CWParser parseFrom: aLine inMessage: self quick: NO]; + if (theRecord) theRecord.from = aData; + } + else if ([aLine hasCaseInsensitiveCPrefix: "In-Reply-To"]) + { + aData = [CWParser parseInReplyTo: aLine inMessage: self quick: NO]; + if (theRecord) theRecord.in_reply_to = aData; + } + else if ([aLine hasCaseInsensitiveCPrefix: "Message-ID"]) + { + aData = [CWParser parseMessageID: aLine inMessage: self quick: NO]; + if (theRecord) theRecord.message_id = aData; + } + else if ([aLine hasCaseInsensitiveCPrefix: "MIME-Version"]) + { + [CWParser parseMIMEVersion: aLine inMessage: self]; + } + else if ([aLine hasCaseInsensitiveCPrefix: "Organization"]) + { + [CWParser parseOrganization: aLine inMessage: self]; + } + else if ([aLine hasCaseInsensitiveCPrefix: "References"]) + { + aData = [CWParser parseReferences: aLine inMessage: self quick: NO]; + if (theRecord) theRecord.references = aData; + } + else if ([aLine hasCaseInsensitiveCPrefix: "Reply-To"]) + { + [CWParser parseReplyTo: aLine inMessage: self]; + } + else if ([aLine hasCaseInsensitiveCPrefix: "Resent-From"]) + { + [CWParser parseResentFrom: aLine inMessage: self]; + } + else if ([aLine hasCaseInsensitiveCPrefix: "Resent-Bcc"]) + { + [CWParser parseDestination: aLine + forType: PantomimeResentBccRecipient + inMessage: self + quick: NO]; + } + else if ([aLine hasCaseInsensitiveCPrefix: "Resent-Cc"]) + { + [CWParser parseDestination: aLine + forType: PantomimeResentCcRecipient + inMessage: self + quick: NO]; + } + else if ([aLine hasCaseInsensitiveCPrefix: "Resent-To"]) + { + [CWParser parseDestination: aLine + forType: PantomimeResentToRecipient + inMessage: self + quick: NO]; + } + else if ([aLine hasCaseInsensitiveCPrefix: "Status"]) + { + [CWParser parseStatus: aLine inMessage: self]; + } + else if ([aLine hasCaseInsensitiveCPrefix: "To"]) + { + aData = [CWParser parseDestination: aLine + forType: PantomimeToRecipient + inMessage: self + quick: NO]; + if (theRecord) theRecord.to = aData; + } + else if ([aLine hasCaseInsensitiveCPrefix: "X-Status"]) + { + [CWParser parseXStatus: aLine inMessage: self]; + } + else if ([aLine hasCaseInsensitiveCPrefix: "Subject"]) + { + aData = [CWParser parseSubject: aLine inMessage: self quick: NO]; + if (theRecord) theRecord.subject = aData; + } + else + { + // We MUST NOT parse the headers that we already parsed in + // Part as "unknown". + if (![aLine hasCaseInsensitiveCPrefix: "Content-Description"] && + ![aLine hasCaseInsensitiveCPrefix: "Content-Disposition"] && + ![aLine hasCaseInsensitiveCPrefix: "Content-ID"] && + ![aLine hasCaseInsensitiveCPrefix: "Content-Length"] && + ![aLine hasCaseInsensitiveCPrefix: "Content-Transfer-Encoding"] && + ![aLine hasCaseInsensitiveCPrefix: "Content-Type"]) + { + [CWParser parseUnknownHeader: aLine inMessage: self]; + } + } } } @@ -1449,7 +1449,7 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setHeadersFromData: (NSData *) theHeaders { - [self setHeadersFromData: theHeaders record: NULL]; + [self setHeadersFromData: theHeaders record: NULL]; } // @@ -1457,14 +1457,14 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (void) setHeadersFromData: (NSData *) theHeaders record: (CWCacheRecord *) theRecord { - if (!theHeaders || [theHeaders length] == 0) + if (!theHeaders || [theHeaders length] == 0) { - return; + return; } - [_recipients removeAllObjects]; - [_headers removeAllObjects]; - [self addHeadersFromData: theHeaders record: theRecord]; + [_recipients removeAllObjects]; + [_headers removeAllObjects]; + [self addHeadersFromData: theHeaders record: theRecord]; } @end @@ -1477,269 +1477,269 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; - (int) compareAccordingToNumber: (CWMessage *) aMessage { - NSUInteger num; - num = [aMessage messageNumber]; - if (_message_number < num) + NSUInteger num; + num = [aMessage messageNumber]; + if (_message_number < num) { - return NSOrderedAscending; + return NSOrderedAscending; } - else if (_message_number > num) + else if (_message_number > num) { - return NSOrderedDescending; + return NSOrderedDescending; } - else + else { - return NSOrderedSame; + return NSOrderedSame; } } - (int) reverseCompareAccordingToNumber: (CWMessage *) aMessage { - NSUInteger num; - num = [aMessage messageNumber]; - if (num < _message_number) + NSUInteger num; + num = [aMessage messageNumber]; + if (num < _message_number) { - return NSOrderedAscending; + return NSOrderedAscending; } - else if (num > _message_number) + else if (num > _message_number) { - return NSOrderedDescending; + return NSOrderedDescending; } - else + else { - return NSOrderedSame; + return NSOrderedSame; } } - (int) compareAccordingToDate: (CWMessage *) aMessage { - NSDate *date1 = [self originationDate]; - NSDate *date2 = [aMessage originationDate]; - NSTimeInterval timeInterval; + NSDate *date1 = [self originationDate]; + NSDate *date2 = [aMessage originationDate]; + NSTimeInterval timeInterval; - if (date1 == nil || date2 == nil) + if (date1 == nil || date2 == nil) { - return [self compareAccordingToNumber: aMessage]; + return [self compareAccordingToNumber: aMessage]; } - timeInterval = [date1 timeIntervalSinceDate: date2]; + timeInterval = [date1 timeIntervalSinceDate: date2]; - if (timeInterval < 0) + if (timeInterval < 0) { - return NSOrderedAscending; + return NSOrderedAscending; } - else if (timeInterval > 0) + else if (timeInterval > 0) { - return NSOrderedDescending; + return NSOrderedDescending; } - else + else { - return [self compareAccordingToNumber: aMessage]; + return [self compareAccordingToNumber: aMessage]; } } - (int) reverseCompareAccordingToDate: (CWMessage *) aMessage { - NSDate *date2 = [self originationDate]; - NSDate *date1 = [aMessage originationDate]; - NSTimeInterval timeInterval; + NSDate *date2 = [self originationDate]; + NSDate *date1 = [aMessage originationDate]; + NSTimeInterval timeInterval; - if (date1 == nil || date2 == nil) + if (date1 == nil || date2 == nil) { - return [self reverseCompareAccordingToNumber: aMessage]; + return [self reverseCompareAccordingToNumber: aMessage]; } - timeInterval = [date1 timeIntervalSinceDate: date2]; + timeInterval = [date1 timeIntervalSinceDate: date2]; - if (timeInterval < 0) + if (timeInterval < 0) { - return NSOrderedAscending; + return NSOrderedAscending; } - else if (timeInterval > 0) + else if (timeInterval > 0) { - return NSOrderedDescending; + return NSOrderedDescending; } - else + else { - return [self reverseCompareAccordingToNumber: aMessage]; + return [self reverseCompareAccordingToNumber: aMessage]; } } - (int) compareAccordingToSender: (CWMessage *) aMessage { - CWInternetAddress *from1, *from2; - NSString *fromString1, *fromString2; - NSString *tempString; - int result; + CWInternetAddress *from1, *from2; + NSString *fromString1, *fromString2; + NSString *tempString; + int result; - from1 = [self from]; - from2 = [aMessage from]; + from1 = [self from]; + from2 = [aMessage from]; - tempString = [from1 personal]; - if (tempString == nil || [tempString length] == 0) + tempString = [from1 personal]; + if (tempString == nil || [tempString length] == 0) { - fromString1 = [from1 address]; - if (fromString1 == nil) - fromString1 = @""; + fromString1 = [from1 address]; + if (fromString1 == nil) + fromString1 = @""; } - else + else { - fromString1 = tempString; + fromString1 = tempString; } - tempString = [from2 personal]; - if (tempString == nil || [tempString length] == 0) + tempString = [from2 personal]; + if (tempString == nil || [tempString length] == 0) { - fromString2 = [from2 address]; - if (fromString2 == nil) - fromString2 = @""; + fromString2 = [from2 address]; + if (fromString2 == nil) + fromString2 = @""; } - else + else { - fromString2 = tempString; + fromString2 = tempString; } - result = (int) [fromString1 caseInsensitiveCompare: fromString2]; - if (result == NSOrderedSame) + result = (int) [fromString1 caseInsensitiveCompare: fromString2]; + if (result == NSOrderedSame) { - return [self compareAccordingToNumber: aMessage]; + return [self compareAccordingToNumber: aMessage]; } - else + else { - return result; + return result; } } - (int) reverseCompareAccordingToSender: (CWMessage *) aMessage { - CWInternetAddress *from1, *from2; - NSString *fromString1, *fromString2; - NSString *tempString; - int result; + CWInternetAddress *from1, *from2; + NSString *fromString1, *fromString2; + NSString *tempString; + int result; - from2 = [self from]; - from1 = [aMessage from]; + from2 = [self from]; + from1 = [aMessage from]; - tempString = [from1 personal]; - if (tempString == nil || [tempString length] == 0) + tempString = [from1 personal]; + if (tempString == nil || [tempString length] == 0) { - fromString1 = [from1 address]; - if (fromString1 == nil) - fromString1 = @""; + fromString1 = [from1 address]; + if (fromString1 == nil) + fromString1 = @""; } - else + else { - fromString1 = tempString; + fromString1 = tempString; } - tempString = [from2 personal]; - if (tempString == nil || [tempString length] == 0) + tempString = [from2 personal]; + if (tempString == nil || [tempString length] == 0) { - fromString2 = [from2 address]; - if (fromString2 == nil) - fromString2 = @""; + fromString2 = [from2 address]; + if (fromString2 == nil) + fromString2 = @""; } - else + else { - fromString2 = tempString; + fromString2 = tempString; } - result = (int) [fromString1 caseInsensitiveCompare: fromString2]; - - if (result == NSOrderedSame) + result = (int) [fromString1 caseInsensitiveCompare: fromString2]; + + if (result == NSOrderedSame) { - return [self reverseCompareAccordingToNumber: aMessage]; + return [self reverseCompareAccordingToNumber: aMessage]; } - else + else { - return result; + return result; } } - (int) compareAccordingToSubject: (CWMessage *) aMessage { - NSString *subject1 = [self baseSubject]; - NSString *subject2 = [aMessage baseSubject]; - int result; - - if (subject1 == nil) - subject1 = @""; - if (subject2 == nil) - subject2 = @""; + NSString *subject1 = [self baseSubject]; + NSString *subject2 = [aMessage baseSubject]; + int result; - result = (int) [subject1 caseInsensitiveCompare: subject2]; + if (subject1 == nil) + subject1 = @""; + if (subject2 == nil) + subject2 = @""; - if (result == NSOrderedSame) + result = (int) [subject1 caseInsensitiveCompare: subject2]; + + if (result == NSOrderedSame) { - return [self compareAccordingToNumber: aMessage]; + return [self compareAccordingToNumber: aMessage]; } - else + else { - return result; + return result; } } - (int) reverseCompareAccordingToSubject: (CWMessage *) aMessage { - NSString *subject2 = [self baseSubject]; - NSString *subject1 = [aMessage baseSubject]; - int result; - - if (subject1 == nil) - subject1 = @""; - if (subject2 == nil) - subject2 = @""; + NSString *subject2 = [self baseSubject]; + NSString *subject1 = [aMessage baseSubject]; + int result; + + if (subject1 == nil) + subject1 = @""; + if (subject2 == nil) + subject2 = @""; - result = (int) [subject1 caseInsensitiveCompare: subject2]; + result = (int) [subject1 caseInsensitiveCompare: subject2]; - if (result == NSOrderedSame) + if (result == NSOrderedSame) { - return [self compareAccordingToNumber: aMessage]; + return [self compareAccordingToNumber: aMessage]; } - else + else { - return result; + return result; } } - (int) compareAccordingToSize: (CWMessage *) aMessage { - NSUInteger size1 = [self size]; - NSUInteger size2 = [aMessage size]; + NSUInteger size1 = [self size]; + NSUInteger size2 = [aMessage size]; - if (size1 < size2) + if (size1 < size2) { - return NSOrderedAscending; + return NSOrderedAscending; } - else if (size1 > size2) + else if (size1 > size2) { - return NSOrderedDescending; + return NSOrderedDescending; } - else + else { - return [self compareAccordingToNumber: aMessage]; + return [self compareAccordingToNumber: aMessage]; } } - (int) reverseCompareAccordingToSize: (CWMessage *) aMessage { - NSUInteger size1 = [aMessage size]; - NSUInteger size2 = [self size]; + NSUInteger size1 = [aMessage size]; + NSUInteger size2 = [self size]; - if (size1 < size2) + if (size1 < size2) { - return NSOrderedAscending; + return NSOrderedAscending; } - else if (size1 > size2) + else if (size1 > size2) { - return NSOrderedDescending; + return NSOrderedDescending; } - else + else { - return [self reverseCompareAccordingToNumber: aMessage]; + return [self reverseCompareAccordingToNumber: aMessage]; } } @@ -1762,117 +1762,117 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSString *) _computeBaseSubject { - NSMutableString *baseSubject; - NSArray *theMatches; - NSString *aSubject; - NSRange aRange; - - BOOL b1, b2; - NSInteger i; - - aSubject = [self subject]; - - if (!aSubject) - { - return nil; - } - - baseSubject = [NSMutableString stringWithString: aSubject]; - - // - // (1) Convert any RFC 2047 encoded-words in the subject to - // UTF-8 as described in "internationalization - // considerations." Convert all tabs and continuations to - // space. Convert all multiple spaces to a single space. - // - theMatches = [atLeastOneSpaceRegex matchString: baseSubject]; - - for (i = [theMatches count]-1; i >= 0; i--) - { - aRange = [[theMatches objectAtIndex:i] rangeValue]; - - if (CHECK_RANGE(aRange, [baseSubject length])) - { - [baseSubject replaceCharactersInRange: aRange withString:@" "]; - } - } - do - { - b1 = NO; - - // - // (2) Remove all trailing text of the subject that matches - // the subj-trailer ABNF, repeat until no more matches are - // possible. - // - theMatches = [suffixSubjTrailerRegex matchString: baseSubject]; - - if ([theMatches count] > 0) + NSMutableString *baseSubject; + NSArray *theMatches; + NSString *aSubject; + NSRange aRange; + + BOOL b1, b2; + NSInteger i; + + aSubject = [self subject]; + + if (!aSubject) + { + return nil; + } + + baseSubject = [NSMutableString stringWithString: aSubject]; + + // + // (1) Convert any RFC 2047 encoded-words in the subject to + // UTF-8 as described in "internationalization + // considerations." Convert all tabs and continuations to + // space. Convert all multiple spaces to a single space. + // + theMatches = [atLeastOneSpaceRegex matchString: baseSubject]; + + for (i = [theMatches count]-1; i >= 0; i--) + { + aRange = [[theMatches objectAtIndex:i] rangeValue]; + + if (CHECK_RANGE(aRange, [baseSubject length])) { - aRange = [[theMatches objectAtIndex:0] rangeValue]; - - if (CHECK_RANGE(aRange,[baseSubject length])) - { - [baseSubject deleteCharactersInRange: [[theMatches objectAtIndex:0] rangeValue]]; - } - } - do + [baseSubject replaceCharactersInRange: aRange withString:@" "]; + } + } + do + { + b1 = NO; + + // + // (2) Remove all trailing text of the subject that matches + // the subj-trailer ABNF, repeat until no more matches are + // possible. + // + theMatches = [suffixSubjTrailerRegex matchString: baseSubject]; + + if ([theMatches count] > 0) { - b2 = NO; - // - // (3) Remove all prefix text of the subject that matches the - // subj-leader ABNF. - // - theMatches = [prefixSubjLeaderRegex matchString: baseSubject]; - - if ([theMatches count] > 0) + aRange = [[theMatches objectAtIndex:0] rangeValue]; + + if (CHECK_RANGE(aRange,[baseSubject length])) { - aRange = [[theMatches objectAtIndex:0] rangeValue]; - - if (CHECK_RANGE(aRange, [baseSubject length])) + [baseSubject deleteCharactersInRange: [[theMatches objectAtIndex:0] rangeValue]]; + } + } + do + { + b2 = NO; + // + // (3) Remove all prefix text of the subject that matches the + // subj-leader ABNF. + // + theMatches = [prefixSubjLeaderRegex matchString: baseSubject]; + + if ([theMatches count] > 0) + { + aRange = [[theMatches objectAtIndex:0] rangeValue]; + + if (CHECK_RANGE(aRange, [baseSubject length])) { - [baseSubject deleteCharactersInRange: [[theMatches objectAtIndex:0] rangeValue]]; - b2 = YES; + [baseSubject deleteCharactersInRange: [[theMatches objectAtIndex:0] rangeValue]]; + b2 = YES; } } - // - // (4) If there is prefix text of the subject that matches the - // subj-blob ABNF, and removing that prefix leaves a non-empty - // subj-base, then remove the prefix text. - // - theMatches = [prefixSubjBlobRegex matchString: baseSubject]; - - if ([theMatches count] > 0) - { - aRange = [[theMatches objectAtIndex:0] rangeValue]; - if (CHECK_RANGE(aRange, [baseSubject length])) + // + // (4) If there is prefix text of the subject that matches the + // subj-blob ABNF, and removing that prefix leaves a non-empty + // subj-base, then remove the prefix text. + // + theMatches = [prefixSubjBlobRegex matchString: baseSubject]; + + if ([theMatches count] > 0) + { + aRange = [[theMatches objectAtIndex:0] rangeValue]; + if (CHECK_RANGE(aRange, [baseSubject length])) { - [baseSubject deleteCharactersInRange:[[theMatches objectAtIndex:0] rangeValue]]; - b2 = YES; + [baseSubject deleteCharactersInRange:[[theMatches objectAtIndex:0] rangeValue]]; + b2 = YES; } } // // (5) Repeat (3) and (4) until no matches remain. // } while (b2); - // - // (6) If the resulting text begins with the subj-fwd-hdr ABNF - // and ends with the subj-fwd-trl ABNF, remove the - // subj-fwd-hdr and subj-fwd-trl and repeat from step (2). - // - theMatches = [prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex matchString:baseSubject]; - - if ([theMatches count] > 0) + // + // (6) If the resulting text begins with the subj-fwd-hdr ABNF + // and ends with the subj-fwd-trl ABNF, remove the + // subj-fwd-hdr and subj-fwd-trl and repeat from step (2). + // + theMatches = [prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex matchString:baseSubject]; + + if ([theMatches count] > 0) { - [baseSubject deleteCharactersInRange:NSMakeRange(0,5)]; - [baseSubject deleteCharactersInRange:NSMakeRange([baseSubject length] - 1,1)]; - b1 = YES; + [baseSubject deleteCharactersInRange:NSMakeRange(0,5)]; + [baseSubject deleteCharactersInRange:NSMakeRange([baseSubject length] - 1,1)]; + b1 = YES; } } while (b1); - // - // (7) The resulting text is the "base subject" used in the SORT. - // - return baseSubject; + // + // (7) The resulting text is the "base subject" used in the SORT. + // + return baseSubject; } @@ -1880,85 +1880,85 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // // - (void) _extractText: (NSMutableData *) theMutableData - part: (id) thePart - quote: (BOOL *) theBOOL -{ - // - // We now get the right text part of the message. - // - // - if ([thePart isMIMEType: @"text" subType: @"*"]) - { - NSData *d; - - d = [[NSString stringWithData: [CWMIMEUtility plainTextContentFromPart: thePart] charset: [[thePart charset] dataUsingEncoding: NSASCIIStringEncoding]] - dataUsingEncoding: NSUTF8StringEncoding]; - [theMutableData appendData: d]; - *theBOOL = YES; - } - // - // If our message only contains the following part types, we cannot - // represent those in a reply. - // - else if ([thePart isMIMEType: @"application" subType: @"*"] || - [thePart isMIMEType: @"audio" subType: @"*"] || - [thePart isMIMEType: @"image" subType: @"*"] || - [thePart isMIMEType: @"message" subType: @"*"] || - [thePart isMIMEType: @"video" subType: @"*"]) - { - [theMutableData appendData: [@"\t[NON-Text Body part not included]" dataUsingEncoding: NSUTF8StringEncoding]]; - } - // - // We have a multipart type. It can be: - // - // multipart/appledouble, multipart/alternative, multipart/related, - // multipart/mixed or even multipart/report. - // - // We must search for a text part to use in our reply. - // - else if ([thePart isMIMEType: @"multipart" subType: @"*"]) - { - CWMIMEMultipart *aMimeMultipart; - CWPart *aPart; - int i; - - aMimeMultipart = (CWMIMEMultipart *)[thePart content]; - - for (i = 0; i < [aMimeMultipart count]; i++) - { - aPart = [aMimeMultipart partAtIndex: i]; - - // - // We do a full verification on the Content-Type since we might - // have a text/x-{something} like text/x-vcard. - // - if ([aPart isMIMEType: @"text" subType: @"plain"] || - [aPart isMIMEType: @"text" subType: @"enriched"] || - [aPart isMIMEType: @"text" subType: @"html"]) - { - [theMutableData appendData: [[NSString stringWithData: [CWMIMEUtility plainTextContentFromPart: aPart] - charset: [[aPart charset] dataUsingEncoding: NSASCIIStringEncoding]] - dataUsingEncoding: NSUTF8StringEncoding]]; - - // If our original Content-Type is multipart/alternative, no need to - // consider to the other text/* parts. Otherwise, we just append - // all text/* parts. - if ([thePart isMIMEType: @"multipart" subType: @"alternative"]) - { - break; - } - } - // - // If we got any other kind of multipart parts, we loop inside of it in order to - // extract all text parts. - // - else if ([aPart isMIMEType: @"multipart" subType: @"*"]) - { - [self _extractText: theMutableData part: aPart quote: theBOOL]; - } - } // for ( ... ) - - *theBOOL = YES; + part: (id) thePart + quote: (BOOL *) theBOOL +{ + // + // We now get the right text part of the message. + // + // + if ([thePart isMIMEType: @"text" subType: @"*"]) + { + NSData *d; + + d = [[NSString stringWithData: [CWMIMEUtility plainTextContentFromPart: thePart] charset: [[thePart charset] dataUsingEncoding: NSASCIIStringEncoding]] + dataUsingEncoding: NSUTF8StringEncoding]; + [theMutableData appendData: d]; + *theBOOL = YES; + } + // + // If our message only contains the following part types, we cannot + // represent those in a reply. + // + else if ([thePart isMIMEType: @"application" subType: @"*"] || + [thePart isMIMEType: @"audio" subType: @"*"] || + [thePart isMIMEType: @"image" subType: @"*"] || + [thePart isMIMEType: @"message" subType: @"*"] || + [thePart isMIMEType: @"video" subType: @"*"]) + { + [theMutableData appendData: [@"\t[NON-Text Body part not included]" dataUsingEncoding: NSUTF8StringEncoding]]; + } + // + // We have a multipart type. It can be: + // + // multipart/appledouble, multipart/alternative, multipart/related, + // multipart/mixed or even multipart/report. + // + // We must search for a text part to use in our reply. + // + else if ([thePart isMIMEType: @"multipart" subType: @"*"]) + { + CWMIMEMultipart *aMimeMultipart; + CWPart *aPart; + int i; + + aMimeMultipart = (CWMIMEMultipart *)[thePart content]; + + for (i = 0; i < [aMimeMultipart count]; i++) + { + aPart = [aMimeMultipart partAtIndex: i]; + + // + // We do a full verification on the Content-Type since we might + // have a text/x-{something} like text/x-vcard. + // + if ([aPart isMIMEType: @"text" subType: @"plain"] || + [aPart isMIMEType: @"text" subType: @"enriched"] || + [aPart isMIMEType: @"text" subType: @"html"]) + { + [theMutableData appendData: [[NSString stringWithData: [CWMIMEUtility plainTextContentFromPart: aPart] + charset: [[aPart charset] dataUsingEncoding: NSASCIIStringEncoding]] + dataUsingEncoding: NSUTF8StringEncoding]]; + + // If our original Content-Type is multipart/alternative, no need to + // consider to the other text/* parts. Otherwise, we just append + // all text/* parts. + if ([thePart isMIMEType: @"multipart" subType: @"alternative"]) + { + break; + } + } + // + // If we got any other kind of multipart parts, we loop inside of it in order to + // extract all text parts. + // + else if ([aPart isMIMEType: @"multipart" subType: @"*"]) + { + [self _extractText: theMutableData part: aPart quote: theBOOL]; + } + } // for ( ... ) + + *theBOOL = YES; } // else if ([thePart isMIMEType: @"multipart" subType: @"*"]) } @@ -1968,32 +1968,32 @@ static CWRegEx *prefixSubjFwdHdrAndSuffixSubjFwdTrlRegex = nil; // - (NSData *) _formatRecipientsWithType: (int) theType { - NSMutableData *aMutableData; - int i; + NSMutableData *aMutableData; + int i; - aMutableData = [[NSMutableData alloc] init]; + aMutableData = [[NSMutableData alloc] init]; - for (i = 0; i < [_recipients count]; i++) + for (i = 0; i < [_recipients count]; i++) { - CWInternetAddress *anInternetAddress; + CWInternetAddress *anInternetAddress; - anInternetAddress = [_recipients objectAtIndex: i]; + anInternetAddress = [_recipients objectAtIndex: i]; - if ([anInternetAddress type] == theType) - { - [aMutableData appendData: [anInternetAddress dataValue]]; - [aMutableData appendCString: ", "]; - } + if ([anInternetAddress type] == theType) + { + [aMutableData appendData: [anInternetAddress dataValue]]; + [aMutableData appendCString: ", "]; + } } - - if ([aMutableData length] > 0) + + if ([aMutableData length] > 0) { - [aMutableData setLength: [aMutableData length]-2]; - return AUTORELEASE(aMutableData); + [aMutableData setLength: [aMutableData length]-2]; + return AUTORELEASE(aMutableData); } - - RELEASE(aMutableData); - return nil; + + RELEASE(aMutableData); + return nil; } @end diff --git a/pantomime-lib/Framework/Pantomime/CWParser.m b/pantomime-lib/Framework/Pantomime/CWParser.m index 0dacfc9..927857d 100644 --- a/pantomime-lib/Framework/Pantomime/CWParser.m +++ b/pantomime-lib/Framework/Pantomime/CWParser.m @@ -1,24 +1,24 @@ /* -** CWParser.m -** -** Copyright (c) 2001-2007 -** -** Author: Ludovic Marcotte -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ + ** CWParser.m + ** + ** Copyright (c) 2001-2007 + ** + ** Author: Ludovic Marcotte + ** + ** This library is free software; you can redistribute it and/or + ** modify it under the terms of the GNU Lesser General Public + ** License as published by the Free Software Foundation; either + ** version 2.1 of the License, or (at your option) any later version. + ** + ** This library is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + ** Lesser General Public License for more details. + ** + ** You should have received a copy of the GNU Lesser General Public + ** License along with this library; if not, write to the Free Software + ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ #import "Pantomime/CWParser.h" @@ -53,47 +53,47 @@ static char *month_name[12] = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"}; static struct _timezone { - char *name; /* time zone name */ - int offset; /* offset, in minutes, EAST of GMT */ + char *name; /* time zone name */ + int offset; /* offset, in minutes, EAST of GMT */ } timezone_info[] = { - - /* the following are from RFC-822 */ - { "ut", 0 }, - { "gmt", 0 }, - { "est", -5*3600 }, { "edt", -4*3600 }, /* USA eastern standard */ - { "cst", -6*3600 }, { "cdt", -5*3600 }, /* USA central standard */ - { "mst", -7*3600 }, { "mdt", -6*3600 }, /* USA mountain standard */ - { "pst", -8*3600 }, { "pdt", -7*3600 }, /* USA pacific standard */ - { "z", 0 }, /* zulu time (the rest of the military codes are bogus) */ - - /* popular European timezones */ - { "wet", 0*3600 }, /* western european */ - { "met", 1*3600 }, /* middle european */ - { "eet", 2*3600 }, /* eastern european */ - { "bst", 1*3600 }, /* ??? british summer time */ - - /* Canadian timezones */ - { "ast", -4*3600 }, { "adt", -3*3600 }, /* atlantic */ - { "nst", -3*1800 },{ "ndt", -2*1800 }, /* newfoundland */ - { "yst", -9*3600 }, { "ydt", -8*3600 }, /* yukon */ - { "hst", -10*3600 }, /* hawaii (not really canada) */ - - /* Asian timezones */ - { "jst", 9*3600 }, /* japan */ - { "sst", 8*3600 }, /* singapore */ - - /* South-Pacific timezones */ - { "nzst", 12*3600 }, { "nzdt", 13*3600 }, /* new zealand */ - { "wst", 8*3600 }, { "wdt", 9*3600 }, /* western australia */ - - /* - * Daylight savings modifiers. These are not real timezones. - * They are used for things like "met dst". The "met" timezone - * is 1*3600, and applying the "dst" modifier makes it 2*3600. - */ - { "dst", 1*3600 }, - { "dt", 1*3600 }, - { "st", 1*3600 } + + /* the following are from RFC-822 */ + { "ut", 0 }, + { "gmt", 0 }, + { "est", -5*3600 }, { "edt", -4*3600 }, /* USA eastern standard */ + { "cst", -6*3600 }, { "cdt", -5*3600 }, /* USA central standard */ + { "mst", -7*3600 }, { "mdt", -6*3600 }, /* USA mountain standard */ + { "pst", -8*3600 }, { "pdt", -7*3600 }, /* USA pacific standard */ + { "z", 0 }, /* zulu time (the rest of the military codes are bogus) */ + + /* popular European timezones */ + { "wet", 0*3600 }, /* western european */ + { "met", 1*3600 }, /* middle european */ + { "eet", 2*3600 }, /* eastern european */ + { "bst", 1*3600 }, /* ??? british summer time */ + + /* Canadian timezones */ + { "ast", -4*3600 }, { "adt", -3*3600 }, /* atlantic */ + { "nst", -3*1800 },{ "ndt", -2*1800 }, /* newfoundland */ + { "yst", -9*3600 }, { "ydt", -8*3600 }, /* yukon */ + { "hst", -10*3600 }, /* hawaii (not really canada) */ + + /* Asian timezones */ + { "jst", 9*3600 }, /* japan */ + { "sst", 8*3600 }, /* singapore */ + + /* South-Pacific timezones */ + { "nzst", 12*3600 }, { "nzdt", 13*3600 }, /* new zealand */ + { "wst", 8*3600 }, { "wdt", 9*3600 }, /* western australia */ + + /* + * Daylight savings modifiers. These are not real timezones. + * They are used for things like "met dst". The "met" timezone + * is 1*3600, and applying the "dst" modifier makes it 2*3600. + */ + { "dst", 1*3600 }, + { "dt", 1*3600 }, + { "st", 1*3600 } }; // @@ -101,22 +101,22 @@ static struct _timezone { // NSInteger next_word(unsigned char *buf, NSUInteger start, NSUInteger len, unsigned char *word) { - unsigned char *p; - NSUInteger i; + unsigned char *p; + NSUInteger i; - for (p = buf+start, i = start; (isspace(*p) || *p == ','); ++p, ++i); - - if (start >= len) return -1; + for (p = buf+start, i = start; (isspace(*p) || *p == ','); ++p, ++i); - while (i < len && !(isspace(*p) || *p == ',')) + if (start >= len) return -1; + + while (i < len && !(isspace(*p) || *p == ',')) { - *word++ = *p++; - i++; + *word++ = *p++; + i++; } - - *word = '\0'; - return p-buf-start; + *word = '\0'; + + return p-buf-start; } // MARK: - private interface @@ -137,13 +137,13 @@ NSInteger next_word(unsigned char *buf, NSUInteger start, NSUInteger len, unsign + (void) parseContentDescription: (NSData *) theLine inPart: (CWPart *) thePart { - NSData *aData; + NSData *aData; - aData = [[theLine subdataFromIndex: 20] dataByTrimmingWhiteSpaces]; + aData = [[theLine subdataFromIndex: 20] dataByTrimmingWhiteSpaces]; - if (aData && [aData length]) + if (aData && [aData length]) { - [thePart setContentDescription: [[aData dataFromQuotedData] asciiString] ]; + [thePart setContentDescription: [[aData dataFromQuotedData] asciiString] ]; } } @@ -188,26 +188,26 @@ NSInteger next_word(unsigned char *buf, NSUInteger start, NSUInteger len, unsign // // + (void) parseContentID: (NSData *) theLine - inPart: (CWPart *) thePart + inPart: (CWPart *) thePart { - if ([theLine length] > 12) + if ([theLine length] > 12) { - NSData *aData; - - aData = [theLine subdataFromIndex: 12]; - - if ([aData hasCPrefix: "<"] && [aData hasCSuffix: ">"]) - { - [thePart setContentID: [[aData subdataWithRange: NSMakeRange(1, [aData length]-2)] asciiString]]; - } - else - { - [thePart setContentID: [aData asciiString]]; - } + NSData *aData; + + aData = [theLine subdataFromIndex: 12]; + + if ([aData hasCPrefix: "<"] && [aData hasCSuffix: ">"]) + { + [thePart setContentID: [[aData subdataWithRange: NSMakeRange(1, [aData length]-2)] asciiString]]; + } + else + { + [thePart setContentID: [aData asciiString]]; + } } - else + else { - [thePart setContentID: @""]; + [thePart setContentID: @""]; } } @@ -218,36 +218,36 @@ NSInteger next_word(unsigned char *buf, NSUInteger start, NSUInteger len, unsign + (void) parseContentTransferEncoding: (NSData *) theLine inPart: (CWPart *) thePart { - if ([theLine length] > 26) + if ([theLine length] > 26) { - NSData *aData; - - aData = [[theLine subdataFromIndex: 26] dataByTrimmingWhiteSpaces]; - - if ([aData caseInsensitiveCCompare: "quoted-printable"] == NSOrderedSame) - { - [thePart setContentTransferEncoding: PantomimeEncodingQuotedPrintable]; - } - else if ([aData caseInsensitiveCCompare: "base64"] == NSOrderedSame) - { - [thePart setContentTransferEncoding: PantomimeEncodingBase64]; - } - else if ([aData caseInsensitiveCCompare: "8bit"] == NSOrderedSame) - { - [thePart setContentTransferEncoding: PantomimeEncoding8bit]; - } - else if ([aData caseInsensitiveCCompare: "binary"] == NSOrderedSame) - { - [thePart setContentTransferEncoding: PantomimeEncodingBinary]; - } - else - { - [thePart setContentTransferEncoding: PantomimeEncodingNone]; - } + NSData *aData; + + aData = [[theLine subdataFromIndex: 26] dataByTrimmingWhiteSpaces]; + + if ([aData caseInsensitiveCCompare: "quoted-printable"] == NSOrderedSame) + { + [thePart setContentTransferEncoding: PantomimeEncodingQuotedPrintable]; + } + else if ([aData caseInsensitiveCCompare: "base64"] == NSOrderedSame) + { + [thePart setContentTransferEncoding: PantomimeEncodingBase64]; + } + else if ([aData caseInsensitiveCCompare: "8bit"] == NSOrderedSame) + { + [thePart setContentTransferEncoding: PantomimeEncoding8bit]; + } + else if ([aData caseInsensitiveCCompare: "binary"] == NSOrderedSame) + { + [thePart setContentTransferEncoding: PantomimeEncodingBinary]; + } + else + { + [thePart setContentTransferEncoding: PantomimeEncodingNone]; + } } - else + else { - [thePart setContentTransferEncoding: PantomimeEncodingNone]; + [thePart setContentTransferEncoding: PantomimeEncodingNone]; } } @@ -268,96 +268,96 @@ NSRange shrinkRange(NSRange range) // // + (void) parseContentType: (NSData *) theLine - inPart: (CWPart *) thePart + inPart: (CWPart *) thePart { - NSRange aRange; - NSData *aData; - NSInteger x; + NSRange aRange; + NSData *aData; + NSInteger x; - if ([theLine length] <= 14) + if ([theLine length] <= 14) { - [thePart setContentType: @"text/plain"]; - return; + [thePart setContentType: @"text/plain"]; + return; } - aData = [[theLine subdataFromIndex: 13] dataByTrimmingWhiteSpaces]; + aData = [[theLine subdataFromIndex: 13] dataByTrimmingWhiteSpaces]; - // We first skip the parameters, if we need to - x = [aData indexOfCharacter: ';']; - if (x > 0) + // We first skip the parameters, if we need to + x = [aData indexOfCharacter: ';']; + if (x > 0) { - aData = [aData subdataToIndex: x]; - } - - // We see if there's a subtype specified for text, if none was specified, we append "/plain" - x = [aData indexOfCharacter: '/']; + aData = [aData subdataToIndex: x]; + } + + // We see if there's a subtype specified for text, if none was specified, we append "/plain" + x = [aData indexOfCharacter: '/']; - if (x < 0 && [aData hasCaseInsensitiveCPrefix: "text"]) + if (x < 0 && [aData hasCaseInsensitiveCPrefix: "text"]) { - [thePart setContentType: [[[aData asciiString] stringByAppendingString: @"/plain"] lowercaseString]]; + [thePart setContentType: [[[aData asciiString] stringByAppendingString: @"/plain"] lowercaseString]]; } - else + else { - [thePart setContentType: [[aData asciiString] lowercaseString]]; + [thePart setContentType: [[aData asciiString] lowercaseString]]; } - // - // We decode our boundary (if we need to) - // - aRange = shrinkRange([theLine rangeOfCString: "boundary=" options: NSCaseInsensitiveSearch]); - - if (aRange.location != NSNotFound) + // + // We decode our boundary (if we need to) + // + aRange = shrinkRange([theLine rangeOfCString: "boundary=" options: NSCaseInsensitiveSearch]); + + if (aRange.location != NSNotFound) { - [thePart setBoundary: [CWParser _parameterValueUsingLine: theLine range: aRange decode: NO charset: nil]]; + [thePart setBoundary: [CWParser _parameterValueUsingLine: theLine range: aRange decode: NO charset: nil]]; } - // - // We decode our charset (if we need to) - // - aRange = shrinkRange([theLine rangeOfCString: "charset=" options: NSCaseInsensitiveSearch]); - - if (aRange.location != NSNotFound) + // + // We decode our charset (if we need to) + // + aRange = shrinkRange([theLine rangeOfCString: "charset=" options: NSCaseInsensitiveSearch]); + + if (aRange.location != NSNotFound) { - [thePart setCharset: [[CWParser _parameterValueUsingLine: theLine range: aRange decode: NO charset: nil] asciiString]]; + [thePart setCharset: [[CWParser _parameterValueUsingLine: theLine range: aRange decode: NO charset: nil] asciiString]]; } - - // - // We decode our format (if we need to). See RFC2646. - // - aRange = shrinkRange([theLine rangeOfCString: "format=" options: NSCaseInsensitiveSearch]); - - if (aRange.location != NSNotFound) + + // + // We decode our format (if we need to). See RFC2646. + // + aRange = shrinkRange([theLine rangeOfCString: "format=" options: NSCaseInsensitiveSearch]); + + if (aRange.location != NSNotFound) { - NSData *aFormat; - - aFormat = [CWParser _parameterValueUsingLine: theLine range: aRange decode: NO charset: nil]; - - if ([aFormat caseInsensitiveCCompare: "flowed"] == NSOrderedSame) - { - [thePart setFormat: PantomimeFormatFlowed]; - } - else - { - [thePart setFormat: PantomimeFormatUnknown]; - } + NSData *aFormat; + + aFormat = [CWParser _parameterValueUsingLine: theLine range: aRange decode: NO charset: nil]; + + if ([aFormat caseInsensitiveCCompare: "flowed"] == NSOrderedSame) + { + [thePart setFormat: PantomimeFormatFlowed]; + } + else + { + [thePart setFormat: PantomimeFormatUnknown]; + } } - else + else { - [thePart setFormat: PantomimeFormatUnknown]; + [thePart setFormat: PantomimeFormatUnknown]; } - // - // We decode the parameter "name" if the thePart is an instance of Part - // - if ([thePart isKindOfClass: [CWPart class]]) - { - aRange = [theLine rangeOfCString: "name=" options: NSCaseInsensitiveSearch]; + // + // We decode the parameter "name" if the thePart is an instance of Part + // + if ([thePart isKindOfClass: [CWPart class]]) + { + aRange = [theLine rangeOfCString: "name=" options: NSCaseInsensitiveSearch]; - if (aRange.location != NSNotFound) - { - [thePart setFilename: [CWParser _parameterValueUsingLine: theLine range: aRange decode: YES charset: [thePart defaultCharset]]]; - } - } + if (aRange.location != NSNotFound) + { + [thePart setFilename: [CWParser _parameterValueUsingLine: theLine range: aRange decode: YES charset: [thePart defaultCharset]]]; + } + } } @@ -365,7 +365,7 @@ NSRange shrinkRange(NSRange range) // // + (void) parseDate: (NSData *) theLine - inMessage: (CWMessage *) theMessage + inMessage: (CWMessage *) theMessage { if ([[theLine asciiString] containsString:@"__Smtpdate"]) { // We have seen spammer to use this date: "Date: __Smtpdate", which we consider invalid. @@ -373,160 +373,160 @@ NSRange shrinkRange(NSRange range) return; } - if ([theLine length] > 6) + if ([theLine length] > 6) { - NSData *aData; + NSData *aData; NSInteger month; int day, year, hours, mins, secs; - NSUInteger tz, i, j, len, tot, s; - unsigned char *bytes, *word; - - aData = [theLine subdataFromIndex: 6]; - - word = malloc(256); - *word = '\0'; - - //LogInfo(@"Have to parse |%@|", [aData asciiString]); - - bytes = (unsigned char*)[aData bytes]; - tot = [aData length]; - i = len = 0; - s = 0; - tz = 0; - - // date-time = [ day-of-week "," ] date FWS time [CFWS] - // day-of-week = ([FWS] day-name) / obs-day-of-week - // day-name = "Mon" / "Tue" / "Wed" / "Thu" / - // "Fri" / "Sat" / "Sun" - // date = day month year - // year = 4*DIGIT / obs-year - // month = (FWS month-name FWS) / obs-month - // month-name = "Jan" / "Feb" / "Mar" / "Apr" / - // "May" / "Jun" / "Jul" / "Aug" / - // "Sep" / "Oct" / "Nov" / "Dec" - // - // day = ([FWS] 1*2DIGIT) / obs-day - // time = time-of-day FWS zone - // time-of-day = hour ":" minute [ ":" second ] - // hour = 2DIGIT / obs-hour - // minute = 2DIGIT / obs-minute - // second = 2DIGIT / obs-second - // zone = (( "+" / "-" ) 4DIGIT) / obs-zone - // - // We need to handle RFC2822 and UNIX time: - // - // Date: Wed, 02 Jan 2002 09:07:19 -0700 - // Date: 02 Jan 2002 19:57:49 +0000 - // - // And broken dates such as: - // - // Date: Thu, 03 Jan 2002 16:40:30 GMT - // Date: Wed, 2 Jan 2002 08:56:18 -0700 (MST) - // Date: Wed, 9 Jan 2002 10:04:23 -0500 (Eastern Standard Time) - // Date: 11-Jan-02 - // Date: Tue, 15 Jan 2002 15:45:53 -0801 - // Date: Thu, 17 Jan 2002 11:54:11 -0900
- // - //while (i < tot && isspace(*bytes)) - // { - // i++; bytes++; - // } - - len = next_word(bytes, i, tot, word); if (len <= 0) { free(word); return; } - - if (isalpha(*word)) - { - //LogInfo(@"UNIX DATE"); - - // We skip the first word, no need for it. - i += len+1; len = next_word(bytes, i, tot, word); if (len <= 0) { free(word); return; } - } - - - month = year = -1; - - // We got a RFC 822 date. The syntax is: - // day month year hh:mm:ss zone - // For example: 03 Apr 2003 17:27:06 +0200 - //LogInfo(@"RFC-822 time"); - day = atoi((const char*)word); - - //printf("len = %d |%s| day = %d\n", len, word, day); - - // We get the month name and we convert it. - i += len+1; len = next_word(bytes, i, tot, word); if (len <= 0) { free(word); return; } - - for (j = 0; j < 12; j++) - { - if (strncasecmp((const char*)word, month_name[j], 3) == 0) - { - month = j+1; - } - } - - if (month < 0) { free(word); return; } - - //printf("len = %d |%s| month = %d\n", len, word, month); - - // We get the year. - i += len+1; len = next_word(bytes, i, tot, word); if (len <= 0) { free(word); return; } - year = atoi((const char*)word); - - if (year < 70) year += 2000; - if (year < 100) year += 1900; - - //printf("len = %d |%s| year = %d\n", len, word, year); - - // We parse the time using the hh:mm:ss format. - i += len+1; len = next_word(bytes, i, tot, word); if (len <= 0) { free(word); return; } - sscanf((const char*)word, "%d:%d:%d", &hours, &mins, &secs); - //printf("len = %d |%s| %d:%d:%d\n", len, word, hours, mins, secs); - - // We parse the timezone. - i += len+1; len = next_word(bytes, i, tot, word); - - if (len <= 0) - { - tz = 0; - } - else - { - unsigned char *p; - - p = word; - - if (*p == '-' || *p == '+') - { - s = (*p == '-' ? -1 : 1); - p++; - } - - len = strlen((const char*)p); - - if (isdigit(*p)) - { - if (len == 2) - { - tz = (*(p)-48)*36000+*((p+1)-48)*3600; - } - else - { - tz = (*(p)-48)*36000+(*(p+1)-48)*3600+(*(p+2)-48)*10+(*(p+3)-48); - } - } - else - { - for (j = 0; j < sizeof(timezone_info)/sizeof(timezone_info[0]); j++) - { - if (strncasecmp((const char*)p, timezone_info[j].name, len) == 0) - { - tz = timezone_info[j].offset; - } - } - } - tz = s*tz; - } + NSUInteger tz, i, j, len, tot, s; + unsigned char *bytes, *word; + + aData = [theLine subdataFromIndex: 6]; + + word = malloc(256); + *word = '\0'; + + //LogInfo(@"Have to parse |%@|", [aData asciiString]); + + bytes = (unsigned char*)[aData bytes]; + tot = [aData length]; + i = len = 0; + s = 0; + tz = 0; + + // date-time = [ day-of-week "," ] date FWS time [CFWS] + // day-of-week = ([FWS] day-name) / obs-day-of-week + // day-name = "Mon" / "Tue" / "Wed" / "Thu" / + // "Fri" / "Sat" / "Sun" + // date = day month year + // year = 4*DIGIT / obs-year + // month = (FWS month-name FWS) / obs-month + // month-name = "Jan" / "Feb" / "Mar" / "Apr" / + // "May" / "Jun" / "Jul" / "Aug" / + // "Sep" / "Oct" / "Nov" / "Dec" + // + // day = ([FWS] 1*2DIGIT) / obs-day + // time = time-of-day FWS zone + // time-of-day = hour ":" minute [ ":" second ] + // hour = 2DIGIT / obs-hour + // minute = 2DIGIT / obs-minute + // second = 2DIGIT / obs-second + // zone = (( "+" / "-" ) 4DIGIT) / obs-zone + // + // We need to handle RFC2822 and UNIX time: + // + // Date: Wed, 02 Jan 2002 09:07:19 -0700 + // Date: 02 Jan 2002 19:57:49 +0000 + // + // And broken dates such as: + // + // Date: Thu, 03 Jan 2002 16:40:30 GMT + // Date: Wed, 2 Jan 2002 08:56:18 -0700 (MST) + // Date: Wed, 9 Jan 2002 10:04:23 -0500 (Eastern Standard Time) + // Date: 11-Jan-02 + // Date: Tue, 15 Jan 2002 15:45:53 -0801 + // Date: Thu, 17 Jan 2002 11:54:11 -0900
+ // + //while (i < tot && isspace(*bytes)) + // { + // i++; bytes++; + // } + + len = next_word(bytes, i, tot, word); if (len <= 0) { free(word); return; } + + if (isalpha(*word)) + { + //LogInfo(@"UNIX DATE"); + + // We skip the first word, no need for it. + i += len+1; len = next_word(bytes, i, tot, word); if (len <= 0) { free(word); return; } + } + + + month = year = -1; + + // We got a RFC 822 date. The syntax is: + // day month year hh:mm:ss zone + // For example: 03 Apr 2003 17:27:06 +0200 + //LogInfo(@"RFC-822 time"); + day = atoi((const char*)word); + + //printf("len = %d |%s| day = %d\n", len, word, day); + + // We get the month name and we convert it. + i += len+1; len = next_word(bytes, i, tot, word); if (len <= 0) { free(word); return; } + + for (j = 0; j < 12; j++) + { + if (strncasecmp((const char*)word, month_name[j], 3) == 0) + { + month = j+1; + } + } + + if (month < 0) { free(word); return; } + + //printf("len = %d |%s| month = %d\n", len, word, month); + + // We get the year. + i += len+1; len = next_word(bytes, i, tot, word); if (len <= 0) { free(word); return; } + year = atoi((const char*)word); + + if (year < 70) year += 2000; + if (year < 100) year += 1900; + + //printf("len = %d |%s| year = %d\n", len, word, year); + + // We parse the time using the hh:mm:ss format. + i += len+1; len = next_word(bytes, i, tot, word); if (len <= 0) { free(word); return; } + sscanf((const char*)word, "%d:%d:%d", &hours, &mins, &secs); + //printf("len = %d |%s| %d:%d:%d\n", len, word, hours, mins, secs); + + // We parse the timezone. + i += len+1; len = next_word(bytes, i, tot, word); + + if (len <= 0) + { + tz = 0; + } + else + { + unsigned char *p; + + p = word; + + if (*p == '-' || *p == '+') + { + s = (*p == '-' ? -1 : 1); + p++; + } + + len = strlen((const char*)p); + + if (isdigit(*p)) + { + if (len == 2) + { + tz = (*(p)-48)*36000+*((p+1)-48)*3600; + } + else + { + tz = (*(p)-48)*36000+(*(p+1)-48)*3600+(*(p+2)-48)*10+(*(p+3)-48); + } + } + else + { + for (j = 0; j < sizeof(timezone_info)/sizeof(timezone_info[0]); j++) + { + if (strncasecmp((const char*)p, timezone_info[j].name, len) == 0) + { + tz = timezone_info[j].offset; + } + } + } + tz = s*tz; + } NSCalendar *calendar = [NSCalendar currentCalendar]; NSDateComponents *components = [[NSDateComponents alloc] init]; [components setDay:day]; @@ -538,8 +538,8 @@ NSRange shrinkRange(NSRange range) [components setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT: tz]]; NSDate *date = [calendar dateFromComponents:components]; - [theMessage setOriginationDate:date]; - free(word); + [theMessage setOriginationDate:date]; + free(word); } } @@ -547,123 +547,123 @@ NSRange shrinkRange(NSRange range) // // + (NSData *) parseDestination: (NSData *) theLine - forType: (PantomimeRecipientType) theType - inMessage: (CWMessage *) theMessage - quick: (BOOL) theBOOL + forType: (PantomimeRecipientType) theType + inMessage: (CWMessage *) theMessage + quick: (BOOL) theBOOL { - CWInternetAddress *anInternetAddress; - NSData *aData; + CWInternetAddress *anInternetAddress; + NSData *aData; - NSUInteger i, len, s_len, x, y; - unsigned char *bytes; - BOOL b; + NSUInteger i, len, s_len, x, y; + unsigned char *bytes; + BOOL b; - len = 0; - if (theBOOL) + len = 0; + if (theBOOL) { - aData = theLine; + aData = theLine; } - else + else { - switch (theType) - { - case PantomimeBccRecipient: - len = 5; - break; - - case PantomimeCcRecipient: - case PantomimeToRecipient: - len = 4; - break; - - case PantomimeResentBccRecipient: - len = 12; - break; - - case PantomimeResentCcRecipient: - case PantomimeResentToRecipient: - len = 11; - break; - } - - // We skip over emtpy headers. - if (len >= [theLine length]) return [NSData data]; - - aData = [theLine subdataFromIndex: len]; + switch (theType) + { + case PantomimeBccRecipient: + len = 5; + break; + + case PantomimeCcRecipient: + case PantomimeToRecipient: + len = 4; + break; + + case PantomimeResentBccRecipient: + len = 12; + break; + + case PantomimeResentCcRecipient: + case PantomimeResentToRecipient: + len = 11; + break; + } + + // We skip over emtpy headers. + if (len >= [theLine length]) return [NSData data]; + + aData = [theLine subdataFromIndex: len]; } - bytes = (unsigned char*)[aData bytes]; - len = [aData length]; - b = NO; x = 0; + bytes = (unsigned char*)[aData bytes]; + len = [aData length]; + b = NO; x = 0; - for (i = 0; i < len; i++) + for (i = 0; i < len; i++) { - if (*bytes == '"') - { - b = !b; - } - - if (*bytes == ',' || i == len-1) - { - if (b) - { - bytes++; - continue; - } - - y = i; - - // We strip the trailing comma for all but the last entries. - s_len = y-x; - if (i == len-1) s_len++; - - anInternetAddress = [[CWInternetAddress alloc] - initWithString: [CWMIMEUtility decodeHeader: [[aData subdataWithRange: NSMakeRange(x, s_len)] dataByTrimmingWhiteSpaces] - charset: [theMessage defaultCharset]]]; - - [anInternetAddress setType: theType]; - [theMessage addRecipient: anInternetAddress]; - RELEASE(anInternetAddress); - x = y+1; - } - - bytes++; + if (*bytes == '"') + { + b = !b; + } + + if (*bytes == ',' || i == len-1) + { + if (b) + { + bytes++; + continue; + } + + y = i; + + // We strip the trailing comma for all but the last entries. + s_len = y-x; + if (i == len-1) s_len++; + + anInternetAddress = [[CWInternetAddress alloc] + initWithString: [CWMIMEUtility decodeHeader: [[aData subdataWithRange: NSMakeRange(x, s_len)] dataByTrimmingWhiteSpaces] + charset: [theMessage defaultCharset]]]; + + [anInternetAddress setType: theType]; + [theMessage addRecipient: anInternetAddress]; + RELEASE(anInternetAddress); + x = y+1; + } + + bytes++; } - return aData; + return aData; } // // // + (NSData *) parseFrom: (NSData *) theLine - inMessage: (CWMessage *) theMessage - quick: (BOOL) theBOOL; + inMessage: (CWMessage *) theMessage + quick: (BOOL) theBOOL; { - CWInternetAddress *anInternetAddress; - NSData *aData; - - if (!theBOOL && !([theLine length] > 6)) + CWInternetAddress *anInternetAddress; + NSData *aData; + + if (!theBOOL && !([theLine length] > 6)) { - return [NSData data]; + return [NSData data]; } - - if (theBOOL) + + if (theBOOL) { - aData = theLine; + aData = theLine; } - else + else { - aData = [theLine subdataFromIndex: 6]; + aData = [theLine subdataFromIndex: 6]; } - anInternetAddress = [[CWInternetAddress alloc] initWithString: - [CWMIMEUtility decodeHeader: aData charset: [theMessage defaultCharset]] - ]; - [theMessage setFrom: anInternetAddress]; - RELEASE(anInternetAddress); + anInternetAddress = [[CWInternetAddress alloc] initWithString: + [CWMIMEUtility decodeHeader: aData charset: [theMessage defaultCharset]] + ]; + [theMessage setFrom: anInternetAddress]; + RELEASE(anInternetAddress); - return aData; + return aData; } @@ -728,11 +728,11 @@ NSRange shrinkRange(NSRange range) // // + (void) parseMIMEVersion: (NSData *) theLine - inMessage: (CWMessage *) theMessage + inMessage: (CWMessage *) theMessage { - if ([theLine length] > 14) + if ([theLine length] > 14) { - [theMessage setMIMEVersion: [[theLine subdataFromIndex: 14] asciiString]]; + [theMessage setMIMEVersion: [[theLine subdataFromIndex: 14] asciiString]]; } } @@ -777,63 +777,63 @@ NSRange shrinkRange(NSRange range) // // + (void) parseReplyTo: (NSData *) theLine - inMessage: (CWMessage *) theMessage + inMessage: (CWMessage *) theMessage { - if ([theLine length] > 10) + if ([theLine length] > 10) { - CWInternetAddress *anInternetAddress; - NSMutableArray *aMutableArray; - NSData *aData; - - unsigned char *bytes; - NSUInteger i, len, s_len, x, y; - BOOL b; - - aMutableArray = [[NSMutableArray alloc] init]; - aData = [theLine subdataFromIndex: 10]; - bytes = (unsigned char*)[aData bytes]; - len = [aData length]; - b = NO; x = 0; - - for (i = 0; i < len; i++) - { - if (*bytes == '"') - { - b = !b; - } - - if (*bytes == ',' || i == len-1) - { - if (b) - { - bytes++; - continue; - } - - y = i; - - // We strip the trailing comma for all but the last entries. - s_len = y-x; - if (i == len-1) s_len++; - - anInternetAddress = [[CWInternetAddress alloc] - initWithString: [CWMIMEUtility decodeHeader: [[aData subdataWithRange: NSMakeRange(x, s_len)] dataByTrimmingWhiteSpaces] - charset: [theMessage defaultCharset]]]; - - [aMutableArray addObject: anInternetAddress]; - RELEASE(anInternetAddress); - x = y+1; - } - - bytes++; - } - - if ([aMutableArray count]) - { - [theMessage setReplyTo: aMutableArray]; - } - - RELEASE(aMutableArray); + CWInternetAddress *anInternetAddress; + NSMutableArray *aMutableArray; + NSData *aData; + + unsigned char *bytes; + NSUInteger i, len, s_len, x, y; + BOOL b; + + aMutableArray = [[NSMutableArray alloc] init]; + aData = [theLine subdataFromIndex: 10]; + bytes = (unsigned char*)[aData bytes]; + len = [aData length]; + b = NO; x = 0; + + for (i = 0; i < len; i++) + { + if (*bytes == '"') + { + b = !b; + } + + if (*bytes == ',' || i == len-1) + { + if (b) + { + bytes++; + continue; + } + + y = i; + + // We strip the trailing comma for all but the last entries. + s_len = y-x; + if (i == len-1) s_len++; + + anInternetAddress = [[CWInternetAddress alloc] + initWithString: [CWMIMEUtility decodeHeader: [[aData subdataWithRange: NSMakeRange(x, s_len)] dataByTrimmingWhiteSpaces] + charset: [theMessage defaultCharset]]]; + + [aMutableArray addObject: anInternetAddress]; + RELEASE(anInternetAddress); + x = y+1; + } + + bytes++; + } + + if ([aMutableArray count]) + { + [theMessage setReplyTo: aMutableArray]; + } + + RELEASE(aMutableArray); } } @@ -842,18 +842,18 @@ NSRange shrinkRange(NSRange range) // // + (void) parseResentFrom: (NSData *) theLine - inMessage: (CWMessage *) theMessage + inMessage: (CWMessage *) theMessage { - if ([theLine length] > 13) + if ([theLine length] > 13) { - CWInternetAddress *anInternetAddress; - - anInternetAddress = [[CWInternetAddress alloc] initWithString: [CWMIMEUtility decodeHeader: - [theLine subdataFromIndex: 13] - charset: [theMessage defaultCharset]]]; - - [theMessage setResentFrom: anInternetAddress]; - RELEASE(anInternetAddress); + CWInternetAddress *anInternetAddress; + + anInternetAddress = [[CWInternetAddress alloc] initWithString: [CWMIMEUtility decodeHeader: + [theLine subdataFromIndex: 13] + charset: [theMessage defaultCharset]]]; + + [theMessage setResentFrom: anInternetAddress]; + RELEASE(anInternetAddress); } } @@ -862,15 +862,15 @@ NSRange shrinkRange(NSRange range) // // + (void) parseStatus: (NSData *) theLine - inMessage: (CWMessage *) theMessage + inMessage: (CWMessage *) theMessage { - if ([theLine length] > 8) + if ([theLine length] > 8) { - NSData *aData; - - aData = [theLine subdataFromIndex: 8]; - [[theMessage flags] addFlagsFromData: aData format: PantomimeFormatMbox]; - [theMessage addHeader: @"Status" withValue: [aData asciiString]]; + NSData *aData; + + aData = [theLine subdataFromIndex: 8]; + [[theMessage flags] addFlagsFromData: aData format: PantomimeFormatMbox]; + [theMessage addHeader: @"Status" withValue: [aData asciiString]]; } } @@ -879,15 +879,15 @@ NSRange shrinkRange(NSRange range) // // + (void) parseXStatus: (NSData *) theLine - inMessage: (CWMessage *) theMessage + inMessage: (CWMessage *) theMessage { - if ([theLine length] > 10) + if ([theLine length] > 10) { - NSData *aData; + NSData *aData; - aData = [theLine subdataFromIndex: 10]; - [[theMessage flags] addFlagsFromData: aData format: PantomimeFormatMbox]; - [theMessage addHeader: @"X-Status" withValue: [aData asciiString]]; + aData = [theLine subdataFromIndex: 10]; + [[theMessage flags] addFlagsFromData: aData format: PantomimeFormatMbox]; + [theMessage addHeader: @"X-Status" withValue: [aData asciiString]]; } } @@ -896,27 +896,27 @@ NSRange shrinkRange(NSRange range) // // + (NSData *) parseSubject: (NSData *) theLine - inMessage: (CWMessage *) theMessage - quick: (BOOL) theBOOL + inMessage: (CWMessage *) theMessage + quick: (BOOL) theBOOL { - NSData *aData; + NSData *aData; - if (theBOOL) + if (theBOOL) { - aData = theLine; + aData = theLine; } - else if ([theLine length] > 9) + else if ([theLine length] > 9) { - aData = [[theLine subdataFromIndex: 8] dataByTrimmingWhiteSpaces]; + aData = [[theLine subdataFromIndex: 8] dataByTrimmingWhiteSpaces]; } - else + else { - return [NSData data]; + return [NSData data]; } - [theMessage setSubject: [CWMIMEUtility decodeHeader: aData charset: [theMessage defaultCharset]]]; - - return aData; + [theMessage setSubject: [CWMIMEUtility decodeHeader: aData charset: [theMessage defaultCharset]]]; + + return aData; } @@ -924,24 +924,24 @@ NSRange shrinkRange(NSRange range) // // + (void) parseUnknownHeader: (NSData *) theLine - inMessage: (CWMessage *) theMessage + inMessage: (CWMessage *) theMessage { - NSData *aName, *aValue; - NSRange range; + NSData *aName, *aValue; + NSRange range; + + range = [theLine rangeOfCString: ":"]; - range = [theLine rangeOfCString: ":"]; - - if (range.location != NSNotFound) + if (range.location != NSNotFound) { - aName = [theLine subdataWithRange: NSMakeRange(0, range.location)]; - - // we keep only the headers that have a value - if (([theLine length]-range.location-1) > 0) - { - aValue = [theLine subdataWithRange: NSMakeRange(range.location + 2, [theLine length]-range.location-2)]; - - [theMessage addHeader: [aName asciiString] withValue: [aValue asciiString]]; - } + aName = [theLine subdataWithRange: NSMakeRange(0, range.location)]; + + // we keep only the headers that have a value + if (([theLine length]-range.location-1) > 0) + { + aValue = [theLine subdataWithRange: NSMakeRange(range.location + 2, [theLine length]-range.location-2)]; + + [theMessage addHeader: [aName asciiString] withValue: [aValue asciiString]]; + } } } @@ -950,21 +950,21 @@ NSRange shrinkRange(NSRange range) // // + (void) parseOrganization: (NSData *) theLine - inMessage: (CWMessage *) theMessage + inMessage: (CWMessage *) theMessage { - NSString *organization; + NSString *organization; - if ([theLine length] > 14) + if ([theLine length] > 14) { - organization = [CWMIMEUtility decodeHeader: [[theLine subdataFromIndex: 13] dataByTrimmingWhiteSpaces] - charset: [theMessage defaultCharset]]; + organization = [CWMIMEUtility decodeHeader: [[theLine subdataFromIndex: 13] dataByTrimmingWhiteSpaces] + charset: [theMessage defaultCharset]]; } - else + else { - organization = @""; + organization = @""; } - - [theMessage setOrganization: organization]; + + [theMessage setOrganization: organization]; } @end @@ -1069,7 +1069,7 @@ NSRange shrinkRange(NSRange range) value_start++; } NSRange r2 = [inData firstSemicolonOrNewlineInRange:NSMakeRange(NSMaxRange(r1), - len - NSMaxRange(r1))]; + len - NSMaxRange(r1))]; if (r2.location != NSNotFound) { value_end = r2.location; } else { @@ -1108,7 +1108,7 @@ NSRange shrinkRange(NSRange range) length: 0]; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" -// Suppress warning. We need to be able to pass the specified charset + // Suppress warning. We need to be able to pass the specified charset if (decode) { NSString *result = [[NSString alloc] initWithData: resultData encoding: NSASCIIStringEncoding]; diff --git a/pantomime-lib/Framework/Pantomime/CWPart.m b/pantomime-lib/Framework/Pantomime/CWPart.m index 9c0bf02..d0e60b8 100644 --- a/pantomime-lib/Framework/Pantomime/CWPart.m +++ b/pantomime-lib/Framework/Pantomime/CWPart.m @@ -1,24 +1,24 @@ /* -** CWPart.m -** -** Copyright (c) 2001-2007 -** -** Author: Ludovic Marcotte -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ + ** CWPart.m + ** + ** Copyright (c) 2001-2007 + ** + ** Author: Ludovic Marcotte + ** + ** This library is free software; you can redistribute it and/or + ** modify it under the terms of the GNU Lesser General Public + ** License as published by the Free Software Foundation; either + ** version 2.1 of the License, or (at your option) any later version. + ** + ** This library is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + ** Lesser General Public License for more details. + ** + ** You should have received a copy of the GNU Lesser General Public + ** License along with this library; if not, write to the Free Software + ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ #import "CWPart.h" @@ -49,19 +49,19 @@ static int currentPartVersion = 2; - (id) init { - self = [super init]; - - [CWPart setVersion: currentPartVersion]; + self = [super init]; - // We initialize our dictionary that will hold all our headers with a capacity of 25. - // This is an empirical number that is used to speedup the addition of headers w/o - // reallocating our array everytime we add a new element. - _headers = [[NSMutableDictionary alloc] initWithCapacity: 25]; - _parameters = [[NSMutableDictionary alloc] init]; - _line_length = _size = 0; - _content = nil; - - return self; + [CWPart setVersion: currentPartVersion]; + + // We initialize our dictionary that will hold all our headers with a capacity of 25. + // This is an empirical number that is used to speedup the addition of headers w/o + // reallocating our array everytime we add a new element. + _headers = [[NSMutableDictionary alloc] initWithCapacity: 25]; + _parameters = [[NSMutableDictionary alloc] init]; + _line_length = _size = 0; + _content = nil; + + return self; } @@ -70,12 +70,12 @@ static int currentPartVersion = 2; // - (void) dealloc { - RELEASE(_defaultCharset); - RELEASE(_parameters); - RELEASE(_headers); - RELEASE(_content); + RELEASE(_defaultCharset); + RELEASE(_parameters); + RELEASE(_headers); + RELEASE(_content); - //[super dealloc]; + //[super dealloc]; } @@ -84,46 +84,43 @@ static int currentPartVersion = 2; // - (id) initWithData: (NSData *) theData { - NSRange aRange; + NSRange aRange; - aRange = [theData rangeOfCString: "\n\n"]; - - if (aRange.length == 0) + aRange = [theData rangeOfCString: "\n\n"]; + + if (aRange.length == 0) { - AUTORELEASE_VOID(self); - return nil; - } - - // We initialize our message with the headers and the content - self = [self init]; - - [CWPart setVersion: currentPartVersion]; - - // We verify if we have an empty body part content like: - // X-UID: 5dc5aa4b82240000 - // - // This is a MIME Message - // - // ------=_NextPart_000_007F_01BDF6C7.FABAC1B0 - // - // - // ------=_NextPart_000_007F_01BDF6C7.FABAC1B0 - // Content-Type: text/html; name="7english.co.kr.htm" - if ([theData length] == 2) + AUTORELEASE_VOID(self); + return nil; + } + + // We initialize our message with the headers and the content + self = [self init]; + + [CWPart setVersion: currentPartVersion]; + + // We verify if we have an empty body part content like: + // X-UID: 5dc5aa4b82240000 + // + // This is a MIME Message + // + // ------=_NextPart_000_007F_01BDF6C7.FABAC1B0 + // + // + // ------=_NextPart_000_007F_01BDF6C7.FABAC1B0 + // Content-Type: text/html; name="7english.co.kr.htm" + if ([theData length] == 2) { - [self setContent: [NSData data]]; - return self; + [self setContent: [NSData data]]; + return self; } - [self setHeadersFromData: - [theData subdataWithRange: NSMakeRange(0,aRange.location)]]; - [CWMIMEUtility setContentFromRawSource: - [theData subdataWithRange: - NSMakeRange(aRange.location + 2, - [theData length]-(aRange.location+2))] - inPart: self]; + [self setHeadersFromData:[theData subdataWithRange:NSMakeRange(0,aRange.location)]]; + [CWMIMEUtility setContentFromRawSource: + [theData subdataWithRange:NSMakeRange(aRange.location + 2, + [theData length]-(aRange.location+2))] inPart: self]; - return self; + return self; } @@ -133,11 +130,11 @@ static int currentPartVersion = 2; - (id) initWithData: (NSData *) theData charset: (NSString *) theCharset { - [CWPart setVersion: currentPartVersion]; + [CWPart setVersion: currentPartVersion]; + + [self setDefaultCharset: theCharset]; - [self setDefaultCharset: theCharset]; - - return [self initWithData: theData]; + return [self initWithData: theData]; } @@ -146,48 +143,48 @@ static int currentPartVersion = 2; // - (void) encodeWithCoder: (NSCoder *) theCoder { - [CWPart setVersion: currentPartVersion]; + [CWPart setVersion: currentPartVersion]; - [theCoder encodeObject: [self contentType]]; - [theCoder encodeObject: [self contentID]]; - [theCoder encodeObject: [self contentDescription]]; - [theCoder encodeObject: [NSNumber numberWithInt: [self contentDisposition]]]; - [theCoder encodeObject: [self filename]]; - - [theCoder encodeObject: [NSNumber numberWithInteger: [self contentTransferEncoding]]]; + [theCoder encodeObject: [self contentType]]; + [theCoder encodeObject: [self contentID]]; + [theCoder encodeObject: [self contentDescription]]; + [theCoder encodeObject: [NSNumber numberWithInt: [self contentDisposition]]]; + [theCoder encodeObject: [self filename]]; + + [theCoder encodeObject: [NSNumber numberWithInteger: [self contentTransferEncoding]]]; [theCoder encodeObject: [NSNumber numberWithInteger: [self format]]]; - [theCoder encodeObject: [NSNumber numberWithInteger: _size]]; + [theCoder encodeObject: [NSNumber numberWithInteger: _size]]; - [theCoder encodeObject: [self boundary]]; - [theCoder encodeObject: [self charset]]; - [theCoder encodeObject: _defaultCharset]; + [theCoder encodeObject: [self boundary]]; + [theCoder encodeObject: [self charset]]; + [theCoder encodeObject: _defaultCharset]; } - (id) initWithCoder: (NSCoder *) theCoder { - self = [super init]; + self = [super init]; + + _headers = [[NSMutableDictionary alloc] initWithCapacity: 25]; + _parameters = [[NSMutableDictionary alloc] init]; - _headers = [[NSMutableDictionary alloc] initWithCapacity: 25]; - _parameters = [[NSMutableDictionary alloc] init]; + [self setContentType: [theCoder decodeObject]]; + [self setContentID: [theCoder decodeObject]]; + [self setContentDescription: [theCoder decodeObject]]; + [self setContentDisposition: [[theCoder decodeObject] intValue]]; + [self setFilename: [theCoder decodeObject]]; - [self setContentType: [theCoder decodeObject]]; - [self setContentID: [theCoder decodeObject]]; - [self setContentDescription: [theCoder decodeObject]]; - [self setContentDisposition: [[theCoder decodeObject] intValue]]; - [self setFilename: [theCoder decodeObject]]; + [self setContentTransferEncoding: [[theCoder decodeObject] intValue]]; + [self setFormat: [[theCoder decodeObject] intValue]]; + [self setSize: [[theCoder decodeObject] intValue]]; - [self setContentTransferEncoding: [[theCoder decodeObject] intValue]]; - [self setFormat: [[theCoder decodeObject] intValue]]; - [self setSize: [[theCoder decodeObject] intValue]]; + [self setBoundary: [theCoder decodeObject]]; + [self setCharset: [theCoder decodeObject]]; + [self setDefaultCharset: [theCoder decodeObject]]; - [self setBoundary: [theCoder decodeObject]]; - [self setCharset: [theCoder decodeObject]]; - [self setDefaultCharset: [theCoder decodeObject]]; - - _content = nil; + _content = nil; - return self; + return self; } @@ -196,7 +193,7 @@ static int currentPartVersion = 2; // - (NSObject *) content { - return _content; + return _content; } @@ -205,15 +202,15 @@ static int currentPartVersion = 2; // - (void) setContent: (NSObject *) theContent { - if (theContent && !([theContent isKindOfClass: [NSData class]] || - [theContent isKindOfClass: [CWMessage class]] || - [theContent isKindOfClass: [CWMIMEMultipart class]])) + if (theContent && !([theContent isKindOfClass: [NSData class]] || + [theContent isKindOfClass: [CWMessage class]] || + [theContent isKindOfClass: [CWMIMEMultipart class]])) { - [NSException raise: NSInvalidArgumentException - format: @"Invalid argument to CWPart: -setContent: The content MUST be either a NSData, CWMessage or CWMIMEMessage instance."]; + [NSException raise: NSInvalidArgumentException + format: @"Invalid argument to CWPart: -setContent: The content MUST be either a NSData, CWMessage or CWMIMEMessage instance."]; } - ASSIGN(_content, theContent); + ASSIGN(_content, theContent); } // @@ -221,14 +218,14 @@ static int currentPartVersion = 2; // - (NSString *) contentType { - return [_headers objectForKey: @"Content-Type"]; + return [_headers objectForKey: @"Content-Type"]; } - (void) setContentType: (NSString*) theContentType { - if (theContentType) + if (theContentType) { - [_headers setObject: theContentType forKey: @"Content-Type"]; + [_headers setObject: theContentType forKey: @"Content-Type"]; } } @@ -237,15 +234,15 @@ static int currentPartVersion = 2; // - (NSString *) contentID { - return [_headers objectForKey: @"Content-Id"]; + return [_headers objectForKey: @"Content-Id"]; } - (void) setContentID: (NSString *) theContentID { - if (theContentID) + if (theContentID) { - [_headers setObject: theContentID forKey: @"Content-Id"]; - } + [_headers setObject: theContentID forKey: @"Content-Id"]; + } } // @@ -253,15 +250,15 @@ static int currentPartVersion = 2; // - (NSString *) contentDescription { - return [_headers objectForKey: @"Content-Description"]; + return [_headers objectForKey: @"Content-Description"]; } - (void) setContentDescription: (NSString *) theContentDescription { - if (theContentDescription) + if (theContentDescription) { - [_headers setObject: theContentDescription forKey: @"Content-Description"]; - } + [_headers setObject: theContentDescription forKey: @"Content-Description"]; + } } @@ -270,16 +267,16 @@ static int currentPartVersion = 2; // - (PantomimeContentDisposition) contentDisposition { - id o; + id o; - o = [_headers objectForKey: @"Content-Disposition"]; + o = [_headers objectForKey: @"Content-Disposition"]; - return (o ? [o intValue] : PantomimeAttachmentDisposition); + return (o ? [o intValue] : PantomimeAttachmentDisposition); } - (void) setContentDisposition: (PantomimeContentDisposition) theContentDisposition { - [_headers setObject: [NSNumber numberWithInt: theContentDisposition] forKey: @"Content-Disposition"]; + [_headers setObject: [NSNumber numberWithInt: theContentDisposition] forKey: @"Content-Disposition"]; } @@ -288,28 +285,28 @@ static int currentPartVersion = 2; // - (PantomimeEncoding) contentTransferEncoding { - id o; - - o = [_headers objectForKey: @"Content-Transfer-Encoding"]; + id o; - if (o) + o = [_headers objectForKey: @"Content-Transfer-Encoding"]; + + if (o) { - return [o intValue]; + return [o intValue]; } - - // Default value for the Content-Transfer-Encoding. - // See RFC2045 - 6.1. Content-Transfer-Encoding Syntax. - return PantomimeEncodingNone; + + // Default value for the Content-Transfer-Encoding. + // See RFC2045 - 6.1. Content-Transfer-Encoding Syntax. + return PantomimeEncodingNone; } - (void) setContentTransferEncoding: (PantomimeEncoding) theEncoding { - [_headers setObject: [NSNumber numberWithInt: theEncoding] forKey: @"Content-Transfer-Encoding"]; + [_headers setObject: [NSNumber numberWithInt: theEncoding] forKey: @"Content-Transfer-Encoding"]; } - (NSString *)filename { - return [_parameters objectForKey: @"filename"]; + return [_parameters objectForKey: @"filename"]; } - (void)setFilename:(NSString *)theFilename @@ -327,21 +324,21 @@ static int currentPartVersion = 2; // - (PantomimeMessageFormat) format { - id o; + id o; - o = [_parameters objectForKey: @"format"]; + o = [_parameters objectForKey: @"format"]; - if (o) + if (o) { - return [o intValue]; + return [o intValue]; } - return PantomimeFormatUnknown; + return PantomimeFormatUnknown; } - (void) setFormat: (PantomimeMessageFormat) theFormat { - [_parameters setObject: [NSNumber numberWithInt: theFormat] forKey: @"format"]; + [_parameters setObject: [NSNumber numberWithInt: theFormat] forKey: @"format"]; } @@ -350,12 +347,12 @@ static int currentPartVersion = 2; // - (NSUInteger) lineLength { - return _line_length; + return _line_length; } - (void) setLineLength: (int) theLineLength { - _line_length = theLineLength; + _line_length = theLineLength; } @@ -363,33 +360,33 @@ static int currentPartVersion = 2; // This method is used to very if the part is of the following primaryType / subType // - (BOOL) isMIMEType: (NSString *) thePrimaryType - subType: (NSString *) theSubType + subType: (NSString *) theSubType { - NSString *aString; + NSString *aString; - if (![self contentType]) + if (![self contentType]) { - return NO;//[self setContentType: @"text/plain"]; + return NO;//[self setContentType: @"text/plain"]; } - if ([theSubType compare: @"*"] == NSOrderedSame) + if ([theSubType compare: @"*"] == NSOrderedSame) { - if ([[self contentType] hasCaseInsensitivePrefix: thePrimaryType]) - { - return YES; - } + if ([[self contentType] hasCaseInsensitivePrefix: thePrimaryType]) + { + return YES; + } } - else + else { - aString = [NSString stringWithFormat: @"%@/%@", thePrimaryType, theSubType]; - - if ([aString caseInsensitiveCompare: [self contentType]] == NSOrderedSame) - { - return YES; - } + aString = [NSString stringWithFormat: @"%@/%@", thePrimaryType, theSubType]; + + if ([aString caseInsensitiveCompare: [self contentType]] == NSOrderedSame) + { + return YES; + } } - - return NO; + + return NO; } @@ -398,12 +395,12 @@ static int currentPartVersion = 2; // - (long) size { - return _size; + return _size; } - (void) setSize: (NSInteger) theSize { - _size = theSize; + _size = theSize; } - (NSData *)dataValue @@ -416,8 +413,8 @@ static int currentPartVersion = 2; filename = [self filename]; } else { filename = [[NSString alloc] initWithData: [CWMIMEUtility encodeWordUsingQuotedPrintable: [self filename] - prefixLength: 0] - encoding: NSASCIIStringEncoding]; + prefixLength: 0] + encoding: NSASCIIStringEncoding]; } // We encode our Content-Transfer-Encoding header. @@ -436,7 +433,7 @@ static int currentPartVersion = 2; if ([self contentDescription]) { [dataValue appendCString: "Content-Description: "]; [dataValue appendData: [CWMIMEUtility encodeWordUsingQuotedPrintable: [self contentDescription] - prefixLength: 21]]; + prefixLength: 21]]; [dataValue appendCString: LF]; } @@ -545,7 +542,7 @@ static int currentPartVersion = 2; } else if ([self contentTransferEncoding] == PantomimeEncodingBase64) { dataToSend = [dataToSend encodeBase64WithLineLength: 72]; } else if (([self contentTransferEncoding] == PantomimeEncodingNone || [self contentTransferEncoding] == PantomimeEncoding8bit) && - [self format] == PantomimeFormatFlowed) { + [self format] == PantomimeFormatFlowed) { NSUInteger limit = _line_length; if (limit < 2 || limit > 998) { limit = 72; @@ -571,14 +568,14 @@ static int currentPartVersion = 2; // - (NSData *) boundary { - return [_parameters objectForKey: @"boundary"]; + return [_parameters objectForKey: @"boundary"]; } - (void) setBoundary: (NSData *) theBoundary { - if (theBoundary) + if (theBoundary) { - [_parameters setObject: theBoundary forKey: @"boundary"]; + [_parameters setObject: theBoundary forKey: @"boundary"]; } } @@ -588,16 +585,16 @@ static int currentPartVersion = 2; // - (NSData *) protocol { - return [_parameters objectForKey: @"protocol"]; - //return _protocol; + return [_parameters objectForKey: @"protocol"]; + //return _protocol; } - (void) setProtocol: (NSData *) theProtocol { - //ASSIGN(_protocol, theProtocol); - if (theProtocol) + //ASSIGN(_protocol, theProtocol); + if (theProtocol) { - [_parameters setObject: theProtocol forKey: @"protocol"]; + [_parameters setObject: theProtocol forKey: @"protocol"]; } } @@ -607,14 +604,14 @@ static int currentPartVersion = 2; // - (NSString *) charset { - return [_parameters objectForKey: @"charset"]; + return [_parameters objectForKey: @"charset"]; } - (void) setCharset: (NSString *) theCharset { - if (theCharset) + if (theCharset) { - [_parameters setObject: theCharset forKey: @"charset"]; + [_parameters setObject: theCharset forKey: @"charset"]; } } @@ -624,7 +621,7 @@ static int currentPartVersion = 2; // - (NSString *) defaultCharset { - return _defaultCharset; + return _defaultCharset; } @@ -633,7 +630,7 @@ static int currentPartVersion = 2; // - (void) setDefaultCharset: (NSString *) theCharset { - ASSIGN(_defaultCharset, theCharset); + ASSIGN(_defaultCharset, theCharset); } @@ -642,61 +639,61 @@ static int currentPartVersion = 2; // - (void) setHeadersFromData: (NSData *) theHeaders { - //NSAutoreleasePool *pool; - NSArray *allLines; - NSUInteger i, count; - - if (!theHeaders || [theHeaders length] == 0) + //NSAutoreleasePool *pool; + NSArray *allLines; + NSUInteger i, count; + + if (!theHeaders || [theHeaders length] == 0) { - return; + return; } - // We initialize a local autorelease pool + // We initialize a local autorelease pool @autoreleasepool { - // We MUST be sure to unfold all headers properly before - // decoding the headers - theHeaders = [theHeaders unfoldLines]; + // We MUST be sure to unfold all headers properly before + // decoding the headers + theHeaders = [theHeaders unfoldLines]; - allLines = [theHeaders componentsSeparatedByCString: "\n"]; - count = [allLines count]; + allLines = [theHeaders componentsSeparatedByCString: "\n"]; + count = [allLines count]; - for (i = 0; i < count; i++) - { - NSData *aLine = [allLines objectAtIndex: i]; - - // We stop if we found the header separator. (\n\n) since someone could - // have called this method with the entire rawsource of a message. - if ([aLine length] == 0) - { - break; - } - - if ([aLine hasCaseInsensitiveCPrefix: "Content-Description"]) - { - [CWParser parseContentDescription: aLine inPart: self]; - } - else if ([aLine hasCaseInsensitiveCPrefix: "Content-Disposition"]) - { - [CWParser parseContentDisposition: aLine inPart: self]; - } - else if ([aLine hasCaseInsensitiveCPrefix: "Content-ID"]) - { - [CWParser parseContentID: aLine inPart: self]; - } - else if ([aLine hasCaseInsensitiveCPrefix: "Content-Length"]) - { - // We just ignore that for now. - } - else if ([aLine hasCaseInsensitiveCPrefix: "Content-Transfer-Encoding"]) - { - [CWParser parseContentTransferEncoding: aLine inPart: self]; - } - else if ([aLine hasCaseInsensitiveCPrefix: "Content-Type"]) - { - [CWParser parseContentType: aLine inPart: self]; - } - } + for (i = 0; i < count; i++) + { + NSData *aLine = [allLines objectAtIndex: i]; + + // We stop if we found the header separator. (\n\n) since someone could + // have called this method with the entire rawsource of a message. + if ([aLine length] == 0) + { + break; + } + + if ([aLine hasCaseInsensitiveCPrefix: "Content-Description"]) + { + [CWParser parseContentDescription: aLine inPart: self]; + } + else if ([aLine hasCaseInsensitiveCPrefix: "Content-Disposition"]) + { + [CWParser parseContentDisposition: aLine inPart: self]; + } + else if ([aLine hasCaseInsensitiveCPrefix: "Content-ID"]) + { + [CWParser parseContentID: aLine inPart: self]; + } + else if ([aLine hasCaseInsensitiveCPrefix: "Content-Length"]) + { + // We just ignore that for now. + } + else if ([aLine hasCaseInsensitiveCPrefix: "Content-Transfer-Encoding"]) + { + [CWParser parseContentTransferEncoding: aLine inPart: self]; + } + else if ([aLine hasCaseInsensitiveCPrefix: "Content-Type"]) + { + [CWParser parseContentType: aLine inPart: self]; + } + } } //RELEASE(pool); } @@ -707,18 +704,18 @@ static int currentPartVersion = 2; // - (id) parameterForKey: (NSString *) theKey { - return [_parameters objectForKey: theKey]; + return [_parameters objectForKey: theKey]; } - (void) setParameter: (NSString *) theParameter forKey: (NSString *) theKey { - if (theParameter) + if (theParameter) { - [_parameters setObject: theParameter forKey: theKey]; + [_parameters setObject: theParameter forKey: theKey]; } - else + else { - [_parameters removeObjectForKey: theKey]; + [_parameters removeObjectForKey: theKey]; } } @@ -727,7 +724,7 @@ static int currentPartVersion = 2; // - (NSDictionary *) allHeaders { - return _headers; + return _headers; } // @@ -735,21 +732,21 @@ static int currentPartVersion = 2; // - (id) headerValueForName: (NSString *) theName { - NSArray *allKeys; - NSUInteger count; + NSArray *allKeys; + NSUInteger count; - allKeys = [_headers allKeys]; - count = [allKeys count]; + allKeys = [_headers allKeys]; + count = [allKeys count]; - while (count--) + while (count--) { - if ([[allKeys objectAtIndex: count] caseInsensitiveCompare: theName] == NSOrderedSame) - { - return [_headers objectForKey: [allKeys objectAtIndex: count]]; - } + if ([[allKeys objectAtIndex: count] caseInsensitiveCompare: theName] == NSOrderedSame) + { + return [_headers objectForKey: [allKeys objectAtIndex: count]]; + } } - - return nil; + + return nil; } // @@ -757,13 +754,13 @@ static int currentPartVersion = 2; // - (void) setHeaders: (NSDictionary *) theHeaders { - if (theHeaders) + if (theHeaders) { - [_headers addEntriesFromDictionary: theHeaders]; + [_headers addEntriesFromDictionary: theHeaders]; } - else + else { - [_headers removeAllObjects]; + [_headers removeAllObjects]; } } diff --git a/pantomime-lib/Framework/Pantomime/CWSMTP+Protected.m b/pantomime-lib/Framework/Pantomime/CWSMTP+Protected.m index d9fb8fe..b32fd0a 100644 --- a/pantomime-lib/Framework/Pantomime/CWSMTP+Protected.m +++ b/pantomime-lib/Framework/Pantomime/CWSMTP+Protected.m @@ -130,7 +130,7 @@ } _lastCommand = aQueueObject->command; [self bulkWriteData:@[[aQueueObject->arguments - dataUsingEncoding: _defaultCStringEncoding], + dataUsingEncoding: _defaultStringEncoding], _crlf]]; } else { LogInfo(@"Sending with nil queue object"); diff --git a/pantomime-lib/Framework/Pantomime/CWSMTP.m b/pantomime-lib/Framework/Pantomime/CWSMTP.m index c2129e7..f5178da 100644 --- a/pantomime-lib/Framework/Pantomime/CWSMTP.m +++ b/pantomime-lib/Framework/Pantomime/CWSMTP.m @@ -1,24 +1,24 @@ /* -** CWSMTP.m -** -** Copyright (c) 2001-2007 -** -** Author: Ludovic Marcotte -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ + ** CWSMTP.m + ** + ** Copyright (c) 2001-2007 + ** + ** Author: Ludovic Marcotte + ** + ** This library is free software; you can redistribute it and/or + ** modify it under the terms of the GNU Lesser General Public + ** License as published by the Free Software Foundation; either + ** version 2.1 of the License, or (at your option) any later version. + ** + ** This library is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + ** Lesser General Public License for more details. + ** + ** You should have received a copy of the GNU Lesser General Public + ** License along with this library; if not, write to the Free Software + ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ #import "CWSMTP.h" #import "CWSMTP+Protected.h" @@ -51,32 +51,32 @@ static NSString *pEpEHLOBase = @"pretty.Easy.privacy"; // static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, BOOL aBOOL) { - CWInternetAddress *theAddress; - NSUInteger i, count; + CWInternetAddress *theAddress; + NSUInteger i, count; - count = [theRecipients count]; + count = [theRecipients count]; - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { - theAddress = [theRecipients objectAtIndex: i]; - - if (aBOOL) - { - if ([theAddress type] > 3) - { - return theAddress; - } - } - else - { - if ([theAddress type] < 4) - { - return theAddress; - } - } + theAddress = [theRecipients objectAtIndex: i]; + + if (aBOOL) + { + if ([theAddress type] > 3) + { + return theAddress; + } + } + else + { + if ([theAddress type] < 4) + { + return theAddress; + } + } } - return nil; + return nil; } @@ -129,7 +129,7 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B _max_size = 0; _lastCommand = SMTP_AUTHORIZATION; - + // We queue our first "command". [_queue addObject: AUTORELEASE([[CWSMTPQueueObject alloc] initWithCommand: _lastCommand arguments: @""])]; @@ -142,13 +142,13 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B // - (void) dealloc { - //LogInfo(@"SMTP: -dealloc"); - RELEASE(_message); - RELEASE(_data); - RELEASE(_recipients); - RELEASE(_sent_recipients); + //LogInfo(@"SMTP: -dealloc"); + RELEASE(_message); + RELEASE(_data); + RELEASE(_recipients); + RELEASE(_sent_recipients); - //[super dealloc]; + //[super dealloc]; } #pragma mark - Overriden @@ -478,32 +478,32 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B - (void) _parseAUTH_CRAM_MD5 { - NSData *aData; - - aData = [_responsesFromServer lastObject]; - - if ([aData hasCPrefix: "334"]) + NSData *aData; + + aData = [_responsesFromServer lastObject]; + + if ([aData hasCPrefix: "334"]) { - NSString *aString; - CWMD5 *aMD5; - - // We trim the "334 ", decode the data using base64 and we keep the challenge phrase - aData = [[aData subdataFromIndex: 4] decodeBase64]; - aMD5 = [[CWMD5 alloc] initWithData: aData]; - [aMD5 computeDigest]; - - aString = [NSString stringWithFormat: @"%@ %@", _username, [aMD5 hmacAsStringUsingPassword: _password]]; - [self bulkWriteData:@[[[aString dataUsingEncoding: _defaultCStringEncoding] encodeBase64WithLineLength: 0], - _crlf]]; - RELEASE(aMD5); + NSString *aString; + CWMD5 *aMD5; + + // We trim the "334 ", decode the data using base64 and we keep the challenge phrase + aData = [[aData subdataFromIndex: 4] decodeBase64]; + aMD5 = [[CWMD5 alloc] initWithData: aData]; + [aMD5 computeDigest]; + + aString = [NSString stringWithFormat: @"%@ %@", _username, [aMD5 hmacAsStringUsingPassword: _password]]; + [self bulkWriteData:@[[[aString dataUsingEncoding: _defaultStringEncoding] encodeBase64WithLineLength: 0], + _crlf]]; + RELEASE(aMD5); } - else if ([aData hasCPrefix: "235"]) + else if ([aData hasCPrefix: "235"]) { - AUTHENTICATION_COMPLETED(_delegate, @"CRAM-MD5"); + AUTHENTICATION_COMPLETED(_delegate, @"CRAM-MD5"); } - else + else { - AUTHENTICATION_FAILED(_delegate, @"CRAM-MD5"); + AUTHENTICATION_FAILED(_delegate, @"CRAM-MD5"); } } @@ -513,22 +513,22 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B // - (void) _parseAUTH_LOGIN { - NSData *aData; - - aData = [_responsesFromServer lastObject]; - - if ([aData hasCPrefix: "334"]) + NSData *aData; + + aData = [_responsesFromServer lastObject]; + + if ([aData hasCPrefix: "334"]) { - NSString *aString; - - aString = [[NSString alloc] initWithData: [[_username dataUsingEncoding: _defaultCStringEncoding] encodeBase64WithLineLength: 0] - encoding: _defaultCStringEncoding]; - [self sendCommand: SMTP_AUTH_LOGIN_CHALLENGE arguments: aString]; - RELEASE(aString); + NSString *aString; + + aString = [[NSString alloc] initWithData: [[_username dataUsingEncoding: _defaultStringEncoding] encodeBase64WithLineLength: 0] + encoding: _defaultStringEncoding]; + [self sendCommand: SMTP_AUTH_LOGIN_CHALLENGE arguments: aString]; + RELEASE(aString); } - else + else { - AUTHENTICATION_FAILED(_delegate, @"LOGIN"); + AUTHENTICATION_FAILED(_delegate, @"LOGIN"); } } @@ -538,28 +538,28 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B // - (void) _parseAUTH_LOGIN_CHALLENGE { - NSData *aData; - - aData = [_responsesFromServer lastObject]; - - if ([aData hasCPrefix: "334"]) + NSData *aData; + + aData = [_responsesFromServer lastObject]; + + if ([aData hasCPrefix: "334"]) { - NSString *aString; - - aString = [[NSString alloc] initWithData: [[_password dataUsingEncoding: _defaultCStringEncoding] encodeBase64WithLineLength: 0] - encoding: _defaultCStringEncoding]; - - [self sendCommand: SMTP_AUTH_LOGIN_CHALLENGE arguments: aString]; - RELEASE(aString); + NSString *aString; + + aString = [[NSString alloc] initWithData: [[_password dataUsingEncoding: _defaultStringEncoding] encodeBase64WithLineLength: 0] + encoding: _defaultStringEncoding]; + + [self sendCommand: SMTP_AUTH_LOGIN_CHALLENGE arguments: aString]; + RELEASE(aString); } - else if ([aData hasCPrefix: "235"]) + else if ([aData hasCPrefix: "235"]) { - AUTHENTICATION_COMPLETED(_delegate, @"LOGIN"); + AUTHENTICATION_COMPLETED(_delegate, @"LOGIN"); } - else + else { LogInfo(@"Authentification response: |%@|", - [aData asciiString]); + [aData asciiString]); AUTHENTICATION_FAILED(_delegate, @"LOGIN"); } } @@ -570,46 +570,18 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B // - (void) _parseAUTH_PLAIN { - NSData *aData; - - aData = [_responsesFromServer lastObject]; + NSData *aData = [_responsesFromServer lastObject]; - if ([aData hasCPrefix: "334"]) - { - NSMutableData *aMutableData; - NSUInteger len_username, len_password; - - len_username = [_username length]; - - if (!_password) - { - len_password = 0; - } - else - { - len_password = [_password length]; - } - - // We create our phrase - aMutableData = [NSMutableData dataWithLength: (len_username + len_password + 2)]; - - [aMutableData replaceBytesInRange: NSMakeRange(1,len_username) - withBytes: [[_username dataUsingEncoding: _defaultCStringEncoding] bytes]]; - - - [aMutableData replaceBytesInRange: NSMakeRange(2 + len_username, len_password) - withBytes: [[_password dataUsingEncoding: [NSString defaultCStringEncoding]] bytes]]; - - [self bulkWriteData:@[[aMutableData encodeBase64WithLineLength: 0], - _crlf]]; + if ([aData hasCPrefix: "334"]) { + NSString *stringToSend = [NSString stringWithFormat:@"\0%@\0%@", _username, _password]; + NSData *dataToSend = [stringToSend dataUsingEncoding:_defaultStringEncoding]; + [self bulkWriteData:@[[dataToSend encodeBase64WithLineLength: 0], + _crlf]]; + } else if ([aData hasCPrefix: "235"]) { + AUTHENTICATION_COMPLETED(_delegate, @"PLAIN"); } - else if ([aData hasCPrefix: "235"]) - { - AUTHENTICATION_COMPLETED(_delegate, @"PLAIN"); - } - else - { - AUTHENTICATION_FAILED(_delegate, @"PLAIN"); + else { + AUTHENTICATION_FAILED(_delegate, @"PLAIN"); } } @@ -643,20 +615,20 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B // - (void) _parseAUTHORIZATION { - NSData *aData; - - aData = [_responsesFromServer lastObject]; - - // 220 Service ready - if ([aData hasCPrefix: "220"]) + NSData *aData; + + aData = [_responsesFromServer lastObject]; + + // 220 Service ready + if ([aData hasCPrefix: "220"]) { - [self sendCommand: SMTP_EHLO arguments: [NSString stringWithFormat:@"EHLO %@", pEpEHLOBase]]; + [self sendCommand: SMTP_EHLO arguments: [NSString stringWithFormat:@"EHLO %@", pEpEHLOBase]]; } - else + else { - // Handle the fact when a server is loaded and can't handle our requests - // right away. -//! unhandled + // Handle the fact when a server is loaded and can't handle our requests + // right away. + //! unhandled } } @@ -666,73 +638,73 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B // - (void) _parseDATA { - NSData *aData; - - aData = [_responsesFromServer lastObject]; + NSData *aData; + + aData = [_responsesFromServer lastObject]; - // If we can proceed to write the message's data, let's do so. - if ([aData hasCPrefix: "354"]) + // If we can proceed to write the message's data, let's do so. + if ([aData hasCPrefix: "354"]) { - NSMutableData *aMutableData; - NSRange r1, r2; - - // We first replace all occurences of LF by CRLF in the Message's data. - // - aMutableData = [[NSMutableData dataWithData: _data] replaceLFWithCRLF]; - _data = nil; // save memory by deleting as soon as possible - - // - // According to RFC 2821 section 4.5.2, we must check for the character - // sequence "."; any occurrence have its period duplicated - // to avoid data transparency. - // - r1 = [aMutableData rangeOfCString: "\r\n."]; - - while (r1.location != NSNotFound) - { - [aMutableData replaceBytesInRange: r1 withBytes: "\r\n.." length: 4]; - - r1 = [aMutableData rangeOfCString: "\r\n." - options: 0 - range: NSMakeRange(NSMaxRange(r1)+1, [aMutableData length]-NSMaxRange(r1)-1)]; - } - - // - // We now look for the Bcc: header. If it is present, we remove it. - // Some servers, like qmail, do not remove it automatically. - // - r1 = [aMutableData rangeOfCString: "\r\n\r\n"]; - r1 = [aMutableData rangeOfCString: "\r\nBcc: " - options: 0 - range: NSMakeRange(0,r1.location-1)]; - - if (r1.location != NSNotFound) - { - // We search for the first \r\n AFTER the Bcc: header and - // replace the whole thing with \r\n. - r2 = [aMutableData rangeOfCString: "\r\n" - options: 0 - range: NSMakeRange(NSMaxRange(r1)+1,[aMutableData length]-NSMaxRange(r1)-1)]; - [aMutableData replaceBytesInRange: NSMakeRange(r1.location, NSMaxRange(r2)-r1.location) - withBytes: "\r\n" - length: 2]; - } + NSMutableData *aMutableData; + NSRange r1, r2; + + // We first replace all occurences of LF by CRLF in the Message's data. + // + aMutableData = [[NSMutableData dataWithData: _data] replaceLFWithCRLF]; + _data = nil; // save memory by deleting as soon as possible + + // + // According to RFC 2821 section 4.5.2, we must check for the character + // sequence "."; any occurrence have its period duplicated + // to avoid data transparency. + // + r1 = [aMutableData rangeOfCString: "\r\n."]; + + while (r1.location != NSNotFound) + { + [aMutableData replaceBytesInRange: r1 withBytes: "\r\n.." length: 4]; + + r1 = [aMutableData rangeOfCString: "\r\n." + options: 0 + range: NSMakeRange(NSMaxRange(r1)+1, [aMutableData length]-NSMaxRange(r1)-1)]; + } + + // + // We now look for the Bcc: header. If it is present, we remove it. + // Some servers, like qmail, do not remove it automatically. + // + r1 = [aMutableData rangeOfCString: "\r\n\r\n"]; + r1 = [aMutableData rangeOfCString: "\r\nBcc: " + options: 0 + range: NSMakeRange(0,r1.location-1)]; + + if (r1.location != NSNotFound) + { + // We search for the first \r\n AFTER the Bcc: header and + // replace the whole thing with \r\n. + r2 = [aMutableData rangeOfCString: "\r\n" + options: 0 + range: NSMakeRange(NSMaxRange(r1)+1,[aMutableData length]-NSMaxRange(r1)-1)]; + [aMutableData replaceBytesInRange: NSMakeRange(r1.location, NSMaxRange(r2)-r1.location) + withBytes: "\r\n" + length: 2]; + } [self bulkWriteData:@[aMutableData, - [NSData dataWithBytes: "\r\n.\r\n" length: 5]]]; + [NSData dataWithBytes: "\r\n.\r\n" length: 5]]]; } - else if ([aData hasCPrefix: "250"]) + else if ([aData hasCPrefix: "250"]) { - // The data we wrote in the previous call was sucessfully written. - // We inform the delegate that the mail was sucessfully sent. - PERFORM_SELECTOR_2(_delegate, @selector(messageSent:), PantomimeMessageSent, _message, @"Message"); + // The data we wrote in the previous call was sucessfully written. + // We inform the delegate that the mail was sucessfully sent. + PERFORM_SELECTOR_2(_delegate, @selector(messageSent:), PantomimeMessageSent, _message, @"Message"); // Delete memory consuming objects as soon as possible _data = nil; _message = nil; } - else + else { - [self fail]; + [self fail]; } } @@ -742,81 +714,81 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B // - (void) _parseEHLO { - NSData *aData; - NSUInteger i, count; + NSData *aData; + NSUInteger i, count; - count = [_responsesFromServer count]; - - for (i = 0; i < count; i++) + count = [_responsesFromServer count]; + + for (i = 0; i < count; i++) { - aData = [_responsesFromServer objectAtIndex: i]; - - if ([aData hasCPrefix: "250"]) - { - // We parse the SMTP service extensions. For now, we support the SIZE - // and the AUTH extensions. We ignore the rest. - aData = [aData subdataFromIndex: 4]; - - // We add it to our capabilities - [_capabilities addObject: AUTORELEASE([[NSString alloc] initWithData: aData encoding: _defaultCStringEncoding])]; - - // Example of responses: - // - // AUTH LOGIN - // AUTH=PLAIN CRAM-MD5 DIGEST-MD5 - // - if ([aData hasCPrefix: "AUTH"]) - { - NSEnumerator *theEnumerator; - id aString; - - // We chomp the "AUTH " or "AUTH=" part and we decode our - // supported mechanisms. - theEnumerator = [[[aData subdataFromIndex: 5] componentsSeparatedByCString: " "] objectEnumerator]; - - while ((aString = [theEnumerator nextObject])) - { - aString = [aString asciiString]; - - if (![_supportedMechanisms containsObject: aString]) - { - [_supportedMechanisms addObject: aString]; - } - } - } - // - // SIZE size-param - // size-param ::= [1*DIGIT] - // - // See RFC1870 for detailed information. - // - else if ([aData hasCPrefix: "SIZE"]) - { - NSRange aRange; - - // We must be careful here. Some broken servers will send only - // 250-SIZE - // and we don't want to parse an inexistant value. - aRange = [aData rangeOfCString: " "]; - - if (aRange.length) - { - _max_size = atoi([[aData subdataFromIndex: aRange.location+1] cString]); - } - } - } - else - { - // The server doesn't handle EHLO. We send it - // a HELO greeting instead. - [self sendCommand: SMTP_HELO arguments: [NSString stringWithFormat:@"HELO %@", pEpEHLOBase]]; - break; - } + aData = [_responsesFromServer objectAtIndex: i]; + + if ([aData hasCPrefix: "250"]) + { + // We parse the SMTP service extensions. For now, we support the SIZE + // and the AUTH extensions. We ignore the rest. + aData = [aData subdataFromIndex: 4]; + + // We add it to our capabilities + [_capabilities addObject: AUTORELEASE([[NSString alloc] initWithData: aData encoding: _defaultStringEncoding])]; + + // Example of responses: + // + // AUTH LOGIN + // AUTH=PLAIN CRAM-MD5 DIGEST-MD5 + // + if ([aData hasCPrefix: "AUTH"]) + { + NSEnumerator *theEnumerator; + id aString; + + // We chomp the "AUTH " or "AUTH=" part and we decode our + // supported mechanisms. + theEnumerator = [[[aData subdataFromIndex: 5] componentsSeparatedByCString: " "] objectEnumerator]; + + while ((aString = [theEnumerator nextObject])) + { + aString = [aString asciiString]; + + if (![_supportedMechanisms containsObject: aString]) + { + [_supportedMechanisms addObject: aString]; + } + } + } + // + // SIZE size-param + // size-param ::= [1*DIGIT] + // + // See RFC1870 for detailed information. + // + else if ([aData hasCPrefix: "SIZE"]) + { + NSRange aRange; + + // We must be careful here. Some broken servers will send only + // 250-SIZE + // and we don't want to parse an inexistant value. + aRange = [aData rangeOfCString: " "]; + + if (aRange.length) + { + _max_size = atoi([[aData subdataFromIndex: aRange.location+1] cString]); + } + } + } + else + { + // The server doesn't handle EHLO. We send it + // a HELO greeting instead. + [self sendCommand: SMTP_HELO arguments: [NSString stringWithFormat:@"HELO %@", pEpEHLOBase]]; + break; + } } -//! - Inform the delegate if it is ready or not, especially if EHLO failed - PERFORM_SELECTOR_1(_delegate, @selector(serviceInitialized:), PantomimeServiceInitialized); + //! - Inform the delegate if it is ready or not, especially if EHLO failed + PERFORM_SELECTOR_1(_delegate, @selector(serviceInitialized:), PantomimeServiceInitialized); } @@ -825,7 +797,7 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B // - (void) _parseHELO { - //! - Implement. + inform the delegate if it's ready or not. + //! - Implement. + inform the delegate if it's ready or not. } @@ -837,24 +809,24 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B // - (void) _parseMAIL { - NSData *aData; - - aData = [_responsesFromServer lastObject]; + NSData *aData; + + aData = [_responsesFromServer lastObject]; - if ([aData hasCPrefix: "250"]) + if ([aData hasCPrefix: "250"]) { - // We write the first recipient while respecting the fact - // that we are bouncing or not the message. - PERFORM_SELECTOR_1(_delegate, @selector(transactionInitiationCompleted:), PantomimeTransactionInitiationCompleted); + // We write the first recipient while respecting the fact + // that we are bouncing or not the message. + PERFORM_SELECTOR_1(_delegate, @selector(transactionInitiationCompleted:), PantomimeTransactionInitiationCompleted); - [self sendCommand: SMTP_RCPT arguments: @"RCPT TO:<%@>", [next_recipient(_sent_recipients, _redirected) address]]; + [self sendCommand: SMTP_RCPT arguments: @"RCPT TO:<%@>", [next_recipient(_sent_recipients, _redirected) address]]; } - else + else { - if (!PERFORM_SELECTOR_1(_delegate, @selector(transactionInitiationFailed:), PantomimeTransactionInitiationFailed)) - { - [self fail]; - } + if (!PERFORM_SELECTOR_1(_delegate, @selector(transactionInitiationFailed:), PantomimeTransactionInitiationFailed)) + { + [self fail]; + } } } @@ -864,7 +836,7 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B // - (void) _parseNOOP { - // Do what? + // Do what? } @@ -873,16 +845,16 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B // - (void) _parseQUIT { - NSData *aData; - - aData = [_responsesFromServer lastObject]; - - if ([aData hasCPrefix: "221"]) + NSData *aData; + + aData = [_responsesFromServer lastObject]; + + if ([aData hasCPrefix: "221"]) { - // Do anything special here? + // Do anything special here? } - [super close]; + [super close]; } @@ -895,40 +867,40 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B // - (void) _parseRCPT { - NSData *aData; - - aData = [_responsesFromServer lastObject]; + NSData *aData; + + aData = [_responsesFromServer lastObject]; - if ([aData hasCPrefix: "250"]) + if ([aData hasCPrefix: "250"]) { - CWInternetAddress *theAddress; - - theAddress = next_recipient(_sent_recipients, _redirected); - - if (theAddress) - { - [_sent_recipients removeObject: theAddress]; - - theAddress = next_recipient(_sent_recipients, _redirected); - - if (theAddress) - { - [self sendCommand: SMTP_RCPT arguments: @"RCPT TO:<%@>", [theAddress address]]; - return; - } - } - - // We are done writing the recipients, we now write the content - // of the message. - PERFORM_SELECTOR_2(_delegate, @selector(recipientIdentificationCompleted:), PantomimeRecipientIdentificationCompleted, _recipients, @"Recipients"); - [self sendCommand: SMTP_DATA arguments: @"DATA"]; + CWInternetAddress *theAddress; + + theAddress = next_recipient(_sent_recipients, _redirected); + + if (theAddress) + { + [_sent_recipients removeObject: theAddress]; + + theAddress = next_recipient(_sent_recipients, _redirected); + + if (theAddress) + { + [self sendCommand: SMTP_RCPT arguments: @"RCPT TO:<%@>", [theAddress address]]; + return; + } + } + + // We are done writing the recipients, we now write the content + // of the message. + PERFORM_SELECTOR_2(_delegate, @selector(recipientIdentificationCompleted:), PantomimeRecipientIdentificationCompleted, _recipients, @"Recipients"); + [self sendCommand: SMTP_DATA arguments: @"DATA"]; } - else + else { - if (!PERFORM_SELECTOR_1(_delegate, @selector(recipientIdentificationFailed:), PantomimeRecipientIdentificationFailed)) - { - [self fail]; - } + if (!PERFORM_SELECTOR_1(_delegate, @selector(recipientIdentificationFailed:), PantomimeRecipientIdentificationFailed)) + { + [self fail]; + } } } @@ -938,17 +910,17 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B // - (void) _parseRSET { - NSData *aData; - - aData = [_responsesFromServer lastObject]; - - if ([aData hasCPrefix: "250"]) + NSData *aData; + + aData = [_responsesFromServer lastObject]; + + if ([aData hasCPrefix: "250"]) { - PERFORM_SELECTOR_1(_delegate, @selector(transactionResetCompleted:), PantomimeTransactionResetCompleted); + PERFORM_SELECTOR_1(_delegate, @selector(transactionResetCompleted:), PantomimeTransactionResetCompleted); } - else + else { - PERFORM_SELECTOR_1(_delegate, @selector(transactionResetFailed:), PantomimeTransactionResetFailed); + PERFORM_SELECTOR_1(_delegate, @selector(transactionResetFailed:), PantomimeTransactionResetFailed); } } @@ -970,7 +942,7 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B // The server probably doesn't support TLS. We inform the delegate that the transaction // initiation failed or that the message wasn't sent. if (!PERFORM_SELECTOR_1(_delegate, @selector(transactionInitiationFailed:), - PantomimeTransactionInitiationFailed)) { + PantomimeTransactionInitiationFailed)) { [self fail]; } } @@ -982,103 +954,103 @@ static inline CWInternetAddress *next_recipient(NSMutableArray *theRecipients, B // - (void) _parseServerOutput { - NSData *aData; + NSData *aData; - if (![_responsesFromServer count]) + if (![_responsesFromServer count]) { - return; + return; } - // We read only the first response. The _parseXYZ methods - // will handle multiline responses. - aData = [_responsesFromServer objectAtIndex: 0]; + // We read only the first response. The _parseXYZ methods + // will handle multiline responses. + aData = [_responsesFromServer objectAtIndex: 0]; - if ([aData hasCPrefix: "421"]) + if ([aData hasCPrefix: "421"]) { - //! - lost connection - //LogInfo(@"LOST CONNECTION TO THE SERVER"); - [super close]; + //! - lost connection + //LogInfo(@"LOST CONNECTION TO THE SERVER"); + [super close]; } - else + else { - switch (_lastCommand) - { - case SMTP_AUTH_CRAM_MD5: - [self _parseAUTH_CRAM_MD5]; - break; - - case SMTP_AUTH_LOGIN: - [self _parseAUTH_LOGIN]; - break; - - case SMTP_AUTH_LOGIN_CHALLENGE: - [self _parseAUTH_LOGIN_CHALLENGE]; - break; - - case SMTP_AUTH_PLAIN: - [self _parseAUTH_PLAIN]; - break; - - case SMTP_AUTH_XOAUTH2: - [self _parseAUTH_OAUTH2]; - break; - - case SMTP_DATA: - [self _parseDATA]; - break; - - case SMTP_EHLO: - [self _parseEHLO]; - break; - - case SMTP_HELO: - [self _parseHELO]; - break; - - case SMTP_MAIL: - [self _parseMAIL]; - break; - - case SMTP_NOOP: - [self _parseNOOP]; - break; - - case SMTP_QUIT: - [self _parseQUIT]; - break; - - case SMTP_RCPT: - [self _parseRCPT]; - break; - - case SMTP_RSET: - [self _parseRSET]; - break; - - case SMTP_STARTTLS: - [self _parseSTARTTLS]; - break; - - case SMTP_AUTHORIZATION: - [self _parseAUTHORIZATION]; - break; - - default: - break; - //! - } + switch (_lastCommand) + { + case SMTP_AUTH_CRAM_MD5: + [self _parseAUTH_CRAM_MD5]; + break; + + case SMTP_AUTH_LOGIN: + [self _parseAUTH_LOGIN]; + break; + + case SMTP_AUTH_LOGIN_CHALLENGE: + [self _parseAUTH_LOGIN_CHALLENGE]; + break; + + case SMTP_AUTH_PLAIN: + [self _parseAUTH_PLAIN]; + break; + + case SMTP_AUTH_XOAUTH2: + [self _parseAUTH_OAUTH2]; + break; + + case SMTP_DATA: + [self _parseDATA]; + break; + + case SMTP_EHLO: + [self _parseEHLO]; + break; + + case SMTP_HELO: + [self _parseHELO]; + break; + + case SMTP_MAIL: + [self _parseMAIL]; + break; + + case SMTP_NOOP: + [self _parseNOOP]; + break; + + case SMTP_QUIT: + [self _parseQUIT]; + break; + + case SMTP_RCPT: + [self _parseRCPT]; + break; + + case SMTP_RSET: + [self _parseRSET]; + break; + + case SMTP_STARTTLS: + [self _parseSTARTTLS]; + break; + + case SMTP_AUTHORIZATION: + [self _parseAUTHORIZATION]; + break; + + default: + break; + //! + } } - - // We are done parsing this entry... - [_responsesFromServer removeAllObjects]; - // We remove the last object of the queue.... - if ([_queue lastObject]) + // We are done parsing this entry... + [_responsesFromServer removeAllObjects]; + + // We remove the last object of the queue.... + if ([_queue lastObject]) { - [_queue removeLastObject]; + [_queue removeLastObject]; } - [self sendCommand: SMTP_EMPTY_QUEUE arguments: @""]; + [self sendCommand: SMTP_EMPTY_QUEUE arguments: @""]; } @end diff --git a/pantomime-lib/Framework/Pantomime/CWService+Protected.h b/pantomime-lib/Framework/Pantomime/CWService+Protected.h index 7451c38..2961aee 100644 --- a/pantomime-lib/Framework/Pantomime/CWService+Protected.h +++ b/pantomime-lib/Framework/Pantomime/CWService+Protected.h @@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN __block NSString *_password; __block NSString *_name; NSData *_crlf; - NSStringEncoding _defaultCStringEncoding; + NSStringEncoding _defaultStringEncoding; #ifdef MACOSX CFRunLoopSourceRef _runLoopSource; diff --git a/pantomime-lib/Framework/Pantomime/CWService.m b/pantomime-lib/Framework/Pantomime/CWService.m index bcf172b..1feafac 100644 --- a/pantomime-lib/Framework/Pantomime/CWService.m +++ b/pantomime-lib/Framework/Pantomime/CWService.m @@ -67,7 +67,7 @@ self = [super init]; if (self) { _crlf = [[NSData alloc] initWithBytes: "\r\n" length: 2]; - _defaultCStringEncoding = [NSString defaultCStringEncoding]; + _defaultStringEncoding = NSUTF8StringEncoding; _supportedMechanisms = [[CWThreadSafeArray alloc] init]; _responsesFromServer = [[CWThreadSafeArray alloc] init]; diff --git a/pantomime-lib/Framework/Pantomime/NSString+Extensions.m b/pantomime-lib/Framework/Pantomime/NSString+Extensions.m index 18d44d6..e38d998 100644 --- a/pantomime-lib/Framework/Pantomime/NSString+Extensions.m +++ b/pantomime-lib/Framework/Pantomime/NSString+Extensions.m @@ -64,881 +64,873 @@ #ifdef MACOSX - (NSString *) stringByTrimmingWhiteSpaces - { - NSMutableString *aMutableString; +{ + NSMutableString *aMutableString; - aMutableString = [[NSMutableString alloc] initWithString: self]; - CFStringTrimWhitespace((CFMutableStringRef)aMutableString); + aMutableString = [[NSMutableString alloc] initWithString: self]; + CFStringTrimWhitespace((CFMutableStringRef)aMutableString); - return AUTORELEASE(aMutableString); - } + return AUTORELEASE(aMutableString); +} #endif - // - // - // +// +// +// - (NSInteger) indexOfCharacter: (unichar) theCharacter - { - return [self indexOfCharacter: theCharacter fromIndex: 0]; - } +{ + return [self indexOfCharacter: theCharacter fromIndex: 0]; +} - // - // - // +// +// +// - (NSInteger) indexOfCharacter: (unichar) theCharacter fromIndex: (NSUInteger) theIndex - { - NSUInteger i, len; +{ + NSUInteger i, len; - len = [self length]; + len = [self length]; - for (i = theIndex; i < len; i++) + for (i = theIndex; i < len; i++) + { + if ([self characterAtIndex: i] == theCharacter) { - if ([self characterAtIndex: i] == theCharacter) - { - return i; - } + return i; } - - return -1; } + return -1; +} - // - // - // + +// +// +// - (BOOL) hasCaseInsensitivePrefix: (NSString *) thePrefix +{ + if (thePrefix) { - if (thePrefix) - { - return [[self uppercaseString] hasPrefix: [thePrefix uppercaseString]]; - } - - return NO; + return [[self uppercaseString] hasPrefix: [thePrefix uppercaseString]]; } + return NO; +} - // - // - // + +// +// +// - (BOOL) hasCaseInsensitiveSuffix: (NSString *) theSuffix +{ + if (theSuffix) { - if (theSuffix) - { - return [[self uppercaseString] hasSuffix: [theSuffix uppercaseString]]; - } - - return NO; + return [[self uppercaseString] hasSuffix: [theSuffix uppercaseString]]; } + return NO; +} - // - // - // -- (NSString *) stringFromQuotedString - { - NSUInteger len; - len = [self length]; +// +// +// +- (NSString *) stringFromQuotedString +{ + NSUInteger len; - if (len > 1 && - [self characterAtIndex: 0] == '"' && - [self characterAtIndex: (len-1)] == '"') - { - return [self substringWithRange: NSMakeRange(1, len-2)]; - } + len = [self length]; - return self; + if (len > 1 && + [self characterAtIndex: 0] == '"' && + [self characterAtIndex: (len-1)] == '"') + { + return [self substringWithRange: NSMakeRange(1, len-2)]; } + return self; +} - // - // - // + +// +// +// + (NSString *) stringValueOfTransferEncoding: (int) theEncoding +{ + switch (theEncoding) { - switch (theEncoding) - { - case PantomimeEncodingNone: + case PantomimeEncodingNone: break; - case PantomimeEncodingQuotedPrintable: + case PantomimeEncodingQuotedPrintable: return @"quoted-printable"; - case PantomimeEncodingBase64: + case PantomimeEncodingBase64: return @"base64"; - case PantomimeEncoding8bit: + case PantomimeEncoding8bit: return @"8bit"; - case PantomimeEncodingBinary: + case PantomimeEncodingBinary: return @"binary"; - default: + default: break; - } - - // PantomimeEncoding7bit will also fall back here. - return @"7bit"; } - // - // - // + // PantomimeEncoding7bit will also fall back here. + return @"7bit"; +} + +// +// +// + (NSInteger) encodingForCharset: (NSData *) theCharset - { - return [self encodingForCharset: theCharset convertToNSStringEncoding: YES]; - } +{ + return [self encodingForCharset: theCharset convertToNSStringEncoding: YES]; +} - // - // Convenience to be able to use CoreFoundation conversion instead of NSString - // +// +// Convenience to be able to use CoreFoundation conversion instead of NSString +// + (NSInteger) encodingForCharset: (NSData *) theCharset convertToNSStringEncoding: (BOOL) shouldConvertToNSStringEncoding - { - // We define some aliases for the string encoding. - static struct { char *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}, +{ + // We define some aliases for the string encoding. + static struct { char *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 + {"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; - - name = [[[NSString alloc ] initWithBytes: [theCharset bytes] length: [theCharset length] - encoding: NSUTF8StringEncoding] lowercaseString]; - AUTORELEASE_VOID(name); - - NSMutableArray *encodingNames = [NSMutableArray array]; - for (i = 0; i < sizeof(encodings)/sizeof(encodings[0]); i++) { - NSString *string = [[NSString alloc] initWithCString:encodings[i].name - encoding:NSUTF8StringEncoding]; - [encodingNames addObject:string]; - } + {"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; + + name = [[[NSString alloc ] initWithBytes: [theCharset bytes] length: [theCharset length] + encoding: NSUTF8StringEncoding] lowercaseString]; + AUTORELEASE_VOID(name); + + NSMutableArray *encodingNames = [NSMutableArray array]; + for (i = 0; i < sizeof(encodings)/sizeof(encodings[0]); i++) { + NSString *string = [[NSString alloc] initWithCString:encodings[i].name + encoding:NSUTF8StringEncoding]; + [encodingNames addObject:string]; + } - for (i = 0; i < sizeof(encodings)/sizeof(encodings[0]); i++) + for (i = 0; i < sizeof(encodings)/sizeof(encodings[0]); i++) + { + if ([name isEqualToString: encodingNames[i]]) { - if ([name isEqualToString: encodingNames[i]]) - { - int enc = encodings[i].encoding; - // Under OS X, we use CoreFoundation if necessary to convert the encoding - // to a NSString encoding. + 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 (encodings[i].fromCoreFoundation) + { + if (shouldConvertToNSStringEncoding) { - if (shouldConvertToNSStringEncoding) - { - return CFStringConvertEncodingToNSStringEncoding(enc); - } - else - { - return enc; - } + return CFStringConvertEncodingToNSStringEncoding(enc); } else { - // enc is a NSStringEncoding - if (!shouldConvertToNSStringEncoding) - { - return CFStringConvertNSStringEncodingToEncoding(enc); - } return enc; } -#else - return enc; -#endif - } - } - -#ifdef MACOSX - // Last resort: try using CoreFoundation... - CFStringEncoding enc; - - enc = CFStringConvertIANACharSetNameToEncoding((CFStringRef)name); - if (kCFStringEncodingInvalidId != enc) - { - if (shouldConvertToNSStringEncoding) - { - return CFStringConvertEncodingToNSStringEncoding(enc); } else { + // enc is a NSStringEncoding + if (!shouldConvertToNSStringEncoding) + { + return CFStringConvertNSStringEncodingToEncoding(enc); + } return enc; } - } +#else + return enc; #endif - - return -1; + } } - // - // - // -+ (NSInteger) encodingForPart: (CWPart *) thePart - { - return [self encodingForPart: thePart convertToNSStringEncoding: YES]; - } +#ifdef MACOSX + // Last resort: try using CoreFoundation... + CFStringEncoding enc; - // - // Convenience to be able to use CoreFoundation conversion instead of NSString - // -+ (NSInteger) encodingForPart: (CWPart *) thePart - convertToNSStringEncoding: (BOOL) shouldConvert + enc = CFStringConvertIANACharSetNameToEncoding((CFStringRef)name); + if (kCFStringEncodingInvalidId != enc) { - NSInteger encoding; - - // We get the encoding we are gonna use. We always favor the default encoding. - if ([thePart defaultCharset]) + if (shouldConvertToNSStringEncoding) { - encoding = [self encodingForCharset: [[thePart defaultCharset] dataUsingEncoding: NSASCIIStringEncoding] - convertToNSStringEncoding: shouldConvert]; - } - else if ([thePart charset]) - { - encoding = [self encodingForCharset: [[thePart charset] dataUsingEncoding: NSASCIIStringEncoding] - convertToNSStringEncoding: shouldConvert]; + return CFStringConvertEncodingToNSStringEncoding(enc); } else { - encoding = [NSString defaultCStringEncoding]; + return enc; } + } +#endif - if (encoding == -1 || encoding == NSASCIIStringEncoding) - { - encoding = NSISOLatin1StringEncoding; - } + return -1; +} + +// +// +// ++ (NSInteger) encodingForPart: (CWPart *) thePart { + return [self encodingForPart: thePart convertToNSStringEncoding: YES]; +} - return encoding; +// +// Convenience to be able to use CoreFoundation conversion instead of NSString +// ++ (NSInteger) encodingForPart: (CWPart *) thePart + convertToNSStringEncoding: (BOOL) shouldConvert { + NSInteger encoding; + + // We get the encoding we are gonna use. We always favor the default encoding. + if ([thePart defaultCharset]) { + encoding = [self encodingForCharset: [[thePart defaultCharset] dataUsingEncoding: NSASCIIStringEncoding] + convertToNSStringEncoding: shouldConvert]; + } else if ([thePart charset]) { + encoding = [self encodingForCharset: [[thePart charset] dataUsingEncoding: NSASCIIStringEncoding] + convertToNSStringEncoding: shouldConvert]; + } else { + encoding = [NSString defaultCStringEncoding]; } + if (encoding == -1 || encoding == NSASCIIStringEncoding) { + encoding = NSISOLatin1StringEncoding; + } - // - // - // + return encoding; +} + + +// +// +// + (NSString *) stringWithData: (NSData *) theData charset: (NSData *) theCharset - { - NSInteger encoding; +{ + NSInteger encoding; - if (theData == nil) - { - return nil; - } + if (theData == nil) + { + return nil; + } #ifdef MACOSX - encoding = [NSString encodingForCharset: theCharset - convertToNSStringEncoding: YES]; + encoding = [NSString encodingForCharset: theCharset + convertToNSStringEncoding: YES]; #else - encoding = [NSString encodingForCharset: theCharset]; + encoding = [NSString encodingForCharset: theCharset]; #endif - if (encoding == -1) - { + if (encoding == -1) + { #ifdef HAVE_ICONV - NSString *aString; + NSString *aString; - const char *i_bytes, *from_code; - char *o_bytes; + const char *i_bytes, *from_code; + char *o_bytes; - size_t i_length, o_length, ret; - int total_length; - iconv_t conv; + size_t i_length, o_length, ret; + int total_length; + iconv_t conv; - // Instead of calling cString directly on theCharset, we first try - // to obtain the ASCII string of the data object. - from_code = [[theCharset asciiString] cString]; + // Instead of calling cString directly on theCharset, we first try + // to obtain the ASCII string of the data object. + from_code = [[theCharset asciiString] cString]; - if (!from_code) - { - return nil; - } + if (!from_code) + { + return nil; + } - conv = iconv_open("UTF-8", from_code); + conv = iconv_open("UTF-8", from_code); - if (conv == (iconv_t)-1) - { - // Let's assume we got US-ASCII here. - return AUTORELEASE([[NSString alloc] initWithData: theData encoding: NSASCIIStringEncoding]); - } + if (conv == (iconv_t)-1) + { + // Let's assume we got US-ASCII here. + return AUTORELEASE([[NSString alloc] initWithData: theData encoding: NSASCIIStringEncoding]); + } - i_bytes = [theData bytes]; - i_length = [theData length]; + i_bytes = [theData bytes]; + i_length = [theData length]; - total_length = o_length = sizeof(unichar)*i_length; - o_bytes = (char *)malloc(o_length); + total_length = o_length = sizeof(unichar)*i_length; + o_bytes = (char *)malloc(o_length); - if (o_bytes == NULL) return nil; + if (o_bytes == NULL) return nil; - while (i_length > 0) - { - ret = iconv(conv, (iconv_const_qualifier char **)&i_bytes, &i_length, &o_bytes, &o_length); + while (i_length > 0) + { + ret = iconv(conv, (iconv_const_qualifier char **)&i_bytes, &i_length, &o_bytes, &o_length); - if (ret == (size_t)-1) - { - iconv_close(conv); + 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; + free(o_bytes); + return nil; } + } - total_length = total_length - o_length; - o_bytes -= total_length; + 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 && total_length > 0) + // If we haven't used all our allocated buffer, we shrink it. + if (o_length > 0 && total_length > 0) + { + if (realloc(o_bytes, total_length) == NULL) { - if (realloc(o_bytes, total_length) == NULL) - { - LogInfo("stringWithData, realloc() failed, returning nil"); - iconv_close(conv); - return nil; - } + LogInfo("stringWithData, realloc() failed, returning nil"); + iconv_close(conv); + return nil; } + } - aString = [[NSString alloc] initWithData: [NSData dataWithBytesNoCopy: o_bytes - length: total_length] - encoding: NSUTF8StringEncoding]; - iconv_close(conv); + aString = [[NSString alloc] initWithData: [NSData dataWithBytesNoCopy: o_bytes + length: total_length] + encoding: NSUTF8StringEncoding]; + iconv_close(conv); - return AUTORELEASE(aString); + return AUTORELEASE(aString); #else - return nil; + return nil; #endif - } - - //#ifdef MACOSX - //return AUTORELEASE((NSString *)CFStringCreateFromExternalRepresentation(NULL, (CFDataRef)theData, encoding)); - //#else - return AUTORELEASE([[NSString alloc] initWithData: theData encoding: encoding]); - //#endif } + //#ifdef MACOSX + //return AUTORELEASE((NSString *)CFStringCreateFromExternalRepresentation(NULL, (CFDataRef)theData, encoding)); + //#else + return AUTORELEASE([[NSString alloc] initWithData: theData encoding: encoding]); + //#endif +} - // - // - // + +// +// +// - (NSString *) charset +{ + NSMutableArray *aMutableArray; + NSString *aString; + CWCharset *aCharset; + + unsigned int i, j; + + aMutableArray = [[NSMutableArray alloc] initWithCapacity: 21]; + + [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-1"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-2"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-3"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-4"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-5"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-6"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-7"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-8"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-9"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-10"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-11"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-13"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-14"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-15"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"koi8-r"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"koi8-u"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"windows-1250"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"windows-1251"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"windows-1252"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"windows-1253"]]; + [aMutableArray addObject: [CWCharset charsetForName: @"windows-1254"]]; + + + for (i = 0; i < [self length]; i++) { - NSMutableArray *aMutableArray; - NSString *aString; - CWCharset *aCharset; - - unsigned int i, j; - - aMutableArray = [[NSMutableArray alloc] initWithCapacity: 21]; - - [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-1"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-2"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-3"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-4"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-5"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-6"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-7"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-8"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-9"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-10"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-11"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-13"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-14"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"iso-8859-15"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"koi8-r"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"koi8-u"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"windows-1250"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"windows-1251"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"windows-1252"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"windows-1253"]]; - [aMutableArray addObject: [CWCharset charsetForName: @"windows-1254"]]; - - - for (i = 0; i < [self length]; i++) + for (j = 0; j < [aMutableArray count]; j++) { - for (j = 0; j < [aMutableArray count]; j++) + if (![[aMutableArray objectAtIndex: j] characterIsInCharset: [self characterAtIndex: i]]) { - if (![[aMutableArray objectAtIndex: j] characterIsInCharset: [self characterAtIndex: i]]) - { - // Character is not in the charset - [aMutableArray removeObjectAtIndex: j]; - j--; - } + // Character is not in the charset + [aMutableArray removeObjectAtIndex: j]; + j--; } + } - //! can't break even if there is only one left. First we have to check - // whether that encoding will actually work for the entire string. If it - // doesn't we'll need to fall back to utf-8 (or something else that can encode - // _everything_). - // - // Intelligent string splitting would help, of course - // - if ([aMutableArray count] < 1) - { - // We have zero or one charset - break; - } + //! can't break even if there is only one left. First we have to check + // whether that encoding will actually work for the entire string. If it + // doesn't we'll need to fall back to utf-8 (or something else that can encode + // _everything_). + // + // Intelligent string splitting would help, of course + // + if ([aMutableArray count] < 1) + { + // We have zero or one charset + break; } + } - if ([aMutableArray count]) + if ([aMutableArray count]) + { + aCharset = [aMutableArray objectAtIndex: 0]; + [aMutableArray removeAllObjects]; + aString = [aCharset name]; + } + else + { + // We have no charset, we try to "guess" a default charset + if ([self canBeConvertedToEncoding: NSISO2022JPStringEncoding]) { - aCharset = [aMutableArray objectAtIndex: 0]; - [aMutableArray removeAllObjects]; - aString = [aCharset name]; + // ISO-2022-JP is the standard of Japanese character encoding + aString = @"iso-2022-jp"; } else { - // We have no charset, we try to "guess" a default charset - if ([self canBeConvertedToEncoding: NSISO2022JPStringEncoding]) - { - // ISO-2022-JP is the standard of Japanese character encoding - aString = @"iso-2022-jp"; - } - else - { - // We have no charset, we return a default charset - aString = @"utf-8"; - } + // We have no charset, we return a default charset + aString = @"utf-8"; } + } - RELEASE(aMutableArray); + RELEASE(aMutableArray); - return aString; - } + return aString; +} - // - // - // +// +// +// - (NSString *) modifiedUTF7String - { +{ #ifndef MACOSX - NSMutableData *aMutableData, *modifiedData; - NSString *aString; + NSMutableData *aMutableData, *modifiedData; + NSString *aString; - const char *b; - BOOL escaped; - unichar ch; - int i, len; + 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]; + // + // 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]; - for (i = 0; i < len; i++) + if (IS_PRINTABLE(ch)) { - ch = [self characterAtIndex: i]; + [aMutableData appendCFormat: @"%c", ch]; + } + else + { + int j; - if (IS_PRINTABLE(ch)) + 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])) { - [aMutableData appendCFormat: @"%c", ch]; + j++; } - 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; - } + // Get the substring. + [aMutableData appendData: [[self substringWithRange: NSMakeRange(i,j-i)] dataUsingEncoding: NSUTF7StringEncoding]]; + i = j-1; } + } - b = [aMutableData bytes]; - len = [aMutableData length]; - escaped = NO; + 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); + // + // We replace: + // + // & -> &- + // + -> & + // +- -> + + // / -> , + // + // in order to produce our modified UTF-7 string. + // + modifiedData = [[NSMutableData alloc] init]; + AUTORELEASE(modifiedData); - for (i = 0; i < len; i++, b++) + for (i = 0; i < len; i++, b++) + { + if (!escaped && *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: "&-"]; + } + else if (!escaped && *b == '+') + { + if (*(b+1) == '-') { - [modifiedData appendCString: "-"]; - - // We leave the escaped mode. - escaped = NO; + [modifiedData appendCString: "+"]; } else { - [modifiedData appendCFormat: @"%c", *b]; + [modifiedData appendCString: "&"]; + + // We enter the escaped mode. + escaped = YES; } } - - // If we're still in the escaped mode we haven't added our trailing -, - // let's add it right now. - if (escaped) + 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]); + aString = AUTORELEASE([[NSString alloc] initWithData: modifiedData encoding: NSASCIIStringEncoding]); - return (aString != nil ? aString : self); + return (aString != nil ? aString : self); #else - NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF7_IMAP); - NSData *data = [self dataUsingEncoding: encoding]; - return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; + NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF7_IMAP); + NSData *data = [self dataUsingEncoding: encoding]; + return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; #endif - } +} - // - // - // +// +// +// - (NSString *) stringFromModifiedUTF7 - { +{ #ifdef MACOSX - // This implementation is clearly wrong. - // Fixing it causes all kinds of wrong foldername issue thought. - return self; + // This implementation is clearly wrong. + // Fixing it causes all kinds of wrong foldername issue thought. + return self; #else - - NSMutableData *aMutableData; - BOOL escaped; - unichar ch; - unsigned long i, len; + NSMutableData *aMutableData; - aMutableData = [[NSMutableData alloc] init]; - AUTORELEASE(aMutableData); + BOOL escaped; + unichar ch; + unsigned long i, len; - len = [self length]; - escaped = NO; + aMutableData = [[NSMutableData alloc] init]; + AUTORELEASE(aMutableData); - // - // We replace: - // - // & -> + - // &- -> & - // , -> / - // - // If we are in escaped mode. That is, between a &....- - // - for (i = 0; i < len; i++) - { - ch = [self characterAtIndex: i]; + len = [self length]; + escaped = NO; - if (!escaped && ch == '&') - { - if ( (i+1) < len && [self characterAtIndex: (i+1)] != '-' ) - { - [aMutableData appendCString: "+"]; + // + // We replace: + // + // & -> + + // &- -> & + // , -> / + // + // If we are in escaped mode. That is, between a &....- + // + for (i = 0; i < len; i++) + { + ch = [self characterAtIndex: i]; - // We enter the escaped mode. - escaped = YES; - } - else - { - // We replace &- by & - [aMutableData appendCString: "&"]; - i++; - } - } - else if (escaped && ch == ',') - { - [aMutableData appendCString: "/"]; - } - else if (escaped && ch == '-') + if (!escaped && ch == '&') + { + if ( (i+1) < len && [self characterAtIndex: (i+1)] != '-' ) { - [aMutableData appendCString: "-"]; + [aMutableData appendCString: "+"]; - // We leave the escaped mode. - escaped = NO; + // We enter the escaped mode. + escaped = YES; } else { - [aMutableData appendCFormat: @"%c", ch]; + // We replace &- by & + [aMutableData appendCString: "&"]; + i++; } } + else if (escaped && ch == ',') + { + [aMutableData appendCString: "/"]; + } + else if (escaped && ch == '-') + { + [aMutableData appendCString: "-"]; - NSStringEncoding encoding = NSUTF7StringEncoding; + // We leave the escaped mode. + escaped = NO; + } + else + { + [aMutableData appendCFormat: @"%c", ch]; + } + } + + NSStringEncoding encoding = NSUTF7StringEncoding; - return AUTORELEASE([[NSString alloc] initWithData: aMutableData encoding: encoding]); + return AUTORELEASE([[NSString alloc] initWithData: aMutableData encoding: encoding]); #endif - } +} - // - // - // +// +// +// - (BOOL) hasREPrefix +{ + if ([self hasCaseInsensitivePrefix: @"re:"] || + [self hasCaseInsensitivePrefix: @"re :"] || + [self hasCaseInsensitivePrefix: _(@"PantomimeReferencePrefix")] || + [self hasCaseInsensitivePrefix: _(@"PantomimeResponsePrefix")]) { - if ([self hasCaseInsensitivePrefix: @"re:"] || - [self hasCaseInsensitivePrefix: @"re :"] || - [self hasCaseInsensitivePrefix: _(@"PantomimeReferencePrefix")] || - [self hasCaseInsensitivePrefix: _(@"PantomimeResponsePrefix")]) - { - return YES; - } - - return NO; + return YES; } + return NO; +} - // - // - // + +// +// +// - (NSString *) stringByReplacingOccurrencesOfCharacter: (unichar) theTarget withCharacter: (unichar) theReplacement +{ + NSMutableString *aMutableString; + NSUInteger len, i; + unichar c; + + if (!theTarget || !theReplacement || theTarget == theReplacement) { - NSMutableString *aMutableString; - NSUInteger len, i; - unichar c; + return self; + } - if (!theTarget || !theReplacement || theTarget == theReplacement) - { - return self; - } + len = [self length]; - len = [self length]; + aMutableString = [NSMutableString stringWithCapacity: len]; - aMutableString = [NSMutableString stringWithCapacity: len]; + for (i = 0; i < len; i++) + { + c = [self characterAtIndex: i]; - for (i = 0; i < len; i++) + if (c == theTarget) { - c = [self characterAtIndex: i]; - - if (c == theTarget) - { - [aMutableString appendFormat: @"%c", theReplacement]; - } - else - { - [aMutableString appendFormat: @"%c", c]; - } + [aMutableString appendFormat: @"%c", theReplacement]; + } + else + { + [aMutableString appendFormat: @"%c", c]; } - - return aMutableString; } - // - // - // + return aMutableString; +} + +// +// +// - (NSString *) stringByDeletingLastPathComponentWithSeparator: (unsigned char) theSeparator - { - NSUInteger c; - NSInteger i; +{ + NSUInteger c; + NSInteger i; - c = [self length]; + c = [self length]; - for (i = c-1; i >= 0; i--) + for (i = c-1; i >= 0; i--) + { + if ([self characterAtIndex: i] == theSeparator) { - if ([self characterAtIndex: i] == theSeparator) - { - return [self substringToIndex: i]; - } + return [self substringToIndex: i]; } - - return @""; } - // - // - // + return @""; +} + +// +// +// - (NSString *) stringByDeletingFirstPathSeparator: (unsigned char) theSeparator +{ + if ([self length] && [self characterAtIndex: 0] == theSeparator) { - if ([self length] && [self characterAtIndex: 0] == theSeparator) - { - return [self substringFromIndex: 1]; - } - - return self; + return [self substringFromIndex: 1]; } - // - // - // + return self; +} + +// +// +// - (BOOL) is7bitSafe - { - NSUInteger i, len; +{ + NSUInteger i, len; - // We search for a non-ASCII character. - len = [self length]; + // We search for a non-ASCII character. + len = [self length]; - for (i = 0; i < len; i++) + for (i = 0; i < len; i++) + { + if ([self characterAtIndex: i] > 0x007E) { - if ([self characterAtIndex: i] > 0x007E) - { - return NO; - } + return NO; } - - return YES; } - // - // - // + return YES; +} + +// +// +// - (NSData *) dataUsingEncodingFromPart: (CWPart *) thePart - { - return [self dataUsingEncodingFromPart: thePart allowLossyConversion: NO]; - } +{ + return [self dataUsingEncodingFromPart: thePart allowLossyConversion: NO]; +} - // - // - // +// +// +// - (NSData *) dataUsingEncodingFromPart: (CWPart *) thePart allowLossyConversion: (BOOL) lossy - { - /* - #ifdef MACOSX - // Use the CF decoding to get the data, bypassing Foundation... - CFStringEncoding enc; - NSData *data; - - enc = [isa encodingForPart: thePart convertToNSStringEncoding: NO]; - data = (NSData *)CFStringCreateExternalRepresentation(NULL, (CFStringRef)self, - enc, (lossy) ? '?' : 0); - return [data autorelease]; - #else - */ - return [self dataUsingEncoding: [object_getClass(self) - encodingForPart: thePart] - allowLossyConversion: lossy]; - //#endif - } +{ + /* + #ifdef MACOSX + // Use the CF decoding to get the data, bypassing Foundation... + CFStringEncoding enc; + NSData *data; + + enc = [isa encodingForPart: thePart convertToNSStringEncoding: NO]; + data = (NSData *)CFStringCreateExternalRepresentation(NULL, (CFStringRef)self, + enc, (lossy) ? '?' : 0); + return [data autorelease]; + #else + */ + return [self dataUsingEncoding: [object_getClass(self) + encodingForPart: thePart] + allowLossyConversion: lossy]; + //#endif +} - // - // - // +// +// +// - (NSData *) dataUsingEncodingWithCharset: (NSString *) theCharset - { - return [self dataUsingEncodingWithCharset: theCharset allowLossyConversion: NO]; - } +{ + return [self dataUsingEncodingWithCharset: theCharset allowLossyConversion: NO]; +} - // - // - // +// +// +// - (NSData *) dataUsingEncodingWithCharset: (NSString *) theCharset allowLossyConversion: (BOOL)lossy - { - /* - #ifdef MACOSX - // Use the CF decoding to get the data, bypassing Foundation... - CFStringEncoding enc; - NSData *data; - - enc = [isa encodingForCharset: [theCharset dataUsingEncoding: NSASCIIStringEncoding] - convertToNSStringEncoding: NO]; - data = (NSData *)CFStringCreateExternalRepresentation(NULL, (CFStringRef)self, - enc, (lossy) ? '?' : 0); - return [data autorelease]; - #else - */ - return [self dataUsingEncoding: - [object_getClass(self) - encodingForCharset: - [theCharset dataUsingEncoding: NSASCIIStringEncoding]] - allowLossyConversion: lossy]; - //#endif - } +{ + /* + #ifdef MACOSX + // Use the CF decoding to get the data, bypassing Foundation... + CFStringEncoding enc; + NSData *data; + + enc = [isa encodingForCharset: [theCharset dataUsingEncoding: NSASCIIStringEncoding] + convertToNSStringEncoding: NO]; + data = (NSData *)CFStringCreateExternalRepresentation(NULL, (CFStringRef)self, + enc, (lossy) ? '?' : 0); + return [data autorelease]; + #else + */ + return [self dataUsingEncoding: + [object_getClass(self) + encodingForCharset: + [theCharset dataUsingEncoding: NSASCIIStringEncoding]] + allowLossyConversion: lossy]; + //#endif +} - - // - // - // + +// +// +// + (NSString *) stringFromRecipients: (NSArray *) theRecipients type: (PantomimeRecipientType) theRecipientType +{ + CWInternetAddress *anInternetAddress; + NSMutableString *aMutableString; + NSUInteger i, count; + + aMutableString = [[NSMutableString alloc] init]; + count = [theRecipients count]; + + for (i = 0; i < count; i++) { - CWInternetAddress *anInternetAddress; - NSMutableString *aMutableString; - NSUInteger i, count; - - aMutableString = [[NSMutableString alloc] init]; - count = [theRecipients count]; - - for (i = 0; i < count; i++) + anInternetAddress = [theRecipients objectAtIndex: i]; + + if ([anInternetAddress type] == theRecipientType) { - anInternetAddress = [theRecipients objectAtIndex: i]; - - if ([anInternetAddress type] == theRecipientType) - { - [aMutableString appendFormat: @"%@, ", [anInternetAddress stringValue]]; - } + [aMutableString appendFormat: @"%@, ", [anInternetAddress stringValue]]; } - - return AUTORELEASE(aMutableString); } + return AUTORELEASE(aMutableString); +} + - (NSString *)wrapped; { if ([self hasPrefix:@"<"] && [self hasSuffix:@">"]) { @@ -946,5 +938,5 @@ } return [NSString stringWithFormat:@"<%@>", self]; } - + @end