ba68bd8935
The folder names are encoded through the `asCSSIdentifier` and `stringByEncodingImap4FolderName` functions when we store them as folder keys. In addition, the prefix "folder" is added to the key. The order in which these operations were done when storing the folder keys (and reverted when retrieving them) wasn't consistent trough the code. This led to problems such as creating twice a folder with a digit at the beginning of its name. The folder name goes now through the following operations when being stored as a key (the retrieval reverts these in the reverse order): * `stringByEncodingImap4FolderName` * `asCSSIdentifier` * Add "folder" prefix
735 lines
20 KiB
Objective-C
735 lines
20 KiB
Objective-C
/*
|
|
Copyright (C) 2007-2014 Inverse inc.
|
|
|
|
This file is part of SOGo.
|
|
|
|
SOGo 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.
|
|
|
|
SOGo 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.
|
|
*/
|
|
|
|
#import <Foundation/NSEnumerator.h>
|
|
#import <Foundation/NSValue.h>
|
|
|
|
#import <EOControl/EOQualifier.h>
|
|
|
|
#import <NGCards/NGVCard.h>
|
|
#import <NGCards/NGVCardReference.h>
|
|
#import <NGCards/NGVList.h>
|
|
#import <NGObjWeb/WOContext.h>
|
|
#import <NGObjWeb/WORequest.h>
|
|
#import <NGObjWeb/WOResponse.h>
|
|
#import <NGObjWeb/SoComponent.h>
|
|
#import <NGExtensions/NSObject+Logs.h>
|
|
#import <NGExtensions/NSString+misc.h>
|
|
|
|
#import <Contacts/SOGoContactObject.h>
|
|
#import <Contacts/SOGoContactGCSList.h>
|
|
#import <Contacts/SOGoContactGCSEntry.h>
|
|
#import <Contacts/SOGoContactFolders.h>
|
|
#import <Contacts/SOGoContactLDIFEntry.h>
|
|
|
|
#import <Mailer/SOGoDraftsFolder.h>
|
|
#import <Mailer/SOGoMailAccount.h>
|
|
#import <Mailer/SOGoMailAccounts.h>
|
|
#import <Mailer/SOGoMailFolder.h>
|
|
#import <Mailer/SOGoMailLabel.h>
|
|
#import <Mailer/SOGoMailObject.h>
|
|
#import <Mailer/SOGoSentFolder.h>
|
|
#import <SOGo/NSDictionary+URL.h>
|
|
#import <SOGo/NSArray+Utilities.h>
|
|
#import <SOGo/NSString+Utilities.h>
|
|
#import <SOGo/NSDictionary+Utilities.h>
|
|
#import <SOGo/SOGoDomainDefaults.h>
|
|
#import <SOGo/SOGoUser.h>
|
|
#import <SOGo/SOGoUserDefaults.h>
|
|
#import <SOGo/SOGoUserFolder.h>
|
|
#import <SOGo/SOGoUserSettings.h>
|
|
#import <SOGoUI/UIxComponent.h>
|
|
|
|
#import "UIxMailMainFrame.h"
|
|
#import "UIxMailListActions.h"
|
|
|
|
// Avoid compilation warnings
|
|
@interface SOGoUserFolder (private)
|
|
|
|
- (SOGoAppointmentFolders *) privateContacts: (NSString *) key
|
|
inContext: (WOContext *) localContext;
|
|
|
|
@end
|
|
|
|
@implementation UIxMailMainFrame
|
|
|
|
- (id) init
|
|
{
|
|
if ((self = [super init]))
|
|
{
|
|
folderType = 0;
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void) dealloc
|
|
{
|
|
RELEASE(_currentLabel);
|
|
[super dealloc];
|
|
}
|
|
|
|
- (void) _setupContext
|
|
{
|
|
SOGoUser *activeUser;
|
|
NSString *module;
|
|
SOGoMailAccounts *clientObject;
|
|
|
|
activeUser = [context activeUser];
|
|
clientObject = [self clientObject];
|
|
|
|
module = [clientObject nameInContainer];
|
|
|
|
us = [activeUser userSettings];
|
|
moduleSettings = [us objectForKey: module];
|
|
if (!moduleSettings)
|
|
{
|
|
moduleSettings = [NSMutableDictionary dictionary];
|
|
[us setObject: moduleSettings forKey: module];
|
|
}
|
|
}
|
|
|
|
/* accessors */
|
|
|
|
- (NSString *) mailAccounts
|
|
{
|
|
NSArray *accounts, *names;
|
|
|
|
accounts = [[self clientObject] mailAccounts];
|
|
names = [accounts objectsForKey: @"name" notFoundMarker: nil];
|
|
|
|
return [names jsonRepresentation];
|
|
}
|
|
|
|
- (NSString *) userNames
|
|
{
|
|
NSArray *accounts, *userNames;
|
|
|
|
accounts = [[self clientObject] mailAccounts];
|
|
userNames = [accounts objectsForKey: @"userName" notFoundMarker: nil];
|
|
|
|
return [userNames jsonRepresentation];
|
|
|
|
}
|
|
|
|
- (NSString *) pageFormURL
|
|
{
|
|
NSString *u;
|
|
NSRange r;
|
|
|
|
u = [[[self context] request] uri];
|
|
if ((r = [u rangeOfString:@"?"]).length > 0) {
|
|
/* has query parameters */
|
|
// TODO: this is ugly, create reusable link facility in SOPE
|
|
// TODO: remove 'search' and 'filterpopup', preserve sorting
|
|
NSMutableString *ms;
|
|
NSArray *qp;
|
|
NSUInteger i, count;
|
|
|
|
qp = [[u substringFromIndex:(r.location + r.length)]
|
|
componentsSeparatedByString:@"&"];
|
|
count = [qp count];
|
|
ms = [NSMutableString stringWithCapacity:count * 12];
|
|
|
|
for (i = 0; i < count; i++) {
|
|
NSString *s;
|
|
|
|
s = [qp objectAtIndex:i];
|
|
|
|
/* filter out */
|
|
if ([s hasPrefix:@"search="]) continue;
|
|
if ([s hasPrefix:@"filterpopup="]) continue;
|
|
|
|
if ([ms length] > 0) [ms appendString:@"&"];
|
|
[ms appendString:s];
|
|
}
|
|
|
|
if ([ms length] == 0) {
|
|
/* no other query params */
|
|
u = [u substringToIndex:r.location];
|
|
}
|
|
else {
|
|
u = [u substringToIndex:r.location + r.length];
|
|
u = [u stringByAppendingString:ms];
|
|
}
|
|
return u;
|
|
}
|
|
return [u hasSuffix:@"/"] ? @"view" : @"#";
|
|
}
|
|
|
|
- (NSString *) inboxData
|
|
{
|
|
SOGoMailAccounts *accounts;
|
|
SOGoMailAccount *account;
|
|
SOGoMailFolder *inbox;
|
|
NSDictionary *data;
|
|
UIxMailListActions *actions;
|
|
|
|
[self _setupContext];
|
|
|
|
#warning this code is dirty: we should not invoke UIxMailListActions from here!
|
|
actions = [[[UIxMailListActions new] initWithRequest: [context request]] autorelease];
|
|
accounts = [self clientObject];
|
|
|
|
account = [accounts lookupName: @"0" inContext: context acquire: NO];
|
|
inbox = [account inboxFolderInContext: context];
|
|
|
|
data = [actions getUIDsInFolder: inbox withHeaders: YES];
|
|
|
|
return [data jsonRepresentation];
|
|
}
|
|
|
|
- (id <WOActionResults>) composeAction
|
|
{
|
|
id contact;
|
|
NSArray *contactsId, *cards;
|
|
NSString *newLocation, *parameters, *folderId, *uid, *formattedMail;
|
|
NSEnumerator *uids;
|
|
NSMutableArray *addresses;
|
|
NGVCard *card;
|
|
NGVList *list;
|
|
SOGoMailAccounts *co;
|
|
SOGoContactFolders *folders;
|
|
SOGoParentFolder *folder;
|
|
WORequest *request;
|
|
NSUInteger i, count;
|
|
|
|
parameters = nil;
|
|
co = [self clientObject];
|
|
|
|
request = [context request];
|
|
|
|
if ((folderId = [request formValueForKey: @"folder"]) &&
|
|
(contactsId = [request formValuesForKey: @"uid"]))
|
|
{
|
|
// Retrieve the email addresses from the specified address book
|
|
// and contact IDs
|
|
folders = (SOGoContactFolders *)[[[self clientObject] container] privateContacts: @"Contacts"
|
|
inContext: nil];
|
|
folder = [folders lookupName: folderId
|
|
inContext: nil
|
|
acquire: NO];
|
|
if (folder)
|
|
{
|
|
uids = [contactsId objectEnumerator];
|
|
uid = [uids nextObject];
|
|
|
|
addresses = [NSMutableArray array];
|
|
|
|
while (uid)
|
|
{
|
|
contact = [folder lookupName: uid
|
|
inContext: [self context]
|
|
acquire: NO];
|
|
if ([contact isKindOfClass: [SOGoContactGCSList class]])
|
|
{
|
|
list = [(SOGoContactGCSList *)contact vList];
|
|
cards = [list cardReferences];
|
|
count = [cards count];
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
formattedMail = [self formattedMailtoString: [cards objectAtIndex: i]];
|
|
if (formattedMail)
|
|
[addresses addObject: formattedMail];
|
|
}
|
|
}
|
|
else if ([contact isKindOfClass: [SOGoContactGCSEntry class]]
|
|
|| [contact isKindOfClass: [SOGoContactLDIFEntry class]])
|
|
{
|
|
// We fetch the preferred email address of the contact or
|
|
// the first defined email address
|
|
card = [contact vCard];
|
|
formattedMail = [self formattedMailtoString: card];
|
|
if (formattedMail)
|
|
[addresses addObject: formattedMail];
|
|
}
|
|
|
|
uid = [uids nextObject];
|
|
}
|
|
|
|
if ([addresses count] > 0)
|
|
parameters = [NSString stringWithFormat: @"?mailto=%@",
|
|
[addresses jsonRepresentation]];
|
|
}
|
|
}
|
|
else if ([[request formValues] objectForKey: @"mailto"])
|
|
// We use the email addresses defined in the request
|
|
parameters = [[request formValues] asURLParameters];
|
|
|
|
if (!parameters)
|
|
// No parameter passed; simply open the compose window
|
|
parameters = @"?mailto=";
|
|
|
|
newLocation = [NSString stringWithFormat: @"%@/0/compose%@",
|
|
[co baseURLInContext: context],
|
|
parameters];
|
|
|
|
return [self redirectToLocation: newLocation];
|
|
}
|
|
|
|
- (NSString *) formattedMailtoString: (NGVCard *) card
|
|
{
|
|
NSString *firstName, *lastName, *email;
|
|
NSMutableString *fn, *rc = nil;
|
|
CardElement *n;
|
|
|
|
if ([card isKindOfClass: [NGVCard class]])
|
|
email = [card preferredEMail];
|
|
else
|
|
email = [(NGVCardReference *)card email];
|
|
|
|
if (email == nil)
|
|
email = (NSString*)[card firstChildWithTag: @"EMAIL"];
|
|
|
|
if (email)
|
|
{
|
|
email = [NSString stringWithFormat: @"<%@>", email];
|
|
|
|
// We append the contact's name
|
|
fn = [NSMutableString stringWithString: [card fn]];
|
|
if ([fn length] == 0
|
|
&& [card isKindOfClass: [NGVCard class]])
|
|
{
|
|
n = [card n];
|
|
lastName = [n flattenedValueAtIndex: 0 forKey: @""];
|
|
firstName = [n flattenedValueAtIndex: 1 forKey: @""];
|
|
if ([firstName length] > 0)
|
|
{
|
|
if ([lastName length] > 0)
|
|
fn = [NSMutableString stringWithFormat: @"%@ %@", firstName, lastName];
|
|
else
|
|
fn = [NSMutableString stringWithString: firstName];
|
|
}
|
|
else if ([lastName length] > 0)
|
|
fn = [NSMutableString stringWithString: lastName];
|
|
}
|
|
if ([fn length] > 0)
|
|
{
|
|
[fn appendFormat: @" %@", email];
|
|
rc = fn;
|
|
}
|
|
else
|
|
rc = [NSMutableString stringWithString: email];
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
- (WOResponse *) getFoldersStateAction
|
|
{
|
|
NSString *expandedFolders;
|
|
|
|
[self _setupContext];
|
|
expandedFolders = [moduleSettings objectForKey: @"ExpandedFolders"];
|
|
|
|
return [self responseWithStatus: 200 andString: expandedFolders];
|
|
}
|
|
|
|
- (NSString *) verticalDragHandleStyle
|
|
{
|
|
NSString *vertical;
|
|
|
|
[self _setupContext];
|
|
vertical = [moduleSettings objectForKey: @"DragHandleVertical"];
|
|
|
|
return ((vertical && [vertical intValue] > 0) ? (id)[vertical stringByAppendingString: @"px"] : nil);
|
|
}
|
|
|
|
- (NSString *) horizontalDragHandleStyle
|
|
{
|
|
NSString *horizontal;
|
|
|
|
[self _setupContext];
|
|
horizontal = [moduleSettings objectForKey: @"DragHandleHorizontal"];
|
|
|
|
return ((horizontal && [horizontal intValue] > 0) ? (id)[horizontal stringByAppendingString: @"px"] : nil);
|
|
}
|
|
|
|
- (NSString *) mailboxContentStyle
|
|
{
|
|
NSString *height;
|
|
|
|
[self _setupContext];
|
|
height = [moduleSettings objectForKey: @"DragHandleVertical"];
|
|
|
|
return ((height && [height intValue] > 0) ? (id)[NSString stringWithFormat: @"%ipx", ([height intValue] - 27)] : nil);
|
|
}
|
|
|
|
- (WOResponse *) saveDragHandleStateAction
|
|
{
|
|
WORequest *request;
|
|
NSString *dragHandle;
|
|
|
|
[self _setupContext];
|
|
request = [context request];
|
|
|
|
if ((dragHandle = [request formValueForKey: @"vertical"]) != nil)
|
|
[moduleSettings setObject: dragHandle
|
|
forKey: @"DragHandleVertical"];
|
|
else if ((dragHandle = [request formValueForKey: @"horizontal"]) != nil)
|
|
[moduleSettings setObject: dragHandle
|
|
forKey: @"DragHandleHorizontal"];
|
|
else
|
|
return [self responseWithStatus: 400];
|
|
|
|
[us synchronize];
|
|
|
|
return [self responseWithStatus: 204];
|
|
}
|
|
|
|
- (WOResponse *) saveFoldersStateAction
|
|
{
|
|
WORequest *request;
|
|
NSString *expandedFolders;
|
|
|
|
[self _setupContext];
|
|
request = [context request];
|
|
expandedFolders = [request formValueForKey: @"expandedFolders"];
|
|
|
|
[moduleSettings setObject: expandedFolders
|
|
forKey: @"ExpandedFolders"];
|
|
|
|
[us synchronize];
|
|
|
|
return [self responseWithStatus: 204];
|
|
}
|
|
|
|
- (NSString *) columnsState
|
|
{
|
|
NSDictionary *columns;
|
|
|
|
[self _setupContext];
|
|
columns = [moduleSettings objectForKey: @"ColumnsState"];
|
|
|
|
return [columns jsonRepresentation];
|
|
}
|
|
|
|
- (WOResponse *) saveColumnsStateAction
|
|
{
|
|
WORequest *request;
|
|
NSDictionary *columns;
|
|
NSArray *columnsIds, *widths;
|
|
|
|
[self _setupContext];
|
|
request = [context request];
|
|
|
|
columnsIds = [[request formValueForKey: @"columns"] componentsSeparatedByString: @","];
|
|
widths = [[request formValueForKey: @"widths"] componentsSeparatedByString: @","];
|
|
if (columnsIds != nil && widths != nil && [columnsIds count] == [widths count])
|
|
{
|
|
columns = [NSDictionary dictionaryWithObjects: widths
|
|
forKeys: columnsIds];
|
|
[moduleSettings setObject: columns
|
|
forKey: @"ColumnsState"];
|
|
}
|
|
else
|
|
return [self responseWithStatus: 400];
|
|
|
|
[us synchronize];
|
|
|
|
return [self responseWithStatus: 204];
|
|
}
|
|
|
|
- (id) defaultAction
|
|
{
|
|
SOGoUserDefaults *ud;
|
|
|
|
ud = [[context activeUser] userDefaults];
|
|
if ([ud rememberLastModule])
|
|
{
|
|
[ud setLoginModule: @"Mail"];
|
|
[ud synchronize];
|
|
}
|
|
|
|
return [super defaultAction];
|
|
}
|
|
|
|
- (BOOL) showToAddress
|
|
{
|
|
SOGoMailFolder *co;
|
|
|
|
if (!folderType)
|
|
{
|
|
co = [self clientObject];
|
|
if ([co isKindOfClass: [SOGoSentFolder class]]
|
|
|| [co isKindOfClass: [SOGoDraftsFolder class]])
|
|
folderType = 1;
|
|
else
|
|
folderType = -1;
|
|
}
|
|
|
|
return (folderType == 1);
|
|
}
|
|
|
|
- (NSDictionary *) columnsMetaData
|
|
{
|
|
NSMutableDictionary *columnsMetaData;
|
|
NSArray *tmpColumns, *tmpKeys;
|
|
|
|
columnsMetaData = [NSMutableDictionary dictionaryWithCapacity: 8];
|
|
|
|
tmpKeys = [NSArray arrayWithObjects: @"headerClass", @"headerId", @"value",
|
|
nil];
|
|
tmpColumns
|
|
= [NSArray arrayWithObjects: @"messageThreadColumn tbtv_headercell",
|
|
@"invisibleHeader", @"Thread", nil];
|
|
[columnsMetaData setObject: [NSDictionary dictionaryWithObjects: tmpColumns
|
|
forKeys: tmpKeys]
|
|
forKey: @"Thread"];
|
|
|
|
tmpColumns
|
|
= [NSArray arrayWithObjects: @"messageSubjectColumn tbtv_headercell sortableTableHeader resizable",
|
|
@"subjectHeader", @"Subject", nil];
|
|
[columnsMetaData setObject: [NSDictionary dictionaryWithObjects: tmpColumns
|
|
forKeys: tmpKeys]
|
|
forKey: @"Subject"];
|
|
|
|
tmpColumns
|
|
= [NSArray arrayWithObjects: @"messageFlagColumn tbtv_headercell",
|
|
@"invisibleHeader", @"Flagged", nil];
|
|
[columnsMetaData setObject: [NSDictionary dictionaryWithObjects: tmpColumns
|
|
forKeys: tmpKeys]
|
|
forKey: @"Flagged"];
|
|
|
|
tmpColumns
|
|
= [NSArray arrayWithObjects: @"messageFlagColumn tbtv_headercell",
|
|
@"attachmentHeader", @"Attachment", nil];
|
|
[columnsMetaData setObject: [NSDictionary dictionaryWithObjects: tmpColumns
|
|
forKeys: tmpKeys]
|
|
forKey: @"Attachment"];
|
|
|
|
tmpColumns
|
|
= [NSArray arrayWithObjects: @"messageFlagColumn tbtv_headercell", @"messageFlagHeader",
|
|
@"Unread", nil];
|
|
[columnsMetaData setObject: [NSDictionary dictionaryWithObjects: tmpColumns forKeys: tmpKeys]
|
|
forKey: @"Unread"];
|
|
|
|
tmpColumns
|
|
= [NSArray arrayWithObjects: @"messageAddressHeader tbtv_headercell sortableTableHeader resizable",
|
|
@"toHeader", @"To", nil];
|
|
[columnsMetaData setObject: [NSDictionary dictionaryWithObjects: tmpColumns forKeys: tmpKeys]
|
|
forKey: @"To"];
|
|
|
|
tmpColumns
|
|
= [NSArray arrayWithObjects: @"messageAddressColumn tbtv_headercell sortableTableHeader resizable",
|
|
@"fromHeader", @"From", nil];
|
|
[columnsMetaData setObject: [NSDictionary dictionaryWithObjects: tmpColumns
|
|
forKeys: tmpKeys]
|
|
forKey: @"From"];
|
|
|
|
tmpColumns
|
|
= [NSArray arrayWithObjects: @"messageDateColumn tbtv_headercell sortableTableHeader resizable",
|
|
@"dateHeader", @"Date", nil];
|
|
[columnsMetaData setObject: [NSDictionary dictionaryWithObjects: tmpColumns
|
|
forKeys: tmpKeys]
|
|
forKey: @"Date"];
|
|
|
|
tmpColumns
|
|
= [NSArray arrayWithObjects: @"messagePriorityColumn tbtv_headercell resizable", @"priorityHeader",
|
|
@"Priority", nil];
|
|
[columnsMetaData setObject: [NSDictionary dictionaryWithObjects: tmpColumns
|
|
forKeys: tmpKeys]
|
|
forKey: @"Priority"];
|
|
|
|
tmpColumns
|
|
= [NSArray arrayWithObjects: @"messageSizeColumn tbtv_headercell sortableTableHeader", @"sizeHeader",
|
|
@"Size", nil];
|
|
[columnsMetaData setObject: [NSDictionary dictionaryWithObjects: tmpColumns
|
|
forKeys: tmpKeys]
|
|
forKey: @"Size"];
|
|
|
|
return columnsMetaData;
|
|
}
|
|
|
|
- (NSArray *) columnsDisplayOrder
|
|
{
|
|
NSMutableArray *finalOrder, *invalid;
|
|
NSArray *available;
|
|
NSDictionary *metaData;
|
|
SOGoUserDefaults *ud;
|
|
NSUInteger i;
|
|
|
|
if (!columnsOrder)
|
|
{
|
|
ud = [[context activeUser] userDefaults];
|
|
columnsOrder = [ud mailListViewColumnsOrder];
|
|
|
|
metaData = [self columnsMetaData];
|
|
|
|
invalid = [columnsOrder mutableCopy];
|
|
[invalid autorelease];
|
|
available = [metaData allKeys];
|
|
[invalid removeObjectsInArray: available];
|
|
if ([invalid count] > 0)
|
|
{
|
|
[self errorWithFormat: @"those column names specified in"
|
|
@" SOGoMailListViewColumnsOrder are invalid: '%@'",
|
|
[invalid componentsJoinedByString: @"', '"]];
|
|
[self errorWithFormat: @" falling back on hardcoded column order"];
|
|
columnsOrder = available;
|
|
}
|
|
|
|
finalOrder = [columnsOrder mutableCopy];
|
|
[finalOrder autorelease];
|
|
|
|
if (![ud mailSortByThreads])
|
|
[finalOrder removeObject: @"Thread"];
|
|
else
|
|
{
|
|
i = [finalOrder indexOfObject: @"Thread"];
|
|
if (i == NSNotFound)
|
|
[finalOrder insertObject: @"Thread" atIndex: 0];
|
|
}
|
|
if ([self showToAddress])
|
|
{
|
|
i = [finalOrder indexOfObject: @"From"];
|
|
if (i != NSNotFound)
|
|
{
|
|
[finalOrder removeObject: @"To"];
|
|
[finalOrder replaceObjectAtIndex: i withObject: @"To"];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
i = [finalOrder indexOfObject: @"To"];
|
|
if (i != NSNotFound)
|
|
{
|
|
[finalOrder removeObject: @"From"];
|
|
[finalOrder replaceObjectAtIndex: i withObject: @"From"];
|
|
}
|
|
}
|
|
|
|
columnsOrder = [[self columnsMetaData] objectsForKeys: finalOrder
|
|
notFoundMarker: @""];
|
|
[columnsOrder retain];
|
|
}
|
|
|
|
return columnsOrder;
|
|
}
|
|
|
|
- (NSString *) columnsDisplayCount
|
|
{
|
|
return [NSString stringWithFormat: @"%d", [[self columnsDisplayOrder] count]];
|
|
}
|
|
|
|
- (void) setCurrentColumn: (NSDictionary *) newCurrentColumn
|
|
{
|
|
ASSIGN (currentColumn, newCurrentColumn);
|
|
}
|
|
|
|
- (NSDictionary *) currentColumn
|
|
{
|
|
return currentColumn;
|
|
}
|
|
|
|
- (NSString *) columnTitle
|
|
{
|
|
return [self labelForKey: [currentColumn objectForKey: @"value"]];
|
|
}
|
|
|
|
- (NSString *) unseenCountFolders
|
|
{
|
|
NSArray *pathComponents, *filters, *actions;
|
|
NSDictionary *d, *action;
|
|
NSMutableArray *folders;
|
|
NSMutableString *path;
|
|
NSString *component;
|
|
SOGoUserDefaults *ud;
|
|
NSString *s;
|
|
NSUInteger i, j, k;
|
|
|
|
// If Sieve scripts aren't enabled, there's no need in considering
|
|
// what's potentially in the database regarding "fileinto" scripts.
|
|
if (![[[context activeUser] domainDefaults] sieveScriptsEnabled])
|
|
return [[NSArray array] jsonRepresentation];
|
|
|
|
ud = [[context activeUser] userDefaults];
|
|
folders = [NSMutableArray array];
|
|
|
|
filters = [ud sieveFilters];
|
|
|
|
for (i = 0; i < [filters count]; i++)
|
|
{
|
|
d = [filters objectAtIndex: i];
|
|
actions = [d objectForKey: @"actions"];
|
|
|
|
for (j = 0; j < [actions count]; j++)
|
|
{
|
|
action = [actions objectAtIndex: j];
|
|
|
|
if ([[action objectForKey: @"method"] caseInsensitiveCompare: @"fileinto"] == NSOrderedSame)
|
|
{
|
|
s = [action objectForKey: @"argument"];
|
|
|
|
// We format the result string so that MailerUI.js can simply consume that information
|
|
// without doing anything special on its side
|
|
if (s)
|
|
{
|
|
pathComponents = [s componentsSeparatedByString: @"/"];
|
|
path = [NSMutableString string];
|
|
|
|
for (k = 0; k < [pathComponents count]; k++)
|
|
{
|
|
component = [[pathComponents objectAtIndex: k] asCSSIdentifier];
|
|
[path appendString: [NSString stringWithFormat: @"folder%@", component]];
|
|
if (k < [pathComponents count] - 1)
|
|
[path appendString: @"/"];
|
|
}
|
|
|
|
[folders addObject: [NSString stringWithFormat: @"/0/%@", path]];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return [folders jsonRepresentation];
|
|
}
|
|
|
|
//
|
|
// Standard mapping done by Thunderbird:
|
|
//
|
|
// label1 => Important
|
|
// label2 => Work
|
|
// label3 => Personal
|
|
// label4 => To Do
|
|
// label5 => Later
|
|
//
|
|
- (NSArray *) availableLabels
|
|
{
|
|
NSDictionary *v;
|
|
|
|
v = [[[context activeUser] userDefaults] mailLabelsColors];
|
|
|
|
return [SOGoMailLabel labelsFromDefaults: v component: self];
|
|
}
|
|
|
|
- (void) setCurrentLabel: (SOGoMailLabel *) theCurrentLabel
|
|
{
|
|
ASSIGN(_currentLabel, theCurrentLabel);
|
|
}
|
|
|
|
- (SOGoMailLabel *) currentLabel
|
|
{
|
|
return _currentLabel;
|
|
}
|
|
|
|
@end /* UIxMailMainFrame */
|