diff --git a/ChangeLog b/ChangeLog index cdc020393..8f78ab9b9 100644 --- a/ChangeLog +++ b/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 + + * 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 - * 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 - * 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 * 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 @@ -2141,32 +2155,32 @@ 2007-11-25 Ludovic Marcotte - * 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 - * SoObjects/Mailer/SOGoMailBaseObject.m + * SoObjects/Mailer/SOGoMailBaseObject.m Fixed typo. * SoObjects/Mailer/SOGoMailBodyPart.m @@ -2455,27 +2469,27 @@ 2007-11-15 Ludovic Marcotte - * 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 @@ -3118,10 +3132,10 @@ 2007-10-10 Ludovic Marcotte * 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 @@ -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
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 * 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 @@ -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 diff --git a/NEWS b/NEWS index 9cb7d59c9..27425c856 100644 --- a/NEWS +++ b/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 diff --git a/SoObjects/Mailer/SOGoDraftsFolder.m b/SoObjects/Mailer/SOGoDraftsFolder.m index f305c2169..47078e920 100644 --- a/SoObjects/Mailer/SOGoDraftsFolder.m +++ b/SoObjects/Mailer/SOGoDraftsFolder.m @@ -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 diff --git a/SoObjects/Mailer/SOGoMailDutchReply.wo/SOGoMailDutchReply.html b/SoObjects/Mailer/SOGoMailDutchReply.wo/SOGoMailDutchReply.html index 7d34187be..e4e5dc000 100644 --- a/SoObjects/Mailer/SOGoMailDutchReply.wo/SOGoMailDutchReply.html +++ b/SoObjects/Mailer/SOGoMailDutchReply.wo/SOGoMailDutchReply.html @@ -1,3 +1,8 @@ +<#signaturePlacementOnTop> + + +<#signature/> + <#outlookMode>-------- Original Message -------- Subject: <#subject/> Date: <#date/> @@ -8,4 +13,5 @@ From: <#from/> <#messageBody/> -<#signature/> + +<#signaturePlacementOnBottom><#signature/> diff --git a/SoObjects/Mailer/SOGoMailDutchReply.wo/SOGoMailDutchReply.wod b/SoObjects/Mailer/SOGoMailDutchReply.wo/SOGoMailDutchReply.wod index 0df01066f..df3789cc3 100644 --- a/SoObjects/Mailer/SOGoMailDutchReply.wo/SOGoMailDutchReply.wod +++ b/SoObjects/Mailer/SOGoMailDutchReply.wo/SOGoMailDutchReply.wod @@ -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; +} diff --git a/SoObjects/Mailer/SOGoMailFolder.h b/SoObjects/Mailer/SOGoMailFolder.h index 839a36084..eba89a3fa 100644 --- a/SoObjects/Mailer/SOGoMailFolder.h +++ b/SoObjects/Mailer/SOGoMailFolder.h @@ -24,6 +24,7 @@ #include #import +#import /* 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 diff --git a/SoObjects/Mailer/SOGoMailFolder.m b/SoObjects/Mailer/SOGoMailFolder.m index 6925e92d5..a462d3b90 100644 --- a/SoObjects/Mailer/SOGoMailFolder.m +++ b/SoObjects/Mailer/SOGoMailFolder.m @@ -23,13 +23,16 @@ #import #import #import +#import #import #import +#import #import #import #import #import +#import #import #import @@ -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 diff --git a/SoObjects/Mailer/SOGoMailFrenchReply.wo/SOGoMailFrenchReply.html b/SoObjects/Mailer/SOGoMailFrenchReply.wo/SOGoMailFrenchReply.html index 660cd3213..177f36d57 100644 --- a/SoObjects/Mailer/SOGoMailFrenchReply.wo/SOGoMailFrenchReply.html +++ b/SoObjects/Mailer/SOGoMailFrenchReply.wo/SOGoMailFrenchReply.html @@ -1,3 +1,8 @@ +<#signaturePlacementOnTop> + + +<#signature/> + <#outlookMode>-------- Message original -------- Sujet: <#subject/> Date: <#date/> @@ -8,4 +13,5 @@ De: <#from/> <#messageBody/> -<#signature/> + +<#signaturePlacementOnBottom><#signature/> diff --git a/SoObjects/Mailer/SOGoMailFrenchReply.wo/SOGoMailFrenchReply.wod b/SoObjects/Mailer/SOGoMailFrenchReply.wo/SOGoMailFrenchReply.wod index 0df01066f..df3789cc3 100644 --- a/SoObjects/Mailer/SOGoMailFrenchReply.wo/SOGoMailFrenchReply.wod +++ b/SoObjects/Mailer/SOGoMailFrenchReply.wo/SOGoMailFrenchReply.wod @@ -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; +} diff --git a/SoObjects/Mailer/SOGoMailGermanReply.wo/SOGoMailGermanReply.html b/SoObjects/Mailer/SOGoMailGermanReply.wo/SOGoMailGermanReply.html index e22ebbc1b..205145b8d 100644 --- a/SoObjects/Mailer/SOGoMailGermanReply.wo/SOGoMailGermanReply.html +++ b/SoObjects/Mailer/SOGoMailGermanReply.wo/SOGoMailGermanReply.html @@ -1,3 +1,8 @@ +<#signaturePlacementOnTop> + + +<#signature/> + <#outlookMode>-------- Original E-Mail -------- Betreff: <#subject/> Datum: <#date/> @@ -8,4 +13,5 @@ Sender: <#from/> <#messageBody/> -<#signature/> + +<#signaturePlacementOnBottom><#signature/> diff --git a/SoObjects/Mailer/SOGoMailGermanReply.wo/SOGoMailGermanReply.wod b/SoObjects/Mailer/SOGoMailGermanReply.wo/SOGoMailGermanReply.wod index 0df01066f..df3789cc3 100644 --- a/SoObjects/Mailer/SOGoMailGermanReply.wo/SOGoMailGermanReply.wod +++ b/SoObjects/Mailer/SOGoMailGermanReply.wo/SOGoMailGermanReply.wod @@ -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; +} diff --git a/SoObjects/Mailer/SOGoMailItalianReply.wo/SOGoMailItalianReply.html b/SoObjects/Mailer/SOGoMailItalianReply.wo/SOGoMailItalianReply.html index e5e96b359..2265ebb3c 100644 --- a/SoObjects/Mailer/SOGoMailItalianReply.wo/SOGoMailItalianReply.html +++ b/SoObjects/Mailer/SOGoMailItalianReply.wo/SOGoMailItalianReply.html @@ -1,3 +1,8 @@ +<#signaturePlacementOnTop> + + +<#signature/> + <#outlookMode>-------- Messaggio originale -------- Oggetto: <#subject/> Data: <#date/> @@ -8,4 +13,5 @@ Da: <#from/> <#messageBody/> -<#signature/> + +<#signaturePlacementOnBottom><#signature/> diff --git a/SoObjects/Mailer/SOGoMailItalianReply.wo/SOGoMailItalianReply.wod b/SoObjects/Mailer/SOGoMailItalianReply.wo/SOGoMailItalianReply.wod index 0df01066f..df3789cc3 100644 --- a/SoObjects/Mailer/SOGoMailItalianReply.wo/SOGoMailItalianReply.wod +++ b/SoObjects/Mailer/SOGoMailItalianReply.wo/SOGoMailItalianReply.wod @@ -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; +} diff --git a/SoObjects/Mailer/SOGoMailSpanishReply.wo/SOGoMailSpanishReply.html b/SoObjects/Mailer/SOGoMailSpanishReply.wo/SOGoMailSpanishReply.html index 7d34187be..e4e5dc000 100644 --- a/SoObjects/Mailer/SOGoMailSpanishReply.wo/SOGoMailSpanishReply.html +++ b/SoObjects/Mailer/SOGoMailSpanishReply.wo/SOGoMailSpanishReply.html @@ -1,3 +1,8 @@ +<#signaturePlacementOnTop> + + +<#signature/> + <#outlookMode>-------- Original Message -------- Subject: <#subject/> Date: <#date/> @@ -8,4 +13,5 @@ From: <#from/> <#messageBody/> -<#signature/> + +<#signaturePlacementOnBottom><#signature/> diff --git a/SoObjects/Mailer/SOGoMailSpanishReply.wo/SOGoMailSpanishReply.wod b/SoObjects/Mailer/SOGoMailSpanishReply.wo/SOGoMailSpanishReply.wod index 0df01066f..df3789cc3 100644 --- a/SoObjects/Mailer/SOGoMailSpanishReply.wo/SOGoMailSpanishReply.wod +++ b/SoObjects/Mailer/SOGoMailSpanishReply.wo/SOGoMailSpanishReply.wod @@ -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; +} diff --git a/UI/MailerUI/Dutch.lproj/Localizable.strings b/UI/MailerUI/Dutch.lproj/Localizable.strings index 99523d1f2..5f5fa7321 100644 --- a/UI/MailerUI/Dutch.lproj/Localizable.strings +++ b/UI/MailerUI/Dutch.lproj/Localizable.strings @@ -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."; diff --git a/UI/MailerUI/English.lproj/Localizable.strings b/UI/MailerUI/English.lproj/Localizable.strings index 3c9524724..f14b4ffe4 100644 --- a/UI/MailerUI/English.lproj/Localizable.strings +++ b/UI/MailerUI/English.lproj/Localizable.strings @@ -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."; diff --git a/UI/MailerUI/French.lproj/Localizable.strings b/UI/MailerUI/French.lproj/Localizable.strings index 6c703ebae..ab6509f37 100644 --- a/UI/MailerUI/French.lproj/Localizable.strings +++ b/UI/MailerUI/French.lproj/Localizable.strings @@ -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."; diff --git a/UI/MailerUI/German.lproj/Localizable.strings b/UI/MailerUI/German.lproj/Localizable.strings index 0a8e7c831..2a3a80758 100644 --- a/UI/MailerUI/German.lproj/Localizable.strings +++ b/UI/MailerUI/German.lproj/Localizable.strings @@ -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."; diff --git a/UI/MailerUI/Italian.lproj/Localizable.strings b/UI/MailerUI/Italian.lproj/Localizable.strings index ed874dd86..42429d1ca 100644 --- a/UI/MailerUI/Italian.lproj/Localizable.strings +++ b/UI/MailerUI/Italian.lproj/Localizable.strings @@ -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."; diff --git a/UI/MailerUI/Spanish.lproj/Localizable.strings b/UI/MailerUI/Spanish.lproj/Localizable.strings index b772b231a..5d93b8658 100644 --- a/UI/MailerUI/Spanish.lproj/Localizable.strings +++ b/UI/MailerUI/Spanish.lproj/Localizable.strings @@ -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."; diff --git a/UI/MailerUI/UIxMailAccountActions.m b/UI/MailerUI/UIxMailAccountActions.m index ffbd1a6b8..2b56ba1c5 100644 --- a/UI/MailerUI/UIxMailAccountActions.m +++ b/UI/MailerUI/UIxMailAccountActions.m @@ -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]; diff --git a/UI/MailerUI/UIxMailFolderActions.h b/UI/MailerUI/UIxMailFolderActions.h index 51e3dc669..594bff8c9 100644 --- a/UI/MailerUI/UIxMailFolderActions.h +++ b/UI/MailerUI/UIxMailFolderActions.h @@ -33,6 +33,7 @@ - (WOResponse *) renameFolderAction; - (WOResponse *) deleteFolderAction; - (WOResponse *) deleteMessagesAction; +- (WOResponse *) saveMessagesAction; - (WOResponse *) expungeAction; - (WOResponse *) emptyTrashAction; - (WOResponse *) subscribeAction; diff --git a/UI/MailerUI/UIxMailFolderActions.m b/UI/MailerUI/UIxMailFolderActions.m index 6e7f2b020..c7237b0d5 100644 --- a/UI/MailerUI/UIxMailFolderActions.m +++ b/UI/MailerUI/UIxMailFolderActions.m @@ -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; diff --git a/UI/MailerUI/UIxMailMainFrame.m b/UI/MailerUI/UIxMailMainFrame.m index b0956fdf9..65ad37976 100644 --- a/UI/MailerUI/UIxMailMainFrame.m +++ b/UI/MailerUI/UIxMailMainFrame.m @@ -20,7 +20,6 @@ */ #import -#import #import #import @@ -150,8 +149,8 @@ - (id ) composeAction { id 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; diff --git a/UI/MailerUI/product.plist b/UI/MailerUI/product.plist index 0bc397b63..f759eea14 100644 --- a/UI/MailerUI/product.plist +++ b/UI/MailerUI/product.plist @@ -141,6 +141,11 @@ actionClass = "UIxMailFolderActions"; actionName = "deleteMessages"; }; + saveMessages = { + protectedBy = "View"; + actionClass = "UIxMailFolderActions"; + actionName = "saveMessages"; + }; setAsDraftsFolder = { protectedBy = "View"; actionClass = "UIxMailFolderActions"; diff --git a/UI/Templates/MailerUI/UIxMailMainFrame.wox b/UI/Templates/MailerUI/UIxMailMainFrame.wox index 96dc58464..63f5c1cb7 100644 --- a/UI/Templates/MailerUI/UIxMailMainFrame.wox +++ b/UI/Templates/MailerUI/UIxMailMainFrame.wox @@ -124,6 +124,7 @@
  • +
  • @@ -191,13 +192,6 @@ - -
    diff --git a/UI/WebServerResources/MailerUI.css b/UI/WebServerResources/MailerUI.css index 0e8713c9b..0a098da8f 100644 --- a/UI/WebServerResources/MailerUI.css +++ b/UI/WebServerResources/MailerUI.css @@ -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 @@ -670,7 +670,15 @@ DIV.quota DIV.level DIV.value.ok 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); } +{ 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; diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index c0d4cce51..e936a49d8 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -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, diff --git a/UI/WebServerResources/UIxMailEditor.js b/UI/WebServerResources/UIxMailEditor.js index c11fdbda4..8080c1340 100644 --- a/UI/WebServerResources/UIxMailEditor.js +++ b/UI/WebServerResources/UIxMailEditor.js @@ -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); diff --git a/UI/WebServerResources/quota-level-alert.png b/UI/WebServerResources/quota-level-alert.png index 4383a2844..5ac2167b7 100644 Binary files a/UI/WebServerResources/quota-level-alert.png and b/UI/WebServerResources/quota-level-alert.png differ diff --git a/UI/WebServerResources/quota-level-ok.png b/UI/WebServerResources/quota-level-ok.png index 8e538c906..b9ae3ae38 100644 Binary files a/UI/WebServerResources/quota-level-ok.png and b/UI/WebServerResources/quota-level-ok.png differ diff --git a/UI/WebServerResources/quota-level-warn.png b/UI/WebServerResources/quota-level-warn.png index 2b0712fc2..793091a8b 100644 Binary files a/UI/WebServerResources/quota-level-warn.png and b/UI/WebServerResources/quota-level-warn.png differ diff --git a/UI/WebServerResources/quota-level.png b/UI/WebServerResources/quota-level.png index 77b723774..c242fbb8e 100644 Binary files a/UI/WebServerResources/quota-level.png and b/UI/WebServerResources/quota-level.png differ