Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f96905c3a | ||
|
|
10d789fb1f | ||
|
|
d505b874f7 | ||
|
|
cbeaa4cc11 | ||
|
|
427f7f4b4f | ||
|
|
d68bbc836c | ||
|
|
51b6c0d9a3 | ||
|
|
5f2e4889f3 | ||
|
|
37379ba416 | ||
|
|
17eca6f96a | ||
|
|
26c7462eb0 | ||
|
|
9ef49bb56f | ||
|
|
54a1f922f9 | ||
|
|
64a6319635 | ||
|
|
31c6f78913 |
No files matched your search
@@ -826,7 +826,17 @@ specified as an array of dictionaries.
|
||||
|D |SOGoCreateIdentitiesDisabled
|
||||
|Disable identity creation for users in preferences. If `YES`, users won't be able to add new identities and will allow to change only full name, signature and default identity. Default value is `NO`. Note : If this settings is set to `YES`, it will not be possible to crete auxiliary mail accounts.
|
||||
|
||||
|S |SOGoURLEncryptionEnabled
|
||||
|Enable URL encryption to make SOGo GDPR compatible. Setting this parameter to `YES` will encrypt username in URL. The encryption data are cached to avoid high cpu usage, ig the value of thie parameter is changed, memcached server needs to be restarted. If the encryption is enabled, the DAV url will change. Default value is `NO`.
|
||||
|
||||
|S |SOGoURLEncryptionPassphrase
|
||||
|Passphrase for `SOGoURLEncryptionEnabled`. The string must be 128 bits (16 characters). If this settings change, the cache server must be restarted, and the DAV url will change. Default value is `SOGoSuperSecret0`.
|
||||
|
||||
|S |SOGoGlobalAddressBookFirstEntries
|
||||
|Display first entries in Global Address Book. Default value is `NO`. If source is LDAP, the LDAP overlay `sssvlv` must be enabled on the system for server side sorting.
|
||||
|
||||
|S |SOGoGlobalAddressBookFirstEntriesCount
|
||||
|Number of entries displayed when `SOGoGlobalAddressBookFirstEntries` is enabled. Default value is `100`.
|
||||
|
||||
|=======================================================================
|
||||
|
||||
|
||||
+11
-4
@@ -349,8 +349,11 @@ static BOOL debugLeaks;
|
||||
{
|
||||
if ([[context request] handledByDefaultHandler])
|
||||
authenticator = [SOGoWebAuthenticator sharedSOGoWebAuthenticator];
|
||||
else
|
||||
else {
|
||||
authenticator = [SOGoDAVAuthenticator sharedSOGoDAVAuthenticator];
|
||||
[authenticator setContext: context];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return authenticator;
|
||||
@@ -363,10 +366,14 @@ static BOOL debugLeaks;
|
||||
{
|
||||
SOGoUser *user;
|
||||
id userFolder;
|
||||
|
||||
user = [SOGoUser userWithLogin: _key roles: nil];
|
||||
NSData *decodedLogin;
|
||||
NSString *login;
|
||||
|
||||
login = [SOGoUser getDecryptedUsernameIfNeeded: _key withContext: _ctx];
|
||||
|
||||
user = [SOGoUser userWithLogin: login roles: nil];
|
||||
if (user)
|
||||
userFolder = [$(@"SOGoUserFolder") objectWithName: _key
|
||||
userFolder = [$(@"SOGoUserFolder") objectWithName: login
|
||||
inContainer: self];
|
||||
else
|
||||
userFolder = nil;
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
}
|
||||
|
||||
tag = [NSArray arrayWithObjects: @"href", XMLNS_WEBDAV, @"D",
|
||||
[NSString stringWithFormat: @"/SOGo/dav/%@/", nameInContainer],
|
||||
[NSString stringWithFormat: @"/SOGo/dav/%@/", [self nameInContainer]],
|
||||
nil];
|
||||
[addresses addObjectUniquely: tag];
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
}
|
||||
|
||||
tag = [NSArray arrayWithObjects: @"href", XMLNS_WEBDAV, @"D",
|
||||
[NSString stringWithFormat: @"/SOGo/dav/%@/", nameInContainer],
|
||||
[NSString stringWithFormat: @"/SOGo/dav/%@/", [self nameInContainer]],
|
||||
nil];
|
||||
[addresses addObjectUniquely: tag];
|
||||
|
||||
|
||||
@@ -434,26 +434,43 @@
|
||||
{
|
||||
NSArray *records, *result;
|
||||
EOSortOrdering *ordering;
|
||||
BOOL processed;
|
||||
|
||||
result = nil;
|
||||
processed = NO;
|
||||
|
||||
if ([filter length] > 0 || ![source listRequiresDot])
|
||||
[source setListRequiresDot: NO];
|
||||
if ( ![source listRequiresDot])
|
||||
{
|
||||
records = [source fetchContactsMatching: filter
|
||||
if ([filter length] > 0) {
|
||||
records = [source fetchContactsMatching: filter
|
||||
withCriteria: criteria
|
||||
inDomain: domain];
|
||||
[childRecords setObjects: records
|
||||
forKeys: [records objectsForKey: @"c_name"
|
||||
notFoundMarker: nil]];
|
||||
records = [self _flattenedRecords: records];
|
||||
ordering
|
||||
= [EOSortOrdering sortOrderingWithKey: sortKey
|
||||
selector: ((sortOrdering == NSOrderedDescending)
|
||||
? EOCompareCaseInsensitiveDescending
|
||||
: EOCompareCaseInsensitiveAscending)];
|
||||
result
|
||||
= [records sortedArrayUsingKeyOrderArray:
|
||||
[NSArray arrayWithObject: ordering]];
|
||||
processed = YES;
|
||||
} else if ([[SOGoSystemDefaults sharedSystemDefaults] globalAddressBookFirstEntriesEnabled]) {
|
||||
records = [source fetchContactsMatching: filter
|
||||
withCriteria: criteria
|
||||
inDomain: domain
|
||||
limit: [[SOGoSystemDefaults sharedSystemDefaults] globalAddressBookFirstEntriesCount]];
|
||||
processed = YES;
|
||||
}
|
||||
|
||||
if (processed) {
|
||||
[childRecords setObjects: records
|
||||
forKeys: [records objectsForKey: @"c_name"
|
||||
notFoundMarker: nil]];
|
||||
records = [self _flattenedRecords: records];
|
||||
ordering
|
||||
= [EOSortOrdering sortOrderingWithKey: sortKey
|
||||
selector: ((sortOrdering == NSOrderedDescending)
|
||||
? EOCompareCaseInsensitiveDescending
|
||||
: EOCompareCaseInsensitiveAscending)];
|
||||
result
|
||||
= [records sortedArrayUsingKeyOrderArray:
|
||||
[NSArray arrayWithObject: ordering]];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
+59
-12
@@ -1384,6 +1384,21 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses
|
||||
- (NSArray *) fetchContactsMatching: (NSString *) match
|
||||
withCriteria: (NSArray *) criteria
|
||||
inDomain: (NSString *) theDomain
|
||||
{
|
||||
if ([match length] > 0) {
|
||||
return [self fetchContactsMatching: (NSString *) match
|
||||
withCriteria: (NSArray *) criteria
|
||||
inDomain: (NSString *) theDomain
|
||||
limit: -1];
|
||||
} else {
|
||||
return [NSMutableArray array];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *) fetchContactsMatching: (NSString *) match
|
||||
withCriteria: (NSArray *) criteria
|
||||
inDomain: (NSString *) theDomain
|
||||
limit: (int) limit
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
NGLdapConnection *ldapConnection;
|
||||
@@ -1392,6 +1407,8 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses
|
||||
NSMutableArray *contacts;
|
||||
EOQualifier *qualifier;
|
||||
unsigned int i;
|
||||
NSString *sortAttribute;
|
||||
BOOL sortReverse;
|
||||
|
||||
contacts = [NSMutableArray array];
|
||||
|
||||
@@ -1400,18 +1417,48 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses
|
||||
ldapConnection = [self _ldapConnection];
|
||||
qualifier = [self _qualifierForFilter: match onCriteria: criteria];
|
||||
|
||||
if ([_scope caseInsensitiveCompare: @"BASE"] == NSOrderedSame)
|
||||
entries = [ldapConnection baseSearchAtBaseDN: _baseDN
|
||||
qualifier: qualifier
|
||||
attributes: _lookupFields];
|
||||
else if ([_scope caseInsensitiveCompare: @"ONE"] == NSOrderedSame)
|
||||
entries = [ldapConnection flatSearchAtBaseDN: _baseDN
|
||||
qualifier: qualifier
|
||||
attributes: _lookupFields];
|
||||
else /* we do it like before */
|
||||
entries = [ldapConnection deepSearchAtBaseDN: _baseDN
|
||||
qualifier: qualifier
|
||||
attributes: _lookupFields];
|
||||
if (limit > 0) {
|
||||
[ldapConnection setQuerySizeLimit: limit];
|
||||
}
|
||||
|
||||
if (limit > 0) {
|
||||
// Sort results
|
||||
sortAttribute = @"cn";
|
||||
sortReverse = NO;
|
||||
if ([_scope caseInsensitiveCompare: @"BASE"] == NSOrderedSame)
|
||||
entries = [ldapConnection baseSearchAtBaseDN: _baseDN
|
||||
qualifier: qualifier
|
||||
attributes: _lookupFields
|
||||
sortAttribute: sortAttribute
|
||||
sortReverse: sortReverse];
|
||||
else if ([_scope caseInsensitiveCompare: @"ONE"] == NSOrderedSame)
|
||||
entries = [ldapConnection flatSearchAtBaseDN: _baseDN
|
||||
qualifier: qualifier
|
||||
attributes: _lookupFields
|
||||
sortAttribute: sortAttribute
|
||||
sortReverse: sortReverse];
|
||||
else /* we do it like before */
|
||||
entries = [ldapConnection deepSearchAtBaseDN: _baseDN
|
||||
qualifier: qualifier
|
||||
attributes: _lookupFields
|
||||
sortAttribute: sortAttribute
|
||||
sortReverse: sortReverse];
|
||||
} else {
|
||||
// No sort results
|
||||
if ([_scope caseInsensitiveCompare: @"BASE"] == NSOrderedSame)
|
||||
entries = [ldapConnection baseSearchAtBaseDN: _baseDN
|
||||
qualifier: qualifier
|
||||
attributes: _lookupFields];
|
||||
else if ([_scope caseInsensitiveCompare: @"ONE"] == NSOrderedSame)
|
||||
entries = [ldapConnection flatSearchAtBaseDN: _baseDN
|
||||
qualifier: qualifier
|
||||
attributes: _lookupFields];
|
||||
else /* we do it like before */
|
||||
entries = [ldapConnection deepSearchAtBaseDN: _baseDN
|
||||
qualifier: qualifier
|
||||
attributes: _lookupFields];
|
||||
}
|
||||
|
||||
|
||||
i = 0;
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#define NSSTRING_CRYPTO_H
|
||||
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef enum {
|
||||
encDefault, //!< default encoding, let the algorithm decide
|
||||
@@ -35,8 +36,10 @@ typedef enum {
|
||||
} keyEncoding;
|
||||
|
||||
@class NSObject;
|
||||
@class NSScanner;
|
||||
|
||||
@interface NSString (SOGoCryptoExtension)
|
||||
@interface
|
||||
NSString(SOGoCryptoExtension)
|
||||
|
||||
- (BOOL) isEqualToCrypted: (NSString *) cryptedPassword
|
||||
withDefaultScheme: (NSString *) theScheme
|
||||
@@ -62,6 +65,9 @@ typedef enum {
|
||||
|
||||
+ (NSArray *) getDefaultEncodingForScheme: (NSString *) passwordScheme;
|
||||
|
||||
- (NSString *) encodeAES128ECBBase64:(NSString *)passwordScheme encodedURL:(BOOL)encodedURL exception:(NSException **)ex;
|
||||
- (NSString *) decodeAES128ECBBase64:(NSString *)passwordScheme encodedURL:(BOOL)encodedURL exception:(NSException **)ex;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* NSSTRING_CRYPTO_H */
|
||||
@@ -29,6 +29,11 @@
|
||||
#import "NSData+Crypto.h"
|
||||
#import <NGExtensions/NGBase64Coding.h>
|
||||
|
||||
#import "aes.h"
|
||||
#define AES_SIZE 8096
|
||||
#define AES_KEY_SIZE 16
|
||||
|
||||
static const NSString *kAES128ECError = @"kAES128ECError";
|
||||
|
||||
@implementation NSString (SOGoCryptoExtension)
|
||||
|
||||
@@ -349,4 +354,135 @@
|
||||
return [[NSData encodeDataAsHexString: [d asLM]] uppercaseString];
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the data using AES 128 ECB mechanism
|
||||
*
|
||||
* @param passwordScheme The 128 bits password key
|
||||
* @param encodedURL YES if the special base64 characters shall be escaped for URL
|
||||
* @param ex Exception pointer
|
||||
* @return If successful, encrypted string in base64
|
||||
*/
|
||||
- (NSString *) encodeAES128ECBBase64:(NSString *)passwordScheme encodedURL:(BOOL)encodedURL exception:(NSException **)ex
|
||||
{
|
||||
NSData *inputData, *keyData, *outputData;
|
||||
|
||||
if (AES_KEY_SIZE != [passwordScheme length]) {
|
||||
*ex = [NSException exceptionWithName:kAES128ECError reason: [NSString stringWithFormat:@"Key must be %d bits", (AES_KEY_SIZE * 8)] userInfo: nil];
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *value;
|
||||
int size, i;
|
||||
uint8_t output[AES_SIZE], input[AES_SIZE];
|
||||
|
||||
inputData = [self dataUsingEncoding: NSUnicodeStringEncoding];
|
||||
keyData = [passwordScheme dataUsingEncoding: NSUnicodeStringEncoding];
|
||||
size = [inputData length] + 16; // Add one unicode char size 16 bits (NUL)
|
||||
|
||||
if (inputData == nil) {
|
||||
*ex = [NSException exceptionWithName:kAES128ECError reason: @"Invalid input data (encrypt)" userInfo: nil];
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (((AES_SIZE / 2) - 16) < [self length]) {
|
||||
*ex = [NSException exceptionWithName:kAES128ECError reason: [NSString stringWithFormat:@"Invalid size (encrypt). max size is %d. Current size : %d", ((AES_SIZE / 2) - 16), [self length]] userInfo: nil];
|
||||
return nil;
|
||||
}
|
||||
|
||||
memset(output, 0x00, AES_SIZE);
|
||||
memset(input, 0x00, AES_SIZE);
|
||||
|
||||
[inputData getBytes: input length: [inputData length]];
|
||||
input[[inputData length]] = '\0'; // Add NUL
|
||||
|
||||
|
||||
for(i = 0 ; i < (AES_SIZE / 16) ; ++i)
|
||||
{
|
||||
AES128_ECB_encrypt(input + (i*16), [keyData bytes], output+(i*16));
|
||||
}
|
||||
|
||||
outputData = [NSData dataWithBytes: (char *)output length: size];
|
||||
|
||||
if (outputData) {
|
||||
value = [outputData base64EncodedStringWithOptions: 0];
|
||||
if (encodedURL) {
|
||||
value = [value stringByReplacingOccurrencesOfString: @"+" withString: @"."];
|
||||
value = [value stringByReplacingOccurrencesOfString: @"/" withString: @"_"];
|
||||
value = [value stringByReplacingOccurrencesOfString: @"=" withString: @"-"];
|
||||
}
|
||||
|
||||
return value;
|
||||
} else {
|
||||
*ex = [NSException exceptionWithName:kAES128ECError reason:@"Empty data" userInfo: nil];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the base64 data using AES 128 ECB mechanism
|
||||
*
|
||||
* @param passwordScheme The 128 bits password key
|
||||
* @param encodedURL YES if the special base64 characters has been escaped for URL
|
||||
* @param ex Exception pointer
|
||||
* @return If successful, decrypted string
|
||||
*/
|
||||
- (NSString *) decodeAES128ECBBase64:(NSString *)passwordScheme encodedURL:(BOOL)encodedURL exception:(NSException **)ex
|
||||
{
|
||||
NSData *inputData, *keyData, *outputData;
|
||||
NSString *value, *inputString, *tmpStr;
|
||||
int i;
|
||||
uint8_t output[AES_SIZE];
|
||||
|
||||
if (AES_KEY_SIZE != [passwordScheme length]) {
|
||||
*ex = [NSException exceptionWithName:kAES128ECError reason: [NSString stringWithFormat:@"Key must be %d bits", (AES_KEY_SIZE * 8)] userInfo: nil];
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
value = nil;
|
||||
keyData = [passwordScheme dataUsingEncoding: NSUnicodeStringEncoding];
|
||||
memset(output, 0x00, AES_SIZE);
|
||||
|
||||
inputString = [NSString stringWithString: self];
|
||||
if (encodedURL) {
|
||||
inputString = [inputString stringByReplacingOccurrencesOfString: @"." withString: @"+"];
|
||||
inputString = [inputString stringByReplacingOccurrencesOfString: @"_" withString: @"/"];
|
||||
inputString = [inputString stringByReplacingOccurrencesOfString: @"-" withString: @"="];
|
||||
}
|
||||
|
||||
inputData = [[NSData alloc] initWithBase64EncodedString:inputString options:0];
|
||||
|
||||
if (inputData == nil) {
|
||||
*ex = [NSException exceptionWithName:kAES128ECError reason: @"Invalid input data (decrypt)" userInfo: nil];
|
||||
return nil;
|
||||
}
|
||||
|
||||
if ((AES_SIZE) < [inputData length]) {
|
||||
*ex = [NSException exceptionWithName:kAES128ECError reason: [NSString stringWithFormat:@"Invalid size (decrypt). max size is %d. Current size : %d", AES_SIZE, [inputData length]] userInfo: nil];
|
||||
return nil;
|
||||
}
|
||||
|
||||
for(i = 0; i < (AES_SIZE / 16); ++i)
|
||||
{
|
||||
AES128_ECB_decrypt([inputData bytes] + (i*16), [keyData bytes], output + (i*16));
|
||||
}
|
||||
|
||||
outputData = [NSData dataWithBytes: output length:([inputData length] - 16)];
|
||||
if (outputData) {
|
||||
tmpStr = [[NSString alloc] initWithData: outputData encoding: NSUnicodeStringEncoding];
|
||||
if (tmpStr) {
|
||||
value = [NSString stringWithUTF8String: [tmpStr UTF8String]];
|
||||
} else {
|
||||
*ex = [NSException exceptionWithName:kAES128ECError reason:@"Empty converted decrypted data" userInfo: nil];
|
||||
value = nil;
|
||||
}
|
||||
[tmpStr release];
|
||||
} else {
|
||||
*ex = [NSException exceptionWithName:kAES128ECError reason:@"Empty data" userInfo: nil];
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -29,6 +29,8 @@
|
||||
|
||||
@interface SOGoDAVAuthenticator : SoHTTPAuthenticator <SOGoAuthenticator>
|
||||
|
||||
WOContext *context;
|
||||
|
||||
+ (id) sharedSOGoDAVAuthenticator;
|
||||
|
||||
@end
|
||||
|
||||
@@ -41,12 +41,19 @@
|
||||
{
|
||||
static SOGoDAVAuthenticator *auth = nil;
|
||||
|
||||
if (!auth)
|
||||
if (!auth) {
|
||||
auth = [self new];
|
||||
context = nil;
|
||||
}
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
- (void) setContext: (WOContext *) _context
|
||||
{
|
||||
context = _context;
|
||||
}
|
||||
|
||||
- (BOOL) checkLogin: (NSString *) _login
|
||||
password: (NSString *) _pwd
|
||||
{
|
||||
@@ -68,6 +75,10 @@
|
||||
expire: &expire
|
||||
grace: &grace]
|
||||
&& perr == PolicyNoError);
|
||||
if (context) {
|
||||
[SOGoUser getEncryptedUsernameIfNeeded: [_login stringByReplacingString: @"%40"
|
||||
withString: @"@"] withContext: context]; // Create cache entry
|
||||
}
|
||||
if (!rc)
|
||||
{
|
||||
sd = [SOGoSystemDefaults sharedSystemDefaults];
|
||||
|
||||
@@ -533,7 +533,7 @@ static NSArray *childRecordFields = nil;
|
||||
publicParticle = @"";
|
||||
path = [NSString stringWithFormat: @"/%@/dav%@/%@/%@/%@/",
|
||||
appName, publicParticle,
|
||||
[[self ownerInContext: nil] stringByEscapingURL],
|
||||
[[SOGoUser getEncryptedUsernameIfNeeded:[self ownerInContext: nil] withContext: context] stringByEscapingURL],
|
||||
[[container nameInContainer] stringByEscapingURL],
|
||||
[[self realNameInContainer] stringByEscapingURL]];
|
||||
currentDavURL = [self davURL];
|
||||
|
||||
@@ -365,7 +365,7 @@
|
||||
NSString *usersUrl;
|
||||
|
||||
usersUrl = [NSString stringWithFormat: @"%@%@/",
|
||||
[[WOApplication application] davURLAsString], owner];
|
||||
[[WOApplication application] davURLAsString], [SOGoUser getEncryptedUsernameIfNeeded: owner withContext: context]];
|
||||
ownerHREF = davElementWithContent (@"href", XMLNS_WEBDAV, usersUrl);
|
||||
|
||||
return [davElementWithContent (@"owner", XMLNS_WEBDAV, ownerHREF)
|
||||
@@ -1227,7 +1227,7 @@
|
||||
davCurrentUserPrincipal = nil;
|
||||
else
|
||||
{
|
||||
s = [NSString stringWithFormat: @"/SOGo/dav/%@", login];
|
||||
s = [NSString stringWithFormat: @"/SOGo/dav/%@", [SOGoUser getEncryptedUsernameIfNeeded:login withContext:[self context]]];
|
||||
userHREF = davElementWithContent (@"href", XMLNS_WEBDAV, s);
|
||||
davCurrentUserPrincipal
|
||||
= [davElementWithContent (@"current-user-principal",
|
||||
|
||||
@@ -32,9 +32,11 @@
|
||||
acquire: (BOOL) acquire
|
||||
{
|
||||
id userFolder;
|
||||
NSString *login;
|
||||
|
||||
if ([key length] > 0 && [SOGoUser userWithLogin: key roles: nil])
|
||||
userFolder = [SOGoUserFolder objectWithName: key inContainer: self];
|
||||
login = [SOGoUser getDecryptedUsernameIfNeeded: key withContext: localContext];
|
||||
if ([key length] > 0 && [SOGoUser userWithLogin: login roles: nil])
|
||||
userFolder = [SOGoUserFolder objectWithName: login inContainer: self];
|
||||
else
|
||||
userFolder = nil;
|
||||
|
||||
|
||||
@@ -75,6 +75,11 @@
|
||||
- (NSArray *) fetchContactsMatching: (NSString *) filter
|
||||
withCriteria: (NSArray *) criteria
|
||||
inDomain: (NSString *) domain;
|
||||
- (NSArray *)fetchContactsMatching:(NSString *)filter
|
||||
withCriteria:(NSArray *)criteria
|
||||
inDomain:(NSString *)domain
|
||||
limit:(int)limit;
|
||||
|
||||
- (NSArray *) lookupContactsWithQualifier: (EOQualifier *) qualifier
|
||||
andSortOrdering: (EOSortOrdering *) ordering
|
||||
inDomain: (NSString *) domain;
|
||||
|
||||
@@ -133,6 +133,12 @@ NSComparisonResult languageSort(id el1, id el2, void *context);
|
||||
- (NSArray *) disableSharingAnyAuthUser;
|
||||
- (NSArray *) disableExport;
|
||||
|
||||
- (BOOL) enableGlobalAddressBookFirstEntries;
|
||||
- (int) globalAddressBookFirstEntriesCount;
|
||||
|
||||
- (BOOL)isURLEncryptionEnabled;
|
||||
- (NSString *)urlEncryptionPassphrase;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SOGOSYSTEMDEFAULTS_H */
|
||||
@@ -819,6 +819,22 @@ NSComparisonResult languageSort(id el1, id el2, void *context)
|
||||
return disableSharing;
|
||||
}
|
||||
|
||||
- (BOOL)isURLEncryptionEnabled {
|
||||
return [self boolForKey: @"SOGoURLEncryptionEnabled"];
|
||||
}
|
||||
|
||||
- (NSString *) urlEncryptionPassphrase
|
||||
{
|
||||
NSString *passphrase;
|
||||
|
||||
passphrase = [self stringForKey: @"SOGoURLEncryptionPassphrase"];
|
||||
|
||||
if (!passphrase)
|
||||
passphrase = @"SOGoSuperSecret0"; // Default passphrase
|
||||
|
||||
return passphrase;
|
||||
}
|
||||
|
||||
- (NSArray *) disableSharingAnyAuthUser
|
||||
{
|
||||
static NSArray *disableSharingAnyAuthUser = nil;
|
||||
@@ -845,4 +861,21 @@ NSComparisonResult languageSort(id el1, id el2, void *context)
|
||||
return disableExport;
|
||||
}
|
||||
|
||||
- (BOOL) globalAddressBookFirstEntriesEnabled
|
||||
{
|
||||
return [self boolForKey: @"SOGoGlobalAddressBookFirstEntries"];
|
||||
}
|
||||
|
||||
- (int) globalAddressBookFirstEntriesCount
|
||||
{
|
||||
int v;
|
||||
|
||||
v = [self integerForKey: @"SOGoGlobalAddressBookFirstEntriesCount"];
|
||||
|
||||
if (!v)
|
||||
v = 100;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -135,6 +135,10 @@
|
||||
- (SOGoAppointmentFolder *) personalCalendarFolderInContext: (WOContext *) context;
|
||||
- (SOGoContactFolder *) personalContactsFolderInContext: (WOContext *) context;
|
||||
|
||||
/* Encryption */
|
||||
+ (NSString *)getEncryptedUsernameIfNeeded:(NSString *)username withContext:(WOContext *)context;
|
||||
+ (NSString *)getDecryptedUsernameIfNeeded:(NSString *)username withContext:(WOContext *)context;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __SOGoUser_H__ */
|
||||
@@ -39,6 +39,7 @@
|
||||
#import "SOGoUserManager.h"
|
||||
#import "SOGoUserSettings.h"
|
||||
#import "WOResourceManager+SOGo.h"
|
||||
#import "NSString+Crypto.h"
|
||||
|
||||
#if defined(MFA_CONFIG)
|
||||
#include <liboath/oath.h>
|
||||
@@ -46,6 +47,8 @@
|
||||
|
||||
#import "SOGoUser.h"
|
||||
|
||||
static const NSString *kEncryptedUserNamePrefix = @"uenc";
|
||||
|
||||
@implementation SoUser (SOGoExtension)
|
||||
|
||||
- (SOGoDomainDefaults *) userDefaults
|
||||
@@ -1197,4 +1200,84 @@
|
||||
return [accessValue boolValue];
|
||||
}
|
||||
|
||||
/* Encryption */
|
||||
+ (NSString *) getEncryptedUsernameIfNeeded:(NSString *)username withContext:(WOContext *)context
|
||||
{
|
||||
NSException *exception;
|
||||
NSString *tmp, *cacheKey;
|
||||
SOGoCache *cache;
|
||||
WORequest *request;
|
||||
|
||||
if (![[SOGoSystemDefaults sharedSystemDefaults] isURLEncryptionEnabled])
|
||||
return username;
|
||||
|
||||
request = [context request];
|
||||
cache = [SOGoCache sharedCache];
|
||||
cacheKey = [NSString stringWithFormat: @"%@_%@_%@", kEncryptedUserNamePrefix, username, [request requestHandlerKey]];
|
||||
|
||||
exception = nil;
|
||||
tmp = nil;
|
||||
|
||||
tmp = [cache valueForKey: cacheKey];
|
||||
if (tmp) {
|
||||
return tmp;
|
||||
} else {
|
||||
if (username && [username length] > 0) {
|
||||
tmp = [username encodeAES128ECBBase64: [[SOGoSystemDefaults sharedSystemDefaults] urlEncryptionPassphrase] encodedURL:YES exception: &exception];
|
||||
if (!exception) {
|
||||
[cache setValue:tmp forKey:cacheKey];
|
||||
return tmp;
|
||||
} else {
|
||||
[self errorWithFormat: @"URL Encryption error : %@", [exception reason]];
|
||||
return username;
|
||||
}
|
||||
} else {
|
||||
[self logWithFormat: @"Empty username for encryption"];
|
||||
return username;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSString *) getDecryptedUsernameIfNeeded:(NSString *)username withContext:(WOContext *)context
|
||||
{
|
||||
NSException *exception;
|
||||
NSString *tmp, *cacheKey;
|
||||
SOGoCache *cache;
|
||||
WORequest *request;
|
||||
|
||||
if (![[SOGoSystemDefaults sharedSystemDefaults] isURLEncryptionEnabled])
|
||||
return username;
|
||||
|
||||
request = [context request];
|
||||
cache = [SOGoCache sharedCache];
|
||||
cacheKey = [NSString stringWithFormat: @"%@_%@_%@", kEncryptedUserNamePrefix, username, [request requestHandlerKey]];
|
||||
exception = nil;
|
||||
tmp = nil;
|
||||
|
||||
tmp = [cache valueForKey: cacheKey];
|
||||
if (tmp) {
|
||||
return tmp;
|
||||
} else {
|
||||
if (username && [username length] > 0) {
|
||||
tmp = [username decodeAES128ECBBase64: [[SOGoSystemDefaults sharedSystemDefaults] urlEncryptionPassphrase] encodedURL:YES exception: &exception];
|
||||
if (tmp) {
|
||||
[cache setValue:tmp forKey:cacheKey];
|
||||
} else {
|
||||
[cache setValue:username forKey:cacheKey];
|
||||
}
|
||||
if (!exception) {
|
||||
return tmp;
|
||||
} else {
|
||||
[self errorWithFormat: @"URL Decryption error : %@", [exception reason]];
|
||||
return username;
|
||||
}
|
||||
} else {
|
||||
[self errorWithFormat: @"Empty username for decryption"];
|
||||
return username;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@end /* SOGoUser */
|
||||
@@ -24,6 +24,8 @@
|
||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
#import <NGObjWeb/WORequest+So.h>
|
||||
|
||||
#import <SaxObjC/XMLNamespaces.h>
|
||||
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
#import <NGExtensions/NSString+misc.h>
|
||||
#import <DOM/DOMNode.h>
|
||||
@@ -36,6 +38,7 @@
|
||||
#import "NSArray+Utilities.h"
|
||||
#import "NSDictionary+Utilities.h"
|
||||
#import "NSString+Utilities.h"
|
||||
#import "NSString+Crypto.h"
|
||||
#import "SOGoUserManager.h"
|
||||
#import "SOGoPermissions.h"
|
||||
#import "SOGoSystemDefaults.h"
|
||||
@@ -83,6 +86,16 @@
|
||||
return children;
|
||||
}
|
||||
|
||||
- (NSString *) nameInContainer {
|
||||
return [SOGoUser getEncryptedUsernameIfNeeded: [super nameInContainer] withContext: context];
|
||||
}
|
||||
|
||||
- (NSString *) davURLAsString
|
||||
{
|
||||
return [[container davURLAsString]
|
||||
stringByAppendingFormat: @"%@/", [self nameInContainer]];
|
||||
}
|
||||
|
||||
/* ownership */
|
||||
|
||||
- (NSString *) ownerInContext: (WOContext *) _ctx
|
||||
|
||||
@@ -924,6 +924,22 @@
|
||||
- (NSArray *) fetchContactsMatching: (NSString *) filter
|
||||
withCriteria: (NSArray *) criteria
|
||||
inDomain: (NSString *) domain
|
||||
|
||||
{
|
||||
if ([filter length] > 0) {
|
||||
return [self fetchContactsMatching: (NSString *) filter
|
||||
withCriteria: (NSArray *) criteria
|
||||
inDomain: (NSString *) domain
|
||||
limit: -1];
|
||||
} else {
|
||||
return [NSMutableArray array];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *)fetchContactsMatching: (NSString *)filter
|
||||
withCriteria: (NSArray *)criteria
|
||||
inDomain: (NSString *)domain
|
||||
limit: (int)limit
|
||||
{
|
||||
EOAdaptorChannel *channel;
|
||||
NSEnumerator *criteriaList;
|
||||
@@ -994,6 +1010,8 @@
|
||||
[sql appendFormat: @" AND %@ IS NULL", _domainField];
|
||||
}
|
||||
|
||||
if (limit > 0)
|
||||
[sql appendFormat: @" ORDER BY c_cn ASC LIMIT %i", limit];
|
||||
ex = [channel evaluateExpressionX: sql];
|
||||
if (!ex)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,8 @@ SOGo_LIBRARIES_DEPEND_UPON += -lcrypto
|
||||
endif
|
||||
endif
|
||||
|
||||
SOGo_LIBRARIES_DEPEND_UPON += -lytnef
|
||||
|
||||
ADDITIONAL_CPPFLAGS += \
|
||||
-Wall -DCOMPILE_FOR_GSTEP_MAKE=1 \
|
||||
-DSOGO_MAJOR_VERSION="@\"$(MAJOR_VERSION)\"" \
|
||||
|
||||
@@ -343,6 +343,8 @@ static const NSString *kJwtKey = @"jwt";
|
||||
forKey: @"expire"];
|
||||
[json setObject: [NSNumber numberWithInt: grace]
|
||||
forKey: @"grace"];
|
||||
[json setObject: [SOGoUser getEncryptedUsernameIfNeeded: username withContext: context]
|
||||
forKey: @"username"];
|
||||
|
||||
response = [self responseWithStatus: 200
|
||||
andJSONRepresentation: json];
|
||||
|
||||
@@ -78,6 +78,32 @@ static SoProduct *preferencesProduct = nil;
|
||||
return labelsDictionary;
|
||||
}
|
||||
|
||||
- (NSDictionary *) _localizedContactsLabels
|
||||
{
|
||||
NSArray *categoryLabels, *localizedCategoryLabels;
|
||||
NSDictionary *labelsDictionary;
|
||||
|
||||
labelsDictionary = nil;
|
||||
localizedCategoryLabels = [[self labelForKey: @"contacts_category_labels"
|
||||
withResourceManager: [preferencesProduct resourceManager]]
|
||||
componentsSeparatedByString: @","];
|
||||
categoryLabels = [[[preferencesProduct resourceManager]
|
||||
stringForKey: @"contacts_category_labels"
|
||||
inTableNamed: nil
|
||||
withDefaultValue: @""
|
||||
languages: [NSArray arrayWithObject: @"English"]]
|
||||
componentsSeparatedByString: @","];
|
||||
|
||||
if ([localizedCategoryLabels count] == [categoryLabels count])
|
||||
labelsDictionary = [NSDictionary dictionaryWithObjects: localizedCategoryLabels
|
||||
forKeys: categoryLabels];
|
||||
else
|
||||
[self logWithFormat: @"ERROR: localizable strings contacts_category_labels is incorrect for language %@",
|
||||
[[[context activeUser] userDefaults] language]];
|
||||
|
||||
return labelsDictionary;
|
||||
}
|
||||
|
||||
- (WOResponse *) activeExternalSieveScriptsAction
|
||||
{
|
||||
NGSieveClient *client;
|
||||
@@ -121,7 +147,7 @@ static SoProduct *preferencesProduct = nil;
|
||||
SOGoUserDefaults *defaults;
|
||||
SOGoDomainDefaults *domainDefaults;
|
||||
NSMutableArray *accounts;
|
||||
NSDictionary *categoryLabels, *vacationOptions;
|
||||
NSDictionary *calendarCategoryLabels, *contactsCategoriesLabels, *vacationOptions;
|
||||
|
||||
if (!preferencesProduct)
|
||||
{
|
||||
@@ -131,7 +157,8 @@ static SoProduct *preferencesProduct = nil;
|
||||
|
||||
defaults = [[context activeUser] userDefaults];
|
||||
domainDefaults = [[context activeUser] domainDefaults];
|
||||
categoryLabels = nil;
|
||||
calendarCategoryLabels = nil;
|
||||
contactsCategoriesLabels = nil;
|
||||
|
||||
//
|
||||
// Default General preferences
|
||||
@@ -223,7 +250,7 @@ static SoProduct *preferencesProduct = nil;
|
||||
{
|
||||
NSArray *defaultCalendarCategories;
|
||||
|
||||
categoryLabels = [self _localizedCategoryLabels];
|
||||
calendarCategoryLabels = [self _localizedCategoryLabels];
|
||||
|
||||
if ((defaultCalendarCategories = [defaults calendarCategories]))
|
||||
{
|
||||
@@ -239,7 +266,7 @@ static SoProduct *preferencesProduct = nil;
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
label = [defaultCalendarCategories objectAtIndex: count];
|
||||
if (!(localizedLabel = [categoryLabels objectForKey: label]))
|
||||
if (!(localizedLabel = [calendarCategoryLabels objectForKey: label]))
|
||||
{
|
||||
localizedLabel = label;
|
||||
}
|
||||
@@ -252,15 +279,15 @@ static SoProduct *preferencesProduct = nil;
|
||||
{
|
||||
// Calendar categories are taken from localizable strings
|
||||
|
||||
[defaults setCalendarCategories: [categoryLabels allValues]];
|
||||
[defaults setCalendarCategories: [calendarCategoryLabels allValues]];
|
||||
}
|
||||
}
|
||||
if (![[defaults source] objectForKey: @"SOGoCalendarCategoriesColors"])
|
||||
{
|
||||
NSDictionary *defaultCalendarCategoriesColors;
|
||||
|
||||
if (!categoryLabels)
|
||||
categoryLabels = [self _localizedCategoryLabels];
|
||||
if (!calendarCategoryLabels)
|
||||
calendarCategoryLabels = [self _localizedCategoryLabels];
|
||||
|
||||
if ((defaultCalendarCategoriesColors = [defaults calendarCategoriesColors]))
|
||||
{
|
||||
@@ -278,7 +305,7 @@ static SoProduct *preferencesProduct = nil;
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
label = [defaultCalendarCategories objectAtIndex: count];
|
||||
if (!(localizedLabel = [categoryLabels objectForKey: label]))
|
||||
if (!(localizedLabel = [calendarCategoryLabels objectForKey: label]))
|
||||
{
|
||||
localizedLabel = label;
|
||||
}
|
||||
@@ -296,7 +323,7 @@ static SoProduct *preferencesProduct = nil;
|
||||
NSMutableDictionary *colors;
|
||||
int i;
|
||||
|
||||
calendarCategories = [categoryLabels allValues];
|
||||
calendarCategories = [calendarCategoryLabels allValues];
|
||||
colors = [NSMutableDictionary dictionaryWithCapacity: [calendarCategories count]];
|
||||
|
||||
for (i = 0; i < [calendarCategories count]; i++)
|
||||
@@ -311,18 +338,41 @@ static SoProduct *preferencesProduct = nil;
|
||||
//
|
||||
// Populate default contact categories, based on the user's preferred language
|
||||
//
|
||||
if (![defaults contactsCategories])
|
||||
if (![[defaults source] objectForKey: @"SOGoContactsCategories"])
|
||||
{
|
||||
NSArray *contactsCategories;
|
||||
|
||||
contactsCategories = [[[[self labelForKey: @"contacts_category_labels" withResourceManager: [preferencesProduct resourceManager]]
|
||||
componentsSeparatedByString: @","] trimmedComponents]
|
||||
sortedArrayUsingSelector: @selector (localizedCaseInsensitiveCompare:)];
|
||||
contactsCategoriesLabels = [self _localizedContactsLabels];
|
||||
|
||||
if (!contactsCategories)
|
||||
contactsCategories = [NSArray array];
|
||||
if((contactsCategories = [defaults contactsCategories]))
|
||||
{
|
||||
// Contact categories are taken from SOGo's configuration or SOGoDefaults.plist
|
||||
|
||||
[defaults setContactsCategories: contactsCategories];
|
||||
NSMutableArray *filteredContactsCategories;
|
||||
NSString *label, *localizedLabel;
|
||||
int count, max;
|
||||
|
||||
max = [contactsCategories count];
|
||||
filteredContactsCategories = [NSMutableArray arrayWithCapacity: max];
|
||||
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
label = [contactsCategories objectAtIndex: count];
|
||||
if (!(localizedLabel = [contactsCategoriesLabels objectForKey: label]))
|
||||
{
|
||||
localizedLabel = label;
|
||||
}
|
||||
[filteredContactsCategories addObject: localizedLabel];
|
||||
}
|
||||
|
||||
[defaults setContactsCategories: filteredContactsCategories];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Contact categories are taken from localizable strings
|
||||
|
||||
[defaults setContactsCategories: [contactsCategoriesLabels allValues]];
|
||||
}
|
||||
}
|
||||
|
||||
if (![[defaults source] objectForKey: @"SOGoMailAddOutgoingAddresses"])
|
||||
|
||||
@@ -909,18 +909,63 @@ static NSArray *reminderValues = nil;
|
||||
//
|
||||
// Used by templates
|
||||
//
|
||||
- (NSDictionary *) _localizedContactsLabels
|
||||
{
|
||||
NSArray *categoryLabels, *localizedCategoryLabels;
|
||||
NSDictionary *labelsDictionary;
|
||||
|
||||
labelsDictionary = nil;
|
||||
localizedCategoryLabels = [[self labelForKey: @"contacts_category_labels"
|
||||
withResourceManager: [self resourceManager]]
|
||||
componentsSeparatedByString: @","];
|
||||
categoryLabels = [[[self resourceManager]
|
||||
stringForKey: @"contacts_category_labels"
|
||||
inTableNamed: nil
|
||||
withDefaultValue: @""
|
||||
languages: [NSArray arrayWithObject: @"English"]]
|
||||
componentsSeparatedByString: @","];
|
||||
|
||||
if ([localizedCategoryLabels count] == [categoryLabels count])
|
||||
labelsDictionary = [NSDictionary dictionaryWithObjects: localizedCategoryLabels
|
||||
forKeys: categoryLabels];
|
||||
else
|
||||
[self logWithFormat: @"ERROR: localizable strings contacts_category_labels is incorrect for language %@",
|
||||
[[[context activeUser] userDefaults] language]];
|
||||
|
||||
return labelsDictionary;
|
||||
}
|
||||
|
||||
- (NSString *) defaultContactsCategories
|
||||
{
|
||||
NSArray *contactsCategories;
|
||||
NSArray *labels;
|
||||
NSDictionary *localizedLabels;
|
||||
NSMutableArray *defaultCategoriesLabels;
|
||||
NSString *label, *localizedLabel;
|
||||
unsigned int i;
|
||||
|
||||
contactsCategories = [[[[self labelForKey: @"contacts_category_labels" withResourceManager: [self resourceManager]]
|
||||
componentsSeparatedByString: @","] trimmedComponents]
|
||||
sortedArrayUsingSelector: @selector (localizedCaseInsensitiveCompare:)];
|
||||
localizedLabels = [self _localizedContactsLabels];
|
||||
labels = [[SOGoSystemDefaults sharedSystemDefaults] contactsCategories];
|
||||
defaultCategoriesLabels = [NSMutableArray array];
|
||||
|
||||
if (!contactsCategories)
|
||||
contactsCategories = [NSArray array];
|
||||
if(labels)
|
||||
{
|
||||
for (i = 0; i < [labels count]; i++)
|
||||
{
|
||||
label = [labels objectAtIndex: i];
|
||||
if (!(localizedLabel = [localizedLabels objectForKey: label]))
|
||||
{
|
||||
localizedLabel = label;
|
||||
}
|
||||
[defaultCategoriesLabels addObject: localizedLabel];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultCategoriesLabels = [localizedLabels allValues];
|
||||
}
|
||||
|
||||
return [contactsCategories jsonRepresentation];
|
||||
|
||||
return [defaultCategoriesLabels jsonRepresentation];
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -221,7 +221,8 @@
|
||||
<!-- Remote/domain addressbooks -->
|
||||
<section>
|
||||
<md-subheader class="sg-md-subheader--with-secondary-icon"
|
||||
md-colors="::{background: 'default-background-300'}">
|
||||
md-colors="::{background: 'default-background-300'}"
|
||||
ng-if="app.service.$remotes.length > 0">
|
||||
<var:string label:value="Global Addressbooks"/>
|
||||
</md-subheader>
|
||||
<md-list>
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
function l(){var n,e,t=arguments[0],o=t,r=arguments;for(labels[t]?o=labels[t]:clabels[t]&&(o=clabels[t]),n=1,e=0;n<r.length;n++,e++)o=o.replace("%{"+e+"}",r[n]);return o=(n=1)<r.length?o.replace(/%((%)|s|d)/g,function(e){var t=null;return e[2]?t=e[2]:(t=r[n],"%d"===e&&(t=parseFloat(t),isNaN(t))&&(t=0),n++),t}):o}function hexToRgb(e){e=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return e?{r:parseInt(e[1],16),g:parseInt(e[2],16),b:parseInt(e[3],16)}:null}function contrast(e){var t=1,e=hexToRgb(e);if(e){for(var n=[e.r/255,e.g/255,e.b/255],o=0;o<n.length;++o)n[o]=n[o]<=.03928?n[o]/12.92:Math.pow((n[o]+.055)/1.055,2.4);t=.2126*n[0]+.7152*n[1]+.0722*n[2]}return.179<t?"black":"white"}function guid(){function e(){return(65536*(1+Math.random())|0).toString(16).substring(1)}return(e()+e()+"-"+e()+"-4"+e().substr(0,3)+"-"+e()+"-"+e()+e()+e()).toLowerCase()}!function(){"use strict";function e(e,t,n,o,r,i,s){e.classNameFilter(/^(?:(?!ng-animate-disabled).)*$/),r.definePalette("sogo-green",{50:"eaf5e9",100:"cbe5c8",200:"aad6a5",300:"88c781",400:"66b86a",500:"56b04c",600:"4da143",700:"388e3c",800:"367d2e",900:"225e1b",A100:"fafafa",A200:"69f0ae",A400:"00e676",A700:"00c853",contrastDefaultColor:"dark",contrastLightColors:["300","400","500","600","700","800","900"]}),r.definePalette("sogo-blue",{50:"f0faf9",100:"e1f5f3",200:"ceebe8",300:"bfe0dd",400:"b2d6d3",500:"a1ccc8",600:"8ebfbb",700:"7db3b0",800:"639997",900:"4d8080",A100:"d4f7fa",A200:"c3f5fa",A400:"53e3f0",A700:"00b0c0",contrastDefaultColor:"light",contrastDarkColors:["50","100","200"]});e=r.extendPalette("grey",{1e3:"baa870"});r.definePalette("sogo-grey",e),r.theme("default").primaryPalette("sogo-blue",{default:"900","hue-1":"400","hue-2":"800","hue-3":"A700"}).accentPalette("sogo-green",{default:"500","hue-1":"A100","hue-2":"300","hue-3":"A700"}).backgroundPalette("sogo-grey"),r.registerStyles(["md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent,","md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent md-input-container[md-no-float] .md-input {"," background-color: '{{accent-hue-1}}';"," color: '{{foreground-1}}';","}","md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent md-icon {"," color: '{{foreground-1}}';"," fill: '{{foreground-1}}';","}"].join("")),r.registerStyles([".md-autocomplete-suggestions.md-3-line li p {"," color: '{{foreground-2}}';","}"].join("")),r.registerStyles([".sg-time-selection-indicator.sg-time-selected,",".sg-time-selection-indicator:hover.sg-time-selected,",".sg-time-selection-indicator.md-focus.sg-time-selected {"," background: '{{primary-500}}';","}",".sg-timepicker-open .sg-timepicker-icon {"," color: '{{primary-900}}';","}",".sg-timepicker-time,",".sg-timepicker-open .sg-timepicker-input-container {"," background: '{{background-hue-1}}';","}",".sg-timepicker-input-mask-opaque {"," box-shadow: 0 0 0 9999px '{{background-hue-1}}';","}"].join("")),r.registerStyles(["[ui-view=calendars] .hours {"," color: '{{primary-700}}';","}",".attendees .busy {"," background-color: '{{background-1000}}';","}",".attendees .event {"," background-color: '{{primary-300}}';","}"].join("")),r.registerStyles([".sg-message-thread {"," background-color: '{{primary-100}}';","}",".sg-message-thread-first {"," background-color: '{{primary-200}}';","}"].join("")),window.DebugEnabled||(t.debugEnabled(!1),n.debugInfoEnabled(!1),i.disableWarnings(),s.errorOnUnhandledRejections(!1),r.generateThemesOnDemand(!0)),o.interceptors.push("AuthInterceptor"),o.interceptors.push("ErrorInterceptor")}function a(t,e,n,o,r){var i=e.defer(),s=angular.element('<iframe class="ng-hide" src="'+t.UserFolderURL+'recover"></iframe>');return s.on("load",function(){var e=o.get("$state");2<r.config.attempt?(angular.element(t).off("beforeunload"),t.location.href=t.ApplicationBaseURL+e.href(e.current),i.reject()):n(function(){var e=o.get("$http");r.config.attempt?r.config.attempt++:r.config.attempt=1,e(r.config).then(function(e){i.resolve(e)},function(e){i.reject(e)}).finally(function(){n(s.remove,1e3)})},2e3)}),document.body.appendChild(s[0]),i.promise}function t(n,o,r,i){return{response:function(e){var t;return e&&/^application\/json/.test(e.config.headers.Accept)&&/^[\n\r\t ]*<!DOCTYPE html/.test(e.data)?n.usesCASAuthentication||n.usesSAML2Authentication?a(n,o,r,i,e):(t=i.get("$state"),angular.element(n).off("beforeunload"),t.href(t.current)?n.location.href=n.ApplicationBaseURL+t.href(t.current):n.location.href=n.ApplicationBaseURL,o.reject()):e}}}function n(n,o,r,i,s){return{responseError:function(e){var t;if(/^application\/json/.test(e.config.headers.Accept)){if((o.usesCASAuthentication||o.usesSAML2Authentication)&&(-1==e.status||500==e.status&&-1!==document.cookie.indexOf("cas-location")))return a(o,r,i,s,e);o.usesSAML2Authentication&&401==e.status&&!o.recovered?(t=s.get("$state"),angular.element(o).off("beforeunload"),o.recovered=!0,o.location.href=o.ApplicationBaseURL+t.href(t.current)):e.data&&e.data.quiet||n.$broadcast("http:Error",e)}return r.reject(e)}}}angular.Line truncated
|
||||
function l(){var n,e,t=arguments[0],o=t,r=arguments;for(labels[t]?o=labels[t]:clabels[t]&&(o=clabels[t]),n=1,e=0;n<r.length;n++,e++)o=o.replace("%{"+e+"}",r[n]);return o=(n=1)<r.length?o.replace(/%((%)|s|d)/g,function(e){var t=null;return e[2]?t=e[2]:(t=r[n],"%d"===e&&(t=parseFloat(t),isNaN(t))&&(t=0),n++),t}):o}function hexToRgb(e){e=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return e?{r:parseInt(e[1],16),g:parseInt(e[2],16),b:parseInt(e[3],16)}:null}function contrast(e){var t=1,e=hexToRgb(e);if(e){for(var n=[e.r/255,e.g/255,e.b/255],o=0;o<n.length;++o)n[o]=n[o]<=.03928?n[o]/12.92:Math.pow((n[o]+.055)/1.055,2.4);t=.2126*n[0]+.7152*n[1]+.0722*n[2]}return.179<t?"black":"white"}function guid(){function e(){return(65536*(1+Math.random())|0).toString(16).substring(1)}return(e()+e()+"-"+e()+"-4"+e().substr(0,3)+"-"+e()+"-"+e()+e()+e()).toLowerCase()}!function(){"use strict";function e(e,t,n,o,r,i,s){e.classNameFilter(/^(?:(?!ng-animate-disabled).)*$/),r.definePalette("sogo-green",{50:"eaf5e9",100:"cbe5c8",200:"aad6a5",300:"88c781",400:"66b86a",500:"56b04c",600:"4da143",700:"388e3c",800:"367d2e",900:"225e1b",A100:"fafafa",A200:"69f0ae",A400:"00e676",A700:"00c853",contrastDefaultColor:"dark",contrastLightColors:["300","400","500","600","700","800","900"]}),r.definePalette("sogo-blue",{50:"f0faf9",100:"e1f5f3",200:"ceebe8",300:"bfe0dd",400:"b2d6d3",500:"a1ccc8",600:"8ebfbb",700:"7db3b0",800:"639997",900:"4d8080",A100:"d4f7fa",A200:"c3f5fa",A400:"53e3f0",A700:"00b0c0",contrastDefaultColor:"light",contrastDarkColors:["50","100","200"]});e=r.extendPalette("grey",{1e3:"baa870"});r.definePalette("sogo-grey",e),r.theme("default").primaryPalette("sogo-blue",{default:"900","hue-1":"400","hue-2":"800","hue-3":"A700"}).accentPalette("sogo-green",{default:"500","hue-1":"A100","hue-2":"300","hue-3":"A700"}).backgroundPalette("sogo-grey"),r.registerStyles(["md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent,","md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent md-input-container[md-no-float] .md-input {"," background-color: '{{accent-hue-1}}';"," color: '{{foreground-1}}';","}","md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent md-icon {"," color: '{{foreground-1}}';"," fill: '{{foreground-1}}';","}"].join("")),r.registerStyles([".md-autocomplete-suggestions.md-3-line li p {"," color: '{{foreground-2}}';","}"].join("")),r.registerStyles([".sg-time-selection-indicator.sg-time-selected,",".sg-time-selection-indicator:hover.sg-time-selected,",".sg-time-selection-indicator.md-focus.sg-time-selected {"," background: '{{primary-500}}';","}",".sg-timepicker-open .sg-timepicker-icon {"," color: '{{primary-900}}';","}",".sg-timepicker-time,",".sg-timepicker-open .sg-timepicker-input-container {"," background: '{{background-hue-1}}';","}",".sg-timepicker-input-mask-opaque {"," box-shadow: 0 0 0 9999px '{{background-hue-1}}';","}"].join("")),r.registerStyles(["[ui-view=calendars] .hours {"," color: '{{primary-700}}';","}",".attendees .busy {"," background-color: '{{background-1000}}';","}",".attendees .event {"," background-color: '{{primary-300}}';","}"].join("")),r.registerStyles([".sg-message-thread {"," background-color: '{{primary-100}}';","}",".sg-message-thread-first {"," background-color: '{{primary-200}}';","}"].join("")),window.DebugEnabled||(t.debugEnabled(!1),n.debugInfoEnabled(!1),i.disableWarnings(),s.errorOnUnhandledRejections(!1),r.generateThemesOnDemand(!0)),o.interceptors.push("AuthInterceptor"),o.interceptors.push("ErrorInterceptor")}function a(t,e,n,o,r){var i=e.defer(),s=angular.element('<iframe class="ng-hide" src="'+t.UserFolderURL+'recover"></iframe>');return s.on("load",function(){var e=o.get("$state");2<r.config.attempt?(angular.element(t).off("beforeunload"),t.location.href=t.ApplicationBaseURL+e.href(e.current),i.reject()):n(function(){var e=o.get("$http");r.config.attempt?r.config.attempt++:r.config.attempt=1,e(r.config).then(function(e){i.resolve(e)},function(e){i.reject(e)}).finally(function(){n(s.remove,1e3)})},2e3)}),document.body.appendChild(s[0]),i.promise}function t(n,o,r,i){return{response:function(e){var t;return e&&/^application\/json/.test(e.config.headers.Accept)&&/^[\n\r\t ]*<!DOCTYPE html/.test(e.data)?n.usesCASAuthentication||n.usesSAML2Authentication?a(n,o,r,i,e):(t=i.get("$state"),angular.element(n).off("beforeunload"),t.href(t.current)?n.location.href=n.ApplicationBaseURL+t.href(t.current):n.location.href=n.ApplicationBaseURL,o.reject()):e}}}function n(n,o,r,i,s){return{responseError:function(e){var t;if(/^application\/json/.test(e.config.headers.Accept)){if((o.usesCASAuthentication||o.usesSAML2Authentication)&&(-1==e.status||500==e.status&&-1!==document.cookie.indexOf("cas-location")))return a(o,r,i,s,e);o.usesSAML2Authentication&&401==e.status&&!o.recovered?(t=s.get("$state"),angular.element(o).off("beforeunload"),o.recovered=!0,o.location.href=o.ApplicationBaseURL+t.href(t.current)):e.data&&e.data.quiet||n.$broadcast("http:Error",e)}return r.reject(e)}}}angular.Line truncated
|
||||
//# sourceMappingURL=Common.js.map
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"Common.js","sources":["Common/utils.js","Common/Common.app.js","Common/mdColors.app.js","Common/decodeUri.filter.js","Common/encodeUri.filter.js","Common/ensureTarget.filter.js","Common/loc.filter.js","Common/range.filter.js","Common/txt2html.filter.js","Common/AclController.js","Common/navController.js","Common/Acl.service.js","Common/Authentication.service.js","Common/Dialog.service.js","Common/Gravatar.service.js","Common/Resource.service.js","Common/sgFocus.service.js","Common/sgHotkeys.service.js","Common/sgRippleClick.service.js","Common/User.service.js","Common/sgAutogrow.directive.js","Common/sgAvatarImage.directive.js","Common/sgBlockToggle.directive.js","Common/sgCheckmark.directive.js","Common/sgColorPicker.directive.js","Common/sgCompile.directive.js","Common/sgDatepickerReadonlyInput.directive.js","Common/sgDraggable.directive.js","Common/sgDroppable.directive.js","Common/sgEnter.directive.js","Common/sgEscape.directive.js","Common/sgFocus.directive.js","Common/sgFolderStylesheet.directive.js","Common/sgLabels.directive.js","Common/sgNoDirtyCheck.directive.js","Common/sgPlaceholder.directive.js","Common/sgQrCode.directive.js","Common/sgResetOnDisabled.directive.js","Common/sgRippleClick.directive.js","Common/sgSearch.directive.js","Common/sgSelectOnly.directive.js","Common/sgSubscribe.directive.js","Common/sgTimepicker.directive.js","Common/sgToggleGrid.directive.js"],"names":["l","i","j","key","arguments","value","args","labels","clabels","length","replace","m","val","parseFloat","isNaN","hexToRgb","hex","result","exec","r","parseInt","g","b","contrast","color","c","Math","pow","guid","S4","random","toString","substring","substr","toLowerCase","configure","$animateProvider","$logProvider","$compileProvider","$httpProvider","$mdThemingProvider","$mdAriaProvider","$qProvider","classNameFilter","definePalette","50","100","200","300","400","500","600","700","800","900","A100","A200","A400","A700","contrastDefaultColor","contrastLightColors","contrastDarkColors","greyMap","extendPalette","1000","theme","primaryPalette","default","hue-1","hue-2","hue-3","accentPalette","backgroundPalette","registerStyles","join","window","DebugEnabled","debugEnabled","debugInfoEnabled","disableWarnings","errorOnUnhandledRejections","generateThemesOnDemand","interceptors","push","renewTicket","$window","$q","$timeout","$injector","response","deferred","defer","iframe","angular","element","UserFolderURL","on","$state","get","config","attempt","off","location","href","ApplicationBaseURL","current","reject","$http","then","resolve","finally","remove","document","body","appendChild","promise","AuthInterceptor","test","headers","Accept","data","usesCASAuthentication","usesSAML2Authentication","ErrorInterceptor","$rootScope","responseError","rejection","status","cookie","indexOf","recovered","quiet","$broadcast","module","isPopup","classList","contains","baseURL","resourcesURL","ResourcesURL","activeUser","param","settings","login","UserLogin","identification","UserIdentification","email","UserEmail","language","UserLanguage","folderURL","isSuperUser","IsSuperUser","path","calendar","UserCalendarPath","contacts","UserContactsPath","mail","UserMailPath","preferences","UserPreferencesPath","administration","UserAdministrationPath","help","HelpURL","logoff","UserLogoffPath","minimumSearchLength","isNumber","constant","selection","xs","gt-xs","sm","gt-sm","md","gt-md","lg","gt-lg","xl","print","toastPosition","factory","$inject","_$mdThemingProvider","runBlock","$interpolate","$document","$log","buildCssSelectors","selectors","fgDefault","bgDefault","bdrDefault","fgDefaultHue","bgDefaultHue","fgColor","bgColor","bdrColor","fgHue","bgHue","customSheet","style","head","querySelector","createElement","title","createTextNode","sheet","index","cssRules","deleteRule","addRule","fgInterpolate","bgInterpolate","themeName","paletteName","colorArray","hueName","context","palette","hue","insertRule","addBorderRule","bdrInterpolate","colorValue","forEach","_THEMES","_PALETTES","colors","primary","name","hues","run","decodeUri","decodeURIComponent","filter","encodeUri","encodeURIComponent","ensureTarget","$sce","tree","find","attr","trustAs","html","n","res","txt2html","linkyFilter","text","String","rel","undefined","AclController","$mdDialog","Dialog","usersWithACL","User","folder","vm","this","selectUser","user","$event","target","parentNode","selectedUid","uid","selectedUser","inactive","$rights","users","userToAdd","searchText","folderClassName","isFunction","getClassName","templateName","getElementById","$isAnonymous","userFilter","$query","$filter","$acl","dry","closeModal","$resetUsersRights","hide","saveModal","$saveUsersRights","alert","confirmChange","confirmation","$confirmRights","showing","message","removeUser","$removeUser","addUser","$addUser","toggleAllRights","$toggleAllRights","hasNoRight","$hasNoRight","showRights","controller","navController","$scope","$interval","$mdSidenav","$mdToast","$mdMedia",Line truncated
|
||||
{"version":3,"file":"Common.js","sources":["Common/utils.js","Common/Common.app.js","Common/mdColors.app.js","Common/decodeUri.filter.js","Common/encodeUri.filter.js","Common/ensureTarget.filter.js","Common/loc.filter.js","Common/range.filter.js","Common/txt2html.filter.js","Common/AclController.js","Common/navController.js","Common/Acl.service.js","Common/Authentication.service.js","Common/Dialog.service.js","Common/Gravatar.service.js","Common/Resource.service.js","Common/sgFocus.service.js","Common/sgHotkeys.service.js","Common/sgRippleClick.service.js","Common/User.service.js","Common/sgAutogrow.directive.js","Common/sgAvatarImage.directive.js","Common/sgBlockToggle.directive.js","Common/sgCheckmark.directive.js","Common/sgColorPicker.directive.js","Common/sgCompile.directive.js","Common/sgDatepickerReadonlyInput.directive.js","Common/sgDraggable.directive.js","Common/sgDroppable.directive.js","Common/sgEnter.directive.js","Common/sgEscape.directive.js","Common/sgFocus.directive.js","Common/sgFolderStylesheet.directive.js","Common/sgLabels.directive.js","Common/sgNoDirtyCheck.directive.js","Common/sgPlaceholder.directive.js","Common/sgQrCode.directive.js","Common/sgResetOnDisabled.directive.js","Common/sgRippleClick.directive.js","Common/sgSearch.directive.js","Common/sgSelectOnly.directive.js","Common/sgSubscribe.directive.js","Common/sgTimepicker.directive.js","Common/sgToggleGrid.directive.js"],"names":["l","i","j","key","arguments","value","args","labels","clabels","length","replace","m","val","parseFloat","isNaN","hexToRgb","hex","result","exec","r","parseInt","g","b","contrast","color","c","Math","pow","guid","S4","random","toString","substring","substr","toLowerCase","configure","$animateProvider","$logProvider","$compileProvider","$httpProvider","$mdThemingProvider","$mdAriaProvider","$qProvider","classNameFilter","definePalette","50","100","200","300","400","500","600","700","800","900","A100","A200","A400","A700","contrastDefaultColor","contrastLightColors","contrastDarkColors","greyMap","extendPalette","1000","theme","primaryPalette","default","hue-1","hue-2","hue-3","accentPalette","backgroundPalette","registerStyles","join","window","DebugEnabled","debugEnabled","debugInfoEnabled","disableWarnings","errorOnUnhandledRejections","generateThemesOnDemand","interceptors","push","renewTicket","$window","$q","$timeout","$injector","response","deferred","defer","iframe","angular","element","UserFolderURL","on","$state","get","config","attempt","off","location","href","ApplicationBaseURL","current","reject","$http","then","resolve","finally","remove","document","body","appendChild","promise","AuthInterceptor","test","headers","Accept","data","usesCASAuthentication","usesSAML2Authentication","ErrorInterceptor","$rootScope","responseError","rejection","status","cookie","indexOf","recovered","quiet","$broadcast","module","isPopup","classList","contains","baseURL","resourcesURL","ResourcesURL","activeUser","param","settings","login","UserLogin","identification","UserIdentification","email","UserEmail","language","UserLanguage","folderURL","isSuperUser","IsSuperUser","path","calendar","UserCalendarPath","contacts","UserContactsPath","mail","UserMailPath","preferences","UserPreferencesPath","administration","UserAdministrationPath","help","HelpURL","logoff","UserLogoffPath","minimumSearchLength","isNumber","constant","selection","xs","gt-xs","sm","gt-sm","md","gt-md","lg","gt-lg","xl","print","toastPosition","factory","$inject","_$mdThemingProvider","runBlock","$interpolate","$document","$log","buildCssSelectors","selectors","fgDefault","bgDefault","bdrDefault","fgDefaultHue","bgDefaultHue","fgColor","bgColor","bdrColor","fgHue","bgHue","customSheet","style","head","querySelector","createElement","title","createTextNode","sheet","index","cssRules","deleteRule","addRule","fgInterpolate","bgInterpolate","themeName","paletteName","colorArray","hueName","context","palette","hue","insertRule","addBorderRule","bdrInterpolate","colorValue","forEach","_THEMES","_PALETTES","colors","primary","name","hues","run","decodeUri","decodeURIComponent","filter","encodeUri","encodeURIComponent","ensureTarget","$sce","tree","find","attr","trustAs","html","n","res","txt2html","linkyFilter","text","String","rel","undefined","AclController","$mdDialog","Dialog","usersWithACL","User","folder","vm","this","selectUser","user","$event","target","parentNode","selectedUid","uid","selectedUser","inactive","$rights","users","userToAdd","searchText","folderClassName","isFunction","getClassName","templateName","getElementById","$isAnonymous","userFilter","$query","$filter","$acl","dry","closeModal","$resetUsersRights","hide","saveModal","$saveUsersRights","alert","confirmChange","confirmation","$confirmRights","showing","message","removeUser","$removeUser","addUser","$addUser","toggleAllRights","$toggleAllRights","hasNoRight","$hasNoRight","showRights","controller","navController","$scope","$interval","$mdSidenav","$mdToast","$mdMedia",Line truncated
|
||||
@@ -102,7 +102,7 @@
|
||||
else if (typeof data.totpDisabled != 'undefined') {
|
||||
d.resolve({
|
||||
cn: data.cn,
|
||||
url: redirectUrl(username, domain),
|
||||
url: redirectUrl(data.username, domain),
|
||||
totpdisabled: 1
|
||||
});
|
||||
}
|
||||
@@ -124,12 +124,12 @@
|
||||
else {
|
||||
d.resolve({
|
||||
cn: data.cn,
|
||||
url: redirectUrl(username, domain)
|
||||
url: redirectUrl(data.username, domain)
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
d.resolve({ url: redirectUrl(username, domain) });
|
||||
d.resolve({ url: redirectUrl(data.username, domain) });
|
||||
}
|
||||
}
|
||||
}, function(error) {
|
||||
@@ -184,10 +184,6 @@
|
||||
},
|
||||
data: { userName: userName, newPassword: newPassword, oldPassword: oldPassword, token: token }
|
||||
}).then(function() {
|
||||
// Clean cookies for reauthenticate
|
||||
$cookies.remove('XSRF-TOKEN', { path: '/SOGo/' });
|
||||
$cookies.remove('0xHIGHFLYxSOGo', { path: '/SOGo/' });
|
||||
|
||||
d.resolve({url: redirectUrl(userName, domain)});
|
||||
}, function(response) {
|
||||
var error,
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
!function(){"use strict";angular.module("SOGo.MainUI",["SOGo.Common","SOGo.Authentication"]);function e(e,o,s,r,a,n,i,t){var d=this;this.$onInit=function(){this.creds={username:o.cookieUsername,password:null,domain:null,rememberLogin:angular.isDefined(o.cookieUsername)&&0<o.cookieUsername.length},/\blanguage=/.test(o.location.search)&&(this.creds.language=o.language),this.loginState=!1,this.verificationCodePattern="\\d{6}",this.passwords={newPassword:null,newPasswordConfirmation:null,oldPassword:null,visible:!1},this.passwordRecovery={passwordRecoveryEnabled:!1,passwordRecoveryQuestionKey:null,passwordRecoveryQuestion:null,passwordRecoveryMode:null,passwordRecoveryQuestionAnswer:null,passwordRecoveryToken:null,passwordRecoveryLinkTimer:null,passwordRecoverySecondaryEmailText:null,passwordRecoveryMailDomain:null,showLoader:!1},this.showLogin=!1,s(function(){d.showLogin=!0;var e=window.location.search;let o=new URLSearchParams(e).get("token");0<window.location.pathname.indexOf("passwordRecoveryEmail")&&o?3===(e=(o=o.replace(/\//g,"")).split(".")).length&&(d.passwordRecovery.passwordRecoveryToken=o,e=JSON.parse(atob(e[1])),d.creds.username=e.username,d.creds.domain=e.domain,d.passwordRecovery.passwordRecoveryToken=o,d.passwordRecovery.passwordRecoveryMode="SecondaryEmail",d.passwordRecovery.passwordRecoveryEnabled=!0,d.loginState="passwordchange",d.showLogin=!1,t("loginContent")):d.retrievePasswordRecoveryEnabled()},100)},this.login=function(){return d.loginState="authenticating",n.login(d.creds).then(function(e){e.totpmissingkey?(d.loginState="totpcode",i("totpcode")):e.totpdisabled?(d.loginState="totpdisabled",d.cn=e.cn,d.url=e.url):(d.loginState="logged",d.cn=e.cn,d.url=e.url,s(function(){d.continueLogin()},1e3))},function(e){var o,s;d.loginState="error",e.error?d.errorMessage=e.error:0<e.grace?(d.loginState="passwordwillexpire",d.cn=e.cn,d.url=e.url,d.errorMessage=l("You have %{0} logins remaining before your account is locked. Please change your password in the preference dialog.",e.grace)):0<e.expire?(s=86400<e.expire?(o=Math.round(e.expire/86400),l("days")):3600<e.expire?(o=Math.round(e.expire/3600),l("hours")):60<e.expire?(o=Math.round(e.expire/60),l("minutes")):(o=e.expire,l("seconds")),d.loginState="passwordwillexpire",d.cn=e.cn,d.url=e.url,d.errorMessage=l("Your password is going to expire in %{0} %{1}.",o,s)):e.passwordexpired&&(d.loginState="passwordchange",d.url=e.url)}),!1},this.restoreLogin=function(){d.showLogin=!1,"SecretQuestion"===d.passwordRecovery.passwordRecoveryMode?(t("loginContent"),d.passwordRecoveryInfo()):(delete d.creds.verificationCode,d.passwordRecoveryAbort())},this.continueLogin=function(){o.location.href===d.url?o.location.reload(!0):o.location.href=d.url},this.showAbout=function(e){function o(e){this.closeDialog=function(){e.hide()}}a.show({targetEvent:e,templateUrl:"aboutBox.html",controller:o,controllerAs:"about"}),o.$inject=["$mdDialog"]},this.changeLanguage=function(e){o.location.href=ApplicationBaseURL+"login?language="+this.creds.language},this.hello=function(e){return!1},this.canChangePassword=function(e){return this.passwords.newPasswordConfirmation&&this.passwords.newPasswordConfirmation.length&&this.passwords.newPassword!=this.passwords.newPasswordConfirmation?(e.newPasswordConfirmation.$setValidity("newPasswordMismatch",!1),!1):(e.newPasswordConfirmation.$setValidity("newPasswordMismatch",!0),!!(this.passwords.newPassword&&0<this.passwords.newPassword.length&&this.passwords.newPasswordConfirmation&&this.passwords.newPasswordConfirmation.length&&this.passwords.newPassword==this.passwords.newPasswordConfirmation&&(this.isInPasswordRecoveryMode()||!this.loginState&&this.passwords.oldPassword&&0<this.passwords.oldPassword.length||"passwordchange"==this.loginState&&this.passwords.oldPassword&&0<this.passwords.oldPassword.length)))},this.changePassword=function(){n.changePassword(this.creds.username,this.creds.domain,this.passwords.newPassword,this.passwords.oldPassword,this.passwordRecovery.passwordRecoveryToken).then(function(e){d.loginState="message",d.url=e.url,d.errorMessage=l("The password was changed successfully.")},function(e){d.loginState="error",d.errorMessage=e})},this.passwordRecoveryInfo=function(){d.loginState="passwordrecovery",d.passwordRecovery.showLoader=!0,n.passwordRecovery(this.creds.username,this.creds.domain).then(function(e){d.passwordRecovery.passwordRecoveryMode=e.mode,"SecretQuestion"===e.mode?(d.passwordRecovery.passwordRecoveryQuestion=e.secretQuestionLabel,d.passwordRecovery.passwordRecoveryQuestionKey=e.secretQuestion):"SecondaryEmail"===e.mode?d.passwordRecovery.passwordRecoverySecondaryEmailText=l("A link will be sent to %{0}",e.obfuscatedRecoveryEmail):"Disabled"===e.mode&&(d.loginState="error",d.errorMessage=l("No password recovery method has been defined for this user")),d.passwordRecovery.showLoader=!1},function(e){d.loginState="error",d.errorMessage=e,d.passwordRecovery.showLoader=!1})},this.passwordRecoveryEmail=function(){d.passLine truncated
|
||||
!function(){"use strict";angular.module("SOGo.MainUI",["SOGo.Common","SOGo.Authentication"]);function e(e,o,s,r,a,n,i,t){var d=this;this.$onInit=function(){this.creds={username:o.cookieUsername,password:null,domain:null,rememberLogin:angular.isDefined(o.cookieUsername)&&0<o.cookieUsername.length},/\blanguage=/.test(o.location.search)&&(this.creds.language=o.language),this.loginState=!1,this.verificationCodePattern="\\d{6}",this.passwords={newPassword:null,newPasswordConfirmation:null,oldPassword:null,visible:!1},this.passwordRecovery={passwordRecoveryEnabled:!1,passwordRecoveryQuestionKey:null,passwordRecoveryQuestion:null,passwordRecoveryMode:null,passwordRecoveryQuestionAnswer:null,passwordRecoveryToken:null,passwordRecoveryLinkTimer:null,passwordRecoverySecondaryEmailText:null,passwordRecoveryMailDomain:null,showLoader:!1},this.showLogin=!1,s(function(){d.showLogin=!0;var e=window.location.search;let o=new URLSearchParams(e).get("token");0<window.location.pathname.indexOf("passwordRecoveryEmail")&&o?3===(e=(o=o.replace(/\//g,"")).split(".")).length&&(d.passwordRecovery.passwordRecoveryToken=o,e=JSON.parse(atob(e[1])),d.creds.username=e.username,d.creds.domain=e.domain,d.passwordRecovery.passwordRecoveryToken=o,d.passwordRecovery.passwordRecoveryMode="SecondaryEmail",d.passwordRecovery.passwordRecoveryEnabled=!0,d.loginState="passwordchange",d.showLogin=!1,t("loginContent")):d.retrievePasswordRecoveryEnabled(),0<document.querySelectorAll("*:autofill").length&&document.querySelectorAll("*:autofill").forEach(e=>{e.parentElement.classList.add("md-input-has-value")})},100)},this.login=function(){return d.loginState="authenticating",n.login(d.creds).then(function(e){e.totpmissingkey?(d.loginState="totpcode",i("totpcode")):e.totpdisabled?(d.loginState="totpdisabled",d.cn=e.cn,d.url=e.url):(d.loginState="logged",d.cn=e.cn,d.url=e.url,s(function(){d.continueLogin()},1e3))},function(e){var o,s;d.loginState="error",e.error?d.errorMessage=e.error:0<e.grace?(d.loginState="passwordwillexpire",d.cn=e.cn,d.url=e.url,d.errorMessage=l("You have %{0} logins remaining before your account is locked. Please change your password in the preference dialog.",e.grace)):0<e.expire?(s=86400<e.expire?(o=Math.round(e.expire/86400),l("days")):3600<e.expire?(o=Math.round(e.expire/3600),l("hours")):60<e.expire?(o=Math.round(e.expire/60),l("minutes")):(o=e.expire,l("seconds")),d.loginState="passwordwillexpire",d.cn=e.cn,d.url=e.url,d.errorMessage=l("Your password is going to expire in %{0} %{1}.",o,s)):e.passwordexpired&&(d.loginState="passwordchange",d.url=e.url)}),!1},this.restoreLogin=function(){d.showLogin=!1,"SecretQuestion"===d.passwordRecovery.passwordRecoveryMode?(t("loginContent"),d.passwordRecoveryInfo()):(delete d.creds.verificationCode,d.passwordRecoveryAbort())},this.continueLogin=function(){o.location.href===d.url?o.location.reload(!0):o.location.href=d.url},this.showAbout=function(e){function o(e){this.closeDialog=function(){e.hide()}}a.show({targetEvent:e,templateUrl:"aboutBox.html",controller:o,controllerAs:"about"}),o.$inject=["$mdDialog"]},this.changeLanguage=function(e){o.location.href=ApplicationBaseURL+"login?language="+this.creds.language},this.hello=function(e){return!1},this.canChangePassword=function(e){return this.passwords.newPasswordConfirmation&&this.passwords.newPasswordConfirmation.length&&this.passwords.newPassword!=this.passwords.newPasswordConfirmation?(e.newPasswordConfirmation.$setValidity("newPasswordMismatch",!1),!1):(e.newPasswordConfirmation.$setValidity("newPasswordMismatch",!0),!!(this.passwords.newPassword&&0<this.passwords.newPassword.length&&this.passwords.newPasswordConfirmation&&this.passwords.newPasswordConfirmation.length&&this.passwords.newPassword==this.passwords.newPasswordConfirmation&&(this.isInPasswordRecoveryMode()||!this.loginState&&this.passwords.oldPassword&&0<this.passwords.oldPassword.length||"passwordchange"==this.loginState&&this.passwords.oldPassword&&0<this.passwords.oldPassword.length)))},this.changePassword=function(){n.changePassword(this.creds.username,this.creds.domain,this.passwords.newPassword,this.passwords.oldPassword,this.passwordRecovery.passwordRecoveryToken).then(function(e){d.loginState="message",d.url=e.url,d.errorMessage=l("The password was changed successfully.")},function(e){d.loginState="error",d.errorMessage=e})},this.passwordRecoveryInfo=function(){d.loginState="passwordrecovery",d.passwordRecovery.showLoader=!0,n.passwordRecovery(this.creds.username,this.creds.domain).then(function(e){d.passwordRecovery.passwordRecoveryMode=e.mode,"SecretQuestion"===e.mode?(d.passwordRecovery.passwordRecoveryQuestion=e.secretQuestionLabel,d.passwordRecovery.passwordRecoveryQuestionKey=e.secretQuestion):"SecondaryEmail"===e.mode?d.passwordRecovery.passwordRecoverySecondaryEmailText=l("A link will be sent to %{0}",e.obfuscatedRecoveryEmail):"Disabled"===e.mode&&(d.loginState="error",d.errorMessage=l("No password recovery method has been defined for this user")),d.passwoLine truncated
|
||||
//# sourceMappingURL=Main.js.map
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"Main.js","sources":["Main/Main.app.js"],"names":["angular","module","LoginController","$scope","$window","$timeout","Dialog","$mdDialog","Authentication","focus","rippleDo","vm","this","$onInit","creds","username","cookieUsername","password","domain","rememberLogin","isDefined","length","test","location","search","language","loginState","verificationCodePattern","passwords","newPassword","newPasswordConfirmation","oldPassword","visible","passwordRecovery","passwordRecoveryEnabled","passwordRecoveryQuestionKey","passwordRecoveryQuestion","passwordRecoveryMode","passwordRecoveryQuestionAnswer","passwordRecoveryToken","passwordRecoveryLinkTimer","passwordRecoverySecondaryEmailText","passwordRecoveryMailDomain","showLoader","showLogin","queryString","window","let","token","URLSearchParams","get","pathname","indexOf","tokenArray","replace","split","info","JSON","parse","atob","retrievePasswordRecoveryEnabled","login","then","data","totpmissingkey","totpdisabled","cn","url","continueLogin","msg","value","string","error","errorMessage","grace","l","expire","Math","round","passwordexpired","restoreLogin","passwordRecoveryInfo","verificationCode","passwordRecoveryAbort","href","reload","showAbout","$event","AboutDialogController","closeDialog","hide","show","targetEvent","templateUrl","controller","controllerAs","$inject","changeLanguage","ApplicationBaseURL","hello","form","canChangePassword","$setValidity","isInPasswordRecoveryMode","changePassword","mode","secretQuestionLabel","secretQuestion","obfuscatedRecoveryEmail","passwordRecoveryEmail","passwordRecoveryCheck","usernameChanged","clearTimeout","setTimeout","mailDomain","changePasswordVisibility","field","document","getElementById","type","innerHTML"],"mappings":"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 truncated
|
||||
{"version":3,"file":"Main.js","sources":["Main/Main.app.js"],"names":["angular","module","LoginController","$scope","$window","$timeout","Dialog","$mdDialog","Authentication","focus","rippleDo","vm","this","$onInit","creds","username","cookieUsername","password","domain","rememberLogin","isDefined","length","test","location","search","language","loginState","verificationCodePattern","passwords","newPassword","newPasswordConfirmation","oldPassword","visible","passwordRecovery","passwordRecoveryEnabled","passwordRecoveryQuestionKey","passwordRecoveryQuestion","passwordRecoveryMode","passwordRecoveryQuestionAnswer","passwordRecoveryToken","passwordRecoveryLinkTimer","passwordRecoverySecondaryEmailText","passwordRecoveryMailDomain","showLoader","showLogin","queryString","window","let","token","URLSearchParams","get","pathname","indexOf","tokenArray","replace","split","info","JSON","parse","atob","retrievePasswordRecoveryEnabled","document","querySelectorAll","forEach","el","parentElement","classList","add","login","then","data","totpmissingkey","totpdisabled","cn","url","continueLogin","msg","value","string","error","errorMessage","grace","l","expire","Math","round","passwordexpired","restoreLogin","passwordRecoveryInfo","verificationCode","passwordRecoveryAbort","href","reload","showAbout","$event","AboutDialogController","closeDialog","hide","show","targetEvent","templateUrl","controller","controllerAs","$inject","changeLanguage","ApplicationBaseURL","hello","form","canChangePassword","$setValidity","isInPasswordRecoveryMode","changePassword","mode","secretQuestionLabel","secretQuestion","obfuscatedRecoveryEmail","passwordRecoveryEmail","passwordRecoveryCheck","usernameChanged","clearTimeout","setTimeout","mailDomain","changePasswordVisibility","field","getElementById","type","innerHTML"],"mappings":"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 truncated
|
||||
@@ -76,8 +76,14 @@
|
||||
} else {
|
||||
vm.retrievePasswordRecoveryEnabled();
|
||||
}
|
||||
}, 100);
|
||||
|
||||
// Manage autofill
|
||||
if (document.querySelectorAll('*:autofill').length > 0) {
|
||||
document.querySelectorAll('*:autofill').forEach((el) => {
|
||||
el.parentElement.classList.add("md-input-has-value");
|
||||
});
|
||||
}
|
||||
}, 100);
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user