See ChangeLog
Monotone-Parent: ed15d4f340fd47347d881c8826eb40a2dc22763d Monotone-Revision: d669b0b3e321e22c68d092f984d543560ae1af0e Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2012-01-12T20:01:34maint-2.0.2
parent
335ba606b4
commit
ccf847f555
33
ChangeLog
33
ChangeLog
|
@ -1,3 +1,36 @@
|
||||||
|
2012-01-12 Francis Lachapelle <flachapelle@inverse.ca>
|
||||||
|
|
||||||
|
* SoObjects/SOGo/SOGoSource.h (-bindDN, -bindPassword)
|
||||||
|
(-MSExchangeHostname): new accessors to the SOGoDNSource protocol.
|
||||||
|
|
||||||
|
* SoObjects/SOGo/LDAPSource.m (-_convertLDAPEntryToContact:):
|
||||||
|
added a reference to the instance source in the returned dictionary.
|
||||||
|
|
||||||
|
* SoObjects/SOGo/SOGoUserManager.m
|
||||||
|
(-_compactAndCompleteContacts:): keep the source instance in the
|
||||||
|
returned dictionary.
|
||||||
|
|
||||||
|
* UI/MainUI/SOGoUserHomePage.m (-readFreeBusyAction): the http
|
||||||
|
post can now include an optional "uid" parameter to perform the
|
||||||
|
freebusy lookup on the user corresponding to the specified
|
||||||
|
uid. This covers the special case where we want to query a user
|
||||||
|
from a contact source (not an authentication source) and for which
|
||||||
|
external freebusy information is available (currently limited to a
|
||||||
|
Microsoft Exchange server with Web Services enabled).
|
||||||
|
|
||||||
|
* SoObjects/Appointments/SOGoFreeBusyObject.m
|
||||||
|
(-fetchFreeBusyInfosFrom:to:forUser:): new method currently
|
||||||
|
limited perform a SOAP request to a MS Exhange server to retrieve
|
||||||
|
the freebusy information of a user.
|
||||||
|
|
||||||
|
* UI/WebServerResources/UIxAttendeesEditor.js
|
||||||
|
(performSearchCallback): if a matching contact has the
|
||||||
|
"isMSExchange" attribute, prefix the uid with the login uid.
|
||||||
|
(_performAjaxRequest): query the freebusy information from the
|
||||||
|
login user (/SOGo/so/<loginuser>/freebusy.ifb/ajaxRead?uid=<contact>)
|
||||||
|
when a contact uid is specified. Otherwise, perform the query on
|
||||||
|
the user instance as usual (/SOGo/so/<contactuser>/freebusy.ifb/ajaxRead).
|
||||||
|
|
||||||
2012-01-10 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
2012-01-10 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
* SoObjects/Appointments/SOGoAppointmentObject.m
|
* SoObjects/Appointments/SOGoAppointmentObject.m
|
||||||
|
|
|
@ -42,10 +42,15 @@ Appointments_OBJC_FILES = \
|
||||||
SOGoAptMailUpdate.m \
|
SOGoAptMailUpdate.m \
|
||||||
SOGoAptMailReceipt.m \
|
SOGoAptMailReceipt.m \
|
||||||
\
|
\
|
||||||
SOGoEMailAlarmsManager.m
|
SOGoEMailAlarmsManager.m \
|
||||||
|
\
|
||||||
|
MSExchangeFreeBusySOAPRequest.m \
|
||||||
|
MSExchangeFreeBusy.m
|
||||||
|
|
||||||
Appointments_RESOURCE_FILES += \
|
Appointments_RESOURCE_FILES += \
|
||||||
product.plist \
|
product.plist \
|
||||||
|
\
|
||||||
|
MSExchangeFreeBusySOAPRequest.wo
|
||||||
|
|
||||||
Appointments_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian SpanishSpain SpanishArgentina Swedish Ukrainian Welsh
|
Appointments_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian SpanishSpain SpanishArgentina Swedish Ukrainian Welsh
|
||||||
|
|
||||||
|
@ -53,6 +58,7 @@ Appointments_LOCALIZED_RESOURCE_FILES = Localizable.strings
|
||||||
|
|
||||||
ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/
|
ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/
|
||||||
ADDITIONAL_LIB_DIRS += -L../../SOPE/GDLContentStore/obj/
|
ADDITIONAL_LIB_DIRS += -L../../SOPE/GDLContentStore/obj/
|
||||||
|
ADDITIONAL_LDFLAGS += -lcurl -lgnutls
|
||||||
|
|
||||||
-include GNUmakefile.preamble
|
-include GNUmakefile.preamble
|
||||||
include $(GNUSTEP_MAKEFILES)/wobundle.make
|
include $(GNUSTEP_MAKEFILES)/wobundle.make
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/* MSExchangeFreeBusy.h - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Inverse inc.
|
||||||
|
*
|
||||||
|
* Author: Francis Lachapelle <flachapelle@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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MSEXCHANGEFREEBUSY_H
|
||||||
|
#define MSEXCHANGEFREEBUSY_H
|
||||||
|
|
||||||
|
#include <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@class MSExchangeFreeBusyResponse;
|
||||||
|
@class MSExchangeFreeBusyView;
|
||||||
|
|
||||||
|
@interface MSExchangeFreeBusy : NSObject
|
||||||
|
{
|
||||||
|
NSMutableData *curlBody;
|
||||||
|
MSExchangeFreeBusyResponse *response;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (size_t) curlWritePtr: (void *) inPtr
|
||||||
|
size: (size_t) inSize
|
||||||
|
number: (size_t) inNumber;
|
||||||
|
- (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) startDate
|
||||||
|
to: (NSCalendarDate *) endDate
|
||||||
|
forEmail: (NSString *) email
|
||||||
|
inSource: (NSObject <SOGoDNSource> *) source
|
||||||
|
// fromServer: (NSString *) hostname
|
||||||
|
inContext: (WOContext *) context;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface MSExchangeFreeBusyResponse : NSObject
|
||||||
|
{
|
||||||
|
MSExchangeFreeBusyView *view;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (MSExchangeFreeBusyView *) view;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface MSExchangeFreeBusyView : NSObject
|
||||||
|
{
|
||||||
|
NSString *freeBusyViewType;
|
||||||
|
NSString *mergedFreeBusy;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) infosFrom: (NSCalendarDate *) startDate
|
||||||
|
to: (NSCalendarDate *) endDate;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif /* MSEXCHANGEFREEBUSY_H */
|
|
@ -0,0 +1,350 @@
|
||||||
|
/* MSExchangeFreeBusy.m - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Inverse inc.
|
||||||
|
*
|
||||||
|
* Author: Francis Lachapelle <flachapelle@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/NSCalendarDate.h>
|
||||||
|
#import <Foundation/NSDictionary.h>
|
||||||
|
|
||||||
|
#import <NGObjWeb/WOApplication.h>
|
||||||
|
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||||
|
#import <NGObjWeb/WOResponse.h>
|
||||||
|
|
||||||
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
|
||||||
|
#import <SaxObjC/SaxObjC.h>
|
||||||
|
#import <SaxObjC/SaxMethodCallHandler.h>
|
||||||
|
#import <SaxObjC/SaxObjectDecoder.h>
|
||||||
|
#import <SaxObjC/SaxXMLReaderFactory.h>
|
||||||
|
|
||||||
|
#import <curl/curl.h>
|
||||||
|
|
||||||
|
#import <SOGo/SOGoSource.h>
|
||||||
|
|
||||||
|
#import "MSExchangeFreeBusySOAPRequest.h"
|
||||||
|
#import "MSExchangeFreeBusy.h"
|
||||||
|
|
||||||
|
size_t curlBodyFunction(void *ptr, size_t size, size_t nmemb, void *inSelf)
|
||||||
|
{
|
||||||
|
return [(MSExchangeFreeBusy *)inSelf curlWritePtr:ptr size:size number:nmemb];
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation MSExchangeFreeBusy
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
curlBody = [[NSMutableData alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[curlBody release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (size_t) curlWritePtr:(void *)inPtr
|
||||||
|
size:(size_t)inSize
|
||||||
|
number:(size_t)inNumber
|
||||||
|
{
|
||||||
|
size_t written = inSize*inNumber;
|
||||||
|
NSData *data = [NSData dataWithBytes:inPtr length:written];
|
||||||
|
[curlBody appendData: data];
|
||||||
|
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the user availability by sending a SOAP request to a MS Exchange server (EWS).
|
||||||
|
* @param startDate the beginning of the covered period
|
||||||
|
* @param endDate the ending of the covered period
|
||||||
|
* @param email the address of the user to query
|
||||||
|
* @param source the SOGo source of the user
|
||||||
|
* @param context the current WO context
|
||||||
|
* @return an array of dictionaries containing the start and end dates of each busy period
|
||||||
|
* @see <http://msdn.microsoft.com/en-us/library/aa563800(v=EXCHG.140).aspx>
|
||||||
|
*/
|
||||||
|
- (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) startDate
|
||||||
|
to: (NSCalendarDate *) endDate
|
||||||
|
forEmail: (NSString *) email
|
||||||
|
inSource: (NSObject <SOGoDNSource> *) source
|
||||||
|
inContext: (WOContext *) context
|
||||||
|
{
|
||||||
|
static id<NSObject,SaxXMLReader> parser = nil;
|
||||||
|
static SaxObjectDecoder *sax = nil;
|
||||||
|
|
||||||
|
MSExchangeFreeBusySOAPRequest *soapRequest;
|
||||||
|
MSExchangeFreeBusyResponse *freeBusyResponse;
|
||||||
|
NSString *rawRequest, *url, *body, *hostname, *httpauth, *authname, *password;
|
||||||
|
NSArray *infos = nil;
|
||||||
|
NSDictionary *root;
|
||||||
|
|
||||||
|
CURL *curl;
|
||||||
|
struct curl_slist *headerlist=NULL;
|
||||||
|
CURLcode rc;
|
||||||
|
char error[CURL_ERROR_SIZE];
|
||||||
|
|
||||||
|
// Construct SOAP GetUserAvailabilityRequest from .wo template
|
||||||
|
soapRequest = [[WOApplication application] pageWithName: @"MSExchangeFreeBusySOAPRequest"
|
||||||
|
inContext: context];
|
||||||
|
[soapRequest setAddress: email
|
||||||
|
from: startDate
|
||||||
|
to: endDate];
|
||||||
|
rawRequest = [[soapRequest generateResponse] contentAsString];
|
||||||
|
|
||||||
|
if ([rawRequest length])
|
||||||
|
{
|
||||||
|
// Prepare HTTPS post using libcurl
|
||||||
|
curl_global_init(CURL_GLOBAL_SSL);
|
||||||
|
curl = curl_easy_init();
|
||||||
|
headerlist = curl_slist_append(headerlist, "Content-Type: text/xml; charset=utf-8");
|
||||||
|
if (curl)
|
||||||
|
{
|
||||||
|
hostname = [source MSExchangeHostname];
|
||||||
|
authname = [source lookupLoginByDN: [source bindDN]];
|
||||||
|
password = [source bindPassword];
|
||||||
|
error[0] = 0;
|
||||||
|
if ([authname length] && [password length])
|
||||||
|
{
|
||||||
|
httpauth = [NSString stringWithFormat: @"%@:%@", authname, password];
|
||||||
|
curl_easy_setopt(curl, CURLOPT_USERPWD, [httpauth UTF8String]);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
|
||||||
|
}
|
||||||
|
url = [NSString stringWithFormat: @"https://%@/ews/Exchange.asmx", hostname];
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, [url UTF8String]);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, [rawRequest UTF8String]);
|
||||||
|
//curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curlHeaderFunction);
|
||||||
|
//curl_easy_setopt(curl, CURLOPT_HEADER, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlBodyFunction);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, self);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error);
|
||||||
|
|
||||||
|
// Perform SOAP request
|
||||||
|
rc = curl_easy_perform(curl);
|
||||||
|
if (rc != 0)
|
||||||
|
[self errorWithFormat: @"CURL error while accessing %@ (%d): ", url, rc, [NSString stringWithCString: error]];
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
curl_slist_free_all(headerlist);
|
||||||
|
|
||||||
|
if ([curlBody length])
|
||||||
|
{
|
||||||
|
// Parse SOAP response
|
||||||
|
if (parser == nil)
|
||||||
|
{
|
||||||
|
parser = [[SaxXMLReaderFactory standardXMLReaderFactory]
|
||||||
|
createXMLReaderForMimeType:@"text/xml"];
|
||||||
|
[parser retain];
|
||||||
|
}
|
||||||
|
if (sax == nil && parser != nil)
|
||||||
|
{
|
||||||
|
sax = [[SaxObjectDecoder alloc] initWithMappingAtPath:@"./MSExchangeFreeBusySOAPResponseMap.plist"];
|
||||||
|
[parser setContentHandler:sax];
|
||||||
|
//[parser setErrorHandler:sax];
|
||||||
|
}
|
||||||
|
|
||||||
|
body = [[NSString alloc] initWithData:curlBody encoding:NSASCIIStringEncoding];
|
||||||
|
[body autorelease];
|
||||||
|
|
||||||
|
[parser parseFromSource: body];
|
||||||
|
root = [sax rootObject];
|
||||||
|
freeBusyResponse = [[root objectForKey: @"Body"] objectForKey: @"GetUserAvailabilityResponse"];
|
||||||
|
|
||||||
|
// Extract busy periods
|
||||||
|
infos = [[freeBusyResponse view] infosFrom: startDate to: endDate];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return infos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@implementation MSExchangeFreeBusyResponse
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
view = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[view release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (MSExchangeFreeBusyView *) view
|
||||||
|
{
|
||||||
|
return self->view;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setFreeBusyResponseArray: (NSDictionary *) _value
|
||||||
|
{
|
||||||
|
NSString *responseCode;
|
||||||
|
NSArray *responses;
|
||||||
|
NSDictionary *response;
|
||||||
|
|
||||||
|
view = nil;
|
||||||
|
responses = (NSArray *) [_value objectForKey: @"responses"];
|
||||||
|
|
||||||
|
if ([responses count] != 1)
|
||||||
|
{
|
||||||
|
[self errorWithFormat: @"unexpected number of responses (%i) from SOAP request", [responses count]];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response = [responses objectAtIndex: 0];
|
||||||
|
responseCode = [[response objectForKey: @"ResponseMessage"] objectForKey: @"ResponseCode"];
|
||||||
|
if ([responseCode compare: @"NoError"] == NSOrderedSame)
|
||||||
|
{
|
||||||
|
view = [response objectForKey: @"FreeBusyView"];
|
||||||
|
[view retain];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[self logWithFormat: @"SOAP Response: %@", self->view];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation MSExchangeFreeBusyView
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
freeBusyViewType = nil;
|
||||||
|
mergedFreeBusy = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[freeBusyViewType release];
|
||||||
|
[mergedFreeBusy release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setFreeBusyViewType: (NSString *) _value
|
||||||
|
{
|
||||||
|
ASSIGN(freeBusyViewType, _value);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setMergedFreeBusy: (NSString *) _value
|
||||||
|
{
|
||||||
|
ASSIGN(mergedFreeBusy, _value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the "DetailedMerged" representation of the freebusy information and
|
||||||
|
* extract the busy periods.
|
||||||
|
* @param startDate the beginning of the covered period
|
||||||
|
* @param endDate the ending of the covered period
|
||||||
|
* @return an array of dictionaries containing the start and end dates of each busy period
|
||||||
|
* @see <http://msdn.microsoft.com/en-us/library/aa565898(v=EXCHG.140).aspx>
|
||||||
|
*/
|
||||||
|
- (NSArray *) infosFrom: (NSCalendarDate *) startDate
|
||||||
|
to: (NSCalendarDate *) endDate
|
||||||
|
{
|
||||||
|
NSMutableArray *infos;
|
||||||
|
NSCalendarDate *currentDate, *currentStartDate, *currentEndDate;
|
||||||
|
unsigned int count;
|
||||||
|
|
||||||
|
infos = [NSMutableArray array];
|
||||||
|
currentStartDate = nil;
|
||||||
|
currentDate = startDate;
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
while (([currentDate compare: endDate] == NSOrderedAscending ||
|
||||||
|
[currentDate compare: endDate] == NSOrderedSame) &&
|
||||||
|
[mergedFreeBusy length] > count)
|
||||||
|
{
|
||||||
|
switch ([mergedFreeBusy characterAtIndex: count])
|
||||||
|
{
|
||||||
|
case '0': // Free
|
||||||
|
if (currentStartDate)
|
||||||
|
{
|
||||||
|
currentEndDate = currentDate;
|
||||||
|
[infos addObject: [NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
|
[NSNumber numberWithBool: YES], @"c_isopaque",
|
||||||
|
currentStartDate, @"startDate",
|
||||||
|
currentEndDate, @"endDate", nil]];
|
||||||
|
[self debugWithFormat: @"Busy period from %@ to %@", currentStartDate, currentEndDate];
|
||||||
|
currentStartDate = nil;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '1': // Tentative
|
||||||
|
case '2': // Busy
|
||||||
|
case '3': // Out of Office
|
||||||
|
if (currentStartDate == nil)
|
||||||
|
currentStartDate = currentDate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
currentDate = [currentDate dateByAddingYears: 0 months: 0 days: 0
|
||||||
|
hours: 0 minutes: 15 seconds: 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentStartDate)
|
||||||
|
{
|
||||||
|
currentEndDate = currentDate;
|
||||||
|
[infos addObject: [NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
|
[NSNumber numberWithBool: YES], @"c_isopaque",
|
||||||
|
currentStartDate, @"startDate",
|
||||||
|
currentEndDate, @"endDate", nil]];
|
||||||
|
[self debugWithFormat: @"Busy period from %@ to %@", currentStartDate, currentEndDate];
|
||||||
|
}
|
||||||
|
|
||||||
|
return infos;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) description
|
||||||
|
{
|
||||||
|
NSMutableString *s;
|
||||||
|
|
||||||
|
s = [NSMutableString stringWithCapacity: 64];
|
||||||
|
[s appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
|
||||||
|
if (freeBusyViewType)
|
||||||
|
[s appendFormat:@" freeBusyViewType='%@'", freeBusyViewType];
|
||||||
|
if (mergedFreeBusy)
|
||||||
|
[s appendFormat:@" mergedFreeBusy='%@'", mergedFreeBusy];
|
||||||
|
[s appendString:@">"];
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2012 Inverse inc.
|
||||||
|
|
||||||
|
This file is part of SOGo.
|
||||||
|
|
||||||
|
SOGo is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with SOGo; see the file COPYING. If not, write to the
|
||||||
|
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __Appointments_MSExchangeFreeBusySOAPRequest_H_
|
||||||
|
#define __Appointments_MSExchangeFreeBusySOAPRequest_H_
|
||||||
|
|
||||||
|
#include <NGObjWeb/SoComponent.h>
|
||||||
|
|
||||||
|
@class NSCalendarDate;
|
||||||
|
@class NSMutableDictionary;
|
||||||
|
@class NSString;
|
||||||
|
@class NSTimeZone;
|
||||||
|
@class iCalEvent;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: We inherit from SoComponent in order to get the correct
|
||||||
|
* resourceManager required for this product
|
||||||
|
*/
|
||||||
|
@interface MSExchangeFreeBusySOAPRequest : SoComponent
|
||||||
|
{
|
||||||
|
NSString *address;
|
||||||
|
NSTimeZone *timeZone;
|
||||||
|
NSCalendarDate *startDate;
|
||||||
|
NSCalendarDate *endDate;
|
||||||
|
int interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setAddress: (NSString *) _address
|
||||||
|
from: (NSCalendarDate *) _startDate
|
||||||
|
to: (NSCalendarDate *) _endDate;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif /* __Appointments_MSExchangeFreeBusySOAPRequest_H_ */
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2012 Inverse inc.
|
||||||
|
|
||||||
|
This file is part of SOGo.
|
||||||
|
|
||||||
|
SOGo is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with SOGo; see the file COPYING. If not, write to the
|
||||||
|
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/NSCharacterSet.h>
|
||||||
|
#import <Foundation/NSCalendarDate.h>
|
||||||
|
#import <Foundation/NSTimeZone.h>
|
||||||
|
|
||||||
|
#import <NGObjWeb/WOActionResults.h>
|
||||||
|
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||||
|
#import <NGObjWeb/WOResponse.h>
|
||||||
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
#import <NGCards/iCalEvent.h>
|
||||||
|
#import <NGCards/iCalPerson.h>
|
||||||
|
|
||||||
|
#import <SOGo/NSDictionary+Utilities.h>
|
||||||
|
#import <SOGo/NSObject+Utilities.h>
|
||||||
|
#import <SOGo/NSString+Utilities.h>
|
||||||
|
#import <SOGo/SOGoDateFormatter.h>
|
||||||
|
#import <SOGo/SOGoUser.h>
|
||||||
|
#import <SOGo/SOGoUserDefaults.h>
|
||||||
|
|
||||||
|
#import "MSExchangeFreeBusySOAPRequest.h"
|
||||||
|
|
||||||
|
@implementation MSExchangeFreeBusySOAPRequest
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
address = nil;
|
||||||
|
timeZone = [NSTimeZone timeZoneWithAbbreviation: @"GMT"];
|
||||||
|
[timeZone retain];
|
||||||
|
startDate = nil;
|
||||||
|
endDate = nil;
|
||||||
|
interval = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[address release];
|
||||||
|
[timeZone release];
|
||||||
|
[startDate release];
|
||||||
|
[endDate release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setAddress: (NSString *) newAddress
|
||||||
|
from: (NSCalendarDate *) newStartDate
|
||||||
|
to: (NSCalendarDate *) newEndDate
|
||||||
|
{
|
||||||
|
ASSIGN(address, newAddress);
|
||||||
|
ASSIGN(startDate, newStartDate);
|
||||||
|
ASSIGN(endDate, newEndDate);
|
||||||
|
|
||||||
|
[startDate setTimeZone: timeZone];
|
||||||
|
[endDate setTimeZone: timeZone];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) serverVersion
|
||||||
|
{
|
||||||
|
return @"Exchange2007_SP1";
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) address
|
||||||
|
{
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) startTime
|
||||||
|
{
|
||||||
|
return [startDate descriptionWithCalendarFormat: @"%Y-%m-%dT%H:%M:%S"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) endTime
|
||||||
|
{
|
||||||
|
return [endDate descriptionWithCalendarFormat: @"%Y-%m-%dT%H:%M:%S"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) interval
|
||||||
|
{
|
||||||
|
return [NSString stringWithFormat: @"%i", interval];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?xml version="1.0" standalone="yes"?>
|
||||||
|
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
|
||||||
|
<soap:Header>
|
||||||
|
<t:RequestServerVersion Version="<#serverVersion/>"/>
|
||||||
|
</soap:Header>
|
||||||
|
<soap:Body>
|
||||||
|
<GetUserAvailabilityRequest xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"
|
||||||
|
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
|
||||||
|
<t:TimeZone xmlns="http://schemas.microsoft.com/exchange/services/2006/types">
|
||||||
|
<Bias>0</Bias>
|
||||||
|
<StandardTime>
|
||||||
|
<Bias>0</Bias>
|
||||||
|
<Time>00:00:00</Time>
|
||||||
|
<DayOrder>1</DayOrder>
|
||||||
|
<Month>1</Month>
|
||||||
|
<DayOfWeek>Sunday</DayOfWeek>
|
||||||
|
</StandardTime>
|
||||||
|
<DaylightTime>
|
||||||
|
<Bias>0</Bias>
|
||||||
|
<Time>00:00:00</Time>
|
||||||
|
<DayOrder>1</DayOrder>
|
||||||
|
<Month>1</Month>
|
||||||
|
<DayOfWeek>Sunday</DayOfWeek>
|
||||||
|
</DaylightTime>
|
||||||
|
</t:TimeZone>
|
||||||
|
<MailboxDataArray>
|
||||||
|
<t:MailboxData>
|
||||||
|
<t:Email>
|
||||||
|
<t:Address><#address/></t:Address>
|
||||||
|
</t:Email>
|
||||||
|
<t:AttendeeType>Required</t:AttendeeType>
|
||||||
|
<t:ExcludeConflicts>false</t:ExcludeConflicts>
|
||||||
|
</t:MailboxData>
|
||||||
|
</MailboxDataArray>
|
||||||
|
<t:FreeBusyViewOptions>
|
||||||
|
<t:TimeWindow>
|
||||||
|
<t:StartTime><#startTime/></t:StartTime>
|
||||||
|
<t:EndTime><#endTime/></t:EndTime>
|
||||||
|
</t:TimeWindow>
|
||||||
|
<t:MergedFreeBusyIntervalInMinutes>15</t:MergedFreeBusyIntervalInMinutes>
|
||||||
|
<t:RequestedView>DetailedMerged</t:RequestedView>
|
||||||
|
</t:FreeBusyViewOptions>
|
||||||
|
</GetUserAvailabilityRequest>
|
||||||
|
</soap:Body>
|
||||||
|
</soap:Envelope>
|
|
@ -0,0 +1,24 @@
|
||||||
|
serverVersion: WOString {
|
||||||
|
value = serverVersion;
|
||||||
|
escapeHTML = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
address: WOString {
|
||||||
|
value = address;
|
||||||
|
escapeHTML = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
startTime: WOString {
|
||||||
|
value = startTime;
|
||||||
|
escapeHTML = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
endTime: WOString {
|
||||||
|
value = endTime;
|
||||||
|
escapeHTML = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
interval: WOString {
|
||||||
|
value = interval;
|
||||||
|
escapeHTML = NO;
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
{ /* -*-java-*- */
|
||||||
|
"http://schemas.xmlsoap.org/soap/envelope/" = {
|
||||||
|
Envelope = {
|
||||||
|
class = NSMutableDictionary;
|
||||||
|
};
|
||||||
|
|
||||||
|
Header = {
|
||||||
|
class = NSMutableDictionary;
|
||||||
|
attributes = {
|
||||||
|
serverVersionInfo = ServerVersionInfo;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Body = {
|
||||||
|
class = NSMutableDictionary;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
"http://schemas.microsoft.com/exchange/services/2006/messages" = {
|
||||||
|
GetUserAvailabilityResponse = {
|
||||||
|
class = MSExchangeFreeBusyResponse;
|
||||||
|
attributes = {
|
||||||
|
FreeBusyResponseArray = FreeBusyResponseArray;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
FreeBusyResponseArray = {
|
||||||
|
class = NSMutableDictionary;
|
||||||
|
ToManyRelationships = {
|
||||||
|
responses = ( FreeBusyResponse );
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
ResponseMessage = {
|
||||||
|
class = NSMutableDictionary;
|
||||||
|
};
|
||||||
|
|
||||||
|
ResponseCode = {
|
||||||
|
class = NSString;
|
||||||
|
};
|
||||||
|
|
||||||
|
FreeBusyResponse = {
|
||||||
|
class = NSMutableDictionary;
|
||||||
|
};
|
||||||
|
|
||||||
|
FreeBusyView = {
|
||||||
|
class = MSExchangeFreeBusyView;
|
||||||
|
attributes = {
|
||||||
|
FreeBusyViewType = freeBusyViewType;
|
||||||
|
MergedFreeBusy = mergedFreeBusy;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
"http://schemas.microsoft.com/exchange/services/2006/types" = {
|
||||||
|
FreeBusyViewType = {
|
||||||
|
class = NSString;
|
||||||
|
};
|
||||||
|
MergedFreeBusy = {
|
||||||
|
class = NSString;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2007-2011 Inverse inc.
|
Copyright (C) 2007-2012 Inverse inc.
|
||||||
Copyright (C) 2000-2004 SKYRIX Software AG
|
Copyright (C) 2000-2004 SKYRIX Software AG
|
||||||
|
|
||||||
This file is part of SOGo
|
This file is part of SOGo
|
||||||
|
@ -38,8 +38,6 @@
|
||||||
@class iCalPerson;
|
@class iCalPerson;
|
||||||
|
|
||||||
@interface SOGoFreeBusyObject : SOGoObject
|
@interface SOGoFreeBusyObject : SOGoObject
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* accessors */
|
/* accessors */
|
||||||
|
|
||||||
|
@ -55,7 +53,9 @@
|
||||||
|
|
||||||
- (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) _startDate
|
- (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) _startDate
|
||||||
to: (NSCalendarDate *) _endDate;
|
to: (NSCalendarDate *) _endDate;
|
||||||
|
- (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) startDate
|
||||||
|
to: (NSCalendarDate *) endDate
|
||||||
|
forUser: (NSString *) uid;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* __Appointments_SOGoFreeBusyObject_H_ */
|
#endif /* __Appointments_SOGoFreeBusyObject_H_ */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2007-2011 Inverse inc.
|
Copyright (C) 2007-2012 Inverse inc.
|
||||||
Copyright (C) 2000-2004 SKYRIX Software AG
|
Copyright (C) 2000-2004 SKYRIX Software AG
|
||||||
|
|
||||||
This file is part of SOGo
|
This file is part of SOGo
|
||||||
|
@ -21,10 +21,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import <Foundation/NSCalendarDate.h>
|
#import <Foundation/NSCalendarDate.h>
|
||||||
|
#import <Foundation/NSData.h>
|
||||||
#import <Foundation/NSDictionary.h>
|
#import <Foundation/NSDictionary.h>
|
||||||
#import <Foundation/NSEnumerator.h>
|
#import <Foundation/NSEnumerator.h>
|
||||||
#import <Foundation/NSValue.h>
|
#import <Foundation/NSValue.h>
|
||||||
|
|
||||||
|
#import <NGObjWeb/WOApplication.h>
|
||||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||||
#import <NGObjWeb/WOResponse.h>
|
#import <NGObjWeb/WOResponse.h>
|
||||||
#import <NGExtensions/NSCalendarDate+misc.h>
|
#import <NGExtensions/NSCalendarDate+misc.h>
|
||||||
|
@ -34,6 +36,7 @@
|
||||||
|
|
||||||
#import <SOGo/SOGoBuild.h>
|
#import <SOGo/SOGoBuild.h>
|
||||||
#import <SOGo/SOGoDomainDefaults.h>
|
#import <SOGo/SOGoDomainDefaults.h>
|
||||||
|
#import <SOGo/SOGoSource.h>
|
||||||
#import <SOGo/SOGoUser.h>
|
#import <SOGo/SOGoUser.h>
|
||||||
#import <SOGo/SOGoUserDefaults.h>
|
#import <SOGo/SOGoUserDefaults.h>
|
||||||
#import <SOGo/SOGoUserManager.h>
|
#import <SOGo/SOGoUserManager.h>
|
||||||
|
@ -42,6 +45,8 @@
|
||||||
#import "SOGoAppointmentFolder.h"
|
#import "SOGoAppointmentFolder.h"
|
||||||
#import "SOGoAppointmentFolders.h"
|
#import "SOGoAppointmentFolders.h"
|
||||||
|
|
||||||
|
#import "MSExchangeFreeBusy.h"
|
||||||
|
|
||||||
#import "SOGoFreeBusyObject.h"
|
#import "SOGoFreeBusyObject.h"
|
||||||
|
|
||||||
@interface SOGoFreeBusyObject (PrivateAPI)
|
@interface SOGoFreeBusyObject (PrivateAPI)
|
||||||
|
@ -240,6 +245,60 @@
|
||||||
to: _endDate];
|
to: _endDate];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch freebusy information for a user that exists in a contact source
|
||||||
|
* (not an authentication source) for which freebusy information is available
|
||||||
|
* (currently limited to a Microsoft Exchange server with Web Services enabled).
|
||||||
|
* @param startDate the beginning of the covered period
|
||||||
|
* @param endDate the ending of the covered period
|
||||||
|
* @param uid the ID of the user within the current domain
|
||||||
|
* @return an array of dictionaries containing the start and end dates of each busy period
|
||||||
|
* @see MSExchangeFreeBusy.m
|
||||||
|
*/
|
||||||
|
- (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) startDate
|
||||||
|
to: (NSCalendarDate *) endDate
|
||||||
|
forUser: (NSString *) uid
|
||||||
|
{
|
||||||
|
if ([uid length])
|
||||||
|
{
|
||||||
|
SOGoUserManager *um;
|
||||||
|
NSArray *users;
|
||||||
|
NSString *domain, *email;
|
||||||
|
NSDictionary *user;
|
||||||
|
MSExchangeFreeBusy *exchangeFreeBusy;
|
||||||
|
NSObject <SOGoDNSource> *source;
|
||||||
|
|
||||||
|
um = [SOGoUserManager sharedUserManager];
|
||||||
|
domain = [[context activeUser] domain];
|
||||||
|
users = [um fetchContactsMatching: uid inDomain: domain];
|
||||||
|
if ([users count] == 1)
|
||||||
|
{
|
||||||
|
user = [users lastObject];
|
||||||
|
email = [user valueForKey: @"c_email"];
|
||||||
|
source = [user objectForKey: @"source"];
|
||||||
|
if ([email length])
|
||||||
|
{
|
||||||
|
exchangeFreeBusy = [[MSExchangeFreeBusy alloc] init];
|
||||||
|
[exchangeFreeBusy autorelease];
|
||||||
|
|
||||||
|
return [exchangeFreeBusy fetchFreeBusyInfosFrom: startDate
|
||||||
|
to: endDate
|
||||||
|
forEmail: email
|
||||||
|
inSource: source
|
||||||
|
inContext: context];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return [self fetchFreeBusyInfosFrom: startDate to: endDate];
|
||||||
|
}
|
||||||
|
|
||||||
|
// No freebusy information found
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
- (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) startDate
|
- (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) startDate
|
||||||
to: (NSCalendarDate *) endDate
|
to: (NSCalendarDate *) endDate
|
||||||
{
|
{
|
||||||
|
|
|
@ -74,6 +74,8 @@
|
||||||
/* resources handling */
|
/* resources handling */
|
||||||
NSString *kindField;
|
NSString *kindField;
|
||||||
NSString *multipleBookingsField;
|
NSString *multipleBookingsField;
|
||||||
|
|
||||||
|
NSString *MSExchangeHostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setBindDN: (NSString *) newBindDN
|
- (void) setBindDN: (NSString *) newBindDN
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* LDAPSource.m - this file is part of SOGo
|
/* LDAPSource.m - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2011 Inverse inc.
|
* Copyright (C) 2007-2012 Inverse inc.
|
||||||
*
|
*
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
* Ludovic Marcotte <lmarcotte@inverse.ca>
|
* Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||||
|
@ -124,6 +124,8 @@ static NSArray *commonSearchFields;
|
||||||
@"serialnumber",
|
@"serialnumber",
|
||||||
@"calfburl",
|
@"calfburl",
|
||||||
@"proxyaddresses",
|
@"proxyaddresses",
|
||||||
|
// MS Exchange
|
||||||
|
@"msExchHomeServerName",
|
||||||
nil];
|
nil];
|
||||||
[commonSearchFields retain];
|
[commonSearchFields retain];
|
||||||
}
|
}
|
||||||
|
@ -181,6 +183,8 @@ static NSArray *commonSearchFields;
|
||||||
kindField = nil;
|
kindField = nil;
|
||||||
multipleBookingsField = nil;
|
multipleBookingsField = nil;
|
||||||
|
|
||||||
|
MSExchangeHostname = nil;
|
||||||
|
|
||||||
_dnCache = [[NSMutableDictionary alloc] init];
|
_dnCache = [[NSMutableDictionary alloc] init];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,6 +220,7 @@ static NSArray *commonSearchFields;
|
||||||
[_dnCache release];
|
[_dnCache release];
|
||||||
[kindField release];
|
[kindField release];
|
||||||
[multipleBookingsField release];
|
[multipleBookingsField release];
|
||||||
|
[MSExchangeHostname release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +254,7 @@ static NSArray *commonSearchFields;
|
||||||
IMAPLoginField: [udSource objectForKey: @"IMAPLoginFieldName"]
|
IMAPLoginField: [udSource objectForKey: @"IMAPLoginFieldName"]
|
||||||
bindFields: [udSource objectForKey: @"bindFields"]
|
bindFields: [udSource objectForKey: @"bindFields"]
|
||||||
kindField: [udSource objectForKey: @"KindFieldName"]
|
kindField: [udSource objectForKey: @"KindFieldName"]
|
||||||
andMultipleBookingsField: [udSource objectForKey: @"MultipleBookingsFieldName"]];
|
andMultipleBookingsField: [udSource objectForKey: @"MultipleBookingsFieldName"]];
|
||||||
|
|
||||||
if ([sourceDomain length])
|
if ([sourceDomain length])
|
||||||
{
|
{
|
||||||
|
@ -286,6 +291,8 @@ static NSArray *commonSearchFields;
|
||||||
|
|
||||||
if ([udSource objectForKey: @"passwordPolicy"])
|
if ([udSource objectForKey: @"passwordPolicy"])
|
||||||
passwordPolicy = [[udSource objectForKey: @"passwordPolicy"] boolValue];
|
passwordPolicy = [[udSource objectForKey: @"passwordPolicy"] boolValue];
|
||||||
|
|
||||||
|
ASSIGN(MSExchangeHostname, [udSource objectForKey: @"MSExchangeHostname"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -297,11 +304,21 @@ static NSArray *commonSearchFields;
|
||||||
ASSIGN(bindDN, theDN);
|
ASSIGN(bindDN, theDN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *) bindDN
|
||||||
|
{
|
||||||
|
return bindDN;
|
||||||
|
}
|
||||||
|
|
||||||
- (void) setBindPassword: (NSString *) thePassword
|
- (void) setBindPassword: (NSString *) thePassword
|
||||||
{
|
{
|
||||||
ASSIGN (password, thePassword);
|
ASSIGN (password, thePassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *) bindPassword
|
||||||
|
{
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL) bindAsCurrentUser
|
- (BOOL) bindAsCurrentUser
|
||||||
{
|
{
|
||||||
return _bindAsCurrentUser;
|
return _bindAsCurrentUser;
|
||||||
|
@ -888,6 +905,7 @@ andMultipleBookingsField: (NSString *) newMultipleBookingsField
|
||||||
id o;
|
id o;
|
||||||
|
|
||||||
contactEntry = [NSMutableDictionary dictionary];
|
contactEntry = [NSMutableDictionary dictionary];
|
||||||
|
[contactEntry setObject: self forKey: @"source"];
|
||||||
[contactEntry setObject: [ldapEntry dn] forKey: @"dn"];
|
[contactEntry setObject: [ldapEntry dn] forKey: @"dn"];
|
||||||
attributes = [[self _searchAttributes] objectEnumerator];
|
attributes = [[self _searchAttributes] objectEnumerator];
|
||||||
|
|
||||||
|
@ -1225,4 +1243,9 @@ andMultipleBookingsField: (NSString *) newMultipleBookingsField
|
||||||
return baseDN;
|
return baseDN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *) MSExchangeHostname
|
||||||
|
{
|
||||||
|
return MSExchangeHostname;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* SOGoSource.h - this file is part of SOGo
|
/* SOGoSource.h - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009-2010 Inverse inc.
|
* Copyright (C) 2009-2012 Inverse inc.
|
||||||
*
|
*
|
||||||
* Author: Ludovic Marcotte <lmarcotte@inverse.ca>
|
* Author: Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||||
*
|
*
|
||||||
|
@ -63,13 +63,16 @@
|
||||||
@protocol SOGoDNSource <SOGoSource>
|
@protocol SOGoDNSource <SOGoSource>
|
||||||
|
|
||||||
- (void) setBindDN: (NSString *) theDN;
|
- (void) setBindDN: (NSString *) theDN;
|
||||||
|
- (NSString *) bindDN;
|
||||||
- (void) setBindPassword: (NSString *) thePassword;
|
- (void) setBindPassword: (NSString *) thePassword;
|
||||||
|
- (NSString *) bindPassword;
|
||||||
- (BOOL) bindAsCurrentUser;
|
- (BOOL) bindAsCurrentUser;
|
||||||
|
|
||||||
- (NSString *) lookupLoginByDN: (NSString *) theDN;
|
- (NSString *) lookupLoginByDN: (NSString *) theDN;
|
||||||
- (NSString *) lookupDNByLogin: (NSString *) theLogin;
|
- (NSString *) lookupDNByLogin: (NSString *) theLogin;
|
||||||
|
|
||||||
- (NSString *) baseDN;
|
- (NSString *) baseDN;
|
||||||
|
- (NSString *) MSExchangeHostname;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
SOGoUserFolder *homeFolder;
|
SOGoUserFolder *homeFolder;
|
||||||
NSString *currentPassword;
|
NSString *currentPassword;
|
||||||
NSString *loginInDomain;
|
NSString *loginInDomain;
|
||||||
NSString *language;
|
//NSString *language;
|
||||||
NSArray *allEmails;
|
NSArray *allEmails;
|
||||||
NSMutableArray *mailAccounts;
|
NSMutableArray *mailAccounts;
|
||||||
NSString *cn;
|
NSString *cn;
|
||||||
|
|
|
@ -234,7 +234,7 @@
|
||||||
[currentPassword release];
|
[currentPassword release];
|
||||||
[cn release];
|
[cn release];
|
||||||
[loginInDomain release];
|
[loginInDomain release];
|
||||||
[language release];
|
//[language release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,15 +91,16 @@
|
||||||
return sharedUserManager;
|
return sharedUserManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) _registerSource: (NSDictionary *) udSource
|
- (BOOL) _registerSource: (NSDictionary *) udSource
|
||||||
inDomain: (NSString *) domain
|
inDomain: (NSString *) domain
|
||||||
{
|
{
|
||||||
NSString *sourceID, *value, *type;
|
NSString *sourceID, *value, *type;
|
||||||
NSMutableDictionary *metadata;
|
NSMutableDictionary *metadata;
|
||||||
NSObject <SOGoSource> *sogoSource;
|
NSObject <SOGoSource> *sogoSource;
|
||||||
BOOL isAddressBook;
|
BOOL isAddressBook, result;
|
||||||
Class c;
|
Class c;
|
||||||
|
|
||||||
|
result = NO;
|
||||||
sourceID = [udSource objectForKey: @"id"];
|
sourceID = [udSource objectForKey: @"id"];
|
||||||
if ([sourceID length] > 0)
|
if ([sourceID length] > 0)
|
||||||
{
|
{
|
||||||
|
@ -147,17 +148,20 @@
|
||||||
[metadata setObject: value forKey: @"SearchFieldNames"];
|
[metadata setObject: value forKey: @"SearchFieldNames"];
|
||||||
|
|
||||||
[_sourcesMetadata setObject: metadata forKey: sourceID];
|
[_sourcesMetadata setObject: metadata forKey: sourceID];
|
||||||
|
result = YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
[self errorWithFormat: @"attempted to register a contact/user source"
|
[self errorWithFormat: @"attempted to register a contact/user source"
|
||||||
@" without id (skipped)"];
|
@" without id (skipped)"];
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) _registerSourcesInDomain: (NSString *) domain
|
- (int) _registerSourcesInDomain: (NSString *) domain
|
||||||
{
|
{
|
||||||
NSArray *userSources;
|
NSArray *userSources;
|
||||||
unsigned int count, max;
|
unsigned int count, max, total;
|
||||||
SOGoDomainDefaults *dd;
|
SOGoDomainDefaults *dd;
|
||||||
|
|
||||||
if (domain)
|
if (domain)
|
||||||
|
@ -167,11 +171,13 @@
|
||||||
|
|
||||||
userSources = [dd userSources];
|
userSources = [dd userSources];
|
||||||
max = [userSources count];
|
max = [userSources count];
|
||||||
|
total = 0;
|
||||||
for (count = 0; count < max; count++)
|
for (count = 0; count < max; count++)
|
||||||
[self _registerSource: [userSources objectAtIndex: count]
|
if ([self _registerSource: [userSources objectAtIndex: count]
|
||||||
inDomain: domain];
|
inDomain: domain])
|
||||||
|
total++;
|
||||||
|
|
||||||
return max;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) _prepareSources
|
- (void) _prepareSources
|
||||||
|
@ -634,8 +640,7 @@
|
||||||
if ([userEntry objectForKey: @"numberOfSimultaneousBookings"])
|
if ([userEntry objectForKey: @"numberOfSimultaneousBookings"])
|
||||||
[currentUser setObject: [userEntry objectForKey: @"numberOfSimultaneousBookings"]
|
[currentUser setObject: [userEntry objectForKey: @"numberOfSimultaneousBookings"]
|
||||||
forKey: @"numberOfSimultaneousBookings"];
|
forKey: @"numberOfSimultaneousBookings"];
|
||||||
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cn)
|
if (!cn)
|
||||||
|
@ -824,8 +829,9 @@
|
||||||
{
|
{
|
||||||
returnContact = [NSMutableDictionary dictionary];
|
returnContact = [NSMutableDictionary dictionary];
|
||||||
[returnContact setObject: uid forKey: @"c_uid"];
|
[returnContact setObject: uid forKey: @"c_uid"];
|
||||||
[compactContacts setObject: returnContact forKey: uid];
|
[returnContact setObject: [userEntry objectForKey: @"source"] forKey: @"source"];
|
||||||
}
|
[compactContacts setObject: returnContact forKey: uid];
|
||||||
|
}
|
||||||
if (![[returnContact objectForKey: @"c_name"] length])
|
if (![[returnContact objectForKey: @"c_name"] length])
|
||||||
[returnContact setObject: [userEntry objectForKey: @"c_name"]
|
[returnContact setObject: [userEntry objectForKey: @"c_name"]
|
||||||
forKey: @"c_name"];
|
forKey: @"c_name"];
|
||||||
|
|
|
@ -158,6 +158,7 @@
|
||||||
- (NSString *) _freeBusyFromStartDate: (NSCalendarDate *) startDate
|
- (NSString *) _freeBusyFromStartDate: (NSCalendarDate *) startDate
|
||||||
toEndDate: (NSCalendarDate *) endDate
|
toEndDate: (NSCalendarDate *) endDate
|
||||||
forFreeBusy: (SOGoFreeBusyObject *) fb
|
forFreeBusy: (SOGoFreeBusyObject *) fb
|
||||||
|
andUser: (NSString *) user
|
||||||
{
|
{
|
||||||
NSMutableArray *freeBusy;
|
NSMutableArray *freeBusy;
|
||||||
unsigned int *freeBusyItems;
|
unsigned int *freeBusyItems;
|
||||||
|
@ -169,7 +170,7 @@
|
||||||
|
|
||||||
freeBusyItems = NSZoneCalloc (NULL, intervals, sizeof (int));
|
freeBusyItems = NSZoneCalloc (NULL, intervals, sizeof (int));
|
||||||
[self _fillFreeBusyItems: freeBusyItems count: intervals
|
[self _fillFreeBusyItems: freeBusyItems count: intervals
|
||||||
withRecords: [fb fetchFreeBusyInfosFrom: startDate to: endDate]
|
withRecords: [fb fetchFreeBusyInfosFrom: startDate to: endDate forUser: user]
|
||||||
fromStartDate: startDate toEndDate: endDate];
|
fromStartDate: startDate toEndDate: endDate];
|
||||||
|
|
||||||
freeBusy = [NSMutableArray arrayWithCapacity: intervals];
|
freeBusy = [NSMutableArray arrayWithCapacity: intervals];
|
||||||
|
@ -184,15 +185,16 @@
|
||||||
- (id <WOActionResults>) readFreeBusyAction
|
- (id <WOActionResults>) readFreeBusyAction
|
||||||
{
|
{
|
||||||
WOResponse *response;
|
WOResponse *response;
|
||||||
SOGoFreeBusyObject *co;
|
SOGoFreeBusyObject *freebusy;
|
||||||
NSCalendarDate *startDate, *endDate;
|
NSCalendarDate *startDate, *endDate;
|
||||||
NSString *queryDay;
|
NSString *queryDay, *uid;
|
||||||
NSTimeZone *uTZ;
|
NSTimeZone *uTZ;
|
||||||
SOGoUser *user;
|
SOGoUser *user;
|
||||||
|
|
||||||
user = [context activeUser];
|
user = [context activeUser];
|
||||||
uTZ = [[user userDefaults] timeZone];
|
uTZ = [[user userDefaults] timeZone];
|
||||||
|
|
||||||
|
uid = [self queryParameterForKey: @"uid"];
|
||||||
queryDay = [self queryParameterForKey: @"sday"];
|
queryDay = [self queryParameterForKey: @"sday"];
|
||||||
if ([queryDay length] == 8)
|
if ([queryDay length] == 8)
|
||||||
{
|
{
|
||||||
|
@ -211,13 +213,13 @@
|
||||||
andString: @"Start date is later than end date."];
|
andString: @"Start date is later than end date."];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
co = [self clientObject];
|
freebusy = [self clientObject];
|
||||||
response
|
response
|
||||||
= [self responseWithStatus: 200
|
= [self responseWithStatus: 200
|
||||||
andString: [self
|
andString: [self _freeBusyFromStartDate: startDate
|
||||||
_freeBusyFromStartDate: startDate
|
toEndDate: endDate
|
||||||
toEndDate: endDate
|
forFreeBusy: freebusy
|
||||||
forFreeBusy: co]];
|
andUser: uid]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -219,7 +219,7 @@ function performSearchCallback(http) {
|
||||||
list.appendChild(node);
|
list.appendChild(node);
|
||||||
node.address = completeEmail;
|
node.address = completeEmail;
|
||||||
// log("node.address: " + node.address);
|
// log("node.address: " + node.address);
|
||||||
node.uid = contact["c_uid"];
|
node.uid = (contact["isMSExchange"]? UserLogin + ":" : "") + contact["c_uid"];
|
||||||
node.isList = isList;
|
node.isList = isList;
|
||||||
if (isList) {
|
if (isList) {
|
||||||
node.cname = contact["c_name"];
|
node.cname = contact["c_name"];
|
||||||
|
@ -272,7 +272,7 @@ function performSearchCallback(http) {
|
||||||
if (data.contacts.length == 1) {
|
if (data.contacts.length == 1) {
|
||||||
// Single result
|
// Single result
|
||||||
var contact = data.contacts[0];
|
var contact = data.contacts[0];
|
||||||
input.uid = contact["c_uid"];
|
input.uid = (contact["isMSExchange"]? UserLogin + ":" : "") + contact["c_uid"];
|
||||||
var isList = (contact["c_component"] &&
|
var isList = (contact["c_component"] &&
|
||||||
contact["c_component"] == "vlist");
|
contact["c_component"] == "vlist");
|
||||||
if (isList) {
|
if (isList) {
|
||||||
|
@ -997,11 +997,19 @@ freeBusyRequest.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
_performAjaxRequest: function fBR__performAjaxRequest(rqStart, rqEnd) {
|
_performAjaxRequest: function fBR__performAjaxRequest(rqStart, rqEnd) {
|
||||||
var urlstr = (UserFolderURL + "../" + this.mUid
|
var urlstr = UserFolderURL + "../";
|
||||||
+ "/freebusy.ifb/ajaxRead?"
|
var uids = this.mUid.split(":");
|
||||||
+ "sday=" + rqStart.getDayString()
|
if (uids.length > 1)
|
||||||
+ "&eday=" + rqEnd.getDayString());
|
urlstr += (uids[0]
|
||||||
|
+ "/freebusy.ifb/ajaxRead?"
|
||||||
|
+ "uid=" + uids[1]
|
||||||
|
+ "&");
|
||||||
|
else
|
||||||
|
urlstr += (this.mUid
|
||||||
|
+ "/freebusy.ifb/ajaxRead?");
|
||||||
|
urlstr += ("sday=" + rqStart.getDayString()
|
||||||
|
+ "&eday=" + rqEnd.getDayString());
|
||||||
|
|
||||||
var thisRequest = this;
|
var thisRequest = this;
|
||||||
var callback = function fBR__performAjaxRequest_cb(http) {
|
var callback = function fBR__performAjaxRequest_cb(http) {
|
||||||
if (http.readyState == 4) {
|
if (http.readyState == 4) {
|
||||||
|
|
Loading…
Reference in New Issue