Monotone-Parent: 3291dd3b0291e6b09f19d1879b5f7a56fd0f5045
Monotone-Revision: 529806b76290054de1e3af14d027b6f92e169941 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2007-10-30T19:46:48 Monotone-Branch: ca.inverse.sogomaint-2.0.2
parent
cb09961275
commit
0986ba4ba1
21
ChangeLog
21
ChangeLog
|
@ -1,5 +1,26 @@
|
|||
2007-10-30 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* SoObjects/Mailer/NSString+Mail.m ([NSString -htmlToText]): new
|
||||
method converting html content to plain text.
|
||||
|
||||
* SoObjects/Mailer/NSString+Mail.[hm]: new category module
|
||||
enhancing NSString with utility methods pertaining to mail handling.
|
||||
|
||||
* SoObjects/Mailer/SOGoMailObject.m
|
||||
([-shouldFetchPartOfType:_typesubtype:_subtype]): removed obsolete method.
|
||||
([SOGoMailObject
|
||||
-addRequiredKeysOfStructure:infopath:ptoArray:keysacceptedTypes:types]):
|
||||
modified method to be always recursive and to take an array of the
|
||||
accepted mime-types as parameter. The returned array now contains
|
||||
the mime-type as well as the part keys.
|
||||
|
||||
* SoObjects/Mailer/SOGoMailObject+Draft.m ([SOGoMailObject
|
||||
-contentForEditingOnParts:_prtskeys:_k]): removed obsolete method.
|
||||
([SOGoMailObject -contentForEditing]): rewrote method to take into
|
||||
account the first text/plain part or the first text/html part
|
||||
converted to text/plain with our new -[NSString htmlToText]
|
||||
category method.
|
||||
|
||||
* UI/MailerUI/UIxMailActions.m ([-replyToAllAction]): invoke
|
||||
"replyToAll:" with YES as parameter instead of NO.
|
||||
|
||||
|
|
|
@ -32,7 +32,8 @@ Mailer_OBJC_FILES += \
|
|||
\
|
||||
SOGoMailForward.m \
|
||||
\
|
||||
NSData+Mail.m
|
||||
NSData+Mail.m \
|
||||
NSString+Mail.m
|
||||
|
||||
Mailer_RESOURCE_FILES += \
|
||||
Version \
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/* NSString+Mail.h - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2007 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef NSSTRING_MAIL_H
|
||||
#define NSSTRING_MAIL_H
|
||||
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
@interface NSString (SOGoExtension)
|
||||
|
||||
- (NSString *) htmlToText;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* NSSTRING_MAIL_H */
|
|
@ -0,0 +1,351 @@
|
|||
/* NSString+Mail.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2007 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <SaxObjC/SaxAttributes.h>
|
||||
#import <SaxObjC/SaxContentHandler.h>
|
||||
#import <SaxObjC/SaxLexicalHandler.h>
|
||||
#import <SaxObjC/SaxXMLReader.h>
|
||||
#import <SaxObjC/SaxXMLReaderFactory.h>
|
||||
#import <NGExtensions/NSString+misc.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
#import "NSString+Mail.h"
|
||||
|
||||
#if 1
|
||||
#define showWhoWeAre() \
|
||||
[self logWithFormat: @"invoked '%@'", NSStringFromSelector (_cmd)]
|
||||
#else
|
||||
#define showWhoWeAre() {}
|
||||
#endif
|
||||
|
||||
@interface _SOGoHTMLToTextContentHandler : NSObject <SaxContentHandler, SaxLexicalHandler>
|
||||
{
|
||||
NSArray *ignoreContentTags;
|
||||
NSArray *specialTreatmentTags;
|
||||
|
||||
BOOL ignoreContent;
|
||||
BOOL orderedList;
|
||||
BOOL unorderedList;
|
||||
unsigned int listCount;
|
||||
|
||||
NSMutableString *result;
|
||||
}
|
||||
|
||||
+ (id) htmlToTextContentHandler;
|
||||
|
||||
- (NSString *) result;
|
||||
|
||||
@end
|
||||
|
||||
@implementation _SOGoHTMLToTextContentHandler
|
||||
|
||||
+ (id) htmlToTextContentHandler
|
||||
{
|
||||
static id htmlToTextContentHandler;
|
||||
|
||||
if (!htmlToTextContentHandler)
|
||||
htmlToTextContentHandler = [self new];
|
||||
|
||||
return htmlToTextContentHandler;
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
ignoreContentTags = [NSArray arrayWithObjects: @"head", @"script",
|
||||
@"style", nil];
|
||||
specialTreatmentTags = [NSArray arrayWithObjects: @"body", @"p", @"ul",
|
||||
@"li", @"table", @"tr", @"td", @"th",
|
||||
@"br", @"hr", @"dt", @"dd", nil];
|
||||
[ignoreContentTags retain];
|
||||
[specialTreatmentTags retain];
|
||||
|
||||
ignoreContent = NO;
|
||||
result = nil;
|
||||
|
||||
orderedList = NO;
|
||||
unorderedList = NO;
|
||||
listCount = 0;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[ignoreContentTags release];
|
||||
[specialTreatmentTags release];
|
||||
[result release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString *) result
|
||||
{
|
||||
NSString *newResult;
|
||||
|
||||
newResult = [NSString stringWithString: result];
|
||||
[result release];
|
||||
result = nil;
|
||||
|
||||
return newResult;
|
||||
}
|
||||
|
||||
/* SaxContentHandler */
|
||||
- (void) startDocument
|
||||
{
|
||||
showWhoWeAre();
|
||||
|
||||
[result release];
|
||||
result = [NSMutableString new];
|
||||
}
|
||||
|
||||
- (void) endDocument
|
||||
{
|
||||
showWhoWeAre();
|
||||
|
||||
ignoreContent = NO;
|
||||
}
|
||||
|
||||
- (void) startPrefixMapping: (NSString *) prefix
|
||||
uri: (NSString *) uri
|
||||
{
|
||||
showWhoWeAre();
|
||||
}
|
||||
|
||||
- (void) endPrefixMapping: (NSString *) prefix
|
||||
{
|
||||
showWhoWeAre();
|
||||
}
|
||||
|
||||
- (void) _startSpecialTreatment: (NSString *) tagName
|
||||
{
|
||||
if ([tagName isEqualToString: @"br"]
|
||||
|| [tagName isEqualToString: @"p"])
|
||||
[result appendString: @"\n"];
|
||||
else if ([tagName isEqualToString: @"hr"])
|
||||
[result appendString: @"______________________________________________________________________________\n"];
|
||||
else if ([tagName isEqualToString: @"ul"])
|
||||
{
|
||||
[result appendString: @"\n"];
|
||||
unorderedList = YES;
|
||||
}
|
||||
else if ([tagName isEqualToString: @"ol"])
|
||||
{
|
||||
[result appendString: @"\n"];
|
||||
orderedList = YES;
|
||||
listCount = 0;
|
||||
}
|
||||
else if ([tagName isEqualToString: @"li"])
|
||||
{
|
||||
if (orderedList)
|
||||
{
|
||||
listCount++;
|
||||
[result appendFormat: @" %d. ", listCount];
|
||||
}
|
||||
else
|
||||
[result appendString: @" * "];
|
||||
}
|
||||
else if ([tagName isEqualToString: @"dd"])
|
||||
[result appendString: @" "];
|
||||
}
|
||||
|
||||
- (void) _endSpecialTreatment: (NSString *) tagName
|
||||
{
|
||||
if ([tagName isEqualToString: @"ul"])
|
||||
{
|
||||
[result appendString: @"\n"];
|
||||
unorderedList = NO;
|
||||
}
|
||||
else if ([tagName isEqualToString: @"ol"])
|
||||
{
|
||||
[result appendString: @"\n"];
|
||||
orderedList = NO;
|
||||
}
|
||||
else if ([tagName isEqualToString: @"dt"])
|
||||
{
|
||||
[result appendString: @":\n"];
|
||||
}
|
||||
else if ([tagName isEqualToString: @"li"]
|
||||
|| [tagName isEqualToString: @"dd"])
|
||||
[result appendString: @"\n"];
|
||||
}
|
||||
|
||||
- (void) startElement: (NSString *) element
|
||||
namespace: (NSString *) namespace
|
||||
rawName: (NSString *) rawName
|
||||
attributes: (id <SaxAttributes>) attributes
|
||||
{
|
||||
NSString *tagName;
|
||||
|
||||
showWhoWeAre();
|
||||
|
||||
if (!ignoreContent)
|
||||
{
|
||||
tagName = [rawName lowercaseString];
|
||||
if ([ignoreContentTags containsObject: tagName])
|
||||
ignoreContent = YES;
|
||||
else if ([specialTreatmentTags containsObject: tagName])
|
||||
[self _startSpecialTreatment: tagName];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) endElement: (NSString *) element
|
||||
namespace: (NSString *) namespace
|
||||
rawName: (NSString *) rawName
|
||||
{
|
||||
NSString *tagName;
|
||||
|
||||
showWhoWeAre();
|
||||
|
||||
if (ignoreContent)
|
||||
{
|
||||
tagName = [rawName lowercaseString];
|
||||
if ([ignoreContentTags containsObject: tagName])
|
||||
ignoreContent = NO;
|
||||
else if ([specialTreatmentTags containsObject: tagName])
|
||||
[self _endSpecialTreatment: tagName];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) characters: (unichar *) characters
|
||||
length: (int) length
|
||||
{
|
||||
if (!ignoreContent)
|
||||
[result appendString: [NSString stringWithCharacters: characters
|
||||
length: length]];
|
||||
}
|
||||
|
||||
- (void) ignorableWhitespace: (unichar *) whitespaces
|
||||
length: (int) length
|
||||
{
|
||||
showWhoWeAre();
|
||||
}
|
||||
|
||||
- (void) processingInstruction: (NSString *) pi
|
||||
data: (NSString *) data
|
||||
{
|
||||
showWhoWeAre();
|
||||
}
|
||||
|
||||
- (void) setDocumentLocator: (id <NSObject, SaxLocator>) locator
|
||||
{
|
||||
showWhoWeAre();
|
||||
}
|
||||
|
||||
- (void) skippedEntity: (NSString *) entity
|
||||
{
|
||||
showWhoWeAre();
|
||||
}
|
||||
|
||||
/* SaxLexicalHandler */
|
||||
- (void) comment: (unichar *) chars
|
||||
length: (int) len
|
||||
{
|
||||
showWhoWeAre();
|
||||
}
|
||||
|
||||
- (void) startDTD: (NSString *) name
|
||||
publicId: (NSString *) pub
|
||||
systemId: (NSString *) sys
|
||||
{
|
||||
showWhoWeAre();
|
||||
}
|
||||
|
||||
- (void) endDTD
|
||||
{
|
||||
showWhoWeAre();
|
||||
}
|
||||
|
||||
- (void) startEntity: (NSString *) entity
|
||||
{
|
||||
showWhoWeAre();
|
||||
}
|
||||
|
||||
- (void) endEntity: (NSString *) entity
|
||||
{
|
||||
showWhoWeAre();
|
||||
}
|
||||
|
||||
- (void) startCDATA
|
||||
{
|
||||
showWhoWeAre();
|
||||
}
|
||||
|
||||
- (void) endCDATA
|
||||
{
|
||||
showWhoWeAre();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// @interface NSDictionary (SOGoDebug)
|
||||
|
||||
// - (void) dump;
|
||||
|
||||
// @end
|
||||
|
||||
// @implementation NSDictionary (SOGoDebug)
|
||||
|
||||
// - (void) dump
|
||||
// {
|
||||
// NSEnumerator *keys;
|
||||
// NSString *key;
|
||||
// NSMutableString *dump;
|
||||
|
||||
// dump = [NSMutableString new];
|
||||
// [dump appendFormat: @"\nNSDictionary dump (%@):\n", self];
|
||||
// keys = [[self allKeys] objectEnumerator];
|
||||
// key = [keys nextObject];
|
||||
// while (key)
|
||||
// {
|
||||
// [dump appendFormat: @"%@: %@\n", key, [self objectForKey: key]];
|
||||
// key = [keys nextObject];
|
||||
// }
|
||||
// [dump appendFormat: @"--- end ---\n"];
|
||||
|
||||
// NSLog (dump);
|
||||
// [dump release];
|
||||
// }
|
||||
|
||||
// @end
|
||||
|
||||
@implementation NSString (SOGoExtension)
|
||||
|
||||
- (NSString *) htmlToText
|
||||
{
|
||||
id <NSObject, SaxXMLReader> parser;
|
||||
_SOGoHTMLToTextContentHandler *handler;
|
||||
|
||||
parser = [[SaxXMLReaderFactory standardXMLReaderFactory]
|
||||
createXMLReaderForMimeType: @"text/html"];
|
||||
handler = [_SOGoHTMLToTextContentHandler htmlToTextContentHandler];
|
||||
[parser setContentHandler: handler];
|
||||
[parser parseFromSource: self];
|
||||
|
||||
return [handler result];
|
||||
}
|
||||
|
||||
@end
|
|
@ -27,8 +27,10 @@
|
|||
#import <NGExtensions/NSString+misc.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
#import <SoObjects/SOGo/NSArray+Utilities.h>
|
||||
#import <SoObjects/SOGo/SOGoUser.h>
|
||||
|
||||
#import "NSString+Mail.h"
|
||||
#import "SOGoMailForward.h"
|
||||
#import "SOGoMailObject+Draft.h"
|
||||
|
||||
|
@ -67,98 +69,54 @@
|
|||
return newSubject;
|
||||
}
|
||||
|
||||
- (NSString *) contentForEditingOnParts: (NSDictionary *) _prts
|
||||
keys: (NSArray *) _k
|
||||
|
||||
- (NSString *) _contentForEditingFromKeys: (NSArray *) keys
|
||||
{
|
||||
static NSString *textPartSeparator = @"\n---\n";
|
||||
NSMutableString *ms;
|
||||
unsigned int count, max;
|
||||
NSString *k, *v;
|
||||
|
||||
ms = [NSMutableString stringWithCapacity: 16000];
|
||||
|
||||
max = [_k count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
k = [_k objectAtIndex: count];
|
||||
|
||||
// TODO: this is DUP code to SOGoMailObject
|
||||
if ([k isEqualToString: @"body[text]"])
|
||||
k = @"";
|
||||
else if ([k hasPrefix: @"body["]) {
|
||||
k = [k substringFromIndex: 5];
|
||||
if ([k length] > 0)
|
||||
k = [k substringToIndex: ([k length] - 1)];
|
||||
}
|
||||
|
||||
v = [_prts objectForKey: k];
|
||||
if ([v isKindOfClass: [NSString class]]
|
||||
&& [v length] > 0)
|
||||
{
|
||||
if (count > 0)
|
||||
[ms appendString: textPartSeparator];
|
||||
[ms appendString: v];
|
||||
}
|
||||
else
|
||||
[self logWithFormat:@"Note: cannot show part %@", k];
|
||||
}
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
||||
#warning this method should be fixed to return the first available text/plain \
|
||||
part, and otherwise the first text/html part converted to text
|
||||
- (NSString *) contentForEditing
|
||||
{
|
||||
NSArray *keys;
|
||||
NSArray *types;
|
||||
NSDictionary *parts;
|
||||
NSMutableArray *topLevelKeys = nil;
|
||||
unsigned int count, max;
|
||||
NSRange r;
|
||||
NSString *contentForEditing;
|
||||
NSString *rawPart, *content;
|
||||
int index;
|
||||
BOOL htmlContent;
|
||||
|
||||
// SOGoMailObject *co;
|
||||
|
||||
// co = self;
|
||||
// keys = [co plainTextContentFetchKeys];
|
||||
// infos = [co fetchCoreInfos];
|
||||
// partInfos = [infos objectForKey: keys];
|
||||
// NSLog (@"infos: '%@'", infos);
|
||||
|
||||
keys = [self plainTextContentFetchKeys];
|
||||
max = [keys count];
|
||||
if (max > 0)
|
||||
if ([keys count])
|
||||
{
|
||||
if (max > 1)
|
||||
types = [keys objectsForKey: @"mimeType"];
|
||||
index = [types indexOfObject: @"text/plain"];
|
||||
if (index == NSNotFound)
|
||||
{
|
||||
/* filter keys, only include top-level, or if none, the first */
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
r = [[keys objectAtIndex: count] rangeOfString: @"."];
|
||||
if (!r.length)
|
||||
{
|
||||
if (!topLevelKeys)
|
||||
topLevelKeys = [NSMutableArray arrayWithCapacity: 4];
|
||||
[topLevelKeys addObject: [keys objectAtIndex: count]];
|
||||
}
|
||||
}
|
||||
|
||||
if ([topLevelKeys count] > 0)
|
||||
/* use top-level keys if we have some */
|
||||
keys = topLevelKeys;
|
||||
else
|
||||
/* just take the first part */
|
||||
keys = [NSArray arrayWithObject: [keys objectAtIndex: 0]];
|
||||
index = [types indexOfObject: @"text/html"];
|
||||
htmlContent = YES;
|
||||
}
|
||||
if (index == NSNotFound)
|
||||
content = @"";
|
||||
else
|
||||
{
|
||||
parts = [self fetchPlainTextStrings: keys];
|
||||
rawPart = [[parts allValues] objectAtIndex: 0];
|
||||
if (htmlContent)
|
||||
content = [rawPart htmlToText];
|
||||
else
|
||||
content = rawPart;
|
||||
}
|
||||
|
||||
parts = [self fetchPlainTextStrings: keys];
|
||||
contentForEditing = [self contentForEditingOnParts: parts
|
||||
keys: keys];
|
||||
}
|
||||
else
|
||||
contentForEditing = nil;
|
||||
content = @"";
|
||||
|
||||
return contentForEditing;
|
||||
return content;
|
||||
}
|
||||
|
||||
- (NSString *) contentForEditing
|
||||
{
|
||||
NSMutableArray *keys;
|
||||
NSArray *acceptedTypes;
|
||||
|
||||
acceptedTypes
|
||||
= [NSArray arrayWithObjects: @"text/plain", @"text/html", nil];
|
||||
keys = [NSMutableArray new];
|
||||
[self addRequiredKeysOfStructure: [self bodyStructure]
|
||||
path: @"" toArray: keys acceptedTypes: acceptedTypes];
|
||||
|
||||
return [self _contentForEditingFromKeys: keys];
|
||||
}
|
||||
|
||||
- (NSString *) contentForReply
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#import <NGImap4/NGImap4EnvelopeAddress.h>
|
||||
#import <NGMail/NGMimeMessageParser.h>
|
||||
|
||||
#import <SoObjects/SOGo/NSArray+Utilities.h>
|
||||
#import <SoObjects/SOGo/SOGoPermissions.h>
|
||||
#import <SoObjects/SOGo/SOGoUser.h>
|
||||
|
||||
|
@ -181,10 +182,13 @@ static BOOL debugSoParts = NO;
|
|||
return ma;
|
||||
}
|
||||
|
||||
- (NSArray *)toOneRelationshipKeys {
|
||||
- (NSArray *) toOneRelationshipKeys
|
||||
{
|
||||
return [self relationshipKeysWithParts:NO];
|
||||
}
|
||||
- (NSArray *)toManyRelationshipKeys {
|
||||
|
||||
- (NSArray *) toManyRelationshipKeys
|
||||
{
|
||||
return [self relationshipKeysWithParts:YES];
|
||||
}
|
||||
|
||||
|
@ -468,29 +472,29 @@ static BOOL debugSoParts = NO;
|
|||
|
||||
/* bulk fetching of plain/text content */
|
||||
|
||||
- (BOOL) shouldFetchPartOfType: (NSString *) _type
|
||||
subtype: (NSString *) _subtype
|
||||
{
|
||||
/*
|
||||
This method decides which parts are 'prefetched' for display. Those are
|
||||
usually text parts (the set is currently hardcoded in this method ...).
|
||||
*/
|
||||
_type = [_type lowercaseString];
|
||||
_subtype = [_subtype lowercaseString];
|
||||
// - (BOOL) shouldFetchPartOfType: (NSString *) _type
|
||||
// subtype: (NSString *) _subtype
|
||||
// {
|
||||
// /*
|
||||
// This method decides which parts are 'prefetched' for display. Those are
|
||||
// usually text parts (the set is currently hardcoded in this method ...).
|
||||
// */
|
||||
// _type = [_type lowercaseString];
|
||||
// _subtype = [_subtype lowercaseString];
|
||||
|
||||
return (([_type isEqualToString: @"text"]
|
||||
&& ([_subtype isEqualToString: @"plain"]
|
||||
|| [_subtype isEqualToString: @"html"]
|
||||
|| [_subtype isEqualToString: @"calendar"]))
|
||||
|| ([_type isEqualToString: @"application"]
|
||||
&& ([_subtype isEqualToString: @"pgp-signature"]
|
||||
|| [_subtype hasPrefix: @"x-vnd.kolab."])));
|
||||
}
|
||||
// return (([_type isEqualToString: @"text"]
|
||||
// && ([_subtype isEqualToString: @"plain"]
|
||||
// || [_subtype isEqualToString: @"html"]
|
||||
// || [_subtype isEqualToString: @"calendar"]))
|
||||
// || ([_type isEqualToString: @"application"]
|
||||
// && ([_subtype isEqualToString: @"pgp-signature"]
|
||||
// || [_subtype hasPrefix: @"x-vnd.kolab."])));
|
||||
// }
|
||||
|
||||
- (void) addRequiredKeysOfStructure: (id) _info
|
||||
path: (NSString *) _p
|
||||
toArray: (NSMutableArray *) _keys
|
||||
recurse: (BOOL) _recurse
|
||||
- (void) addRequiredKeysOfStructure: (NSDictionary *) info
|
||||
path: (NSString *) p
|
||||
toArray: (NSMutableArray *) keys
|
||||
acceptedTypes: (NSArray *) types
|
||||
{
|
||||
/*
|
||||
This is used to collect the set of IMAP4 fetch-keys required to fetch
|
||||
|
@ -501,19 +505,19 @@ static BOOL debugSoParts = NO;
|
|||
*/
|
||||
NSArray *parts;
|
||||
unsigned i, count;
|
||||
BOOL fetchPart;
|
||||
NSString *k;
|
||||
id body;
|
||||
NSString *sp;
|
||||
NSString *sp, *mimeType;
|
||||
id childInfo;
|
||||
|
||||
/* Note: if the part itself doesn't qualify, we still check subparts */
|
||||
fetchPart = [self shouldFetchPartOfType: [_info valueForKey: @"type"]
|
||||
subtype: [_info valueForKey: @"subtype"]];
|
||||
if (fetchPart)
|
||||
|
||||
mimeType = [[NSString stringWithFormat: @"%@/%@",
|
||||
[info valueForKey: @"type"],
|
||||
[info valueForKey: @"subtype"]]
|
||||
lowercaseString];
|
||||
if ([types containsObject: mimeType])
|
||||
{
|
||||
if ([_p length] > 0)
|
||||
k = [NSString stringWithFormat: @"body[%@]", _p];
|
||||
if ([p length] > 0)
|
||||
k = [NSString stringWithFormat: @"body[%@]", p];
|
||||
else
|
||||
{
|
||||
/*
|
||||
|
@ -523,40 +527,37 @@ static BOOL debugSoParts = NO;
|
|||
*/
|
||||
k = @"body[text]";
|
||||
}
|
||||
[_keys addObject: k];
|
||||
[keys addObject: [NSDictionary dictionaryWithObjectsAndKeys: k, @"key",
|
||||
mimeType, @"mimeType", nil]];
|
||||
}
|
||||
|
||||
if (_recurse)
|
||||
parts = [info objectForKey: @"parts"];
|
||||
count = [parts count];
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
/* recurse */
|
||||
parts = [(NSDictionary *)_info objectForKey: @"parts"];
|
||||
count = [parts count];
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
sp = (([_p length] > 0)
|
||||
? [_p stringByAppendingFormat: @".%d", i + 1]
|
||||
: [NSString stringWithFormat: @"%d", i + 1]);
|
||||
|
||||
childInfo = [parts objectAtIndex: i];
|
||||
|
||||
[self addRequiredKeysOfStructure: childInfo
|
||||
path: sp toArray: _keys
|
||||
recurse: YES];
|
||||
}
|
||||
sp = (([p length] > 0)
|
||||
? [p stringByAppendingFormat: @".%d", i + 1]
|
||||
: [NSString stringWithFormat: @"%d", i + 1]);
|
||||
|
||||
/* check body */
|
||||
body = [(NSDictionary *)_info objectForKey: @"body"];
|
||||
if (body)
|
||||
{
|
||||
sp = [[body valueForKey: @"type"] lowercaseString];
|
||||
if ([sp isEqualToString: @"multipart"])
|
||||
sp = _p;
|
||||
else
|
||||
sp = [_p length] > 0 ? [_p stringByAppendingString: @".1"] : @"1";
|
||||
[self addRequiredKeysOfStructure: body
|
||||
path: sp toArray: _keys
|
||||
recurse: YES];
|
||||
}
|
||||
childInfo = [parts objectAtIndex: i];
|
||||
|
||||
[self addRequiredKeysOfStructure: childInfo
|
||||
path: sp toArray: keys
|
||||
acceptedTypes: types];
|
||||
}
|
||||
|
||||
/* check body */
|
||||
body = [info objectForKey: @"body"];
|
||||
if (body)
|
||||
{
|
||||
sp = [[body valueForKey: @"type"] lowercaseString];
|
||||
if ([sp isEqualToString: @"multipart"])
|
||||
sp = p;
|
||||
else
|
||||
sp = [p length] > 0 ? [p stringByAppendingString: @".1"] : @"1";
|
||||
[self addRequiredKeysOfStructure: body
|
||||
path: sp toArray: keys
|
||||
acceptedTypes: types];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -567,10 +568,13 @@ static BOOL debugSoParts = NO;
|
|||
keys which are marked by the -shouldFetchPartOfType:subtype: method.
|
||||
*/
|
||||
NSMutableArray *ma;
|
||||
|
||||
ma = [NSMutableArray arrayWithCapacity:4];
|
||||
NSArray *types;
|
||||
|
||||
types = [NSArray arrayWithObjects: @"text/plain", @"text/html",
|
||||
@"text/calendar", @"application/pgp-signature", nil];
|
||||
ma = [NSMutableArray arrayWithCapacity: 4];
|
||||
[self addRequiredKeysOfStructure: [self bodyStructure]
|
||||
path: @"" toArray: ma recurse: YES];
|
||||
path: @"" toArray: ma acceptedTypes: types];
|
||||
|
||||
return ma;
|
||||
}
|
||||
|
@ -584,7 +588,7 @@ static BOOL debugSoParts = NO;
|
|||
|
||||
[self debugWithFormat: @"fetch keys: %@", _fetchKeys];
|
||||
|
||||
result = [self fetchParts:_fetchKeys];
|
||||
result = [self fetchParts: [_fetchKeys objectsForKey: @"key"]];
|
||||
result = [result valueForKey: @"RawResponse"]; // hackish
|
||||
|
||||
// Note: -valueForKey: doesn't work!
|
||||
|
@ -596,7 +600,7 @@ static BOOL debugSoParts = NO;
|
|||
NSString *key;
|
||||
NSData *data;
|
||||
|
||||
key = [_fetchKeys objectAtIndex:i];
|
||||
key = [[_fetchKeys objectAtIndex:i] objectForKey: @"key"];
|
||||
data = [(NSDictionary *)[(NSDictionary *)result objectForKey:key]
|
||||
objectForKey: @"data"];
|
||||
|
||||
|
@ -622,7 +626,7 @@ static BOOL debugSoParts = NO;
|
|||
|
||||
- (NSDictionary *) fetchPlainTextParts
|
||||
{
|
||||
return [self fetchPlainTextParts:[self plainTextContentFetchKeys]];
|
||||
return [self fetchPlainTextParts: [self plainTextContentFetchKeys]];
|
||||
}
|
||||
|
||||
/* convert parts to strings */
|
||||
|
@ -656,19 +660,20 @@ static BOOL debugSoParts = NO;
|
|||
- (NSDictionary *) stringifyTextParts: (NSDictionary *) _datas
|
||||
{
|
||||
NSMutableDictionary *md;
|
||||
NSDictionary *info;
|
||||
NSEnumerator *keys;
|
||||
NSString *key;
|
||||
|
||||
md = [NSMutableDictionary dictionaryWithCapacity:4];
|
||||
NSString *key, *s;
|
||||
|
||||
md = [NSMutableDictionary dictionaryWithCapacity:4];
|
||||
keys = [_datas keyEnumerator];
|
||||
while ((key = [keys nextObject]) != nil) {
|
||||
NSDictionary *info;
|
||||
NSString *s;
|
||||
|
||||
info = [self lookupInfoForBodyPart:key];
|
||||
if ((s = [self stringForData:[_datas objectForKey:key] partInfo:info]))
|
||||
[md setObject:s forKey:key];
|
||||
}
|
||||
while ((key = [keys nextObject]))
|
||||
{
|
||||
info = [self lookupInfoForBodyPart: key];
|
||||
s = [self stringForData: [_datas objectForKey:key] partInfo: info];
|
||||
if (s)
|
||||
[md setObject: s forKey: key];
|
||||
}
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue