mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-08-02 05:32:18 +00:00
See ChangeLog
Monotone-Parent: 178cf4e5311729ac333305676b5ad2aa35a7ca71 Monotone-Revision: d51bb1b592f986d2e34036c3dad0c70f43f0150a Monotone-Author: ludovic@Sophos.ca Monotone-Date: 2011-06-29T17:43:10 Monotone-Branch: ca.inverse.sogo
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
2011-06-29 Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||
|
||||
* Added get/set/unset capabilities to sogo-tool to set
|
||||
user's defaults/settings. Refactored some code to be
|
||||
more cleanly structured.
|
||||
|
||||
2011-06-24 Francis Lachapelle <flachapelle@inverse.ca>
|
||||
|
||||
* SoObjects/SOGo/SOGoSystemDefaults.m (-loginDomains): new method
|
||||
|
||||
@@ -33,8 +33,6 @@ Mailer_OBJC_FILES += \
|
||||
SOGoMailForward.m \
|
||||
SOGoMailReply.m \
|
||||
\
|
||||
SOGoSieveConverter.m \
|
||||
\
|
||||
EOQualifier+MailDAV.m \
|
||||
NSData+Mail.m \
|
||||
NSString+Mail.m \
|
||||
|
||||
@@ -30,14 +30,12 @@
|
||||
#import <NGObjWeb/SoHTTPAuthenticator.h>
|
||||
#import <NGObjWeb/WORequest.h>
|
||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
#import <NGStreams/NGInternetSocketAddress.h>
|
||||
#import <NGExtensions/NSNull+misc.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
#import <NGExtensions/NSString+misc.h>
|
||||
#import <NGImap4/NGImap4Connection.h>
|
||||
#import <NGImap4/NGImap4Client.h>
|
||||
#import <NGImap4/NGImap4Context.h>
|
||||
#import <NGImap4/NGSieveClient.h>
|
||||
|
||||
#import <SOGo/NSArray+Utilities.h>
|
||||
#import <SOGo/NSString+Utilities.h>
|
||||
@@ -45,13 +43,13 @@
|
||||
#import <SOGo/SOGoDomainDefaults.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
#import <SOGo/SOGoUserDefaults.h>
|
||||
#import <SOGo/SOGoSieveManager.h>
|
||||
|
||||
#import "SOGoDraftsFolder.h"
|
||||
#import "SOGoMailFolder.h"
|
||||
#import "SOGoMailManager.h"
|
||||
#import "SOGoMailNamespace.h"
|
||||
#import "SOGoSentFolder.h"
|
||||
#import "SOGoSieveConverter.h"
|
||||
#import "SOGoTrashFolder.h"
|
||||
#import "SOGoUser+Mailer.h"
|
||||
|
||||
@@ -60,7 +58,6 @@
|
||||
@implementation SOGoMailAccount
|
||||
|
||||
static NSString *inboxFolderName = @"INBOX";
|
||||
static NSString *sieveScriptName = @"sogo";
|
||||
|
||||
- (id) init
|
||||
{
|
||||
@@ -283,228 +280,15 @@ static NSString *sieveScriptName = @"sogo";
|
||||
|
||||
- (BOOL) updateFilters
|
||||
{
|
||||
NSMutableArray *requirements;
|
||||
NSMutableString *script, *header;
|
||||
NGInternetSocketAddress *address;
|
||||
NSDictionary *result, *values;
|
||||
SOGoUserDefaults *ud;
|
||||
SOGoDomainDefaults *dd;
|
||||
NGSieveClient *client;
|
||||
NSString *filterScript, *v, *password, *sieveServer;
|
||||
SOGoSieveConverter *converter;
|
||||
int sievePort;
|
||||
BOOL b;
|
||||
SOGoSieveManager *manager;
|
||||
|
||||
dd = [[context activeUser] domainDefaults];
|
||||
if (!([dd sieveScriptsEnabled] || [dd vacationEnabled] || [dd forwardEnabled]))
|
||||
return YES;
|
||||
manager = [SOGoSieveManager sieveManagerForUser: [context activeUser]];
|
||||
|
||||
requirements = [NSMutableArray arrayWithCapacity: 15];
|
||||
ud = [[context activeUser] userDefaults];
|
||||
b = NO;
|
||||
|
||||
script = [NSMutableString string];
|
||||
|
||||
// Right now, we handle Sieve filters here and only for vacation
|
||||
// and forwards. Traditional filters support (for fileinto, for
|
||||
// example) will be added later.
|
||||
values = [ud vacationOptions];
|
||||
|
||||
// We handle vacation messages.
|
||||
// See http://ietfreport.isoc.org/idref/draft-ietf-sieve-vacation/
|
||||
if (values && [[values objectForKey: @"enabled"] boolValue])
|
||||
{
|
||||
NSArray *addresses;
|
||||
NSString *text;
|
||||
BOOL ignore;
|
||||
int days, i;
|
||||
|
||||
days = [[values objectForKey: @"daysBetweenResponse"] intValue];
|
||||
addresses = [values objectForKey: @"autoReplyEmailAddresses"];
|
||||
ignore = [[values objectForKey: @"ignoreLists"] boolValue];
|
||||
text = [values objectForKey: @"autoReplyText"];
|
||||
b = YES;
|
||||
|
||||
if (days == 0)
|
||||
days = 7;
|
||||
|
||||
[requirements addObjectUniquely: @"vacation"];
|
||||
|
||||
// Skip mailing lists
|
||||
if (ignore)
|
||||
[script appendString: @"if allof ( not exists [\"list-help\", \"list-unsubscribe\", \"list-subscribe\", \"list-owner\", \"list-post\", \"list-archive\", \"list-id\", \"Mailing-List\"], not header :comparator \"i;ascii-casemap\" :is \"Precedence\" [\"list\", \"bulk\", \"junk\"], not header :comparator \"i;ascii-casemap\" :matches \"To\" \"Multiple recipients of*\" ) {"];
|
||||
|
||||
[script appendFormat: @"vacation :days %d :addresses [", days];
|
||||
|
||||
for (i = 0; i < [addresses count]; i++)
|
||||
{
|
||||
[script appendFormat: @"\"%@\"", [addresses objectAtIndex: i]];
|
||||
|
||||
if (i == [addresses count]-1)
|
||||
[script appendString: @"] "];
|
||||
else
|
||||
[script appendString: @", "];
|
||||
}
|
||||
|
||||
[script appendFormat: @"text:\r\n%@\r\n.\r\n;\r\n", text];
|
||||
|
||||
if (ignore)
|
||||
[script appendString: @"}\r\n"];
|
||||
}
|
||||
|
||||
|
||||
// We handle mail forward
|
||||
values = [ud forwardOptions];
|
||||
|
||||
if (values && [[values objectForKey: @"enabled"] boolValue])
|
||||
{
|
||||
id addresses;
|
||||
int i;
|
||||
|
||||
b = YES;
|
||||
|
||||
addresses = [values objectForKey: @"forwardAddress"];
|
||||
if ([addresses isKindOfClass: [NSString class]])
|
||||
addresses = [NSArray arrayWithObject: addresses];
|
||||
|
||||
for (i = 0; i < [addresses count]; i++)
|
||||
{
|
||||
v = [addresses objectAtIndex: i];
|
||||
if (v && [v length] > 0)
|
||||
[script appendFormat: @"redirect \"%@\";\r\n", v];
|
||||
}
|
||||
|
||||
if ([[values objectForKey: @"keepCopy"] boolValue])
|
||||
[script appendString: @"keep;\r\n"];
|
||||
}
|
||||
|
||||
converter = [SOGoSieveConverter sieveConverterForUser: [context activeUser]];
|
||||
filterScript = [converter sieveScriptWithRequirements: requirements];
|
||||
if (filterScript)
|
||||
{
|
||||
if ([filterScript length])
|
||||
{
|
||||
b = YES;
|
||||
[script appendString: filterScript];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[self errorWithFormat: @"Sieve generation failure: %@",
|
||||
[converter lastScriptError]];
|
||||
return NO;
|
||||
}
|
||||
|
||||
if ([requirements count])
|
||||
{
|
||||
header = [NSString stringWithFormat: @"require [\"%@\"];\r\n",
|
||||
[requirements componentsJoinedByString: @"\",\""]];
|
||||
[script insertString: header atIndex: 0];
|
||||
}
|
||||
|
||||
// We connect to our Sieve server and upload the script.
|
||||
//
|
||||
// sieveServer might have the following format:
|
||||
//
|
||||
// sieve://localhost
|
||||
// sieve://localhost:2000
|
||||
//
|
||||
// Values such as "localhost" or "localhost:2000" are NOT supported.
|
||||
//
|
||||
sieveServer = [dd sieveServer];
|
||||
sievePort = 2000;
|
||||
|
||||
if (!sieveServer)
|
||||
{
|
||||
NSString *s;
|
||||
|
||||
sieveServer = @"localhost";
|
||||
s = [dd imapServer];
|
||||
|
||||
if (s)
|
||||
{
|
||||
NSURL *url;
|
||||
|
||||
url = [NSURL URLWithString: s];
|
||||
|
||||
if ([url host])
|
||||
sieveServer = [url host];
|
||||
else
|
||||
sieveServer = s;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSURL *url;
|
||||
|
||||
url = [NSURL URLWithString: sieveServer];
|
||||
|
||||
if ([url host])
|
||||
sieveServer = [url host];
|
||||
|
||||
if ([[url port] intValue] != 0)
|
||||
sievePort = [[url port] intValue];
|
||||
}
|
||||
|
||||
address = [NGInternetSocketAddress addressWithPort: sievePort onHost: sieveServer];
|
||||
|
||||
client = [NGSieveClient clientWithAddress: address];
|
||||
|
||||
if (!client) {
|
||||
[self errorWithFormat: @"Sieve connection failed on %@", [address description]];
|
||||
return NO;
|
||||
}
|
||||
|
||||
password = [self imap4PasswordRenewed: NO];
|
||||
if (!password) {
|
||||
[client closeConnection];
|
||||
return NO;
|
||||
}
|
||||
result = [client login: [[self imap4URL] user] password: password];
|
||||
if (![[result valueForKey:@"result"] boolValue]) {
|
||||
[self errorWithFormat: @"failure. Attempting with a renewed password."];
|
||||
password = [self imap4PasswordRenewed: YES];
|
||||
result = [client login: [[self imap4URL] user] password: password];
|
||||
}
|
||||
|
||||
if (![[result valueForKey:@"result"] boolValue]) {
|
||||
[self errorWithFormat: @"Could not login '%@' on Sieve server: %@: %@",
|
||||
[[self imap4URL] user], client, result];
|
||||
[client closeConnection];
|
||||
return NO;
|
||||
}
|
||||
|
||||
/* We ensure to deactive the current active script since it could prevent
|
||||
its deletion from the server. */
|
||||
result = [client setActiveScript: @""];
|
||||
// We delete the existing Sieve script
|
||||
result = [client deleteScript: sieveScriptName];
|
||||
|
||||
if (![[result valueForKey:@"result"] boolValue]) {
|
||||
[self logWithFormat:@"WARNING: Could not delete Sieve script - continuing...: %@", result];
|
||||
}
|
||||
|
||||
// We put and activate the script only if we actually have a script
|
||||
// that does something...
|
||||
if (b)
|
||||
{
|
||||
result = [client putScript: sieveScriptName script: script];
|
||||
|
||||
if (![[result valueForKey:@"result"] boolValue]) {
|
||||
[self errorWithFormat:@"Could not upload Sieve script: %@", result];
|
||||
[client closeConnection];
|
||||
return NO;
|
||||
}
|
||||
|
||||
result = [client setActiveScript: sieveScriptName];
|
||||
if (![[result valueForKey:@"result"] boolValue]) {
|
||||
[self errorWithFormat:@"Could not enable Sieve script: %@", result];
|
||||
[client closeConnection];
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
return [manager updateFiltersForLogin: [[self imap4URL] user]
|
||||
authname: [[self imap4URL] user]
|
||||
password: [self imap4PasswordRenewed: NO]
|
||||
account: self];
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ SOGo_HEADER_FILES = \
|
||||
SOGoParentFolder.h \
|
||||
SOGoUserFolder.h \
|
||||
\
|
||||
SOGoSieveManager.h \
|
||||
\
|
||||
SOGoUserManager.h \
|
||||
LDAPSource.h \
|
||||
SQLSource.h \
|
||||
@@ -81,6 +83,8 @@ SOGo_OBJC_FILES = \
|
||||
SOGoPublicBaseFolder.m \
|
||||
SOGoUserFolder.m \
|
||||
\
|
||||
SOGoSieveManager.m \
|
||||
\
|
||||
SOGoDefaultsSource.m \
|
||||
SOGoSystemDefaults.m \
|
||||
SOGoDomainDefaults.m \
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/* SOGoSieveConverter.h - this file is part of SOGo
|
||||
/* SOGoSieveManager.h - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2010 Wolfgang Sourdeau
|
||||
* Copyright (C) 2010-2011 Inverse inc.
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
* Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,30 +21,35 @@
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef SOGOSIEVECONVERTER_H
|
||||
#define SOGOSIEVECONVERTER_H
|
||||
#ifndef SOGOSIEVEMANAGER_H
|
||||
#define SOGOSIEVEMANAGER_H
|
||||
|
||||
#import <Foundation/NSObject.h>
|
||||
|
||||
@class NSDictionary;
|
||||
@class NSMutableArray;
|
||||
@class NSString;
|
||||
|
||||
@class SOGoMailAccount;
|
||||
@class SOGoUser;
|
||||
|
||||
@interface SOGoSieveConverter : NSObject
|
||||
@interface SOGoSieveManager : NSObject
|
||||
{
|
||||
SOGoUser *user;
|
||||
NSMutableArray *requirements;
|
||||
NSString *scriptError;
|
||||
}
|
||||
|
||||
+ (id) sieveConverterForUser: (SOGoUser *) user;
|
||||
+ (id) sieveManagerForUser: (SOGoUser *) user;
|
||||
- (id) initForUser: (SOGoUser *) newUser;
|
||||
|
||||
- (NSString *) sieveScriptWithRequirements: (NSMutableArray *) newRequirements;
|
||||
- (NSString *) lastScriptError;
|
||||
|
||||
- (BOOL) updateFiltersForLogin: (NSString *) theLogin
|
||||
authname: (NSString *) theAuthName
|
||||
password: (NSString *) thePassword
|
||||
account: (SOGoMailAccount *) theAccount;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SOGOSIEVECONVERTER_H */
|
||||
#endif /* SOGOSIEVEMANAGER_H */
|
||||
@@ -1,8 +1,9 @@
|
||||
/* SOGoSieveConverter.m - this file is part of SOGo
|
||||
/* SOGoSieveManager.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2010 Wolfgang Sourdeau
|
||||
* Copyright (C) 2010-2011 Inverse inc.
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
* Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -23,6 +24,7 @@
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSURL.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
#import <SOGo/NSArray+Utilities.h>
|
||||
@@ -30,9 +32,12 @@
|
||||
#import <SOGo/SOGoDomainDefaults.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
|
||||
#import "SOGoMailAccounts.h"
|
||||
#import <NGStreams/NGInternetSocketAddress.h>
|
||||
#import <NGImap4/NGSieveClient.h>
|
||||
|
||||
#import "SOGoSieveConverter.h"
|
||||
#import "../Mailer/SOGoMailAccount.h"
|
||||
|
||||
#import "SOGoSieveManager.h"
|
||||
|
||||
typedef enum {
|
||||
UIxFilterFieldTypeAddress,
|
||||
@@ -47,6 +52,8 @@ static NSDictionary *sieveFields = nil;
|
||||
static NSDictionary *sieveFlags = nil;
|
||||
static NSDictionary *operatorRequirements = nil;
|
||||
static NSDictionary *methodRequirements = nil;
|
||||
static NSString *sieveScriptName = @"sogo";
|
||||
|
||||
|
||||
@interface NSString (SOGoSieveExtension)
|
||||
|
||||
@@ -106,7 +113,7 @@ static NSDictionary *methodRequirements = nil;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SOGoSieveConverter
|
||||
@implementation SOGoSieveManager
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
@@ -195,14 +202,14 @@ static NSDictionary *methodRequirements = nil;
|
||||
}
|
||||
}
|
||||
|
||||
+ (id) sieveConverterForUser: (SOGoUser *) newUser
|
||||
+ (id) sieveManagerForUser: (SOGoUser *) newUser
|
||||
{
|
||||
SOGoSieveConverter *newConverter;
|
||||
SOGoSieveManager *newManager;
|
||||
|
||||
newConverter = [[self alloc] initForUser: newUser];
|
||||
[newConverter autorelease];
|
||||
newManager = [[self alloc] initForUser: newUser];
|
||||
[newManager autorelease];
|
||||
|
||||
return newConverter;
|
||||
return newManager;
|
||||
}
|
||||
|
||||
- (id) init
|
||||
@@ -605,4 +612,232 @@ static NSDictionary *methodRequirements = nil;
|
||||
return scriptError;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (BOOL) updateFiltersForLogin: (NSString *) theLogin
|
||||
authname: (NSString *) theAuthName
|
||||
password: (NSString *) thePassword
|
||||
account: (SOGoMailAccount *) theAccount
|
||||
{
|
||||
NSMutableArray *req;
|
||||
NSMutableString *script, *header;
|
||||
NGInternetSocketAddress *address;
|
||||
NSDictionary *result, *values;
|
||||
SOGoUserDefaults *ud;
|
||||
SOGoDomainDefaults *dd;
|
||||
NGSieveClient *client;
|
||||
NSString *filterScript, *v, *sieveServer;
|
||||
int sievePort;
|
||||
BOOL b;
|
||||
|
||||
dd = [user domainDefaults];
|
||||
if (!([dd sieveScriptsEnabled] || [dd vacationEnabled] || [dd forwardEnabled]))
|
||||
return YES;
|
||||
|
||||
req = [NSMutableArray arrayWithCapacity: 15];
|
||||
ud = [user userDefaults];
|
||||
b = NO;
|
||||
|
||||
script = [NSMutableString string];
|
||||
|
||||
// Right now, we handle Sieve filters here and only for vacation
|
||||
// and forwards. Traditional filters support (for fileinto, for
|
||||
// example) will be added later.
|
||||
values = [ud vacationOptions];
|
||||
|
||||
// We handle vacation messages.
|
||||
// See http://ietfreport.isoc.org/idref/draft-ietf-sieve-vacation/
|
||||
if (values && [[values objectForKey: @"enabled"] boolValue])
|
||||
{
|
||||
NSArray *addresses;
|
||||
NSString *text;
|
||||
BOOL ignore;
|
||||
int days, i;
|
||||
|
||||
days = [[values objectForKey: @"daysBetweenResponse"] intValue];
|
||||
addresses = [values objectForKey: @"autoReplyEmailAddresses"];
|
||||
ignore = [[values objectForKey: @"ignoreLists"] boolValue];
|
||||
text = [values objectForKey: @"autoReplyText"];
|
||||
b = YES;
|
||||
|
||||
if (days == 0)
|
||||
days = 7;
|
||||
|
||||
[req addObjectUniquely: @"vacation"];
|
||||
|
||||
// Skip mailing lists
|
||||
if (ignore)
|
||||
[script appendString: @"if allof ( not exists [\"list-help\", \"list-unsubscribe\", \"list-subscribe\", \"list-owner\", \"list-post\", \"list-archive\", \"list-id\", \"Mailing-List\"], not header :comparator \"i;ascii-casemap\" :is \"Precedence\" [\"list\", \"bulk\", \"junk\"], not header :comparator \"i;ascii-casemap\" :matches \"To\" \"Multiple recipients of*\" ) {"];
|
||||
|
||||
[script appendFormat: @"vacation :days %d :addresses [", days];
|
||||
|
||||
for (i = 0; i < [addresses count]; i++)
|
||||
{
|
||||
[script appendFormat: @"\"%@\"", [addresses objectAtIndex: i]];
|
||||
|
||||
if (i == [addresses count]-1)
|
||||
[script appendString: @"] "];
|
||||
else
|
||||
[script appendString: @", "];
|
||||
}
|
||||
|
||||
[script appendFormat: @"text:\r\n%@\r\n.\r\n;\r\n", text];
|
||||
|
||||
if (ignore)
|
||||
[script appendString: @"}\r\n"];
|
||||
}
|
||||
|
||||
|
||||
// We handle mail forward
|
||||
values = [ud forwardOptions];
|
||||
|
||||
if (values && [[values objectForKey: @"enabled"] boolValue])
|
||||
{
|
||||
id addresses;
|
||||
int i;
|
||||
|
||||
b = YES;
|
||||
|
||||
addresses = [values objectForKey: @"forwardAddress"];
|
||||
if ([addresses isKindOfClass: [NSString class]])
|
||||
addresses = [NSArray arrayWithObject: addresses];
|
||||
|
||||
for (i = 0; i < [addresses count]; i++)
|
||||
{
|
||||
v = [addresses objectAtIndex: i];
|
||||
if (v && [v length] > 0)
|
||||
[script appendFormat: @"redirect \"%@\";\r\n", v];
|
||||
}
|
||||
|
||||
if ([[values objectForKey: @"keepCopy"] boolValue])
|
||||
[script appendString: @"keep;\r\n"];
|
||||
}
|
||||
|
||||
filterScript = [self sieveScriptWithRequirements: req];
|
||||
if (filterScript)
|
||||
{
|
||||
if ([filterScript length])
|
||||
{
|
||||
b = YES;
|
||||
[script appendString: filterScript];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"Sieve generation failure: %@", [self lastScriptError]);
|
||||
return NO;
|
||||
}
|
||||
|
||||
if ([req count])
|
||||
{
|
||||
header = [NSString stringWithFormat: @"require [\"%@\"];\r\n",
|
||||
[req componentsJoinedByString: @"\",\""]];
|
||||
[script insertString: header atIndex: 0];
|
||||
}
|
||||
|
||||
// We connect to our Sieve server and upload the script.
|
||||
//
|
||||
// sieveServer might have the following format:
|
||||
//
|
||||
// sieve://localhost
|
||||
// sieve://localhost:2000
|
||||
//
|
||||
// Values such as "localhost" or "localhost:2000" are NOT supported.
|
||||
//
|
||||
sieveServer = [dd sieveServer];
|
||||
sievePort = 2000;
|
||||
|
||||
if (!sieveServer)
|
||||
{
|
||||
NSString *s;
|
||||
|
||||
sieveServer = @"localhost";
|
||||
s = [dd imapServer];
|
||||
|
||||
if (s)
|
||||
{
|
||||
NSURL *url;
|
||||
|
||||
url = [NSURL URLWithString: s];
|
||||
|
||||
if ([url host])
|
||||
sieveServer = [url host];
|
||||
else
|
||||
sieveServer = s;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSURL *url;
|
||||
|
||||
url = [NSURL URLWithString: sieveServer];
|
||||
|
||||
if ([url host])
|
||||
sieveServer = [url host];
|
||||
|
||||
if ([[url port] intValue] != 0)
|
||||
sievePort = [[url port] intValue];
|
||||
}
|
||||
|
||||
address = [NGInternetSocketAddress addressWithPort: sievePort onHost: sieveServer];
|
||||
|
||||
client = [NGSieveClient clientWithAddress: address];
|
||||
|
||||
if (!client) {
|
||||
NSLog(@"Sieve connection failed on %@", [address description]);
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (!thePassword) {
|
||||
[client closeConnection];
|
||||
return NO;
|
||||
}
|
||||
result = [client login: theLogin authname: theAuthName password: thePassword];
|
||||
if (![[result valueForKey:@"result"] boolValue]) {
|
||||
NSLog(@"failure. Attempting with a renewed password (no authname supported)");
|
||||
thePassword = [theAccount imap4PasswordRenewed: YES];
|
||||
result = [client login: theLogin password: thePassword];
|
||||
}
|
||||
|
||||
if (![[result valueForKey:@"result"] boolValue]) {
|
||||
NSLog(@"Could not login '%@' on Sieve server: %@: %@",
|
||||
theLogin, client, result);
|
||||
[client closeConnection];
|
||||
return NO;
|
||||
}
|
||||
|
||||
/* We ensure to deactive the current active script since it could prevent
|
||||
its deletion from the server. */
|
||||
result = [client setActiveScript: @""];
|
||||
// We delete the existing Sieve script
|
||||
result = [client deleteScript: sieveScriptName];
|
||||
|
||||
if (![[result valueForKey:@"result"] boolValue]) {
|
||||
NSLog(@"WARNING: Could not delete Sieve script - continuing...: %@", result);
|
||||
}
|
||||
|
||||
// We put and activate the script only if we actually have a script
|
||||
// that does something...
|
||||
if (b)
|
||||
{
|
||||
result = [client putScript: sieveScriptName script: script];
|
||||
|
||||
if (![[result valueForKey:@"result"] boolValue]) {
|
||||
NSLog(@"Could not upload Sieve script: %@", result);
|
||||
[client closeConnection];
|
||||
return NO;
|
||||
}
|
||||
|
||||
result = [client setActiveScript: sieveScriptName];
|
||||
if (![[result valueForKey:@"result"] boolValue]) {
|
||||
NSLog(@"Could not enable Sieve script: %@", result);
|
||||
[client closeConnection];
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SOGoUserSettings.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2009-2010 Inverse inc.
|
||||
* Copyright (C) 2009-2011 Inverse inc.
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
|
||||
@@ -16,6 +16,7 @@ $(SOGO_TOOL)_OBJC_FILES += \
|
||||
SOGoToolRemoveDoubles.m \
|
||||
SOGoToolRemove.m \
|
||||
SOGoToolRenameUser.m \
|
||||
SOGoToolUserPreferences.m
|
||||
|
||||
SOGO_SLAPD_SOCKD = sogo-slapd-sockd
|
||||
$(SOGO_SLAPD_SOCKD)_INSTALL_DIR = $(SOGO_ADMIN_TOOLS)
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* SOGoTool.h - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2009 Inverse inc.
|
||||
* Copyright (C) 2009-2011 Inverse inc.
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* SOGoTool.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2009 Inverse inc.
|
||||
* Copyright (C) 2009-2011 Inverse inc.
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
/* SOGoToolUserPreferences.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2011 Inverse inc.
|
||||
*
|
||||
* Author: Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import <SOGo/NSString+Utilities.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
#import <SOGo/SOGoUserDefaults.h>
|
||||
#import <SOGo/SOGoUserSettings.h>
|
||||
#import <SOGo/SOGoSieveManager.h>
|
||||
|
||||
#import "SOGoTool.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UserPreferencesUnknown = -1,
|
||||
UserPreferencesGet = 0,
|
||||
UserPreferencesSet = 1,
|
||||
UserPreferencesUnset = 2,
|
||||
} SOGoUserPreferencesCommand;
|
||||
|
||||
@interface SOGoToolUserPreferences : SOGoTool
|
||||
@end
|
||||
|
||||
@implementation SOGoToolUserPreferences
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
}
|
||||
|
||||
+ (NSString *) command
|
||||
{
|
||||
return @"user-preferences";
|
||||
}
|
||||
|
||||
+ (NSString *) description
|
||||
{
|
||||
return @"set user defaults / settings in the database";
|
||||
}
|
||||
|
||||
- (void) usage
|
||||
{
|
||||
fprintf (stderr, "user-preferences get|set|unset defaults|settings user [authname:authpassword] key value\n\n"
|
||||
" user the user of whom to set the defaults/settings key/value\n");
|
||||
}
|
||||
|
||||
//
|
||||
// possible values are: get | set | unset
|
||||
//
|
||||
- (SOGoUserPreferencesCommand) _cmdFromString: (NSString *) theString
|
||||
{
|
||||
if ([theString length] > 2)
|
||||
{
|
||||
if ([theString caseInsensitiveCompare: @"get"] == NSOrderedSame)
|
||||
return UserPreferencesGet;
|
||||
else if ([theString caseInsensitiveCompare: @"set"] == NSOrderedSame)
|
||||
return UserPreferencesSet;
|
||||
else if ([theString caseInsensitiveCompare: @"unset"] == NSOrderedSame)
|
||||
return UserPreferencesUnset; }
|
||||
|
||||
return UserPreferencesUnknown;
|
||||
}
|
||||
|
||||
// If we got any of those keys for "defaults", we regenerate the Sieve script
|
||||
//
|
||||
// Forward
|
||||
// SOGoSieveFilters
|
||||
// Vacation
|
||||
//
|
||||
- (BOOL) _updateSieveScripsForkey: (NSString *) theKey
|
||||
manager: (SOGoSieveManager *) theManager
|
||||
login: (NSString *) theLogin
|
||||
authname: (NSString *) theAuthName
|
||||
password: (NSString *) thePassword
|
||||
{
|
||||
if ([theKey caseInsensitiveCompare: @"Forward"] == NSOrderedSame ||
|
||||
[theKey caseInsensitiveCompare: @"SOGoSieveFilters"] == NSOrderedSame ||
|
||||
[theKey caseInsensitiveCompare: @"Vacation"] == NSOrderedSame)
|
||||
{
|
||||
if ([theAuthName length] == 0 || [thePassword length] == 0)
|
||||
{
|
||||
NSLog(@"To update Sieve scripts, you must provide the \"authname:password\" parameter");
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [theManager updateFiltersForLogin: theLogin
|
||||
authname: theAuthName
|
||||
password: thePassword
|
||||
account: nil];
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (BOOL) run
|
||||
{
|
||||
NSString *userId, *type, *key;
|
||||
SOGoUserPreferencesCommand cmd;
|
||||
id o;
|
||||
|
||||
NSRange r;
|
||||
BOOL rc;
|
||||
int max;
|
||||
|
||||
max = [arguments count];
|
||||
rc = NO;
|
||||
|
||||
if (max > 3)
|
||||
{
|
||||
SOGoDefaultsSource *source;
|
||||
SOGoSieveManager *manager;
|
||||
SOGoUser *user;
|
||||
|
||||
cmd = [self _cmdFromString: [arguments objectAtIndex: 0]];
|
||||
|
||||
if (cmd != UserPreferencesUnknown)
|
||||
{
|
||||
type = [arguments objectAtIndex: 1];
|
||||
userId = [arguments objectAtIndex: 2];
|
||||
key = [arguments objectAtIndex: 3];
|
||||
|
||||
user = [SOGoUser userWithLogin: userId];
|
||||
manager = [SOGoSieveManager sieveManagerForUser: user];
|
||||
|
||||
if ([type caseInsensitiveCompare: @"defaults"] == NSOrderedSame)
|
||||
source = [user userDefaults];
|
||||
else
|
||||
source = [user userSettings];
|
||||
|
||||
if (cmd == UserPreferencesGet)
|
||||
{
|
||||
o = [source objectForKey: key];
|
||||
|
||||
if (o)
|
||||
NSLog(@"value for key \"%@\": %@", key, [o jsonRepresentation]);
|
||||
else
|
||||
NSLog(@"Value for key \"%@\" not found in %@", key, type);
|
||||
|
||||
rc = YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *authname, *authpwd, *value;
|
||||
|
||||
authname = @"";
|
||||
authpwd = @"";
|
||||
value = @"";
|
||||
|
||||
if (max > 4)
|
||||
{
|
||||
r = [[arguments objectAtIndex: 3] rangeOfString: @":"];
|
||||
authname = [[arguments objectAtIndex: 3] substringToIndex: r.location];
|
||||
authpwd = [[arguments objectAtIndex: 3] substringFromIndex: r.location+1];
|
||||
key = [arguments objectAtIndex: 4];
|
||||
|
||||
if (max > 5)
|
||||
value = [arguments objectAtIndex: 5];
|
||||
}
|
||||
else
|
||||
{
|
||||
key = [arguments objectAtIndex: 3];
|
||||
value = [arguments objectAtIndex: 4];
|
||||
}
|
||||
|
||||
if (cmd == UserPreferencesUnset)
|
||||
[source removeObjectForKey: key];
|
||||
else
|
||||
{
|
||||
o = [value objectFromJSONString];
|
||||
|
||||
//
|
||||
// We support setting only "values" - for example, setting :
|
||||
//
|
||||
// SOGoDayStartTime to 9:00
|
||||
//
|
||||
// Values in JSON must be a dictionary so we must support passing:
|
||||
//
|
||||
// key == SOGoDayStartTime
|
||||
// value == '{"SOGoDayStartTime": "09:00"}'
|
||||
//
|
||||
// to achieve what we want.
|
||||
//
|
||||
if (o && [o count] == 1)
|
||||
{
|
||||
[source setObject: [[o allValues] lastObject] forKey: key];
|
||||
}
|
||||
//
|
||||
// We also support passing values that are already dictionaries so in this
|
||||
// case, we simply set it to the passed key.
|
||||
//
|
||||
else if (o)
|
||||
{
|
||||
[source setObject: o forKey: key];
|
||||
}
|
||||
else
|
||||
NSLog(@"Invalid JSON input - no changes performed in the database.");
|
||||
}
|
||||
|
||||
[source synchronize];
|
||||
rc = [self _updateSieveScripsForkey: key
|
||||
manager: manager
|
||||
login: userId
|
||||
authname: authname
|
||||
password: authpwd];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!rc)
|
||||
{
|
||||
[self usage];
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user