#import <NGExtensions/NSNull+misc.h>
#import <NGExtensions/NSString+misc.h>
+#import <EOControl/EOQualifier.h>
+
#import <SoObjects/Mailer/SOGoMailFolder.h>
#import <SoObjects/Mailer/SOGoMailObject.h>
#import <SoObjects/SOGo/SOGoDateFormatter.h>
@implementation UIxMailListView
+- (id) init
+{
+ SOGoUser *user;
+
+ if ((self = [super init]))
+ {
+ qualifier = nil;
+ user = [context activeUser];
+ ASSIGN (dateFormatter, [user dateFormatterInContext: context]);
+ ASSIGN (userTimeZone, [user timeZone]);
+ }
+
+ return self;
+}
+
- (void) dealloc
{
- [self->qualifier release];
- [self->sortedUIDs release];
- [self->messages release];
- [self->message release];
+ [qualifier release];
+ [sortedUIDs release];
+ [messages release];
+ [message release];
[dateFormatter release];
[userTimeZone release];
[super dealloc];
}
-/* notifications */
-
-- (void) sleep
-{
- [self->qualifier release]; self->qualifier = nil;
- [self->sortedUIDs release]; self->sortedUIDs = nil;
- [self->messages release]; self->messages = nil;
- [self->message release]; self->message = nil;
- [super sleep];
-}
-
/* accessors */
-- (void)setMessage:(id)_msg
+- (void) setMessage: (id) _msg
{
- ASSIGN(self->message, _msg);
+ ASSIGN(message, _msg);
}
- (id) message
{
- return self->message;
+ return message;
}
- (NSString *) messageDate
{
NSCalendarDate *messageDate;
- messageDate = [[message objectForKey: @"envelope"] date];
+ messageDate = [[message valueForKey: @"envelope"] date];
[messageDate setTimeZone: userTimeZone];
return [dateFormatter formattedDateAndTime: messageDate];
}
-- (void) setQualifier: (EOQualifier *) _msg
+- (NSString *) messageSubject
{
- ASSIGN(self->qualifier, _msg);
-}
+ NSString *subject;
+ id envSubject;
-- (EOQualifier *) qualifier
-{
- return self->qualifier;
+ envSubject = [[message valueForKey: @"envelope"] subject];
+ if ([envSubject isKindOfClass: [NSData class]])
+ {
+ subject = [[NSString alloc] initWithData: envSubject
+ encoding: NSUTF8StringEncoding];
+ [subject autorelease];
+ }
+ else
+ subject = envSubject;
+
+ return subject;
}
- (BOOL) showToAddress
flags = [[self message] valueForKey:@"flags"];
return [flags containsObject:@"seen"];
}
+
- (NSString *) messageUidString
{
return [[[self message] valueForKey:@"uid"] stringValue];
/* Note: see SOGoMailManager.m for allowed IMAP4 keys */
static NSArray *keys = nil;
if (keys == nil) {
- keys = [[NSArray alloc] initWithObjects:
+ keys = [[NSArray alloc] initWithObjects: @"UID",
@"FLAGS", @"ENVELOPE", @"RFC822.SIZE", nil];
}
return keys;
- (NSString *) defaultSortKey
{
- return @"DATE";
+ return @"ARRIVAL";
}
- (NSString *) imap4SortKey
{
NSString *sort;
- sort = [[[self context] request] formValueForKey:@"sort"];
+ sort = [[context request] formValueForKey: @"sort"];
- if ([sort length] == 0)
+ if (![sort length])
sort = [self defaultSortKey];
return [sort uppercaseString];
}
-- (BOOL) isSortedDescending
-{
- NSString *desc;
-
- desc = [[[self context] request] formValueForKey:@"desc"];
-
- return ((desc)
- ? [desc boolValue]
- : YES);
-}
-
- (NSString *) imap4SortOrdering
{
- NSString *sort;
+ NSString *sort, *ascending;
sort = [self imap4SortKey];
- if ([self isSortedDescending])
+ ascending = [[context request] formValueForKey: @"asc"];
+ if (![ascending boolValue])
sort = [@"REVERSE " stringByAppendingString: sort];
return sort;
- (NSRange) fetchRange
{
- if (self->firstMessageNumber == 0)
+ if (firstMessageNumber == 0)
return NSMakeRange(0, messagesPerPage);
- return NSMakeRange(self->firstMessageNumber - 1, messagesPerPage);
+ return NSMakeRange(firstMessageNumber - 1, messagesPerPage);
}
- (NSArray *) sortedUIDs
{
+ EOQualifier *fetchQualifier, *notDeleted;
if (!sortedUIDs)
{
- sortedUIDs
- = [[self clientObject] fetchUIDsMatchingQualifier: [self qualifier]
- sortOrdering: [self imap4SortOrdering]];
+ notDeleted = [EOQualifier qualifierWithQualifierFormat:
+ @"(not (flags = %@))",
+ @"deleted"];
+ if (qualifier)
+ {
+ fetchQualifier = [[EOAndQualifier alloc] initWithQualifiers:
+ notDeleted, qualifier,
+ nil];
+ [fetchQualifier autorelease];
+ }
+ else
+ fetchQualifier = notDeleted;
+
+ sortedUIDs
+ = [[self clientObject] fetchUIDsMatchingQualifier: fetchQualifier
+ sortOrdering: [self imap4SortOrdering]];
[sortedUIDs retain];
}
- return self->sortedUIDs;
+ return sortedUIDs;
}
- (unsigned int) totalMessageCount
{
- return [self->sortedUIDs count];
+ return [sortedUIDs count];
}
- (BOOL) showsAllMessages
NSArray *msgs;
NSRange r;
unsigned len;
- SOGoUser *user;
- if (self->messages != nil)
- return self->messages;
-
- user = [context activeUser];
- if (!dateFormatter)
- dateFormatter = [user dateFormatterInContext: context];
- if (!userTimeZone)
- ASSIGN (userTimeZone, [user timeZone]);
+ if (messages != nil)
+ return messages;
r = [self fetchBlock];
uids = [self sortedUIDs];
/* only need to restrict if we have a lot */
uids = [uids subarrayWithRange:r];
- msgs = [[self clientObject] fetchUIDs:uids parts:[self fetchKeys]];
- self->messages = [[msgs valueForKey:@"fetch"] retain];
- return self->messages;
+ msgs = [[self clientObject] fetchUIDs: uids parts: [self fetchKeys]];
+ messages = [[msgs valueForKey: @"fetch"] retain];
+
+ return messages;
}
/* URL processing */
return [self redirectToLocation:url];
}
-/* active message */
-
-- (SOGoMailObject *) lookupActiveMessage
-{
- NSString *uid;
-
- if ((uid = [[[self context] request] formValueForKey:@"uid"]) == nil)
- return nil;
-
- return [[self clientObject] lookupName:uid inContext:[self context]
- acquire:NO];
-}
-
/* actions */
-- (BOOL) isJavaScriptRequest
-{
- return [[[[self context] request] formValueForKey:@"jsonly"] boolValue];
-}
-
-- (id) javaScriptOK
-{
- WOResponse *r;
-
- r = [[self context] response];
- [r setStatus:200 /* OK */];
- return r;
-}
-
- (int) firstMessageOfPageFor: (int) messageNbr
{
NSArray *messageNbrs;
return firstMessage;
}
+- (void) _setQualifierForCriteria: (NSString *) criteria
+ andValue: (NSString *) value
+{
+ [qualifier release];
+
+ if ([criteria isEqualToString: @"subject"])
+ qualifier = [EOQualifier qualifierWithQualifierFormat:
+ @"(subject doesContain: %@)", value];
+ else if ([criteria isEqualToString: @"sender"])
+ qualifier = [EOQualifier qualifierWithQualifierFormat:
+ @"(from doesContain: %@)", value];
+ else if ([criteria isEqualToString: @"subject_or_sender"])
+ qualifier = [EOQualifier qualifierWithQualifierFormat:
+ @"((subject doesContain: %@)"
+ @" OR (from doesContain: %@))",
+ value, value];
+ else if ([criteria isEqualToString: @"to_or_cc"])
+ qualifier = [EOQualifier qualifierWithQualifierFormat:
+ @"((to doesContain: %@)"
+ @" OR (cc doesContain: %@))",
+ value, value];
+ else if ([criteria isEqualToString: @"entire_message"])
+ qualifier = [EOQualifier qualifierWithQualifierFormat:
+ @"(body doesContain: %@)", value];
+ else
+ qualifier = nil;
+
+ [qualifier retain];
+}
+
- (id) defaultAction
{
WORequest *request;
- NSString *specificMessage;
+ NSString *specificMessage, *searchCriteria, *searchValue;
- request = [[self context] request];
+ request = [context request];
[[self clientObject] flushMailCaches];
specificMessage = [request formValueForKey: @"pageforuid"];
- self->firstMessageNumber
+ searchCriteria = [request formValueForKey: @"search"];
+ searchValue = [request formValueForKey: @"value"];
+ if ([searchValue length])
+ [self _setQualifierForCriteria: searchCriteria
+ andValue: searchValue];
+
+ firstMessageNumber
= ((specificMessage)
? [self firstMessageOfPageFor: [specificMessage intValue]]
: [[request formValueForKey:@"idx"] intValue]);
-
return self;
}
-- (id) viewAction
-{
- return [self defaultAction];
-}
-
-- (id) markMessageUnreadAction
-{
- NSException *error;
-
- if ((error = [[self lookupActiveMessage] removeFlags:@"seen"]) != nil)
- // TODO: improve error handling
- return error;
-
- if ([self isJavaScriptRequest])
- return [self javaScriptOK];
-
- return [self redirectToLocation:@"view"];
-}
-
-- (id) markMessageReadAction
-{
- NSException *error;
-
- if ((error = [[self lookupActiveMessage] addFlags:@"seen"]) != nil)
- // TODO: improve error handling
- return error;
-
- if ([self isJavaScriptRequest])
- return [self javaScriptOK];
-
- return [self redirectToLocation:@"view"];
-}
-
- (id) getMailAction
{
// TODO: we might want to flush the caches?
return [self redirectToLocation:@"view"];
}
-- (id) expungeAction
+- (NSString *) msgLabels
{
- // TODO: we might want to flush the caches?
- NSException *error;
- id client;
-
- if ((client = [self clientObject]) == nil) {
- return [NSException exceptionWithHTTPStatus:404 /* Not Found */
- reason:@"did not find mail folder"];
- }
-
- if ((error = [[self clientObject] expunge]) != nil)
- return error;
-
- if ([client respondsToSelector:@selector(flushMailCaches)])
- [client flushMailCaches];
- return [self redirectToLocation:@"view"];
+ NSMutableArray *labels;
+ NSEnumerator *flags;
+ NSString *currentFlag;
+
+ labels = [NSMutableArray new];
+ [labels autorelease];
+
+ flags = [[message objectForKey: @"flags"] objectEnumerator];
+ while ((currentFlag = [flags nextObject]))
+ if ([currentFlag hasPrefix: @"$label"])
+ [labels addObject: [currentFlag substringFromIndex: 1]];
+
+ return [labels componentsJoinedByString: @" "];
}
@end