2005-02-08 Helge Hess <helge.hess@opengroupware.org>
+ * v0.9.96
+
+ * UIxMailPartMessageViewer.m: fixed for multivalue from fields
+
+ * UIxMailEditorAction.m, product.plist: split editor action in multiple
+ classes
+
* v0.9.95
* product.plist: do not use clickedEditorDelete() JS function for
UIxMailEditor.m \
UIxMailEditorAttach.m \
UIxMailEditorAction.m \
+ UIxMailReplyAction.m \
+ UIxMailForwardAction.m \
UIxMailToSelection.m \
UIxMailAddressbook.m \
UIxMailWindowCloser.m \
--- /dev/null
+/*
+ Copyright (C) 2004-2005 SKYRIX Software AG
+
+ This file is part of OpenGroupware.org.
+
+ OGo is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ OGo 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 Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with OGo; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#ifndef __UIxMailEditorAction_H__
+#define __UIxMailEditorAction_H__
+
+#include <NGObjWeb/WODirectAction.h>
+
+/*
+ UIxMailEditorAction
+
+ This action implements the backend for the various buttons which invoke the
+ mail editor. The mail editor itself only works on a SOGoDraftObject which
+ needs to be created in advance.
+*/
+
+@class NSException;
+@class WOResponse;
+@class SOGoDraftObject, SOGoDraftsFolder;
+
+@interface UIxMailEditorAction : WODirectAction
+{
+ SOGoDraftObject *newDraft;
+}
+
+/* errors */
+
+- (id)didNotFindDraftsError;
+- (id)couldNotCreateDraftError:(SOGoDraftsFolder *)_draftsFolder;
+- (id)didNotFindMailError;
+
+/* creating new draft object */
+
+- (NSException *)_setupNewDraft;
+- (WOResponse *)redirectToEditNewDraft;
+
+/* state */
+
+- (void)reset;
+
+@end
+
+#endif /* __UIxMailEditorAction_H__ */
02111-1307, USA.
*/
-#include <NGObjWeb/WODirectAction.h>
-
-/*
- UIxMailEditorAction
-
- This action implements the backend for the various buttons which invoke the
- mail editor. The mail editor itself only works on a SOGoDraftObject which
- needs to be created in advance.
-*/
-
-@class SOGoDraftObject;
-
-@interface UIxMailEditorAction : WODirectAction
-{
- SOGoDraftObject *newDraft;
-}
-
-@end
+#include "UIxMailEditorAction.h"
#include <SOGo/SoObjects/Mailer/SOGoDraftsFolder.h>
#include <SOGo/SoObjects/Mailer/SOGoDraftObject.h>
#include <SOGo/SoObjects/Mailer/SOGoMailAccount.h>
#include <SOGo/SoObjects/Mailer/SOGoMailObject.h>
-#include <NGImap4/NGImap4EnvelopeAddress.h>
-#include <NGImap4/NGImap4Envelope.h>
#include "common.h"
@implementation UIxMailEditorAction
return r;
}
-/* reply */
-
-- (BOOL)hasReplyPrefix:(NSString *)_subject {
- static NSString *replyPrefixes[] = {
- @"Re:", // regular
- @"RE:", // Outlook v11 (English?)
- @"AW:", // German Outlook v11
- @"Re[", // numbered Re, eg "Re[2]:"
- nil
- };
- unsigned i;
- for (i = 0; replyPrefixes[i] != nil; i++) {
- if ([_subject hasPrefix:replyPrefixes[i]])
- return YES;
- }
- return NO;
-}
-
-- (NSString *)replySubject:(NSString *)_subject {
- if (![_subject isNotNull] || [_subject length] == 0)
- return _subject;
-
- if ([self hasReplyPrefix:_subject]) {
- /* do not do: "Re: Re: Re: My Mail" - a single Re is sufficient ;-) */
- return _subject;
- }
-
- return [@"Re: " stringByAppendingString:_subject];
-}
-
-- (void)addEMailsOfAddresses:(NSArray *)_addrs toArray:(NSMutableArray *)_ma {
- unsigned i, count;
-
- for (i = 0, count = [_addrs count]; i < count; i++)
- [_ma addObject:[(NGImap4EnvelopeAddress *)[_addrs objectAtIndex:i] email]];
-}
-
-- (void)fillInReplyAddresses:(NSMutableDictionary *)_info
- replyToAll:(BOOL)_replyToAll
- envelope:(NGImap4Envelope *)_envelope
-{
- /*
- The rules as implemented by Thunderbird:
- - if there is a 'reply-to' header, only include that (as TO)
- - if we reply to all, all non-from addresses are added as CC
- - the from is always the lone TO (except for reply-to)
-
- Note: we cannot check reply-to, because Cyrus even sets a reply-to in the
- envelope if none is contained in the message itself! (bug or
- feature?)
-
- TODO: what about sender (RFC 822 3.6.2)
- */
- NSMutableArray *to;
- NSArray *addrs;
-
- to = [NSMutableArray arrayWithCapacity:2];
-
- /* first check for "reply-to" */
-
- addrs = [_envelope replyTo];
- if ([addrs count] == 0) {
- /* no "reply-to", try "from" */
- addrs = [_envelope from];
- }
- [self addEMailsOfAddresses:addrs toArray:to];
- [_info setObject:to forKey:@"to"];
-
- /* CC processing if we reply-to-all: add all 'to' and 'cc' */
-
- if (_replyToAll) {
- to = [NSMutableArray arrayWithCapacity:8];
-
- [self addEMailsOfAddresses:[_envelope to] toArray:to];
- [self addEMailsOfAddresses:[_envelope cc] toArray:to];
-
- [_info setObject:to forKey:@"cc"];
- }
-}
-
-- (id)replyToAll:(BOOL)_replyToAll {
- NSMutableDictionary *info;
- NSException *error;
- id result;
- id tmp;
-
- /* ensure mail exists and is filled */
-
- // TODO: we could transport the body structure in a hidden field of the mail
- // viewer to avoid refetching the core-info?
- tmp = [[self clientObject] fetchCoreInfos];
- if ([tmp isKindOfClass:[NSException class]])
- return tmp;
- if (![tmp isNotNull])
- return [self didNotFindMailError];
-
- /* setup draft */
-
- if ((error = [self _setupNewDraft]) != nil)
- return error;
-
- /* fill draft info */
-
- info = [NSMutableDictionary dictionaryWithCapacity:16];
-
- [info setObject:[self replySubject:[[self clientObject] subject]]
- forKey:@"subject"];
- [self fillInReplyAddresses:info replyToAll:_replyToAll
- envelope:[[self clientObject] envelope]];
-
- /* fill content */
-
- // TODO: add quoted content
-
- /* save draft info */
-
- if ((error = [self->newDraft storeInfo:info]) != nil)
- return error;
-
- // TODO: we might want to pass the original URL to the editor for a final
- // redirect back to the message?
- result = [self redirectToEditNewDraft];
- [self reset];
- return result;
-}
-
-- (id)replyAction {
- return [self replyToAll:NO];
-}
-- (id)replyallAction {
- return [self replyToAll:YES];
-}
-
-/* forwarding */
-
-- (NSString *)getAttachmentNameForSubject:(NSString *)_subject {
- /* SOGoDraftObject disallows some strings - anything else required? */
- static NSString *sescape[] = {
- @"/", @"..", @"~", @"\"", @"'", @" ", @".", nil
- };
- static int maxFilenameLength = 64;
- NSString *s;
- unsigned i;
-
- if (![_subject isNotNull] || [_subject length] == 0)
- return _subject;
- s = _subject;
-
- if ([s length] > maxFilenameLength)
- s = [s substringToIndex:maxFilenameLength];
-
- for (i = 0; sescape[i] != nil; i++)
- s = [s stringByReplacingString:sescape[i] withString:@"_"];
-
- return [s stringByAppendingString:@".mail"];
-}
-
-- (NSString *)forwardSubject:(NSString *)_subject {
- if (![_subject isNotNull] || [_subject length] == 0)
- return _subject;
-
- /* Note: this is how Thunderbird 1.0 creates the subject */
- _subject = [@"[Fwd: " stringByAppendingString:_subject];
- _subject = [_subject stringByAppendingString:@"]"];
- return _subject;
-}
-
-- (id)forwardAction {
- NSException *error;
- NSData *content;
- NSDictionary *info;
- id result;
-
- /* fetch message */
-
- if ((content = [[self clientObject] content]) == nil)
- return [self didNotFindMailError];
- if ([content isKindOfClass:[NSException class]])
- return content;
-
- /* setup draft */
-
- if ((error = [self _setupNewDraft]) != nil)
- return error;
-
- /* set subject (do we need to set anything else?) */
-
- info = [NSDictionary dictionaryWithObjectsAndKeys:
- [self forwardSubject:[[self clientObject] subject]],
- @"subject",
- nil];
- if ((error = [self->newDraft storeInfo:info]) != nil)
- return error;
-
- /* attach message */
-
- // TODO: use subject for filename?
- error = [self->newDraft saveAttachment:content withName:@"forward.mail"];
- if (error != nil)
- return error;
-
- // TODO: we might want to pass the original URL to the editor for a final
- // redirect back to the message?
- result = [self redirectToEditNewDraft];
- [self reset];
- return result;
-}
-
@end /* UIxMailEditorAction */
--- /dev/null
+/*
+ Copyright (C) 2004-2005 SKYRIX Software AG
+
+ This file is part of OpenGroupware.org.
+
+ OGo is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ OGo 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 Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with OGo; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#include "UIxMailEditorAction.h"
+
+@interface UIxMailForwardAction : UIxMailEditorAction
+@end
+
+#include <SOGo/SoObjects/Mailer/SOGoMailObject.h>
+#include <SOGo/SoObjects/Mailer/SOGoDraftObject.h>
+#include "common.h"
+
+@implementation UIxMailForwardAction
+
+- (NSString *)getAttachmentNameForSubject:(NSString *)_subject {
+ /* SOGoDraftObject disallows some strings - anything else required? */
+ static NSString *sescape[] = {
+ @"/", @"..", @"~", @"\"", @"'", @" ", @".", nil
+ };
+ static int maxFilenameLength = 64;
+ NSString *s;
+ unsigned i;
+
+ if (![_subject isNotNull] || [_subject length] == 0)
+ return _subject;
+ s = _subject;
+
+ if ([s length] > maxFilenameLength)
+ s = [s substringToIndex:maxFilenameLength];
+
+ for (i = 0; sescape[i] != nil; i++)
+ s = [s stringByReplacingString:sescape[i] withString:@"_"];
+
+ return [s stringByAppendingString:@".mail"];
+}
+
+- (NSString *)forwardSubject:(NSString *)_subject {
+ if (![_subject isNotNull] || [_subject length] == 0)
+ return _subject;
+
+ /* Note: this is how Thunderbird 1.0 creates the subject */
+ _subject = [@"[Fwd: " stringByAppendingString:_subject];
+ _subject = [_subject stringByAppendingString:@"]"];
+ return _subject;
+}
+
+- (id)forwardAction {
+ NSException *error;
+ NSData *content;
+ NSDictionary *info;
+ id result;
+
+ /* fetch message */
+
+ if ((content = [[self clientObject] content]) == nil)
+ return [self didNotFindMailError];
+ if ([content isKindOfClass:[NSException class]])
+ return content;
+
+ /* setup draft */
+
+ if ((error = [self _setupNewDraft]) != nil)
+ return error;
+
+ /* set subject (do we need to set anything else?) */
+
+ info = [NSDictionary dictionaryWithObjectsAndKeys:
+ [self forwardSubject:[[self clientObject] subject]],
+ @"subject",
+ nil];
+ if ((error = [self->newDraft storeInfo:info]) != nil)
+ return error;
+
+ /* attach message */
+
+ // TODO: use subject for filename?
+ error = [self->newDraft saveAttachment:content withName:@"forward.mail"];
+ if (error != nil)
+ return error;
+
+ // TODO: we might want to pass the original URL to the editor for a final
+ // redirect back to the message?
+ result = [self redirectToEditNewDraft];
+ [self reset];
+ return result;
+}
+
+@end /* UIxMailForwardAction */
return [@"mailto:" stringByAppendingString:[_address baseEMail]];
}
-- (NSString *)fromLink {
- return [self linkToEnvelopeAddress:[[self envelope] from]];
-}
- (NSString *)currentAddressLink {
return [self linkToEnvelopeAddress:[self currentAddress]];
}
<td class="mailer_fieldname" ><var:string label:value="From"/>:</td>
<td class="mailer_fieldvalue">
<!-- compose link? -->
- <a var:href="fromLink">
- <var:string value="envelope.from"
- formatter="context.mailEnvelopeFullAddressFormatter" /></a>
+ <var:foreach list="envelope.from" item="currentAddress">
+ <a var:href="currentAddressLink">
+ <var:string value="currentAddress"
+ formatter="context.mailEnvelopeFullAddressFormatter" /></a>
+ </var:foreach>
</td>
</tr>
<tr class="mailer_fieldrow">
--- /dev/null
+/*
+ Copyright (C) 2004-2005 SKYRIX Software AG
+
+ This file is part of OpenGroupware.org.
+
+ OGo is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ OGo 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 Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with OGo; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#include "UIxMailEditorAction.h"
+
+@interface UIxMailReplyAction : UIxMailEditorAction
+@end
+
+#include <SOGo/SoObjects/Mailer/SOGoMailObject.h>
+#include <SOGo/SoObjects/Mailer/SOGoDraftObject.h>
+#include <NGImap4/NGImap4EnvelopeAddress.h>
+#include <NGImap4/NGImap4Envelope.h>
+#include "common.h"
+
+@implementation UIxMailReplyAction
+
+- (BOOL)hasReplyPrefix:(NSString *)_subject {
+ static NSString *replyPrefixes[] = {
+ @"Re:", // regular
+ @"RE:", // Outlook v11 (English?)
+ @"AW:", // German Outlook v11
+ @"Re[", // numbered Re, eg "Re[2]:"
+ nil
+ };
+ unsigned i;
+ for (i = 0; replyPrefixes[i] != nil; i++) {
+ if ([_subject hasPrefix:replyPrefixes[i]])
+ return YES;
+ }
+ return NO;
+}
+
+- (NSString *)replySubject:(NSString *)_subject {
+ if (![_subject isNotNull] || [_subject length] == 0)
+ return _subject;
+
+ if ([self hasReplyPrefix:_subject]) {
+ /* do not do: "Re: Re: Re: My Mail" - a single Re is sufficient ;-) */
+ return _subject;
+ }
+
+ return [@"Re: " stringByAppendingString:_subject];
+}
+
+- (void)addEMailsOfAddresses:(NSArray *)_addrs toArray:(NSMutableArray *)_ma {
+ unsigned i, count;
+
+ for (i = 0, count = [_addrs count]; i < count; i++)
+ [_ma addObject:[(NGImap4EnvelopeAddress *)[_addrs objectAtIndex:i] email]];
+}
+
+- (void)fillInReplyAddresses:(NSMutableDictionary *)_info
+ replyToAll:(BOOL)_replyToAll
+ envelope:(NGImap4Envelope *)_envelope
+{
+ /*
+ The rules as implemented by Thunderbird:
+ - if there is a 'reply-to' header, only include that (as TO)
+ - if we reply to all, all non-from addresses are added as CC
+ - the from is always the lone TO (except for reply-to)
+
+ Note: we cannot check reply-to, because Cyrus even sets a reply-to in the
+ envelope if none is contained in the message itself! (bug or
+ feature?)
+
+ TODO: what about sender (RFC 822 3.6.2)
+ */
+ NSMutableArray *to;
+ NSArray *addrs;
+
+ to = [NSMutableArray arrayWithCapacity:2];
+
+ /* first check for "reply-to" */
+
+ addrs = [_envelope replyTo];
+ if ([addrs count] == 0) {
+ /* no "reply-to", try "from" */
+ addrs = [_envelope from];
+ }
+ [self addEMailsOfAddresses:addrs toArray:to];
+ [_info setObject:to forKey:@"to"];
+
+ /* CC processing if we reply-to-all: add all 'to' and 'cc' */
+
+ if (_replyToAll) {
+ to = [NSMutableArray arrayWithCapacity:8];
+
+ [self addEMailsOfAddresses:[_envelope to] toArray:to];
+ [self addEMailsOfAddresses:[_envelope cc] toArray:to];
+
+ [_info setObject:to forKey:@"cc"];
+ }
+}
+
+- (NSString *)contentForReply {
+ // TODO: add quoted content
+ [self logWithFormat:@"keys: %@",
+ [[self clientObject] plainTextContentFetchKeys]];
+ [self logWithFormat:@"texts: %@", [[self clientObject] fetchPlainTextParts]];
+ return nil;
+}
+
+- (id)replyToAll:(BOOL)_replyToAll {
+ NSMutableDictionary *info;
+ NSException *error;
+ id result;
+ id tmp;
+
+ /* ensure mail exists and is filled */
+
+ // TODO: we could transport the body structure in a hidden field of the mail
+ // viewer to avoid refetching the core-info?
+ tmp = [[self clientObject] fetchCoreInfos];
+ if ([tmp isKindOfClass:[NSException class]])
+ return tmp;
+ if (![tmp isNotNull])
+ return [self didNotFindMailError];
+
+ /* setup draft */
+
+ if ((error = [self _setupNewDraft]) != nil)
+ return error;
+
+ /* fill draft info */
+
+ info = [NSMutableDictionary dictionaryWithCapacity:16];
+
+ [info setObject:[self replySubject:[[self clientObject] subject]]
+ forKey:@"subject"];
+ [self fillInReplyAddresses:info replyToAll:_replyToAll
+ envelope:[[self clientObject] envelope]];
+
+ /* fill in text content */
+
+ if ((tmp = [self contentForReply]) != nil)
+ [info setObject:tmp forKey:@"text"];
+
+ /* save draft info */
+
+ if ((error = [self->newDraft storeInfo:info]) != nil)
+ return error;
+
+ // TODO: we might want to pass the original URL to the editor for a final
+ // redirect back to the message?
+ result = [self redirectToEditNewDraft];
+ [self reset];
+ return result;
+}
+
+- (id)replyAction {
+ return [self replyToAll:NO];
+}
+- (id)replyallAction {
+ return [self replyToAll:YES];
+}
+
+@end /* UIxMailReplyAction */
# version file
-SUBMINOR_VERSION:=95
+SUBMINOR_VERSION:=96
# v0.9.94 requires SoObjects/Mailer v0.9.69
# v0.9.94 requires libNGMime v4.5.210
else
return false;
}
+
+/* main window */
+
+function reopenToRemoveLocationBar() {
+ if (window.locationbar && window.locationbar.visible) {
+ newwin = window.open(window.location.href, "SOGo",
+ "width=800,height=600,resizable=1,scrollbars=1," +
+ "toolbar=0,location=0,directories=0,status=0," +
+ "menubar=0,copyhistory=0");
+ if (newwin) {
+ window.close(); // this does only work for windows opened by scripts!
+ newwin.focus();
+ return true;
+ }
+ return false;
+ }
+ return true;
+}
};
reply = {
protectedBy = "View";
- actionClass = "UIxMailEditorAction";
+ actionClass = "UIxMailReplyAction";
actionName = "reply";
};
replyall = {
protectedBy = "View";
- actionClass = "UIxMailEditorAction";
+ actionClass = "UIxMailReplyAction";
actionName = "replyall";
};
forward = {
protectedBy = "View";
- actionClass = "UIxMailEditorAction";
+ actionClass = "UIxMailForwardAction";
actionName = "forward";
};
};