+2007-10-29 Wolfgang Sourdeau <wsourdeau@inverse.ca>
+
+ * SoObjects/Mailer/SOGoMailBodyPart.m ([SOGoMailBodyPart
+ -davContentType]): ignore any possible parameter taken from the
+ mime-info of the body part.
+
+ * UI/MailerUI/UIxMailListView.m ([UIxMailListView
+ -lastFirstMessageNumber]): new accessor that returns the first
+ message number of the last series of messages.
+ ([UIxMailListView -fetchKeys]): request the bodystructure for each
+ listed message.
+ ([UIxMailListView -hasMessageAttachment]): extract the attachment
+ information from the message bodystructure.
+
2007-10-26 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/Mailer/SOGoMailBodyPart.m ([SOGoMailBodyPart
+2007-10-29 Wolfgang Sourdeau <wsourdeau@inverse.ca>
+
+ * GCSFolder.m ([GCSFolder -writeContent:toName:baseVersion:]):
+ purge the record if previously marked as deleted.
+
2007-10-24 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* GCSFolderManager.m ([GCSFolderManager -baseTableNameWithUID:]):
return [self _fetchValueOfColumn:@"c_version" inContentWithName:_name];
}
+- (NSNumber *)deletionOfContentWithName:(NSString *)_name {
+ return [self _fetchValueOfColumn:@"c_deleted" inContentWithName:_name];
+}
+
- (NSString *)fetchContentWithName:(NSString *)_name {
return [self _fetchValueOfColumn:@"c_content" inContentWithName:_name];
}
return AUTORELEASE(qualifier);
}
+- (void) _purgeRecordWithName: (NSString *) recordName
+{
+ NSString *delSql, *table;
+ EOAdaptorChannel *channel;
+
+ channel = [self acquireStoreChannel];
+
+ table = [self storeTableName];
+ delSql = [NSString stringWithFormat: @"DELETE FROM %@"
+ @" WHERE c_name = %@", table,
+ [self _formatRowValue: recordName]];
+ [channel evaluateExpressionX: delSql];
+ [self releaseChannel: channel];
+}
+
- (NSException *)writeContent:(NSString *)_content toName:(NSString *)_name
baseVersion:(unsigned int)_baseVersion
{
if (doLogStore)
[self logWithFormat:@" version: %@", storedVersion];
isNewRecord = [storedVersion isNotNull] ? NO : YES;
+ if (!isNewRecord)
+ {
+ if ([[self deletionOfContentWithName:_name] isNotNull])
+ {
+ [self _purgeRecordWithName: _name];
+ isNewRecord = YES;
+ }
+ }
/* check whether sequence matches */
if (_baseVersion != 0 /* use 0 to override check */) {
return @"application/octet-stream";
}
-- (NSString *)davContentType {
+- (NSString *) davContentType
+{
// TODO: what about the content-type and other headers?
// => we could pass them in as the extension? (eg generate 1.gif!)
- NSString *pe;
+ NSString *parts, *contentType, *extension;
/* try type from body structure info */
- if ((pe = [self contentTypeForBodyPartInfo:[self partInfo]]) != nil)
- return pe;
-
- /* construct type */
-
- pe = [[self nameInContainer] pathExtension];
- return [self contentTypeForPathExtension:pe];
+ parts = [self contentTypeForBodyPartInfo: [self partInfo]];
+ contentType = [[parts componentsSeparatedByString: @";"] objectAtIndex: 0];
+
+ if (![contentType length])
+ {
+ extension = [[self nameInContainer] pathExtension];
+ contentType = [self contentTypeForPathExtension: extension];
+ }
+
+ return contentType;
}
/* actions */
"Unread" = "Unread";
"messages" = "messages";
-"first" = "first";
-"previous" = "prev";
-"next" = "next";
+"first" = "First";
+"previous" = "Previous";
+"next" = "Next";
+"last" = "Last";
"msgnumber_to" = "to";
"msgnumber_of" = "of";
"messages" = "message(s)";
"first" = "Premier";
-"previous" = "précédent";
-"next" = "suivant";
+"previous" = "Précédent";
+"next" = "Suivant";
+"last" = "Dernier";
"Mark Unread" = "Marquer comme non lu";
"Mark Read" = "Marquer comme lu";
"first" = "Erste";
"previous" = "Vorherige";
"next" = "Nächste";
+"last" = "Letzter";
"Mark Unread" = "Als ungelesen markieren";
"Mark Read" = "Als gelesen markieren";
#import <SoObjects/Mailer/SOGoMailFolder.h>
#import <SoObjects/Mailer/SOGoMailObject.h>
+#import <SoObjects/SOGo/NSArray+Utilities.h>
#import <SoObjects/SOGo/SOGoDateFormatter.h>
#import <SoObjects/SOGo/SOGoUser.h>
#import "UIxMailListView.h"
#define messagesPerPage 50
-static int attachmentFlagSize = 8096;
@implementation UIxMailListView
- (void) setMessage: (id) _msg
{
- ASSIGN(message, _msg);
+ ASSIGN (message, _msg);
}
- (id) message
- (BOOL) hasMessageAttachment
{
- /* we detect attachments by size ... */
- unsigned size;
-
- size = [[[self message] valueForKey:@"size"] intValue];
- return size > attachmentFlagSize;
+ NSArray *parts;
+ NSEnumerator *dispositions;
+ NSDictionary *currentDisp;
+ BOOL hasAttachment;
+
+ parts = [[message objectForKey: @"body"] objectForKey: @"parts"];
+ if ([parts count] > 1)
+ {
+ dispositions
+ = [[parts objectsForKey: @"disposition"] objectEnumerator];
+ while (!hasAttachment
+ && (currentDisp = [dispositions nextObject]))
+ hasAttachment = ([[currentDisp objectForKey: @"type"]
+ isEqualToString: @"ATTACHMENT"]);
+ }
+ else
+ hasAttachment = NO;
+
+ return hasAttachment;
}
/* fetching messages */
{
/* Note: see SOGoMailManager.m for allowed IMAP4 keys */
static NSArray *keys = nil;
- if (keys == nil) {
+
+ if (!keys)
keys = [[NSArray alloc] initWithObjects: @"UID",
- @"FLAGS", @"ENVELOPE", @"RFC822.SIZE", nil];
- }
+ @"FLAGS", @"ENVELOPE", @"RFC822.SIZE",
+ @"BODYSTRUCTURE", nil];
+
return keys;
}
- (NSArray *) sortedUIDs
{
EOQualifier *fetchQualifier, *notDeleted;
+
if (!sortedUIDs)
{
notDeleted = [EOQualifier qualifierWithQualifierFormat:
return [self firstMessageNumber] + [self fetchRange].length;
}
+- (unsigned int) lastFirstMessageNumber
+{
+ unsigned int max, modulo;
+
+ if (!sortedUIDs)
+ [self sortedUIDs];
+
+ max = [sortedUIDs count];
+ modulo = (max % messagesPerPage);
+ if (modulo == 0)
+ modulo = messagesPerPage;
+
+ return (max + 1 - modulo);
+}
+
- (unsigned int) prevFirstMessageNumber
{
NSRange r;
- (NSArray *) messages
{
- NSArray *uids;
- NSArray *msgs;
- NSRange r;
+ NSArray *uids;
+ NSDictionary *msgs;
+ NSRange r;
unsigned len;
- if (messages != nil)
- return messages;
-
- r = [self fetchBlock];
- uids = [self sortedUIDs];
- if ((len = [uids count]) > r.length)
- /* only need to restrict if we have a lot */
- uids = [uids subarrayWithRange:r];
+ if (!messages)
+ {
+ r = [self fetchBlock];
+ uids = [self sortedUIDs];
+ len = [uids count];
+ if (len > r.length)
+ /* only need to restrict if we have a lot */
+ uids = [uids subarrayWithRange: r];
- msgs = [[self clientObject] fetchUIDs: uids parts: [self fetchKeys]];
- messages = [[msgs valueForKey: @"fetch"] retain];
+ msgs = [[self clientObject] fetchUIDs: uids parts: [self fetchKeys]];
+ messages = [[msgs objectForKey: @"fetch"] retain];
+ }
return messages;
}
>| <a href="#"
var:idx="nextFirstMessageNumber"
><var:string label:value="next" /></a>
+ | <a href="#"
+ var:idx="lastFirstMessageNumber"
+ ><var:string label:value="last" /></a>
</var:if>
</var:if
></td
}
else
success = false;
-
+
return success;
}
-
+
var plusSignEnter = function() {
var nodeNr = parseInt(this.id.substr(2));
if (!mailboxTree.aNodes[nodeNr]._io)
this.plusSignTimer = setTimeout("openPlusSign('" + nodeNr + "');", 1000);
}
-
+
var plusSignExit = function() {
if (this.plusSignTimer) {
clearTimeout(this.plusSignTimer);