merge of 'c31687d1f15f8f1be580514cd252776e204a1b65'
and 'd44c77e73da2480ce01afa441c8a2705f220ae25' Monotone-Parent: c31687d1f15f8f1be580514cd252776e204a1b65 Monotone-Parent: d44c77e73da2480ce01afa441c8a2705f220ae25 Monotone-Revision: 701785bc094e6e0cc71468721c162b7ddd82fda5 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-30T16:50:07 Monotone-Branch: ca.inverse.sogo
122
ChangeLog
|
@ -5,9 +5,23 @@
|
|||
lookup syntax has been generalized by testing for "ref-dn" instead
|
||||
of "dict-dn". Make use of only non-deprecated LDAP functions.
|
||||
|
||||
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>
|
||||
|
||||
* Modified the following files:
|
||||
* Modified the following files:
|
||||
SoObjects/Mailer/SOGoDraftObject.m
|
||||
UI/MailerUI/Dutch.lproj/Localizable.strings
|
||||
UI/MailerUI/English.lproj/Localizable.strings
|
||||
|
@ -329,7 +343,7 @@
|
|||
|
||||
2008-08-22 Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||
|
||||
* Modified SoObjects/Mailer/NSData+Mail.m
|
||||
* Modified SoObjects/Mailer/NSData+Mail.m
|
||||
-decodedSubject so we correctly implement decoding
|
||||
instead of relying on the broken SOPE implementation.
|
||||
|
||||
|
@ -1679,14 +1693,14 @@
|
|||
2008-01-14 Ludovic Marcotte <ludovic@inverse.ca>
|
||||
|
||||
* Added files related to the custom recurrence
|
||||
editor of the SOGo Web interface. The CSS
|
||||
needs to be done correctly.
|
||||
editor of the SOGo Web interface. The CSS
|
||||
needs to be done correctly.
|
||||
|
||||
* Fixed a bug in the daily recurrence generator.
|
||||
We now consider the byDayMask, if any.
|
||||
We now consider the byDayMask, if any.
|
||||
|
||||
* Moved the repeat/reminder code to the
|
||||
UIxComponentEditor class / template.
|
||||
UIxComponentEditor class / template.
|
||||
|
||||
* Added a few JavaScript methods to HTMLElement.js
|
||||
|
||||
|
@ -1828,7 +1842,7 @@
|
|||
and created re-entrant issues.
|
||||
|
||||
* UI/MailPartViewers/UIxMailPartHTMLViewer.m
|
||||
Added a hack (and stated so in the source file)
|
||||
Added a hack (and stated so in the source file)
|
||||
to avoid what seems to be a bug in libxml.
|
||||
|
||||
2007-12-12 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
@ -2141,32 +2155,32 @@
|
|||
|
||||
2007-11-25 Ludovic Marcotte <ludovic@inverse.ca>
|
||||
|
||||
* SoObjects/Mailer/SOGoMailForward.m
|
||||
Use [sourceMail decodedSubject] instead of [sourceMail subject]
|
||||
Signature fix in -signature - see the comment
|
||||
for SOGoMailReply.
|
||||
* SoObjects/Mailer/SOGoMailForward.m
|
||||
Use [sourceMail decodedSubject] instead of [sourceMail subject]
|
||||
Signature fix in -signature - see the comment
|
||||
for SOGoMailReply.
|
||||
|
||||
* SoObjects/Mailer/SOGoMailObject.m
|
||||
Improved -stringFromData: to try UTF-8 then fallback to Latin1
|
||||
* SoObjects/Mailer/SOGoMailObject.m
|
||||
Improved -stringFromData: to try UTF-8 then fallback to Latin1
|
||||
|
||||
* SoObjects/Mailer/SOGoMailReply.m
|
||||
Modified -messageBody to strip the signature from the reply.
|
||||
Also modified -signature to add "-- \n%@" instead of the
|
||||
broken ""--\r\n%@" pattern.
|
||||
* SoObjects/Mailer/SOGoMailReply.m
|
||||
Modified -messageBody to strip the signature from the reply.
|
||||
Also modified -signature to add "-- \n%@" instead of the
|
||||
broken ""--\r\n%@" pattern.
|
||||
|
||||
* UI/MailPartViewers/UIxMailPartAlternativeViewer.m
|
||||
We now favor text/calendar parts over text/html and
|
||||
text/plain parts when viewing a multipart/alternative mail.
|
||||
This allows us to show the email invitations coming from
|
||||
Microsoft Outlook.
|
||||
* UI/MailPartViewers/UIxMailPartAlternativeViewer.m
|
||||
We now favor text/calendar parts over text/html and
|
||||
text/plain parts when viewing a multipart/alternative mail.
|
||||
This allows us to show the email invitations coming from
|
||||
Microsoft Outlook.
|
||||
|
||||
* UI/MailerUI/UIxMailAccountActions.m
|
||||
Signature fix in -composeAction - see the comment
|
||||
for SOGoMailReply.
|
||||
* UI/MailerUI/UIxMailAccountActions.m
|
||||
Signature fix in -composeAction - see the comment
|
||||
for SOGoMailReply.
|
||||
|
||||
* UI/MailPartViewers/UIxMailPartViewer.m
|
||||
Modified -flatContentAsString to use UTF-8 as the
|
||||
default fallback encoding for 8-bit content.
|
||||
* UI/MailPartViewers/UIxMailPartViewer.m
|
||||
Modified -flatContentAsString to use UTF-8 as the
|
||||
default fallback encoding for 8-bit content.
|
||||
|
||||
* SoObjects/Mailer/SOGoDraftObject.m
|
||||
Modified _fillInReplyAddresses:replyToAll:envelope:
|
||||
|
@ -2427,7 +2441,7 @@
|
|||
|
||||
2007-11-16 Ludovic Marcotte <ludovic@inverse.ca>
|
||||
|
||||
* SoObjects/Mailer/SOGoMailBaseObject.m
|
||||
* SoObjects/Mailer/SOGoMailBaseObject.m
|
||||
Fixed typo.
|
||||
|
||||
* SoObjects/Mailer/SOGoMailBodyPart.m
|
||||
|
@ -2455,27 +2469,27 @@
|
|||
|
||||
2007-11-15 Ludovic Marcotte <ludovic@inverse.ca>
|
||||
|
||||
* UI/WebServerResources/MailerUI.js
|
||||
We now check for empty selection and warn the
|
||||
user about it when deleting messages
|
||||
* UI/WebServerResources/MailerUI.js
|
||||
We now check for empty selection and warn the
|
||||
user about it when deleting messages
|
||||
|
||||
* SoObjects/Mailer/SOGoDraftObject.m
|
||||
Correctly check for the presence of a subject
|
||||
before attempting to forward a message from
|
||||
the Drafts folder.
|
||||
* SoObjects/Mailer/SOGoDraftObject.m
|
||||
Correctly check for the presence of a subject
|
||||
before attempting to forward a message from
|
||||
the Drafts folder.
|
||||
|
||||
* SoObjects/Mailer/SOGoMailObject+Draft.m
|
||||
We no longer use "[Fwd: ]" but simply "Fwd:"
|
||||
when forwarding email messages.
|
||||
* SoObjects/Mailer/SOGoMailObject+Draft.m
|
||||
We no longer use "[Fwd: ]" but simply "Fwd:"
|
||||
when forwarding email messages.
|
||||
|
||||
* SoObjects/SOGo/SOGoUser.m
|
||||
Modified the default forwarding format to be
|
||||
inline instead of "attachment".
|
||||
* SoObjects/SOGo/SOGoUser.m
|
||||
Modified the default forwarding format to be
|
||||
inline instead of "attachment".
|
||||
|
||||
* SoObjects/Mailer/SOGoDraftObject.m
|
||||
We now create and use a NGMimeContentDispositionHeaderField
|
||||
in order to avoid encoding the whole Content-Disposition
|
||||
header in case a non-ASCII char is present!
|
||||
* SoObjects/Mailer/SOGoDraftObject.m
|
||||
We now create and use a NGMimeContentDispositionHeaderField
|
||||
in order to avoid encoding the whole Content-Disposition
|
||||
header in case a non-ASCII char is present!
|
||||
|
||||
2007-11-13 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
|
@ -3118,10 +3132,10 @@
|
|||
2007-10-10 Ludovic Marcotte <ludovic@inverse.ca>
|
||||
|
||||
* We now send advisory emails when folders
|
||||
are created / deleted.
|
||||
are created / deleted.
|
||||
|
||||
* Fixed the sending of advisory emails upon
|
||||
ACL changes on folders.
|
||||
ACL changes on folders.
|
||||
|
||||
2007-10-10 Ludovic Marcotte <ludovic@inverse.ca>
|
||||
|
||||
|
@ -3137,7 +3151,7 @@
|
|||
in every LDAP-based authentication sources.
|
||||
|
||||
* UI/MailPartViewers/UIxMailPartTextViewer.m and
|
||||
UI/WebServerResources/MailerUI.css
|
||||
UI/WebServerResources/MailerUI.css
|
||||
We avoid replacing "\r\n" and "\n" with <br /> and
|
||||
rather use CSS capabilities for proper formatting.
|
||||
This is _WAY_ faster on very large mails.
|
||||
|
@ -5448,10 +5462,10 @@
|
|||
2007-02-09 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* SoObjects/Appointments/SOGoAppointmentFolder.m: added CalDAV
|
||||
resourcetype
|
||||
resourcetype
|
||||
|
||||
* SoObjects/SOGo/SOGoUserFolder.m: added davCalendarHomeSet CalDAV
|
||||
property to point at the user folder
|
||||
property to point at the user folder
|
||||
|
||||
2007-03-07 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
|
@ -7525,9 +7539,9 @@
|
|||
|
||||
2006-06-15 ludovic@inverse.ca
|
||||
|
||||
* It's now possible to set the default
|
||||
domain using for email using the
|
||||
SOGoDefaultMailDomain preference key.
|
||||
* It's now possible to set the default
|
||||
domain using for email using the
|
||||
SOGoDefaultMailDomain preference key.
|
||||
|
||||
2006-06-15 ludovic@inverse.ca
|
||||
|
||||
|
|
5
NEWS
|
@ -1,3 +1,8 @@
|
|||
1.0-2008XXYY (1.0)
|
||||
------------------
|
||||
- added quota indicator in web mail module
|
||||
- improved drag handles behavior
|
||||
|
||||
1.0-20080826 (1.0 rc8)
|
||||
----------------------
|
||||
- fixed a bug that would prevent deleted event and tasks from being removed from the events and tasks list
|
||||
|
|
|
@ -47,7 +47,7 @@ static unsigned int newCount;
|
|||
ud = [NSUserDefaults standardUserDefaults];
|
||||
spoolFolder = [ud stringForKey:@"SOGoMailSpoolPath"];
|
||||
if (![spoolFolder length])
|
||||
spoolFolder = @"/tmp/";
|
||||
spoolFolder = @"/tmp/";
|
||||
[spoolFolder retain];
|
||||
|
||||
NSLog(@"Note: using SOGo mail spool folder: %@", spoolFolder);
|
||||
|
@ -102,14 +102,5 @@ static unsigned int newCount;
|
|||
return YES;
|
||||
}
|
||||
|
||||
- (NSString *) userSpoolFolderPath
|
||||
{
|
||||
NSString *login;
|
||||
|
||||
login = [[context activeUser] login];
|
||||
|
||||
return [NSString stringWithFormat: @"%@/%@",
|
||||
spoolFolder, login];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
<#signaturePlacementOnTop>
|
||||
|
||||
|
||||
<#signature/>
|
||||
</#signaturePlacementOnTop>
|
||||
<#outlookMode>-------- Original Message --------
|
||||
Subject: <#subject/>
|
||||
Date: <#date/>
|
||||
|
@ -8,4 +13,5 @@ From: <#from/>
|
|||
|
||||
<#messageBody/>
|
||||
|
||||
<#signature/>
|
||||
|
||||
<#signaturePlacementOnBottom><#signature/></#signaturePlacementOnBottom>
|
||||
|
|
|
@ -81,3 +81,21 @@ signature: WOString {
|
|||
value = signature;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
replyPlacementOnTop: WOConditional {
|
||||
condition = replyPlacementOnTop;
|
||||
}
|
||||
|
||||
replyPlacementOnBottom: WOConditional {
|
||||
condition = replyPlacementOnTop;
|
||||
negate = YES;
|
||||
}
|
||||
|
||||
signaturePlacementOnTop: WOConditional {
|
||||
condition = signaturePlacementOnTop;
|
||||
}
|
||||
|
||||
signaturePlacementOnBottom: WOConditional {
|
||||
condition = signaturePlacementOnTop;
|
||||
negate = YES;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <SoObjects/Mailer/SOGoMailBaseObject.h>
|
||||
#import <Foundation/NSRange.h>
|
||||
#import <NGObjWeb/WOResponse.h>
|
||||
|
||||
/*
|
||||
SOGoMailFolder
|
||||
|
@ -55,6 +56,7 @@ typedef enum {
|
|||
|
||||
/* messages */
|
||||
- (NSException *) deleteUIDs: (NSArray *) uids inContext: (id) context;
|
||||
- (WOResponse *) archiveUIDs: (NSArray *) uids inContext: (id) context;
|
||||
|
||||
- (NSArray *) fetchUIDsMatchingQualifier: (id)_q sortOrdering: (id) _so;
|
||||
- (NSArray *) fetchUIDs: (NSArray *) _uids parts: (NSArray *) _parts;
|
||||
|
@ -81,6 +83,9 @@ typedef enum {
|
|||
- (NSArray *) allFolderPaths;
|
||||
- (NSArray *) allFolderURLs;
|
||||
|
||||
- (NSString *) userSpoolFolderPath;
|
||||
- (BOOL) ensureSpoolFolderPath;
|
||||
|
||||
@end
|
||||
|
||||
@interface SOGoSpecialMailFolder : SOGoMailFolder
|
||||
|
|
|
@ -23,13 +23,16 @@
|
|||
#import <Foundation/NSEnumerator.h>
|
||||
#import <Foundation/NSURL.h>
|
||||
#import <Foundation/NSUserDefaults.h>
|
||||
#import <Foundation/NSTask.h>
|
||||
|
||||
#import <NGObjWeb/NSException+HTTP.h>
|
||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
#import <NGObjWeb/WOResponse.h>
|
||||
#import <NGExtensions/NSNull+misc.h>
|
||||
#import <NGExtensions/NSURL+misc.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
#import <NGExtensions/NSString+misc.h>
|
||||
#import <NGExtensions/NSFileManager+Extensions.h>
|
||||
|
||||
#import <NGImap4/NGImap4Connection.h>
|
||||
#import <NGImap4/NGImap4Client.h>
|
||||
|
@ -51,6 +54,8 @@ static BOOL aclUsernamesAreQuoted = NO;
|
|||
/* http://www.tools.ietf.org/wg/imapext/draft-ietf-imapext-acl/ */
|
||||
static BOOL aclConformsToIMAPExt = NO;
|
||||
|
||||
static NSString *spoolFolder = nil;
|
||||
|
||||
@interface NGImap4Connection (PrivateMethods)
|
||||
|
||||
- (NSString *) imap4FolderNameForURL: (NSURL *) url;
|
||||
|
@ -65,19 +70,29 @@ static BOOL aclConformsToIMAPExt = NO;
|
|||
NSString *aclStyleStr;
|
||||
|
||||
if (aclStyle == undefined)
|
||||
{
|
||||
ud = [NSUserDefaults standardUserDefaults];
|
||||
aclStyleStr = [ud stringForKey: @"SOGoIMAPAclStyle"];
|
||||
if ([aclStyleStr isEqualToString: @"rfc2086"])
|
||||
aclStyle = rfc2086;
|
||||
else
|
||||
aclStyle = rfc4314;
|
||||
{
|
||||
ud = [NSUserDefaults standardUserDefaults];
|
||||
aclStyleStr = [ud stringForKey: @"SOGoIMAPAclStyle"];
|
||||
if ([aclStyleStr isEqualToString: @"rfc2086"])
|
||||
aclStyle = rfc2086;
|
||||
else
|
||||
aclStyle = rfc4314;
|
||||
|
||||
aclUsernamesAreQuoted
|
||||
= [ud boolForKey: @"SOGoIMAPAclUsernamesAreQuoted"];
|
||||
aclConformsToIMAPExt
|
||||
= [ud boolForKey: @"SOGoIMAPAclConformsToIMAPExt"];
|
||||
}
|
||||
aclUsernamesAreQuoted
|
||||
= [ud boolForKey: @"SOGoIMAPAclUsernamesAreQuoted"];
|
||||
aclConformsToIMAPExt
|
||||
= [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
|
||||
|
@ -302,6 +317,82 @@ static BOOL aclConformsToIMAPExt = NO;
|
|||
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"];
|
||||
|
||||
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
|
||||
sortOrdering: (id) _so
|
||||
{
|
||||
|
@ -891,6 +982,25 @@ static BOOL aclConformsToIMAPExt = NO;
|
|||
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 */
|
||||
|
||||
@implementation SOGoSpecialMailFolder
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
<#signaturePlacementOnTop>
|
||||
|
||||
|
||||
<#signature/>
|
||||
</#signaturePlacementOnTop>
|
||||
<#outlookMode>-------- Message original --------
|
||||
Sujet: <#subject/>
|
||||
Date: <#date/>
|
||||
|
@ -8,4 +13,5 @@ De: <#from/>
|
|||
|
||||
<#messageBody/>
|
||||
|
||||
<#signature/>
|
||||
|
||||
<#signaturePlacementOnBottom><#signature/></#signaturePlacementOnBottom>
|
||||
|
|
|
@ -81,3 +81,21 @@ signature: WOString {
|
|||
value = signature;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
replyPlacementOnTop: WOConditional {
|
||||
condition = replyPlacementOnTop;
|
||||
}
|
||||
|
||||
replyPlacementOnBottom: WOConditional {
|
||||
condition = replyPlacementOnTop;
|
||||
negate = YES;
|
||||
}
|
||||
|
||||
signaturePlacementOnTop: WOConditional {
|
||||
condition = signaturePlacementOnTop;
|
||||
}
|
||||
|
||||
signaturePlacementOnBottom: WOConditional {
|
||||
condition = signaturePlacementOnTop;
|
||||
negate = YES;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
<#signaturePlacementOnTop>
|
||||
|
||||
|
||||
<#signature/>
|
||||
</#signaturePlacementOnTop>
|
||||
<#outlookMode>-------- Original E-Mail --------
|
||||
Betreff: <#subject/>
|
||||
Datum: <#date/>
|
||||
|
@ -8,4 +13,5 @@ Sender: <#from/>
|
|||
|
||||
<#messageBody/>
|
||||
|
||||
<#signature/>
|
||||
|
||||
<#signaturePlacementOnBottom><#signature/></#signaturePlacementOnBottom>
|
||||
|
|
|
@ -81,3 +81,21 @@ signature: WOString {
|
|||
value = signature;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
replyPlacementOnTop: WOConditional {
|
||||
condition = replyPlacementOnTop;
|
||||
}
|
||||
|
||||
replyPlacementOnBottom: WOConditional {
|
||||
condition = replyPlacementOnTop;
|
||||
negate = YES;
|
||||
}
|
||||
|
||||
signaturePlacementOnTop: WOConditional {
|
||||
condition = signaturePlacementOnTop;
|
||||
}
|
||||
|
||||
signaturePlacementOnBottom: WOConditional {
|
||||
condition = signaturePlacementOnTop;
|
||||
negate = YES;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
<#signaturePlacementOnTop>
|
||||
|
||||
|
||||
<#signature/>
|
||||
</#signaturePlacementOnTop>
|
||||
<#outlookMode>-------- Messaggio originale --------
|
||||
Oggetto: <#subject/>
|
||||
Data: <#date/>
|
||||
|
@ -8,4 +13,5 @@ Da: <#from/>
|
|||
|
||||
<#messageBody/>
|
||||
|
||||
<#signature/>
|
||||
|
||||
<#signaturePlacementOnBottom><#signature/></#signaturePlacementOnBottom>
|
||||
|
|
|
@ -81,3 +81,21 @@ signature: WOString {
|
|||
value = signature;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
replyPlacementOnTop: WOConditional {
|
||||
condition = replyPlacementOnTop;
|
||||
}
|
||||
|
||||
replyPlacementOnBottom: WOConditional {
|
||||
condition = replyPlacementOnTop;
|
||||
negate = YES;
|
||||
}
|
||||
|
||||
signaturePlacementOnTop: WOConditional {
|
||||
condition = signaturePlacementOnTop;
|
||||
}
|
||||
|
||||
signaturePlacementOnBottom: WOConditional {
|
||||
condition = signaturePlacementOnTop;
|
||||
negate = YES;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
<#signaturePlacementOnTop>
|
||||
|
||||
|
||||
<#signature/>
|
||||
</#signaturePlacementOnTop>
|
||||
<#outlookMode>-------- Original Message --------
|
||||
Subject: <#subject/>
|
||||
Date: <#date/>
|
||||
|
@ -8,4 +13,5 @@ From: <#from/>
|
|||
|
||||
<#messageBody/>
|
||||
|
||||
<#signature/>
|
||||
|
||||
<#signaturePlacementOnBottom><#signature/></#signaturePlacementOnBottom>
|
||||
|
|
|
@ -81,3 +81,21 @@ signature: WOString {
|
|||
value = signature;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
replyPlacementOnTop: WOConditional {
|
||||
condition = replyPlacementOnTop;
|
||||
}
|
||||
|
||||
replyPlacementOnBottom: WOConditional {
|
||||
condition = replyPlacementOnTop;
|
||||
negate = YES;
|
||||
}
|
||||
|
||||
signaturePlacementOnTop: WOConditional {
|
||||
condition = signaturePlacementOnTop;
|
||||
}
|
||||
|
||||
signaturePlacementOnBottom: WOConditional {
|
||||
condition = signaturePlacementOnTop;
|
||||
negate = YES;
|
||||
}
|
||||
|
|
|
@ -209,7 +209,7 @@
|
|||
"Operation failed" = "Operatie mislukt.";
|
||||
|
||||
"Quota" = "Quota";
|
||||
"quotasFormat" = "%{0} van %{1} KB gebruikt (%{2}%)";
|
||||
"quotasFormat" = "%{0}% van %{1} MB gebruikt";
|
||||
|
||||
"Please select a message." = "Selecteer een bericht.";
|
||||
"Please select a message to print." = "Selecteer een bericht om af te drukken.";
|
||||
|
|
|
@ -223,8 +223,8 @@
|
|||
= "Do you really want to move this folder into the trash ?";
|
||||
"Operation failed" = "Operation failed";
|
||||
|
||||
"Quota" = "Quota";
|
||||
"quotasFormat" = "%{0} used on %{1} Kb (%{2}%)";
|
||||
"Quota" = "Quota:";
|
||||
"quotasFormat" = "%{0}% used on %{1} MB";
|
||||
|
||||
"Please select a message." = "Please select a message.";
|
||||
"Please select a message to print." = "Please select a message to print.";
|
||||
|
|
|
@ -226,7 +226,7 @@
|
|||
"Operation failed" = "L'opération a échoué.";
|
||||
|
||||
"Quota" = "Quota";
|
||||
"quotasFormat" = "%{0} Ko utilisés sur %{1} (%{2}%)";
|
||||
"quotasFormat" = "%{0}% utilisé sur %{1} MO";
|
||||
|
||||
"Please select a message." = "Veuillez sélectionner un message.";
|
||||
"Please select a message to print." = "Veuillez sélectionner un message à imprimer.";
|
||||
|
|
|
@ -209,7 +209,7 @@
|
|||
"Operation failed" = "L'opération a échoué.";
|
||||
|
||||
"Quota" = "Quota";
|
||||
"quotasFormat" = "%{0} von %{1} KB verwendet (%{2}%)";
|
||||
"quotasFormat" = "%{0}% von %{1} MB verwendet";
|
||||
|
||||
"Please select a message." = "Sie müssen eine Nachricht auswählen.";
|
||||
"Please select a message to print." = "Sie müssen eine Nachricht zum Drucken auswählen.";
|
||||
|
|
|
@ -232,7 +232,7 @@
|
|||
"Operation failed" = "Operazione non riuscita";
|
||||
|
||||
"Quota" = "Spazio usato";
|
||||
"quotasFormat" = "%{0} su %{1} Kb (%{2}%)";
|
||||
"quotasFormat" = "%{0}% usato su %{1} MB";
|
||||
|
||||
"Please select a message." = "Per favore seleziona un messaggio.";
|
||||
"Please select a message to print." = "Per favore seleziona un messaggio da stampare.";
|
||||
|
|
|
@ -228,7 +228,7 @@
|
|||
"Operation failed" = "Operación fallida";
|
||||
|
||||
"Quota" = "Quotas";
|
||||
"quotasFormat" = "%{0} de %{1} Kb usados (%{2}%)";
|
||||
"quotasFormat" = "%{0}% de %{1} MB usados";
|
||||
|
||||
"Please select a message." = "Seleccione un mensaje primero.";
|
||||
"Please select a message to print." = "Seleccione el mensaje que desea imprimir.";
|
||||
|
|
|
@ -134,7 +134,7 @@
|
|||
NSString *inboxName;
|
||||
NSUserDefaults *ud;
|
||||
WOResponse *response;
|
||||
int quota;
|
||||
float quota;
|
||||
|
||||
ud = [NSUserDefaults standardUserDefaults];
|
||||
co = [self clientObject];
|
||||
|
@ -143,18 +143,21 @@
|
|||
folders = [self _jsonFolders: rawFolders];
|
||||
|
||||
// Retrieve INBOX quota
|
||||
quota = [ud integerForKey: @"SOGoSoftQuota"];
|
||||
quota = [ud floatForKey: @"SOGoSoftQuotaRatio"];
|
||||
inbox = [co inboxFolderInContext: context];
|
||||
inboxName = [NSString stringWithFormat: @"/%@", [inbox relativeImap4Name]];
|
||||
client = [[inbox imap4Connection] client];
|
||||
infos = [[client getQuotaRoot: [inbox relativeImap4Name]] objectForKey: @"quotas"];
|
||||
inboxQuota = [infos objectForKey: inboxName];
|
||||
if (quota > 0 && inboxQuota != nil)
|
||||
// A soft quota is imposed for all users
|
||||
inboxQuota = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithInt: quota], @"maxQuota",
|
||||
[inboxQuota objectForKey: @"usedSpace"], @"usedSpace",
|
||||
nil];
|
||||
if (quota != 0 && inboxQuota != nil)
|
||||
{
|
||||
// A soft quota ration is imposed for all users
|
||||
quota = quota * [(NSNumber*)[inboxQuota objectForKey: @"maxQuota"] intValue];
|
||||
inboxQuota = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithFloat: (long)(quota+0.5)], @"maxQuota",
|
||||
[inboxQuota objectForKey: @"usedSpace"], @"usedSpace",
|
||||
nil];
|
||||
}
|
||||
data = [NSDictionary dictionaryWithObjectsAndKeys: folders, @"mailboxes",
|
||||
inboxQuota, @"quotas",
|
||||
nil];
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
- (WOResponse *) renameFolderAction;
|
||||
- (WOResponse *) deleteFolderAction;
|
||||
- (WOResponse *) deleteMessagesAction;
|
||||
- (WOResponse *) saveMessagesAction;
|
||||
- (WOResponse *) expungeAction;
|
||||
- (WOResponse *) emptyTrashAction;
|
||||
- (WOResponse *) subscribeAction;
|
||||
|
|
|
@ -209,6 +209,33 @@
|
|||
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
|
||||
{
|
||||
SOGoMailFolder *co;
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
*/
|
||||
|
||||
#import <Foundation/NSEnumerator.h>
|
||||
#import <Foundation/NSUserDefaults.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
#import <NGCards/NGVCard.h>
|
||||
|
@ -150,8 +149,8 @@
|
|||
- (id <WOActionResults>) composeAction
|
||||
{
|
||||
id <SOGoContactObject> contact;
|
||||
NSArray *accounts, *contactsId;
|
||||
NSString *firstAccount, *newLocation, *parameters, *folderId, *uid, *email, *n;
|
||||
NSArray *accounts, *contactsId, *n;
|
||||
NSString *firstAccount, *newLocation, *parameters, *folderId, *uid, *email;
|
||||
NSMutableString *fn;
|
||||
NSEnumerator *uids;
|
||||
NSMutableArray *addresses;
|
||||
|
|
|
@ -141,6 +141,11 @@
|
|||
actionClass = "UIxMailFolderActions";
|
||||
actionName = "deleteMessages";
|
||||
};
|
||||
saveMessages = {
|
||||
protectedBy = "View";
|
||||
actionClass = "UIxMailFolderActions";
|
||||
actionName = "saveMessages";
|
||||
};
|
||||
setAsDraftsFolder = {
|
||||
protectedBy = "View";
|
||||
actionClass = "UIxMailFolderActions";
|
||||
|
|
|
@ -124,6 +124,7 @@
|
|||
<li><var:string label:value="Label"/></li>
|
||||
<li><var:string label:value="Mark"/></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..."/></li>
|
||||
<li><var:string label:value="Delete Selected Messages"/></li>
|
||||
|
@ -191,13 +192,6 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="quotaDialog" style="display: none;">
|
||||
<div>
|
||||
<h1><var:string label:value="Quota"/></h1>
|
||||
<p><!-- space --></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="leftPanel">
|
||||
<div class="titlediv"><var:string label:value="Folders" /></div>
|
||||
<div id="folderTreeContent"><!-- space --></div>
|
||||
|
|
|
@ -650,7 +650,7 @@ DIV.quota DIV.level
|
|||
background-position: 25% 0;
|
||||
border-left: 1px solid #999;
|
||||
border-right: 1px solid #999;
|
||||
height: 20px; }
|
||||
/*height: 20px;*/ }
|
||||
DIV.quota DIV.marks DIV
|
||||
{ float: left;
|
||||
margin: 0;
|
||||
|
@ -658,11 +658,11 @@ DIV.quota DIV.marks DIV
|
|||
width: 25%;
|
||||
border: 0;
|
||||
border-right: 1px solid #999;
|
||||
height: 5px; }
|
||||
height: 3px; }
|
||||
DIV.quota DIV.level DIV.value
|
||||
{ background-repeat: repeat-x;
|
||||
border-left: 1px solid transparent;
|
||||
height: 15px;
|
||||
height: 9px;
|
||||
margin: 0;
|
||||
position: relative; }
|
||||
DIV.quota DIV.level DIV.value.ok
|
||||
|
@ -671,6 +671,14 @@ DIV.quota DIV.level DIV.value.warn
|
|||
{ background-image: url(quota-level-warn.png); }
|
||||
DIV.quota DIV.level DIV.value.alert
|
||||
{ background-image: url(quota-level-alert.png); }
|
||||
DIV.quota DIV.level P
|
||||
{ margin: 0;
|
||||
padding: 0;
|
||||
clear: both;
|
||||
color: #555;
|
||||
font-size: 1em;
|
||||
text-align: center;
|
||||
}
|
||||
DIV#quotaDialog
|
||||
{ background-image: url("dialog-left.png");
|
||||
background-repeat: no-repeat;
|
||||
|
|
|
@ -1373,39 +1373,29 @@ function updateMailboxTreeInPage() {
|
|||
}
|
||||
}
|
||||
if (Mailer.quotas) {
|
||||
// Build quota indicator
|
||||
// Build quota indicator, show values in MB
|
||||
var percents = (Math.round(Mailer.quotas.usedSpace * 10000 / Mailer.quotas.maxQuota) / 100);
|
||||
var level = (percents > 85)? "alert" : (percents > 70)? "warn" : "ok";
|
||||
var format = labels["quotasFormat"];
|
||||
var text = format.formatted(Mailer.quotas.usedSpace, Mailer.quotas.maxQuota, percents);
|
||||
var text = format.formatted(percents,
|
||||
Math.round(Mailer.quotas.maxQuota/10.24)/100);
|
||||
var quotaDiv = new Element('div', { 'class': 'quota', 'info': text });
|
||||
var levelDiv = new Element('div', { 'class': 'level' });
|
||||
var valueDiv = new Element('div', { 'class': 'value ' + level, 'style': 'width: ' + ((percents > 100)?100:percents) + '%' });
|
||||
var marksDiv = new Element('div', { 'class': 'marks' });
|
||||
var textP = new Element('p').update(text);
|
||||
marksDiv.appendChild(new Element('div'));
|
||||
marksDiv.appendChild(new Element('div'));
|
||||
marksDiv.appendChild(new Element('div'));
|
||||
levelDiv.appendChild(valueDiv);
|
||||
levelDiv.appendChild(marksDiv);
|
||||
levelDiv.appendChild(textP);
|
||||
quotaDiv.appendChild(levelDiv);
|
||||
|
||||
treeContent.insertBefore(quotaDiv, tree);
|
||||
quotaDiv.observe("mouseover", onViewQuota);
|
||||
quotaDiv.observe("mouseout", function(event) { $("quotaDialog").hide(); });
|
||||
}
|
||||
}
|
||||
|
||||
function onViewQuota(event) {
|
||||
var div = $("quotaDialog");
|
||||
if (div.visible()) return;
|
||||
var position = this.cumulativeOffset();
|
||||
position[0] += this.getWidth();
|
||||
div.down("p").update(this.readAttribute("info"));
|
||||
div.setStyle({ left: position[0] + "px",
|
||||
top: position[1] + "px" });
|
||||
div.show();
|
||||
}
|
||||
|
||||
function mailboxMenuNode(type, name) {
|
||||
var newNode = document.createElement("li");
|
||||
var icon = MailerUIdTreeExtension.folderIcons[type];
|
||||
|
@ -1840,6 +1830,28 @@ function onLabelMenuPrepareVisibility() {
|
|||
lis[0].addClassName("_chosen");
|
||||
}
|
||||
|
||||
function saveAs(event) {
|
||||
var messageList = $("messageList").down("TBODY");
|
||||
var rows = messageList.getSelectedNodes();
|
||||
var uids = new Array(); // message IDs
|
||||
var paths = new Array(); // row IDs
|
||||
|
||||
if (rows.length > 0) {
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var uid = rows[i].readAttribute("id").substr(4);
|
||||
var path = Mailer.currentMailbox + "/" + uid;
|
||||
uids.push(uid);
|
||||
paths.push(path);
|
||||
}
|
||||
var url = ApplicationBaseURL + encodeURI(Mailer.currentMailbox) + "/saveMessages";
|
||||
window.open(url+"?id="+uids+"&uid="+uids+"&mailbox="+Mailer.currentMailbox+"&path="+paths);
|
||||
}
|
||||
else
|
||||
window.alert(labels["Please select a message."]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getMenus() {
|
||||
var menus = {}
|
||||
menus["accountIconMenu"] = new Array(null, null, onMenuCreateFolder, null,
|
||||
|
@ -1867,14 +1879,14 @@ function getMenus() {
|
|||
onMenuForwardMessage, null,
|
||||
"-", "moveMailboxMenu",
|
||||
"copyMailboxMenu", "label-menu",
|
||||
"mark-menu", "-", null,
|
||||
"mark-menu", "-", saveAs,
|
||||
onMenuViewMessageSource, null,
|
||||
null, onMenuDeleteMessage);
|
||||
menus["messagesListMenu"] = new Array(onMenuForwardMessage,
|
||||
"-", "moveMailboxMenu",
|
||||
"copyMailboxMenu", "label-menu",
|
||||
"mark-menu", "-",
|
||||
null, null,
|
||||
saveAs, null,
|
||||
onMenuDeleteMessage);
|
||||
menus["imageMenu"] = new Array(saveImage);
|
||||
menus["messageContentMenu"] = new Array(onMenuReplyToSender,
|
||||
|
@ -1884,7 +1896,7 @@ function getMenus() {
|
|||
"copyMailboxMenu",
|
||||
"-", "label-menu", "mark-menu",
|
||||
"-",
|
||||
null, onMenuViewMessageSource,
|
||||
saveAs, onMenuViewMessageSource,
|
||||
null, onPrintCurrentMessage,
|
||||
onMenuDeleteMessage);
|
||||
menus["folderTypeMenu"] = new Array(onMenuChangeToSentFolder,
|
||||
|
|
|
@ -539,7 +539,9 @@ function initMailEditor() {
|
|||
var sigLimit = textContent.lastIndexOf("--");
|
||||
if (sigLimit > -1)
|
||||
signatureLength = (textContent.length - sigLimit);
|
||||
textarea.scrollTop = textarea.scrollHeight;
|
||||
if ( userDefaults["ReplyPlacement"] != "above" ) {
|
||||
textarea.scrollTop = textarea.scrollHeight;
|
||||
}
|
||||
textarea.observe("focus", onTextFirstFocus);
|
||||
textarea.observe("focus", onTextFocus);
|
||||
// textarea.observe("contextmenu", onTextContextMenu);
|
||||
|
|
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 3.9 KiB |