<img src=data...> conversion to file attachments + CIDs.
parent
6587f4f193
commit
e4aedbac08
13
NEWS
13
NEWS
|
@ -1,3 +1,16 @@
|
||||||
|
2.1.2 (2013-11-XX)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
New features
|
||||||
|
-
|
||||||
|
|
||||||
|
Enhancements
|
||||||
|
- we now automatically convert <img src=data...> into file attachments
|
||||||
|
using CIDs. This prevents Outlook issues.
|
||||||
|
|
||||||
|
Bug fixes
|
||||||
|
-
|
||||||
|
|
||||||
2.1.1 (2013-11-19)
|
2.1.1 (2013-11-19)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,16 @@
|
||||||
#ifndef NSSTRING_MAIL_H
|
#ifndef NSSTRING_MAIL_H
|
||||||
#define NSSTRING_MAIL_H
|
#define NSSTRING_MAIL_H
|
||||||
|
|
||||||
|
#import <Foundation/NSArray.h>
|
||||||
#import <Foundation/NSString.h>
|
#import <Foundation/NSString.h>
|
||||||
|
|
||||||
@interface NSString (SOGoExtension)
|
@interface NSString (SOGoExtension)
|
||||||
|
|
||||||
- (NSString *) htmlToText;
|
- (NSString *) htmlToText;
|
||||||
|
- (NSString *) htmlByExtractingImages: (NSMutableArray *) theImages;
|
||||||
- (NSString *) stringByConvertingCRLNToHTML;
|
- (NSString *) stringByConvertingCRLNToHTML;
|
||||||
|
- (int) indexOf: (unichar) _c
|
||||||
|
fromIndex: (int) start;
|
||||||
- (int) indexOf: (unichar) _c;
|
- (int) indexOf: (unichar) _c;
|
||||||
- (NSString *) decodedHeader;
|
- (NSString *) decodedHeader;
|
||||||
|
|
||||||
|
|
|
@ -22,19 +22,25 @@
|
||||||
#import <Foundation/NSDictionary.h>
|
#import <Foundation/NSDictionary.h>
|
||||||
#import <Foundation/NSObject.h>
|
#import <Foundation/NSObject.h>
|
||||||
#import <Foundation/NSException.h>
|
#import <Foundation/NSException.h>
|
||||||
|
#import <Foundation/NSValue.h>
|
||||||
|
|
||||||
#import <SaxObjC/SaxAttributes.h>
|
#import <SaxObjC/SaxAttributes.h>
|
||||||
#import <SaxObjC/SaxContentHandler.h>
|
#import <SaxObjC/SaxContentHandler.h>
|
||||||
#import <SaxObjC/SaxLexicalHandler.h>
|
#import <SaxObjC/SaxLexicalHandler.h>
|
||||||
#import <SaxObjC/SaxXMLReader.h>
|
#import <SaxObjC/SaxXMLReader.h>
|
||||||
#import <SaxObjC/SaxXMLReaderFactory.h>
|
#import <SaxObjC/SaxXMLReaderFactory.h>
|
||||||
|
#import <NGExtensions/NGHashMap.h>
|
||||||
#import <NGExtensions/NGQuotedPrintableCoding.h>
|
#import <NGExtensions/NGQuotedPrintableCoding.h>
|
||||||
#import <NGExtensions/NSString+misc.h>
|
#import <NGExtensions/NSString+misc.h>
|
||||||
#import <NGExtensions/NSObject+Logs.h>
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
#import <NGMime/NGMimeBodyPart.h>
|
||||||
|
#import <NGMime/NGMimeFileData.h>
|
||||||
|
|
||||||
#include <libxml/encoding.h>
|
#include <libxml/encoding.h>
|
||||||
|
|
||||||
#import "NSString+Mail.h"
|
#import "NSString+Mail.h"
|
||||||
#import "NSData+Mail.h"
|
#import "NSData+Mail.h"
|
||||||
|
#import "../SOGo/SOGoObject.h"
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define showWhoWeAre() \
|
#define showWhoWeAre() \
|
||||||
|
@ -43,8 +49,12 @@
|
||||||
#define showWhoWeAre() {}
|
#define showWhoWeAre() {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@interface _SOGoHTMLToTextContentHandler : NSObject <SaxContentHandler, SaxLexicalHandler>
|
#define paddingBuffer 8192
|
||||||
|
|
||||||
|
@interface _SOGoHTMLContentHandler : NSObject <SaxContentHandler, SaxLexicalHandler>
|
||||||
{
|
{
|
||||||
|
NSMutableArray *images;
|
||||||
|
|
||||||
NSArray *ignoreContentTags;
|
NSArray *ignoreContentTags;
|
||||||
NSArray *specialTreatmentTags;
|
NSArray *specialTreatmentTags;
|
||||||
|
|
||||||
|
@ -57,32 +67,26 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id) htmlToTextContentHandler;
|
+ (id) htmlToTextContentHandler;
|
||||||
|
+ (id) sanitizerContentHandler;
|
||||||
|
|
||||||
- (NSString *) result;
|
- (NSString *) result;
|
||||||
|
|
||||||
|
- (void) setIgnoreContentTags: (NSArray *) theTags;
|
||||||
|
- (void) setSpecialTreatmentTags: (NSArray *) theTags;
|
||||||
|
- (void) setImages: (NSMutableArray *) theImages;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation _SOGoHTMLToTextContentHandler
|
@implementation _SOGoHTMLContentHandler
|
||||||
|
|
||||||
+ (id) htmlToTextContentHandler
|
|
||||||
{
|
|
||||||
static id htmlToTextContentHandler;
|
|
||||||
|
|
||||||
if (!htmlToTextContentHandler)
|
|
||||||
htmlToTextContentHandler = [self new];
|
|
||||||
|
|
||||||
return htmlToTextContentHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) init
|
- (id) init
|
||||||
{
|
{
|
||||||
if ((self = [super init]))
|
if ((self = [super init]))
|
||||||
{
|
{
|
||||||
ignoreContentTags = [NSArray arrayWithObjects: @"head", @"script",
|
images = nil;
|
||||||
@"style", nil];
|
|
||||||
specialTreatmentTags = [NSArray arrayWithObjects: @"body", @"p", @"ul",
|
ignoreContentTags = nil;
|
||||||
@"li", @"table", @"tr", @"td", @"th",
|
specialTreatmentTags = nil;
|
||||||
@"br", @"hr", @"dt", @"dd", nil];
|
|
||||||
[ignoreContentTags retain];
|
[ignoreContentTags retain];
|
||||||
[specialTreatmentTags retain];
|
[specialTreatmentTags retain];
|
||||||
|
|
||||||
|
@ -97,6 +101,32 @@
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (id) htmlToTextContentHandler
|
||||||
|
{
|
||||||
|
static id htmlToTextContentHandler;
|
||||||
|
|
||||||
|
if (!htmlToTextContentHandler)
|
||||||
|
htmlToTextContentHandler = [self new];
|
||||||
|
|
||||||
|
[htmlToTextContentHandler setIgnoreContentTags: [NSArray arrayWithObjects: @"head", @"script",
|
||||||
|
@"style", nil]];
|
||||||
|
[htmlToTextContentHandler setSpecialTreatmentTags: [NSArray arrayWithObjects: @"body", @"p", @"ul",
|
||||||
|
@"li", @"table", @"tr", @"td", @"th",
|
||||||
|
@"br", @"hr", @"dt", @"dd", nil]];
|
||||||
|
|
||||||
|
return htmlToTextContentHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (id) sanitizerContentHandler
|
||||||
|
{
|
||||||
|
static id sanitizerContentHandler;
|
||||||
|
|
||||||
|
if (!sanitizerContentHandler)
|
||||||
|
sanitizerContentHandler = [self new];
|
||||||
|
|
||||||
|
return sanitizerContentHandler;
|
||||||
|
}
|
||||||
|
|
||||||
- (xmlCharEncoding) contentEncoding
|
- (xmlCharEncoding) contentEncoding
|
||||||
{
|
{
|
||||||
return XML_CHAR_ENCODING_UTF8;
|
return XML_CHAR_ENCODING_UTF8;
|
||||||
|
@ -121,6 +151,25 @@
|
||||||
return newResult;
|
return newResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) setIgnoreContentTags: (NSArray *) theTags
|
||||||
|
{
|
||||||
|
ASSIGN(ignoreContentTags, theTags);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setSpecialTreatmentTags: (NSArray *) theTags
|
||||||
|
{
|
||||||
|
ASSIGN(specialTreatmentTags, theTags);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// We MUST NOT retain the array here
|
||||||
|
//
|
||||||
|
- (void) setImages: (NSMutableArray *) theImages
|
||||||
|
{
|
||||||
|
images = theImages;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* SaxContentHandler */
|
/* SaxContentHandler */
|
||||||
- (void) startDocument
|
- (void) startDocument
|
||||||
{
|
{
|
||||||
|
@ -210,14 +259,89 @@
|
||||||
|
|
||||||
showWhoWeAre();
|
showWhoWeAre();
|
||||||
|
|
||||||
if (!ignoreContent)
|
tagName = [rawName lowercaseString];
|
||||||
|
|
||||||
|
if (!ignoreContent && ignoreContentTags && specialTreatmentTags)
|
||||||
{
|
{
|
||||||
tagName = [rawName lowercaseString];
|
|
||||||
if ([ignoreContentTags containsObject: tagName])
|
if ([ignoreContentTags containsObject: tagName])
|
||||||
ignoreContent = YES;
|
ignoreContent = YES;
|
||||||
else if ([specialTreatmentTags containsObject: tagName])
|
else if ([specialTreatmentTags containsObject: tagName])
|
||||||
[self _startSpecialTreatment: tagName];
|
[self _startSpecialTreatment: tagName];
|
||||||
}
|
}
|
||||||
|
else if ([tagName isEqualToString: @"img"])
|
||||||
|
{
|
||||||
|
NSString *value;
|
||||||
|
|
||||||
|
value = [attributes valueForRawName: @"src"];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check for Data URI Scheme
|
||||||
|
//
|
||||||
|
// data:[<MIME-type>][;charset=<encoding>][;base64],<data>
|
||||||
|
//
|
||||||
|
if ([value length] > 5 && [[value substringToIndex: 5] caseInsensitiveCompare: @"data:"] == NSOrderedSame)
|
||||||
|
{
|
||||||
|
NSString *uniqueId, *mimeType, *encoding, *charset;
|
||||||
|
NGMimeBodyPart *bodyPart;
|
||||||
|
NGMutableHashMap *map;
|
||||||
|
NSData *data;
|
||||||
|
id body;
|
||||||
|
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
i = [value indexOf: ';'];
|
||||||
|
j = [value indexOf: ';' fromIndex: i+1];
|
||||||
|
k = [value indexOf: ','];
|
||||||
|
|
||||||
|
// We try to get the MIME type
|
||||||
|
mimeType = nil;
|
||||||
|
|
||||||
|
if (i > 5 && i < k)
|
||||||
|
{
|
||||||
|
mimeType = [value substringWithRange: NSMakeRange(5, i-5)];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
i = 5;
|
||||||
|
|
||||||
|
// We might get a stupid value. We discard anything that doesn't have a / in it
|
||||||
|
if ([mimeType indexOf: '/'] < 0)
|
||||||
|
mimeType = @"image/jpeg";
|
||||||
|
|
||||||
|
// We check and skip the charset
|
||||||
|
if (j > i)
|
||||||
|
charset = [value substringWithRange: NSMakeRange(i+1, j-i-1)];
|
||||||
|
else
|
||||||
|
j = i;
|
||||||
|
|
||||||
|
// We check the encoding and we completely ignore it
|
||||||
|
encoding = [value substringWithRange: NSMakeRange(j+1, k-j-1)];
|
||||||
|
|
||||||
|
if (![encoding length])
|
||||||
|
encoding = @"base64";
|
||||||
|
|
||||||
|
data = [[value substringFromIndex: k+1] dataUsingEncoding: NSASCIIStringEncoding];
|
||||||
|
|
||||||
|
uniqueId = [SOGoObject globallyUniqueObjectId];
|
||||||
|
|
||||||
|
map = [[[NGMutableHashMap alloc] initWithCapacity:5] autorelease];
|
||||||
|
[map setObject: encoding forKey: @"content-transfer-encoding"];
|
||||||
|
[map setObject:[NSNumber numberWithInt:[data length]] forKey: @"content-length"];
|
||||||
|
[map setObject: [NSString stringWithFormat: @"inline; filename=\"%@\"", uniqueId] forKey: @"content-disposition"];
|
||||||
|
[map setObject: [NSString stringWithFormat: @"%@; name=\"%@\"", mimeType, uniqueId] forKey: @"content-type"];
|
||||||
|
[map setObject: [NSString stringWithFormat: @"<%@>", uniqueId] forKey: @"content-id"];
|
||||||
|
|
||||||
|
|
||||||
|
body = [[NGMimeFileData alloc] initWithBytes: [data bytes] length: [data length]];
|
||||||
|
|
||||||
|
bodyPart = [[[NGMimeBodyPart alloc] initWithHeader:map] autorelease];
|
||||||
|
[bodyPart setBody: body];
|
||||||
|
[body release];
|
||||||
|
|
||||||
|
[images addObject: bodyPart];
|
||||||
|
|
||||||
|
[result appendFormat: @"<img src=\"cid:%@\" type=\"%@\">", uniqueId, mimeType];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) endElement: (NSString *) element
|
- (void) endElement: (NSString *) element
|
||||||
|
@ -228,7 +352,7 @@
|
||||||
|
|
||||||
showWhoWeAre();
|
showWhoWeAre();
|
||||||
|
|
||||||
if (ignoreContent)
|
if (ignoreContent && ignoreContentTags && specialTreatmentTags)
|
||||||
{
|
{
|
||||||
tagName = [rawName lowercaseString];
|
tagName = [rawName lowercaseString];
|
||||||
if ([ignoreContentTags containsObject: tagName])
|
if ([ignoreContentTags containsObject: tagName])
|
||||||
|
@ -345,13 +469,13 @@
|
||||||
|
|
||||||
- (NSString *) htmlToText
|
- (NSString *) htmlToText
|
||||||
{
|
{
|
||||||
_SOGoHTMLToTextContentHandler *handler;
|
_SOGoHTMLContentHandler *handler;
|
||||||
id <NSObject, SaxXMLReader> parser;
|
id <NSObject, SaxXMLReader> parser;
|
||||||
NSData *d;
|
NSData *d;
|
||||||
|
|
||||||
parser = [[SaxXMLReaderFactory standardXMLReaderFactory]
|
parser = [[SaxXMLReaderFactory standardXMLReaderFactory]
|
||||||
createXMLReaderForMimeType: @"text/html"];
|
createXMLReaderForMimeType: @"text/html"];
|
||||||
handler = [_SOGoHTMLToTextContentHandler htmlToTextContentHandler];
|
handler = [_SOGoHTMLContentHandler htmlToTextContentHandler];
|
||||||
[parser setContentHandler: handler];
|
[parser setContentHandler: handler];
|
||||||
|
|
||||||
d = [self dataUsingEncoding: NSUTF8StringEncoding];
|
d = [self dataUsingEncoding: NSUTF8StringEncoding];
|
||||||
|
@ -360,7 +484,24 @@
|
||||||
return [handler result];
|
return [handler result];
|
||||||
}
|
}
|
||||||
|
|
||||||
#define paddingBuffer 8192
|
- (NSString *) htmlByExtractingImages: (NSMutableArray *) theImages
|
||||||
|
{
|
||||||
|
_SOGoHTMLContentHandler *handler;
|
||||||
|
id <NSObject, SaxXMLReader> parser;
|
||||||
|
NSData *d;
|
||||||
|
|
||||||
|
parser = [[SaxXMLReaderFactory standardXMLReaderFactory]
|
||||||
|
createXMLReaderForMimeType: @"text/html"];
|
||||||
|
handler = [_SOGoHTMLContentHandler sanitizerContentHandler];
|
||||||
|
[handler setImages: theImages];
|
||||||
|
|
||||||
|
[parser setContentHandler: handler];
|
||||||
|
|
||||||
|
d = [self dataUsingEncoding: NSUTF8StringEncoding];
|
||||||
|
[parser parseFromSource: d];
|
||||||
|
|
||||||
|
return [handler result];
|
||||||
|
}
|
||||||
|
|
||||||
static inline char *
|
static inline char *
|
||||||
convertChars (const char *oldString, unsigned int oldLength,
|
convertChars (const char *oldString, unsigned int oldLength,
|
||||||
|
@ -434,18 +575,29 @@ convertChars (const char *oldString, unsigned int oldLength,
|
||||||
return convertedString;
|
return convertedString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (int) indexOf: (unichar) _c
|
- (int) indexOf: (unichar) _c
|
||||||
|
fromIndex: (int) start
|
||||||
{
|
{
|
||||||
int i, len;
|
int i, len;
|
||||||
|
|
||||||
len = [self length];
|
len = [self length];
|
||||||
|
|
||||||
for (i = 0; i < len; i++)
|
if (start < 0 || start >= len)
|
||||||
|
start = 0;
|
||||||
|
|
||||||
|
for (i = start; i < len; i++)
|
||||||
{
|
{
|
||||||
if ([self characterAtIndex: i] == _c) return i;
|
if ([self characterAtIndex: i] == _c) return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) indexOf: (unichar) _c
|
||||||
|
{
|
||||||
|
return [self indexOf: _c fromIndex: 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *) decodedHeader
|
- (NSString *) decodedHeader
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2007-2012 Inverse inc.
|
Copyright (C) 2007-2013 Inverse inc.
|
||||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||||
|
|
||||||
This file is part of SOGo.
|
This file is part of SOGo.
|
||||||
|
@ -395,11 +395,17 @@ static NSString *userAgent = nil;
|
||||||
[self setSourceFolder: [paths componentsJoinedByString: @"/"]];
|
[self setSourceFolder: [paths componentsJoinedByString: @"/"]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSString *) sourceFolder
|
- (NSString *) sourceFolder
|
||||||
{
|
{
|
||||||
return sourceFolder;
|
return sourceFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSException *) storeInfo
|
- (NSException *) storeInfo
|
||||||
{
|
{
|
||||||
NSMutableDictionary *infos;
|
NSMutableDictionary *infos;
|
||||||
|
@ -446,6 +452,9 @@ static NSString *userAgent = nil;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (void) _loadInfosFromDictionary: (NSDictionary *) infoDict
|
- (void) _loadInfosFromDictionary: (NSDictionary *) infoDict
|
||||||
{
|
{
|
||||||
id value;
|
id value;
|
||||||
|
@ -478,11 +487,17 @@ static NSString *userAgent = nil;
|
||||||
[self setInReplyTo: value];
|
[self setInReplyTo: value];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSString *) relativeImap4Name
|
- (NSString *) relativeImap4Name
|
||||||
{
|
{
|
||||||
return [NSString stringWithFormat: @"%d", IMAP4ID];
|
return [NSString stringWithFormat: @"%d", IMAP4ID];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (void) fetchInfo
|
- (void) fetchInfo
|
||||||
{
|
{
|
||||||
NSString *p;
|
NSString *p;
|
||||||
|
@ -504,16 +519,25 @@ static NSString *userAgent = nil;
|
||||||
[self debugWithFormat: @"Note: info object does not yet exist: %@", p];
|
[self debugWithFormat: @"Note: info object does not yet exist: %@", p];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (void) setIMAP4ID: (int) newIMAP4ID
|
- (void) setIMAP4ID: (int) newIMAP4ID
|
||||||
{
|
{
|
||||||
IMAP4ID = newIMAP4ID;
|
IMAP4ID = newIMAP4ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (int) IMAP4ID
|
- (int) IMAP4ID
|
||||||
{
|
{
|
||||||
return IMAP4ID;
|
return IMAP4ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSException *) save
|
- (NSException *) save
|
||||||
{
|
{
|
||||||
NGImap4Client *client;
|
NGImap4Client *client;
|
||||||
|
@ -552,6 +576,9 @@ static NSString *userAgent = nil;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (void) _addEMailsOfAddresses: (NSArray *) _addrs
|
- (void) _addEMailsOfAddresses: (NSArray *) _addrs
|
||||||
toArray: (NSMutableArray *) _ma
|
toArray: (NSMutableArray *) _ma
|
||||||
{
|
{
|
||||||
|
@ -564,6 +591,9 @@ static NSString *userAgent = nil;
|
||||||
[_ma addObject: [currentAddress email]];
|
[_ma addObject: [currentAddress email]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (void) _addRecipients: (NSArray *) recipients
|
- (void) _addRecipients: (NSArray *) recipients
|
||||||
toArray: (NSMutableArray *) array
|
toArray: (NSMutableArray *) array
|
||||||
{
|
{
|
||||||
|
@ -576,6 +606,9 @@ static NSString *userAgent = nil;
|
||||||
[array addObject: [currentAddress baseEMail]];
|
[array addObject: [currentAddress baseEMail]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (void) _purgeRecipients: (NSArray *) recipients
|
- (void) _purgeRecipients: (NSArray *) recipients
|
||||||
fromAddresses: (NSMutableArray *) addresses
|
fromAddresses: (NSMutableArray *) addresses
|
||||||
{
|
{
|
||||||
|
@ -602,6 +635,9 @@ static NSString *userAgent = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (void) _fillInReplyAddresses: (NSMutableDictionary *) _info
|
- (void) _fillInReplyAddresses: (NSMutableDictionary *) _info
|
||||||
replyToAll: (BOOL) _replyToAll
|
replyToAll: (BOOL) _replyToAll
|
||||||
envelope: (NGImap4Envelope *) _envelope
|
envelope: (NGImap4Envelope *) _envelope
|
||||||
|
@ -711,6 +747,9 @@ static NSString *userAgent = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSArray *) _attachmentBodiesFromPaths: (NSArray *) paths
|
- (NSArray *) _attachmentBodiesFromPaths: (NSArray *) paths
|
||||||
fromResponseFetch: (NSDictionary *) fetch;
|
fromResponseFetch: (NSDictionary *) fetch;
|
||||||
{
|
{
|
||||||
|
@ -731,6 +770,9 @@ static NSString *userAgent = nil;
|
||||||
return bodies;
|
return bodies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (void) _fetchAttachments: (NSArray *) parts
|
- (void) _fetchAttachments: (NSArray *) parts
|
||||||
fromMail: (SOGoMailObject *) sourceMail
|
fromMail: (SOGoMailObject *) sourceMail
|
||||||
{
|
{
|
||||||
|
@ -758,6 +800,9 @@ static NSString *userAgent = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (void) fetchMailForEditing: (SOGoMailObject *) sourceMail
|
- (void) fetchMailForEditing: (SOGoMailObject *) sourceMail
|
||||||
{
|
{
|
||||||
NSString *subject, *msgid;
|
NSString *subject, *msgid;
|
||||||
|
@ -804,6 +849,9 @@ static NSString *userAgent = nil;
|
||||||
[self storeInfo];
|
[self storeInfo];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (void) fetchMailForReplying: (SOGoMailObject *) sourceMail
|
- (void) fetchMailForReplying: (SOGoMailObject *) sourceMail
|
||||||
toAll: (BOOL) toAll
|
toAll: (BOOL) toAll
|
||||||
{
|
{
|
||||||
|
@ -1255,6 +1303,9 @@ static NSString *userAgent = nil;
|
||||||
return bodyPart;
|
return bodyPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSArray *) bodyPartsForAllAttachments
|
- (NSArray *) bodyPartsForAllAttachments
|
||||||
{
|
{
|
||||||
/* returns nil on error */
|
/* returns nil on error */
|
||||||
|
@ -1276,6 +1327,9 @@ static NSString *userAgent = nil;
|
||||||
return bodyParts;
|
return bodyParts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NGMimeBodyPart *) mimeMultipartAlternative
|
- (NGMimeBodyPart *) mimeMultipartAlternative
|
||||||
{
|
{
|
||||||
NGMimeMultipartBody *textParts;
|
NGMimeMultipartBody *textParts;
|
||||||
|
@ -1301,6 +1355,9 @@ static NSString *userAgent = nil;
|
||||||
return part;
|
return part;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NGMimeMessage *) mimeMultiPartMessageWithHeaderMap: (NGMutableHashMap *) map
|
- (NGMimeMessage *) mimeMultiPartMessageWithHeaderMap: (NGMutableHashMap *) map
|
||||||
andBodyParts: (NSArray *) _bodyParts
|
andBodyParts: (NSArray *) _bodyParts
|
||||||
{
|
{
|
||||||
|
@ -1340,6 +1397,9 @@ static NSString *userAgent = nil;
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (void) _addHeaders: (NSDictionary *) _h
|
- (void) _addHeaders: (NSDictionary *) _h
|
||||||
toHeaderMap: (NGMutableHashMap *) _map
|
toHeaderMap: (NGMutableHashMap *) _map
|
||||||
{
|
{
|
||||||
|
@ -1511,48 +1571,59 @@ static NSString *userAgent = nil;
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NGMimeMessage *) mimeMessageWithHeaders: (NSDictionary *) _headers
|
- (NGMimeMessage *) mimeMessageWithHeaders: (NSDictionary *) _headers
|
||||||
excluding: (NSArray *) _exclude
|
excluding: (NSArray *) _exclude
|
||||||
{
|
{
|
||||||
NGMutableHashMap *map;
|
NSMutableArray *bodyParts;
|
||||||
NSArray *bodyParts;
|
NGMimeMessage *message;
|
||||||
NGMimeMessage *message;
|
NGMutableHashMap *map;
|
||||||
|
NSString *newText;
|
||||||
|
|
||||||
message = nil;
|
message = nil;
|
||||||
|
|
||||||
|
bodyParts = [NSMutableArray array];
|
||||||
|
newText = [text htmlByExtractingImages: bodyParts];
|
||||||
|
|
||||||
|
if ([bodyParts count])
|
||||||
|
[self setText: newText];
|
||||||
|
|
||||||
map = [self mimeHeaderMapWithHeaders: _headers
|
map = [self mimeHeaderMapWithHeaders: _headers
|
||||||
excluding: _exclude];
|
excluding: _exclude];
|
||||||
if (map)
|
if (map)
|
||||||
{
|
{
|
||||||
//[self debugWithFormat: @"MIME Envelope: %@", map];
|
//[self debugWithFormat: @"MIME Envelope: %@", map];
|
||||||
|
|
||||||
bodyParts = [self bodyPartsForAllAttachments];
|
[bodyParts addObjectsFromArray: [self bodyPartsForAllAttachments]];
|
||||||
if (bodyParts)
|
|
||||||
{
|
|
||||||
//[self debugWithFormat: @"attachments: %@", bodyParts];
|
|
||||||
|
|
||||||
if ([bodyParts count] == 0)
|
//[self debugWithFormat: @"attachments: %@", bodyParts];
|
||||||
/* no attachments */
|
|
||||||
message = [self mimeMessageForContentWithHeaderMap: map];
|
if ([bodyParts count] == 0)
|
||||||
else
|
/* no attachments */
|
||||||
/* attachments, create multipart/mixed */
|
message = [self mimeMessageForContentWithHeaderMap: map];
|
||||||
message = [self mimeMultiPartMessageWithHeaderMap: map
|
|
||||||
andBodyParts: bodyParts];
|
|
||||||
//[self debugWithFormat: @"message: %@", message];
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
[self errorWithFormat:
|
/* attachments, create multipart/mixed */
|
||||||
@"could not create body parts for attachments!"];
|
message = [self mimeMultiPartMessageWithHeaderMap: map
|
||||||
|
andBodyParts: bodyParts];
|
||||||
|
//[self debugWithFormat: @"message: %@", message];
|
||||||
}
|
}
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NGMimeMessage *) mimeMessage
|
- (NGMimeMessage *) mimeMessage
|
||||||
{
|
{
|
||||||
return [self mimeMessageWithHeaders: nil excluding: nil];
|
return [self mimeMessageWithHeaders: nil excluding: nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSData *) mimeMessageAsData
|
- (NSData *) mimeMessageAsData
|
||||||
{
|
{
|
||||||
NGMimeMessageGenerator *generator;
|
NGMimeMessageGenerator *generator;
|
||||||
|
@ -1565,6 +1636,9 @@ static NSString *userAgent = nil;
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSArray *) allRecipients
|
- (NSArray *) allRecipients
|
||||||
{
|
{
|
||||||
NSMutableArray *allRecipients;
|
NSMutableArray *allRecipients;
|
||||||
|
@ -1584,6 +1658,9 @@ static NSString *userAgent = nil;
|
||||||
return allRecipients;
|
return allRecipients;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSArray *) allBareRecipients
|
- (NSArray *) allBareRecipients
|
||||||
{
|
{
|
||||||
NSMutableArray *bareRecipients;
|
NSMutableArray *bareRecipients;
|
||||||
|
@ -1599,11 +1676,17 @@ static NSString *userAgent = nil;
|
||||||
return bareRecipients;
|
return bareRecipients;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSException *) sendMail
|
- (NSException *) sendMail
|
||||||
{
|
{
|
||||||
return [self sendMailAndCopyToSent: YES];
|
return [self sendMailAndCopyToSent: YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSException *) sendMailAndCopyToSent: (BOOL) copyToSent
|
- (NSException *) sendMailAndCopyToSent: (BOOL) copyToSent
|
||||||
{
|
{
|
||||||
NSMutableData *cleaned_message;
|
NSMutableData *cleaned_message;
|
||||||
|
|
|
@ -42,6 +42,9 @@
|
||||||
|
|
||||||
#define maxFilenameLength 64
|
#define maxFilenameLength 64
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
@implementation SOGoMailObject (SOGoDraftObjectExtensions)
|
@implementation SOGoMailObject (SOGoDraftObjectExtensions)
|
||||||
|
|
||||||
- (NSString *) subjectForReply
|
- (NSString *) subjectForReply
|
||||||
|
@ -77,6 +80,9 @@
|
||||||
return newSubject;
|
return newSubject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSString *) _convertRawContentForEditing: (NSString *) raw
|
- (NSString *) _convertRawContentForEditing: (NSString *) raw
|
||||||
rawHtml: (BOOL) html
|
rawHtml: (BOOL) html
|
||||||
{
|
{
|
||||||
|
@ -96,6 +102,9 @@
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSString *) _contentForEditingFromKeys: (NSArray *) keys
|
- (NSString *) _contentForEditingFromKeys: (NSArray *) keys
|
||||||
{
|
{
|
||||||
NSArray *types;
|
NSArray *types;
|
||||||
|
@ -151,6 +160,9 @@
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSString *) contentForEditing
|
- (NSString *) contentForEditing
|
||||||
{
|
{
|
||||||
NSMutableArray *keys;
|
NSMutableArray *keys;
|
||||||
|
@ -166,6 +178,9 @@
|
||||||
return [self _contentForEditingFromKeys: keys];
|
return [self _contentForEditingFromKeys: keys];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSString *) contentForReply
|
- (NSString *) contentForReply
|
||||||
{
|
{
|
||||||
NSString *pageName;
|
NSString *pageName;
|
||||||
|
@ -185,6 +200,9 @@
|
||||||
return [[page generateResponse] contentAsString];
|
return [[page generateResponse] contentAsString];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSString *) filenameForForward
|
- (NSString *) filenameForForward
|
||||||
{
|
{
|
||||||
NSString *subject;
|
NSString *subject;
|
||||||
|
@ -218,6 +236,9 @@
|
||||||
return newSubject;
|
return newSubject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSString *) subjectForForward
|
- (NSString *) subjectForForward
|
||||||
{
|
{
|
||||||
NSString *subject, *newSubject;
|
NSString *subject, *newSubject;
|
||||||
|
@ -231,6 +252,9 @@
|
||||||
return newSubject;
|
return newSubject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (NSString *) contentForInlineForward
|
- (NSString *) contentForInlineForward
|
||||||
{
|
{
|
||||||
SOGoUserDefaults *ud;
|
SOGoUserDefaults *ud;
|
||||||
|
@ -247,6 +271,9 @@
|
||||||
return [[page generateResponse] contentAsString];
|
return [[page generateResponse] contentAsString];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (void) _fetchFileAttachmentKey: (NSDictionary *) part
|
- (void) _fetchFileAttachmentKey: (NSDictionary *) part
|
||||||
intoArray: (NSMutableArray *) keys
|
intoArray: (NSMutableArray *) keys
|
||||||
withPath: (NSString *) path
|
withPath: (NSString *) path
|
||||||
|
@ -291,6 +318,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
- (void) _fetchFileAttachmentKeysInPart: (NSDictionary *) part
|
- (void) _fetchFileAttachmentKeysInPart: (NSDictionary *) part
|
||||||
intoArray: (NSMutableArray *) keys
|
intoArray: (NSMutableArray *) keys
|
||||||
withPath: (NSString *) path
|
withPath: (NSString *) path
|
||||||
|
@ -325,6 +355,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
#warning we might need to handle parts with a "name" attribute
|
#warning we might need to handle parts with a "name" attribute
|
||||||
- (NSArray *) fetchFileAttachmentKeys
|
- (NSArray *) fetchFileAttachmentKeys
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
/* UIxMailPartHTMLViewer.h - this file is part of SOGo
|
/* UIxMailPartHTMLViewer.h - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007, 2008 Inverse inc.
|
* Copyright (C) 2007-2013 Inverse inc.
|
||||||
*
|
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
|
||||||
*
|
*
|
||||||
* This file is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
/* UIxMailPartHTMLViewer.m - this file is part of SOGo
|
/* UIxMailPartHTMLViewer.m - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2012 Inverse inc.
|
* Copyright (C) 2007-2013 Inverse inc.
|
||||||
*
|
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
|
||||||
* Ludovic Marcotte <lmarcotte@inverse.ca>
|
|
||||||
* Francis Lachapelle <flachapelle@inverse.ca>
|
|
||||||
*
|
*
|
||||||
* This file is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
Loading…
Reference in New Issue