mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-07-06 00:45:09 +00:00
merge of '0a3d8971fb4a3b2c5dfbe3f501204e4f46f3ce96'
and '411e18da9b8303cd9a4927e92d807baf5025523f' Monotone-Parent: 0a3d8971fb4a3b2c5dfbe3f501204e4f46f3ce96 Monotone-Parent: 411e18da9b8303cd9a4927e92d807baf5025523f Monotone-Revision: b8739c38c2f4892f1fb2d687073e8cd5538e75f8 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2007-10-25T19:22:23 Monotone-Branch: ca.inverse.sogo
This commit is contained in:
@@ -1,3 +1,27 @@
|
||||
2007-10-25 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* SoObjects/Mailer/NSData+Mail.m ([NSData
|
||||
-bodyDataFromEncoding:encoding]): new utility method that decodes
|
||||
the NSData instance properly depending on the encoding string
|
||||
passed as parameter.
|
||||
|
||||
* SoObjects/Mailer/SOGoMailObject+Draft.m ([SOGoMailObject
|
||||
-fetchFileAttachmentKeys]): fetch the attachment encoding as well.
|
||||
|
||||
* SoObjects/Mailer/SOGoMailObject.m ([SOGoMailObject
|
||||
-stringForData:_datapartInfo:_info]): simplified by invoking
|
||||
-bodyDataFromEncoding: from our new NSData category methods.
|
||||
|
||||
* SoObjects/Mailer/SOGoDraftObject.m ([SOGoDraftObject
|
||||
-fetchMailForEditing:sourceMail]): work-around a bug in SOPE-mime
|
||||
where only the body part of the first of the keys fetched was
|
||||
returned. Also decodes the body parts properly following their
|
||||
encoding.
|
||||
|
||||
* SoObjects/Mailer/NSData+Mail.[hm]: new extension module that
|
||||
extends the NSData class with utility methods useful for handling
|
||||
mail.
|
||||
|
||||
2007-10-23 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* SoObjects/SOGo/NSArray+Utilities.m
|
||||
|
||||
@@ -30,7 +30,9 @@ Mailer_OBJC_FILES += \
|
||||
SOGoDraftsFolder.m \
|
||||
SOGoDraftObject.m \
|
||||
\
|
||||
SOGoMailForward.m
|
||||
SOGoMailForward.m \
|
||||
\
|
||||
NSData+Mail.m
|
||||
|
||||
Mailer_RESOURCE_FILES += \
|
||||
Version \
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/* NSData+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 NSDATA_MAIL_H
|
||||
#define NSDATA_MAIL_H
|
||||
|
||||
#import <Foundation/NSData.h>
|
||||
|
||||
@class NSString;
|
||||
|
||||
@interface NSData (SOGoMailUtilities)
|
||||
|
||||
- (NSData *) bodyDataFromEncoding: (NSString *) encoding;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* NSDATA_MAIL_H */
|
||||
@@ -0,0 +1,55 @@
|
||||
/* NSData+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/NSString.h>
|
||||
|
||||
#import <NGExtensions/NGBase64Coding.h>
|
||||
#import <NGExtensions/NGQuotedPrintableCoding.h>
|
||||
|
||||
#import "NSData+Mail.h"
|
||||
|
||||
@implementation NSData (SOGoMailUtilities)
|
||||
|
||||
- (NSData *) bodyDataFromEncoding: (NSString *) encoding
|
||||
{
|
||||
NSString *realEncoding;
|
||||
NSData *decodedData;
|
||||
|
||||
realEncoding = [encoding lowercaseString];
|
||||
|
||||
if ([realEncoding isEqualToString: @"7bit"]
|
||||
|| [realEncoding isEqualToString: @"8bit"])
|
||||
decodedData = self;
|
||||
else if ([realEncoding isEqualToString: @"base64"])
|
||||
decodedData = [self dataByDecodingBase64];
|
||||
else if ([realEncoding isEqualToString: @"quoted-printable"])
|
||||
decodedData = [self dataByDecodingQuotedPrintable];
|
||||
else
|
||||
{
|
||||
decodedData = nil;
|
||||
NSLog (@"encoding '%@' unknown, returning nil data", realEncoding);
|
||||
}
|
||||
|
||||
return decodedData;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -56,6 +56,8 @@
|
||||
#import <SoObjects/SOGo/NSString+Utilities.h>
|
||||
#import <SoObjects/SOGo/SOGoMailer.h>
|
||||
#import <SoObjects/SOGo/SOGoUser.h>
|
||||
|
||||
#import "NSData+Mail.h"
|
||||
#import "SOGoMailAccount.h"
|
||||
#import "SOGoMailFolder.h"
|
||||
#import "SOGoMailObject.h"
|
||||
@@ -411,30 +413,49 @@ static BOOL showTextAttachmentsInline = NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *) _attachmentBodiesFromPaths: (NSArray *) paths
|
||||
fromResponseFetch: (NSDictionary *) fetch;
|
||||
{
|
||||
NSEnumerator *attachmentKeys;
|
||||
NSMutableArray *bodies;
|
||||
NSString *currentKey;
|
||||
NSDictionary *body;
|
||||
|
||||
bodies = [NSMutableArray array];
|
||||
|
||||
attachmentKeys = [paths objectEnumerator];
|
||||
while ((currentKey = [attachmentKeys nextObject]))
|
||||
{
|
||||
body = [fetch objectForKey: [currentKey lowercaseString]];
|
||||
[bodies addObject: [body objectForKey: @"data"]];
|
||||
}
|
||||
|
||||
return bodies;
|
||||
}
|
||||
|
||||
- (void) _fetchAttachments: (NSArray *) parts
|
||||
fromMail: (SOGoMailObject *) sourceMail
|
||||
{
|
||||
unsigned int count, max;
|
||||
NSDictionary *currentPart, *attachment, *body;
|
||||
NSArray *paths, *result;
|
||||
NSArray *paths, *bodies;
|
||||
NSData *body;
|
||||
NSDictionary *currentInfo;
|
||||
NGHashMap *response;
|
||||
|
||||
max = [parts count];
|
||||
if (max > 0)
|
||||
{
|
||||
paths = [parts keysWithFormat: @"BODY[%{path}]"];
|
||||
result = [[sourceMail fetchParts: paths] objectForKey: @"fetch"];
|
||||
response = [[sourceMail fetchParts: paths] objectForKey: @"RawResponse"];
|
||||
bodies = [self _attachmentBodiesFromPaths: paths
|
||||
fromResponseFetch: [response objectForKey: @"fetch"]];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
currentPart = [parts objectAtIndex: count];
|
||||
body = [[result objectAtIndex: count] objectForKey: @"body"];
|
||||
attachment = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[currentPart objectForKey: @"filename"],
|
||||
@"filename",
|
||||
[currentPart objectForKey: @"mimetype"],
|
||||
@"mime-type",
|
||||
nil];
|
||||
[self saveAttachment: [body objectForKey: @"data"]
|
||||
withMetadata: attachment];
|
||||
currentInfo = [parts objectAtIndex: count];
|
||||
body = [[bodies objectAtIndex: count]
|
||||
bodyDataFromEncoding: [currentInfo
|
||||
objectForKey: @"encoding"]];
|
||||
[self saveAttachment: body withMetadata: currentInfo];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -529,7 +550,7 @@ static BOOL showTextAttachmentsInline = NO;
|
||||
// error = [newDraft saveAttachment:content withName:@"forward.mail"];
|
||||
attachment = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[sourceMail filenameForForward], @"filename",
|
||||
@"message/rfc822", @"mime-type",
|
||||
@"message/rfc822", @"mimetype",
|
||||
nil];
|
||||
[self saveAttachment: [sourceMail content]
|
||||
withMetadata: attachment];
|
||||
@@ -639,7 +660,7 @@ static BOOL showTextAttachmentsInline = NO;
|
||||
reason: @"Could not write attachment to draft!"];
|
||||
}
|
||||
|
||||
mimeType = [metadata objectForKey: @"mime-type"];
|
||||
mimeType = [metadata objectForKey: @"mimetype"];
|
||||
if ([mimeType length] > 0)
|
||||
{
|
||||
p = [self pathToAttachmentWithName:
|
||||
|
||||
@@ -232,20 +232,22 @@
|
||||
intoArray: (NSMutableArray *) keys
|
||||
withPath: (NSString *) path
|
||||
{
|
||||
NSDictionary *parameters, *currentFile;
|
||||
NSDictionary *disposition, *currentFile;
|
||||
NSString *filename, *mimeType;
|
||||
|
||||
parameters = [[part objectForKey: @"disposition"]
|
||||
objectForKey: @"parameterList"];
|
||||
if (parameters)
|
||||
disposition = [part objectForKey: @"disposition"];
|
||||
filename = [[disposition objectForKey: @"parameterList"]
|
||||
objectForKey: @"filename"];
|
||||
if (filename)
|
||||
{
|
||||
filename = [parameters objectForKey: @"filename"];
|
||||
mimeType = [NSString stringWithFormat: @"%@/%@",
|
||||
[part objectForKey: @"type"],
|
||||
[part objectForKey: @"subtype"]];
|
||||
currentFile = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
filename, @"filename",
|
||||
[mimeType lowercaseString], @"mimetype",
|
||||
[part
|
||||
objectForKey: @"encoding"], @"encoding",
|
||||
path, @"path", nil];
|
||||
[keys addObject: currentFile];
|
||||
}
|
||||
|
||||
@@ -31,10 +31,8 @@
|
||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
#import <NGObjWeb/WOResponse.h>
|
||||
#import <NGObjWeb/NSException+HTTP.h>
|
||||
#import <NGExtensions/NGBase64Coding.h>
|
||||
#import <NGExtensions/NSNull+misc.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
#import <NGExtensions/NGQuotedPrintableCoding.h>
|
||||
#import <NGExtensions/NSString+Encoding.h>
|
||||
#import <NGExtensions/NSString+misc.h>
|
||||
#import <NGImap4/NGImap4Connection.h>
|
||||
@@ -44,6 +42,8 @@
|
||||
|
||||
#import <SoObjects/SOGo/SOGoPermissions.h>
|
||||
#import <SoObjects/SOGo/SOGoUser.h>
|
||||
|
||||
#import "NSData+Mail.h"
|
||||
#import "SOGoMailFolder.h"
|
||||
#import "SOGoMailAccount.h"
|
||||
#import "SOGoMailManager.h"
|
||||
@@ -619,37 +619,29 @@ static BOOL debugSoParts = NO;
|
||||
}
|
||||
|
||||
/* convert parts to strings */
|
||||
|
||||
- (NSString *) stringForData: (NSData *) _data
|
||||
partInfo: (NSDictionary *) _info
|
||||
{
|
||||
NSString *charset, *encoding, *s;
|
||||
NSString *charset, *s;
|
||||
NSData *mailData;
|
||||
|
||||
if (![_data isNotNull])
|
||||
return nil;
|
||||
|
||||
s = nil;
|
||||
|
||||
encoding = [[_info objectForKey: @"encoding"] lowercaseString];
|
||||
|
||||
if ([encoding isEqualToString: @"7bit"]
|
||||
|| [encoding isEqualToString: @"8bit"])
|
||||
mailData = _data;
|
||||
else if ([encoding isEqualToString: @"base64"])
|
||||
mailData = [_data dataByDecodingBase64];
|
||||
else if ([encoding isEqualToString: @"quoted-printable"])
|
||||
mailData = [_data dataByDecodingQuotedPrintable];
|
||||
|
||||
charset = [[_info valueForKey: @"parameterList"] valueForKey: @"charset"];
|
||||
if (![charset length])
|
||||
if ([_data isNotNull])
|
||||
{
|
||||
s = [[NSString alloc] initWithData:mailData encoding:NSUTF8StringEncoding];
|
||||
[s autorelease];
|
||||
mailData
|
||||
= [_data bodyDataFromEncoding: [_info objectForKey: @"encoding"]];
|
||||
|
||||
charset = [[_info valueForKey: @"parameterList"] valueForKey: @"charset"];
|
||||
if (![charset length])
|
||||
{
|
||||
s = [[NSString alloc] initWithData: mailData encoding: NSUTF8StringEncoding];
|
||||
[s autorelease];
|
||||
}
|
||||
else
|
||||
s = [NSString stringWithData: mailData
|
||||
usingEncodingNamed: charset];
|
||||
}
|
||||
else
|
||||
s = [NSString stringWithData: mailData
|
||||
usingEncodingNamed: charset];
|
||||
s = nil;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -280,13 +280,14 @@ static NSArray *infoKeys = nil;
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
part = [parts objectAtIndex: count];
|
||||
header = (NGMimeContentDispositionHeaderField *) [part headerForKey: @"content-disposition"];
|
||||
mimeType = [(NGMimeType *) [part headerForKey: @"content-type"] stringValue];
|
||||
header = (NGMimeContentDispositionHeaderField *)
|
||||
[part headerForKey: @"content-disposition"];
|
||||
mimeType = [(NGMimeType *)
|
||||
[part headerForKey: @"content-type"] stringValue];
|
||||
attachment = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[header filename], @"filename",
|
||||
mimeType, @"mime-type", nil];
|
||||
[filenames setObject: attachment
|
||||
forKey: [header name]];
|
||||
mimeType, @"mimetype", nil];
|
||||
[filenames setObject: attachment forKey: [header name]];
|
||||
}
|
||||
|
||||
return filenames;
|
||||
|
||||
@@ -16,7 +16,7 @@ function onContactAdd() {
|
||||
w.focus();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function addContact(tag, fullContactName, contactId, contactName, contactEmail) {
|
||||
if (!mailIsRecipient(contactEmail)) {
|
||||
@@ -121,59 +121,76 @@ function updateInlineAttachmentList(sender, attachments) {
|
||||
/* mail editor */
|
||||
|
||||
function validateEditorInput(sender) {
|
||||
var errortext = "";
|
||||
var field;
|
||||
var errortext = "";
|
||||
var field;
|
||||
|
||||
field = document.pageform.subject;
|
||||
if (field.value == "")
|
||||
errortext = errortext + labels["error_missingsubject"] + "\n";
|
||||
field = document.pageform.subject;
|
||||
if (field.value == "")
|
||||
errortext = errortext + labels["error_missingsubject"] + "\n";
|
||||
|
||||
if (!UIxRecipientSelectorHasRecipients())
|
||||
errortext = errortext + labels["error_missingrecipients"] + "\n";
|
||||
if (!UIxRecipientSelectorHasRecipients())
|
||||
errortext = errortext + labels["error_missingrecipients"] + "\n";
|
||||
|
||||
if (errortext.length > 0) {
|
||||
alert(labels["error_validationfailed"] + ":\n" + errortext);
|
||||
return false;
|
||||
}
|
||||
if (errortext.length > 0) {
|
||||
alert(labels["error_validationfailed"] + ":\n" + errortext);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
function clickedEditorSend(sender) {
|
||||
if (!validateEditorInput(sender))
|
||||
return false;
|
||||
if (!validateEditorInput(sender))
|
||||
return false;
|
||||
|
||||
window.shouldPreserve = true;
|
||||
document.pageform.action = "send";
|
||||
document.pageform.submit();
|
||||
var input = currentAttachmentInput();
|
||||
if (input)
|
||||
input.parentNode.removeChild(input);
|
||||
|
||||
return false;
|
||||
var toolbar = document.getElementById("toolbar");
|
||||
if (!document.busyAnim)
|
||||
document.busyAnim = startAnimation(toolbar);
|
||||
|
||||
window.shouldPreserve = true;
|
||||
document.pageform.action = "send";
|
||||
document.pageform.submit();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function currentAttachmentInput() {
|
||||
var input = null;
|
||||
|
||||
var inputs = $("attachmentsArea").getElementsByTagName("input");
|
||||
var i = 0;
|
||||
while (!input && i < inputs.length)
|
||||
if ($(inputs[i]).hasClassName("currentAttachment"))
|
||||
input = inputs[i];
|
||||
else
|
||||
i++;
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
function clickedEditorAttach(sender) {
|
||||
var area = $("attachmentsArea");
|
||||
var input = currentAttachmentInput();
|
||||
if (!input) {
|
||||
var area = $("attachmentsArea");
|
||||
|
||||
if (!area.style.display) {
|
||||
area.setStyle({ display: "block" });
|
||||
onWindowResize(null);
|
||||
}
|
||||
|
||||
var inputs = area.getElementsByTagName("input");
|
||||
|
||||
// Verify if there's already a visible file input field
|
||||
for (var i = 0; i < inputs.length; i++)
|
||||
if ($(inputs[i]).hasClassName("currentAttachment"))
|
||||
return false;
|
||||
|
||||
// Add new file input field
|
||||
var attachmentName = "attachment" + inputs.length;
|
||||
var newAttachment = createElement("input", attachmentName,
|
||||
"currentAttachment", null,
|
||||
{ type: "file",
|
||||
name: attachmentName },
|
||||
area);
|
||||
Event.observe(newAttachment, "change",
|
||||
onAttachmentChange.bindAsEventListener(newAttachment));
|
||||
if (!area.style.display) {
|
||||
area.setStyle({ display: "block" });
|
||||
onWindowResize(null);
|
||||
}
|
||||
var inputs = area.getElementsByTagName("input");
|
||||
var attachmentName = "attachment" + inputs.length;
|
||||
var newAttachment = createElement("input", attachmentName,
|
||||
"currentAttachment", null,
|
||||
{ type: "file",
|
||||
name: attachmentName },
|
||||
area);
|
||||
Event.observe(newAttachment, "change",
|
||||
onAttachmentChange.bindAsEventListener(newAttachment));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -211,6 +228,14 @@ function createAttachment(node, list) {
|
||||
}
|
||||
|
||||
function clickedEditorSave(sender) {
|
||||
var input = currentAttachmentInput();
|
||||
if (input)
|
||||
input.parentNode.removeChild(input);
|
||||
|
||||
var toolbar = document.getElementById("toolbar");
|
||||
if (!document.busyAnim)
|
||||
document.busyAnim = startAnimation(toolbar);
|
||||
|
||||
window.shouldPreserve = true;
|
||||
document.pageform.action = "save";
|
||||
document.pageform.submit();
|
||||
|
||||
Reference in New Issue
Block a user