See ChangeLog

Monotone-Parent: da4549a652b63b86055b1d36eb59d91375871786
Monotone-Revision: 694484559aed659a4395cabbbbf946966b25ff4e

Monotone-Author: crobert@inverse.ca
Monotone-Date: 2008-09-30T13:42:48
Monotone-Branch: ca.inverse.sogo
This commit is contained in:
C Robert 2008-09-30 13:42:48 +00:00
parent 4b4a8d3446
commit d228e96a78
9 changed files with 179 additions and 23 deletions

View file

@ -1,3 +1,19 @@
2008-09-30 Cyril Robert <crobert@inverse.ca>
* SoObjects/Mailer/SOGoDraftsFolder.m
Moved userSpoolFolderPath method to SOGoMailFolder.m
* SoObjects/Mailer/SOGoMailFolder.h
* SoObjects/Mailer/SOGoMailFolder.m
Added userSpoolFolderPath from SOGoDraftsFolder
Added archiveUIDs method to create an archive from email uids
* UI/MailerUI/UIxMailFolderActions.h
* UI/MailerUI/UIxMailFolderActions.m
Added saveMessagesAction method to handle the /saveMessages call
* UI/MailerUI/product.plist
Added a definition for saveMessages
2008-09-28 Ludovic Marcotte <lmarcotte@inverse.ca> 2008-09-28 Ludovic Marcotte <lmarcotte@inverse.ca>
* Modified the following files: * Modified the following files:

View file

@ -102,14 +102,5 @@ static unsigned int newCount;
return YES; return YES;
} }
- (NSString *) userSpoolFolderPath
{
NSString *login;
login = [[context activeUser] login];
return [NSString stringWithFormat: @"%@/%@",
spoolFolder, login];
}
@end @end

View file

@ -24,6 +24,7 @@
#include <SoObjects/Mailer/SOGoMailBaseObject.h> #include <SoObjects/Mailer/SOGoMailBaseObject.h>
#import <Foundation/NSRange.h> #import <Foundation/NSRange.h>
#import <NGObjWeb/WOResponse.h>
/* /*
SOGoMailFolder SOGoMailFolder
@ -55,6 +56,7 @@ typedef enum {
/* messages */ /* messages */
- (NSException *) deleteUIDs: (NSArray *) uids inContext: (id) context; - (NSException *) deleteUIDs: (NSArray *) uids inContext: (id) context;
- (WOResponse *) archiveUIDs: (NSArray *) uids inContext: (id) context;
- (NSArray *) fetchUIDsMatchingQualifier: (id)_q sortOrdering: (id) _so; - (NSArray *) fetchUIDsMatchingQualifier: (id)_q sortOrdering: (id) _so;
- (NSArray *) fetchUIDs: (NSArray *) _uids parts: (NSArray *) _parts; - (NSArray *) fetchUIDs: (NSArray *) _uids parts: (NSArray *) _parts;
@ -81,6 +83,9 @@ typedef enum {
- (NSArray *) allFolderPaths; - (NSArray *) allFolderPaths;
- (NSArray *) allFolderURLs; - (NSArray *) allFolderURLs;
- (NSString *) userSpoolFolderPath;
- (BOOL) ensureSpoolFolderPath;
@end @end
@interface SOGoSpecialMailFolder : SOGoMailFolder @interface SOGoSpecialMailFolder : SOGoMailFolder

View file

@ -23,13 +23,16 @@
#import <Foundation/NSEnumerator.h> #import <Foundation/NSEnumerator.h>
#import <Foundation/NSURL.h> #import <Foundation/NSURL.h>
#import <Foundation/NSUserDefaults.h> #import <Foundation/NSUserDefaults.h>
#import <Foundation/NSTask.h>
#import <NGObjWeb/NSException+HTTP.h> #import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/WOContext+SoObjects.h> #import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WOResponse.h>
#import <NGExtensions/NSNull+misc.h> #import <NGExtensions/NSNull+misc.h>
#import <NGExtensions/NSURL+misc.h> #import <NGExtensions/NSURL+misc.h>
#import <NGExtensions/NSObject+Logs.h> #import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSString+misc.h> #import <NGExtensions/NSString+misc.h>
#import <NGExtensions/NSFileManager+Extensions.h>
#import <NGImap4/NGImap4Connection.h> #import <NGImap4/NGImap4Connection.h>
#import <NGImap4/NGImap4Client.h> #import <NGImap4/NGImap4Client.h>
@ -51,6 +54,8 @@ static BOOL aclUsernamesAreQuoted = NO;
/* http://www.tools.ietf.org/wg/imapext/draft-ietf-imapext-acl/ */ /* http://www.tools.ietf.org/wg/imapext/draft-ietf-imapext-acl/ */
static BOOL aclConformsToIMAPExt = NO; static BOOL aclConformsToIMAPExt = NO;
static NSString *spoolFolder = nil;
@interface NGImap4Connection (PrivateMethods) @interface NGImap4Connection (PrivateMethods)
- (NSString *) imap4FolderNameForURL: (NSURL *) url; - (NSString *) imap4FolderNameForURL: (NSURL *) url;
@ -78,6 +83,16 @@ static BOOL aclConformsToIMAPExt = NO;
aclConformsToIMAPExt aclConformsToIMAPExt
= [ud boolForKey: @"SOGoIMAPAclConformsToIMAPExt"]; = [ud boolForKey: @"SOGoIMAPAclConformsToIMAPExt"];
} }
if (!spoolFolder)
{
spoolFolder = [ud stringForKey:@"SOGoMailSpoolPath"];
if (![spoolFolder length])
spoolFolder = @"/tmp/";
[spoolFolder retain];
NSLog(@"Note: using SOGo mail spool folder: %@", spoolFolder);
}
} }
+ (SOGoIMAPAclStyle) imapAclStyle + (SOGoIMAPAclStyle) imapAclStyle
@ -302,6 +317,82 @@ static BOOL aclConformsToIMAPExt = NO;
return error; return error;
} }
- (WOResponse *) archiveUIDs: (NSArray *) uids
inContext: (id) localContext
{
NSException *error;
NSFileManager *fm;
NSString *spoolPath, *fileName;
NSDictionary *msgs;
NSArray *messages;
NSData *content, *zipContent;
NSTask *zipTask;
NSMutableArray *zipTaskArguments;
WOResponse *response;
int i;
spoolPath = [self userSpoolFolderPath];
if ( ![self ensureSpoolFolderPath] ) {
error = [NSException exceptionWithHTTPStatus: 500
reason: @"spoolFolderPath doesn't exist"];
return (WOResponse *)error;
}
fm = [NSFileManager defaultManager];
if ( ![fm fileExistsAtPath: @"/usr/bin/zip"] ) {
error = [NSException exceptionWithHTTPStatus: 500
reason: @"zip not available"];
return (WOResponse *)error;
}
zipTask = [[NSTask alloc] init];
[zipTask setCurrentDirectoryPath: spoolPath];
[zipTask setLaunchPath: @"/usr/bin/zip"];
zipTaskArguments = [NSMutableArray arrayWithObjects: nil];
[zipTaskArguments addObject: @"SavedMessages.zip"];
msgs = (NSDictionary *)[self fetchUIDs: uids
parts: [NSArray arrayWithObject: @"RFC822"]];
messages = [[msgs objectForKey: @"fetch"] retain];
for (i = 0; i < [messages count]; i++) {
content = [[messages objectAtIndex: i] objectForKey: @"message"];
[content writeToFile:
[NSString stringWithFormat:@"%@/%d.eml", spoolPath, [uids objectAtIndex: i]]
atomically: YES];
[zipTaskArguments addObject:
[NSString stringWithFormat:@"%d.eml", [uids objectAtIndex: i]]];
}
[zipTask setArguments: zipTaskArguments];
[zipTask launch];
[zipTask waitUntilExit];
[zipTask release];
zipContent = [[NSData alloc] initWithContentsOfFile:
[NSString stringWithFormat: @"%@/SavedMessages.zip", spoolPath]];
for(i = 0; i < [zipTaskArguments count]; i++) {
fileName = [zipTaskArguments objectAtIndex: i];
[fm removeFileAtPath:
[NSString stringWithFormat: @"%@/%@", spoolPath, fileName] handler: nil];
}
response = [[WOResponse alloc] init];
[response autorelease];
[response setHeader: @"application/zip" forKey:@"content-type"];
[response setHeader: @"attachment;filename=SavedMessages.zip" forKey: @"Content-Disposition"];
[response setContent: zipContent];
[zipContent release];
return response;
}
- (NSArray *) fetchUIDsMatchingQualifier: (id) _q - (NSArray *) fetchUIDsMatchingQualifier: (id) _q
sortOrdering: (id) _so sortOrdering: (id) _so
{ {
@ -891,6 +982,25 @@ static BOOL aclConformsToIMAPExt = NO;
return [userURL absoluteString]; return [userURL absoluteString];
} }
- (NSString *) userSpoolFolderPath
{
NSString *login;
login = [[context activeUser] login];
return [NSString stringWithFormat: @"%@/%@",
spoolFolder, login];
}
- (BOOL) ensureSpoolFolderPath
{
NSFileManager *fm;
fm = [NSFileManager defaultManager];
return ([fm createDirectoriesAtPath: [self userSpoolFolderPath] attributes:nil]);
}
@end /* SOGoMailFolder */ @end /* SOGoMailFolder */
@implementation SOGoSpecialMailFolder @implementation SOGoSpecialMailFolder

View file

@ -33,6 +33,7 @@
- (WOResponse *) renameFolderAction; - (WOResponse *) renameFolderAction;
- (WOResponse *) deleteFolderAction; - (WOResponse *) deleteFolderAction;
- (WOResponse *) deleteMessagesAction; - (WOResponse *) deleteMessagesAction;
- (WOResponse *) saveMessagesAction;
- (WOResponse *) expungeAction; - (WOResponse *) expungeAction;
- (WOResponse *) emptyTrashAction; - (WOResponse *) emptyTrashAction;
- (WOResponse *) subscribeAction; - (WOResponse *) subscribeAction;

View file

@ -209,6 +209,33 @@
return response; return response;
} }
- (WOResponse *) saveMessagesAction
{
SOGoMailFolder *co;
WOResponse *response;
NSArray *uids;
NSString *value;
co = [self clientObject];
value = [[context request] formValueForKey: @"uid"];
response = nil;
if ([value length] > 0)
{
uids = [value componentsSeparatedByString: @","];
response = [co archiveUIDs: uids inContext: context];
if (!response)
response = [self responseWith204];
}
else
{
response = [self responseWithStatus: 500];
[response appendContentString: @"Missing 'uid' parameter."];
}
return response;
}
- (WOResponse *) _setFolderPurpose: (NSString *) purpose - (WOResponse *) _setFolderPurpose: (NSString *) purpose
{ {
SOGoMailFolder *co; SOGoMailFolder *co;

View file

@ -141,6 +141,11 @@
actionClass = "UIxMailFolderActions"; actionClass = "UIxMailFolderActions";
actionName = "deleteMessages"; actionName = "deleteMessages";
}; };
saveMessages = {
protectedBy = "View";
actionClass = "UIxMailFolderActions";
actionName = "saveMessages";
};
setAsDraftsFolder = { setAsDraftsFolder = {
protectedBy = "View"; protectedBy = "View";
actionClass = "UIxMailFolderActions"; actionClass = "UIxMailFolderActions";

View file

@ -124,6 +124,7 @@
<li><var:string label:value="Label"/></li> <li><var:string label:value="Label"/></li>
<li><var:string label:value="Mark"/></li> <li><var:string label:value="Mark"/></li>
<li><!-- separator --></li> <li><!-- separator --></li>
<li><var:string label:value="Save As..."/></li>
<li><var:string label:value="Print Preview"/></li> <li><var:string label:value="Print Preview"/></li>
<li><var:string label:value="Print..."/></li> <li><var:string label:value="Print..."/></li>
<li><var:string label:value="Delete Selected Messages"/></li> <li><var:string label:value="Delete Selected Messages"/></li>

View file

@ -539,7 +539,7 @@ function initMailEditor() {
var sigLimit = textContent.lastIndexOf("--"); var sigLimit = textContent.lastIndexOf("--");
if (sigLimit > -1) if (sigLimit > -1)
signatureLength = (textContent.length - sigLimit); signatureLength = (textContent.length - sigLimit);
if ( userDefaults["SignaturePlacement"] != "above" ) { if ( userDefaults["ReplyPlacement"] != "above" ) {
textarea.scrollTop = textarea.scrollHeight; textarea.scrollTop = textarea.scrollHeight;
} }
textarea.observe("focus", onTextFirstFocus); textarea.observe("focus", onTextFirstFocus);