mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-05-01 01:39:30 +00:00
(fix) remaining S/MIME fixes to handle image/CIDs in HTML mails
This commit is contained in:
@@ -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]];
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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]];
|
||||
}
|
||||
|
||||
|
||||
@@ -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]];
|
||||
}
|
||||
|
||||
|
||||
@@ -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]] ||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user