+2005-01-28 Helge Hess <helge.hess@skyrix.com>
+
+ * v0.9.57
+
+ * SOGoMailBodyPart.m: enhanced lookup to allow for arbitary filenames
+ being attached to a body-part name. Improves download behaviour.
+
+ * SOGoMailBaseObject.m, SOGoMailObject.m: moved
+ -isBodyPartKey:inContext: method to base object for reuse in
+ SOGoMailBodyPart
+
+ * SOGoMailBodyPart.m: minor code cleanup
+
2005-01-26 Helge Hess <helge.hess@skyrix.com>
* v0.9.56
[self errorWithFormat:@"missing login in account folder name: %@", s];
return nil;
}
-
+ if ([s hasSuffix:@":80"]) { // HACK
+ [self logWithFormat:@"WARNING: incorrect value for IMAP4 URL: '%@'", s];
+ s = [s substringToIndex:([s length] - 3)];
+ }
+
s = [([self useSSL] ? @"imaps://" : @"imap://") stringByAppendingString:s];
s = [s stringByAppendingString:@"/"];
SOGoMailBaseObject
Common base class for mailer SoObjects.
+
+ Subclasses:
+ SOGoDraftObject
+ SOGoDraftsFolder
+ SOGoMailAccount
+ SOGoMailBodyPart
+ SOGoMailFolder
+ SOGoMailObject
*/
@class NSString, NSArray, NSURL;
- (void)flushMailCaches;
+/* IMAP4 names */
+
+- (BOOL)isBodyPartKey:(NSString *)_key inContext:(id)_ctx;
+
@end
#endif /* __Mailer_SOGoMailBaseObject_H__ */
[[self mailManager] flushCachesForURL:[self imap4URL]];
}
+/* IMAP4 names */
+
+- (BOOL)isBodyPartKey:(NSString *)_key inContext:(id)_ctx {
+ /*
+ Every key starting with a digit is consider an IMAP4 mime part key, used in
+ SOGoMailObject and SOGoMailBodyPart.
+ */
+ if ([_key length] == 0)
+ return NO;
+
+ if (isdigit([_key characterAtIndex:0]))
+ return YES;
+
+ return NO;
+}
+
/* debugging */
- (NSString *)loggingPrefix {
/*
- Copyright (C) 2004 SKYRIX Software AG
+ Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
SOGoMailBodyPart
Parent object: SOGoMailObject or SOGoMailBodyPart
Child objects: SOGoMailBodyPart's
-
+
Represents a MIME part of a mail as retrieved using IMAP4 body structure
commands in NGImap4.
*/
/*
- Copyright (C) 2004 SKYRIX Software AG
+ Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
/* lookup body part */
- if ((obj = [self lookupImap4BodyPartKey:_key inContext:_ctx]) != nil)
- return obj;
+ if ([self isBodyPartKey:_key inContext:_ctx]) {
+ if ((obj = [self lookupImap4BodyPartKey:_key inContext:_ctx]) != nil)
+ return obj;
+ }
+
+ /*
+ Treat other keys which have a path-extension as 'virtual' noops to allow
+ addition of path names to the attachment path, eg:
+ http://.../login@server/INBOX/1/2/3/MyDocument.pdf
+ */
+ if ([[_key pathExtension] length] > 0)
+ return self;
/* return 404 to stop acquisition */
return [NSException exceptionWithHTTPStatus:404 /* Not Found */];
mt = [_info valueForKey:@"type"]; if (![mt isNotNull]) return nil;
st = [_info valueForKey:@"subtype"]; if (![st isNotNull]) return nil;
-
+
type = [NSMutableString stringWithCapacity:16];
- [type appendString:mt];
+ [type appendString:[mt lowercaseString]];
[type appendString:@"/"];
- [type appendString:st];
+ [type appendString:[st lowercaseString]];
parameters = [_info valueForKey:@"parameterList"];
ke = [parameters keyEnumerator];
- while ((pn = [ke nextObject])) {
+ while ((pn = [ke nextObject]) != nil) {
[type appendString:@"; "];
[type appendString:pn];
[type appendString:@"=\""];
return type;
}
+- (NSString *)contentTypeForPathExtension:(NSString *)pe {
+ if ([pe length] == 0)
+ return @"application/octet-stream";
+
+ /* TODO: add some map */
+ if ([pe isEqualToString:@"gif"]) return @"image/gif";
+ if ([pe isEqualToString:@"png"]) return @"image/png";
+ if ([pe isEqualToString:@"jpg"]) return @"image/jpeg";
+ if ([pe isEqualToString:@"txt"]) return @"text/plain";
+
+ return @"application/octet-stream";
+}
+
- (NSString *)davContentType {
// TODO: what about the content-type and other headers?
// => we could pass them in as the extension? (eg generate 1.gif!)
/* construct type */
pe = [[self nameInContainer] pathExtension];
- if ([pe length] == 0)
- return @"application/octet-stream";
-
- /* TODO: add some map */
- if ([pe isEqualToString:@"gif"]) return @"image/gif";
- if ([pe isEqualToString:@"png"]) return @"image/png";
- if ([pe isEqualToString:@"jpg"]) return @"image/jpeg";
- if ([pe isEqualToString:@"txt"]) return @"text/plain";
-
- return @"application/octet-stream";
+ return [self contentTypeForPathExtension:pe];
}
/* actions */
/*
- Copyright (C) 2004 SKYRIX Software AG
+ Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
-// $Id$
#ifndef __Mailer_SOGoMailObject_H__
#define __Mailer_SOGoMailObject_H__
/*
- Copyright (C) 2004 SKYRIX Software AG
+ Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
-// $Id$
#include "SOGoMailObject.h"
#include "SOGoMailManager.h"
/* name lookup */
-- (BOOL)isBodyPartKey:(NSString *)_key inContext:(id)_ctx {
- /*
- Every key starting with a digit is consider an IMAP4 mime part key.
- */
- if ([_key length] == 0)
- return NO;
-
- if (isdigit([_key characterAtIndex:0]))
- return YES;
-
- return NO;
-}
-
- (id)lookupImap4BodyPartKey:(NSString *)_key inContext:(id)_ctx {
// TODO: we might want to check for existence prior controller creation
return [[[SOGoMailBodyPart alloc] initWithName:_key
# Version file
-SUBMINOR_VERSION:=56
+SUBMINOR_VERSION:=57
# v0.9.55 requires NGExtensions v4.5.136
# v0.9.44 requires libNGMime v4.3.194
+2005-01-28 Helge Hess <helge.hess@skyrix.com>
+
+ * v0.9.77
+
+ * added UIxMailSizeFormatter to render big file size numbers with some
+ M or K suffix
+
+ * UIxMailPartViewer.m: added methods to retrieve filename, file
+ extension and file size formatter
+
+ * UIxMailSortableTableHeader.m: minor code cleanups
+
2005-01-27 Helge Hess <helge.hess@skyrix.com>
* started attachment (download) viewer (#1074) (v0.9.76)
\
UIxFilterList.m \
UIxSieveEditor.m \
+ \
+ UIxMailSizeFormatter.m \
MailerUI_RESOURCE_FILES += \
Version \
}
- (id)lookupSentFolder {
- /* lookup INBOX/Sent folder */
+ /*
+ Lookup INBOX/Sent folder. This must be in the UI layer, because the Sent
+ folder could be a user defined folder (so we cannot have a simple
+ -saveToSent action on the SOGoDraftObject).
+ */
SOGoMailAccount *account;
SOGoMailFolder *folder;
-
+
if (self->sentFolder != nil)
return self;
-
+
account = [[self clientObject] mailAccountFolder];
if ([account isKindOfClass:[NSException class]]) return account;
/*
- Copyright (C) 2004 SKYRIX Software AG
+ Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
-// $Id: UIxMailMainFrame.m 278 2004-08-26 23:29:09Z helge $
#include <SOGoUI/UIxComponent.h>
/*
- Copyright (C) 2004 SKYRIX Software AG
+ Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
- (NSString *)pathToAttachment {
NSString *url, *n;
+
+ /* path to mail controller object */
url = [[self clientObject] baseURLInContext:[self context]];
if (![url hasSuffix:@"/"]) url = [url stringByAppendingString:@"/"];
+ /* mail relative path to body-part */
+
n = [[self partPath] componentsJoinedByString:@"/"];
- return [url stringByAppendingString:n];
+ url = [url stringByAppendingString:n];
+
+ /*
+ If we have an attachment name, we attach it, this is properly handled by
+ SOGoMailBodyPart.
+ */
+
+ n = [[[self bodyInfo] valueForKey:@"parameterList"] valueForKey:@"name"];
+ if ([n isNotNull] && [n length] > 0) {
+ url = [url stringByAppendingString:@"/"];
+ url = [url stringByAppendingString:n];
+ }
+ else if ([(n = [[self bodyInfo] valueForKey:@"type"]) isNotNull]) {
+ /* attach extension */
+ url = [url stringByAppendingString:@"."];
+ url = [url stringByAppendingString:[self preferredPathExtension]];
+ }
+
+ return url;
}
@end /* UIxMailPartLinkViewer */
<?xml version="1.0" standalone="yes"?>
<div xmlns="http://www.w3.org/1999/xhtml"
xmlns:var="http://www.skyrix.com/od/binding"
+ class="linked_attachment_frame"
>
- <a var:href="pathToAttachment"
- var:title="bodyInfo"
- class="mailer_imagecontent"
- >[abc <var:string value="bodyInfo" />]</a>
+ <div class="linked_attachment_body">
+ <a var:href="pathToAttachment"
+ var:title="filenameForDisplay"
+ ><var:string value="filenameForDisplay" /></a>
+ <div class="linked_attachment_meta">
+ <var:string label:value="Type" />:
+ <var:string value="bodyInfo.type" /> /
+ <var:string value="bodyInfo.subtype" />,
+
+ <var:string label:value="Size" />:
+ <var:string value="bodyInfo.size" formatter="sizeFormatter" />
+ </div>
+
+<!-- debug
+ <a var:href="pathToAttachment"
+ var:title="bodyInfo"
+ class="mailer_imagecontent"
+ >[<var:string value="pathToAttachment" />]</a>
+ <br />
+ Id: <var:string value="bodyInfo.bodyId" /><br />
+ Desc: <var:string value="bodyInfo.description" /><br />
+ Enc: <var:string value="bodyInfo.encoding" /><br />
+ Par: <var:string value="bodyInfo.parameterList" /><br />
+ Size: <var:string value="bodyInfo.size" /><br />
+ Type: <var:string value="bodyInfo.type" /><br />
+ Subtype: <var:string value="bodyInfo.subtype" /><br />
+ Path: <var:string value="pathToAttachment" /><br />
+ PartPath: <var:string value="partPath" /><br />
+-->
+ </div>
</div>
/*
- Copyright (C) 2004 SKYRIX Software AG
+ Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
#include "UIxMailPartViewer.h"
+/*
+ UIxMailPartTextViewer
+
+ Show plain/text mail parts in a <pre> section.
+
+ TODO: add server side wrapping.
+ TODO: add contained link detection.
+*/
+
@interface UIxMailPartTextViewer : UIxMailPartViewer
{
}
@implementation UIxMailPartTextViewer
-- (void)dealloc {
- [super dealloc];
-}
-
-/* accessors */
-
@end /* UIxMailPartTextViewer */
/*
- Copyright (C) 2004 SKYRIX Software AG
+ Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
This class is the superclass for MIME content viewers.
*/
-@class NSData, NSArray;
+@class NSData, NSArray, NSFormatter;
@interface UIxMailPartViewer : UIxComponent
{
- (NSData *)decodedFlatContent;
- (NSString *)flatContentAsString;
+- (NSString *)preferredPathExtension;
+- (NSString *)filename;
+- (NSString *)filenameForDisplay;
+- (NSFormatter *)sizeFormatter;
+
/* caches */
- (void)resetPathCaches;
/*
- Copyright (C) 2004 SKYRIX Software AG
+ Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
#include "UIxMailPartViewer.h"
#include "UIxMailRenderingContext.h"
+#include "UIxMailSizeFormatter.h"
#include "WOContext+UIxMailer.h"
#include <NGExtensions/NSString+Encoding.h>
#include "common.h"
- (void)dealloc {
[self->flatContent release];
- [self->bodyInfo release];
- [self->partPath release];
+ [self->bodyInfo release];
+ [self->partPath release];
[super dealloc];
}
return s;
}
+/* path extension */
+
+- (NSString *)pathExtensionForType:(NSString *)_mt subtype:(NSString *)_st {
+ // TODO: support /etc/mime.types
+
+ if (![_mt isNotNull] || ![_st isNotNull])
+ return nil;
+ if ([_mt length] == 0) return nil;
+ if ([_st length] == 0) return nil;
+ _mt = [_mt lowercaseString];
+ _st = [_st lowercaseString];
+
+ if ([_mt isEqualToString:@"image"]) {
+ if ([_st isEqualToString:@"gif"]) return @"gif";
+ if ([_st isEqualToString:@"jpeg"]) return @"jpg";
+ if ([_st isEqualToString:@"png"]) return @"png";
+ }
+ else if ([_mt isEqualToString:@"text"]) {
+ if ([_st isEqualToString:@"plain"]) return @"txt";
+ if ([_st isEqualToString:@"xml"]) return @"xml";
+ }
+ else if ([_mt isEqualToString:@"application"]) {
+ if ([_st isEqualToString:@"pdf"]) return @"pdf";
+ }
+ return nil;
+}
+
+- (NSString *)preferredPathExtension {
+ return [self pathExtensionForType:[[self bodyInfo] valueForKey:@"type"]
+ subtype:[[self bodyInfo] valueForKey:@"subtype"]];
+}
+
+- (NSString *)filename {
+ id tmp;
+
+ tmp = [[self bodyInfo] valueForKey:@"parameterList"];
+ if (![tmp isNotNull])
+ return nil;
+
+ tmp = [tmp valueForKey:@"name"];
+ if (![tmp isNotNull])
+ return nil;
+
+ return [tmp length] > 0 ? tmp : nil;
+}
+
+- (NSString *)filenameForDisplay {
+ NSString *s;
+
+ if ((s = [self filename]) != nil)
+ return s;
+
+ s = [[self partPath] componentsJoinedByString:@"-"];
+ return [@"untitled-" stringByAppendingString:s];
+}
+
+- (NSFormatter *)sizeFormatter {
+ return [UIxMailSizeFormatter sharedMailSizeFormatter];
+}
+
@end /* UIxMailPartViewer */
--- /dev/null
+/*
+ Copyright (C) 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 __Mailer_UIxMailSizeFormatter_H__
+#define __Mailer_UIxMailSizeFormatter_H__
+
+#include <Foundation/NSFormatter.h>
+
+/*
+ UIxMailSizeFormatter
+
+ This class formats the size values for display.
+*/
+
+@interface UIxMailSizeFormatter : NSFormatter
+{
+}
+
++ (id)sharedMailSizeFormatter;
+
+@end
+
+#endif /* __Mailer_UIxMailSizeFormatter_H__ */
--- /dev/null
+/*
+ Copyright (C) 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 "UIxMailSizeFormatter.h"
+#include "common.h"
+
+@implementation UIxMailSizeFormatter
+
++ (id)sharedMailSizeFormatter {
+ static UIxMailSizeFormatter *fmt = nil; // THREAD
+ if (fmt == nil) fmt = [[self alloc] init];
+ return fmt;
+}
+
+/* formatting */
+
+- (NSString *)stringForSize:(unsigned int)size {
+ unsigned char buf[128];
+
+ if (size < 1024)
+ sprintf(buf, "%d", size);
+ else if (size < 1024 * 1024)
+ sprintf(buf, "%.1fK", ((double)size / 1024));
+ else
+ sprintf(buf, "%.1fM", ((double)size / 1024 / 1024));
+
+ return [NSString stringWithCString:buf];
+}
+
+- (NSString *)stringForObjectValue:(id)_object {
+ return [self stringForSize:[_object unsignedIntValue]];
+}
+
+@end /* UIxMailSizeFormatter */
/*
- Copyright (C) 2000-2004 SKYRIX Software AG
+ Copyright (C) 2004-2005 SKYRIX Software AG
- This file is part of OGo
+ 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
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.
- */
-// $Id$
-
+*/
#include <NGObjWeb/NGObjWeb.h>
+/*
+ UIxMailSortableTableHeader
+
+ TODO: document.
+*/
+
@interface UIxMailSortableTableHeader : WOComponent
{
NSString *label;
/* Accessors */
- (void)setLabel:(NSString *)_label {
- ASSIGN(self->label, _label);
+ ASSIGNCOPY(self->label, _label);
}
- (NSString *)label {
return self->label;
}
- (void)setSortKey:(NSString *)_sortKey {
- ASSIGN(self->sortKey, _sortKey);
+ ASSIGNCOPY(self->sortKey, _sortKey);
}
- (NSString *)sortKey {
return self->sortKey;
}
- (void)setHref:(NSString *)_href {
- ASSIGN(self->href, _href);
+ ASSIGNCOPY(self->href, _href);
}
- (NSString *)href {
return self->href;
- (BOOL)isSelected {
NSString *so;
+
so = [self->queryDictionary objectForKey:@"sort"];
- if(!so) {
+ if (![so isNotNull])
return self->isDefault;
- }
+
return [so isEqualToString:self->sortKey];
}
NSString *desc;
desc = [self->queryDictionary objectForKey:@"desc"];
- if(!desc)
+ if (desc == nil)
return NO;
- return [desc boolValue] ? YES : NO;
+ return [desc boolValue];
}
-@end
+@end /* UIxMailSortableTableHeader */
# version file
-SUBMINOR_VERSION:=76
+SUBMINOR_VERSION:=77
+# v0.9.77 requires SoObjects/Mailer v0.9.57
# v0.9.74 requires SoObjects/Mailer v0.9.56
# v0.9.70 requires NGExtensions v4.5.136
# v0.9.69 requires libNGMime v4.5.203
font-size: 11px;
text-align: left;
}
+
+/* attachment link viewer */
+
+div.linked_attachment_frame {
+ background-color: #D4D0C8;
+ padding: 4px;
+}
+
+div.linked_attachment_body {
+ font-family: Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+ font-size: 10pt;
+ padding: 4px;
+
+ border-width: 1;
+ border-style: solid;
+ border-top-color: white;
+ border-left-color: white;
+ border-bottom-color: #808080;
+ border-right-color: #808080;
+}
+
+div.linked_attachment_meta {
+ color: #444444;
+ font-style: italic;
+ border-width: 0;
+ padding: 2px;
+}