Applied PR90 as a patch due to too-many merge conflicts when cherry-picking

This commit is contained in:
Ludovic Marcotte
2015-07-22 09:05:17 -04:00
parent cc03430ac6
commit 8650492989
11 changed files with 396 additions and 116 deletions

View File

@@ -2862,6 +2862,7 @@ static BOOL debugOn = NO;
NSAutoreleasePool *pool;
id builder, dom;
SEL aSelector;
id activeUser;
NSString *cmdName, *deviceId;
NSData *d;
@@ -2870,6 +2871,14 @@ static BOOL debugOn = NO;
ASSIGN(context, theContext);
activeUser = [context activeUser];
if (![activeUser canAccessModule: @"ActiveSync"])
{
[theResponse setStatus: 403];
[self logWithFormat: @"EAS - Forbidden access for user %@", [activeUser loginInDomain]];
return nil;
}
// Get the device ID, device type and "stash" them
deviceId = [[theRequest uri] deviceId];
[context setObject: deviceId forKey: @"DeviceId"];

View File

@@ -178,56 +178,101 @@ rtf2html (NSData *compressedRTF)
andColumns: (struct SPropTagArray *) columns
{
NSMutableDictionary *recipientProperties;
enum MAPITAGS prop_tag;
char *displayName = NULL;
char *email = NULL;
enum MAPI_OBJTYPE object_type = 0;
char *smtpAddress = NULL;
SOGoUser *recipientUser;
NSUInteger count;
NSString *recipientEmail = nil;
NSString *recipientFullName = nil;
id value;
recipientProperties = [NSMutableDictionary dictionaryWithCapacity: columns->cValues + 2];
for (count = 0; count < columns->cValues; count++)
{
prop_tag = columns->aulPropTag[count];
switch(prop_tag) {
case PidTagDisplayName:
displayName = recipient->data[count];
break;
case PidTagEmailAddress:
email = recipient->data[count];
break;
case PidTagObjectType:
if (recipient->data[count])
object_type = *((uint8_t*) recipient->data[count]);
break;
case PidTagSmtpAddress:
smtpAddress = recipient->data[count];
break;
default:
break;
}
if (recipient->data[count])
{
value = NSObjectFromValuePointer (prop_tag,
recipient->data[count]);
if (value)
[recipientProperties setObject: value
forKey: MAPIPropertyKey (prop_tag)];
}
}
if (recipient->username)
{
value = [NSString stringWithUTF8String: recipient->username];
[recipientProperties setObject: value forKey: @"x500dn"];
}
if (object_type == MAPI_MAILUSER && recipient->username)
{
/* values from user object have priority over data sent by the client */
recipientUser = [SOGoUser userWithLogin: [value lowercaseString]];
if (recipientUser)
{
value = [recipientUser cn];
if ([value length] > 0)
[recipientProperties setObject: value forKey: @"fullName"];
recipientFullName = value;
value = [[recipientUser allEmails] objectAtIndex: 0];
if ([value length] > 0)
[recipientProperties setObject: value forKey: @"email"];
}
}
else
{
if (recipient->data[0])
{
value = [NSString stringWithUTF8String: recipient->data[0]];
if ([value length] > 0)
[recipientProperties setObject: value forKey: @"fullName"];
}
if (recipient->data[1])
{
value = [NSString stringWithUTF8String: recipient->data[1]];
if ([value length] > 0)
[recipientProperties setObject: value forKey: @"email"];
}
recipientEmail = value;
}
}
for (count = 0; count < columns->cValues; count++)
/* If we do not have values from the user object we try to get them from the parameters */
if (!recipientFullName && displayName)
{
if (recipient->data[count])
{
value = NSObjectFromValuePointer (columns->aulPropTag[count],
recipient->data[count]);
if (value)
[recipientProperties setObject: value
forKey: MAPIPropertyKey (columns->aulPropTag[count])];
}
value = [NSString stringWithUTF8String: displayName];
if ([value length] > 0)
recipientFullName = value;
}
if (!recipientEmail && email)
{
value = [NSString stringWithUTF8String: email];
if ([value length] > 0)
recipientEmail = value;
}
if (!recipientEmail && smtpAddress)
{
value = [NSString stringWithUTF8String: smtpAddress];
if ([value length] > 0)
recipientEmail = value;
}
/* Now we can set the properties if we have them */
if (recipientFullName)
[recipientProperties setObject: recipientFullName forKey: @"fullName"];
if (recipientEmail)
[recipientProperties setObject: recipientEmail forKey: @"email"];
return recipientProperties;
}

View File

@@ -2132,32 +2132,23 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
//
if ([[newEvent attendees] count] || [[oldEvent attendees] count])
{
NSString *uid;
BOOL userIsOrganizer;
// newEvent might be nil here, if we're deleting a RECURRENCE-ID with attendees
// If that's the case, we use the oldEvent for now just to obtain the organizer
// and we'll swap it back to nil once we're done.
if (!newEvent)
newEvent = oldEvent;
// We fetch the organizer's uid. Sometimes, the recurrence-id will
// have it, sometimes not. If it doesn't, we fetch it from the master event.
uid = [[newEvent organizer] uid];
if (!uid && !recurrenceId)
uid = [[[[[newEvent parent] events] objectAtIndex: 0] organizer] uid];
// If that's the case, we use the oldEvent to obtain the organizer
if (newEvent)
userIsOrganizer = [newEvent userIsOrganizer: ownerUser];
else
userIsOrganizer = [oldEvent userIsOrganizer: ownerUser];
// With Thunderbird 10, if you create a recurring event with an exception
// occurence, and invite someone, the PUT will have the organizer in the
// recurrence-id and not in the master event. We must fix this, otherwise
// SOGo will break.
if (!recurrenceId && ![[[[[newEvent parent] events] objectAtIndex: 0] organizer] uid])
[[[[newEvent parent] events] objectAtIndex: 0] setOrganizer: [newEvent organizer]];
if (newEvent == oldEvent)
newEvent = nil;
if (uid && [uid caseInsensitiveCompare: owner] == NSOrderedSame)
if (userIsOrganizer)
{
// A RECCURENCE-ID was removed
if (!newEvent && oldEvent)

View File

@@ -1,10 +1,12 @@
//
// BSONCodec.m
// BSON Codec for Objective-C.
//
// Created by Martin Kou on 8/17/10.
// MIT License, see LICENSE file for details.
//
/*
* BSONCodec.m
* BSON Codec for Objective-C.
*
* Created by Martin Kou on 8/17/10.
* MIT License, see LICENSE file for details.
*
* Adapted by Ludovic Marcotte and Enrique J. Hernández
*/
#import "BSONCodec.h"
#import <ctype.h>
@@ -570,7 +572,7 @@ static NSDictionary *BSONTypes()
{
NSString *v;
v = [self descriptionWithCalendarFormat: @"%Y-%m-%d %H:%M:%S %Z"
v = [self descriptionWithCalendarFormat: @"%Y-%m-%d %H:%M:%S %z"
locale: nil];
return [v BSONEncode];
@@ -599,7 +601,22 @@ static NSDictionary *BSONTypes()
key = [NSString stringWithFormat: @"%s", timezone];
if (!(tz = [timezoneCache objectForKey: key]))
/* We may have the zone using the UTC offset
or abbreviation (deprecated) */
if (timezone && strlen(timezone) > 0 && (timezone[0] == '+' || timezone[0] == '-'))
{
NSCalendarDate *tzDate;
tzDate = [[NSCalendarDate alloc] initWithString: key
calendarFormat: @"%z"
locale: nil];
[tzDate autorelease];
if (tzDate)
tz = [tzDate timeZone];
else
tz = nil;
}
else if (!(tz = [timezoneCache objectForKey: key]))
{
tz = [NSTimeZone timeZoneWithAbbreviation: key];

View File

@@ -737,7 +737,8 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses
}
NS_HANDLER
{
if ([[localException name] isEqual: @"LDAPException"] && ([[[localException userInfo] objectForKey: @"error_code"] intValue] == LDAP_CONSTRAINT_VIOLATION))
if ([[localException name] isEqual: @"LDAPException"] &&
([[[localException userInfo] objectForKey: @"error_code"] intValue] == LDAP_CONSTRAINT_VIOLATION))
{
*perr = PolicyInsufficientPasswordQuality;
}
@@ -1166,6 +1167,8 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses
intoLDIFRecord: (NSMutableDictionary *) ldifRecord];
[self _fillConstraints: ldapEntry forModule: @"Mail"
intoLDIFRecord: (NSMutableDictionary *) ldifRecord];
[self _fillConstraints: ldapEntry forModule: @"ActiveSync"
intoLDIFRecord: (NSMutableDictionary *) ldifRecord];
if (contactMapping)
[self _applyContactMappingToResult: ldifRecord];

View File

@@ -157,7 +157,7 @@
// that much about this for now.
//
+ (NSString *) securedValue: (NSString *) theValue
usingKey: (NSString *) theKey
usingKey: (NSString *) theKey
{
NSData *data;
NSString *s;
@@ -171,13 +171,12 @@
klen = [data length];
// Get the key - padding it with 0 with key length
pass = (char *)malloc(klen);
memset(pass, 0, klen);
pass = (char *) calloc(klen, sizeof(char));
[theValue getCString: pass maxLength: klen encoding: NSUTF8StringEncoding];
// Target buffer
buf = (char *)malloc(klen);
for (i = 0; i < klen; i++)
{
buf[i] = key[i] ^ pass[i];
@@ -186,36 +185,38 @@
free(pass);
data = [NSData dataWithBytesNoCopy: buf length: klen freeWhenDone: YES];
s = [[NSString alloc] initWithData: [data dataByEncodingBase64WithLineLength: 1024]
encoding: NSASCIIStringEncoding];
encoding: NSASCIIStringEncoding];
return [s autorelease];
}
+ (NSString *) valueFromSecuredValue: (NSString *) theValue
usingKey: (NSString *) theKey
usingKey: (NSString *) theKey
{
NSData *data;
NSData *dataKey, *dataValue;
NSString *s;
char *buf, *key, *pass;
int i, klen;
char *buf, *key, *value;
size_t i, klen, vlen;
// Get the key length and its bytes
data = [theKey dataByDecodingBase64];
key = (char *)[data bytes];
klen = [data length];
dataKey = [theKey dataByDecodingBase64];
key = (char *)[dataKey bytes];
klen = [dataKey length];
// Get the secured value length and its bytes
dataValue = [theValue dataByDecodingBase64];
value = (char *)[dataValue bytes];
vlen = [dataValue length];
// Get the secured password
pass = (char *)[[theValue dataByDecodingBase64] bytes];
// Target buffer
buf = (char *)malloc(klen);
buf = (char *) calloc(klen, sizeof(char));
for (i = 0; i < klen; i++)
for (i = 0; i < klen && i < vlen; i++)
{
buf[i] = key[i] ^ pass[i];
buf[i] = key[i] ^ value[i];
}
// buf is now our C string in UTF8

View File

@@ -438,14 +438,16 @@ static Class NSNullK;
NSEnumerator *authIDs;
NSString *currentID;
BOOL checkOK;
SOGoSystemDefaults *sd;
NSRange r;
checkOK = NO;
authIDs = [[self authenticationSourceIDsInDomain: *domain] objectEnumerator];
while (!checkOK && (currentID = [authIDs nextObject]))
{
sogoSource = [_sources objectForKey: currentID];
checkOK = [sogoSource checkLogin: login
password: password
perr: perr
@@ -649,7 +651,7 @@ static Class NSNullK;
[currentSource setBindPassword: _pwd];
}
}
return checkOK;
}
@@ -742,6 +744,12 @@ static Class NSNullK;
NSNumber *isGroup;
NSArray *c_emails;
BOOL access;
NSEnumerator *enumerator;
NSString *access_type;
NSArray *access_types_list = [NSArray arrayWithObjects: @"CalendarAccess",
@"MailAccess",
@"ActiveSyncAccess",
nil];
emails = [NSMutableArray array];
cn = nil;
@@ -751,10 +759,10 @@ static Class NSNullK;
c_imaplogin = nil;
c_sievehostname = nil;
[theCurrentUser setObject: [NSNumber numberWithBool: YES]
forKey: @"CalendarAccess"];
[theCurrentUser setObject: [NSNumber numberWithBool: YES]
forKey: @"MailAccess"];
enumerator = [access_types_list objectEnumerator];
while ((access_type = [enumerator nextObject]) != nil)
[theCurrentUser setObject: [NSNumber numberWithBool: YES]
forKey: access_type];
if ([[theCurrentUser objectForKey: @"DomainLessLogin"] boolValue])
{
@@ -763,7 +771,6 @@ static Class NSNullK;
r = [theUID rangeOfString: [NSString stringWithFormat: @"@%@", theDomain]];
theUID = [theUID substringToIndex: r.location];
}
sogoSources = [[self authenticationSourceIDsInDomain: theDomain] objectEnumerator];
userEntry = nil;
@@ -791,14 +798,15 @@ static Class NSNullK;
c_imaplogin = [userEntry objectForKey: @"c_imaplogin"];
if (!c_sievehostname)
c_sievehostname = [userEntry objectForKey: @"c_sievehostname"];
access = [[userEntry objectForKey: @"CalendarAccess"] boolValue];
if (!access)
[theCurrentUser setObject: [NSNumber numberWithBool: NO]
forKey: @"CalendarAccess"];
access = [[userEntry objectForKey: @"MailAccess"] boolValue];
if (!access)
[theCurrentUser setObject: [NSNumber numberWithBool: NO]
forKey: @"MailAccess"];
enumerator = [access_types_list objectEnumerator];
while ((access_type = [enumerator nextObject]) != nil)
{
access = [[userEntry objectForKey: access_type] boolValue];
if (!access)
[theCurrentUser setObject: [NSNumber numberWithBool: NO]
forKey: access_type];
}
// We check if it's a group
isGroup = [userEntry objectForKey: @"isGroup"];

View File

@@ -22,6 +22,7 @@ $(SOGO_TOOL)_OBJC_FILES += \
SOGoToolRemoveDoubles.m \
SOGoToolRenameUser.m \
SOGoToolRestore.m \
SOGoToolCreateFolder.m \
SOGoToolUserPreferences.m \
SOGoToolManageEAS.m
TOOL_NAME += $(SOGO_TOOL)

View File

@@ -0,0 +1,175 @@
/* SOGoToolCreateFolder.m - this file is part of SOGo
* Implementation of create-folder command for sogo-tool
*
* Copyright (C) 2015 Javier Amor Garcia
*
* 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 <Foundation/NSException.h>
#import <SOGo/NSArray+Utilities.h>
#import <SOGo/SOGoObject.h>
#import <GDLContentStore/GCSFolderManager.h>
#import <GDLContentStore/GCSFolder.h>
#import "SOGoToolRestore.h"
@interface SOGoToolCreateFolder : SOGoToolRestore
{
NSMutableArray *foldersContents;
NSString *folderType;
}
@end
@implementation SOGoToolCreateFolder
+ (NSString *) command
{
return @"create-folder";
}
+ (NSString *) description
{
return @"create folders for a user";
}
- (id) init
{
if ((self = [super init]))
{
foldersContents = nil;
folderType = nil;
}
return self;
}
- (void) dealloc
{
[foldersContents release];
[folderType release];
[super dealloc];
}
- (void) usage
{
fprintf (stderr, "create-folder user type [displayname ...]\n\n"
" user the user on which the folder(s) will be created\n"
" type type of directory. Calendar or Contacts\n"
" displayname display name(s) for the created folder(s)\n\n"
"Examples: sogo-tool create-folder user1 Calendar cal1 cal2\n"
" sogo-tool create-folder user1 Contacts agenda\n");
}
- (BOOL) createNewFolderOfType: (NSString *) type
withContent: (NSDictionary *) content
{
NSString *folder;
NSString *guid;
GCSFolderManager *fm;
GCSFolder *gcsFolder;
BOOL rc;
guid = [SOGoObject globallyUniqueObjectId];
folder= [NSString stringWithFormat: @"/Users/%@/%@/%@",
userID, type, guid];
fm = [GCSFolderManager defaultFolderManager];
rc = [self createFolder: folder withFM: fm];
if (!rc)
{
NSLog (@"Create directory failed at path %s", folder);
return NO;
}
gcsFolder = [fm folderAtPath: folder];
if (!gcsFolder)
{
NSLog (@"folder '%@' could not be created", folder);
return NO;
}
rc = [self restoreDisplayName: [content objectForKey: @"displayname"]
ofFolder: gcsFolder
withFM: fm];
return rc;
}
- (BOOL) proceed
{
BOOL rc;
NSUInteger count, i;
NSDictionary * content;
rc = YES;
count = [foldersContents count];
for (i = 0; i < count; i++)
{
content = [foldersContents objectAtIndex: i];
if (![self createNewFolderOfType: folderType withContent: content])
{
rc = NO;
}
}
return rc;
}
- (BOOL) parseArguments
{
NSString *identifier;
NSUInteger count, i;
NSDictionary *content;
count = [arguments count];
if (count < 3)
{
[self usage];
return NO;
}
identifier = [arguments objectAtIndex: 0];
if (![self fetchUserID: identifier])
{
fprintf (stderr, "Invalid user:%s\n", [identifier cString]);
return NO;
}
folderType = [arguments objectAtIndex: 1];
if (!([folderType isEqualToString: @"Contacts"] || [folderType isEqualToString: @"Calendar"]))
{
fprintf (stderr, "Invalid folder type:%s\n", [folderType cString]);
return NO;
}
foldersContents = [[NSMutableArray alloc] init];
for (i = 2; i < count; i++)
{
content = [NSDictionary dictionaryWithObject: [arguments objectAtIndex: i]
forKey: @"displayname"];
[foldersContents addObject: content];
}
return YES;
}
@end

49
Tools/SOGoToolRestore.h Normal file
View File

@@ -0,0 +1,49 @@
/* SOGoToolRestore.h - this file is part of SOGo
* Header to allow subclassing of SOGoToolRestore class
*
* Copyright (C) 2015 Javier Amor Garcia
*
* 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 "SOGoTool.h"
typedef enum SOGoToolRestoreMode {
SOGoToolRestoreFolderMode,
SOGoToolRestoreFolderDestructiveMode,
SOGoToolRestoreListFoldersMode,
SOGoToolRestorePreferencesMode
} SOGoToolRestoreMode;
@interface SOGoToolRestore : SOGoTool
{
NSString *directory;
NSString *userID;
NSString *filename;
NSString *restoreFolder;
BOOL destructive; /* destructive mode not handled */
SOGoToolRestoreMode restoreMode;
}
- (BOOL) fetchUserID: (NSString *) identifier;
- (BOOL) createFolder: (NSString *) folder
withFM: (GCSFolderManager *) fm;
- (BOOL) restoreDisplayName: (NSString *) newDisplayName
ofFolder: (GCSFolder *) gcsFolder
withFM: (GCSFolderManager *) fm;
@end

View File

@@ -46,33 +46,14 @@
#import <NGCards/NGVCard.h>
#import <NGCards/NGVList.h>
#import "SOGoTool.h"
#import "SOGoToolRestore.h"
/* TODO:
- respond to "--help restore"
- handle database connectivity errors
- handle the case where the restored folder has been deleted
- write methods in GDLContentStore to get/update displayname
and storing roles */
typedef enum SOGoToolRestoreMode {
SOGoToolRestoreFolderMode,
SOGoToolRestoreFolderDestructiveMode,
SOGoToolRestoreListFoldersMode,
SOGoToolRestorePreferencesMode
} SOGoToolRestoreMode;
@interface SOGoToolRestore : SOGoTool
{
NSString *directory;
NSString *userID;
NSString *filename;
NSString *restoreFolder;
BOOL destructive; /* destructive mode not handled */
SOGoToolRestoreMode restoreMode;
}
@end
and storing roles */
@implementation SOGoToolRestore
@@ -176,8 +157,8 @@ typedef enum SOGoToolRestoreMode {
SOGoSystemDefaults *sd;
SOGoUserManager *lm;
NSDictionary *infos;
NSString *uid;
NSString *uid = nil;
BOOL rc;
lm = [SOGoUserManager sharedUserManager];
@@ -188,7 +169,7 @@ typedef enum SOGoToolRestoreMode {
{
sd = [SOGoSystemDefaults sharedSystemDefaults];
uid = [infos objectForKey: @"c_uid"];
if ([sd enableDomainBasedUID] && [uid rangeOfString: @"@"].location == NSNotFound)
uid = [NSString stringWithFormat: @"%@@%@",
[infos objectForKey: @"c_uid"],