(fix) remaining S/MIME fixes to handle image/CIDs in HTML mails

This commit is contained in:
Ludovic Marcotte
2018-01-23 10:35:46 -05:00
parent 341e5cbab0
commit 511aa63a34
13 changed files with 221 additions and 92 deletions

View File

@@ -1,5 +1,5 @@
/*
Copyright (C) 2007-2017 Inverse inc.
Copyright (C) 2007-2018 Inverse inc.
Copyright (C) 2004 SKYRIX Software AG
This file is part of SOGo.
@@ -23,8 +23,11 @@
#import <Foundation/NSDictionary.h>
#import <Foundation/NSNull.h>
#import <SOGo/NSObject+Utilities.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGMail/NGMimeMessageParser.h>
#import <NGMime/NGMimeBodyPart.h>
#import <NGMime/NGMimeMultipartBody.h>
#import <NGMime/NGMimeType.h>
@@ -65,20 +68,20 @@
NSUInteger i, count;
if ([[self decodedFlatContent] isKindOfClass: [NGMimeMultipartBody class]])
if ([self decodedFlatContent])
childParts = [[self decodedFlatContent] parts];
else
childParts = [[self bodyInfo] valueForKey:@"parts"];
childParts = [[self bodyInfo] valueForKey: @"parts"];
count = [childParts count];
types = [NSMutableArray arrayWithCapacity: count];
for (i = 0; i < count; i++)
{
if ([[self decodedFlatContent] isKindOfClass: [NGMimeMultipartBody class]])
if ([self decodedFlatContent])
{
mt = [[[[[self decodedFlatContent] parts] objectAtIndex: i] contentType] type];
st = [[[[[self decodedFlatContent] parts] objectAtIndex: i] contentType] subType];
mt = [[[childParts objectAtIndex: i] contentType] type];
st = [[[childParts objectAtIndex: i] contentType] subType];
}
else
{
@@ -141,20 +144,19 @@
{
NSUInteger idx;
[childInfo release]; childInfo = nil;
DESTROY(childInfo);
childIndex = 0;
idx = [self _selectPartIndexFromTypes: [self childPartTypes]];
if (idx == NSNotFound)
{
[self errorWithFormat:@"could not select a part of types: %@",
[self childPartTypes]];
[self errorWithFormat:@"could not select a part of types: %@", [self childPartTypes]];
return;
}
childIndex = idx + 1;
if ([[self decodedFlatContent] isKindOfClass: [NGMimeMultipartBody class]])
if ([self decodedFlatContent])
childInfo = [[[[self decodedFlatContent] parts] objectAtIndex: idx] bodyInfo];
else
childInfo = [[[self bodyInfo] valueForKey:@"parts"] objectAtIndex: idx];
@@ -172,17 +174,18 @@
return [[[self context] mailRenderingContext] viewerForBodyInfo: info];
}
- (id) renderedPart {
- (id) renderedPart
{
id info, viewer;
NSArray *parts;
NSMutableArray *renderedParts;
NSString *preferredType;
NSUInteger i, max;
if ([[self decodedFlatContent] isKindOfClass: [NGMimeMultipartBody class]])
if ([self decodedFlatContent])
parts = [[self decodedFlatContent] parts];
else
parts = [[self bodyInfo] valueForKey:@"parts"];
parts = [[self bodyInfo] valueForKey: @"parts"];
max = [parts count];
renderedParts = [NSMutableArray arrayWithCapacity: max];
@@ -190,7 +193,7 @@
{
[self setChildIndex: i];
if ([[self decodedFlatContent] isKindOfClass: [NGMimeMultipartBody class]])
if ([self decodedFlatContent])
[self setChildInfo: [[parts objectAtIndex: i] bodyInfo]];
else
[self setChildInfo: [parts objectAtIndex: i]];
@@ -200,7 +203,7 @@
[viewer setBodyInfo: info];
[viewer setPartPath: [self childPartPath]];
[viewer setAttachmentIds: attachmentIds];
if ([[self decodedFlatContent] isKindOfClass: [NGMimeMultipartBody class]])
if ([self decodedFlatContent])
[viewer setDecodedContent: [parts objectAtIndex: i]];
[renderedParts addObject: [viewer renderedPart]];
}

View File

@@ -1,5 +1,5 @@
/*
Copyright (C) 2017 Inverse inc.
Copyright (C) 2017-2018 Inverse inc.
This file is part of SOGo.
@@ -21,12 +21,17 @@
#import <Foundation/NSDictionary.h>
#import <Foundation/NSNull.h>
#import <Foundation/NSValue.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGMail/NGMimeMessageParser.h>
#import <NGMime/NGMimeBodyPart.h>
#import <NGMime/NGMimeHeaderFields.h>
#import <NGMime/NGMimeMultipartBody.h>
#import <NGMime/NGMimeType.h>
#import <NGMail/NGMimeMessageParser.h>
#import <SoObjects/Mailer/NSData+SMIME.h>
#import <SoObjects/Mailer/NSString+Mail.h>
#import <SoObjects/Mailer/SOGoMailAccount.h>
#import <SoObjects/Mailer/SOGoMailObject.h>
#import <UI/MailerUI/WOContext+UIxMailer.h>
@@ -36,7 +41,45 @@
@implementation UIxMailPartEncryptedViewer
/* nested viewers */
- (void) _attachmentIdsFromBodyPart: (id) thePart
partPath: (NSString *) thePartPath
{
// Small hack to avoid SOPE's stupid behavior to wrap a multipart
// object in a NGMimeBodyPart.
if ([thePart isKindOfClass: [NGMimeBodyPart class]] &&
[[[thePart contentType] type] isEqualToString: @"multipart"])
thePart = [thePart body];
if ([thePart isKindOfClass: [NGMimeBodyPart class]])
{
NSString *filename, *mimeType;
mimeType = [[thePart contentType] stringValue];
filename = [(NGMimeContentDispositionHeaderField *)[thePart headerForKey: @"content-disposition"] filename];
if (!filename)
filename = [mimeType asPreferredFilenameUsingPath: nil];
if (filename)
{
[(id)attachmentIds setObject: [NSString stringWithFormat: @"%@%@%@",
[[self clientObject] baseURLInContext: [self context]],
thePartPath,
filename]
forKey: [NSString stringWithFormat: @"<%@>", filename]];
}
}
else if ([thePart isKindOfClass: [NGMimeMultipartBody class]])
{
int i;
for (i = 0; i < [[thePart parts] count]; i++)
{
[self _attachmentIdsFromBodyPart: [[thePart parts] objectAtIndex: i]
partPath: [NSString stringWithFormat: @"%@%d/", thePartPath, i+1]];
}
}
}
- (id) contentViewerComponent
{
@@ -49,7 +92,6 @@
- (id) renderedPart
{
NSData *certificate, *decryptedData, *encryptedData;
id info, viewer;
certificate = [[[self clientObject] mailAccountFolder] certificate];
@@ -71,16 +113,25 @@
[viewer setFlatContent: decryptedData];
[viewer setDecodedContent: [part body]];
// attachmentIds is empty in an ecrypted email as the IMAP body structure
// is of course not available for file attachments
[self _attachmentIdsFromBodyPart: [part body] partPath: @""];
[viewer setAttachmentIds: attachmentIds];
return [NSDictionary dictionaryWithObjectsAndKeys:
[self className], @"type",
[NSNumber numberWithBool: YES], @"valid",
[NSArray arrayWithObject: [viewer renderedPart]], @"content",
nil];
}
// Decryption failed, let's return something else...
// FIXME - does not work for now.
return nil;
return [NSDictionary dictionaryWithObjectsAndKeys:
[self className], @"type",
[NSNumber numberWithBool: NO], @"valid",
[NSArray array], @"content",
nil];
}
@end /* UIxMailPartAlternativeViewer */

View File

@@ -1,6 +1,5 @@
/*
Copyright (C) 2007-2017 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
Copyright (C) 2007-2018 Inverse inc.
This file is part of SOGo

View File

@@ -22,6 +22,9 @@
#import <Foundation/NSDictionary.h>
#import <SOGo/NSObject+Utilities.h>
#import <NGMime/NGMimeBodyPart.h>
#import <NGMime/NGMimeMultipartBody.h>
#import <UI/MailerUI/WOContext+UIxMailer.h>
@@ -31,24 +34,25 @@
@implementation UIxMailPartMixedViewer
- (void)dealloc {
- (void) dealloc
{
[self->childInfo release];
[super dealloc];
}
/* caches */
- (void)resetBodyInfoCaches {
[self->childInfo release]; self->childInfo = nil;
- (void)resetBodyInfoCaches
{
DESTROY(self->childInfo);
[super resetBodyInfoCaches];
}
/* accessors */
- (void)setChildInfo:(id)_info {
- (void) setChildInfo:(id)_info
{
ASSIGN(self->childInfo, _info);
}
- (id)childInfo {
- (id) childInfo
{
return self->childInfo;
}
@@ -56,6 +60,7 @@
{
self->childIndex = _index;
}
- (NSUInteger) childIndex
{
return self->childIndex;
@@ -67,7 +72,7 @@
(unsigned int) ([self childIndex] + 1)];
}
- (id)childPartPath
- (id) childPartPath
{
NSArray *pp;
@@ -96,7 +101,7 @@
NSUInteger i, max;
if ([[self decodedFlatContent] isKindOfClass: [NGMimeMultipartBody class]])
if ([self decodedFlatContent])
parts = [[self decodedFlatContent] parts];
else
parts = [[self bodyInfo] valueForKey: @"parts"];
@@ -108,7 +113,7 @@
{
[self setChildIndex: i];
if ([[self decodedFlatContent] isKindOfClass: [NGMimeMultipartBody class]])
if ([self decodedFlatContent])
[self setChildInfo: [[parts objectAtIndex: i] bodyInfo]];
else
[self setChildInfo: [parts objectAtIndex: i]];
@@ -117,9 +122,10 @@
viewer = [[[self context] mailRenderingContext] viewerForBodyInfo: info];
[viewer setBodyInfo: info];
[viewer setPartPath: [self childPartPath]];
[viewer setAttachmentIds: attachmentIds];
if ([[self decodedFlatContent] isKindOfClass: [NGMimeMultipartBody class]])
if ([self decodedFlatContent])
[viewer setDecodedContent: [parts objectAtIndex: i]];
[viewer setAttachmentIds: attachmentIds];
[renderedParts addObject: [viewer renderedPart]];
}

View File

@@ -247,7 +247,7 @@
NSUInteger i, max;
if ([[self decodedFlatContent] isKindOfClass: [NGMimeMultipartBody class]])
if ([self decodedFlatContent])
parts = [[self decodedFlatContent] parts];
else
parts = [[self bodyInfo] objectForKey: @"parts"];
@@ -259,7 +259,7 @@
{
[self setChildIndex: i];
if ([[self decodedFlatContent] isKindOfClass: [NGMimeMultipartBody class]])
if ([self decodedFlatContent])
[self setChildInfo: [[parts objectAtIndex: i] bodyInfo]];
else
[self setChildInfo: [parts objectAtIndex: i]];
@@ -268,10 +268,11 @@
viewer = [[[self context] mailRenderingContext] viewerForBodyInfo: info];
[viewer setBodyInfo: info];
[viewer setPartPath: [self childPartPath]];
[viewer setAttachmentIds: attachmentIds];
if ([[self decodedFlatContent] isKindOfClass: [NGMimeMultipartBody class]])
if ([self decodedFlatContent])
[viewer setDecodedContent: [[parts objectAtIndex: i] body]];
[viewer setAttachmentIds: attachmentIds];
[renderedParts addObject: [viewer renderedPart]];
}

View File

@@ -214,8 +214,7 @@
// but rather directly with NGMime objects.
if ([content isKindOfClass: [NSData class]])
{
charset = [[bodyInfo objectForKey:@"parameterList"]
objectForKey: @"charset"];
charset = [[bodyInfo objectForKey: @"parameterList"] objectForKey: @"charset"];
s = [content bodyStringFromCharset: charset];
}
else if ([content isKindOfClass: [NGMimeBodyPart class]] ||

View File

@@ -203,7 +203,7 @@ static BOOL showNamedTextAttachmentsInline = NO;
else if ([mt isEqualToString: @"text"])
{
if ([st isEqualToString: @"plain"] || [st isEqualToString: @"html"]) {
if (!showNamedTextAttachmentsInline && [self _shouldDisplayAsAttachment: _info textPart:YES])
if (!showNamedTextAttachmentsInline && [self _shouldDisplayAsAttachment: _info textPart: YES])
return [self linkViewer];
return [st isEqualToString: @"html"]
@@ -219,7 +219,7 @@ static BOOL showNamedTextAttachmentsInline = NO;
if ([mt isEqualToString: @"image"] &&
!([st isEqualToString: @"tiff"] || [st isEqualToString: @"pdf"]))
{
if ([self _shouldDisplayAsAttachment: _info textPart: NO])
if ([self _shouldDisplayAsAttachment: _info textPart: NO])
return [self linkViewer];
return [self imageViewer];

View File

@@ -2,8 +2,6 @@
*
* Copyright (C) 2006 Inverse inc.
*
* 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)

View File

@@ -226,19 +226,26 @@ static NSString *mailETag = nil;
viewer = [[context mailRenderingContext] viewerForBodyInfo: info];
[viewer setBodyInfo: info];
max = [[self attachmentAttrs] count];
attachmentIds = [NSMutableDictionary dictionaryWithCapacity: max];
for (count = 0; count < max; count++)
if (![[self clientObject] isEncrypted])
{
attributes = [[self attachmentAttrs] objectAtIndex: count];
filename = [NSString stringWithFormat: @"<%@>", [attributes objectForKey: @"filename"]];
[attachmentIds setObject: [attributes objectForKey: @"url"]
forKey: filename];
if ([[attributes objectForKey: @"bodyId"] length])
[attachmentIds setObject: [attributes objectForKey: @"url"]
forKey: [attributes objectForKey: @"bodyId"]];
max = [[self attachmentAttrs] count];
attachmentIds = [NSMutableDictionary dictionaryWithCapacity: max];
for (count = 0; count < max; count++)
{
attributes = [[self attachmentAttrs] objectAtIndex: count];
filename = [NSString stringWithFormat: @"<%@>", [attributes objectForKey: @"filename"]];
[attachmentIds setObject: [attributes objectForKey: @"url"]
forKey: filename];
if ([[attributes objectForKey: @"bodyId"] length])
[attachmentIds setObject: [attributes objectForKey: @"url"]
forKey: [attributes objectForKey: @"bodyId"]];
}
// Attachment IDs will be decoded in UIxMailPartEncryptedViewer for
// S/MIME encrypted emails with file attachments.
[viewer setAttachmentIds: attachmentIds];
}
[viewer setAttachmentIds: attachmentIds];
else
[viewer setAttachmentIds: [NSMutableDictionary dictionary]];
// If we are looking at a S/MIME signed mail which wasn't sent
// by our actual active user, we update the certificate of that
@@ -327,7 +334,7 @@ static NSString *mailETag = nil;
data = [NSDictionary dictionaryWithObject: [self labelForKey: @"Did not find specified message"]
forKey: @"message"];
return [self responseWithStatus: 404 /* Not Found */
andJSONRepresentation: data];
andJSONRepresentation: data];
}
data = [NSMutableDictionary dictionaryWithObjectsAndKeys: