+2004-10-03 Helge Hess <helge.hess@opengroupware.org>
+
+ * v0.9.20
+
+ * SOGoMailObject.m: added method to fetch parts
+
+ * SOGoMailManager.m: properly select folder prior fetch, added method
+ to fetch parts of a single (message) URL
+
2004-10-02 Helge Hess <helge.hess@opengroupware.org>
* SOGoMailFolder.[hm]: removed ability to restrict UID fetch range,
- (NSArray *)fetchUIDs:(NSArray *)_uids inURL:(NSURL *)_url
parts:(NSArray *)_parts password:(NSString *)_pwd;
+/* individual message */
+
+- (id)fetchURL:(NSURL *)_url parts:(NSArray *)_parts password:(NSString *)_pwd;
+
@end
#endif /* __Mailer_SOGoMailManager_H__ */
return @".";
}
-- (NSString *)imap4FolderNameForURL:(NSURL *)_url {
+- (NSString *)imap4FolderNameForURL:(NSURL *)_url removeFileName:(BOOL)_delfn {
/* a bit hackish, but should be OK */
NSString *folderName;
return nil;
if ([folderName characterAtIndex:0] == '/')
folderName = [folderName substringFromIndex:1];
+
+ if (_delfn) folderName = [folderName stringByDeletingLastPathComponent];
return [[folderName pathComponents] componentsJoinedByString:
[self imap4Separator]];
}
+- (NSString *)imap4FolderNameForURL:(NSURL *)_url {
+ return [self imap4FolderNameForURL:_url removeFileName:NO];
+}
- (NSArray *)extractSubfoldersForURL:(NSURL *)_url
fromResultSet:(NSDictionary *)_result
- (NSArray *)fetchUIDs:(NSArray *)_uids inURL:(NSURL *)_url
parts:(NSArray *)_parts password:(NSString *)_pwd
{
+ // currently returns a dict?!
/*
Allowed fetch keys:
UID
if (_uids == nil)
return nil;
if ([_uids count] == 0)
- return [NSArray array];
+ return nil; // TODO: might break empty folders?! return a dict!
if ((client = [self imap4ClientForURL:_url password:_pwd]) == nil)
return nil;
+ /* select folder */
+
+ result = [client select:[self imap4FolderNameForURL:_url]];
+ if (![[result valueForKey:@"result"] boolValue]) {
+ [self logWithFormat:@"ERROR: could not select URL: %@: %@", _url, result];
+ return nil;
+ }
+
+ /* fetch parts */
+
#warning TODO: split uids into batches, otherwise Cyrus will complain
// not really important because we batch before (in the sort)
// if the list is too long, we get a:
return (id)result;
}
+- (id)fetchURL:(NSURL *)_url parts:(NSArray *)_parts password:(NSString *)_pwd{
+ // currently returns a dict
+ NGImap4Client *client;
+ NSDictionary *result;
+ NSString *uid;
+
+ if (![_url isNotNull]) return nil;
+
+
+ if ((client = [self imap4ClientForURL:_url password:_pwd]) == nil)
+ return nil;
+
+ /* select folder */
+
+ result = [client select:[self imap4FolderNameForURL:_url
+ removeFileName:YES]];
+ if (![[result valueForKey:@"result"] boolValue]) {
+ [self logWithFormat:@"ERROR: could not select URL: %@: %@", _url, result];
+ return nil;
+ }
+
+ /* fetch parts */
+
+ uid = [[_url path] lastPathComponent];
+
+ result = [client fetchUids:[NSArray arrayWithObject:uid] parts:_parts];
+ if (![[result valueForKey:@"result"] boolValue]) {
+ [self logWithFormat:@"ERROR: could not fetch url: %@", _url];
+ return nil;
+ }
+ //[self logWithFormat:@"RESULT: %@", result];
+ return (id)result;
+}
+
/* debugging */
- (BOOL)isDebuggingEnabled {
{
}
+/* message */
+
+- (id)fetchParts:(NSArray *)_parts;
+
@end
#endif /* __Mailer_SOGoMailObject_H__ */
// $Id$
#include "SOGoMailObject.h"
+#include "SOGoMailManager.h"
#include "common.h"
@implementation SOGoMailObject
return [self nameInContainer];
}
+/* message */
+
+- (id)fetchParts:(NSArray *)_parts {
+ return [[self mailManager] fetchURL:[self imap4URL] parts:_parts
+ password:[self imap4Password]];
+}
+
@end /* SOGoMailObject */
# $Id$
-SUBMINOR_VERSION:=19
+SUBMINOR_VERSION:=20
2004-10-03 Helge Hess <helge.hess@opengroupware.org>
+ * work on viewer (v0.9.11)
+
* UIxMailMainFrame.wox: made toolbar floating (v0.9.10)
2004-10-02 Helge Hess <helge.hess@opengroupware.org>
MailerUI_OBJC_FILES += \
MailerUIProduct.m \
\
- UIxMailFormatter.m \
- UIxSubjectFormatter.m \
- WOContext+UIxMailer.m \
+ UIxMailFormatter.m \
+ UIxSubjectFormatter.m \
+ UIxEnvelopeAddressFormatter.m \
+ WOContext+UIxMailer.m \
\
UIxMailMainFrame.m \
UIxMailTree.m \
--- /dev/null
+/*
+ Copyright (C) 2004 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 "UIxMailFormatter.h"
+#include <NGImap4/NGImap4EnvelopeAddress.h>
+#include "common.h"
+
+@implementation UIxEnvelopeAddressFormatter
+
+static Class EnvAddrClass = Nil;
+static Class StrClass = Nil;
+
++ (void)initialize {
+ EnvAddrClass = [NGImap4EnvelopeAddress class];
+ StrClass = [NSString class];
+}
+
+- (id)initWithMaxLength:(unsigned int)_max generateFullEMail:(BOOL)_genFull {
+ if ((self = [super init])) {
+ self->maxLength = _max;
+ self->separator = @", ";
+
+ self->eafFlags.fullEMail = _genFull ? 1 : 0;
+ }
+ return self;
+}
+- (id)init {
+ return [self initWithMaxLength:128 generateFullEMail:NO];
+}
+
+/* configuration */
+
+- (unsigned)maxLength {
+ return self->maxLength;
+}
+- (NSString *)separator {
+ return self->separator;
+}
+- (BOOL)generateFullEMail {
+ return self->eafFlags.fullEMail ? YES : NO;
+}
+
+/* formatting envelope addresses */
+
+- (NSString *)stringForEnvelopeAddress:(NGImap4EnvelopeAddress *)_address {
+ NSString *s;
+
+ if ([self generateFullEMail])
+ return [_address email];
+
+ s = [_address personalName];
+ if ([s isNotNull]) return s;
+
+ s = [_address baseEMail];
+ if ([s isNotNull]) return s;
+
+ [self debugWithFormat:@"WARNING: unexpected envelope address: %@", _address];
+ return [_address stringValue];
+}
+
+- (NSString *)stringForArray:(NSArray *)_addresses {
+ NSMutableString *ms;
+ unsigned i, count;
+
+ if ((count = [_addresses count]) == 0)
+ return nil;
+
+ if (count == 1)
+ return [self stringForObjectValue:[_addresses objectAtIndex:0]];
+
+ ms = [NSMutableString stringWithCapacity:16 * count];
+ for (i = 0; i < count && [ms length] < [self maxLength]; i++) {
+ NSString *s;
+
+ s = [self stringForObjectValue:[_addresses objectAtIndex:i]];
+ if (s == nil)
+ continue;
+
+ if ([ms length] > 0) [ms appendString:[self separator]];
+ [ms appendString:s];
+ }
+ return ms;
+}
+
+/* formatter entry function */
+
+- (NSString *)stringForObjectValue:(id)_address {
+ if (![_address isNotNull])
+ return nil;
+
+ if ([_address isKindOfClass:StrClass]) /* preformatted? */
+ return _address;
+
+ if ([_address isKindOfClass:EnvAddrClass])
+ return [self stringForEnvelopeAddress:_address];
+
+ if ([_address isKindOfClass:[NSArray class]])
+ return [self stringForArray:_address];
+
+ [self debugWithFormat:
+ @"NOTE: unexpected object for envelope formatter: %@<%@>",
+ _address, NSStringFromClass([_address class])];
+ return [_address stringValue];
+}
+
+@end /* UIxEnvelopeAddressFormatter */
@end
@interface UIxEnvelopeAddressFormatter : UIxMailFormatter
+{
+ NSString *separator;
+ unsigned int maxLength;
+ struct {
+ int fullEMail:1;
+ int reserved:31;
+ } eafFlags;
+}
+
+- (id)initWithMaxLength:(unsigned int)_max generateFullEMail:(BOOL)_genFull;
+
@end
#endif /* __Mailer_UIxMailFormatter_H__ */
}
@end /* UIxMailDateFormatter */
-
-#include <NGImap4/NGImap4EnvelopeAddress.h>
-
-@implementation UIxEnvelopeAddressFormatter
-
-static Class EnvAddrClass = Nil;
-
-+ (void)initialize {
- if (EnvAddrClass == Nil) EnvAddrClass = [NGImap4EnvelopeAddress class];
-}
-
-/* configuration */
-
-- (unsigned)maxLength {
- return 128; // TODO
-}
-
-- (NSString *)separator {
- return @", ";
-}
-
-/* formatting envelope addresses */
-
-- (NSString *)stringForEnvelopeAddress:(NGImap4EnvelopeAddress *)_address {
- NSString *s;
-
- s = [_address personalName];
- if ([s isNotNull]) return s;
-
- s = [_address baseEMail];
- if ([s isNotNull]) return s;
-
- [self debugWithFormat:@"WARNING: unexpected envelope address: %@", _address];
- return [_address stringValue];
-}
-
-- (NSString *)stringForArray:(NSArray *)_addresses {
- NSMutableString *ms;
- unsigned i, count;
-
- if ((count = [_addresses count]) == 0)
- return nil;
-
- if (count == 1)
- return [self stringForObjectValue:[_addresses objectAtIndex:0]];
-
- ms = [NSMutableString stringWithCapacity:16 * count];
- for (i = 0; i < count && [ms length] < [self maxLength]; i++) {
- NSString *s;
-
- s = [self stringForObjectValue:[_addresses objectAtIndex:i]];
- if (s == nil)
- continue;
-
- if ([ms length] > 0) [ms appendString:[self separator]];
- [ms appendString:s];
- }
- return ms;
-}
-
-/* formatter entry function */
-
-- (NSString *)stringForObjectValue:(id)_address {
- if (![_address isNotNull])
- return nil;
-
- if ([_address isKindOfClass:StrClass]) /* preformatted? */
- return _address;
-
- if ([_address isKindOfClass:EnvAddrClass])
- return [self stringForEnvelopeAddress:_address];
-
- if ([_address isKindOfClass:[NSArray class]])
- return [self stringForArray:_address];
-
- [self debugWithFormat:
- @"NOTE: unexpected object for envelope formatter: %@<%@>",
- _address, NSStringFromClass([_address class])];
- return [_address stringValue];
-}
-
-@end /* UIxEnvelopeAddressFormatter */
@interface UIxMailView : UIxComponent
{
+ id message;
}
- (BOOL)isDeletableClientObject;
@end
#include <SoObjects/Mailer/SOGoMailObject.h>
+#include <NGImap4/NGImap4Envelope.h>
#include "common.h"
@implementation UIxMailView
+- (void)dealloc {
+ [self->message release];
+ [super dealloc];
+}
+
+/* notifications */
+
+- (void)sleep {
+ [self->message release]; self->message = nil;
+ [super sleep];
+}
+
+/* fetching */
+
+- (NSArray *)fetchKeys {
+ /* Note: see SOGoMailManager.m for allowed IMAP4 keys */
+ static NSArray *keys = nil;
+ if (keys == nil)
+ keys = [[NSArray alloc] initWithObjects:@"FLAGS", @"ENVELOPE", nil];
+ return keys;
+}
+
+- (id)message {
+ id msgs;
+
+ if (self->message != nil)
+ return [self->message isNotNull] ? self->message : nil;
+
+ msgs = [[self clientObject] fetchParts:[self fetchKeys]]; // returns dict
+ msgs = [msgs valueForKey:@"fetch"];
+ if ([msgs count] == 0)
+ return nil;
+ return [msgs objectAtIndex:0];
+}
+
+/* derived accessors */
+
+- (BOOL)hasCC {
+ return [[self valueForKeyPath:@"message.envelope.cc"] count] > 0 ? YES : NO;
+}
+
+/* actions */
+
+- (id)defaultAction {
+ if ([self message] == nil) {
+ return [NSException exceptionWithHTTPStatus:404 /* Not Found */
+ reason:@"did not find specified message!"];
+ }
+ return self;
+}
+
- (BOOL)isDeletableClientObject {
return [[self clientObject] respondsToSelector:@selector(delete)];
}
title="name"
const:hideFolderTree="1"
>
+ <!--
+ todo: we cannot make this static because the CC list has a dynamic height?
+ -->
<table class="mailer_fieldtable">
<tr class="mailer_fieldrow">
<td class="mailer_fieldname" ><var:string label:value="Subject"/>:</td>
- <td class="mailer_subjectfieldvalue">Re: Statuslist</td>
+ <td class="mailer_subjectfieldvalue">
+ <var:string value="message.envelope.subject"
+ formatter="context.mailSubjectFormatter"/>
+ </td>
</tr>
<tr class="mailer_fieldrow">
<td class="mailer_fieldname" ><var:string label:value="From"/>:</td>
<td class="mailer_fieldvalue">
<!-- compose link? -->
- <a href="#">Maxime Wacker [mwacker@linagora.com]</a>
+ <a href="#">
+ <var:string value="message.envelope.from"
+ formatter="context.mailEnvelopeFullAddressFormatter" /></a>
</td>
</tr>
<tr class="mailer_fieldrow">
<td class="mailer_fieldname" ><var:string label:value="Date"/>:</td>
- <td class="mailer_fieldvalue">08.09.2004 15:32</td>
+ <td class="mailer_fieldvalue">
+ <var:string value="message.envelope.date"
+ formatter="context.mailDateFormatter"/>
+ </td>
</tr>
+
<tr class="mailer_fieldrow">
<td class="mailer_fieldname" ><var:string label:value="To"/>:</td>
<td class="mailer_fieldvalue">
<!-- compose link? -->
- <a href="#">Helge Hess [helge.hess@skyrix.com]</a>
+ <var:foreach list="message.envelope.to" item="currentAddress">
+ <a href="#">
+ <var:string value="currentAddress"
+ formatter="context.mailEnvelopeFullAddressFormatter" /></a>
+ </var:foreach>
</td>
</tr>
+ <var:if condition="hasCC">
+ <tr class="mailer_fieldrow">
+ <td class="mailer_fieldname" ><var:string label:value="CC"/>:</td>
+ <td class="mailer_fieldvalue">
+ <!-- compose link? -->
+ <var:foreach list="message.envelope.cc" item="currentAddress">
+ <a href="#">
+ <var:string value="currentAddress"
+ formatter="context.mailEnvelopeFullAddressFormatter" /></a>
+ <br /> <!-- TODO: better to use li+CSS -->
+ </var:foreach>
+ </td>
+ </tr>
+ </var:if>
</table>
<div class="mailer_mailcontent">
- a b c<br />
+<!--
+ <pre><var:string value="message" /></pre><br />
+-->
<img rsrc:src="tbird_073_viewer.png" />
</div>
<!--
# $Id$
-SUBMINOR_VERSION:=10
+SUBMINOR_VERSION:=11
- (NSFormatter *)mailSubjectFormatter;
- (NSFormatter *)mailDateFormatter;
- (NSFormatter *)mailEnvelopeAddressFormatter;
+- (NSFormatter *)mailEnvelopeFullAddressFormatter;
@end
- (NSFormatter *)mailEnvelopeAddressFormatter {
return [[[UIxEnvelopeAddressFormatter alloc] init] autorelease];
}
+- (NSFormatter *)mailEnvelopeFullAddressFormatter {
+ return [[[UIxEnvelopeAddressFormatter alloc]
+ initWithMaxLength:256 generateFullEMail:YES] autorelease];
+}
@end /* WOContext(UIxMailer) */
font-family: Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
}
td.mailer_fieldname {
- padding-left: 24px;
- text-align: right;
- font-weight: bold;
+ padding-left: 24px;
+ text-align: right;
+ font-weight: bold;
+ vertical-align: top;
}
td.mailer_fieldvalue {
width: 95%;
}
td.mailer_fieldvalue a {
text-decoration: underline;
+ vertical-align: top;
}
div.mailer_mailcontent {
border-top-width: 1;
border-top-style: solid;
background-color: white;
+ padding: 8px;
}