Compare commits

..
Author SHA1 Message Date
Luc Charland 1dd4d870e0 Changed the keyname to EventsSortingState 2015-08-06 12:38:26 -04:00
1912 changed files with 35797 additions and 209512 deletions

No files matched your search

+6 -5
View File
@@ -9,7 +9,6 @@
*/*/obj/
*/obj/
.scss-lint-config.yml_
ActiveSync/ActiveSync.SOGo
Documentation/*.docbook
Documentation/*.pdf
SoObjects/SOGo/SOGo.framework/
@@ -21,10 +20,12 @@ UI/WebServerResources/bower_components/
UI/WebServerResources/css/
UI/WebServerResources/css/styles.css
UI/WebServerResources/css/styles.css.map
UI/WebServerResources/js/*.js
UI/WebServerResources/js/*.js.map
UI/WebServerResources/js/vendor/*.js
UI/WebServerResources/js/vendor/*.js.map
UI/WebServerResources/js/Common.js*
UI/WebServerResources/js/Contacts.js*
UI/WebServerResources/js/Mailer.js*
UI/WebServerResources/js/Preferences.js*
UI/WebServerResources/js/Scheduler.js*
UI/WebServerResources/js/vendor/
UI/WebServerResources/node_modules/
UI/WebServerResources/scss/.sass-cache/
config.make
-66
View File
@@ -15,24 +15,18 @@ trans.es_ES = UI/MailerUI/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/MailerUI/Basque.lproj/Localizable.strings
trans.fi = UI/MailerUI/Finnish.lproj/Localizable.strings
trans.fr = UI/MailerUI/French.lproj/Localizable.strings
trans.hr_HR = UI/MailerUI/Croatian.lproj/Localizable.strings
trans.hu = UI/MailerUI/Hungarian.lproj/Localizable.strings
trans.is = UI/MailerUI/Icelandic.lproj/Localizable.strings
trans.it = UI/MailerUI/Italian.lproj/Localizable.strings
trans.lt = UI/MailerUI/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/MailerUI/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/MailerUI/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/MailerUI/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/MailerUI/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/MailerUI/Polish.lproj/Localizable.strings
trans.pt = UI/MailerUI/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/MailerUI/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/MailerUI/Russian.lproj/Localizable.strings
trans.sk = UI/MailerUI/Slovak.lproj/Localizable.strings
trans.sl_SI = UI/MailerUI/Slovenian.lproj/Localizable.strings
trans.sr = UI/MailerUI/Serbian.lproj/Localizable.strings
trans.sv = UI/MailerUI/Swedish.lproj/Localizable.strings
trans.tr_TR = UI/MailerUI/TurkishTurkey.lproj/Localizable.strings
trans.uk = UI/MailerUI/Ukrainian.lproj/Localizable.strings
trans.zh_TW = UI/MailerUI/ChineseTaiwan.lproj/Localizable.strings
@@ -50,24 +44,18 @@ trans.es_ES = UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/PreferencesUI/Basque.lproj/Localizable.strings
trans.fi = UI/PreferencesUI/Finnish.lproj/Localizable.strings
trans.fr = UI/PreferencesUI/French.lproj/Localizable.strings
trans.hr_HR = UI/PreferencesUI/Croatian.lproj/Localizable.strings
trans.hu = UI/PreferencesUI/Hungarian.lproj/Localizable.strings
trans.is = UI/PreferencesUI/Icelandic.lproj/Localizable.strings
trans.it = UI/PreferencesUI/Italian.lproj/Localizable.strings
trans.lt = UI/PreferencesUI/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/PreferencesUI/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/PreferencesUI/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/PreferencesUI/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/PreferencesUI/Polish.lproj/Localizable.strings
trans.pt = UI/PreferencesUI/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/PreferencesUI/Russian.lproj/Localizable.strings
trans.sk = UI/PreferencesUI/Slovak.lproj/Localizable.strings
trans.sl_SI = UI/PreferencesUI/Slovenian.lproj/Localizable.strings
trans.sr = UI/PreferencesUI/Serbian.lproj/Localizable.strings
trans.sv = UI/PreferencesUI/Swedish.lproj/Localizable.strings
trans.tr_TR = UI/PreferencesUI/TurkishTurkey.lproj/Localizable.strings
trans.uk = UI/PreferencesUI/Ukrainian.lproj/Localizable.strings
trans.zh_TW = UI/PreferencesUI/ChineseTaiwan.lproj/Localizable.strings
@@ -85,24 +73,18 @@ trans.es_ES = UI/Scheduler/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/Scheduler/Basque.lproj/Localizable.strings
trans.fi = UI/Scheduler/Finnish.lproj/Localizable.strings
trans.fr = UI/Scheduler/French.lproj/Localizable.strings
trans.hr_HR = UI/Scheduler/Croatian.lproj/Localizable.strings
trans.hu = UI/Scheduler/Hungarian.lproj/Localizable.strings
trans.is = UI/Scheduler/Icelandic.lproj/Localizable.strings
trans.it = UI/Scheduler/Italian.lproj/Localizable.strings
trans.lt = UI/Scheduler/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/Scheduler/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/Scheduler/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/Scheduler/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/Scheduler/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/Scheduler/Polish.lproj/Localizable.strings
trans.pt = UI/Scheduler/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/Scheduler/Russian.lproj/Localizable.strings
trans.sk = UI/Scheduler/Slovak.lproj/Localizable.strings
trans.sl_SI = UI/Scheduler/Slovenian.lproj/Localizable.strings
trans.sr = UI/Scheduler/Serbian.lproj/Localizable.strings
trans.sv = UI/Scheduler/Swedish.lproj/Localizable.strings
trans.tr_TR = UI/Scheduler/TurkishTurkey.lproj/Localizable.strings
trans.uk = UI/Scheduler/Ukrainian.lproj/Localizable.strings
trans.zh_TW = UI/Scheduler/ChineseTaiwan.lproj/Localizable.strings
@@ -120,24 +102,18 @@ trans.es_ES = UI/Contacts/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/Contacts/Basque.lproj/Localizable.strings
trans.fi = UI/Contacts/Finnish.lproj/Localizable.strings
trans.fr = UI/Contacts/French.lproj/Localizable.strings
trans.hr_HR = UI/Contacts/Croatian.lproj/Localizable.strings
trans.hu = UI/Contacts/Hungarian.lproj/Localizable.strings
trans.is = UI/Contacts/Icelandic.lproj/Localizable.strings
trans.it = UI/Contacts/Italian.lproj/Localizable.strings
trans.lt = UI/Contacts/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/Contacts/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/Contacts/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/Contacts/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/Contacts/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/Contacts/Polish.lproj/Localizable.strings
trans.pt = UI/Contacts/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/Contacts/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/Contacts/Russian.lproj/Localizable.strings
trans.sk = UI/Contacts/Slovak.lproj/Localizable.strings
trans.sl_SI = UI/Contacts/Slovenian.lproj/Localizable.strings
trans.sr = UI/Contacts/Serbian.lproj/Localizable.strings
trans.sv = UI/Contacts/Swedish.lproj/Localizable.strings
trans.tr_TR = UI/Contacts/TurkishTurkey.lproj/Localizable.strings
trans.uk = UI/Contacts/Ukrainian.lproj/Localizable.strings
trans.zh_TW = UI/Contacts/ChineseTaiwan.lproj/Localizable.strings
@@ -155,24 +131,18 @@ trans.es_ES = UI/MainUI/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/MainUI/Basque.lproj/Localizable.strings
trans.fi = UI/MainUI/Finnish.lproj/Localizable.strings
trans.fr = UI/MainUI/French.lproj/Localizable.strings
trans.hr_HR = UI/MainUI/Croatian.lproj/Localizable.strings
trans.hu = UI/MainUI/Hungarian.lproj/Localizable.strings
trans.is = UI/MainUI/Icelandic.lproj/Localizable.strings
trans.it = UI/MainUI/Italian.lproj/Localizable.strings
trans.lt = UI/MainUI/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/MainUI/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/MainUI/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/MainUI/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/MainUI/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/MainUI/Polish.lproj/Localizable.strings
trans.pt = UI/MainUI/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/MainUI/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/MainUI/Russian.lproj/Localizable.strings
trans.sk = UI/MainUI/Slovak.lproj/Localizable.strings
trans.sl_SI = UI/MainUI/Slovenian.lproj/Localizable.strings
trans.sr = UI/MainUI/Serbian.lproj/Localizable.strings
trans.sv = UI/MainUI/Swedish.lproj/Localizable.strings
trans.tr_TR = UI/MainUI/TurkishTurkey.lproj/Localizable.strings
trans.uk = UI/MainUI/Ukrainian.lproj/Localizable.strings
trans.zh_TW = UI/MainUI/ChineseTaiwan.lproj/Localizable.strings
@@ -190,24 +160,18 @@ trans.es_ES = UI/Common/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/Common/Basque.lproj/Localizable.strings
trans.fi = UI/Common/Finnish.lproj/Localizable.strings
trans.fr = UI/Common/French.lproj/Localizable.strings
trans.hr_HR = UI/Common/Croatian.lproj/Localizable.strings
trans.hu = UI/Common/Hungarian.lproj/Localizable.strings
trans.is = UI/Common/Icelandic.lproj/Localizable.strings
trans.it = UI/Common/Italian.lproj/Localizable.strings
trans.lt = UI/Common/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/Common/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/Common/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/Common/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/Common/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/Common/Polish.lproj/Localizable.strings
trans.pt = UI/Common/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/Common/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/Common/Russian.lproj/Localizable.strings
trans.sk = UI/Common/Slovak.lproj/Localizable.strings
trans.sl_SI = UI/Common/Slovenian.lproj/Localizable.strings
trans.sr = UI/Common/Serbian.lproj/Localizable.strings
trans.sv = UI/Common/Swedish.lproj/Localizable.strings
trans.tr_TR = UI/Common/TurkishTurkey.lproj/Localizable.strings
trans.uk = UI/Common/Ukrainian.lproj/Localizable.strings
trans.zh_TW = UI/Common/ChineseTaiwan.lproj/Localizable.strings
@@ -225,24 +189,18 @@ trans.es_ES = UI/AdministrationUI/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/AdministrationUI/Basque.lproj/Localizable.strings
trans.fi = UI/AdministrationUI/Finnish.lproj/Localizable.strings
trans.fr = UI/AdministrationUI/French.lproj/Localizable.strings
trans.hr_HR = UI/AdministrationUI/Croatian.lproj/Localizable.strings
trans.hu = UI/AdministrationUI/Hungarian.lproj/Localizable.strings
trans.is = UI/AdministrationUI/Icelandic.lproj/Localizable.strings
trans.it = UI/AdministrationUI/Italian.lproj/Localizable.strings
trans.lt = UI/AdministrationUI/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/AdministrationUI/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/AdministrationUI/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/AdministrationUI/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/AdministrationUI/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/AdministrationUI/Polish.lproj/Localizable.strings
trans.pt = UI/AdministrationUI/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/AdministrationUI/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/AdministrationUI/Russian.lproj/Localizable.strings
trans.sk = UI/AdministrationUI/Slovak.lproj/Localizable.strings
trans.sl_SI = UI/AdministrationUI/Slovenian.lproj/Localizable.strings
trans.sr = UI/AdministrationUI/Serbian.lproj/Localizable.strings
trans.sv = UI/AdministrationUI/Swedish.lproj/Localizable.strings
trans.tr_TR = UI/AdministrationUI/TurkishTurkey.lproj/Localizable.strings
trans.uk = UI/AdministrationUI/Ukrainian.lproj/Localizable.strings
trans.zh_TW = UI/AdministrationUI/ChineseTaiwan.lproj/Localizable.strings
@@ -260,24 +218,18 @@ trans.es_ES = SoObjects/Appointments/SpanishSpain.lproj/Localizable.strings
trans.eu = SoObjects/Appointments/Basque.lproj/Localizable.strings
trans.fi = SoObjects/Appointments/Finnish.lproj/Localizable.strings
trans.fr = SoObjects/Appointments/French.lproj/Localizable.strings
trans.hr_HR = SoObjects/Appointments/Croatian.lproj/Localizable.strings
trans.hu = SoObjects/Appointments/Hungarian.lproj/Localizable.strings
trans.is = SoObjects/Appointments/Icelandic.lproj/Localizable.strings
trans.it = SoObjects/Appointments/Italian.lproj/Localizable.strings
trans.lt = SoObjects/Appointments/Lithuanian.lproj/Localizable.strings
trans.mk_MK = SoObjects/Appointments/Macedonian.lproj/Localizable.strings
trans.nb_NO = SoObjects/Appointments/NorwegianBokmal.lproj/Localizable.strings
trans.nl = SoObjects/Appointments/Dutch.lproj/Localizable.strings
trans.nn_NO = SoObjects/Appointments/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = SoObjects/Appointments/Polish.lproj/Localizable.strings
trans.pt = SoObjects/Appointments/Portuguese.lproj/Localizable.strings
trans.pt_BR = SoObjects/Appointments/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = SoObjects/Appointments/Russian.lproj/Localizable.strings
trans.sk = SoObjects/Appointments/Slovak.lproj/Localizable.strings
trans.sl_SI = SoObjects/Appointments/Slovenian.lproj/Localizable.strings
trans.sr = SoObjects/Appointments/Serbian.lproj/Localizable.strings
trans.sv = SoObjects/Appointments/Swedish.lproj/Localizable.strings
trans.tr_TR = SoObjects/Appointments/TurkishTurkey.lproj/Localizable.strings
trans.uk = SoObjects/Appointments/Ukrainian.lproj/Localizable.strings
trans.zh_TW = SoObjects/Appointments/ChineseTaiwan.lproj/Localizable.strings
@@ -295,24 +247,18 @@ trans.es_ES = SoObjects/Contacts/SpanishSpain.lproj/Localizable.strings
trans.eu = SoObjects/Contacts/Basque.lproj/Localizable.strings
trans.fi = SoObjects/Contacts/Finnish.lproj/Localizable.strings
trans.fr = SoObjects/Contacts/French.lproj/Localizable.strings
trans.hr_HR = SoObjects/Contacts/Croatian.lproj/Localizable.strings
trans.hu = SoObjects/Contacts/Hungarian.lproj/Localizable.strings
trans.is = SoObjects/Contacts/Icelandic.lproj/Localizable.strings
trans.it = SoObjects/Contacts/Italian.lproj/Localizable.strings
trans.lt = SoObjects/Contacts/Lithuanian.lproj/Localizable.strings
trans.mk_MK = SoObjects/Contacts/Macedonian.lproj/Localizable.strings
trans.nb_NO = SoObjects/Contacts/NorwegianBokmal.lproj/Localizable.strings
trans.nl = SoObjects/Contacts/Dutch.lproj/Localizable.strings
trans.nn_NO = SoObjects/Contacts/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = SoObjects/Contacts/Polish.lproj/Localizable.strings
trans.pt = SoObjects/Contacts/Portuguese.lproj/Localizable.strings
trans.pt_BR = SoObjects/Contacts/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = SoObjects/Contacts/Russian.lproj/Localizable.strings
trans.sk = SoObjects/Contacts/Slovak.lproj/Localizable.strings
trans.sl_SI = SoObjects/Contacts/Slovenian.lproj/Localizable.strings
trans.sr = SoObjects/Contacts/Serbian.lproj/Localizable.strings
trans.sv = SoObjects/Contacts/Swedish.lproj/Localizable.strings
trans.tr_TR = SoObjects/Contacts/TurkishTurkey.lproj/Localizable.strings
trans.uk = SoObjects/Contacts/Ukrainian.lproj/Localizable.strings
trans.zh_TW = SoObjects/Contacts/ChineseTaiwan.lproj/Localizable.strings
@@ -330,24 +276,18 @@ trans.es_ES = SoObjects/Mailer/SpanishSpain.lproj/Localizable.strings
trans.eu = SoObjects/Mailer/Basque.lproj/Localizable.strings
trans.fi = SoObjects/Mailer/Finnish.lproj/Localizable.strings
trans.fr = SoObjects/Mailer/French.lproj/Localizable.strings
trans.hr_HR = SoObjects/Mailer/Croatian.lproj/Localizable.strings
trans.hu = SoObjects/Mailer/Hungarian.lproj/Localizable.strings
trans.is = SoObjects/Mailer/Icelandic.lproj/Localizable.strings
trans.it = SoObjects/Mailer/Italian.lproj/Localizable.strings
trans.lt = SoObjects/Mailer/Lithuanian.lproj/Localizable.strings
trans.mk_MK = SoObjects/Mailer/Macedonian.lproj/Localizable.strings
trans.nb_NO = SoObjects/Mailer/NorwegianBokmal.lproj/Localizable.strings
trans.nl = SoObjects/Mailer/Dutch.lproj/Localizable.strings
trans.nn_NO = SoObjects/Mailer/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = SoObjects/Mailer/Polish.lproj/Localizable.strings
trans.pt = SoObjects/Mailer/Portuguese.lproj/Localizable.strings
trans.pt_BR = SoObjects/Mailer/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = SoObjects/Mailer/Russian.lproj/Localizable.strings
trans.sk = SoObjects/Mailer/Slovak.lproj/Localizable.strings
trans.sl_SI = SoObjects/Mailer/Slovenian.lproj/Localizable.strings
trans.sr = SoObjects/Mailer/Serbian.lproj/Localizable.strings
trans.sv = SoObjects/Mailer/Swedish.lproj/Localizable.strings
trans.tr_TR = SoObjects/Mailer/TurkishTurkey.lproj/Localizable.strings
trans.uk = SoObjects/Mailer/Ukrainian.lproj/Localizable.strings
trans.zh_TW = SoObjects/Mailer/ChineseTaiwan.lproj/Localizable.strings
@@ -365,23 +305,17 @@ trans.es_ES = UI/MailPartViewers/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/MailPartViewers/Basque.lproj/Localizable.strings
trans.fi = UI/MailPartViewers/Finnish.lproj/Localizable.strings
trans.fr = UI/MailPartViewers/French.lproj/Localizable.strings
trans.hr_HR = UI/MailPartViewers/Croatian.lproj/Localizable.strings
trans.hu = UI/MailPartViewers/Hungarian.lproj/Localizable.strings
trans.is = UI/MailPartViewers/Icelandic.lproj/Localizable.strings
trans.it = UI/MailPartViewers/Italian.lproj/Localizable.strings
trans.lt = UI/MailPartViewers/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/MailPartViewers/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/MailPartViewers/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/MailPartViewers/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/MailPartViewers/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/MailPartViewers/Polish.lproj/Localizable.strings
trans.pt = UI/MailPartViewers/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/MailPartViewers/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/MailPartViewers/Russian.lproj/Localizable.strings
trans.sk = UI/MailPartViewers/Slovak.lproj/Localizable.strings
trans.sl_SI = UI/MailPartViewers/Slovenian.lproj/Localizable.strings
trans.sr = UI/MailPartViewers/Serbian.lproj/Localizable.strings
trans.sv = UI/MailPartViewers/Swedish.lproj/Localizable.strings
trans.tr_TR = UI/MailPartViewers/TurkishTurkey.lproj/Localizable.strings
trans.uk = UI/MailPartViewers/Ukrainian.lproj/Localizable.strings
trans.zh_TW = UI/MailPartViewers/ChineseTaiwan.lproj/Localizable.strings
+1 -4
View File
@@ -1,4 +1 @@
ifeq ($(HAS_LIBRARY_ssl),yes)
ADDITIONAL_CPPFLAGS += -DHAVE_OPENSSL=1
BUNDLE_LIBS += -lcrypto
endif
# compilation settings
+1
View File
@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define __NGDOMELEMENTACTIVESYNC_H__
#import <DOM/DOMElement.h>
#import <DOM/DOMProtocols.h>
@class NSDictionary;
+1 -1
View File
@@ -101,7 +101,7 @@ static NSArray *asElementArray = nil;
int i, count;
if (!asElementArray)
asElementArray = [[NSArray alloc] initWithObjects: @"Attendee", @"Category", @"Exception", nil];
asElementArray = [[NSArray alloc] initWithObjects: @"Attendee", @"Category", nil];
data = [NSMutableDictionary dictionary];
+2
View File
@@ -30,6 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import "NGMimeMessage+ActiveSync.h"
#import <Foundation/NSArray.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSString.h>
#import <NGMail/NGMailAddress.h>
#import <NGMail/NGMailAddressParser.h>
+56 -195
View File
@@ -29,12 +29,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "NGVCard+ActiveSync.h"
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSTimeZone.h>
#import <NGExtensions/NSString+misc.h>
#import <NGCards/CardElement.h>
#import <Contacts/NGVCard+SOGo.h>
#import <SOGo/NSString+Utilities.h>
@@ -42,49 +46,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "NSDate+ActiveSync.h"
#include "NSString+ActiveSync.h"
#import <NGObjWeb/WOContext+SoObjects.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserDefaults.h>
@implementation NGVCard (ActiveSync)
//
// This function is called for each elements which can be ghosted according to specs.
// https://msdn.microsoft.com/en-us/library/gg650908%28v=exchg.80%29.aspx
//
- (BOOL) _isGhosted: (NSString *) element
inContext: (WOContext *) context
{
NSArray *supportedElements;
supportedElements = [context objectForKey: @"SupportedElements"];
// If the client does not include a Supported element in the initial Sync command request for
// a folder, then all of the elements that can be ghosted are considered not ghosted.
if (!supportedElements)
return NO;
// If the client includes an empty Supported element in the initial Sync command request for
// a folder, then all elements that can be ghosted are considered ghosted.
if (![supportedElements count])
return YES;
// If the client includes a Supported element that contains child elements in the initial
// Sync command request for a folder, then each child element of that Supported element is
// considered not ghosted. All elements that can be ghosted that are not included as child
// elements of the Supported element are considered ghosted.
if (!([supportedElements indexOfObject: element] == NSNotFound))
return YES;
return NO;
}
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
{
NSArray *emails, *addresses, *categories, *elements;
CardElement *n, *homeAdr, *workAdr;
NSMutableString *s, *a;
NSMutableString *s;
NSString *url;
id o;
@@ -95,7 +63,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if ((o = [n flattenedValueAtIndex: 0 forKey: @""]))
[s appendFormat: @"<LastName xmlns=\"Contacts:\">%@</LastName>", [o activeSyncRepresentationInContext: context]];
if ((o = [n flattenedValueAtIndex: 1 forKey: @""]))
[s appendFormat: @"<FirstName xmlns=\"Contacts:\">%@</FirstName>", [o activeSyncRepresentationInContext: context]];
@@ -138,7 +106,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendFormat: @"<JobTitle xmlns=\"Contacts:\">%@</JobTitle>", [o activeSyncRepresentationInContext: context]];
if ((o = [self preferredEMail]))
[s appendFormat: @"<Email1Address xmlns=\"Contacts:\">%@</Email1Address>", [o activeSyncRepresentationInContext: context]];
[s appendFormat: @"<Email1Address xmlns=\"Contacts:\">%@</Email1Address>", o];
// Secondary email addresses (2 and 3)
@@ -148,7 +116,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
o = [[emails objectAtIndex: i] flattenedValuesForKey: @""];
[s appendFormat: @"<Email%dAddress xmlns=\"Contacts:\">%@</Email%dAddress>", i+2, [o activeSyncRepresentationInContext: context], i+2];
[s appendFormat: @"<Email%dAddress xmlns=\"Contacts:\">%@</Email%dAddress>", i+2, o, i+2];
if (i == 1)
break;
@@ -178,22 +146,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if ([addresses count])
{
homeAdr = [addresses objectAtIndex: 0];
a = [NSMutableString string];
if ((o = [homeAdr flattenedValueAtIndex: 2 forKey: @""]))
[a appendString: [o activeSyncRepresentationInContext: context]];
if ((o = [homeAdr flattenedValueAtIndex: 1 forKey: @""]) && [o length])
[a appendFormat: @"\n%@", [o activeSyncRepresentationInContext: context]];
[s appendFormat: @"<HomeStreet xmlns=\"Contacts:\">%@</HomeStreet>", [o activeSyncRepresentationInContext: context]];
[s appendFormat: @"<HomeStreet xmlns=\"Contacts:\">%@</HomeStreet>", [a activeSyncRepresentationInContext: context]];
if ((o = [homeAdr flattenedValueAtIndex: 3 forKey: @""]))
[s appendFormat: @"<HomeCity xmlns=\"Contacts:\">%@</HomeCity>", [o activeSyncRepresentationInContext: context]];
if ((o = [homeAdr flattenedValueAtIndex: 4 forKey: @""]))
[s appendFormat: @"<HomeState xmlns=\"Contacts:\">%@</HomeState>", [o activeSyncRepresentationInContext: context]];
if ((o = [homeAdr flattenedValueAtIndex: 5 forKey: @""]))
[s appendFormat: @"<HomePostalCode xmlns=\"Contacts:\">%@</HomePostalCode>", [o activeSyncRepresentationInContext: context]];
@@ -209,15 +171,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if ([addresses count])
{
workAdr = [addresses objectAtIndex: 0];
a = [NSMutableString string];
if ((o = [workAdr flattenedValueAtIndex: 2 forKey: @""]))
[a appendString: [o activeSyncRepresentationInContext: context]];
if ((o = [workAdr flattenedValueAtIndex: 1 forKey: @""]) && [o length])
[a appendFormat: @"\n%@", [o activeSyncRepresentationInContext: context]];
[s appendFormat: @"<BusinessStreet xmlns=\"Contacts:\">%@</BusinessStreet>", [a activeSyncRepresentationInContext: context]];
[s appendFormat: @"<BusinessStreet xmlns=\"Contacts:\">%@</BusinessStreet>", [o activeSyncRepresentationInContext: context]];
if ((o = [workAdr flattenedValueAtIndex: 3 forKey: @""]))
[s appendFormat: @"<BusinessCity xmlns=\"Contacts:\">%@</BusinessCity>", [o activeSyncRepresentationInContext: context]];
@@ -234,13 +190,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Other, less important fields
if ((o = [self birthday]))
{
[s appendFormat: @"<Birthday xmlns=\"Contacts:\">%@</Birthday>",
[[o dateByAddingYears: 0 months: 0 days: 0
hours: -12 minutes: 0
seconds: 0]
activeSyncRepresentationInContext: context]];
}
[s appendFormat: @"<Birthday xmlns=\"Contacts:\">%@</Birthday>", [o activeSyncRepresentationInContext: context]];
if ((o = [self note]))
{
@@ -267,7 +217,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
inContext: (WOContext *) context
{
CardElement *element;
NSMutableArray *addressLines;
id o;
// Contact's note
@@ -277,8 +226,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Categories
if ((o = [theValues objectForKey: @"Categories"]) && [o length])
[self setCategories: o];
else
[[self children] removeObjectsInArray: [self childrenWithTag: @"Categories"]];
// Birthday
if ((o = [theValues objectForKey: @"Birthday"]))
@@ -286,11 +233,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
o = [o calendarDate];
[self setBday: [o descriptionWithCalendarFormat: @"%Y-%m-%d" timeZone: nil locale: nil]];
}
else if (![self _isGhosted: @"Birthday" inContext: context])
{
[self setBday: @""];
}
//
// Business address information
@@ -302,48 +244,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// BusinessCountry
//
element = [self elementWithTag: @"adr" ofType: @"work"];
if ((o = [theValues objectForKey: @"BusinessStreet"]) || ![self _isGhosted: @"BusinessStreet" inContext: context])
{
addressLines = [NSMutableArray arrayWithArray: [o componentsSeparatedByString: @"\n"]];
[element setSingleValue: @""
atIndex: 1 forKey: @""];
[element setSingleValue: [addressLines count] ? [addressLines objectAtIndex: 0] : @""
atIndex: 2 forKey: @""];
// Extended address line. If there are more than 2 address lines we add them to the extended address line.
if ([addressLines count] > 1)
{
[addressLines removeObjectAtIndex: 0];
[element setSingleValue: [addressLines componentsJoinedByString: @" "]
atIndex: 1 forKey: @""];
}
}
if ((o = [theValues objectForKey: @"BusinessCity"]) || ![self _isGhosted: @"BusinessCity" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"BusinessCity"]
atIndex: 3 forKey: @""];
}
if ((o = [theValues objectForKey: @"BusinessState"]) || ![self _isGhosted: @"BusinessState" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"BusinessState"]
atIndex: 4 forKey: @""];
}
if ((o = [theValues objectForKey: @"BusinessPostalCode"]) || ![self _isGhosted: @"BusinessPostalCode" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"BusinessPostalCode"]
atIndex: 5 forKey: @""];
}
if ((o = [theValues objectForKey: @"BusinessCountry"]) || ![self _isGhosted: @"BusinessCountry" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"BusinessCountry"]
atIndex: 6 forKey: @""];
}
[element setSingleValue: @""
atIndex: 1 forKey: @""];
[element setSingleValue: [theValues objectForKey: @"BusinessStreet"]
atIndex: 2 forKey: @""];
[element setSingleValue: [theValues objectForKey: @"BusinessCity"]
atIndex: 3 forKey: @""];
[element setSingleValue: [theValues objectForKey: @"BusinessState"]
atIndex: 4 forKey: @""];
[element setSingleValue: [theValues objectForKey: @"BusinessPostalCode"]
atIndex: 5 forKey: @""];
[element setSingleValue: [theValues objectForKey: @"BusinessCountry"]
atIndex: 6 forKey: @""];
//
// Home address information
@@ -355,69 +267,35 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// HomeCountry
//
element = [self elementWithTag: @"adr" ofType: @"home"];
if ((o = [theValues objectForKey: @"HomeStreet"]) || ![self _isGhosted: @"HomeStreet" inContext: context])
{
addressLines = [NSMutableArray arrayWithArray: [o componentsSeparatedByString: @"\n"]];
[element setSingleValue: @""
atIndex: 1 forKey: @""];
[element setSingleValue: [addressLines count] ? [addressLines objectAtIndex: 0] : @""
atIndex: 2 forKey: @""];
// Extended address line. If there are more then 2 address lines we add them to the extended address line.
if ([addressLines count] > 1)
{
[addressLines removeObjectAtIndex: 0];
[element setSingleValue: [addressLines componentsJoinedByString: @" "]
atIndex: 1 forKey: @""];
}
}
if ((o = [theValues objectForKey: @"HomeCity"]) || ![self _isGhosted: @"HomeCity" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"HomeCity"]
atIndex: 3 forKey: @""];
}
if ((o = [theValues objectForKey: @"HomeState"]) || ![self _isGhosted: @"HomeState" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"HomeState"]
atIndex: 4 forKey: @""];
}
if ((o = [theValues objectForKey: @"HomePostalCode"]) || ![self _isGhosted: @"HomePostalCode" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"HomePostalCode"]
atIndex: 5 forKey: @""];
}
if ((o = [theValues objectForKey: @"HomeCountry"]) || ![self _isGhosted: @"HomeCountry" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"HomeCountry"]
atIndex: 6 forKey: @""];
}
[element setSingleValue: @""
atIndex: 1 forKey: @""];
[element setSingleValue: [theValues objectForKey: @"HomeStreet"]
atIndex: 2 forKey: @""];
[element setSingleValue: [theValues objectForKey: @"HomeCity"]
atIndex: 3 forKey: @""];
[element setSingleValue: [theValues objectForKey: @"HomeState"]
atIndex: 4 forKey: @""];
[element setSingleValue: [theValues objectForKey: @"HomePostalCode"]
atIndex: 5 forKey: @""];
[element setSingleValue: [theValues objectForKey: @"HomeCountry"]
atIndex: 6 forKey: @""];
// Company's name
if ((o = [theValues objectForKey: @"CompanyName"]))
[self setOrg: o units: nil];
else if (![self _isGhosted: @"CompanyName" inContext: context])
[self setOrg: @"" units: nil];
// Department
if ((o = [theValues objectForKey: @"Department"]))
[self setOrg: nil units: [NSArray arrayWithObjects:o,nil]];
else if (![self _isGhosted: @"Department" inContext: context])
[self setOrg: nil units: [NSArray arrayWithObjects:@"",nil]];
// Email addresses
if ((o = [theValues objectForKey: @"Email1Address"]) || ![self _isGhosted: @"Email1Address" inContext: context])
if ((o = [theValues objectForKey: @"Email1Address"]))
{
element = [self elementWithTag: @"email" ofType: @"work"];
[element setSingleValue: [o pureEMailAddress] forKey: @""];
}
if ((o = [theValues objectForKey: @"Email2Address"]) || ![self _isGhosted: @"Email2Address" inContext: context])
if ((o = [theValues objectForKey: @"Email2Address"]))
{
element = [self elementWithTag: @"email" ofType: @"home"];
[element setSingleValue: [o pureEMailAddress] forKey: @""];
@@ -425,7 +303,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// SOGo currently only supports 2 email addresses ... but AS clients might send 3
// FIXME: revise this when the GUI revamp is done in SOGo
if ((o = [theValues objectForKey: @"Email3Address"]) || ![self _isGhosted: @"Email3Address" inContext: context])
if ((o = [theValues objectForKey: @"Email3Address"]))
{
element = [self elementWithTag: @"email" ofType: @"three"];
[element setSingleValue: [o pureEMailAddress] forKey: @""];
@@ -435,62 +313,45 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// MiddleName
// Suffix (II)
// Title (Mr.)
if ((o = [theValues objectForKey: @"FileAs"]) || ![self _isGhosted: @"FileAs" inContext: context])
[self setFn: [theValues objectForKey: @"FileAs"]];
[self setFn: [theValues objectForKey: @"FileAs"]];
[self setNWithFamily: [theValues objectForKey: @"LastName"]
given: [theValues objectForKey: @"FirstName"]
additional: nil prefixes: nil suffixes: nil];
// IM information
if ((o = [theValues objectForKey: @"IMAddress"]) || ![self _isGhosted: @"IMAddress" inContext: context])
[[self uniqueChildWithTag: @"x-aim"]
setSingleValue: [theValues objectForKey: @"IMAddress"]
forKey: @""];
[[self uniqueChildWithTag: @"x-aim"]
setSingleValue: [theValues objectForKey: @"IMAddress"]
forKey: @""];
//
// Phone numbrrs
//
if ((o = [theValues objectForKey: @"BusinessPhoneNumber"]) || ![self _isGhosted: @"BusinessPhoneNumber" inContext: context])
{
element = [self elementWithTag: @"tel" ofType: @"work"];
[element setSingleValue: [theValues objectForKey: @"BusinessPhoneNumber"] forKey: @""];
}
element = [self elementWithTag: @"tel" ofType: @"work"];
[element setSingleValue: [theValues objectForKey: @"BusinessPhoneNumber"] forKey: @""];
if ((o = [theValues objectForKey: @"HomePhoneNumber"]) || ![self _isGhosted: @"HomePhoneNumber" inContext: context])
{
element = [self elementWithTag: @"tel" ofType: @"home"];
[element setSingleValue: [theValues objectForKey: @"HomePhoneNumber"] forKey: @""];
}
element = [self elementWithTag: @"tel" ofType: @"home"];
[element setSingleValue: [theValues objectForKey: @"HomePhoneNumber"] forKey: @""];
if ((o = [theValues objectForKey: @"MobilePhoneNumber"]) || ![self _isGhosted: @"MobilePhoneNumber" inContext: context])
{
element = [self elementWithTag: @"tel" ofType: @"cell"];
[element setSingleValue: [theValues objectForKey: @"MobilePhoneNumber"] forKey: @""];
}
element = [self elementWithTag: @"tel" ofType: @"cell"];
[element setSingleValue: [theValues objectForKey: @"MobilePhoneNumber"] forKey: @""];
if ((o = [theValues objectForKey: @"BusinessFaxNumber"]) || ![self _isGhosted: @"BusinessFaxNumber" inContext: context])
{
element = [self elementWithTag: @"tel" ofType: @"fax"];
[element setSingleValue: [theValues objectForKey: @"BusinessFaxNumber"] forKey: @""];
}
element = [self elementWithTag: @"tel" ofType: @"fax"];
[element setSingleValue: [theValues objectForKey: @"BusinessFaxNumber"] forKey: @""];
if ((o = [theValues objectForKey: @"PagerNumber"]) || ![self _isGhosted: @"PagerNumber" inContext: context])
{
element = [self elementWithTag: @"tel" ofType: @"pager"];
[element setSingleValue: [theValues objectForKey: @"PagerNumber"] forKey: @""];
}
element = [self elementWithTag: @"tel" ofType: @"pager"];
[element setSingleValue: [theValues objectForKey: @"PagerNumber"] forKey: @""];
// Job's title
if ((o = [theValues objectForKey: @"JobTitle"]) || ![self _isGhosted: @"JobTitle" inContext: context])
if ((o = [theValues objectForKey: @"JobTitle"]))
[self setTitle: o];
// WebPage (work)
if ((o = [theValues objectForKey: @"WebPage"]) || ![self _isGhosted: @"WebPage" inContext: context])
if ((o = [theValues objectForKey: @"WebPage"]))
[[self elementWithTag: @"url" ofType: @"work"]
setSingleValue: o forKey: @""];
if ((o = [theValues objectForKey: @"NickName"]) || ![self _isGhosted: @"NickName" inContext: context])
if ((o = [theValues objectForKey: @"NickName"]))
[self setNickname: o];
if ((o = [theValues objectForKey: @"Picture"]))
+1
View File
@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import "NSCalendarDate+ActiveSync.h"
#import <Foundation/NSString.h>
#import <Foundation/NSTimeZone.h>
#define ONE_DAY 86400
+3
View File
@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import "NSData+ActiveSync.h"
#import <Foundation/NSProcessInfo.h>
#import <Foundation/NSString.h>
#import <SOGo/SOGoSystemDefaults.h>
@@ -37,6 +38,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <NGExtensions/NSObject+Logs.h>
#include <wbxml/wbxml.h>
#include <wbxml/wbxml_conv.h>
#include <wbxml/wbxml_errors.h>
#define WBXMLDEBUG 0
+1 -1
View File
@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define __NSSTRINGACTIVESYNC_H__
#import <Foundation/NSString.h>
#include "SOGoActiveSyncConstants.h"
@class NSCalendarDate;
@@ -52,7 +53,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- (NSString *) itemid;
- (BOOL) acceptsMultiPart;
- (NSData *) convertHexStringToBytes;
- (NSString *) protocolVersion;
@end
+97 -22
View File
@@ -31,6 +31,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <Foundation/NSArray.h>
#include <Foundation/NSCalendarDate.h>
#include <Foundation/NSData.h>
#include <Foundation/NSDate.h>
#include <Foundation/NSTimeZone.h>
#include <SOGo/NSString+Utilities.h>
#include <SOGo/NSData+Crypto.h>
@@ -43,6 +46,99 @@ static NSArray *easCommandParameters = nil;
@implementation NSString (ActiveSync)
//
// This is a copy from NSString+XMLEscaping.m from SOPE.
// The difference here is that we use wchar_t instead of unichar.
// This is needed to get the rigth numeric character reference.
// e.g. SMILING FACE WITH OPEN MOUTH
// ok: wchar_t -> &#128515; wrong: unichar -> &#55357; &#56835;
//
// We avoir naming it like the one in SOPE since if the ActiveSync
// bundle is loaded, it'll overwrite the one provided by SOPE.
//
- (NSString *) _stringByEscapingXMLStringUsingCharacters {
register unsigned i, len, j;
register wchar_t *buf;
const wchar_t *chars;
unsigned escapeCount;
if ([self length] == 0) return @"";
NSData *data = [self dataUsingEncoding:NSUTF32StringEncoding];
chars = [data bytes];
len = [data length]/4;
/* check for characters to escape ... */
for (i = 0, escapeCount = 0; i < len; i++) {
switch (chars[i]) {
case '&': case '"': case '<': case '>': case '\r':
escapeCount++;
break;
default:
if (chars[i] > 127)
escapeCount++;
break;
}
}
if (escapeCount == 0 ) {
/* nothing to escape ... */
return [[self copy] autorelease];
}
buf = calloc((len + 5) + (escapeCount * 16), sizeof(wchar_t));
for (i = 0, j = 0; i < len; i++) {
switch (chars[i]) {
/* escape special chars */
case '\r':
buf[j] = '&'; j++; buf[j] = '#'; j++; buf[j] = '1'; j++;
buf[j] = '3'; j++; buf[j] = ';'; j++;
break;
case '&':
buf[j] = '&'; j++; buf[j] = 'a'; j++; buf[j] = 'm'; j++;
buf[j] = 'p'; j++; buf[j] = ';'; j++;
break;
case '"':
buf[j] = '&'; j++; buf[j] = 'q'; j++; buf[j] = 'u'; j++;
buf[j] = 'o'; j++; buf[j] = 't'; j++; buf[j] = ';'; j++;
break;
case '<':
buf[j] = '&'; j++; buf[j] = 'l'; j++; buf[j] = 't'; j++;
buf[j] = ';'; j++;
break;
case '>':
buf[j] = '&'; j++; buf[j] = 'g'; j++; buf[j] = 't'; j++;
buf[j] = ';'; j++;
break;
default:
/* escape big chars */
if (chars[i] > 127) {
unsigned char nbuf[32];
unsigned int k;
sprintf((char *)nbuf, "&#%i;", (int)chars[i]);
for (k = 0; nbuf[k] != '\0'; k++) {
buf[j] = nbuf[k];
j++;
}
}
else if (chars[i] == 0x9 || chars[i] == 0xA || chars[i] == 0xD || chars[i] >= 0x20) { // ignore any unsupported control character
/* nothing to escape */
buf[j] = chars[i];
j++;
}
break;
}
}
self = [[NSString alloc] initWithBytesNoCopy: buf
length: (j*sizeof(wchar_t))
encoding: NSUTF32StringEncoding
freeWhenDone: YES];
return [self autorelease];
}
- (NSString *) sanitizedServerIdWithType: (SOGoMicrosoftActiveSyncFolderType) folderType
{
if (folderType == ActiveSyncEventFolder)
@@ -62,7 +158,7 @@ static NSArray *easCommandParameters = nil;
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
{
return [self safeStringByEscapingXMLString: YES];
return [self _stringByEscapingXMLStringUsingCharacters];
}
- (int) activeSyncFolderType
@@ -135,27 +231,6 @@ static NSArray *easCommandParameters = nil;
return o;
}
- (NSString *) protocolVersion
{
NSMutableArray *components;
components = [NSMutableArray arrayWithArray: [[[self componentsSeparatedByString: @"?"] lastObject] componentsSeparatedByString: @"&"]];
// We handle BASE64 encoded queryStrings. See http://msdn.microsoft.com/en-us/library/ee160227%28v=exchg.80%29.aspx for details.
if ([components count] == 1)
{
NSData *queryString;
const char* qs_bytes;
queryString = [[components objectAtIndex: 0] dataByDecodingBase64];
qs_bytes = (const char*)[queryString bytes];
return [NSString stringWithFormat:@"%.1f", (float)((uint8_t)qs_bytes[0]/10)];
}
return nil;
}
- (NSString *) _valueForParameter: (NSString *) theParameter
{
NSMutableArray *components;
@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import "SOGoActiveSyncDispatcher.h"
#import <DOM/DOMElement.h>
#import <DOM/DOMProtocols.h>
@class WOResponse;
File diff suppressed because it is too large. Load diff
+1 -14
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2014-2015, Inverse inc.
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -27,31 +27,19 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <Foundation/NSObject.h>
#include "SOGoActiveSyncConstants.h"
@class NSCalendarDate;
@class NSException;
@class NSMutableDictionary;
@class NSURL;
@class NSNumber;
static volatile BOOL easShouldTerminate = NO;
@interface SOGoActiveSyncDispatcher : NSObject
{
NSURL *folderTableURL;
NSDictionary *imapFolderGUIDS;
id context;
NSNumber *syncRequest;
BOOL debugOn;
}
- (NSMutableDictionary *) globalMetadataForDevice;
- (id) collectionFromId: (NSString *) theCollectionId
type: (SOGoMicrosoftActiveSyncFolderType) theFolderType;
@@ -64,6 +52,5 @@ static volatile BOOL easShouldTerminate = NO;
- (NSURL *) folderTableURL;
- (void) ensureFolderTableExists;
- (BOOL) easShouldTerminate;
@end
File diff suppressed because it is too large. Load diff
+48 -265
View File
@@ -29,19 +29,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "SOGoMailObject+ActiveSync.h"
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
#import <Foundation/NSString.h>
#import <Foundation/NSCharacterSet.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalDateTime.h>
#import <NGCards/iCalEvent.h>
#import <NGCards/iCalPerson.h>
#import <NGCards/iCalTimeZone.h>
#import <NGExtensions/NGBase64Coding.h>
#import <NGExtensions/NGQuotedPrintableCoding.h>
#import <NGExtensions/NSString+misc.h>
#import <NGExtensions/NSString+Encoding.h>
#import <NGImap4/NGImap4Envelope.h>
@@ -49,7 +50,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <NGImap4/NSString+Imap4.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WOApplication.h>
#import <NGObjWeb/WORequest.h>
#import <NGMime/NGMimeBodyPart.h>
#import <NGMime/NGMimeFileData.h>
@@ -59,6 +59,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <NGMail/NGMimeMessage.h>
#import <NGMail/NGMimeMessageGenerator.h>
#import <Mailer/SOGoMailLabel.h>
#import <SOGo/SOGoUserDefaults.h>
#include "iCalTimeZone+ActiveSync.h"
@@ -68,16 +70,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <Appointments/iCalEntityObject+SOGo.h>
#include <Appointments/iCalPerson+SOGo.h>
#include <Mailer/SOGoMailBodyPart.h>
#include <Mailer/NSString+Mail.h>
#include <Mailer/SOGoMailBodyPart.h>
#include <SOGo/SOGoUser.h>
#include <SOGo/NSString+Utilities.h>
#import <Appointments/SOGoAptMailNotification.h>
unsigned char strToChar(char a, char b) {
char encoder[3] = {'\0','\0','\0'};
encoder[0] = a;
@@ -424,7 +423,7 @@ struct GlobalObjectId {
mimeType = [NGMimeType mimeType: [[thePart contentType] type]
subType: [[thePart contentType] subType]
parameters: [NSDictionary dictionaryWithObject: @"utf-8" forKey: @"charset"]];
[(NGMimeBodyPart *)thePart setHeader: mimeType forKey: @"content-type"];
[thePart setHeader: mimeType forKey: @"content-type"];
fdata = [[NGMimeFileData alloc] initWithBytes: [body bytes]
length: [body length]];
@@ -473,131 +472,18 @@ struct GlobalObjectId {
return d;
}
//
//
//
- (BOOL) _sanitinizeNeeded: (NSArray *) theParts
{
NSString *encoding, *charset;
int i;
for (i = 0; i < [theParts count]; i++)
{
encoding = [[theParts objectAtIndex: i ] objectForKey: @"encoding"];
charset = [[[theParts objectAtIndex: i ] objectForKey: @"parameterList"] objectForKey: @"charset"];
if (encoding && ([encoding caseInsensitiveCompare: @"7bit"] == NSOrderedSame || [encoding caseInsensitiveCompare: @"8bit"] == NSOrderedSame) &&
charset && ![charset caseInsensitiveCompare: @"utf-8"] == NSOrderedSame
&& ![charset caseInsensitiveCompare: @"us-ascii"] == NSOrderedSame)
{
return YES;
}
if ([self _sanitinizeNeeded: [[theParts objectAtIndex: i ] objectForKey: @"parts"]])
return YES;
}
return NO;
}
- (BOOL) _isSigned: (NSDictionary *) thePart
{
NSMutableDictionary *currentPart;
NSArray *subparts;
NSString *type, *subtype;
NSUInteger i;
type = [[thePart objectForKey: @"type"] lowercaseString];
subtype = [[thePart objectForKey: @"subtype"] lowercaseString];
if ([type isEqualToString: @"multipart"])
{
if ([subtype isEqualToString: @"signed"])
return YES;
subparts = [thePart objectForKey: @"parts"];
for (i = 0; i < [subparts count]; i++)
{
currentPart = [subparts objectAtIndex: i];
if ([self _isSigned: currentPart])
return YES;
}
}
return NO;
}
- (BOOL) _isSmimeEncrypted: (NSDictionary *) thePart
{
NSMutableDictionary *currentPart;
NSArray *subparts;
NSString *type, *subtype;
NSUInteger i;
type = [[thePart objectForKey: @"type"] lowercaseString];
subtype = [[thePart objectForKey: @"subtype"] lowercaseString];
if ([type isEqualToString: @"multipart"])
{
subparts = [thePart objectForKey: @"parts"];
for (i = 0; i < [subparts count]; i++)
{
currentPart = [subparts objectAtIndex: i];
if ([self _isSmimeEncrypted: currentPart])
return YES;
}
}
else if ([type isEqualToString: @"application"] && ([subtype isEqualToString: @"pkcs7-mime"] ||
[subtype isEqualToString: @"x-pkcs7-mime"]))
return YES;
return NO;
}
- (BOOL) _isPGP: (NSDictionary *) thePart
{
NSMutableDictionary *currentPart;
NSArray *subparts;
NSString *type, *subtype, *protocol;
NSUInteger i;
type = [[thePart objectForKey: @"type"] lowercaseString];
subtype = [[thePart objectForKey: @"subtype"] lowercaseString];
protocol = [[[thePart objectForKey: @"parameterList"] objectForKey: @"protocol"] lowercaseString];
if ([type isEqualToString: @"multipart"])
{
if (([protocol isEqualToString: @"application/pgp-signature"] || [protocol isEqualToString: @"application/pgp-encrypted"]))
return YES;
subparts = [thePart objectForKey: @"parts"];
for (i = 0; i < [subparts count]; i++)
{
currentPart = [subparts objectAtIndex: i];
if ([self _isPGP: currentPart])
return YES;
}
}
else if ([type isEqualToString: @"application"] && [subtype isEqualToString: @"pgp-encrypted"])
return YES;
return NO;
}
//
//
//
- (NSData *) _preferredBodyDataUsingType: (int) theType
mimeSupport: (int) theMimeSupport
nativeType: (int *) theNativeType
{
NSString *type, *subtype, *encoding;
NSData *d;
BOOL isSMIME, sanitinizeNeeded;
type = [[[self bodyStructure] valueForKey: @"type"] lowercaseString];
subtype = [[[self bodyStructure] valueForKey: @"subtype"] lowercaseString];
isSMIME = NO;
d = nil;
// We determine the native type
@@ -608,16 +494,8 @@ struct GlobalObjectId {
else if ([type isEqualToString: @"multipart"])
*theNativeType = 4;
if (([self _isSigned: [self bodyStructure]] ||
[self _isSmimeEncrypted: [self bodyStructure]] ||
[self _isPGP: [self bodyStructure]]) && theMimeSupport > 0)
{
*theNativeType = 4;
isSMIME = YES;
}
// We get the right part based on the preference
if ((theType == 1 || theType == 2) && !isSMIME)
if (theType == 1 || theType == 2)
{
if ([type isEqualToString: @"text"] && ![subtype isEqualToString: @"calendar"])
{
@@ -658,12 +536,12 @@ struct GlobalObjectId {
d = [self _preferredBodyDataInMultipartUsingType: theType nativeTypeFound: theNativeType];
}
}
else if (theType == 4 || isSMIME)
else if (theType == 4)
{
// We sanitize the content if the content-transfer-encoding is 8bit and charset is not utf-8 or us-ascii.
sanitinizeNeeded = [self _sanitinizeNeeded: [NSArray arrayWithObject: [self bodyStructure]]];
if (sanitinizeNeeded && !isSMIME)
// We sanitize the content *ONLY* for Outlook clients and if the content-transfer-encoding is 8bit. Outlook has strange issues
// with quoted-printable/base64 encoded text parts. It just doesn't decode them.
encoding = [[self lookupInfoForBodyPart: @""] objectForKey: @"encoding"];
if ([[context objectForKey: @"DeviceType"] isEqualToString: @"WindowsOutlook15"] || ([encoding caseInsensitiveCompare: @"8bit"] == NSOrderedSame))
d = [self _sanitizedMIMEMessage];
else
d = [self content];
@@ -694,35 +572,6 @@ struct GlobalObjectId {
}
- (NSString *) _truncateContent: (NSString *) theContent
limit: (int) theLimit
truncated: (int *) wasTruncated
{
if ([theContent length] > theLimit)
{
int i, len;
theContent = [theContent substringToIndex: theLimit];
*wasTruncated = 1;
// We search for the first "space" character starting from the
// end and we truncate the string once more. We do this to avoid
// truncating the content in the middle of a XML entity
len = theLimit-1;
for (i = len; i >= 0; i--)
{
if (isspace([theContent characterAtIndex: i]))
break;
}
return [theContent substringToIndex: i];
}
*wasTruncated = 0;
return theContent;
}
//
//
//
@@ -782,7 +631,7 @@ struct GlobalObjectId {
iCalCalendar *calendar;
NSData *calendarData;
calendarData = [bodyPart fetchBLOBWithPeek: YES];
calendarData = [bodyPart fetchBLOB];
calendar = nil;
NS_DURING
@@ -807,17 +656,16 @@ struct GlobalObjectId {
{
NSData *d, *globalObjId;
NSArray *attachmentKeys;
iCalCalendar *calendar;
NSString *p;
NSMutableString *s;
id value;
int preferredBodyType, mimeSupport, mimeTruncation, nativeBodyType;
uint32_t v;
preferredBodyType = [[context objectForKey: @"BodyPreferenceType"] intValue];
mimeSupport = [[context objectForKey: @"MIMESupport"] intValue];
mimeTruncation = [[context objectForKey: @"MIMETruncation"] intValue];
uint32_t v;
NSString *p;
id value;
iCalCalendar *calendar;
int preferredBodyType, nativeBodyType;
s = [NSMutableString string];
@@ -1003,7 +851,7 @@ struct GlobalObjectId {
[s appendFormat: @"<GlobalObjId xmlns=\"Email:\">%@</GlobalObjId>", [globalObjId activeSyncRepresentationInContext: context]];
// We set the right message type - we must set AS version to 14.1 for this
if ([[context objectForKey: @"ASProtocolVersion"] floatValue] >= 14.1)
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"14.1"])
[s appendFormat: @"<MeetingMessageType xmlns=\"Email2:\">%d</MeetingMessageType>", 1];
[s appendString: @"</MeetingRequest>"];
@@ -1014,13 +862,7 @@ struct GlobalObjectId {
else
{
// MesssageClass and ContentClass
if ([self _isSigned: [self bodyStructure]])
[s appendFormat: @"<MessageClass xmlns=\"Email:\">%@</MessageClass>", @"IPM.Note.SMIME.MultipartSigned"];
else if ([self _isSmimeEncrypted: [self bodyStructure]])
[s appendFormat: @"<MessageClass xmlns=\"Email:\">%@</MessageClass>", @"IPM.Note.SMIME"];
else
[s appendFormat: @"<MessageClass xmlns=\"Email:\">%@</MessageClass>", @"IPM.Note"];
[s appendFormat: @"<MessageClass xmlns=\"Email:\">%@</MessageClass>", @"IPM.Note"];
[s appendFormat: @"<ContentClass xmlns=\"Email:\">%@</ContentClass>", @"urn:content-classes:message"];
}
@@ -1034,8 +876,10 @@ struct GlobalObjectId {
[s appendFormat: @"<InternetCPID xmlns=\"Email:\">%@</InternetCPID>", @"65001"];
// Body - namespace 17
preferredBodyType = [[context objectForKey: @"BodyPreferenceType"] intValue];
nativeBodyType = 1;
d = [self _preferredBodyDataUsingType: preferredBodyType mimeSupport: mimeSupport nativeType: &nativeBodyType];
d = [self _preferredBodyDataUsingType: preferredBodyType nativeType: &nativeBodyType];
if (calendar && !d)
{
@@ -1124,87 +968,44 @@ struct GlobalObjectId {
AUTORELEASE(content);
content = [content activeSyncRepresentationInContext: context];
len = [content length];
truncated = 0;
// We handle MIMETruncation
switch (mimeTruncation)
{
case 0:
{
content = @"";
len = 0; truncated = 1;
}
break;
case 1:
content = [self _truncateContent: content limit: 4096 truncated: &truncated];
len = [content length];
break;
case 2:
content = [self _truncateContent: content limit: 5120 truncated: &truncated];
len = [content length];
break;
case 3:
content = [self _truncateContent: content limit: 7168 truncated: &truncated];
len = [content length];
break;
case 4:
content = [self _truncateContent: content limit: 10240 truncated: &truncated];
len = [content length];
break;
case 5:
content = [self _truncateContent: content limit: 20480 truncated: &truncated];
len = [content length];
break;
case 6:
content = [self _truncateContent: content limit: 51200 truncated: &truncated];
len = [content length];
break;
case 7:
content = [self _truncateContent: content limit: 102400 truncated: &truncated];
len = [content length];
break;
case 8:
default:
truncated = 0;
}
len = [content length];
if ([[context objectForKey: @"ASProtocolVersion"] isEqualToString: @"2.5"])
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
{
[s appendFormat: @"<Body xmlns=\"Email:\">%@</Body>", content];
[s appendFormat: @"<BodyTruncated xmlns=\"Email:\">%d</BodyTruncated>", truncated];
}
else
{
{
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
// Set the correct type if client requested text/html but we got text/plain.
// For s/mime mails type is always 4 if mimeSupport is 1 or 2.
// Set the correct type if client requested text/html but we got text/plain
if (preferredBodyType == 2 && nativeBodyType == 1)
[s appendString: @"<Type>1</Type>"];
else if (([self _isSigned: [self bodyStructure]] ||
[self _isSmimeEncrypted: [self bodyStructure]] ||
[self _isPGP: [self bodyStructure]]) && mimeSupport > 0)
[s appendString: @"<Type>4</Type>"];
else
[s appendFormat: @"<Type>%d</Type>", preferredBodyType];
[s appendFormat: @"<Truncated>%d</Truncated>", truncated];
[s appendFormat: @"<Preview></Preview>"];
[s appendFormat: @"<Data>%@</Data>", content];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", len];
if (!truncated)
{
[s appendFormat: @"<Data>%@</Data>", content];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", len];
}
[s appendString: @"</Body>"];
}
}
// Attachments -namespace 16
attachmentKeys = [self fetchFileAttachmentKeys];
if ([attachmentKeys count] && !([self _isSigned: [self bodyStructure]]))
if ([attachmentKeys count])
{
int i;
if ([[context objectForKey: @"ASProtocolVersion"] isEqualToString: @"2.5"])
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
[s appendString: @"<Attachments xmlns=\"Email:\">"];
else
[s appendString: @"<Attachments xmlns=\"AirSyncBase:\">"];
@@ -1219,24 +1020,18 @@ struct GlobalObjectId {
// FileReference must be a unique identifier across the whole store. We use the following structure:
// mail/<foldername>/<message UID/<pathofpart>
// mail/INBOX/2
if ([[context objectForKey: @"ASProtocolVersion"] isEqualToString: @"2.5"])
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
[s appendFormat: @"<AttName>mail/%@/%@/%@</AttName>", [[[self container] relativeImap4Name] stringByEscapingURL], [self nameInContainer], [value objectForKey: @"path"]];
else
[s appendFormat: @"<FileReference>mail/%@/%@/%@</FileReference>", [[[self container] relativeImap4Name] stringByEscapingURL], [self nameInContainer], [value objectForKey: @"path"]];
if ([[context objectForKey: @"ASProtocolVersion"] isEqualToString: @"2.5"])
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
{
[s appendFormat: @"<AttMethod>%d</AttMethod>", 1];
[s appendFormat: @"<AttSize>%d</AttSize>", [[value objectForKey: @"size"] intValue]];
}
else
{
if ([[value objectForKey: @"bodyId"] length])
{
[s appendFormat: @"<ContentId>%@</ContentId>", [[value objectForKey: @"bodyId"] activeSyncRepresentationInContext: context]];
[s appendFormat: @"<IsInline>%d</IsInline>", 1];
}
[s appendFormat: @"<Method>%d</Method>", 1]; // See: http://msdn.microsoft.com/en-us/library/ee160322(v=exchg.80).aspx
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [[value objectForKey: @"size"] intValue]];
//[s appendFormat: @"<IsInline>%d</IsInline>", 1];
@@ -1273,31 +1068,19 @@ struct GlobalObjectId {
[s appendFormat: @"</Categories>"];
}
if ([[context objectForKey: @"ASProtocolVersion"] floatValue] >= 14.0)
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"14.0"] ||
[[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"14.1"])
{
id value;
NSString *reference;
value = [[self mailHeaders] objectForKey: @"references"];
if ([value isKindOfClass: [NSArray class]])
reference = [[[value objectAtIndex: 0] componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] objectAtIndex: 0];
else
reference = [[value componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] objectAtIndex: 0];
reference = [[[[self mailHeaders] objectForKey: @"references"] componentsSeparatedByString: @" "] objectAtIndex: 0];
if ([reference length] > 0)
[s appendFormat: @"<ConversationId xmlns=\"Email2:\">%@</ConversationId>", [[reference dataUsingEncoding: NSUTF8StringEncoding] activeSyncRepresentationInContext: context]];
else if ([[self inReplyTo] length] > 0)
else if ([self inReplyTo])
[s appendFormat: @"<ConversationId xmlns=\"Email2:\">%@</ConversationId>", [[[self inReplyTo] dataUsingEncoding: NSUTF8StringEncoding] activeSyncRepresentationInContext: context]];
else if ([[self messageId] length] > 0)
else if ([self messageId])
[s appendFormat: @"<ConversationId xmlns=\"Email2:\">%@</ConversationId>", [[[self messageId] dataUsingEncoding: NSUTF8StringEncoding] activeSyncRepresentationInContext: context]];
if ([self replied])
[s appendFormat: @"<LastVerbExecuted xmlns=\"Email2:\">%d</LastVerbExecuted>", 1];
else if ([self forwarded])
[s appendFormat: @"<LastVerbExecuted xmlns=\"Email2:\">%d</LastVerbExecuted>", 3];
else
[s appendFormat: @"<LastVerbExecuted xmlns=\"Email2:\">%d</LastVerbExecuted>", 0];
}
// FIXME - support these in the future
-1
View File
@@ -37,7 +37,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@interface SOGoSyncCacheObject : NSObject
{
@public
id _uid;
id _sequence;
}
+13 -22
View File
@@ -32,17 +32,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <Foundation/NSNull.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
static Class NSNullK;
@implementation SOGoSyncCacheObject
+ (void) initialize
{
NSNullK = [NSNull class];
}
- (id) init
{
if ((self = [super init]))
@@ -54,14 +46,14 @@ static Class NSNullK;
return self;
}
+ (id) syncCacheObjectWithUID: (id) theUID sequence: (id) theSequence
+ (id) syncCacheObjectWithUID: (id) theUID sequence: (id) theSequence;
{
id o;
o = [[self alloc] init];
[o setUID: [NSNumber numberWithInt: [theUID intValue]]];
[o setSequence: ([theSequence isKindOfClass: NSNullK] ? theSequence : [NSNumber numberWithInt: [theSequence intValue]])];
[o setUID: theUID];
[o setSequence: theSequence];
return [o autorelease];
}
@@ -75,7 +67,7 @@ static Class NSNullK;
- (id) uid
{
return [_uid description];
return _uid;
}
- (void) setUID: (id) theUID
@@ -85,7 +77,7 @@ static Class NSNullK;
- (id) sequence
{
return ([_sequence isKindOfClass: NSNullK] ? _sequence : [_sequence description]);
return _sequence;
}
- (void) setSequence: (id) theSequence
@@ -96,7 +88,7 @@ static Class NSNullK;
- (NSComparisonResult) compareUID: (SOGoSyncCacheObject *) theSyncCacheObject
{
return [self->_uid compare: theSyncCacheObject->_uid];
return [[self uid] compare: [theSyncCacheObject uid]];
}
//
@@ -105,21 +97,21 @@ static Class NSNullK;
//
- (NSComparisonResult) compareSequence: (SOGoSyncCacheObject *) theSyncCacheObject
{
if ([self->_sequence isEqual: [NSNull null]] &&
[theSyncCacheObject->_sequence isEqual: [NSNull null]])
if ([[self sequence] isEqual: [NSNull null]] &&
[[theSyncCacheObject sequence] isEqual: [NSNull null]])
return [self compareUID: theSyncCacheObject];
if (![self->_sequence isEqual: [NSNull null]] && [theSyncCacheObject->_sequence isEqual: [NSNull null]])
if (![[self sequence] isEqual: [NSNull null]] && [[theSyncCacheObject sequence] isEqual: [NSNull null]])
return NSOrderedDescending;
if ([self->_sequence isEqual: [NSNull null]] && ![theSyncCacheObject->_sequence isEqual: [NSNull null]])
if ([[self sequence] isEqual: [NSNull null]] && ![[theSyncCacheObject sequence] isEqual: [NSNull null]])
return NSOrderedAscending;
// Must check this here, to avoid comparing NSNull objects
if ([self->_sequence compare: theSyncCacheObject->_sequence] == NSOrderedSame)
if ([[self sequence] compare: [theSyncCacheObject sequence]] == NSOrderedSame)
return [self compareUID: theSyncCacheObject];
return [self->_sequence compare: theSyncCacheObject->_sequence];
return [[self sequence] compare: [theSyncCacheObject sequence]];
}
- (NSString *) description
@@ -128,4 +120,3 @@ static Class NSNullK;
}
@end
@@ -27,11 +27,9 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <NGObjWeb/SoObjectWebDAVDispatcher.h>
#include <NGObjWeb/SoObject+SoDAV.h>
#include <NGObjWeb/WEClientCapabilities.h>
#include <NGObjWeb/WOContext.h>
#include <NGObjWeb/WORequest.h>
@@ -39,7 +37,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <Foundation/NSArray.h>
@interface SoObjectWebDAVDispatcher (ActiveSync)
- (id)_callObjectMethod:(NSString *)_method inContext:(WOContext *)_ctx;
+5 -2
View File
@@ -30,9 +30,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import "iCalAlarm+ActiveSync.h"
#import <Foundation/NSDictionary.h>
#import <NGExtensions/NSCalendarDate+misc.h>
#import <Foundation/NSString.h>
#import <NGExtensions/NSString+misc.h>
#import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGCards/iCalAlarm.h>
#import <NGCards/iCalEvent.h>
#import <NGCards/iCalTrigger.h>
@@ -55,7 +58,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// don't send negative reminder - not supported
if (delta > 0)
[s appendFormat: @"<Reminder xmlns=\"Calendar:\">%d</Reminder>", (int)delta];
[s appendFormat: @"<Reminder xmlns=\"Calendar:\">%d</Reminder>", delta];
}
return s;
+1 -3
View File
@@ -41,9 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context;
- (void) changeParticipationStatus: (NSDictionary *) theValues
inContext: (WOContext *) context
component: (id) component;
@end
#endif
+53 -376
View File
@@ -30,27 +30,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import "iCalEvent+ActiveSync.h"
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSTimeZone.h>
#import <NGExtensions/NSString+misc.h>
#import <NGExtensions/NSCalendarDate+misc.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WORequest.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalDateTime.h>
#import <NGCards/iCalPerson.h>
#import <NGCards/NSCalendarDate+NGCards.h>
#import <NGCards/NSString+NGCards.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserDefaults.h>
#import <SOGo/WORequest+SOGo.h>
#import <Appointments/iCalEntityObject+SOGo.h>
#import <Appointments/iCalRepeatableEntityObject+SOGo.h>
#import <Appointments/SOGoAppointmentObject.h>
#include "iCalAlarm+ActiveSync.h"
#include "iCalRecurrenceRule+ActiveSync.h"
@@ -63,7 +62,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- (int) _attendeeStatus: (iCalPerson *) attendee
{
int attendee_status;
attendee_status = 5;
if ([[attendee partStat] caseInsensitiveCompare: @"ACCEPTED"] == NSOrderedSame)
attendee_status = 3;
@@ -75,29 +74,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
return attendee_status;
}
//
// Possible values are:
// 0 Free
// 1 Tentative
// 2 Busy
// 3 Out of Office
// 4 Working elsewhere
//
- (int) _busyStatus: (iCalPerson *) attendee
{
int attendee_status;
attendee_status = 2;
if ([[attendee partStat] caseInsensitiveCompare: @"DECLINED"] == NSOrderedSame)
attendee_status = 0;
else if ([[attendee partStat] caseInsensitiveCompare: @"TENTATIVE"] == NSOrderedSame)
attendee_status = 1;
return attendee_status;
}
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
{
NSMutableString *s;
@@ -122,13 +98,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
else if ([self created])
[s appendFormat: @"<DTStamp xmlns=\"Calendar:\">%@</DTStamp>", [[self created] activeSyncRepresentationWithoutSeparatorsInContext: context]];
// Timezone
tz = [(iCalDateTime *)[self firstChildWithTag: @"dtstart"] timeZone];
// StartTime -- http://msdn.microsoft.com/en-us/library/ee157132(v=exchg.80).aspx
if ([self startDate])
{
if ([self isAllDay] && !tz)
if ([self isAllDay])
[s appendFormat: @"<StartTime xmlns=\"Calendar:\">%@</StartTime>",
[[[self startDate] dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
@@ -141,7 +114,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// EndTime -- http://msdn.microsoft.com/en-us/library/ee157945(v=exchg.80).aspx
if ([self endDate])
{
if ([self isAllDay] && !tz)
if ([self isAllDay])
[s appendFormat: @"<EndTime xmlns=\"Calendar:\">%@</EndTime>",
[[[self endDate] dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
@@ -151,24 +124,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendFormat: @"<EndTime xmlns=\"Calendar:\">%@</EndTime>", [[self endDate] activeSyncRepresentationWithoutSeparatorsInContext: context]];
}
// Timezone
tz = [(iCalDateTime *)[self firstChildWithTag: @"dtstart"] timeZone];
if (!tz)
tz = [iCalTimeZone timeZoneForName: [userTimeZone name]];
if (![self recurrenceId])
[s appendFormat: @"<TimeZone xmlns=\"Calendar:\">%@</TimeZone>", [tz activeSyncRepresentationInContext: context]];
[s appendFormat: @"<TimeZone xmlns=\"Calendar:\">%@</TimeZone>", [tz activeSyncRepresentationInContext: context]];
// Organizer and other invitations related properties
if ((organizer = [self organizer]))
{
meetingStatus = 1; // meeting and the user is the meeting organizer.
o = [organizer rfc822Email];
if (![self recurrenceId] && [o length])
if ([o length])
{
[s appendFormat: @"<Organizer_Email xmlns=\"Calendar:\">%@</Organizer_Email>", o];
o = [organizer cn];
if ([o length])
[s appendFormat: @"<Organizer_Name xmlns=\"Calendar:\">%@</Organizer_Name>", [o activeSyncRepresentationInContext: context]];
[s appendFormat: @"<Organizer_Name xmlns=\"Calendar:\">%@</Organizer_Name>", o];
}
}
@@ -206,7 +181,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
else
{
meetingStatus = 0; // The event is an appointment, which has no attendees.
meetingStatus = 0; // appointment
}
// This depends on the 'NEEDS-ACTION' parameter.
@@ -227,12 +202,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendFormat: @"<DisallowNewTimeProposal xmlns=\"Calendar:\">%d</DisallowNewTimeProposal>", 1];
// BusyStatus -- http://msdn.microsoft.com/en-us/library/ee202290(v=exchg.80).aspx
[s appendFormat: @"<BusyStatus xmlns=\"Calendar:\">%d</BusyStatus>", [self _busyStatus: attendee]];
}
else
{
// If it's a normal event (ie, with no organizer/attendee) or we are the organizer to an event
// invitation, we set the busy status to 2 (Busy)
[s appendFormat: @"<BusyStatus xmlns=\"Calendar:\">%d</BusyStatus>", 2];
}
@@ -257,37 +226,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//[s appendFormat: @"<Importance xmlns=\"Calendar:\">%d</Importance>", v];
// UID -- http://msdn.microsoft.com/en-us/library/ee159919(v=exchg.80).aspx
if (![self recurrenceId] && [[self uid] length])
[s appendFormat: @"<UID xmlns=\"Calendar:\">%@</UID>", [[self uid] activeSyncRepresentationInContext: context]];
// Recurrence rules
if ([self isRecurrent])
[s appendString: [[[self recurrenceRules] lastObject] activeSyncRepresentationInContext: context]];
// Comment
o = [self comment];
//if (![self recurrenceId] && [o length])
if ([o length])
{
// It is very important here to NOT set <Truncated>0</Truncated> in the response,
// otherwise it'll prevent WP8 phones from sync'ing. See #3028 for details.
o = [o activeSyncRepresentationInContext: context];
if ([[context objectForKey: @"ASProtocolVersion"] isEqualToString: @"2.5"])
{
[s appendFormat: @"<Body xmlns=\"Calendar:\">%@</Body>", o];
[s appendString: @"<BodyTruncated xmlns=\"Calendar:\">0</BodyTruncated>"];
}
else
{
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", (int)[o length]];
[s appendFormat: @"<Data>%@</Data>", o];
[s appendString: @"</Body>"];
}
}
if ([[self uid] length])
[s appendFormat: @"<UID xmlns=\"Calendar:\">%@</UID>", [self uid]];
// Sensitivity
if ([[self accessClass] isEqualToString: @"PRIVATE"])
v = 2;
@@ -310,6 +251,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendFormat: @"</Categories>"];
}
// Reminder -- http://msdn.microsoft.com/en-us/library/ee219691(v=exchg.80).aspx
// TODO: improve this to handle more alarm types
if ([self hasAlarms])
@@ -320,79 +262,36 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendString: [alarm activeSyncRepresentationInContext: context]];
}
// Exceptions
// Recurrence rules
if ([self isRecurrent])
{
NSMutableArray *components, *exdates;
iCalEvent *current_component;
NSString *recurrence_id;
unsigned int count, max, i;
components = [NSMutableArray arrayWithArray: [[self parent] events]];
max = [components count];
if (max > 1 || [self hasExceptionDates])
{
exdates = [NSMutableArray arrayWithArray: [self exceptionDates]];
[s appendString: @"<Exceptions xmlns=\"Calendar:\">"];
for (count = 1; count < max; count++)
{
current_component = [components objectAtIndex: count] ;
if ([self isAllDay])
{
recurrence_id = [NSString stringWithFormat: @"%@",
[[[current_component recurrenceId] dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: -[userTimeZone secondsFromGMTForDate:
[current_component recurrenceId]]]
activeSyncRepresentationWithoutSeparatorsInContext: context]];
}
else
{
recurrence_id = [NSString stringWithFormat: @"%@", [[current_component recurrenceId]
activeSyncRepresentationWithoutSeparatorsInContext: context]];
}
[s appendString: @"<Exception>"];
[s appendFormat: @"<Exception_StartTime xmlns=\"Calendar:\">%@</Exception_StartTime>", recurrence_id];
[s appendFormat: @"%@", [current_component activeSyncRepresentationInContext: context]];
[s appendString: @"</Exception>"];
}
for (i = 0; i < [exdates count]; i++)
{
[s appendString: @"<Exception>"];
[s appendString: @"<Exception_Deleted>1</Exception_Deleted>"];
if ([self isAllDay])
{
recurrence_id = [NSString stringWithFormat: @"%@",
[[[[exdates objectAtIndex: i] asCalendarDate] dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: -[userTimeZone secondsFromGMTForDate:
[[exdates objectAtIndex: i] asCalendarDate]]]
activeSyncRepresentationWithoutSeparatorsInContext: context]];
}
else
{
recurrence_id = [NSString stringWithFormat: @"%@", [[[exdates objectAtIndex: i] asCalendarDate]
activeSyncRepresentationWithoutSeparatorsInContext: context]];
}
[s appendFormat: @"<Exception_StartTime xmlns=\"Calendar:\">%@</Exception_StartTime>", recurrence_id];
[s appendString: @"</Exception>"];
}
[s appendString: @"</Exceptions>"];
}
[s appendString: [[[self recurrenceRules] lastObject] activeSyncRepresentationInContext: context]];
}
if (![self recurrenceId])
[s appendFormat: @"<NativeBodyType xmlns=\"AirSyncBase:\">%d</NativeBodyType>", 1];
// Comment
o = [self comment];
if ([o length])
{
// It is very important here to NOT set <Truncated>0</Truncated> in the response,
// otherwise it'll prevent WP8 phones from sync'ing. See #3028 for details.
o = [o activeSyncRepresentationInContext: context];
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
{
[s appendFormat: @"<Body xmlns=\"Calendar:\">%@</Body>", o];
[s appendString: @"<BodyTruncated xmlns=\"Calendar:\">0</BodyTruncated>"];
}
else
{
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];
[s appendFormat: @"<Data>%@</Data>", o];
[s appendString: @"</Body>"];
}
}
[s appendFormat: @"<NativeBodyType xmlns=\"AirSyncBase:\">%d</NativeBodyType>", 1];
return s;
}
@@ -438,19 +337,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context
{
iCalDateTime *start, *end; //, *oldstart;
NSCalendarDate *oldstart;
iCalDateTime *start, *end;
NSTimeZone *userTimeZone;
iCalTimeZone *tz;
id o;
int deltasecs;
BOOL isAllDay;
NSMutableArray *occurences;
occurences = [NSMutableArray arrayWithArray: [[self parent] events]];
if ((o = [theValues objectForKey: @"UID"]))
[self setUid: o];
@@ -463,11 +356,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
isAllDay = YES;
}
else if ([occurences count] && !([theValues objectForKey: @"AllDayEvent"]))
{
// If the occurence has no AllDay tag use it from master.
isAllDay = [[occurences objectAtIndex: 0] isAllDay];
}
//
// 0- free, 1- tentative, 2- busy and 3- out of office
@@ -516,7 +404,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
// FIXME: merge with iCalToDo
if ([[context objectForKey: @"ASProtocolVersion"] isEqualToString: @"2.5"])
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
{
if ((o = [theValues objectForKey: @"Body"]))
[self setComment: o];
@@ -530,18 +418,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if ((o = [theValues objectForKey: @"Location"]))
[self setLocation: o];
deltasecs = 0;
start = nil;
if ((o = [theValues objectForKey: @"StartTime"]))
{
o = [o calendarDate];
start = (iCalDateTime *) [self uniqueChildWithTag: @"dtstart"];
oldstart = [start dateTime];
[start setTimeZone: tz];
if (isAllDay)
{
if (isAllDay)
{
[start setDate: o];
[start setTimeZone: nil];
}
@@ -549,10 +433,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
[start setDateTime: o];
}
// Calculate delta if start date has been changed.
if (oldstart)
deltasecs = [[start dateTime ] timeIntervalSinceDate: oldstart] * -1;
}
if ((o = [theValues objectForKey: @"EndTime"]))
@@ -611,177 +491,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
RELEASE(rule);
[rule takeActiveSyncValues: o inContext: context];
// Exceptions
if ((o = [theValues objectForKey: @"Exceptions"]) && [o isKindOfClass: [NSArray class]])
{
NSCalendarDate *recurrenceId, *adjustedRecurrenceId, *currentId;
NSMutableArray *exdates, *exceptionstouched;
iCalEvent *currentOccurence;
NSDictionary *exception;
unsigned int i, count, max;
[self removeAllExceptionDates];
exdates = [NSMutableArray array];
exceptionstouched = [NSMutableArray array];
for (i = 0; i < [o count]; i++)
{
exception = [o objectAtIndex: i];
if (![[exception objectForKey: @"Exception_Deleted"] intValue])
{
recurrenceId = [[exception objectForKey: @"Exception_StartTime"] asCalendarDate];
if (isAllDay)
recurrenceId = [recurrenceId dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: [userTimeZone secondsFromGMTForDate:recurrenceId]];
// When moving the calendar entry (i.e. changing the startDate) iOS and Android sometimes send a value for
// Exception_StartTime which is not what we expect.
// With this we make sure the recurrenceId is always correct.
//
// iOS problem - If the master is a no-allday-event but the exception is, an invalid Exception_StartTime is in the request.
// e.g. it sends 20150409T040000Z instead of 20150409T060000Z;
// This might be a special case since iPhone doesn't allow an allday-exception on a non-allday-event.
if (!([[start dateTime] compare: [[start dateTime] hour:[recurrenceId hourOfDay] minute:[recurrenceId minuteOfHour]]] == NSOrderedSame))
recurrenceId = [recurrenceId hour:[[start dateTime] hourOfDay] minute:[[start dateTime] minuteOfHour]];
// We need to store the recurrenceIds and exception dates adjusted by deltasecs.
// This ensures that the adjustment in SOGoCalendarComponent->updateComponent->_updateRecurrenceIDsWithEvent gives the correct dates.
adjustedRecurrenceId = [recurrenceId dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0 seconds: deltasecs];
// search for an existing occurence and update it
max = [occurences count];
currentOccurence = nil;
count = 1;
while (count < max)
{
currentOccurence = [occurences objectAtIndex: count] ;
currentId = [currentOccurence recurrenceId];
if ([currentId compare: adjustedRecurrenceId] == NSOrderedSame)
{
[exceptionstouched addObject: adjustedRecurrenceId];
[currentOccurence takeActiveSyncValues: exception inContext: context];
break;
}
count++;
currentOccurence = nil;
}
// Create a new occurence if we found none to update.
if (!currentOccurence)
{
iCalDateTime *recid;
currentOccurence = [self mutableCopy];
[currentOccurence removeAllRecurrenceRules];
[currentOccurence removeAllExceptionRules];
[currentOccurence removeAllExceptionDates];
[[self parent] addToEvents: currentOccurence];
[currentOccurence takeActiveSyncValues: exception inContext: context];
recid = (iCalDateTime *)[currentOccurence uniqueChildWithTag: @"recurrence-id"];
if (isAllDay)
[recid setDate: adjustedRecurrenceId];
else
[recid setDateTime: adjustedRecurrenceId];
[exceptionstouched addObject: [recid dateTime]];
}
}
else if ([[exception objectForKey: @"Exception_Deleted"] intValue])
{
recurrenceId = [[exception objectForKey: @"Exception_StartTime"] asCalendarDate];
if (isAllDay)
recurrenceId = [recurrenceId dateByAddingYears: 0 months: 0
days: 0 hours: 0 minutes: 0
seconds: [userTimeZone secondsFromGMTForDate:recurrenceId]];
// We add only valid exception dates.
if ([self doesOccurOnDate: recurrenceId] &&
([[start dateTime] compare: [[start dateTime] hour:[recurrenceId hourOfDay]
minute:[recurrenceId minuteOfHour]]] == NSOrderedSame))
{
// We need to store the recurrenceIds and exception dates adjusted by deltasecs.
// This ensures that the adjustment in SOGoCalendarComponent->updateComponent->_updateRecurrenceIDsWithEvent gives the correct dates.
[exdates addObject: [recurrenceId dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: deltasecs]];
}
}
}
// Update exception dates in master event.
max = [exdates count];
if (max > 0)
{
for (count = 0; count < max; count++)
{
if (([exceptionstouched indexOfObject: [exdates objectAtIndex: count]] == NSNotFound))
[self addToExceptionDates: [exdates objectAtIndex: count]];
}
}
// Remove all exceptions included in the request.
max = [occurences count];
count = 1; // skip the master event
while (count < max)
{
currentOccurence = [occurences objectAtIndex: count] ;
currentId = [currentOccurence recurrenceId];
// Delete all occurences which are not touched (modified/added).
if (([exceptionstouched indexOfObject: currentId] == NSNotFound))
[[[self parent] children] removeObject: currentOccurence];
count++;
}
}
else if ([self isRecurrent])
{
// We have no exceptions in request but there is a recurrence rule.
// Remove all excpetions and exception dates.
iCalEvent *currentOccurence;
unsigned int count, max;
[self removeAllExceptionDates];
max = [occurences count];
count = 1; // skip the master event
while (count < max)
{
currentOccurence = [occurences objectAtIndex: count];
[[[self parent] children] removeObject: currentOccurence];
count++;
}
}
}
else if ([self isRecurrent])
{
// We have no recurrence rule in request.
// Remove all exceptions, exception dates and recurrence rules.
iCalEvent *currentOccurence;
unsigned int count, max;
[self removeAllRecurrenceRules];
[self removeAllExceptionRules];
[self removeAllExceptionDates];
max = [occurences count];
count = 1; // skip the master event
while (count < max)
{
currentOccurence = [occurences objectAtIndex: count];
[[[self parent] children] removeObject: currentOccurence];
count++;
}
}
// Organizer - we don't touch the value unless we're the organizer
@@ -789,7 +498,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
([self userIsOrganizer: [context activeUser]] || [[context activeUser] hasEmail: o]))
{
iCalPerson *person;
person = [iCalPerson elementWithTag: @"organizer"];
[person setEmail: o];
[person setCn: [theValues objectForKey: @"Organizer_Name"]];
@@ -837,7 +546,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
// Windows phones sens sometimes an empty Attendees tag.
// We check it's an array before processing it.
if ((o = [theValues objectForKey: @"Attendees"]) && [o isKindOfClass: [NSArray class]])
if ((o = [theValues objectForKey: @"Attendees"])&& [o isKindOfClass: [NSArray class]])
{
NSMutableArray *attendees;
NSDictionary *attendee;
@@ -886,36 +595,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
}
- (void) changeParticipationStatus: (NSDictionary *) theValues
inContext: (WOContext *) context
component: (id) component
{
NSString *status;
id o;
// See: https://msdn.microsoft.com/en-us/library/ee202290(v=exchg.80).aspx
//
// 0 == Free
// 1 == Tentative
// 2 == Busy
// 3 == Out of Office
// 4 == Working elsehwere
//
if ((o = [theValues objectForKey: @"BusyStatus"]))
{
// We translate >= 2 into ACCEPTED
if ([o intValue] == 0)
status = @"NEEDS-ACTION";
else if ([o intValue] >= 2)
status = @"ACCEPTED";
else
status = @"TENTATIVE";
// There's no delegate in EAS
[(SOGoAppointmentObject *) component changeParticipationStatus: status
withDelegate: nil
alarm: nil];
}
}
@end
+24 -49
View File
@@ -35,42 +35,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <Foundation/NSString.h>
#import <NGCards/iCalEvent.h>
#import <NGCards/iCalToDo.h>
#import <NGCards/iCalByDayMask.h>
#import <NGCards/iCalDateTime.h>
#import <NGCards/iCalTimeZone.h>
#import "NSCalendarDate+ActiveSync.h"
#import "NSDate+ActiveSync.h"
@implementation iCalRecurrenceRule (ActiveSync)
- (NSCalendarDate *) _adjustedStartDate
{
iCalTimeZone *timeZone;
timeZone = [(iCalDateTime *)[[self parent] firstChildWithTag: @"dtstart"] timeZone];
if (timeZone)
return [timeZone computedDateForDate: [[self parent] startDate]];
else
return [[self parent] startDate];
}
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
{
NSMutableString *s;
NSString *t;
int type;
s = [NSMutableString string];
if ([[self parent] isKindOfClass: [iCalToDo class]])
t = @"Tasks";
else
t = @"Calendar";
[s appendFormat: @"<Recurrence xmlns=\"%@:\">", t];
[s appendString: @"<Recurrence xmlns=\"Calendar:\">"];
// 0 -> daily, 1 -> weekly, 2 -> montly, 5 -> yearly
type = 0;
@@ -82,11 +61,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// 1 -> sunday, 2 -> monday, 4 -> tuesday, 8 -> wednesday, 16 -> thursday, 32 -> friday, 64 -> saturday, 127 -> last day of month (montly or yearl recurrences only)
if ([[self byDayMask] isWeekDays])
{
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"%@:\">%d</Recurrence_DayOfWeek>", t, (2|4|8|16|32)];
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"Calendar:\">%d</Recurrence_DayOfWeek>", (2|4|8|16|32)];
}
else
{
[s appendFormat: @"<Recurrence_Interval xmlns=\"%@:\">%d</Recurrence_Interval>", t, [self repeatInterval]];
[s appendFormat: @"<Recurrence_Interval xmlns=\"Calendar:\">%d</Recurrence_Interval>", [self repeatInterval]];
}
}
else if ([self frequency] == iCalRecurrenceFrequenceWeekly)
@@ -111,11 +90,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
// No byDayMask, we take the event's start date to compute the DayOfWeek
// 0 == Sunday, 6 == Saturday
v = (1 << [[self _adjustedStartDate] dayOfWeek]);
v = (1 << [[[self parent] startDate] dayOfWeek]);
}
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"%@:\">%d</Recurrence_DayOfWeek>", t, v];
[s appendFormat: @"<Recurrence_Interval xmlns=\"%@:\">%d</Recurrence_Interval>", t, [self repeatInterval]];
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"Calendar:\">%d</Recurrence_DayOfWeek>", v];
[s appendFormat: @"<Recurrence_Interval xmlns=\"Calendar:\">%d</Recurrence_Interval>", [self repeatInterval]];
}
else if ([self frequency] == iCalRecurrenceFrequenceMonthly)
{
@@ -132,8 +111,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if (firstOccurrence < 0)
firstOccurrence = 5;
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"%@:\">%d</Recurrence_DayOfWeek>", t, (1 << [dm firstDay])];
[s appendFormat: @"<Recurrence_WeekOfMonth xmlns=\"%@:\">%d</Recurrence_WeekOfMonth>", t, firstOccurrence];
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"Calendar:\">%d</Recurrence_DayOfWeek>", (1 << [dm firstDay])];
[s appendFormat: @"<Recurrence_WeekOfMonth xmlns=\"Calendar:\">%d</Recurrence_WeekOfMonth>", firstOccurrence];
}
else if ([[self byMonthDay] count])
{
@@ -147,8 +126,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
iCalByDayMask *dm;
dm = [self byDayMask];
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"%@:\">%d</Recurrence_DayOfWeek>", t, (1 << [dm firstDay])];
[s appendFormat: @"<Recurrence_WeekOfMonth xmlns=\"%@:\">%d</Recurrence_WeekOfMonth>", t, 5];
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"Calendar:\">%d</Recurrence_DayOfWeek>", (1 << [dm firstDay])];
[s appendFormat: @"<Recurrence_WeekOfMonth xmlns=\"Calendar:\">%d</Recurrence_WeekOfMonth>", 5];
}
else
{
@@ -160,7 +139,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
// Simple reccurrence rule of type "Monthly"
type = 2;
[s appendFormat: @"<Recurrence_DayOfMonth xmlns=\"%@:\">%d</Recurrence_DayOfMonth>", t, [[self _adjustedStartDate] dayOfMonth]];
[s appendFormat: @"<Recurrence_DayOfMonth xmlns=\"Calendar:\">%d</Recurrence_DayOfMonth>",
[[[self parent] startDate] dayOfMonth]];
}
}
else if ([self frequency] == iCalRecurrenceFrequenceYearly)
@@ -179,39 +159,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if (firstOccurrence < 0)
firstOccurrence = 5;
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"%@:\">%d</Recurrence_DayOfWeek>", t, (1 << [dm firstDay])];
[s appendFormat: @"<Recurrence_WeekOfMonth xmlns=\"%@:\">%d</Recurrence_WeekOfMonth>", t, firstOccurrence];
[s appendFormat: @"<Recurrence_MonthOfYear xmlns=\"%@:\">%@</Recurrence_MonthOfYear>", t,
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"Calendar:\">%d</Recurrence_DayOfWeek>", (1 << [dm firstDay])];
[s appendFormat: @"<Recurrence_WeekOfMonth xmlns=\"Calendar:\">%d</Recurrence_WeekOfMonth>", firstOccurrence];
[s appendFormat: @"<Recurrence_MonthOfYear xmlns=\"Calendar:\">%@</Recurrence_MonthOfYear>",
[self flattenedValuesForKey: @"bymonth"]];
}
else
{
type = 5; // Yearly
[s appendFormat: @"<Recurrence_DayOfMonth xmlns=\"%@:\">%@</Recurrence_DayOfMonth>", t,
[s appendFormat: @"<Recurrence_DayOfMonth xmlns=\"Calendar:\">%@</Recurrence_DayOfMonth>",
[self flattenedValuesForKey: @"bymonthday"]];
[s appendFormat: @"<Recurrence_MonthOfYear xmlns=\"%@:\">%@</Recurrence_MonthOfYear>", t,
[s appendFormat: @"<Recurrence_MonthOfYear xmlns=\"Calendar:\">%@</Recurrence_MonthOfYear>",
[self flattenedValuesForKey: @"bymonth"]];
}
}
else
{
type = 5;
[s appendFormat: @"<Recurrence_DayOfMonth xmlns=\"%@:\">%d</Recurrence_DayOfMonth>", t, [[self _adjustedStartDate] dayOfMonth]];
[s appendFormat: @"<Recurrence_MonthOfYear xmlns=\"%@:\">%d</Recurrence_MonthOfYear>", t, [[self _adjustedStartDate] monthOfYear]];
}
type = 5;
}
[s appendFormat: @"<Recurrence_Type xmlns=\"%@:\">%d</Recurrence_Type>", t, type];
if ([[self parent] isKindOfClass: [iCalToDo class]])
[s appendFormat: @"<Recurrence_Start xmlns=\"%@:\">%@</Recurrence_Start>", t, [[[self parent] startDate] activeSyncRepresentationInContext: context]];
[s appendFormat: @"<Recurrence_Type xmlns=\"Calendar:\">%d</Recurrence_Type>", type];
// Occurrences / Until
//[s appendFormat: @"<Recurrence_Occurrences xmlns=\"Calendar:\">%d</Recurrence_Occurrences>", 5];
if ([self repeatCount])
{
[s appendFormat: @"<Recurrence_Occurrences xmlns=\"%@:\">%@</Recurrence_Occurrences>", t,
[s appendFormat: @"<Recurrence_Occurrences xmlns=\"Calendar:\">%@</Recurrence_Occurrences>",
[self flattenedValuesForKey: @"count"]];
}
else if ([self untilDate])
@@ -222,10 +196,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//ud = [[context activeUser] userDefaults];
//[date setTimeZone: [ud timeZone]];
[s appendFormat: @"<Recurrence_Until xmlns=\"%@:\">%@</Recurrence_Until>", t,
[s appendFormat: @"<Recurrence_Until xmlns=\"Calendar:\">%@</Recurrence_Until>",
[date activeSyncRepresentationWithoutSeparatorsInContext: context]];
}
[s appendString: @"</Recurrence>"];
return s;
+13 -12
View File
@@ -31,10 +31,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <Foundation/NSArray.h>
#include <Foundation/NSCalendarDate.h>
#include <Foundation/NSData.h>
#include <Foundation/NSDate.h>
#include <Foundation/NSString.h>
#import <NGCards/iCalByDayMask.h>
#import <NGCards/iCalTimeZonePeriod.h>
#import <NGCards/iCalRecurrenceRule.h>
#import <NGExtensions/NGBase64Coding.h>
#include "NSData+ActiveSync.h"
@@ -123,7 +128,7 @@ struct SYSTEMTIME {
//uint16_t wStandardYear;
struct SYSTEMTIME stStandardDate;
//uint16_t wDaylightYear;
struct SYSTEMTIME stDaylightDate = {0,0,0,0,0,0,0,0};
struct SYSTEMTIME stDaylightDate;
char standardName[64], daylightName[64];
@@ -139,17 +144,13 @@ struct SYSTEMTIME {
period = [self _mostRecentPeriodWithName: @"DAYLIGHT"];
if (!period)
{
stStandardDate.wMonth = 0;
lDaylightBias = 0;
}
else
{
lDaylightBias = (uint32_t) -([period secondsOffsetFromGMT] / 60) - lBias;
[period _fillTZDate: &stDaylightDate];
//wStandardYear = stStandardDate.wYear;
//wDaylightYear = stDaylightDate.wYear;
}
stStandardDate.wMonth = 0;
lDaylightBias = (uint32_t) -([period secondsOffsetFromGMT] / 60) - lBias;
[period _fillTZDate: &stDaylightDate];
//wStandardYear = stStandardDate.wYear;
//wDaylightYear = stDaylightDate.wYear;
// We build the timezone
[bytes appendBytes: &lBias length: 4];
+8 -31
View File
@@ -29,10 +29,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "iCalToDo+ActiveSync.h"
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSTimeZone.h>
#import <NGExtensions/NSString+misc.h>
#import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WORequest.h>
@@ -45,7 +49,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "NSDate+ActiveSync.h"
#include "NSString+ActiveSync.h"
#include "iCalRecurrenceRule+ActiveSync.h"
@implementation iCalToDo (ActiveSync)
@@ -80,10 +84,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendFormat: @"<DueDate xmlns=\"Tasks:\">%@</DueDate>", [o activeSyncRepresentationInContext: context]];
[s appendFormat: @"<UTCDueDate xmlns=\"Tasks:\">%@</UTCDueDate>", [o activeSyncRepresentationInContext: context]];
}
// Recurrence rules
if ([self isRecurrent])
[s appendString: [[[self recurrenceRules] lastObject] activeSyncRepresentationInContext: context]];
// Importance
o = [self priority];
@@ -131,7 +131,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// otherwise it'll prevent WP8 phones from sync'ing. See #3028 for details.
o = [o activeSyncRepresentationInContext: context];
if ([[context objectForKey: @"ASProtocolVersion"] isEqualToString: @"2.5"])
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
{
[s appendFormat: @"<Body xmlns=\"Tasks:\">%@</Body>", o];
[s appendString: @"<BodyTruncated xmlns=\"Tasks:\">0</BodyTruncated>"];
@@ -140,7 +140,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", (int)[o length]];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];
[s appendFormat: @"<Data>%@</Data>", o];
[s appendString: @"</Body>"];
}
@@ -165,7 +165,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[self setSummary: o];
// FIXME: merge with iCalEvent
if ([[context objectForKey: @"ASProtocolVersion"] isEqualToString: @"2.5"])
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
{
if ((o = [theValues objectForKey: @"Body"]))
[self setComment: o];
@@ -251,29 +251,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
}
// Recurrence
if ((o = [theValues objectForKey: @"Recurrence"]) && !([[o objectForKey: @"Recurrence_DeadOccur"] intValue]))
{
iCalRecurrenceRule *rule;
rule = [[iCalRecurrenceRule alloc] init];
[self setRecurrenceRules: [NSArray arrayWithObject: rule]];
RELEASE(rule);
[rule takeActiveSyncValues: o inContext: context];
if (!([theValues objectForKey: @"StartDate"]))
{
iCalDateTime *start;
start = (iCalDateTime *) [self uniqueChildWithTag: @"dtstart"];
[start setTimeZone: tz];
[start setDate: [[o objectForKey: @"Recurrence_Start"] calendarDate]];
}
}
}
@end
+4 -8
View File
@@ -57,6 +57,8 @@ ProxyPreserveHost On
# Allow from your-cas-host-addr
# </Proxy>
ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0
# Enable to use Microsoft ActiveSync support
# Note that you MUST have many sogod workers to use ActiveSync.
# See the SOGo Installation and Configuration guide for more details.
@@ -65,15 +67,11 @@ ProxyPreserveHost On
# http://127.0.0.1:20000/SOGo/Microsoft-Server-ActiveSync \
# retry=60 connectiontimeout=5 timeout=360
ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0
<Proxy http://127.0.0.1:20000/SOGo>
## adjust the following to your configuration
## and do not forget to enable the headers module
<IfModule headers_module>
RequestHeader set "x-webobjects-server-port" "443"
RequestHeader set "x-webobjects-server-name" "%{HTTP_HOST}e" env=HTTP_HOST
RequestHeader set "x-webobjects-server-url" "https://%{HTTP_HOST}e" env=HTTP_HOST
RequestHeader set "x-webobjects-server-name" "yourhostname"
RequestHeader set "x-webobjects-server-url" "https://yourhostname"
## When using proxy-side autentication, you need to uncomment and
## adjust the following line:
@@ -81,7 +79,6 @@ ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0
# RequestHeader set "x-webobjects-remote-user" "%{REMOTE_USER}e" env=REMOTE_USER
RequestHeader set "x-webobjects-server-protocol" "HTTP/1.0"
</IfModule>
AddDefaultCharset UTF-8
@@ -93,6 +90,5 @@ ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0
<IfModule rewrite_module>
RewriteEngine On
RewriteRule ^/.well-known/caldav/?$ /SOGo/dav [R=301]
RewriteRule ^/.well-known/carddav/?$ /SOGo/dav [R=301]
</IfModule>
+393 -33906
View File
File diff suppressed because it is too large. Load diff
+44 -76
View File
@@ -1,47 +1,36 @@
Developer's Guide
=================
:toc: left
:icons: font
////
This file is part of the SOGo project.
See docinfo.xml for authors, copyright and license information.
////
include::includes/global-attributes.asciidoc[]
https://wiki.inverse.ca/focus/SOGo/CodingStyle
https://wiki.inverse.ca/focus/SOGo/D%C3%A9veloppement
https://wiki.inverse.ca/focus/PacketFence/Devel/BestPractices
UI and UX
---------
* http://www.google.com/design/spec/material-design/
* http://goodui.org/
- Try Repeating Your Primary Action instead of showing it just once.
- Try Distinct Clickable/Selected Styles instead of blurring them.
- Try Undos instead of prompting for confirmation.
- Try More Contrast instead of similarity.
- Try Exposing Options instead of hiding them.
- Try Showing State instead of being state agnostic.
- Try Direct Manipulation instead of contextless menus.
- Try Exposing Fields instead of creating extra pages.
- Try Transitions instead of showing changes instantly.
- Try Fewer Borders instead of wasting attention.
- Try Designing For Zero Data instead of just data heavy cases.
- Try Consistency instead of making people relearn.
- Try Conventions instead of reinventing the wheel.
- Try Visual Hierarchy instead of dullness.
- Try Grouping Related Items instead of disordering.
- Try Inline Validation instead of delaying errors.
- Try Forgiving Inputs instead of being strict with data.
- Try Bigger Click Areas instead of tiny ones.
- Try Faster Load Times instead of making people wait.
- Try Keyboard Shortcuts instead of buttons only.
- Try Upfront Progress instead of starting with a blank.
- Try Softer Prompts instead of modal windows.
- Try Multifunctional Controls instead of more parts.
- Try Icon Labels instead of opening for interpretation.
* Try Repeating Your Primary Action instead of showing it just once.
* Try Distinct Clickable/Selected Styles instead of blurring them.
* Try Undos instead of prompting for confirmation.
* Try More Contrast instead of similarity.
* Try Exposing Options instead of hiding them.
* Try Showing State instead of being state agnostic.
* Try Direct Manipulation instead of contextless menus.
* Try Exposing Fields instead of creating extra pages.
* Try Transitions instead of showing changes instantly.
* Try Fewer Borders instead of wasting attention.
* Try Designing For Zero Data instead of just data heavy cases.
* Try Consistency instead of making people relearn.
* Try Conventions instead of reinventing the wheel.
* Try Visual Hierarchy instead of dullness.
* Try Grouping Related Items instead of disordering.
* Try Inline Validation instead of delaying errors.
* Try Forgiving Inputs instead of being strict with data.
* Try Bigger Click Areas instead of tiny ones.
* Try Faster Load Times instead of making people wait.
* Try Keyboard Shortcuts instead of buttons only.
* Try Upfront Progress instead of starting with a blank.
* Try Softer Prompts instead of modal windows.
* Try Multifunctional Controls instead of more parts.
* Try Icon Labels instead of opening for interpretation.
* http://designmodo.com/create-style-guides/
* http://uxmyths.com/
@@ -54,14 +43,23 @@ GNUstep
SOPE
~~~~
JavaScript libraries
~~~~~~~~~~~~~~~~~~~~
AngularJS
~~~~~~~~~
* https://angularjs.org/
* http://angular-ui.github.io/ui-router/
* https://www.airpair.com/angularjs/posts/angularjs-tutorial
Angular Material
~~~~~~~~~~~~~~~~
* https://material.angularjs.org/
Lo-Dash
~~~~~~~
* http://lodash.com/
* https://github.com/nervgh/angular-file-upload
* http://underscorejs.org/
Code Style
----------
@@ -73,11 +71,6 @@ Objective-C
apidoc -f ".*\\.m" -i UI -o Documentation/JSON-API
* When returning JSON from an object extending UIxComponent, use the following method:
- (WOResponse *) responseWithStatus: (unsigned int) status
andJSONRepresentation: (NSObject *) contentObject;
HTML
~~~~
@@ -95,11 +88,8 @@ JavaScript
~~~~~~~~~~
* http://eslint.org/
* http://standardjs.com
* https://github.com/toddmotto/angularjs-styleguide
* https://github.com/angular/material/blob/master/docs/guides/CODING.md
* http://jshint.com/
* https://github.com/angular/material/tree/master/docs/guides
* We conform to https://github.com/airbnb/javascript[Airbnb coding standards]. Use https://github.com/jscs-dev/node-jscs[jscs] with the 'airbnb' preset to validate your code style:
@@ -107,7 +97,7 @@ JavaScript
* For documentation, we follow the http://usejsdoc.org/[JSDoc3] standards:
jsdoc UI/WebServerResources/js/{Common,Contacts,Mailer,Preferences,Scheduler}/*.js -d Documentation/JavaScript-API
jsdoc UI/WebServerResources/js/{Appointments,Common,Contacts,Mailer}/*.js -d Documentation/JavaScript-API
Models (facades)
^^^^^^^^^^^^^^^^
@@ -124,13 +114,6 @@ SASS/CSS
* http://componentcss.com/
* https://github.com/styleguide/css
* https://smacss.com/
* http://cssguidelin.es/
* http://sixrevisions.com/css/css-methodologies/
* https://css-tricks.com/what-a-css-code-review-might-look-like/
* http://una.im/classy-css/
* http://stylelint.io/
A `@mixin` is like a stamp: it creates a duplicated version of the property block (optionally) with arguments provided. An `@extend` appends the element you are extending to the property block. It is your "yes, and ___" statement.
* For documentation, we follow http://sassdoc.com/[SassDoc] annotations.
* We need the SASS files of Angular Material to build our CSS. The git repository of Angular Material is included as a submodule of SOGo:
@@ -143,29 +126,14 @@ A `@mixin` is like a stamp: it creates a duplicated version of the property bloc
Fonts
^^^^^
* http://mozilla.github.io/Fira/[Mozilla Fira]
* https://www.google.com/design/icons/[Material icons]
Building frontend
-----------------
* Install the latest stable release of https://nodejs.org[Node.js]
* Install grunt
npm install -g grunt-cli
npm install -g bower
* Generate JavaScript files
cd UI/WebServerResources
npm install
grunt build
* We build a custom icons font using the online app https://icomoon.io/app/#/select[icomoon].
* http://www.carrois.com/fira-4-0/
* Material Design Iconic Font http://zavoloklom.github.io/material-design-iconic-font/icons.html
Version Control
---------------
* https://devcharm.com/articles/46/improve-your-git-workflow/
* https://github.com/angular/material/blob/master/docs/guides/CONTRIBUTING.md#-commit-message-format
* Each commit should cover only one thing;
* Begin the commit message with a single short (less than 50 characters) line summarizing the change, followed by a blank line and then a more thorough description;
* When fixing a bug, commit to the devel branch as well as the maintenance branch of the latest release version (named maintenance/x.y). When a ticket is associated to the bug, add to the description a line saying *Fixes #1234*.
@@ -182,7 +150,7 @@ Testing
JSON API
~~~~~~~~
One practical way to test the JSON API is to use `curl`. To do so, you need to enable `SOGoTrustProxyAuthentication` and configure HTTP authentifcation in Apache. You can pipe the result to http://stedolan.github.io/jq/[jq] to nicely format and filter the output:
One practical way to test the JSON API is to use `curl`. To do so, you need to enable `SOGoTrustProxyAuthentication` and configure HTTP authentifcation in Apache. You can pipe the result to [jq](http://stedolan.github.io/jq/) to nicely format and filter the output:
curl -u username:password http://localhost/SOGo/so/username/Calendar/calendarslist | jq '.'
+75 -336
View File
@@ -1,7 +1,5 @@
Installation and Configuration Guide
====================================
:toc: left
:icons: font
////
@@ -18,13 +16,13 @@ About this Guide
This guide will walk you through the installation and configuration of
the SOGo solution. It also covers the installation and configuration of
SOGo ActiveSync support - the solution used to synchronize mobile
SOGo ActiveSync support – the solution used to synchronize mobile
devices with SOGo.
The instructions are based on version {release_version} of SOGo.
The latest version of this guide is available
at http://sogo.nu/downloads/documentation.html.
at http://www.sogo.nu/downloads/documentation.html.
Introduction
------------
@@ -50,12 +48,13 @@ the SOGo Connector and the SOGo Integrator
device, or Outlook 2013
SOGo is developed by a community of developers located mainly in North
America and Europe. More information can be found at http://sogo.nu/
America and Europe. More information can be found
at http://www.sogo.nu/
Architecture and Compatibility
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
image::images/architecture.png[System Architecture, 400, 964]
image::images/architecture.png[System Architecture]
Standard protocols such as CalDAV, CardDAV, GroupDAV, HTTP, IMAP and
SMTP are used to communicate with the SOGo platform or its
@@ -170,21 +169,21 @@ supported by SOGo:
* Red Hat Enterprise Linux (RHEL) Server 5, 6 and 7
* Community ENTerprise Operating System (CentOS) 5, 6 and 7
* Debian GNU/Linux 6.0 (Squeeze), 7.0 (Wheezy) and 8.0 (Jessie)
* Ubuntu 12.04 (Precise), 14.04 (Trusty) and 16.04 (Xenial)
* Debian GNU/Linux 6.0 (Squeeze) to 8.0 (Jessie)
* Ubuntu 10.04 (Lucid) to 14.04 (Trusty)
Make sure the required components are started automatically at boot time
and that they are running before proceeding with the SOGo configuration.
Also make sure that you can install additional packages from your
standard distribution. For example, if you are using Red Hat Enterprise
Linux 7, you have to be subscribed to the Red Hat Network before
Linux 5, you have to be subscribed to the Red Hat Network before
continuing with the SOGo software installation.
NOTE: This document covers the installation of SOGo under RHEL 7.
This document covers the installation of SOGo under RHEL 6.
For installation instructions on Debian and Ubuntu, please refer
directly to the SOGo website at http://sogo.nu/.
Under the _Support_ section, you will find links for installation steps
directly to the SOGo website at http://www.sogo.nu/.
Under the downloads section, you will find links for installation steps
for Debian and Ubuntu.
Note that once the SOGo packages are installed under Debian and Ubuntu,
@@ -195,17 +194,12 @@ Installation
This section will guide you through the installation of SOGo together
with its dependencies. The steps described here apply to an RPM-based
installation for a Red Hat or CentOS 7 distribution. Most of these steps
installation for a Red Hat or CentOS 6 distribution. Most of these steps
should apply to all supported operating systems.
Software Downloads
~~~~~~~~~~~~~~~~~~
[NOTE]
In order to access the production builds, you need a proper support contract
from https://sogo.nu/support/index_new.html#support-plans[Inverse]. Continue
with the configuration once you received your username and password.
SOGo can be installed using the `yum` utility. To do so, first create
the `/etc/yum.repos.d/inverse.repo` configuration file with the following
content:
@@ -213,32 +207,19 @@ content:
----
[SOGo]
name=Inverse SOGo Repository
baseurl=https://<username>:<password>@packages.inverse.ca/SOGo/release/3/rhel/7/$basearch
gpgcheck=1
baseurl=http://inverse.ca/downloads/SOGo/RHEL6/$basearch
gpgcheck=0
----
[NOTE]
Any non-URL safe characters in username/password must be URL-encoded. For
example, if your password is `so%go`, you must set the value in your
configuration file to `so%25go` - where `%` is encoded to `%25`.
Some of the softwares on which SOGo depends are available from the
repository of RepoForge (previously known as RPMforge). To add RepoForge
to your packages sources, download and install the appropriate RPM
package
from http://packages.sw.be/rpmforge-release/.
Also make sure you enabled the "rpmforge-extras" repository.
Inverse signs its RPM packages with its GPG key. Integrity verification happens
all by itself on package installation, all you need to do is first import the
key into your rpm keychain:
----
rpm --import "https://pgp.mit.edu/pks/lookup?op=get&search=0xCB2D3A2AA0030E2C"
----
Some of the softwares on which SOGo depends are available from the repository
"Extra Packages for Enterprise Linux" (EPEL). To add EPEL to your packages
sources, install the following package:
----
rpm -ivh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
----
For more information on EPEL, visit http://fedoraproject.org/wiki/EPEL/.
For more information on using RepoForge,
visit http://repoforge.org/use/.
Software Installation
~~~~~~~~~~~~~~~~~~~~~
@@ -313,7 +294,7 @@ associated to a domain is limited to access only the users data from the
same domain. Consequently, the configuration parameters of SOGo are
defined on three levels:
image::images/preferences-hierarchy.png[Preferences Hierarchy, 400, 400]
image::images/preferences-hierarchy.png[Preferences Hierarchy]
Each level inherits the preferences of the parent level. Therefore,
domain preferences define the defaults values of the user preferences,
@@ -387,13 +368,6 @@ Defaults to 10 (minutes).
Do not set this too low as child processes replying to clients on a slow
internet connection could be killed prematurely.
|S |WOMaxUploadSize
|Parameter used to set the maximum allowed size for content being
sent to SOGo using a PUT or a POST call. This can also limit the file
attachment size being uploaded to SOGo when composing a mail. The
value is in kilobyte. By default, the value is 0, or disabled so no
limit will be set.
|S |SxVMemLimit
|Parameter used to set the maximum amount of memory (in
megabytes) that a child can use. Reaching that value will force children
@@ -523,8 +497,8 @@ In our example, we set the default domain to `acme.com`.
meeting participants. Possible values are:
[options="compact"]
* `YES` - to send notifications
* `NO` - to not send notifications
* `YES` – to send notifications
* `NO` – to not send notifications
Defaults to `NO` when unset.
@@ -597,8 +571,6 @@ for SOGo. Possible values are:
* `Basque`
* `BrazilianPortuguese`
* `Catalan`
* `ChineseTaiwan`
* `Croatian`
* `Czech`
* `Danish`
* `Dutch`
@@ -609,19 +581,14 @@ for SOGo. Possible values are:
* `Hungarian`
* `Icelandic`
* `Italian`
* `Lithuanian`
* `Macedonian`
* `NorwegianBokmal`
* `NorwegianNynorsk`
* `Polish`
* `Portuguese`
* `Russian`
* `Slovak`
* `Slovenian`
* `SpanishArgentina`
* `SpanishSpain`
* `SpanishArgentina`
* `Swedish`
* `TurkishTurkey`
* `Ukrainian`
* `Welsh`
@@ -630,8 +597,8 @@ for SOGo. Possible values are:
someone changes his/her own calendar. Possible values are:
[options="compact"]
- `YES` - to send notifications
- `NO` - to not send notifications
- `YES` – to send notifications
- `NO` – to not send notifications
Defaults to `NO` when unset. User can overwrite this from the calendar
properties window.
@@ -642,8 +609,8 @@ modification is being done to his/her own calendar by someone else.
Possible values are:
[options="compact"]
* `YES` - to send notifications
* `NO` - to not send notifications
* `YES` – to send notifications
* `NO` – to not send notifications
Defaults to `NO` when unset. User can overwrite this from the calendar
properties window.
@@ -666,8 +633,8 @@ requiring not authentication) their calendars and address books.
Possible values are:
[options="compact"]
* `YES` - to allow them
* `NO` - to prevent them from doing so
* `YES` – to allow them
* `NO` – to prevent them from doing so
Defaults to `NO` when unset.
@@ -678,8 +645,8 @@ SOGo.
Possible values are:
[options="compact"]
* `YES` - to allow them
* `NO` - to prevent them from doing so
* `YES` – to allow them
* `NO` – to prevent them from doing so
Defaults to `NO` when unset.
@@ -709,7 +676,7 @@ Defaults to `NO` when unset.
string (attendee completion, address book search, etc.) prior triggering
the server-side search operation.
Defaults to `2` when unset - which means a search operation will be
Defaults to `2` when unset – which means a search operation will be
triggered on the 3rd typed character.
|S |SOGoMaximumFailedLoginCount
@@ -747,25 +714,6 @@ Default value is `0`, or disabled.
|Number of seconds, default to `300` (or 5 minutes). Note that
_SOGoCacheCleanupInterval_ must be set to a value equal or higher than
_SOGoFailedLoginBlockInterval_.
|S |SOGoMaximumRequestCount
|Parameter used to control the number of requests a user can send to the SOGo
server in _SOGoMaximumRequestInterval_ seconds or more. If conditions are met
or exceeded, the user will not be able to perform requests on the SOGo server
for _SOGoRequestBlockInterval_ seconds and will receive 429 HTTP responses for
any requests being made. Default value is 0, or disabled
|S |SOGoMaximumRequestInterval
|Number of seconds, defaults to `30`.
|S |SOGoRequestBlockInterval
|Number of seconds, defaults to 300 (or 5 minutes). Note that _SOGoCacheCleanupInterval_
must be set to a value equal or higher than _SOGoRequestBlockInterval_.
|D |SOGoXSRFValidationEnabled
|Parameter used to enable or not XSRF (also known as CSRF) protection in SOGo.
Default value is `NO`, or disabled.
|=======================================================================
Authentication using LDAP
@@ -892,11 +840,11 @@ would be:
CNFieldName = cn;
IDFieldName = cn;
UIDFieldName = cn;
baseDN = "ou=groups,dc=inverse,dc=ca";
baseDN = "ou=groups,dc=inverse,dc=ca”;
bindDN = "cn=sogo,ou=services,dc=inverse,dc=ca";
bindPassword = zot;
canAuthenticate = YES;
displayName = "Inverse Groups";
displayName = “Inverse Groups”;
hostname = ldap://127.0.0.1:389;
id = inverse_groups;
isAddressBook = YES;
@@ -908,7 +856,7 @@ source:
[cols="^3,>47,50a"]
|=======================================================================
.36+|D <|SOGoUserSources
.34+|D <|SOGoUserSources
|Parameter used to set the LDAP and/or SQL sources used for
authentication and global address books. Multiple sources can be
specified as an array of dictionaries. A dictionary that defines an LDAP
@@ -918,7 +866,7 @@ source can contain the following values:
|The type of this user source, set to ldap` for an LDAP source.
|id
|The identification name of the LDAP repository. This must be unique -
|The identification name of the LDAP repository. This must be unique –
even when using multiple domains.
|CNFieldName
@@ -937,8 +885,7 @@ table.
|MailFieldNames
|An array of fields that returns the user's email addresses (defaults to
`mail` when unset). Note that SOGo will always automatically strip the
protocol value from the attribute if the attribute name is `proxyAddresses`.
`mail` when unset).
|SearchFieldNames
|An array of fields to to match against the search string when filtering
@@ -985,8 +932,8 @@ be marked as busy the first time it is booked.
EOQualifier. The following operators are supported:
[options="compact"]
* `<>` - inequality operator
* `=` - equality operator
* `<>` – inequality operator
* `=` – equality operator
Multiple qualifiers can be joined by using `OR` and `AND`, they can also
be grouped together by using parenthesis. Attribute values should be
@@ -1048,9 +995,9 @@ be specified as a LDAP Extension in the LDAP URL (e.g.
without Password Policies enabled.
Possible values are: `none`, `plain`, `crypt`, `md5`, `md5-crypt`,
`sha256-crypt` and `sha512-crypt`, `smd5`, `cram-md5` and `sha`, `sha256`,
`sha512` and its ssha (e.g. `ssha` or `ssha256`) variants
(plus setting of the encoding with `.b64` or `.hex`).
`smd5`, `cram-md5` and `sha`, `sha256`, `sha512` and its ssha (e.g.
`ssha` or `ssha256`) variants (plus setting of the encoding with `.b64`
or `.hex`).
For a more detailed description see
http://wiki.dovecot.org/Authentication/PasswordSchemes.
@@ -1059,9 +1006,6 @@ Note that `cram-md5` is not actually using cram-md5 (due to the lack of
challenge-response mechanism), its just saving the intermediate MD5
context as Dovecot stores in its database.
Also note that `sha256-crypt` and `sha512-crypt` requires that your
operating system supports glibc 2.7 or more recent.
|canAuthenticate
|If set to `YES`, this LDAP source is used for authentication
@@ -1089,10 +1033,6 @@ not work for entries in this source and thus, freebusy lookups.
|If set as an address book, the human identification name of the LDAP
repository
|listRequiresDot (optional)
|If set to `YES`, listing of this LDAP source is only possible when performing a search (respecting the SOGoSearchMinimumWordLength parameter) or when explicitely typing a single dot.
Defaults to `YES` when unset.
|ModulesConstraints (optional)
|Limits the access of any module through a constraint based on an LDAP
attribute; must be a dictionary with keys `Mail`, and/or `Calendar`,
@@ -1165,7 +1105,6 @@ LDAP Attributes Indexing
To ensure proper performance of the SOGo application, the following LDAP
attributes must be fully indexed:
[options="compact"]
* givenName
* cn
* mail
@@ -1186,7 +1125,7 @@ fax number, one could map it to the _facsimiletelephonenumber_ attribute
like this:
----
mapping = {
mapping = \{
  facsimiletelephonenumber = ("fax", "facsimiletelephonenumber");
};
----
@@ -1361,7 +1300,7 @@ If you want to test the IdP-initiated logout using SimpleSAMLphp, you can do so
the following URL:
----
https://idp.example.org/simplesaml/saml2/idp/SingleLogoutService.php?ReturnTo=sogo.nu
https://idp.example.org/simplesaml/saml2/idp/SingleLogoutService.php?ReturnTo=www.sogo.nu
----
In order to relay authentication information to your IMAP server and if
@@ -1383,35 +1322,12 @@ supported, such as MySQL and Oracle.
First, make sure that your PostgreSQL server has TCP/IP connections
support enabled.
[TIP]
===============================
SOGo stores the database hostname together with table references inside
several database tables. To prevent possible future issues when moving
the database to another host, it is best practice to add a local alias name to
your `/etc/hosts` file, and using this in `/etc/sogo/sogo.conf` instead of the
actual name of your server or localhost. When the database host name changes,
you can now simply change the hosts file instead of updating several table
columns replacing the old hostname. An example entry for `/etc/hosts` when
running the database on the same host, registering `127.0.0.1` not only for
`localhost`, but also the `db-alias` alias:
127.0.0.1 localhost db-alias
In the SOGo configuration, use the alias name instead of the real IP address or
host name, for example
----
SOGoProfileURL =
"postgresql://sogo:sogo@db-alias:5432/sogo/sogo_user_profile";
----
===============================
Create the database user and schema using the following commands:
----
su - postgres
createuser --no-superuser --no-createdb --no-createrole \
--encrypted --pwprompt sogo
su – postgres
createuser --no-superuser --no-createdb –-no-createrole \
–-encrypted --pwprompt sogo
(specify “sogo” as password)
createdb -O sogo sogo
----
@@ -1466,46 +1382,9 @@ _SOGoEnableEMailAlarms_ is set to `YES`. For PostgreSQL, the database
URL could be set to something like:
`postgresql://sogo:sogo@localhost:5432/sogo/sogo_alarms_folder`
|S |OCSStoreURL
|Parameter used to set the database URL so that SOGo can use to store
all content data. You must also set `OCSAclURL` and `OCSCacheFolderURL`
if you set this parameter. Using these parameters will allow SOGo to use
a total of nine database tables - and prevent SOGo from creating three
database tables per collection.
For PostgresSQL, set the database URL to something like:
`postgresql://sogo:@localhost:5432/sogo/sogo_store`.
|S |OCSAclURL
|Parameter used to set the database URL so that SOGo can use to store
all ACL data. You must also set `OCSStoreURL` and `OCSCacheFolderURL`
if you set this parameter.
For PostgresSQL, set the database URL to something like:
`postgresql://sogo:@localhost:5432/sogo/sogo_acl`.
|S |OCSCacheFolderURL
|Parameter used to set the database URL so that SOGo can use to store
all cache data. You must also set `OCSStoreURL` and `OCSAclURL`
if you set this parameter.
For PostgresSQL, set the database URL to something like:
`postgresql://sogo:@localhost:5432/sogo/sogo_cache_folder`.
See the "EMail reminders" section in this document for more information.
|=======================================================================
[NOTE]
Any non-URL safe characters in username/password must be URL-encoded.
For example, if your SOGo database password is `so%go`, you must set
the value in your preferences to `so%25go` - where `%` is encoded
to `%25`.
In addition to the seven tables described above, two other tables get
created in the database: `sogo_quick_appointment` and `sogo_quick_contact`
which store calendar and contact information.
If you're using MySQL, make sure in your `my.cnf` file you have:
----
@@ -1521,72 +1400,6 @@ default-character-set=utf8
default-character-set=utf8
----
MySQL complete Unicode compliance
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
By default MySQL only supports a subset of UTF-8, meaning that characters such
as emoji are not handled properly. Some extra steps at installation can be
undertaken to leverage full Unicode support under MySQL.
IMPORTANT: Switching to complete Unicode compliance on an already-deployed SOGo
is out of scope of this document, as it would typically involve delicate manual
operations on the database system.
Requirements:
* MySQL >= 5.5
* SOGo >= 3.1.0
Strongly suggested MySQL configuration settings (innodb* parameters are
mandatory):
----
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
innodb_file_per_table = TRUE
innodb_file_format = barracuda
innodb_large_prefix = TRUE
----
CAUTION: Changing InnoDB parameters on an already deployed database server can
cause severe data loss. Do not blindly edit MySQL parameters without reading
and understanding the implication of such changes.
A parameter must be added to `sogo.conf` to turn on complete Unicode
compliance:
----
MySQL4Encoding = "utf8mb4";
----
SOGo automatically creates missing database tables on start but slightly
different table creation parameters are needed for complete Unicode compliance;
meaning that before SOGo runs for the first time, all database tables must
already exist. A MySQL script to achieve just that is provided in the SOGo
distribution under `Scripts/mysql-utf8mb4.sql` and you can deploy it with
a command such as:
----
mysql -hHOST -uUSER -p -D SOGO < Scripts/mysql-utf8mb4.sql
----
Where `HOST`, `USER` and `SOGO` are your MySQL host, username and database name
respectively.
Once SOGo is running, you can test correctness by creating an event such as
“Lunch with &#127829; and fries” and seeing it properly displayed in the SOGo
calendar.
Ensure the computer used for the test has emoji fonts installed.
Authentication using SQL
~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1608,7 +1421,7 @@ source can contain the following values:
|The type of this user source, set to `sql` for a SQL source.
|id
|The identification name of the SQL repository. This must be unique -
|The identification name of the SQL repository. This must be unique –
even when using multiple domains.
|viewURL
@@ -1616,14 +1429,14 @@ even when using multiple domains.
present. Required columns are:
[options="compact"]
* `c_uid`: will be used for authentication - it's a username or
* `c_uid`: will be used for authentication – it's a username or
username@domain.tld
* `c_name`: will be used to uniquely identify entries - which can be
* `c_name`: will be used to uniquely identify entries – which can be
identical to `c_uid`
* `c_password`: password of the user, plain text, crypt, md5 or sha
encoded
* `c_cn`: the user's common name
* `mail`: the user's email address
* mail : the user's email address
Other columns can exist and will actually be mapped automatically if
they have the same name as popular LDAP attributes (such as `givenName`,
@@ -1669,10 +1482,8 @@ repository.
authentication usernames (defaults to `c_uid` when unset).
|MailFieldNames (optional)
|An array of fields that specifies the column names that hold
|Aan array of fields that specifies the column names that hold
additional email addresses (beside the `mail` column) for each user.
Values must be unique and not appear in more than one column.
Space-separated values allowed in all *additional* columns (besides in `mail`).
|IMAPHostFieldName (optional)
|The field that returns the IMAP hostname for the user.
@@ -1726,14 +1537,14 @@ SOGoUserSources =
Certain database columns must be present in the view/table, such as:
* `c_uid` - will be used for authentication - it's the username
* `c_uid` – will be used for authentication – it's the username
or username@domain.tld
* `c_name` - which can be identical to `c_uid` - will be used to
* `c_name` – which can be identical to `c_uid` – will be used to
uniquely identify entries
* `c_password` - password of the user, plain-text, md5 or sha encoded
* `c_password` – password of the user, plain-text, md5 or sha encoded
for now
* `c_cn` - the user's common name - such as "John Doe"
* `mail` - the user's mail address
* `c_cn` – the user's common name – such as "John Doe"
* `mail` – the user's mail address
Note that groups are currently not supported for SQL-based
authentication sources.
@@ -1753,8 +1564,8 @@ The following table describes the related parameters.
are:
[options="compact"]
* `sendmail` - to use the sendmail binary
* `smtp` - to use the SMTP protocol
* `sendmail` – to use the sendmail binary
* `smtp` – to use the SMTP protocol
|D |SOGoSMTPServer
|The DNS name or IP address of the SMTP server used when
@@ -1817,16 +1628,6 @@ Defaults to `Trash` when unset.
Use a `/` as a hierarchy separator if referring to an IMAP subfolder.
For example: `INBOX/Trash`.
|U |SOGoJunkFolderName
|Parameter used to set the IMAP folder name used to store junk
messages.
Defaults to `Junk` when unset.
Use a `/` as a hierarchy separator if referring to an IMAP subfolder.
For example: `INBOX/Junk`. Also see the SOGoMailJunkSettings for
more options regarding junk/not-junk actions.
|D |SOGoIMAPCASServiceName
|Parameter used to set the CAS service name (URL) of the imap service.
This is useful if SOGo is connecting to the IMAP service through a
@@ -1954,11 +1755,6 @@ behaviour of SOGo.
Defaults to `SOGo` when unset.
|S |SOGoHelpURL
|Parameter used to define the URL to online help for SOGo. When set,
an additional icon will appear near the logout button in SOGo's
web interface. The URL will always be open in a separate page.
|U |SOGoLoginModule
|Parameter used to specify which module to show after login. Possible
values are:
@@ -1997,17 +1793,7 @@ interface)
|Parameter used to specify the default order of the columns from the
SOGo webmail interface. The parameter is an array, for example:
`SOGoMailListViewColumnsOrder = (Flagged, Attachment, Priority, From, Subject, Unread, Date, Size);`
|D |SOGoExternalAvatarsEnabled
|Parameter used to enable fetching of avatars from remote services.
Defaults to `YES` when unset.
|U |SOGoGravatarEnabled
|Parameter used to activate fetching of avatars from http://gravatar.com/[Gravatar].
Defaults to `YES` when unset.
SOGoMailListViewColumnsOrder = (Flagged, Attachment, Priority, From, Subject, Unread, Date, Size);
|D |SOGoVacationEnabled
|Parameter used to activate the edition from the preferences window of a
@@ -2024,33 +1810,6 @@ message expiration.
See the _Cronjob — Vacation messages expiration_ section below for
details.
|D |SOGoVacationDefaultSubject
|Parameter used to define a default vacation subject if user don't specify a
custom subject.
Defaults to the characters "Auto: " followed by the original subject when unset,
as stated by RFC 5230.
|D |SOGoVacationHeaderTemplateFile
|Parameter used to specify the path of a text file whose content must be
prepended to the user's vacation message. For example:
`SOGoVacationHeaderTemplateFile = /etc/sogo/autoresponder.header.txt;`
The following template variables can appear in the content:
[options="compact"]
* `%{username}`
* `%{daysBetweenResponse}`
|D |SOGoVacationFooterTemplateFile
|Parameter used to specify the path of a text file whose content must be
appended to the user's vacation message. For example:
`SOGoVacationFooterTemplateFile = /etc/sogo/autoresponder.footer.txt;`
See `SOGoVacationHeaderTemplateFile` for available template variables.
|D |SOGoForwardEnabled
|Parameter used to activate the edition from the preferences window of a
forwarding email address. Requires Sieve script support on the IMAP
@@ -2071,11 +1830,6 @@ host.
Defaults to `NO` when unset.
|U |SOGoSieveFilters
|Parameter used to define initial Sieve scripts for users. The user
can still modify the scripts and the initial values will be written
to the Sieve server upon first login.
|D |SOGoMailPollingIntervals
|Parameter used to define the mail polling intervals (in minutes)
available to the user. The parameter is an array that can contain the
@@ -2328,21 +2082,7 @@ Defaults to `%{FolderName} (%{UserName} <%{Email}>)` when unset.
the template named `UIxAdditionalPreferences.wox`. This template should
be put under `~sogo/GNUstep/Library/SOGo/Templates/PreferencesUI/`.
|D |SOGoMailJunkSettings
|Parameter used to enable email junk settings. The value is a dictionary
and the follow keys are supported: `vendor` (which must be set to "generic"
for now), `junkEmailAddress` which sets the email address to whom SOGo will
send junk mails to, `notJunkEmailAddress` which sets the email address to
whom SOGo will send non-junk mails to and `limit`, which is an integer value
and sets the maximum number of mails that will be attached to a
junk/not junk report sent by SOGo. Example: `SOGoMailJunkSettings = {
vendor = "generic"; junkEmailAddress = "spam@foo.com";
notJunkEmailAddress = "ham@foo.com"; limit = 10;
};`
|D |SOGoMailKeepDraftsAfterSend
|Parameter used to keep mails in the drafts folder once they have been
sent by SOGo. Defaults to `NO` when unset.
Defaults to `NO` when unset.
|=======================================================================
SOGo Configuration Summary
@@ -2371,7 +2111,6 @@ like this:
SOGoDraftsFolderName = Drafts;
SOGoSentFolderName = Sent;
SOGoTrashFolderName = Trash;
SOGoJunkFolderName = Junk;
SOGoMailingMechanism = smtp;
SOGoSMTPServer = 127.0.0.1;
SOGoUserSources = (
@@ -2485,7 +2224,7 @@ as keys for the the `domains` dictionary.
|Parameter used to set domains visible among themselves. This parameter
is an array of arrays.
Example: `SOGoDomainsVisibility = ( (acme, coyote) );`
Example: `SOGoDomainsVisibility = ((acme, coyote));`
Defaults to an empty array, which means domains are isolated from each
other.
@@ -2512,7 +2251,7 @@ RequestHeader set "x-webobjects-server-url" "http://yourhostname"
You may consider enabling SSL on top of this current installation to
secure access to your SOGo installation.
See http://httpd.apache.org/docs/2.4/ssl/ for details.
See http://httpd.apache.org/docs/2.2/ssl/ for details.
You might also have to adjust the configuration if you have SELinux
enabled.
@@ -2527,13 +2266,13 @@ Starting Services
Once SOGo if fully installed and configured, start the services using
the following command:
systemctl start sogod.service
service sogod start
You may verify using the `systemctl is-enabled sogod` command that the SOGo
service is automatically started at boot time. Restart the Apache service since
You may verify using thechkconfigcommand that the SOGo service is
automatically started at boot time. Restart the Apache service since
modules and configuration files were added:
systemctl restart httpd.service
service httpd restart
Finally, you should also make sure that the `memcached` service is
started and that it is also automatically started at boot time.
@@ -2562,11 +2301,11 @@ If your mail server requires use of SMTP AUTH, specify a credential file
using `-p /path/to/credFile`. This file should contain the username and
password, separated by a colon (`username:password`)
_Cronjob_ — Vacation messages activation and expiration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_Cronjob_ — Vacation messages expiration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When vacation messages are enabled (see the parameter
_SOGoVacationEnabled_), users can set an activation or expiration date to messages
_SOGoVacationEnabled_), users can set an expiration date to messages
auto-reply. For this feature to work, you must run a _cronjob_ under the
"sogo" user.
@@ -2580,7 +2319,7 @@ contain the username and password, separated by a colon
The _cronjob_ should look like this:
----
0 0 * * * sogo /usr/sbin/sogo-tool update-autoreply -p /etc/sogo/sieve.creds
0 0 * * * sogo /usr/sbin/sogo-tool expire-autoreply -p /etc/sogo/sieve.creds
----
Managing User Accounts
@@ -2877,7 +2616,7 @@ your site. However, be aware that in order to use the SOGo Integrator
plug in, you will need to repackage it with specific modifications.
Please refer to the documentation published online:
http://sogo.nu/downloads/documentation.html
http://www.sogo.nu/downloads/documentation.html
If you only use the SOGo Connector plug in, you can still easily access
your data.
@@ -1,7 +1,5 @@
Mobile Devices Configuration Guide
==================================
:toc: left
:icons: font
////
@@ -1,7 +1,5 @@
Mozilla Thunderbird Configuration Guide
=======================================
:toc: left
:icons: font
////
@@ -63,8 +61,9 @@ Mozilla Thunderbird
Mozilla Thunderbird is the official front end client of SOGo.
Mozilla Thunderbird versions 31, 38, 45 and above are supported
and it is recommended to use the latest version of Thunderbird.
Mozilla Thunderbird version 2, 3.1, 10 ESR (Extended Support Release),
17 ESR, 24 and 31 are supported and it is recommended to use version 31 of
Thunderbird.
In order to download and install Mozilla Thunderbird, please visit:
@@ -73,16 +72,33 @@ https://www.mozilla.org/en-US/thunderbird/organizations/all-esr.html
Mozilla Lightning
~~~~~~~~~~~~~~~~~
When using Thunderbird, you can use the latest version of Mozilla
Lightning. Use the Add-ons manager of Thunderbird or visit:
When using version 24 or 31 of Thunderbird, you can use the latest version of
Mozilla Lightning. Use the Add-ons manager of Thunderbird or visit:
https://addons.mozilla.org/en-US/thunderbird/addon/lightning/
When using version 17 ESR of Thunderbird, you can use Mozilla Lightning
version 1.9.1. In order to download the extension, please visit:
https://addons.mozilla.org/en-US/thunderbird/addon/lightning/versions/1.9.1
For Thunderbird 2 and 3.1, you need the _Inverse Edition_of Mozilla
Lightning. It provides back ported features, bug fixes and security
fixes from the current development version of Mozilla Lightning. For
Thunderbird 2, it is based on release version 0.9 of Lightning. For
Thunderbird 3.1, it is based on 1.0b2.
In order to download and install Mozilla Lightning – Inverse Edition for
Thunderbird 2 or 3.1, please visit:
http://www.sogo.nu/downloads/frontends.html
SOGo Connector and SOGo Integrator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The SOGo Connector and Integrator extensions are provided to perfect the
integration of Mozilla Thunderbird with the SOGo groupware solution.
integration of Mozilla Thunderbird 2, 3.1, 10 ESR, 17 ESR, 24 and 31 with
the SOGo groupware solution.
First of all, the SOGo Connector extension transforms Thunderbird into a
full DAV client for groupware servers such as SOGo, eGroupware or
@@ -120,7 +136,7 @@ extensions, please visit:
http://www.sogo.nu/downloads/frontends.html
Prior to installing the SOGo Integrator extension, you should read the
following chapter - _SOGo Integrator Customization_.
following chapter – _SOGo Integrator Customization_.
SOGo Integrator Customization
-----------------------------
@@ -141,7 +157,7 @@ the same user name used to connect to the first email server configured
in Thunderbird. It is a current limitation but it will fit nearly all
configurations out there.
For testing purpose, it is strongly recommended to create and
For testing purpose, you are strongly recommended to create and
configure an additional user profile for Thunderbird. This is for two
reasons. The first is because of the limitation mentioned above. The
second is because the Integrator will synchronize your personal address
@@ -152,7 +168,7 @@ you may want to make a copy of that address book beforehand.
The second part requires editing one file in the extension file sub tree
to specify where the SOGo server is located. This is done by hand. In an
enterprise environment, this step is only required once per release
since the updates are expected to propagate automatically.
since the updates are expected to propagate automatically. 
Uncompress (using a ZIP or jar tool) the SOGo Integrator XPI and locate
the following file:
@@ -179,7 +195,7 @@ if the SOGo server is accessible from the following URL:
Note that if you changed the `x-webobjects-server-url` configuration
setting from your HTTP server configuration file for SOGo, the
value *must* match the one you specify in `isi:updateURL` - even the
value *must* match the one you specify in `isi:updateURL` – even the
port number.
Moreover, you *must* change the value of the
@@ -200,7 +216,7 @@ In this section, you will learn how to install and configure the SOGo
Update Server.
The SOGo Update Server can be used to automatically install or uninstall
Mozilla Thunderbird extensions, push user settings and more - all from a
Mozilla Thunderbird extensions, push user settings and more – all from a
central place managed by system administrators.
Installation
@@ -1,7 +1,5 @@
Native Microsoft Outlook Configuration Guide
============================================
:toc: left
:icons: font
////
@@ -144,7 +142,7 @@ to authenticate users. A SOGoUserSources entry to achieve this wold look
like this:
----
su - sogo
su – sogo
defaults write sogod SOGoUserSources '(
{
CNFieldName = displayName;
@@ -235,7 +233,6 @@ Installation
This section will guide you through the installation of the native
Microsoft Outlook compatibility layer SOGo offers.
////
Red Hat Enterprise Linux v6 x86_64
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -247,7 +244,7 @@ http://www.sogo.nu/english/downloads/backend.html.
In order to satisfy certain dependencies, you should also add the EPEL
source corresponding to your distribution and architecture. More
information on this is available here:
http://fedoraproject.org/wiki/EPEL - or more specifically,
http://fedoraproject.org/wiki/EPEL – or more specifically,
http://fedoraproject.org/wiki/EPEL/FAQ#How_can_I_install_the_packages_from_the_EPEL_software_repository.3F.
Once ready, install the OpenChange packages on top of an existing SOGo
@@ -319,13 +316,13 @@ from this guide.
On Ubuntu 12.04, the Samba init scripts need to be modified to
disable the upstart check. For more details, refer to:
https://wiki.samba.org/index.php/Samba4/InitScript
////
Ubuntu 16.04 (Xenial Xerus)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Debian 8 (Jessie) and Ubuntu 14.04 (Trusty Tahr)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Please follow the instructions from
https://sogo.nu/download.html to setup your
http://www.sogo.nu/english/downloads/backend.html to setup your
apt sources.
Then install Samba 4 on top of an existing SOGo
@@ -390,7 +387,7 @@ Run the following commands as root: 
----
samba-tool domain provision --realm=example.com \
--domain=EXAMPLE \
--domain=OPENCHANGE \
--adminpass='%1OpenChange' \
--server-role='domain controller'
@@ -398,7 +395,7 @@ samba-tool user setexpiry administrator --noexpiry
----
You might consider changing the realm and domain used, to suit your
environment.
enviroment.
You might also have to
remove `/etc/samba/smb.conf` prior running this command.
@@ -444,7 +441,7 @@ Your Samba 4 configuration file should look like this:
OpenChange Configuration
~~~~~~~~~~~~~~~~~~~~~~~~
Since v2.2, OpenChange stores its metadata in MySQL so you need to have it installed.
OpenChange 2.2 stores its metadata in MySQL so you need to have it installed.
First, create the OpenChange MySQL user:
@@ -515,11 +512,9 @@ mapistore:indexing_backend = mysql://openchange-user:openchange$123@localhost/op
mapiproxy:openchangedb = mysql://openchange-user:openchange$123@localhost/openchange
----
////
On RHEL, make sure SELinux is disabled:
setenforce 0
////
Next, you can start Samba using the usual command:
@@ -550,11 +545,9 @@ This service runs as a WSGI application under apache (mod_wsgi).
While HTTPS is not required to access this service, it is strongly
recommended.
////
On RHEL-based distributions, the apache configuration required by these
services can be found in `/etc/httpd/conf.d/ocsmanager.conf` and
`/etc/httpd/conf.d/rpcproxy.conf`.
////
For Debian-based distributions, these files can be found
in `/etc/apache2/conf.d/` or `/etc/apache2/conf-available`.
@@ -570,10 +563,8 @@ The OCS Manager and RPC Proxy configuration module can be enabled using:
a2enconf ocsmanager
a2enconf rpcproxy
////
On RHEL-based distributions, make sure the `LoadModule` directive is
uncommented in `/etc/httpd/conf.d/wsgi.conf`.
////
The _reqtimeout_ apache module is known to cause problems when using the
default configuration shipped with Debian-based systems. On such
@@ -589,12 +580,10 @@ To avoid this problem, use a much higher timeout or disable the module:
a2dismod reqtimeout
You should now restart the Apache service and make sure it will start on
boot.
////
On RHEL-based distributions, do:
boot. On RHEL-based distributions, do:
chkconfig httpd on && /etc/init.d/httpd restart
////
On Debian-based distributions, do:
update-rc.d apache2 defaults && /etc/init.d/apache2 restart
@@ -722,7 +711,7 @@ Adding Users
------------
Users that wish to connect natively to SOGo must be provisioned in
Samba 4 and in OpenChange - even if they already exist in your current
Samba 4 and in OpenChange – even if they already exist in your current
LDAP or Microsoft Active Directory server.
To add a user, execute the following commands: 
@@ -805,6 +794,10 @@ contact Inverse by sending an email to support@inverse.ca.
General
^^^^^^^
* If you can't see any email's content with Microsoft Outlook 2007,
install the latest Service Pack available from Microsoft's website for
this specific version. Microsoft Outlook 2007 (12.0.6423.100) SP2 MSO
(12.0.6425.1000) is known to work.
* When you create a new Microsoft Outlook profile, not all folders might
be synchronized during the first start. Simply select the appropriate
folder and click "Send and Receive". Synchronizing a folder may take
@@ -816,10 +809,11 @@ can be ignored for now. This feature is currently not supported.
remove any data associated with the user from the SOGo server and
recreate a Microsoft Outlook profile.
To remove any data associated to a user, use
the `openchange_user_cleanup` script distributed with OpenChange. The script
can be found in `/usr/share/openchange/`.
the `openchange_user_cleanup` script distributed with SOGo. The script
can be found in `/usr/share/doc/sogo/` (`/usr/share/sogo-VERSION/` on
RHEL).
To reset a user, run the script as root:
`openchange_user_cleanup username`. See the usage output for additional options.
`python openchange_user_cleanup username`. See the usage output for additional options.
* The "Out of Office Assistant" will not currently work. This feature
has not been implemented.
* Creating folders below INBOX (when not normally permitted by the IMAP
+3 -3
View File
@@ -1,7 +1,7 @@
<!-- TODO have the build system take care of this -->
<releaseinfo>Version 3.2.2 - November 2016</releaseinfo>
<subtitle>for version 3.2.2</subtitle>
<date>2016-11-23</date>
<releaseinfo>Version 2.3.1 - July 2015</releaseinfo>
<subtitle>for version 2.3.1</subtitle>
<date>2015-07-23</date>
<legalnotice>
<para>Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".</para>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

@@ -6,7 +6,7 @@
Authors:
- Inverse inc. <info@inverse.ca>
Copyright (C) 2008-2016 Inverse inc.
Copyright (C) 2008-2014 Inverse inc.
License: GFDL 1.2 or later. http://www.gnu.org/licenses/fdl.html
////
@@ -17,7 +17,7 @@ Additional Information
For more information, please consult the online FAQs (Frequently Asked
Questions) :
http://sogo.nu/support/faq.html
http://www.sogo.nu/english/support/faq.html
You can also read the mailing archives or post your questions to it. For
details, see :
@@ -6,13 +6,13 @@
Authors:
- Inverse inc. <info@inverse.ca>
Copyright (C) 2008-2016 Inverse inc.
Copyright (C) 2008-2015 Inverse inc.
License: GFDL 1.2 or later. http://www.gnu.org/licenses/fdl.html
////
// TODO have the build system take care of this
:release_version: 3.2.2
:release_version: 2.3.1
// vim: set syntax=asciidoc tabstop=2 shiftwidth=2 expandtab:
+2
View File
@@ -19,6 +19,7 @@
02111-1307, USA.
*/
#import <Foundation/NSObject.h>
@interface MainUIProduct : NSObject
{
@@ -26,6 +27,7 @@
@end
#import <Foundation/Foundation.h>
@implementation MainUIProduct
+1
View File
@@ -20,6 +20,7 @@
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSException.h>
@interface NSException (SOGoExtensions)
+1
View File
@@ -19,6 +19,7 @@
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <execinfo.h>
#import "NSException+Stacktrace.h"
+4 -1
View File
@@ -1,6 +1,8 @@
/* SOGo+DAV.h - this file is part of SOGo
*
* Copyright (C) 2010-2016 Inverse inc.
* Copyright (C) 2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@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
@@ -29,6 +31,7 @@
@interface SOGo (SOGoWebDAVExtensions)
- (WOResponse *) davPrincipalMatch: (WOContext *) localContext;
// - (WOResponse *) davPrincipalPropertySearch: (WOContext *) localContext;
- (WOResponse *) davPrincipalSearchPropertySet: (WOContext *) localContext;
@end
+30 -18
View File
@@ -1,6 +1,6 @@
/* SOGo+DAV.m - this file is part of SOGo
*
* Copyright (C) 2010-2016 Inverse inc.
* Copyright (C) 2010-2013 Inverse inc.
*
* 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
@@ -18,12 +18,18 @@
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSDictionary.h>
#import <Foundation/NSEnumerator.h>
#import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/SoObject+SoDAV.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WORequest.h>
#import <NGExtensions/NSObject+Logs.h>
#import <DOM/DOMDocument.h>
#import <DOM/DOMNode.h>
#import <DOM/DOMProtocols.h>
#import <SaxObjC/XMLNamespaces.h>
#import <SOGo/NSArray+Utilities.h>
@@ -36,7 +42,6 @@
#import <SOGo/SOGoPermissions.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserFolder.h>
#import <SOGo/SOGoUserManager.h>
#import "SOGo+DAV.h"
@@ -179,8 +184,9 @@
[hrefs addObject: [self davURLAsString]];
}
- (NSDictionary *) _handlePrincipalMatchPrincipalProperty: (id <DOMElement>) child
inContext: (WOContext *) localContext
- (NSDictionary *)
_handlePrincipalMatchPrincipalProperty: (id <DOMElement>) child
inContext: (WOContext *) localContext
{
NSMutableArray *hrefs;
NSDictionary *response;
@@ -261,7 +267,7 @@
NSObject <DOMNodeList> *list;
NSObject <DOMNode> *valueNode;
NSArray *elements;
NSString *property=nil, *match=nil;
NSString *property, *match;
list = [searchElement getElementsByTagName: @"prop"];
if ([list length])
@@ -359,26 +365,31 @@
withEmailAddressSetMatching: (NSString *) value
inContext: (WOContext *) localContext
{
SOGoUserManager *um;
id <SOGoSource> authenticationSource;
SOGoUser *activeUser;
NSArray *records;
NSUInteger count, max;
NSString *uid;
SOGoUserFolder *collection;
um = [SOGoUserManager sharedUserManager];
records = [um fetchUsersMatching: value
inDomain: [[localContext activeUser] domain]];
max = [records count];
for (count = 0; count < max; count++)
activeUser = [localContext activeUser];
if ([activeUser respondsToSelector: @selector (authenticationSource)])
{
uid = [[records objectAtIndex: count] objectForKey: @"c_uid"];
if ([uid length] > 0)
{
collection = [[SOGoUser userWithLogin: uid]
authenticationSource = [[localContext activeUser] authenticationSource];
records = [authenticationSource
fetchContactsMatching: value
inDomain: [activeUser domain]];
max = [records count];
for (count = 0; count < max; count++)
{
uid = [[records objectAtIndex: count] objectForKey: @"c_uid"];
if ([uid length] > 0)
{
collection = [[SOGoUser userWithLogin: uid]
homeFolderInContext: localContext];
[collections addObject: collection];
}
[collections addObject: collection];
}
}
}
}
@@ -574,6 +585,7 @@
@"addressbook", @"calendar-access",
@"calendar-schedule", @"calendar-auto-schedule",
@"calendar-proxy",
@"calendar-query-extended",
@"extended-mkcol",
@"calendarserver-principal-property-search",
+3 -1
View File
@@ -1,5 +1,6 @@
/*
Copyright (C) 2005-2016 Inverse inc.
Copyright (C) 2005-2010 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of SOGo.
@@ -26,6 +27,7 @@
@class NSArray;
@class NSDictionary;
@class NSMutableDictionary;
@class SOGoCache;
+24 -136
View File
@@ -1,5 +1,6 @@
/*
Copyright (C) 2005-2016 Inverse inc.
Copyright (C) 2005-2014 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of SOGo
@@ -19,11 +20,18 @@
02111-1307, USA.
*/
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSDebug.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDate.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSProcessInfo.h>
#import <Foundation/NSRunLoop.h>
#import <Foundation/NSURL.h>
#import <GDLAccess/EOAdaptorChannel.h>
#import <GDLContentStore/GCSChannelManager.h>
#import <GDLContentStore/GCSFolderManager.h>
#import <GDLContentStore/GCSFolderType.h>
#import <GDLContentStore/GCSAlarmsFolder.h>
#import <GDLContentStore/GCSSessionsFolder.h>
@@ -50,6 +58,7 @@
#import <SOGo/SOGoPublicBaseFolder.h>
#import <SOGo/SOGoProductLoader.h>
#import <SOGo/SOGoProxyAuthenticator.h>
#import <SOGo/SOGoUserFolder.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoSystemDefaults.h>
#import <SOGo/SOGoWebAuthenticator.h>
@@ -136,7 +145,7 @@ static BOOL debugLeaks;
[$(@"SOGoFolder") soClass];
/* load products */
[[SOGoProductLoader productLoader] loadAllProducts: YES];
[[SOGoProductLoader productLoader] loadAllProducts];
}
- (id) init
@@ -211,94 +220,36 @@ static BOOL debugLeaks;
[cm releaseChannel: tc];
}
- (void) _checkQuickTableWithTypeName: typeName
withCm: (GCSChannelManager *) cm
tableURL: (NSString *) url
{
GCSFolderType *type;
NSString *sql;
NSString *tableName;
EOAdaptorChannel *channel;
channel = [cm acquireOpenChannelForURL: [NSURL URLWithString: url]];
tableName = [NSString stringWithFormat: @"sogo_quick_%@", typeName];
sql = [NSString stringWithFormat: @"SELECT count(*) FROM %@",
tableName];
if ([channel evaluateExpressionX: sql])
{
type = [GCSFolderType folderTypeWithName: typeName];
if (type)
{
sql = [type sqlQuickCreateWithTableName: tableName];
if (![channel evaluateExpressionX: sql])
[self logWithFormat: @"sogo quick table %@ successfully created!",
tableName];
}
}
else
[channel cancelFetch];
[cm releaseChannel:channel];
}
//
// If OCSStoreURL is defined, we also check for OCSAclURL, OCSCacheFolderURL
// and we create the combined quick tables.
//
- (BOOL) _checkMandatoryTables
{
GCSChannelManager *cm;
GCSFolderManager *fm;
NSArray *urlStrings;
NSArray *quickTypeStrings;
NSString *tmp, *value;
NSString *urlStrings[] = {@"SOGoProfileURL", @"OCSFolderInfoURL", nil};
NSString **urlString;
NSString *value;
SOGoSystemDefaults *defaults;
NSEnumerator *e;
BOOL ok, combined;
BOOL ok;
defaults = [SOGoSystemDefaults sharedSystemDefaults];
ok = YES;
if ([GCSFolderManager singleStoreMode])
{
urlStrings = [NSArray arrayWithObjects: @"SOGoProfileURL", @"OCSFolderInfoURL", @"OCSStoreURL", @"OCSAclURL", @"OCSCacheFolderURL", nil];
quickTypeStrings = [NSArray arrayWithObjects: @"contact", @"appointment", nil];
combined = YES;
}
else
{
urlStrings = [NSArray arrayWithObjects: @"SOGoProfileURL", @"OCSFolderInfoURL", nil];
combined = NO;
}
cm = [GCSChannelManager defaultChannelManager];
e = [urlStrings objectEnumerator];
while (ok && (tmp = [e nextObject]))
urlString = urlStrings;
while (ok && *urlString)
{
value = [defaults stringForKey: tmp];
value = [defaults stringForKey: *urlString];
if (value)
[self _checkTableWithCM: cm tableURL: value andType: tmp];
{
[self _checkTableWithCM: cm tableURL: value andType: *urlString];
urlString++;
}
else
{
[self errorWithFormat: @"No value specified for '%@'", tmp];
[self errorWithFormat: @"No value specified for '%@'", *urlString];
ok = NO;
}
}
if (combined)
{
e = [quickTypeStrings objectEnumerator];
while ((tmp = [e nextObject]))
{
[self _checkQuickTableWithTypeName: tmp
withCm: cm
tableURL: [defaults stringForKey: @"OCSFolderInfoURL"]];
}
}
if (ok)
{
fm = [GCSFolderManager defaultFolderManager];
@@ -474,12 +425,8 @@ static BOOL debugLeaks;
{
static NSArray *runLoopModes = nil;
static BOOL debugOn = NO;
SOGoSystemDefaults *sd;
WOResponse *resp;
NSDate *startDate;
NSString *path;
NSTimeInterval timeDelta;
if (debugRequests)
@@ -489,7 +436,6 @@ static BOOL debugLeaks;
startDate = [NSDate date];
}
sd = [SOGoSystemDefaults sharedSystemDefaults];
cache = [SOGoCache sharedCache];
#ifdef GNUSTEP_BASE_LIBRARY
if (debugLeaks)
@@ -504,64 +450,6 @@ static BOOL debugLeaks;
}
#endif
// We check for rate-limiting settings - ignore anything actually
// sent to /SOGo/ (so unauthenticated requests).
path = [_request requestHandlerPath];
if ([path length] && [sd maximumRequestCount] > 0)
{
NSDictionary *requestCount;
NSString *username;
NSRange r;
r = [path rangeOfString: @"/"];
// We handle /sogo1/Calendar/.../ and "sogo1" as paths
if (r.length)
username = [path substringWithRange: NSMakeRange(0, r.location)];
else
username = path;
requestCount = [cache requestCountForLogin: username];
if (requestCount)
{
unsigned int current_time, start_time, delta, block_time, request_count;
current_time = [[NSCalendarDate date] timeIntervalSince1970];
start_time = [[requestCount objectForKey: @"InitialDate"] unsignedIntValue];
delta = current_time - start_time;
block_time = [sd requestBlockInterval];
request_count = [[requestCount objectForKey: @"RequestCount"] intValue];
if ( request_count >= [sd maximumRequestCount] &&
delta < [sd maximumRequestInterval] &&
delta <= block_time )
{
resp = [WOResponse responseWithRequest: _request];
[resp setStatus: 429];
return resp;
}
if (delta > block_time)
{
[cache setRequestCount: 1
forLogin: username
interval: current_time];
}
else
[cache setRequestCount: (request_count+1)
forLogin: username
interval: start_time];
}
else
{
[cache setRequestCount: 1
forLogin: username
interval: 0];
}
}
resp = [super dispatchRequest: _request];
[cache killCache];
+2
View File
@@ -21,8 +21,10 @@
*/
#include <unistd.h>
#include <sys/types.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSString.h>
#import <Foundation/NSTimeZone.h>
#import <NGObjWeb/SoApplication.h>
+5 -551
View File
@@ -1,557 +1,12 @@
3.2.2 (2016-11-23)
2.3.x (2015-MM-DD)
------------------
New features
- [core] support repetitive email alarms on tasks and events (#1053)
- [web] allow to hide center column on large screens (#3861)
- [eas] relaxed permission requirements for subscription synchronizations (#3118 and #3180)
Enhancements
- [core] added sha256-crypt and sha512-crypt password support
- [core] updated time zones to version 2016i
- [eas] now also search on senders when using EAS Search ops
- [web] allow multiple messages to be marked as seen (#3873)
- [web] use switches instead of checkboxes in Calendars module
Bug fixes
- [core] fixed condition in weekly recurrence calculator
- [core] always send IMIP messages using UTF-8
- [web] fixed mail settings persistence when sorting by arrival date
- [web] disable submit button while saving an event or a task (#3880)
- [web] disable submit button while saving a contact
- [web] fixed computation of week number
- [web] fixed and improved IMAP folder subscriptions manager (#3865)
- [web] fixed Sieve script activation when vacation start date is in the future (#3885)
- [web] fixed moving a component without the proper rights (#3889)
- [web] restored Sieve folder encoding support (#3904)
- [web] allow edition of a mailbox rights when user can administer mailbox
3.2.1 (2016-11-02)
------------------
Enhancements
- [web] add constraints to start/end dates of automatic responder (#3841)
- [web] allow a mailbox to be deleted immediately (#3875)
- [web] updated Angular to version 1.5.8
- [eas] initial support for recurring tasks EAS
- [eas] now support replied/forwarded flags using EAS (#3796)
- [core] updated time zones to version 2016h
Bug fixes
- [web] fixed tasks list when some weekdays are disabled
- [web] fixed automatic refresh of calendar view
- [web] respect SOGoSearchMinimumWordLength in contacts list editor
- [web] improved memory usage when importing very large address books
- [web] fixed progress indicator while importing cards or events and tasks
- [web] improved detection of changes in CKEditor (#3839)
- [web] fixed vCard generation for tags with no type (#3826)
- [web] only show the organizer field of an IMIP REPLY if one is defined
- [web] fixed saving the note of a card (#3849)
- [web] fixed support for recurrent tasks (#3864)
- [web] restored support for alarms in tasks
- [web] improved validation of mail account delegators
- [web] fixed auto-completion of list members (#3870)
- [web] added missing options to subscribed addressbooks (#3850)
- [web] added missing options to subscribed calendars (#3863)
- [web] fixed resource conflict error handling (403 vs 409 HTTP code) (#3837)
- [web] restored immediate deletion of messages (without moving them to the trash)
- [web] avoid mail notifications on superfluous event changes (#3790)
- [web] CKEditor: added the pastefromexcel plugin (#3854)
- [eas] improve handling of email folders without a parent
- [eas] never send IMIP reply when the "initiator" is Outlook 2013/2016
- [core] only consider SMTP addresses for AD's proxyAddresses (#3842)
- [core] sogo-tool manage-eas now works with single store mode
3.2.0 (2016-10-03)
------------------
New features
- [web] added IMAP folder subscriptions management (#255)
- [web] keyboard hotkeys (#1711, #1467, #3817)
- [eas] initial support for server-side mailbox search operations
Enhancements
- [web] don't allow a recurrence rule to end before the first occurrence
- [web] updated Angular Material to version 1.1.1
- [web] show user's name upon successful login
- [web] inserted unseen messages count and mailbox name in browser's window title
- [web] disable JavaScript theme generation when SOGoUIxDebugEnabled is set to NO
- [web] added Serbian (sr) translation - thanks to Bogdanović Bojan
- [web] added sort by arrival date in Mail module (#708)
- [web] restored "now" line in Calendar module
- [web] updated CKEditor to version 4.5.11
- [web] allow custom email address to be one of the user's profile (#3551)
- [eas] propagate message submission errors to EAS clients (#3774)
Bug fixes
- [eas] properly generate the BusyStatus for normal events
- [eas] properly escape all email and address fields
- [eas] properly generate yearly rrule
- [eas] make sure we don't sleep for too long when EAS processes need interruption
- [eas] fixed recurring events with timezones for EAS (#3822)
- [web] restored functionality to save unknown recipient emails to address book on send
- [web] fixed ripple blocking the form when submitting no values (#3808)
- [web] fixed error handling when renaming a mailbox
- [web] handle binary content transfer encoding when displaying mails
- [web] removed resize grips to short events (#3771)
- [core] strip protocol value from proxyAddresses attribute (#3182)
- [core] we now search in all domain sources for Apple Calendar
- [core] properly handle groups in Apple Calendar's delegation
- [core] fixed caching expiration of ACLs assigned to LDAP groups (#2867)
- [core] make sure new cards always have a UID (#3819)
- [core] fixed default TRANSP value when creating event
3.1.5 (2016-08-10)
------------------
New features
- [web] drag'n'drop of messages in the Mail module (#3497, #3586, #3734, #3788)
- [web] drag'n'drop of cards in the AddressBook module
- [eas] added folder merging capabilities
Enhancements
- [web] improve action progress when login in or sending a message (#3765, #3761)
- [web] don't allow to send the message while an upload is in progress
- [web] notify when successfully copied or moved some messages
- [web] restored indicator in the top banner when a vacation message (auto-reply) is active
- [web] removed animation when dragging an event to speed up rendering
- [web] expunge drafts mailbox when a draft is sent and deleted
- [web] actions of Sieve filters are now sortable
- [web] show progress indicator when refreshing events/tasks lists
- [web] updated CKEditor to version 4.5.10
Bug fixes
- [web] fixed refresh of addressbook when deleting one or many cards
- [web] reset multiple-selection mode after deleting cards, events or tasks
- [web] fixed exception when moving tasks to a different calendar
- [web] fixed printing of long mail (#3731)
- [web] fixed position of ghost block when creating an event from DnD
- [web] fixed avatar image in autocompletion
- [web] restored expunge of current mailbox when leaving the Mail module
- [web] added support for multiple description values in LDAP entries (#3750)
- [web] don't allow drag'n'drop of invitations
- [eas] fixed long GUID issue preventing sometimes synchronisation (#3460)
- [core] fixing sogo-tool backup with multi-domain configuration but domain-less logins
- [core] during event scheduling, use 409 instead of 403 so Lightning doesn't fail silently
- [core] correctly calculate recurrence exceptions when not overlapping the recurrence id
- [core] prevent invalid SENT-BY handling during event invitations (#3759)
3.1.4 (2016-07-12)
------------------
New features
- [core] new sogo-tool truncate-calendar feature (#1513, #3141)
- [eas] initial Out-of-Office support in EAS
- [oc] initial support for calendar and address book sharing with OpenChange
Enhancements
- [eas] use the preferred email identity in EAS if valid (#3698)
- [eas] handle inline attachments during EAS content generation
- [web] all batch operations can now be performed on selected messages in advanced search mode
- [web] add date picker to change date, week, or month of current Calendar view
- [web] style cancelled events in Calendar module
- [web] replace sortable library for better support with Firefox
- [web] stage-1 tuning of sgColorPicker directive
- [oc] better handling of nested attachments with OpenChange
Bug fixes
- [web] fixed crash when an attachment filename has no extension
- [web] fixed selection of transparent all-day events (#3744)
- [web] leaving the dropping area while dragging a file was blocking the mail editor
- [web] fixed scrolling of all-day events (#3190)
- [eas] handle base64 EAS protocol version
- [eas] handle missing IMAP folders from a hierarchy using EAS
3.1.3 (2016-06-22)
------------------
New features
- [core] now possible to define default Sieve filters (#2949)
- [core] now possible to set vacation message start date (#3679)
- [web] add a header and/or footer to the vacation message (#1961)
- [web] specify a custom subject for the vacation message (#685, #1447)
Enhancements
- [core] when restoring data using sogo-tool, regenerate Sieve script (#3029)
- [web] always display name of month in week view (#3724)
- [web] use a speed dial (instead of a dialog) for card/list creation
- [web] use a speed dial for event/task creation
- [web] CSS is now minified using clean-css
Bug fixes
- [core] properly handle sorted/deleted calendars (#3723)
- [core] properly handle flattened timezone definitions (#2690)
- [web] fixed generic avatar in lists (#3719)
- [web] fixed validation in Sieve filter editor
- [web] properly encode rawsource of events and tasks to avoid XSS issues (#3718)
- [web] properly encode rawsource of cards to avoid XSS issues
- [web] fixed all-day events covering a timezone change (#3457)
- [web] sgTimePicker parser now respects the user's time format and language
- [web] fixed time format when user chooses the default one
- [web] added missing delegators identities in mail editor (#3720)
- [web] honour the domain default SOGoAppointmentSendEMailNotifications (#3729)
- [web] the login module parameter is now properly restored when set as "Last used"
- [web] if cn isn't found for shared mailboxes, use email address (#3733)
- [web] fixed handling of attendees when updating an event
- [web] show tooltips over long calendar/ab names (#232)
- [web] one-click option to give all permissions for user (#1637)
- [web] never query gravatar.com when disabled
3.1.2 (2016-06-06)
------------------
Enhancements
- [web] updated Angular Material to version 1.1.0rc5
Bug fixes
- [web] fixed error handling when renaming a mailbox
- [web] fixed user removal from ACLs in Administration module (#3713)
- [web] fixed event classification icon (private/confidential) in month view (#3711)
- [web] CKEditor: added the pastefromword plugin (#2295, #3313)
- [web] fixed loading of card from global addressbooks
- [web] fixed negative offset when saving an all-day event (#3717)
3.1.1 (2016-06-02)
------------------
Enhancements
- [web] expose all email addresses in autocompletion of message editor (#3443)
- [web] Gravatar service can now be disabled (#3600)
- [web] collapsable mail accounts (#3493)
- [web] show progress indicator when loading messages and cards
- [web] display messages sizes in list of Mail module
- [web] link event's attendees email addresses to mail composer
- [web] respect SOGoSearchMinimumWordLength when searching for events or tasks
- [web] updated CKEditor to version 4.5.9
- [web] CKEditor: switched to the minimalist skin
- [web] CKEditor: added the base64image plugin
Bug fixes
- [core] strip X- tags when securing content (#3695)
- [web] fixed creation of chip on blur (sgTransformOnBlur directive)
- [web] fixed composition of new messages from Contacts module
- [web] fixed autocompletion of LDAP-based groups (#3673)
- [web] fixed month view when current month covers six weeks (#3663)
- [web] fixed negative offset when converting a regular event to an all-day event (#3655)
- [web] fixed event classification icon (private/confidential) in day/week/multicolumn views
- [web] fixed display of mailboxes list on mobiles (#3654)
- [web] restored Catalan and Slovak translations (#3687)
- [web] fixed restore of mailboxes expansion state when multiple IMAP accounts are configured
- [web] improved CSS sanitizer for HTML messages (#3700)
- [web] fixed toolbar of mail editor when sender address was too long (#3705)
- [web] fixed decoding of filename in attachments (quotes and Cyrillic characters) (#2272)
- [web] fixed recipients when replying from a message in the Sent mailbox (#2625)
- [eas] when using EAS/ItemOperations, use IMAP PEEK operation
3.1.0 (2016-05-18)
------------------
New features
- [core] new database structure options to make SOGo use a total of nine tables
- [core] new user-based rate-limiting support for all SOGo requests (#3188)
- [web] toolbar of all-day events can be expanded to display all events
- [web] added AngularJS's XSRF support (#3246)
- [web] calendars list can be reordered and filtered
- [web] user can limit the calendars view to specific week days (#1841)
Enhancements
- [web] updated Angular Material to version 1.1.0rc4
- [web] added Lithuanan (lt) translation - thanks to Mantas Liobė
- [web] added Turkish (Turkey) (tr_TR) translation - thanks to Sinan Kurşunoğlu
- [web] we now "cc" delegates during invitation updates (#3195)
- [web] new SOGoHelpURL preference to set a custom URL for SOGo help (#2768)
- [web] now able to copy/move events and also duplicate them (#3196)
- [web] improved preferences validation and now check for unsaved changes
- [web] display events and tasks priorities in list and day/week views (#3162)
- [web] style events depending on the user participation state
- [web] style transparent events (show time as free) (#3192)
- [web] improved input parsing of time picker (#3659)
- [web] restored support for Web calendars that require authentication
Bug fixes
- [core] properly escape wide characters (#3616)
- [core] avoid double-appending domains in cache for multi-domain configurations (#3614)
- [core] fixed multidomain issue with non-unique ID accross domains (#3625)
- [core] fixed bogus headers generation when stripping folded bcc header (#3664)
- [core] fixed issue with multi-value org units (#3630)
- [core] sanity checks for events with bogus timezone offsets
- [web] fixed missing columns in SELECT statements (PostgreSQL)
- [web] fixed display of ghosts when dragging events
- [web] fixed management of mail labels in Preferences module
- [web] respect super user privileges to create in any calendar and addressbook (#3533)
- [web] properly null-terminate IS8601-formatted dates (#3539)
- [web] display CC/BCC fields in message editor when initialized with values
- [web] fixed message initialization in popup window (#3583)
- [web] create chip (recipient) on blur (#3470)
- [web] fixed position of warning when JavaScript is disabled (#3449)
- [web] respect the LDAP attributes mapping in the list view
- [web] handle empty body data when forwarding mails (#3581)
- [web] show repeating events when we ask for "All" or "Future" events (#69)
- [web] show the To instead of From when we are in the Sent folder (#3547)
- [web] fixed handling of mail tags in mail viewer
- [web] avoid marking mails as read when archiving a folder (#2792)
- [web] fixed crash when sending a message with a special priority
- [web] fixed saving of a custom weekly recurrence definition
- [web] properly escape the user's display name (#3617)
- [web] avoid returning search results on objects without read permissions (#3619)
- [web] restore priority of event or task in component editor
- [web] fixed menu content visibility when printing an email (#3584)
- [web] retired CSS reset so the style of HTML messages is respected (#3582)
- [web] fixed messages archiving as zip file
- [web] adapted time picker to match changes of md calendar picker
- [web] fixed sender addresses of draft when using multiple IMAP accounts (#3577)
- [web] create a new message when clicking on a "mailto" link (#3588)
- [web] fixed handling of Web calendars option "reload on login"
- [web] add recipient chip when leaving an input field (to/cc/bcc) (#3470)
- [dav] we now handle the default classifications for tasks (#3541)
- [eas] properly unfold long mail headers (#3152)
- [eas] correctly set EAS message class for S/MIME messages (#3576)
- [eas] handle FilterType changes using EAS (#3543)
- [eas] handle Dovecot's mail_shared_explicit_inbox parameter
- [eas] prevent concurrent Sync ops from same device (#3603)
- [eas] handle EAS loop termination when SOGo is being shutdown (#3604)
- [eas] now cache heartbeat interval and folders list during Ping ops (#3606)
- [eas] sanitize non-us-ascii 7bit emails (#3592)
- [eas] properly escape organizer name (#3615)
- [eas] correctly set answered/forwarded flags during smart operations
- [eas] don't mark calendar invitations as read when fetching messages
3.0.2 (2016-03-04)
------------------
New features
- [web] show all/only this calendar
- [web] convert a message to an appointment or a task (#1722)
- [web] customizable base font size for HTML messages
- [web you can now limit the file upload size using the WOMaxUploadSize
configuration parameter (integer value in kilobytes) (#3510, #3135)
Enhancements
- [web] added Junk handling feature from v2
- [web] updated Material Icons font to version 2.1.3
- [web] don't offer forward/vacation options in filters if not enabled
- [web] mail filters are now sortable
- [web] now supports RFC6154 and NoInferiors IMAP flag
- [web] improved confirm dialogs for deletions
- [web] allow resources to prevent invitations (#3410)
- [web] warn when double-booking attendees and offer force save option
- [web] list search now displays a warning regarding the minlength constraint
- [web] loading an LDAP-based addressbook is now instantaneous when listRequiresDot is disabled (#438, #3464)
- [web] improve display of messages with many recipients
- [web] colorize categories chips in event and task viewers
- [web] initial stylesheet for printing (#3484)
- [web] updated lodash to version 4.6.1
- [i18n] updated French and Finnish translations
- [eas] now support EAS MIME truncation
Bug fixes
- [web] handle birthday dates before 1970 (#3567)
- [web] safe-guarding against bogus value coming from the quick tables
- [web] apply search filters when automatically reloading current mailbox (#3507)
- [web] fixed virtual repeater when moving up in messages list
- [web] really delete mailboxes being deleted from the Trash folder (#595, #1189, #641)
- [web] fixed address autocompletion of mail editor affecting cards list of active addressbook
- [web] fixed batched delete of components (#3516)
- [web] fixed mail draft autosave in preferences (#3519)
- [web] fixed password change (#3496)
- [web] fixed saving of notification email for calendar changes (#3522)
- [web] fixed ACL editor for authenticated users in Mail module
- [web] fixed fab button position in Calendar module (#3462)
- [web] fixed default priority of sent messages (#3542)
- [web] removed double-quotes from Chinese (Taiwan) translations that were breaking templates
- [web] fixed unseen count retrieval of nested IMAP folders
- [web] properly extract the mail column values from an SQL contacts source (#3544)
- [web] fixed incorrect date formatting when timezone was after UTC+0 (#3481, #3494)
- [web] replaced checkboxes in menu by a custom checkmark (#3557)
- [web] fixed attachments display when forwarding a message (#3560)
- [web] activate new calendar subscriptions by default
- [web] keep specified task status when not completed (#3499)
- [eas] allow EAS attachments get on 2nd-level mailboxes (#3505)
- [eas] fix EAS bday shift (#3518)
- [eas] encode CR in EAS payload (#3626)
3.0.1 (2016-02-05)
------------------
Enhancements
- [web] improved scrolling behavior when deleting a single message (#3489)
- [web] added "Move To" option for selected messages (#3477)
- [web] updated CKEditor to version 4.5.7
- [web] updated Angular Material to 1.0.5
- [web/eas] add shared/public namespaces in the list or returned folders
Bug fixes
- [web] safeguard against mailboxes with no quota (#3468)
- [web] fixed blank calendar view when selecting "Descending Order" in the sort menu
- [web] show active user's default email address instead of system email address (#3473)
- [web] fixed display of HTML tags when viewing a message raw source (#3490)
- [web] fixed IMIP accept/decline when there is only one MIME part
- [web] improved handling of IMAP connection problem in Web interface
- [web] fixed frequency parsing of recurrence rule when saving new appointment (#3472)
- [web] added support for %p in date formatting (#3480)
- [web] make sure an email is defined before trying to use it (#3488)
- [web] handle broken messages that have no date (#3498)
- [web] fixed virtual-repeater display in Webmail when a search is performed (#3500)
- [web] fixed drag'n'drop of all-day events in multicolumn view
- [eas] correctly encode filename of attachments over EAS (#3491)
3.0.0 (2016-01-27)
------------------
New features
- complete rewrite of the JavaScript frontend using Angular and AngularMaterial
- responsive design and accessible options focused on mobile devices
- horizontal 3-pane view for a better experience on large desktop screens
- new color palette and better contrast ratio as recommended by the W3C
- improved accessibility to persons with disabilities by enabling common ARIA attributes
- use of Mozilla's Fira Sans typeface
- and many more!
2.3.7 (2016-01-25)
------------------
New features
- new junk/not junk capability with generic SMTP integration
Enhancements
- newly created folders using EAS are always sync'ed by default (#3454)
- added Croatian (hr_HR) translation - thanks to Jens Riecken
Bug fixes
- now always generate invitation updates when using EAS
- rewrote the string sanitization to be 32-bit Unicode safe
- do not try to decode non-wbxml responses for debug output (#3444)
2.3.6 (2016-01-18)
------------------
New features
- now able to sync only default mail folders when using EAS
Enhancements
- Unit testing for RTFHandler
- JUnit output for sogo-tests
Bug fixes
- don't unescape twice mail folder names (#3423)
- don't consider mobile Outlook EAS clients as DAV ones (#3431)
- we now follow 301 redirects when fetching ICS calendars
- when deleting an event using EAS, properly invoke the auto-scheduling code
- do not include failure attachments (really long filenames)
- fix encoding of email subjects with non-ASCII characters
- fix appointment notification mails using SOGoEnableDomainBasedUID configuration
- fix shifts in event times on Outlook
2.3.5 (2016-01-05)
------------------
Enhancements
- return an error to openchange if mail message delivery fails
- return the requested elements on complex requests from Outlook when downloading changes
- user sources can be loaded dynamically
- unify user sources API
- updated Russian translation (#3383)
Bug fixes
- properly compute the last week number for the year (#1010)
- share calendar, tasks and contacts folders in Outlook 2013 with editor permissions
- priorize filename in Content-Disposition against name in Content-Type to get the filename of an attachment in mail
- request all contacts when there is no filter in Contacts menu in Webmail
- personal contacts working properly on Outlook
- fixes on RTF parsing used by event/contact description and mail as RTF to read non-ASCII characters:
better parsing of font table, when using a font, switch to its character set, correct parsing of
escaped characters and Unicode character command word support for unicode characters greater than 32767
- no crash resolving recipients after reconnecting LDAP connection
- avoid creation of phantom contacts in SOGo from distribution list synced from Outlook.
- accepted & updated event names are now shown correctly in Outlook
- provide safe guards in mail and calendar to avoid exceptions while syncing
2.3.4 (2015-12-15)
------------------
New features
- initial support for EAS calendar exceptions
Enhancements
- limit the maximum width of toolbar buttons (#3381)
- updated CKEditor to version 4.5.6
Bug fixes
- JavaScript exception when printing events from calendars with no assigned color (#3203)
- EAS fix for wrong charset being used (#3392)
- EAS fix on qp-encoded subjects (#3390)
- correctly handle all-day event exceptions when the master event changes
- prevent characters in calendar component UID causing issues during import process
- avoid duplicating attendees when accepting event using a different identity over CalDAV
2.3.3a (2015-11-18)
-------------------
Bug fixes
- expanded mail folders list is not saved (#3386)
- cleanup translations
2.3.3 (2015-11-11)
------------------
New features
- initial S/MIME support for EAS (#3327)
- now possible to choose which folders to sync over EAS
Enhancements
- we no longer always entirely rewrite messages for Outlook 2013 when using EAS
- support for ghosted elements on contacts over EAS
- added Macedonian (mk_MK) translation - thanks to Miroslav Jovanovic
- added Portuguese (pt) translation - thanks to Eduardo Crispim
Bug fixes
- numerous EAS fixes when connections are dropped before the EAS client receives the response (#3058, #2849)
- correctly handle the References header over EAS (#3365)
- make sure English is always used when generating Date headers using EAS (#3356)
- don't escape quoted strings during versit generation
- we now return all cards when we receive an empty addressbook-query REPORT
- avoid crash when replying to a mail with no recipients (#3359)
- inline images sent from SOGo webmail are not displayed in Mozilla Thunderbird (#3271)
- prevent postal address showing on single line over EAS (#2614)
- display missing events when printing working hours only
- fix corner case making server crash when syncing hard deleted messages when clear offline items was set up (Zentyal)
- avoid infinite Outlook client loops trying to set read flag when it is already set (Zentyal)
- avoid crashing when calendar metadata is missing in the cache (Zentyal)
- fix recurrence pattern event corner case created by Mozilla Thunderbird which made server crash (Zentyal)
- fix corner case that removes attachments on sending messages from Outlook (Zentyal)
- freebusy on web interface works again in multidomain environments (Zentyal)
- fix double creation of folders in Outlook when the folder name starts with a digit (Zentyal)
- avoid crashing Outlook after setting a custom view in a calendar folder (Zentyal)
- handle emails having an attachment as their content
- fixed JavaScript syntax error in attendees editor
- fixed wrong comparison of meta vs. META tag in HTML mails
- fixed popup menu position when moved to the left (#3381)
- fixed dialog position when at the bottom of the window (#2646, #3378)
2.3.2 (2015-09-16)
------------------
Enhancements
- improved EAS speed and memory usage, avoiding many IMAP LIST commands (#3294)
- improved EAS speed during initial syncing of large mailboxes (#3293)
- updated CKEditor to version 4.5.3
Bug fixes
- fixed display of whitelisted attendees in Preferences window on Firefox (#3285)
- non-latin subfolder names are displayed correctly on Outlook (Zentyal)
- fixed several sync issues on environments with multiple users (Zentyal)
- folders from other users will no longer appear on your Outlook (Zentyal)
- use right auth in multidomain environments in contacts and calendar from Outlook (Zentyal)
- session fix when SOGoEnableDomainBasedUID is enabled but logins are domain-less
- less sync issues when setting read flag (Zentyal)
- attachments with non-latin filenames sent by Outlook are now received (Zentyal)
- support attachments from more mail clients (Zentyal)
- avoid conflicting message on saving a draft mail (Zentyal)
- less conflicting messages in Outlook while moving messages between folders (Zentyal)
- start/end shifting by 1 hour due to timezone change on last Sunday of October 2015 (#3344)
- fixed localization of calendar categories with empty profile (#3295)
- fixed options availability in contextual menu of Contacts module (#3342)
- Non-latin subfolder names are displayed correctly on Outlook (Zentyal)
- Fixed several sync issues on environments with multiple users (Zentyal)
- Folders from other users will no longer appear on your Outlook (Zentyal)
- Use right auth in multidomain environments in contacts and calendar from Outlook (Zentyal)
2.3.1 (2015-07-23)
------------------
@@ -564,7 +19,6 @@ Enhancements
- added create-folder subcommand to sogo-tool to create contact and calendar folders
- group mail addresses can be used as recipient in Outlook
- added 'ActiveSync' module constraints
- updated CKEditor to version 4.5.1
- added Slovenian translation - thanks to Jens Riecken
- added Chinese (Taiwan) translation
+1 -5
View File
@@ -78,9 +78,6 @@ $(SOGOBACKEND)_OBJC_FILES += \
MAPIStoreGCSMessage.m \
MAPIStoreGCSMessageTable.m \
\
MAPIStoreCalTaskFolder.m \
MAPIStoreCalTaskMessage.m \
\
MAPIStoreCalendarAttachment.m \
MAPIStoreCalendarContext.m \
MAPIStoreCalendarFolder.m \
@@ -148,8 +145,7 @@ $(DBMSGREADER_TOOL)_LIB_DIRS += \
-L../SoObjects/SOGo/SOGo.framework/sogo -lSOGo \
-L../SOPE/GDLContentStore/obj/ -lGDLContentStore \
-L../SOPE/NGCards/obj/ -lNGCards \
-lNGObjWeb \
$(LIBMAPI_LIBS)
-lNGObjWeb
TEST_TOOL_NAME += $(PLREADER_TOOL) $(DBMSGREADER_TOOL)
+97 -100
View File
@@ -24,7 +24,6 @@
#define MAPISTORECALENDARWRAPPER_H
#import <NGCards/iCalPerson.h>
#import <NGCards/iCalTimeZone.h>
#import <Appointments/iCalEntityObject+SOGo.h>
#import "MAPIStoreObjectProxy.h"
@@ -43,7 +42,7 @@
iCalCalendar *calendar;
iCalEvent *firstEvent;
iCalEvent *event;
iCalTimeZone *timeZone;
NSTimeZone *timeZone;
SOGoUser *user;
NSString *senderEmail;
NSData *globalObjectId;
@@ -58,119 +57,117 @@
+ (id) wrapperWithICalEvent: (iCalEvent *) newEvent
andUser: (SOGoUser *) newUser
andSenderEmail: (NSString *) newSenderEmail
inTimeZone: (NSTimeZone *) newTimeZone
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo;
- (id) initWithICalEvent: (iCalEvent *) newEvent
andUser: (SOGoUser *) newUser
andSenderEmail: (NSString *) newSenderEmail
inTimeZone: (NSTimeZone *) newTimeZone
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo;
/* getters */
- (void) fillMessageData: (struct mapistore_message *) dataPtr
inMemCtx: (TALLOC_CTX *) memCtx;
- (NSString *) creator;
- (NSString *) owner;
- (NSUInteger) sensitivity;
- (int) getPidTagSenderEmailAddress: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagSenderAddressType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagSenderName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagSenderEntryId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagSenderEmailAddress: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagSenderAddressType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagSenderName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagSenderEntryId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagReceivedByAddressType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagReceivedByEmailAddress: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagReceivedByName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagReceivedByEntryId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagReceivedByAddressType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagReceivedByEmailAddress: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagReceivedByName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagReceivedByEntryId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagIconIndex: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagOwnerAppointmentId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidMeetingType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagStartDate: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidAppointmentSequence: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidAppointmentStateFlags: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidResponseStatus: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidAppointmentStartWhole: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidCommonStart: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagEndDate: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidAppointmentEndWhole: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidCommonEnd: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidAppointmentDuration: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidAppointmentSubType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidBusyStatus: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidIndentedBusyStatus: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagNormalizedSubject: (void **) data // SUMMARY
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidLocation: (void **) data // LOCATION
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidPrivate: (void **) data // private (bool), should depend on CLASS and permissions
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagSensitivity: (void **) data // not implemented, depends on CLASS
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagImportance: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagBody: (void **) data
- (int) getPidTagIconIndex: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagOwnerAppointmentId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidMeetingType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagStartDate: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidAppointmentSequence: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidAppointmentStateFlags: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidIsRecurring: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidRecurring: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidAppointmentRecur: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidGlobalObjectId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidCleanGlobalObjectId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidServerProcessed: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidServerProcessingActions: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidAppointmentReplyTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidResponseStatus: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidAppointmentStartWhole: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidCommonStart: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagEndDate: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidAppointmentEndWhole: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidCommonEnd: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidAppointmentDuration: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidAppointmentSubType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidBusyStatus: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidIndentedBusyStatus: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagNormalizedSubject: (void **) data // SUMMARY
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidLocation: (void **) data // LOCATION
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidPrivate: (void **) data // private (bool), should depend on CLASS and permissions
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagSensitivity: (void **) data // not implemented, depends on CLASS
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagImportance: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagBody: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidIsRecurring: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidRecurring: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidAppointmentRecur: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidGlobalObjectId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidCleanGlobalObjectId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidServerProcessed: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidServerProcessingActions: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidAppointmentReplyTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
/* reminders */
- (enum mapistore_error) getPidLidReminderSet: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidReminderDelta: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidReminderTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidReminderSignalTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidReminderOverride: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidReminderType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidReminderPlaySound: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidLidReminderFileParameter: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidReminderSet: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidReminderDelta: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidReminderTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidReminderSignalTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidReminderOverride: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidReminderType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidReminderPlaySound: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidReminderFileParameter: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
@end
File diff suppressed because it is too large. Load diff
+7 -7
View File
@@ -36,13 +36,13 @@
- (void) setAID: (uint32_t) newAID;
- (uint32_t) AID;
- (enum mapistore_error) openEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
withMID: (uint64_t *) mid
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) createEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) openEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
withMID: (uint64_t *) mid
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) createEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
inMemCtx: (TALLOC_CTX *) memCtx;
/* helpers */
- (NSData *) mimeAttachTag;
+15 -15
View File
@@ -67,40 +67,40 @@
return mimeAttachTag;
}
- (enum mapistore_error) getPidTagMid: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagMid: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongLongValue (memCtx, [container objectId]);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachNumber: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachNumber: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, aid);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagRenderingPosition: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagRenderingPosition: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, 0xffffffff);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAccessLevel: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAccessLevel: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getLongZero: data inMemCtx: memCtx];
}
- (enum mapistore_error) openEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
withMID: (uint64_t *) mid
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
inMemCtx: (TALLOC_CTX *) memCtx
- (int) openEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
withMID: (uint64_t *) mid
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
inMemCtx: (TALLOC_CTX *) memCtx
{
MAPIStoreEmbeddedMessage *attMessage;
struct mapistore_message *mapistoreMsg;
@@ -118,9 +118,9 @@
return (attMessage ? MAPISTORE_SUCCESS : MAPISTORE_ERROR);
}
- (enum mapistore_error) createEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
inMemCtx: (TALLOC_CTX *) memCtx
- (int) createEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
inMemCtx: (TALLOC_CTX *) memCtx
{
MAPIStoreEmbeddedMessage *attMessage;
struct mapistore_message *mapistoreMsg;
-3
View File
@@ -46,9 +46,6 @@
forURL: (NSURL *) server
forceRenew: (BOOL) renew;
- (NSString *) passwordInContext: (WOContext *) context;
@end
#endif /* MAPISTOREAUTHENTICATOR_H */
-4
View File
@@ -72,8 +72,4 @@
return imapPassword;
}
- (NSString *) passwordInContext: (WOContext *) context
{
return password;
}
@end
-35
View File
@@ -1,35 +0,0 @@
/* MAPIStoreCalTaskFolder.h - this file is part of SOGo
*
* Copyright (C) 2016 Enrique J. Hernandez
*
* Author: Enrique J. Hernandez <ejhernandez@zentyal.com>
*
* 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 MAPISTORECALTASKFOLDER_H
#define MAPISTORECALTASKFOLDER_H
#import "MAPIStoreGCSFolder.h"
/* This class is intended to share code between Calendar and Tasks as
of nowadays share the table */
@interface MAPIStoreCalTaskFolder : MAPIStoreGCSFolder
@end
#endif /* MAPISTORECALTASKFOLDER_H */
-101
View File
@@ -1,101 +0,0 @@
/* MAPIStoreCalTaskFolder.m - this file is part of SOGo
*
* Copyright (C) 2016 Enrique J. Hernandez
*
* Author: Enrique J. Hernandez <ejhernandez@zentyal.com>
*
* 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 3, 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/NSSet.h>
#import <Foundation/NSString.h>
#import <SOGo/SOGoPermissions.h>
#import "MAPIStoreCalTaskFolder.h"
@implementation MAPIStoreCalTaskFolder
- (NSArray *) expandRoles: (NSArray *) roles
{
static NSDictionary *rolesMap = nil;
NSArray *subRoles;
NSMutableSet *expandedRoles;
NSString *role, *subRole;
NSUInteger i, max, j;
if (!rolesMap)
{
/* Build the map of array permissions */
rolesMap = [[NSDictionary alloc] initWithObjects: [NSArray arrayWithObjects:
[NSArray arrayWithObjects: SOGoCalendarRole_PublicDAndTViewer,
SOGoCalendarRole_PublicViewer,
SOGoCalendarRole_PublicResponder,
SOGoCalendarRole_PublicModifier, nil],
[NSArray arrayWithObjects: SOGoCalendarRole_ConfidentialDAndTViewer,
SOGoCalendarRole_ConfidentialViewer,
SOGoCalendarRole_ConfidentialResponder,
SOGoCalendarRole_ConfidentialModifier, nil],
[NSArray arrayWithObjects: SOGoCalendarRole_PrivateDAndTViewer,
SOGoCalendarRole_PrivateViewer,
SOGoCalendarRole_PrivateResponder,
SOGoCalendarRole_PrivateModifier, nil],
[NSArray arrayWithObjects: SOGoCalendarRole_ComponentDAndTViewer,
SOGoCalendarRole_ComponentViewer,
SOGoCalendarRole_ComponentResponder,
SOGoCalendarRole_ComponentModifier, nil],
nil]
forKeys: [NSArray arrayWithObjects: @"Public", @"Confidential", @"Private",
@"Component", nil]];
}
max = [roles count];
expandedRoles = [NSMutableSet set];
for (i = 0; i < max; i++)
{
role = [roles objectAtIndex: i];
subRoles = nil;
if ([role hasPrefix: @"Public"])
subRoles = [rolesMap objectForKey: @"Public"];
else if ([role hasPrefix: @"Confidential"])
subRoles = [rolesMap objectForKey: @"Confidential"];
else if ([role hasPrefix: @"Private"])
subRoles = [rolesMap objectForKey: @"Private"];
else if ([role hasPrefix: @"Component"])
subRoles = [rolesMap objectForKey: @"Component"];
if (subRoles)
{
for (j = 0; j < [subRoles count]; j++)
{
subRole = [subRoles objectAtIndex: j];
[expandedRoles addObject: subRole];
if ([subRole isEqualToString: role])
break;
}
}
else
{
[expandedRoles addObject: role];
}
}
return [expandedRoles allObjects];
}
@end
-40
View File
@@ -1,40 +0,0 @@
/* MAPIStoreCalTaskMessage.h - this file is part of SOGo
*
* Copyright (C) 2016 Enrique J. Hernandez
*
* Author: Enrique J. Hernandez <ejhernandez@zentyal.com>
*
* 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 MAPISTORECALTASKMESSAGE_H
#define MAPISTORECALTASKMESSAGE_H
#import "MAPIStoreGCSMessage.h"
/* This class is intended to share common logic for Calendar and Tasks
as of today they are stored in the same table. This is relevant for
permissions */
@interface MAPIStoreCalTaskMessage : MAPIStoreGCSMessage
{
}
/* Get the sensitivity (access class) from a message */
- (NSUInteger) sensitivity;
@end
#endif /* MAPISTORECALTASKMESSAGE_H */
-107
View File
@@ -1,107 +0,0 @@
/* MAPIStoreCalTaskMessage.h - this file is part of SOGo
*
* Copyright (C) 2016 Enrique J. Hernandez
*
* Author: Enrique J. Hernandez <ejhernandez@zentyal.com>
*
* 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/NSString.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <SOGo/SOGoPermissions.h>
#import "MAPIStoreFolder.h"
#import "MAPIStoreCalTaskMessage.h"
@implementation MAPIStoreCalTaskMessage
/* It must be implemented by subclasses */
- (NSUInteger) sensitivity
{
[self subclassResponsibility: _cmd];
return 0;
}
- (NSArray *) expandRoles: (NSArray *) roles
{
return [container expandRoles: roles];
}
- (BOOL) subscriberCanModifyMessage
{
BOOL rc;
NSArray *roles;
roles = [self activeUserRoles];
if (isNew)
rc = [roles containsObject: SOGoRole_ObjectCreator];
else
rc = ([roles containsObject: SOGoCalendarRole_ComponentModifier]
|| [roles containsObject: SOGoCalendarRole_ComponentResponder]);
/* Check if the message is owned and it has permission to edit it */
if (!rc && [roles containsObject: MAPIStoreRightEditOwn])
{
NSString *currentUser;
currentUser = [[container context] activeUser];
rc = [currentUser isEqual: [self ownerUser]];
}
if (!rc)
{
NSUInteger sensitivity;
/* Get sensitivity of the message to check if the user can
modify the message */
sensitivity = [self sensitivity];
/* FIXME: Use OpenChange constant names */
switch (sensitivity)
{
case 0: /* PUBLIC */
rc = [roles containsObject: SOGoCalendarRole_PublicModifier]
|| [roles containsObject: SOGoCalendarRole_PublicResponder];
break;
case 1: /* PERSONAL */
case 2: /* PRIVATE */
rc = [roles containsObject: SOGoCalendarRole_PrivateModifier]
|| [roles containsObject: SOGoCalendarRole_PrivateResponder];
break;
case 3: /* CONFIDENTIAL */
rc = [roles containsObject: SOGoCalendarRole_ConfidentialModifier]
|| [roles containsObject: SOGoCalendarRole_ConfidentialResponder];
}
}
return rc;
}
- (BOOL) subscriberCanReadMessage
{
NSArray *roles;
roles = [self activeUserRoles];
return ([roles containsObject: SOGoCalendarRole_ComponentViewer]
|| [roles containsObject: SOGoCalendarRole_ComponentDAndTViewer]
|| [self subscriberCanModifyMessage]);
}
@end
+22 -22
View File
@@ -94,64 +94,64 @@
flattenedValuesForKey: @""];
}
- (enum mapistore_error) getPidTagAttachmentHidden: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
- (int) getPidTagAttachmentHidden: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
return [self getYes: data inMemCtx: localMemCtx];
}
- (enum mapistore_error) getPidTagAttachmentFlags: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
- (int) getPidTagAttachmentFlags: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
*data = MAPILongValue (localMemCtx, 0x00000002); /* afException */
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachmentLinkId: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
- (int) getPidTagAttachmentLinkId: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
return [self getLongZero: data inMemCtx: localMemCtx];
}
- (enum mapistore_error) getPidTagAttachFlags: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
- (int) getPidTagAttachFlags: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
return [self getLongZero: data inMemCtx: localMemCtx];
}
- (enum mapistore_error) getPidTagAttachMethod: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
- (int) getPidTagAttachMethod: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
*data = MAPILongValue (localMemCtx, afEmbeddedMessage);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachEncoding: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
- (int) getPidTagAttachEncoding: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
*data = [[NSData data] asBinaryInMemCtx: localMemCtx];
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
- (int) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
*data = [@"Untitled" asUnicodeInMemCtx: localMemCtx];
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachmentContactPhoto: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachmentContactPhoto: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagExceptionReplaceTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagExceptionReplaceTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
NSCalendarDate *dateValue;
@@ -178,8 +178,8 @@
return rc;
}
- (enum mapistore_error) getPidTagExceptionStartTime: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
- (int) getPidTagExceptionStartTime: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
enum mapistore_error rc;
NSCalendarDate *dateValue;
@@ -205,8 +205,8 @@
return rc;
}
- (enum mapistore_error) getPidTagExceptionEndTime: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
- (int) getPidTagExceptionEndTime: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
enum mapistore_error rc;
NSCalendarDate *dateValue;
+22 -22
View File
@@ -58,6 +58,7 @@
wrapperWithICalEvent: [newContainer event]
andUser: [userContext sogoUser]
andSenderEmail: nil
inTimeZone: [userContext timeZone]
withConnectionInfo: [context connectionInfo]];
[self addProxy: appointmentWrapper];
}
@@ -89,73 +90,73 @@
*dataPtr = msgData;
}
- (enum mapistore_error) getPidTagMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = talloc_strdup (memCtx, "IPM.OLE.CLASS.{00061055-0000-0000-C000-000000000046}");
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagMessageFlags: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagMessageFlags: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, MSGFLAG_UNMODIFIED);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagProcessed: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagProcessed: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getYes: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagResponseRequested: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagResponseRequested: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getYes: data inMemCtx: memCtx];
}
/* discarded properties */
- (enum mapistore_error) getPidLidAppointmentLastSequence: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidLidAppointmentLastSequence: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidLidMeetingWorkspaceUrl: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidLidMeetingWorkspaceUrl: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidLidContacts: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidLidContacts: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidTagSensitivity: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagSensitivity: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidLidPrivate: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidLidPrivate: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidNameKeywords: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidNameKeywords: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidLidFExceptionalBody: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidLidFExceptionalBody: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];
}
@@ -208,7 +209,6 @@
[[container event] updateFromMAPIProperties: properties
inUserContext: [self userContext]
withActiveUser: activeUser
isNew: NO
inMemCtx: memCtx];
}
+2 -2
View File
@@ -23,9 +23,9 @@
#ifndef MAPISTORECALENDARFOLDER_H
#define MAPISTORECALENDARFOLDER_H
#import "MAPIStoreCalTaskFolder.h"
#import "MAPIStoreGCSFolder.h"
@interface MAPIStoreCalendarFolder : MAPIStoreCalTaskFolder
@interface MAPIStoreCalendarFolder : MAPIStoreGCSFolder
@end
+18 -43
View File
@@ -77,13 +77,6 @@
- (NSArray *) rolesForExchangeRights: (uint32_t) rights
{
/* Limitations
Following rights are not supported by SOGo specifically:
- CreateSubfolders: No calendar subfolders
- FolderVisible: It is inferred by other rights when extracting
*/
NSMutableArray *roles;
roles = [NSMutableArray arrayWithCapacity: 6];
@@ -91,35 +84,26 @@
[roles addObject: SOGoRole_ObjectCreator];
if (rights & RightsDeleteAll)
[roles addObject: SOGoRole_ObjectEraser];
if (rights & RightsDeleteOwn)
[roles addObject: MAPIStoreRightDeleteOwn];
if (rights & RightsEditAll)
{
[roles addObject: SOGoCalendarRole_PublicModifier];
[roles addObject: SOGoCalendarRole_PrivateModifier];
[roles addObject: SOGoCalendarRole_ConfidentialModifier];
}
if (rights & RightsEditOwn)
[roles addObject: MAPIStoreRightEditOwn];
if (rights & RightsReadItems)
else if (rights & RightsReadItems)
{
[roles addObject: SOGoCalendarRole_PublicViewer];
[roles addObject: SOGoCalendarRole_PrivateViewer];
[roles addObject: SOGoCalendarRole_ConfidentialViewer];
}
if (rights & RightsFreeBusySimple)
[roles addObject: SOGoCalendarRole_PublicDAndTViewer];
{
[roles addObject: SOGoCalendarRole_PublicDAndTViewer];
}
if (rights & RightsFreeBusyDetailed)
[roles addObject: SOGoCalendarRole_ConfidentialDAndTViewer];
if (rights & RightsFolderOwner)
[roles addObject: MAPIStoreRightFolderOwner];
if (rights & RightsFolderContact)
[roles addObject: MAPIStoreRightFolderContact];
{
[roles addObject: SOGoCalendarRole_ConfidentialDAndTViewer];
}
// [self logWithFormat: @"roles for rights %.8x = (%@)", rights, roles];
@@ -133,36 +117,27 @@
if ([roles containsObject: SOGoRole_ObjectCreator])
rights |= RightsCreateItems;
if ([roles containsObject: SOGoRole_ObjectEraser])
rights |= RightsDeleteAll | RightsDeleteOwn;
rights |= RightsDeleteAll;
if ([roles containsObject: SOGoCalendarRole_PublicModifier]
&& [roles containsObject: SOGoCalendarRole_PrivateModifier]
&& [roles containsObject: SOGoCalendarRole_ConfidentialModifier])
rights |= RightsReadItems | RightsEditAll | RightsEditOwn | RightsFreeBusySimple | RightsFreeBusyDetailed;
rights |= RightsReadItems | RightsEditAll;
else if ([roles containsObject: SOGoCalendarRole_PublicViewer]
&& [roles containsObject: SOGoCalendarRole_PrivateViewer]
&& [roles containsObject: SOGoCalendarRole_ConfidentialViewer])
rights |= RightsReadItems;
if ([roles containsObject: MAPIStoreRightEditOwn])
rights |= RightsEditOwn;
if ([roles containsObject: MAPIStoreRightDeleteOwn])
rights |= RightsDeleteOwn;
// We have to set by hand other rights as only the highest role is returned
// See SOGoAppointmentFolder.m:aclsForUser for details
rights |= RightsReadItems | RightsFreeBusySimple | RightsFreeBusyDetailed;
if ([roles containsObject: SOGoCalendarRole_PublicDAndTViewer])
rights |= RightsFreeBusySimple;
if ([roles containsObject: SOGoCalendarRole_ConfidentialDAndTViewer])
rights |= RightsFreeBusySimple | RightsFreeBusyDetailed;
rights |= RightsFreeBusyDetailed;
if ((rights & RightsReadItems) != 0 || (rights & RightsCreateItems) != 0 || (rights & RightsDeleteAll) != 0)
if (rights != 0)
rights |= RoleNone; /* actually "folder visible" */
if ([roles containsObject: MAPIStoreRightFolderOwner])
rights |= RightsFolderOwner | RoleNone;
if ([roles containsObject: MAPIStoreRightFolderContact])
rights |= RightsFolderContact;
// [self logWithFormat: @"rights for roles (%@) = %.8x", roles, rights];
return rights;
@@ -207,16 +182,16 @@
[(SOGoAppointmentFolder *) sogoObject aclSQLListingFilter]];
}
- (enum mapistore_error) getPidTagContainerClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagContainerClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"IPF.Appointment" asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagDefaultPostMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagDefaultPostMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"IPM.Appointment" asUnicodeInMemCtx: memCtx];
+2 -2
View File
@@ -23,13 +23,13 @@
#ifndef MAPISTORECALENDARMESSAGE_H
#define MAPISTORECALENDARMESSAGE_H
#import "MAPIStoreCalTaskMessage.h"
#import "MAPIStoreGCSMessage.h"
@class iCalCalendar;
@class iCalEvent;
@class MAPIStoreAppointmentWrapper;
@interface MAPIStoreCalendarMessage : MAPIStoreCalTaskMessage
@interface MAPIStoreCalendarMessage : MAPIStoreGCSMessage
{
iCalCalendar *calendar;
iCalEvent *masterEvent;
+33 -23
View File
@@ -197,6 +197,7 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
= [MAPIStoreAppointmentWrapper wrapperWithICalEvent: masterEvent
andUser: [userContext sogoUser]
andSenderEmail: nil
inTimeZone: [userContext timeZone]
withConnectionInfo: [context connectionInfo]];
[self addProxy: appointmentWrapper];
}
@@ -228,8 +229,8 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
/* getters */
- (enum mapistore_error) getPidTagMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
SOGoUser *owner;
@@ -242,8 +243,8 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidLidSideEffects: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidLidSideEffects: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx,
seOpenToDelete | seOpenToCopy | seOpenToMove
@@ -252,7 +253,7 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagProcessed: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagProcessed: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getYes: data inMemCtx: memCtx];
}
@@ -347,8 +348,8 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
*dataPtr = msgData;
}
- (enum mapistore_error) getPidTagResponseRequested: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagResponseRequested: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getYes: data inMemCtx: memCtx];
}
@@ -358,8 +359,8 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
MAPIStoreMessage base class, then the proxy method is not reached
(see MAPIStoreObject).
*/
- (enum mapistore_error) getPidTagNormalizedSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagNormalizedSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
MAPIStoreAppointmentWrapper *appointmentWrapper;
@@ -370,8 +371,8 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidTagSensitivity: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagSensitivity: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
MAPIStoreAppointmentWrapper *appointmentWrapper;
@@ -382,8 +383,8 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
return [self getLongZero: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagImportance: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagImportance: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
MAPIStoreAppointmentWrapper *appointmentWrapper;
@@ -528,19 +529,29 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
ASSIGN (sogoObject, newObject);
}
- (NSUInteger) sensitivity
- (BOOL) subscriberCanReadMessage
{
return [[self _appointmentWrapper] sensitivity];
NSArray *roles;
roles = [self activeUserRoles];
return ([roles containsObject: SOGoCalendarRole_ComponentViewer]
|| [roles containsObject: SOGoCalendarRole_ComponentDAndTViewer]
|| [self subscriberCanModifyMessage]);
}
- (NSString *) creator
- (BOOL) subscriberCanModifyMessage
{
return [[self _appointmentWrapper] creator];
}
BOOL rc;
NSArray *roles = [self activeUserRoles];
- (NSString *) owner
{
return [[self _appointmentWrapper] owner];
if (isNew)
rc = [roles containsObject: SOGoRole_ObjectCreator];
else
rc = ([roles containsObject: SOGoCalendarRole_ComponentModifier]
|| [roles containsObject: SOGoCalendarRole_ComponentResponder]);
return rc;
}
- (void) _updateAttachedEvents
@@ -622,7 +633,6 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
[masterEvent updateFromMAPIProperties: properties
inUserContext: [self userContext]
withActiveUser: activeUser
isNew: isNew
inMemCtx: memCtx];
[self _updateAttachedEvents];
[[self userContext] activate];
@@ -661,7 +671,7 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
return newAttachment;
}
- (enum mapistore_error) setReadFlag: (uint8_t) flag
- (int) setReadFlag: (uint8_t) flag
{
return MAPISTORE_SUCCESS;
}
+24 -24
View File
@@ -92,52 +92,52 @@
return [container lastModificationTime];
}
- (enum mapistore_error) getPidTagAttachEncoding: (void **) data inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagAttachEncoding: (void **) data inMemCtx: (TALLOC_CTX *) memCtx;
{
*data = [[NSData data] asBinaryInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachFlags: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachFlags: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getLongZero: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagAttachmentFlags: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachmentFlags: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getLongZero: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagAttachmentHidden: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachmentHidden: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagAttachmentLinkId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachmentLinkId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getLongZero: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagAttachMethod: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachMethod: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, 0x00000001);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachmentContactPhoto: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachmentContactPhoto: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getYes: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagAttachDataBinary: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachDataBinary: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
if (!photoData)
ASSIGN (photoData,
@@ -148,8 +148,8 @@
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachSize: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachSize: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
if (!photoData)
ASSIGN (photoData,
@@ -160,16 +160,16 @@
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachExtension: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachExtension: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[self fileExtension] asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachLongFilename: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachLongFilename: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSString *filename;
@@ -181,15 +181,15 @@
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachFilename: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachFilename: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidTagAttachLongFilename: data
inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidTagAttachLongFilename: data inMemCtx: memCtx];
}
+5 -34
View File
@@ -74,34 +74,18 @@
- (NSArray *) rolesForExchangeRights: (uint32_t) rights
{
/* Limitations
Following rights are not supported by SOGo specifically:
- CreateSubfolders: No contacts subfolders
- FolderVisible: It is inferred by other rights when extracting
*/
NSMutableArray *roles;
roles = [NSMutableArray arrayWithCapacity: 8];
roles = [NSMutableArray arrayWithCapacity: 6];
if (rights & RightsCreateItems)
[roles addObject: SOGoRole_ObjectCreator];
if (rights & RightsDeleteAll)
[roles addObject: SOGoRole_ObjectEraser];
if (rights & RightsDeleteOwn)
[roles addObject: MAPIStoreRightDeleteOwn];
if (rights & RightsEditAll)
[roles addObject: SOGoRole_ObjectEditor];
if (rights & RightsEditOwn)
[roles addObject: MAPIStoreRightEditOwn];
if (rights & RightsReadItems)
[roles addObject: SOGoRole_ObjectViewer];
if (rights & RightsFolderOwner)
[roles addObject: MAPIStoreRightFolderOwner];
if (rights & RightsFolderContact)
[roles addObject: MAPIStoreRightFolderContact];
return roles;
}
@@ -111,28 +95,15 @@
if ([roles containsObject: SOGoRole_ObjectCreator])
rights |= RightsCreateItems;
if ([roles containsObject: SOGoRole_ObjectEraser])
rights |= RightsDeleteAll | RightsDeleteOwn;
else if ([roles containsObject: MAPIStoreRightDeleteOwn])
rights |= RightsDeleteOwn;
rights |= RightsDeleteAll;
if ([roles containsObject: SOGoRole_ObjectEditor])
rights |= RightsEditAll | RightsEditOwn;
else if ([roles containsObject: MAPIStoreRightEditOwn])
rights |= RightsEditOwn;
rights |= RightsEditAll;
if ([roles containsObject: SOGoRole_ObjectViewer])
rights |= RightsReadItems;
if (rights != 0)
rights |= RoleNone; /* actually "folder visible" */
if ([roles containsObject: MAPIStoreRightFolderOwner])
rights |= RightsFolderOwner | RoleNone;
if ([roles containsObject: MAPIStoreRightFolderContact])
rights |= RightsFolderContact;
return rights;
}
@@ -146,8 +117,8 @@
return [[self activeUserRoles] containsObject: SOGoRole_ObjectViewer];
}
- (enum mapistore_error) getPidTagDefaultPostMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagDefaultPostMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"IPM.Contact" asUnicodeInMemCtx: memCtx];
File diff suppressed because it is too large. Load diff
+9 -9
View File
@@ -72,10 +72,10 @@
forUser: (NSString *) username
withRole: (enum mapistore_context_role) role;
+ (enum mapistore_error) openContext: (MAPIStoreContext **) contextPtr
withURI: (const char *) newUri
connectionInfo: (struct mapistore_connection_info *) newConnInfo
andTDBIndexing: (struct indexing_context *) indexing;
+ (int) openContext: (MAPIStoreContext **) contextPtr
withURI: (const char *) newUri
connectionInfo: (struct mapistore_connection_info *) newConnInfo
andTDBIndexing: (struct indexing_context *) indexing;
- (id) initFromURL: (NSURL *) newUri
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo
@@ -91,11 +91,11 @@
// - (id) lookupObject: (NSString *) objectURLString;
/* backend methods */
- (enum mapistore_error) getPath: (char **) path
ofFMID: (uint64_t) fmid
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getRootFolder: (MAPIStoreFolder **) folderPtr
withFID: (uint64_t) fmid;
- (int) getPath: (char **) path
ofFMID: (uint64_t) fmid
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getRootFolder: (MAPIStoreFolder **) folderPtr
withFID: (uint64_t) fmid;
/* util methods */
- (NSString *) extractChildNameFromURL: (NSString *) childURL
+35 -68
View File
@@ -212,16 +212,16 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
return completeURL;
}
+ (enum mapistore_error) openContext: (MAPIStoreContext **) contextPtr
withURI: (const char *) newUri
connectionInfo: (struct mapistore_connection_info *) newConnInfo
andTDBIndexing: (struct indexing_context *) indexing
+ (int) openContext: (MAPIStoreContext **) contextPtr
withURI: (const char *) newUri
connectionInfo: (struct mapistore_connection_info *) newConnInfo
andTDBIndexing: (struct indexing_context *) indexing
{
MAPIStoreContext *context;
Class contextClass;
NSString *module;
NSURL *baseURL;
enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND;
int rc = MAPISTORE_ERR_NOT_FOUND;
context = nil;
@@ -338,11 +338,11 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
return activeUser;
}
- (enum mapistore_error) getPath: (char **) path
ofFMID: (uint64_t) fmid
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPath: (char **) path
ofFMID: (uint64_t) fmid
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
int rc;
NSString *objectURL, *url;
url = [contextUrl absoluteString];
@@ -379,8 +379,8 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
{
}
- (enum mapistore_error) getRootFolder: (MAPIStoreFolder **) folderPtr
withFID: (uint64_t) newFid
- (int) getRootFolder: (MAPIStoreFolder **) folderPtr
withFID: (uint64_t) newFid
{
enum mapistore_error rc;
MAPIStoreFolder *baseFolder;
@@ -438,16 +438,8 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
mapiStoreObjectWithSOGoObject: currentFolder
inContainer: nil];
[baseFolder setContext: self];
if ([[userContext sogoUser] isEqual: activeUser]
|| [baseFolder subscriberCanReadMessages])
{
*folderPtr = baseFolder;
rc = MAPISTORE_SUCCESS;
}
else
rc = MAPISTORE_ERR_DENIED;
*folderPtr = baseFolder;
rc = MAPISTORE_SUCCESS;
}
else if ([[userContext sogoUser] isEqual: activeUser])
rc = MAPISTORE_ERR_NOT_FOUND;
@@ -502,11 +494,8 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
mappingId = [mapping idFromURL: childURL];
if (mappingId == NSNotFound)
{
const char *owner;
[self logWithFormat: @"No id exist yet for '%@', requesting one", childURL];
owner = [[userContext username] UTF8String];
ret = mapistore_indexing_get_new_folderID_as_user (connInfo->mstore_ctx, owner, &mappingId);
ret = mapistore_indexing_get_new_folderID (connInfo->mstore_ctx, &mappingId);
if (ret == MAPISTORE_SUCCESS)
[mapping registerURL: childURL withID: mappingId];
else
@@ -517,56 +506,36 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
return mappingId;
}
/* Get new change number from openchange db interface using
resource's owner user */
- (uint64_t) getNewChangeNumber
{
const char *owner;
enum MAPISTATUS retval;
uint64_t newVersionNumber;
owner = [[userContext username] UTF8String];
retval = openchangedb_get_new_changeNumber (connInfo->oc_ctx, owner, &newVersionNumber);
if (retval != MAPI_E_SUCCESS)
[NSException raise: @"MAPIStoreIOException"
format: @"Impossible to get new change number for %s: %s", owner,
mapi_get_errstr (retval)];
if (openchangedb_get_new_changeNumber (connInfo->oc_ctx, connInfo->username, &newVersionNumber)
!= MAPI_E_SUCCESS)
abort ();
return newVersionNumber;
}
/* Get new change numbers from openchange db interface using
resource's owner user */
- (NSArray *) getNewChangeNumbers: (uint64_t) max
{
const char *owner;
enum MAPISTATUS retval;
TALLOC_CTX *memCtx;
NSMutableArray *newChangeNumbers;
uint64_t count;
struct UI8Array_r *numbers;
NSString *newNumber;
memCtx = talloc_new (NULL);
if (!memCtx)
[NSException raise: @"MAPIStoreIOException"
format: @"Not enough memory to allocate change numbers"];
memCtx = talloc_zero(NULL, TALLOC_CTX);
newChangeNumbers = [NSMutableArray arrayWithCapacity: max];
owner = [[userContext username] UTF8String];
retval = openchangedb_get_new_changeNumbers (connInfo->oc_ctx, memCtx, owner, max, &numbers);
if (retval != MAPI_E_SUCCESS || numbers->cValues != max)
{
talloc_free (memCtx);
[NSException raise: @"MAPIStoreIOException"
format: @"Failing to get %d new change numbers: %s", max,
mapi_get_errstr (retval)];
}
if (openchangedb_get_new_changeNumbers (connInfo->oc_ctx,
memCtx, connInfo->username, max, &numbers)
!= MAPI_E_SUCCESS || numbers->cValues != max)
abort ();
for (count = 0; count < max; count++)
{
newNumber = [NSString stringWithUnsignedLongLong: numbers->lpui8[count]];
newNumber
= [NSString stringWithUnsignedLongLong: numbers->lpui8[count]];
[newChangeNumbers addObject: newNumber];
}
@@ -575,31 +544,29 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
return newChangeNumbers;
}
/* Get new fmids from mapistore_indexing interface using resource's
owner user */
- (NSArray *) getNewFMIDs: (uint64_t) max
{
const char *owner;
enum mapistore_error ret;
TALLOC_CTX *memCtx;
NSMutableArray *newFMIDs;
uint64_t count;
struct UI8Array_r *numbers;
NSString *newNumber;
uint64_t count, newFID;
memCtx = talloc_zero(NULL, TALLOC_CTX);
newFMIDs = [NSMutableArray arrayWithCapacity: max];
/* Get the resource's owner name */
owner = [[userContext username] UTF8String];
if (mapistore_indexing_get_new_folderIDs (connInfo->mstore_ctx,
memCtx, max, &numbers)
!= MAPISTORE_SUCCESS || numbers->cValues != max)
abort ();
for (count = 0; count < max; count++)
{
ret = mapistore_indexing_get_new_folderID_as_user (connInfo->mstore_ctx, owner, &newFID);
if (ret != MAPISTORE_SUCCESS)
[NSException raise: @"MAPIStoreIOException"
format: @"Impossible to get new fmid for %s", owner];
newNumber = [NSString stringWithUnsignedLongLong: newFID];
newNumber = [NSString stringWithUnsignedLongLong: numbers->lpui8[count]];
[newFMIDs addObject: newNumber];
}
talloc_free (memCtx);
return newFMIDs;
}
-10
View File
@@ -25,16 +25,6 @@
#import "MAPIStoreFolder.h"
extern NSString *MAPIStoreRightReadItems;
extern NSString *MAPIStoreRightCreateItems;
extern NSString *MAPIStoreRightEditOwn;
extern NSString *MAPIStoreRightEditAll;
extern NSString *MAPIStoreRightDeleteOwn;
extern NSString *MAPIStoreRightDeleteAll;
extern NSString *MAPIStoreRightCreateSubfolders;
extern NSString *MAPIStoreRightFolderOwner;
extern NSString *MAPIStoreRightFolderContact;
@interface MAPIStoreDBFolder : MAPIStoreFolder
@end
+17 -5
View File
@@ -51,6 +51,16 @@
static Class EOKeyValueQualifierK, SOGoCacheGCSFolderK, MAPIStoreDBFolderK;
static NSString *MAPIStoreRightReadItems = @"RightsReadItems";
static NSString *MAPIStoreRightCreateItems = @"RightsCreateItems";
static NSString *MAPIStoreRightEditOwn = @"RightsEditOwn";
static NSString *MAPIStoreRightEditAll = @"RightsEditAll";
static NSString *MAPIStoreRightDeleteOwn = @"RightsDeleteOwn";
static NSString *MAPIStoreRightDeleteAll = @"RightsDeleteAll";
static NSString *MAPIStoreRightCreateSubfolders = @"RightsCreateSubfolders";
static NSString *MAPIStoreRightFolderOwner = @"RightsFolderOwner";
static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
@implementation MAPIStoreDBFolder
+ (void) initialize
@@ -92,7 +102,7 @@ static Class EOKeyValueQualifierK, SOGoCacheGCSFolderK, MAPIStoreDBFolderK;
{
value = get_SPropValue_SRow (aRow, PidTagDisplayName_string8);
if (value)
folderName = [NSString stringWithUTF8String: (const char *) value->value.lpszA];
folderName = [NSString stringWithUTF8String: value->value.lpszA];
else
folderName = nil;
}
@@ -311,9 +321,9 @@ static Class EOKeyValueQualifierK, SOGoCacheGCSFolderK, MAPIStoreDBFolderK;
if ([roles containsObject: MAPIStoreRightDeleteOwn])
rights |= RightsDeleteOwn;
if ([roles containsObject: MAPIStoreRightEditAll])
rights |= RightsEditAll | RightsEditOwn;
rights |= RightsEditAll;
if ([roles containsObject: MAPIStoreRightDeleteAll])
rights |= RightsDeleteAll | RightsDeleteOwn;
rights |= RightsDeleteAll;
if ([roles containsObject: MAPIStoreRightCreateSubfolders])
rights |= RightsCreateSubfolders;
if ([roles containsObject: MAPIStoreRightFolderOwner])
@@ -345,7 +355,8 @@ static Class EOKeyValueQualifierK, SOGoCacheGCSFolderK, MAPIStoreDBFolderK;
- (BOOL) subscriberCanModifyMessages
{
return [self _testRoleForActiveUser: MAPIStoreRightEditAll];
return ([self _testRoleForActiveUser: MAPIStoreRightEditAll]
|| [self _testRoleForActiveUser: MAPIStoreRightEditOwn]);
}
- (BOOL) subscriberCanReadMessages
@@ -366,7 +377,8 @@ static Class EOKeyValueQualifierK, SOGoCacheGCSFolderK, MAPIStoreDBFolderK;
- (BOOL) subscriberCanDeleteMessages
{
return [self _testRoleForActiveUser: MAPIStoreRightDeleteAll];
return ([self _testRoleForActiveUser: MAPIStoreRightDeleteAll]
|| [self _testRoleForActiveUser: MAPIStoreRightDeleteOwn]);
}
- (BOOL) subscriberCanCreateSubFolders
+30 -313
View File
@@ -22,14 +22,10 @@
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <SOGo/SOGoFolder.h>
#import <SOGo/SOGoUser.h>
#import "MAPIStoreContext.h"
#import "MAPIStorePropertySelectors.h"
@@ -38,7 +34,6 @@
#import "MAPIStoreDBFolder.h"
#import "MAPIStoreDBMessage.h"
#import "MAPIStoreTypes.h"
#import "NSData+MAPIStore.h"
#import "NSObject+MAPIStore.h"
#import "NSString+MAPIStore.h"
@@ -48,28 +43,16 @@
@implementation MAPIStoreDBMessage
+ (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP
inMemCtx: (TALLOC_CTX *) memCtx
+ (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
inMemCtx: (TALLOC_CTX *) memCtx
{
struct SPropTagArray *properties;
NSUInteger count;
enum MAPITAGS faiProperties[] = {
0x68330048, /* PR_VIEW_CLSID */
0x68350102, /* PR_VIEW_STATE */
0x683c0102,
0x683d0040,
0x683e0102,
0x683f0102, /* PR_VIEW_VIEWTYPE_KEY */
0x68410003,
0x68420102,
0x68450102,
0x68460003,
0x7006001F, /* PR_VD_NAME_W */
0x70030003, /* PR_VD_FLAGS */
0x70070003 /* PR_VD_VERSION */
};
enum MAPITAGS faiProperties[] = { 0x68350102, 0x683c0102, 0x683e0102,
0x683f0102, 0x68410003, 0x68420102,
0x68450102, 0x68460003,
// PR_VD_NAME_W, PR_VD_FLAGS, PR_VD_VERSION, PR_VIEW_CLSID
0x7006001F, 0x70030003, 0x70070003, 0x68330048 };
size_t faiSize = sizeof(faiProperties) / sizeof(enum MAPITAGS);
properties = talloc_zero (memCtx, struct SPropTagArray);
@@ -91,13 +74,6 @@
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP
inMemCtx: (TALLOC_CTX *) memCtx
{
return [[self class] getAvailableProperties: propertiesP
inMemCtx: memCtx];
}
- (id) initWithSOGoObject: (id) newSOGoObject
inContainer: (MAPIStoreObject *) newContainer
{
@@ -112,180 +88,29 @@
return self;
}
- (NSString *) description
{
id key, value;
NSEnumerator *propEnumerator;
NSMutableString *description;
description = [NSMutableString stringWithFormat: @"%@ %@. Properties: {", NSStringFromClass ([self class]),
[self url]];
propEnumerator = [properties keyEnumerator];
while ((key = [propEnumerator nextObject]))
{
uint32_t proptag = 0;
if ([key isKindOfClass: [NSString class]] && [(NSString *)key intValue] > 0)
proptag = [(NSString *)key intValue];
else if ([key isKindOfClass: [NSNumber class]])
proptag = [key unsignedLongValue];
if (proptag > 0)
{
const char *propTagName = get_proptag_name ([key unsignedLongValue]);
NSString *propName;
if (propTagName)
propName = [NSString stringWithCString: propTagName
encoding: NSUTF8StringEncoding];
else
propName = [NSString stringWithFormat: @"0x%.4x", [key unsignedLongValue]];
[description appendFormat: @"'%@': ", propName];
}
else
[description appendFormat: @"'%@': ", key];
value = [properties objectForKey: key];
[description appendFormat: @"%@ (%@), ", value, NSStringFromClass ([value class])];
}
[description appendString: @"}\n"];
return description;
}
- (uint64_t) objectVersion
{
/* Return the global counter from CN structure.
See [MS-OXCFXICS] Section 2.2.2.1 */
NSNumber *versionNbr, *cn;
NSNumber *versionNbr;
uint64_t objectVersion;
[(SOGoMAPIDBMessage *) sogoObject reloadIfNeeded];
versionNbr = [properties objectForKey: @"version_number"];
versionNbr = [properties objectForKey: @"version"];
if (versionNbr)
objectVersion = exchange_globcnt ([versionNbr unsignedLongLongValue]);
objectVersion = (([versionNbr unsignedLongLongValue] >> 16)
& 0x0000ffffffffffffLL);
else
{
/* Old version which stored the CN structure not useful for searching */
cn = [properties objectForKey: @"version"];
if (cn)
objectVersion = (([cn unsignedLongLongValue] >> 16)
& 0x0000ffffffffffffLL);
else
objectVersion = ULLONG_MAX;
}
objectVersion = ULLONG_MAX;
return objectVersion;
}
- (void) _updatePredecessorChangeList
{
BOOL updated;
enum mapistore_error rc;
NSData *currentChangeList, *changeKey;
NSMutableArray *changeKeys;
NSMutableData *newChangeList;
NSUInteger count, len;
struct SizedXid *changes;
struct SPropValue property;
struct SRow aRow;
struct XID *currentChangeKey;
TALLOC_CTX *localMemCtx;
uint32_t nChanges;
localMemCtx = talloc_new (NULL);
if (!localMemCtx)
{
[self errorWithFormat: @"No more memory"];
return;
}
changeKey = [self getReplicaKeyFromGlobCnt: [self objectVersion]];
currentChangeList = [properties objectForKey: MAPIPropertyKey (PidTagPredecessorChangeList)];
if (!currentChangeList)
{
/* Create a new PredecessorChangeList */
len = [changeKey length];
newChangeList = [NSMutableData dataWithCapacity: len + 1];
[newChangeList appendUInt8: len];
[newChangeList appendData: changeKey];
}
else
{
/* Update current predecessor change list with new change key */
changes = [currentChangeList asSizedXidArrayInMemCtx: localMemCtx
with: &nChanges];
updated = NO;
currentChangeKey = [changeKey asXIDInMemCtx: localMemCtx];
for (count = 0; count < nChanges && !updated; count++)
{
if (GUID_equal(&changes[count].XID.NameSpaceGuid, &currentChangeKey->NameSpaceGuid))
{
NSData *globCnt, *oldGlobCnt;
oldGlobCnt = [NSData dataWithBytes: changes[count].XID.LocalId.data length: changes[count].XID.LocalId.length];
globCnt = [NSData dataWithBytes: currentChangeKey->LocalId.data length: currentChangeKey->LocalId.length];
if ([globCnt compare: oldGlobCnt] == NSOrderedDescending)
{
if ([globCnt length] != [oldGlobCnt length])
{
[self errorWithFormat: @"Cannot compare globcnt with different length: %@ and %@", globCnt, oldGlobCnt];
abort();
}
memcpy (changes[count].XID.LocalId.data, currentChangeKey->LocalId.data, currentChangeKey->LocalId.length);
updated = YES;
}
}
}
/* Serialise it */
changeKeys = [NSMutableArray array];
if (!updated)
[changeKeys addObject: changeKey];
for (count = 0; count < nChanges; count++)
{
changeKey = [NSData dataWithXID: &changes[count].XID];
[changeKeys addObject: changeKey];
}
[changeKeys sortUsingFunction: MAPIChangeKeyGUIDCompare context: localMemCtx];
newChangeList = [NSMutableData data];
len = [changeKeys count];
for (count = 0; count < len; count++)
{
changeKey = [changeKeys objectAtIndex: count];
[newChangeList appendUInt8: [changeKey length]];
[newChangeList appendData: changeKey];
}
}
if ([newChangeList length] > 0)
{
property.ulPropTag = PidTagPredecessorChangeList;
property.value.bin = *[newChangeList asBinaryInMemCtx: localMemCtx];
aRow.cValues = 1;
aRow.lpProps = &property;
rc = [self addPropertiesFromRow: &aRow];
if (rc != MAPISTORE_SUCCESS)
[self errorWithFormat: @"Impossible to add a new predecessor change list: %d", rc];
}
talloc_free (localMemCtx);
}
//
// FIXME: how this can happen?
//
// We might get there if for some reasons, all classes weren't able
// to tell us the message class.
//
- (enum mapistore_error) getPidTagMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"IPM.Note" asUnicodeInMemCtx: memCtx];
@@ -294,10 +119,10 @@
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getProperties: (struct mapistore_property_data *) data
withTags: (enum MAPITAGS *) tags
andCount: (uint16_t) columnCount
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getProperties: (struct mapistore_property_data *) data
withTags: (enum MAPITAGS *) tags
andCount: (uint16_t) columnCount
inMemCtx: (TALLOC_CTX *) memCtx
{
[sogoObject reloadIfNeeded];
@@ -307,12 +132,12 @@
inMemCtx: memCtx];
}
- (enum mapistore_error) getProperty: (void **) data
withTag: (enum MAPITAGS) propTag
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getProperty: (void **) data
withTag: (enum MAPITAGS) propTag
inMemCtx: (TALLOC_CTX *) memCtx
{
id value;
enum mapistore_error rc;
int rc;
value = [properties objectForKey: MAPIPropertyKey (propTag)];
if (value)
@@ -338,29 +163,10 @@
[properties setObject: attachmentParts forKey: @"attachments"];
newVersion = [[self context] getNewChangeNumber];
newVersion = exchange_globcnt ((newVersion >> 16) & 0x0000ffffffffffffLL);
[properties setObject: [NSNumber numberWithUnsignedLongLong: newVersion]
forKey: @"version_number"];
forKey: @"version"];
/* Remove old version */
[properties removeObjectForKey: @"version"];
/* Update PredecessorChangeList accordingly */
[self _updatePredecessorChangeList];
if (isNew)
{
NSString *lastModifierName;
lastModifierName = (NSString *)[properties objectForKey: MAPIPropertyKey (PidTagLastModifierName)];
if ([lastModifierName length] > 0)
[properties setObject: lastModifierName
forKey: MAPIPropertyKey (PidTagCreatorName)];
}
// [self logWithFormat: @"Saving %@", [self description]];
// [self logWithFormat: @"%d props in dict", [properties count]];
[self logWithFormat: @"%d props in dict", [properties count]];
[sogoObject save];
}
@@ -377,77 +183,20 @@
return [msgClass isEqualToString: @"IPM.Microsoft.ScheduleData.FreeBusy"];
}
//-----------------------------
// Permissions
//-----------------------------
/* TODO: differentiate between the "Own" and "All" cases */
- (BOOL) subscriberCanReadMessage
{
return [(MAPIStoreFolder *) container subscriberCanReadMessages];
}
- (SOGoUser *) _ownerUser
{
NSString *ownerName;
SOGoUser *ownerUser = nil;
ownerName = [properties objectForKey: MAPIPropertyKey (PidTagCreatorName)];
if ([ownerName length] > 0)
ownerUser = [SOGoUser userWithLogin: ownerName];
return ownerUser;
}
- (NSArray *) activeUserRoles
{
/* Override because of this exception: NSInvalidArgumentException,
reason: [SOGoMAPIDBMessage-aclsForUser:] should be overridden by
subclass */
if (!activeUserRoles)
{
SOGoUser *activeUser;
activeUser = [[self context] activeUser];
activeUserRoles = [[container aclFolder] aclsForUser: [activeUser login]];
[activeUserRoles retain];
}
return activeUserRoles;
// || [self _messageIsFreeBusy]);
}
- (BOOL) subscriberCanModifyMessage
{
BOOL rc;
NSArray *roles;
roles = [self activeUserRoles];
if (isNew)
rc = [(MAPIStoreFolder *) container subscriberCanCreateMessages];
else
rc = [roles containsObject: MAPIStoreRightEditAll];
/* Check if the message is owned and it has permission to edit it */
if (!rc && [roles containsObject: MAPIStoreRightEditOwn])
rc = [[[container context] activeUser] isEqual: [self _ownerUser]];
return rc;
}
- (BOOL) subscriberCanDeleteMessage
{
BOOL rc;
NSArray *roles;
roles = [self activeUserRoles];
rc = [roles containsObject: MAPIStoreRightDeleteAll];
/* Check if the message is owned and it has permission to delete it */
if (!rc && [roles containsObject: MAPIStoreRightDeleteOwn])
rc = [[[container context] activeUser] isEqual: [self _ownerUser]];
return rc;
return ((isNew
&& [(MAPIStoreFolder *) container subscriberCanCreateMessages])
|| (!isNew
&& [(MAPIStoreFolder *) container subscriberCanModifyMessages]));
// || [self _messageIsFreeBusy]);
}
- (NSDate *) creationTime
@@ -460,36 +209,4 @@
return [sogoObject lastModified];
}
- (enum mapistore_error) setReadFlag: (uint8_t) flag
{
/* Modify PidTagMessageFlags from SetMessageReadFlag and
SyncImportReadStateChanges ROPs */
NSNumber *flags;
uint32_t newFlag;
flags = [properties objectForKey: MAPIPropertyKey (PR_MESSAGE_FLAGS)];
if (flags)
{
newFlag = [flags unsignedLongValue];
if (flag & SUPPRESS_RECEIPT)
newFlag |= MSGFLAG_READ;
if (flag & CLEAR_RN_PENDING)
newFlag &= ~MSGFLAG_RN_PENDING;
if (flag & CLEAR_READ_FLAG)
newFlag &= ~MSGFLAG_READ;
if (flag & CLEAR_NRN_PENDING)
newFlag &= ~MSGFLAG_NRN_PENDING;
}
else
{
newFlag = MSGFLAG_READ;
if (flag & CLEAR_READ_FLAG)
newFlag = 0x0;
}
[properties setObject: [NSNumber numberWithUnsignedLong: newFlag]
forKey: MAPIPropertyKey (PR_MESSAGE_FLAGS)];
return MAPISTORE_SUCCESS;
}
@end
+4 -5
View File
@@ -61,15 +61,14 @@ static Class MAPIStoreDBMessageK = Nil;
if ((uint32_t) res->ulPropTag == PidTagChangeNumber)
{
SEL operator;
value = NSObjectFromMAPISPropValue (&res->lpProp);
cVersion = exchange_globcnt (([value unsignedLongLongValue] >> 16)
& 0x0000ffffffffffffLL);
version = [NSNumber numberWithUnsignedLongLong: cVersion];
operator = [self operatorFromRestrictionOperator: res->relop];
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"version_number"
operatorSelector: operator
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
[self logWithFormat: @" version: %.16lx", cVersion];
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"version"
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
value: version];
[*qualifier autorelease];
rc = MAPIRestrictionStateNeedsEval;
+26 -26
View File
@@ -56,81 +56,81 @@ static Class MAPIStoreAttachmentK;
idForObjectWithKey: objectKey];
}
- (enum mapistore_error) getPidTagAccessLevel: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAccessLevel: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getLongZero: data inMemCtx: memCtx];
}
/* disabled properties */
- (enum mapistore_error) getPidTagFolderId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagFolderId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidTagChangeKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagChangeKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidTagSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidTagParentSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagParentSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidTagChangeNumber: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagChangeNumber: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidTagInstID: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagInstID: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidTagInstanceNum: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagInstanceNum: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidTagRowType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagRowType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidTagDepth: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagDepth: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidTagIconIndex: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagIconIndex: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidTagGenerateExchangeViews: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagGenerateExchangeViews: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidTagOriginalMessageClass: (void **) dataa
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagOriginalMessageClass: (void **) dataa
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
+3 -4
View File
@@ -24,7 +24,6 @@
#import "MAPIStoreActiveTables.h"
#import "MAPIStoreContext.h"
#import "MAPIStoreFolder.h"
#import "MAPIStoreUserContext.h"
#import "NSObject+MAPIStore.h"
@@ -46,8 +45,8 @@
andType: MAPISTORE_FAI_TABLE];
}
- (enum mapistore_error) getPidTagAssociated: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAssociated: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getYes: data inMemCtx: memCtx];
}
@@ -70,7 +69,7 @@
- (BOOL) subscriberCanReadMessage
{
return [(MAPIStoreFolder *)container subscriberCanReadMessages];
return NO;
}
- (BOOL) subscriberCanModifyMessage
+36 -54
View File
@@ -22,7 +22,6 @@
#define MAPISTOREFOLDER_H
#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
@class NSArray;
@class NSMutableArray;
@@ -42,20 +41,6 @@
#import "MAPIStoreSOGoObject.h"
/* MAPI Permissions
This set has only sogo-openchange library scope
*/
extern NSString *MAPIStoreRightReadItems;
extern NSString *MAPIStoreRightCreateItems;
extern NSString *MAPIStoreRightEditOwn;
extern NSString *MAPIStoreRightEditAll;
extern NSString *MAPIStoreRightDeleteOwn;
extern NSString *MAPIStoreRightDeleteAll;
extern NSString *MAPIStoreRightCreateSubfolders;
extern NSString *MAPIStoreRightFolderOwner;
extern NSString *MAPIStoreRightFolderContact;
@interface MAPIStoreFolder : MAPIStoreSOGoObject
{
MAPIStoreContext *context;
@@ -89,8 +74,6 @@ extern NSString *MAPIStoreRightFolderContact;
- (MAPIStorePermissionsTable *) permissionsTable;
- (NSArray *) permissionEntries;
- (NSArray *) expandRoles: (NSArray *) roles;
/* message objects and tables */
- (id) lookupMessage: (NSString *) messageKey;
- (NSArray *) messageKeys;
@@ -113,34 +96,33 @@ extern NSString *MAPIStoreRightFolderContact;
/* backend interface */
- (enum mapistore_error) openFolder: (MAPIStoreFolder **) childFolderPtr
withFID: (uint64_t) fid;
- (enum mapistore_error) createFolder: (MAPIStoreFolder **) childFolderPtr
withRow: (struct SRow *) aRow
andFID: (uint64_t) fid;
- (enum mapistore_error) deleteFolder;
- (enum mapistore_error) getChildCount: (uint32_t *) rowCount
ofTableType: (enum mapistore_table_type) tableType;
- (int) openFolder: (MAPIStoreFolder **) childFolderPtr
withFID: (uint64_t) fid;
- (int) createFolder: (MAPIStoreFolder **) childFolderPtr
withRow: (struct SRow *) aRow
andFID: (uint64_t) fid;
- (int) deleteFolder;
- (int) getChildCount: (uint32_t *) rowCount
ofTableType: (enum mapistore_table_type) tableType;
- (enum mapistore_error) createMessage: (MAPIStoreMessage **) messagePtr
withMID: (uint64_t) mid
isAssociated: (BOOL) isAssociated;
- (int) createMessage: (MAPIStoreMessage **) messagePtr
withMID: (uint64_t) mid
isAssociated: (BOOL) isAssociated;
- (enum mapistore_error) openMessage: (MAPIStoreMessage **) messagePtr
withMID: (uint64_t) mid
forWriting: (BOOL) readWrite
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) deleteMessageWithMID: (uint64_t) mid
andFlags: (uint8_t) flags;
- (int) openMessage: (MAPIStoreMessage **) messagePtr
withMID: (uint64_t) mid
forWriting: (BOOL) readWrite
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) deleteMessageWithMID: (uint64_t) mid
andFlags: (uint8_t) flags;
- (enum mapistore_error) moveCopyMessagesWithMIDs: (uint64_t *) srcMids
andCount: (uint32_t) count
fromFolder: (MAPIStoreFolder *) sourceFolder
withMIDs: (uint64_t *) targetMids
andChangeKeys: (struct Binary_r **) targetChangeKeys
andPredecessorChangeLists: (struct Binary_r **) targetPredecessorChangeLists
wantCopy: (uint8_t) want_copy
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) moveCopyMessagesWithMIDs: (uint64_t *) srcMids
andCount: (uint32_t) count
fromFolder: (MAPIStoreFolder *) sourceFolder
withMIDs: (uint64_t *) targetMids
andChangeKeys: (struct Binary_r **) targetChangeKeys
wantCopy: (uint8_t) want_copy
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) moveCopyToFolder: (MAPIStoreFolder *) targetFolder
withNewName: (NSString *) newFolderName
@@ -148,20 +130,20 @@ extern NSString *MAPIStoreRightFolderContact;
isRecursive: (BOOL) isRecursive
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getDeletedFMIDs: (struct UI8Array_r **) fmidsPtr
andCN: (uint64_t *) cnPtr
fromChangeNumber: (uint64_t) changeNum
inTableType: (enum mapistore_table_type) tableType
inMemCtx: (TALLOC_CTX *) mem_ctx;
- (int) getDeletedFMIDs: (struct UI8Array_r **) fmidsPtr
andCN: (uint64_t *) cnPtr
fromChangeNumber: (uint64_t) changeNum
inTableType: (enum mapistore_table_type) tableType
inMemCtx: (TALLOC_CTX *) mem_ctx;
- (enum mapistore_error) getTable: (MAPIStoreTable **) tablePtr
andRowCount: (uint32_t *) count
tableType: (enum mapistore_table_type) tableType
andHandleId: (uint32_t) handleId;
- (int) getTable: (MAPIStoreTable **) tablePtr
andRowCount: (uint32_t *) count
tableType: (enum mapistore_table_type) tableType
andHandleId: (uint32_t) handleId;
- (enum mapistore_error) modifyPermissions: (struct PermissionData *) permissions
withCount: (uint16_t) pcount
andFlags: (int8_t) flags;
- (int) modifyPermissions: (struct PermissionData *) permissions
withCount: (uint16_t) pcount
andFlags: (int8_t) flags;
- (enum mapistore_error) preloadMessageBodiesWithMIDs: (const struct UI8Array_r *) mids
ofTableType: (enum mapistore_table_type) tableType;
+122 -182
View File
@@ -65,17 +65,6 @@
Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMessageTableK, MAPIStoreFolderTableK;
/* MAPI permissions */
NSString *MAPIStoreRightReadItems = @"RightsReadItems";
NSString *MAPIStoreRightCreateItems = @"RightsCreateItems";
NSString *MAPIStoreRightEditOwn = @"RightsEditOwn";
NSString *MAPIStoreRightEditAll = @"RightsEditAll";
NSString *MAPIStoreRightDeleteOwn = @"RightsDeleteOwn";
NSString *MAPIStoreRightDeleteAll = @"RightsDeleteAll";
NSString *MAPIStoreRightCreateSubfolders = @"RightsCreateSubfolders";
NSString *MAPIStoreRightFolderOwner = @"RightsFolderOwner";
NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
@implementation MAPIStoreFolder
+ (void) initialize
@@ -376,10 +365,10 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
return foundObject;
}
- (enum mapistore_error) openFolder: (MAPIStoreFolder **) childFolderPtr
withFID: (uint64_t) fid
- (int) openFolder: (MAPIStoreFolder **) childFolderPtr
withFID: (uint64_t) fid
{
enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND;
int rc = MAPISTORE_ERR_NOT_FOUND;
MAPIStoreFolder *childFolder;
MAPIStoreMapping *mapping;
NSString *childURL;
@@ -401,9 +390,9 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
return rc;
}
- (enum mapistore_error) createFolder: (MAPIStoreFolder **) childFolderPtr
withRow: (struct SRow *) aRow
andFID: (uint64_t) fid
- (int) createFolder: (MAPIStoreFolder **) childFolderPtr
withRow: (struct SRow *) aRow
andFID: (uint64_t) fid
{
BOOL mapped;
enum mapistore_error rc = MAPISTORE_SUCCESS;
@@ -458,7 +447,7 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
return rc;
}
- (enum mapistore_error) deleteFolder
- (int) deleteFolder
{
// TODO: raise exception in case underlying delete fails?
// [propsMessage delete];
@@ -469,11 +458,11 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getChildCount: (uint32_t *) rowCount
ofTableType: (enum mapistore_table_type) tableType
- (int) getChildCount: (uint32_t *) rowCount
ofTableType: (enum mapistore_table_type) tableType
{
NSArray *keys;
enum mapistore_error rc = MAPISTORE_SUCCESS;
int rc = MAPISTORE_SUCCESS;
//[self logWithFormat: @"METHOD '%s' (%d) -- tableType: %d",
//__FUNCTION__, __LINE__, tableType];
@@ -494,16 +483,16 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
return rc;
}
- (enum mapistore_error) openMessage: (MAPIStoreMessage **) messagePtr
withMID: (uint64_t) mid
forWriting: (BOOL) readWrite
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) openMessage: (MAPIStoreMessage **) messagePtr
withMID: (uint64_t) mid
forWriting: (BOOL) readWrite
inMemCtx: (TALLOC_CTX *) memCtx;
{
NSString *messageURL;
MAPIStoreMapping *mapping;
MAPIStoreMessage *message;
SOGoUser *ownerUser;
enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND;
int rc = MAPISTORE_ERR_NOT_FOUND;
mapping = [self mapping];
messageURL = [mapping urlFromID: mid];
@@ -534,9 +523,9 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
return rc;
}
- (enum mapistore_error) createMessage: (MAPIStoreMessage **) messagePtr
withMID: (uint64_t) mid
isAssociated: (BOOL) isAssociated
- (int) createMessage: (MAPIStoreMessage **) messagePtr
withMID: (uint64_t) mid
isAssociated: (BOOL) isAssociated
{
enum mapistore_error rc;
MAPIStoreMessage *message;
@@ -581,8 +570,8 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
return rc;
}
- (enum mapistore_error) deleteMessageWithMID: (uint64_t) mid
andFlags: (uint8_t) flags
- (int) deleteMessageWithMID: (uint64_t) mid
andFlags: (uint8_t) flags
{
NSString *childURL;
MAPIStoreMapping *mapping;
@@ -591,7 +580,7 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
NSUInteger count, max;
id msgObject;
SOGoUser *ownerUser;
enum mapistore_error rc;
int rc;
/* flags that control the behaviour of the operation
(MAPISTORE_SOFT_DELETE or MAPISTORE_PERMANENT_DELETE) */
@@ -608,7 +597,7 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
if ([[context activeUser] isEqual: ownerUser]
|| (![message isKindOfClass: MAPIStoreFAIMessageK]
&& ([self subscriberCanDeleteMessages] || [message subscriberCanDeleteMessage])))
&& [self subscriberCanDeleteMessages]))
{
/* we ensure the table caches are loaded so that old and new state
can be compared */
@@ -649,15 +638,14 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
}
// private method
- (enum mapistore_error) _moveCopyMessageWithMID: (uint64_t) srcMid
fromFolder: (MAPIStoreFolder *) sourceFolder
withMID: (uint64_t) targetMid
andChangeKey: (struct Binary_r *) targetChangeKey
andPredecessorChangeList: (struct Binary_r *) targetPredecessorChangeList
wantCopy: (uint8_t) wantCopy
inMemCtx: (TALLOC_CTX *) memCtx
- (int) _moveCopyMessageWithMID: (uint64_t) srcMid
fromFolder: (MAPIStoreFolder *) sourceFolder
withMID: (uint64_t) targetMid
andChangeKey: (struct Binary_r *) targetChangeKey
wantCopy: (uint8_t) wantCopy
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
int rc;
MAPIStoreMessage *sourceMsg, *destMsg;
//TALLOC_CTX *memCtx;
struct SRow aRow;
@@ -681,18 +669,15 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
[sourceMsg copyToMessage: destMsg inMemCtx: memCtx];
if (targetPredecessorChangeList)
if (targetChangeKey)
{
property.ulPropTag = PidTagPredecessorChangeList;
property.value.bin = *targetPredecessorChangeList;
property.ulPropTag = PidTagChangeKey;
property.value.bin = *targetChangeKey;
aRow.cValues = 1;
aRow.lpProps = &property;
rc = [destMsg addPropertiesFromRow: &aRow];
if (rc != MAPISTORE_SUCCESS)
{
[self errorWithFormat: @"Cannot add PredecessorChangeList on move"];
goto end;
}
goto end;
}
[destMsg save: memCtx];
if (!wantCopy)
@@ -706,22 +691,21 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
return rc;
}
- (enum mapistore_error) moveCopyMessagesWithMIDs: (uint64_t *) srcMids
andCount: (uint32_t) midCount
fromFolder: (MAPIStoreFolder *) sourceFolder
withMIDs: (uint64_t *) targetMids
andChangeKeys: (struct Binary_r **) targetChangeKeys
andPredecessorChangeLists: (struct Binary_r **) targetPredecessorChangeLists
wantCopy: (uint8_t) wantCopy
inMemCtx: (TALLOC_CTX *) memCtx
- (int) moveCopyMessagesWithMIDs: (uint64_t *) srcMids
andCount: (uint32_t) midCount
fromFolder: (MAPIStoreFolder *) sourceFolder
withMIDs: (uint64_t *) targetMids
andChangeKeys: (struct Binary_r **) targetChangeKeys
wantCopy: (uint8_t) wantCopy
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc = MAPISTORE_SUCCESS;
int rc = MAPISTORE_SUCCESS;
NSUInteger count;
NSMutableArray *oldMessageURLs;
NSString *oldMessageURL;
MAPIStoreMapping *mapping;
SOGoUser *ownerUser;
struct Binary_r *targetChangeKey, *targetPredecessorChangeList;
struct Binary_r *targetChangeKey;
//TALLOC_CTX *memCtx;
//memCtx = talloc_zero (NULL, TALLOC_CTX);
@@ -742,21 +726,14 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
if (oldMessageURL)
{
[oldMessageURLs addObject: oldMessageURL];
if (targetChangeKeys && targetPredecessorChangeList)
{
targetChangeKey = targetChangeKeys[count];
targetPredecessorChangeList = targetPredecessorChangeLists[count];
}
if (targetChangeKeys)
targetChangeKey = targetChangeKeys[count];
else
{
targetChangeKey = NULL;
targetPredecessorChangeList = NULL;
}
targetChangeKey = NULL;
rc = [self _moveCopyMessageWithMID: srcMids[count]
fromFolder: sourceFolder
withMID: targetMids[count]
andChangeKey: targetChangeKey
andPredecessorChangeList: targetPredecessorChangeList
wantCopy: wantCopy
inMemCtx: memCtx];
}
@@ -919,11 +896,6 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
return nil;
}
- (NSArray *) expandRoles: (NSArray *) roles
{
return roles;
}
- (void) _modifyPermissionEntryForUser: (NSString *) user
withRoles: (NSArray *) roles
isAddition: (BOOL) isAddition
@@ -973,13 +945,13 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
withIDs: newIDs];
}
- (enum mapistore_error) getDeletedFMIDs: (struct UI8Array_r **) fmidsPtr
andCN: (uint64_t *) cnPtr
fromChangeNumber: (uint64_t) changeNum
inTableType: (enum mapistore_table_type) tableType
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getDeletedFMIDs: (struct UI8Array_r **) fmidsPtr
andCN: (uint64_t *) cnPtr
fromChangeNumber: (uint64_t) changeNum
inTableType: (enum mapistore_table_type) tableType
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
int rc;
NSString *baseURL, *format, *url;
NSArray *keys;
NSNumber *cnNbr;
@@ -1032,15 +1004,14 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
return rc;
}
- (enum mapistore_error) getTable: (MAPIStoreTable **) tablePtr
andRowCount: (uint32_t *) countPtr
tableType: (enum mapistore_table_type) tableType
andHandleId: (uint32_t) handleId
- (int) getTable: (MAPIStoreTable **) tablePtr
andRowCount: (uint32_t *) countPtr
tableType: (enum mapistore_table_type) tableType
andHandleId: (uint32_t) handleId
{
BOOL access;
enum mapistore_error rc = MAPISTORE_SUCCESS;
int rc = MAPISTORE_SUCCESS;
MAPIStoreTable *table;
SOGoUser *activeUser, *ownerUser;
SOGoUser *ownerUser;
if (tableType == MAPISTORE_MESSAGE_TABLE)
table = [self messageTable];
@@ -1051,20 +1022,8 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
else if (tableType == MAPISTORE_PERMISSIONS_TABLE)
{
ownerUser = [[self userContext] sogoUser];
activeUser = [context activeUser];
access = [activeUser isEqual: ownerUser];
if (!access)
{
NSArray *roles;
roles = [[self aclFolder] aclsForUser: [activeUser login]];
roles = [self expandRoles: roles]; // Not required here
/* Check FolderVisible right to return the table */
access = ([self exchangeRightsForRoles: roles] & RoleNone) != 0;
}
if (access)
table = [self permissionsTable];
if ([[context activeUser] isEqual: ownerUser])
table = [self permissionsTable];
else
rc = MAPISTORE_ERR_DENIED;
}
@@ -1237,16 +1196,16 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
// folderKeys = nil;
}
- (enum mapistore_error) getPidTagParentFolderId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagParentFolderId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongLongValue (memCtx, [container objectId]);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagFolderId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagFolderId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongLongValue (memCtx, [self objectId]);
@@ -1263,8 +1222,8 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
0x00000010 Create Contents Table
0x00000020 Create Associated Contents Table
*/
- (enum mapistore_error) getPidTagAccess: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAccess: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
uint32_t access = 0;
SOGoUser *ownerUser;
@@ -1292,107 +1251,103 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagRights: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagRights: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
uint32_t rights = 0;
SOGoUser *activeUser, *ownerUser;
SOGoUser *ownerUser;
BOOL userIsOwner;
ownerUser = [[self userContext] sogoUser];
activeUser = [context activeUser];
if ([activeUser isEqual: ownerUser])
{
rights = RightsReadItems | RightsCreateItems | RightsEditOwn | RightsEditAll
| RightsDeleteOwn | RightsDeleteAll | RightsFolderOwner | RightsFolderContact | RoleNone;
if ([self supportsSubFolders])
rights |= RightsCreateSubfolders;
}
else
{
NSArray *roles;
roles = [[self aclFolder] aclsForUser: [activeUser login]];
roles = [self expandRoles: roles];
rights = [self exchangeRightsForRoles: roles];
/* FreeBusySimple and FreeBusyDetailed does not apply here
[MS-OXCFOLD] Section 2.2.2.2.2.8 */
rights &= ~RightsFreeBusySimple & ~RightsFreeBusyDetailed;
}
userIsOwner = [[context activeUser] isEqual: ownerUser];
if (userIsOwner || [self subscriberCanReadMessages])
rights |= RightsReadItems;
if (userIsOwner || [self subscriberCanCreateMessages])
rights |= RightsCreateItems;
if (userIsOwner || [self subscriberCanModifyMessages])
rights |= RightsEditOwn | RightsEditAll;
if (userIsOwner || [self subscriberCanDeleteMessages])
rights |= RightsDeleteOwn | RightsDeleteAll;
if ((userIsOwner || [self subscriberCanCreateSubFolders])
&& [self supportsSubFolders])
rights |= RightsCreateSubfolders;
if (userIsOwner)
rights |= RightsFolderOwner | RightsFolderContact;
*data = MAPILongValue (memCtx, rights);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAccessControlListData: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAccessControlListData: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[NSData data] asBinaryInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttributeHidden: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttributeHidden: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagAttributeSystem: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttributeSystem: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagAttributeReadOnly: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttributeReadOnly: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagSubfolders: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagSubfolders: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPIBoolValue (memCtx, [self supportsSubFolders] && [[self folderKeys] count] > 0);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagFolderChildCount: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagFolderChildCount: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, [[self folderKeys] count]);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagContentCount: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagContentCount: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, [[self messageKeys] count]);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagContentUnreadCount: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagContentUnreadCount: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, 0);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAssociatedContentCount: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAssociatedContentCount: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, [[self faiMessageKeys] count]);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagDeletedCountTotal: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagDeletedCountTotal: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
/* TODO */
*data = MAPILongValue (memCtx, 0);
@@ -1400,10 +1355,10 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagLocalCommitTimeMax: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagLocalCommitTimeMax: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc = MAPISTORE_SUCCESS;
int rc = MAPISTORE_SUCCESS;
NSDate *date;
date = [self lastMessageModificationTime];
@@ -1415,18 +1370,18 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
return rc;
}
- (enum mapistore_error) getPidTagDefaultPostMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagDefaultPostMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"IPM.Note" asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getProperties: (struct mapistore_property_data *) data
withTags: (enum MAPITAGS *) tags
andCount: (uint16_t) columnCount
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getProperties: (struct mapistore_property_data *) data
withTags: (enum MAPITAGS *) tags
andCount: (uint16_t) columnCount
inMemCtx: (TALLOC_CTX *) memCtx
{
[dbFolder reloadIfNeeded];
@@ -1436,11 +1391,11 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
inMemCtx: memCtx];
}
- (enum mapistore_error) getProperty: (void **) data
withTag: (enum MAPITAGS) propTag
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getProperty: (void **) data
withTag: (enum MAPITAGS) propTag
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
int rc;
id value;
value = [properties objectForKey: MAPIPropertyKey (propTag)];
@@ -1582,6 +1537,7 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
struct Binary_r bin32;
struct AddressBookEntryId *entryId;
NSString *username;
struct ldb_context *samCtx;
if (bin && bin->cb)
{
@@ -1591,8 +1547,8 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
entryId = get_AddressBookEntryId (NULL, &bin32);
if (entryId)
{
username = MAPIStoreSamDBUserAttribute ([[self context] connectionInfo],
@"legacyExchangeDN",
samCtx = [[self context] connectionInfo]->sam_ctx;
username = MAPIStoreSamDBUserAttribute (samCtx, @"legacyExchangeDN",
[NSString stringWithUTF8String: entryId->X500DN],
@"sAMAccountName");
}
@@ -1647,9 +1603,9 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
[users release];
}
- (enum mapistore_error) modifyPermissions: (struct PermissionData *) permissions
withCount: (uint16_t) pcount
andFlags: (int8_t) flags
- (int) modifyPermissions: (struct PermissionData *) permissions
withCount: (uint16_t) pcount
andFlags: (int8_t) flags
{
NSUInteger count, propCount;
struct PermissionData *currentPermission;
@@ -1659,22 +1615,6 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
NSArray *permissionRoles;
BOOL reset, isAdd = NO, isDelete = NO, isModify = NO;
SOGoFolder *aclFolder;
SOGoUser *activeUser, *ownerUser;
/* Check if we have permissions to modify the permissions.
See [MS-OXCPERM] Section 3.2.5.2 for details */
ownerUser = [[self userContext] sogoUser];
activeUser = [context activeUser];
if (![activeUser isEqual: ownerUser])
{
/* Check if we have FolderOwner right */
NSArray *roles;
roles = [[self aclFolder] aclsForUser: [activeUser login]];
roles = [self expandRoles: roles]; // Not required
if (([self exchangeRightsForRoles: roles] & RightsFolderOwner) == 0)
return MAPISTORE_ERR_DENIED;
}
aclFolder = [self aclFolder];
+1 -3
View File
@@ -41,10 +41,8 @@
/* synchronisation */
- (BOOL) synchroniseCache;
- (BOOL) synchroniseCacheFor: (NSString *) nameInContainer;
- (void) updateVersionsForMessageWithKey: (NSString *) messageKey
withChangeKey: (NSData *) oldChangeKey
andPredecessorChangeList: (NSData *) pcl;
withChangeKey: (NSData *) newChangeKey;
- (NSNumber *) lastModifiedFromMessageChangeNumber: (NSString *) changeNumber;
- (NSString *) changeNumberForMessageWithKey: (NSString *) messageKey;
- (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey;
+25 -202
View File
@@ -75,7 +75,6 @@ static Class NSNumberK;
[SOGoMAPIDBMessage objectWithName: @"versions.plist"
inContainer: dbFolder]);
[versionsMessage setObjectType: MAPIInternalCacheObject];
[versionsMessage reloadIfNeeded];
}
- (void) dealloc
@@ -86,9 +85,9 @@ static Class NSNumberK;
[super dealloc];
}
- (enum mapistore_error) deleteFolder
- (int) deleteFolder
{
enum mapistore_error rc;
int rc;
NSException *error;
NSString *name;
@@ -138,8 +137,8 @@ static Class NSNumberK;
[sogoObject renameTo: newDisplayName];
}
- (enum mapistore_error) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSString *displayName;
Class cClass;
@@ -262,6 +261,7 @@ static Class NSNumberK;
*/
- (void) _setChangeKey: (NSData *) changeKey
forMessageEntry: (NSMutableDictionary *) messageEntry
inChangeListOnly: (BOOL) inChangeListOnly
{
struct XID *xid;
NSString *guid;
@@ -270,15 +270,19 @@ static Class NSNumberK;
NSMutableDictionary *changeList;
xid = [changeKey asXIDInMemCtx: NULL];
guid = [NSString stringWithGUID: &xid->NameSpaceGuid];
globCnt = [NSData dataWithBytes: xid->LocalId.data length: xid->LocalId.length];
guid = [NSString stringWithGUID: &xid->GUID];
globCnt = [NSData dataWithBytes: xid->Data length: xid->Size];
talloc_free (xid);
/* 1. set change key association */
changeKeyDict = [NSDictionary dictionaryWithObjectsAndKeys: guid, @"GUID",
globCnt, @"LocalId",
nil];
[messageEntry setObject: changeKeyDict forKey: @"ChangeKey"];
if (!inChangeListOnly)
{
/* 1. set change key association */
changeKeyDict = [NSDictionary dictionaryWithObjectsAndKeys:
guid, @"GUID",
globCnt, @"LocalId",
nil];
[messageEntry setObject: changeKeyDict forKey: @"ChangeKey"];
}
/* 2. append/update predecessor change list */
changeList = [messageEntry objectForKey: @"PredecessorChangeList"];
@@ -292,77 +296,6 @@ static Class NSNumberK;
[changeList setObject: globCnt forKey: guid];
}
- (void) _updatePredecessorChangeList: (NSData *) predecessorChangeList
forMessageEntry: (NSMutableDictionary *) messageEntry
withOldChangeKey: (NSData *) oldChangeKey
{
NSData *globCnt, *oldGlobCnt;
NSDictionary *changeKeyDict;
NSString *guid;
NSMutableDictionary *changeList;
struct SizedXid *sizedXIDList;
struct XID xid, *givenChangeKey;
TALLOC_CTX *localMemCtx;
uint32_t i, length;
localMemCtx = talloc_new (NULL);
if (!localMemCtx)
{
[self errorWithFormat: @"No more memory"];
return;
}
if (predecessorChangeList)
{
sizedXIDList = [predecessorChangeList asSizedXidArrayInMemCtx: localMemCtx with: &length];
changeList = [messageEntry objectForKey: @"PredecessorChangeList"];
if (!changeList)
{
changeList = [NSMutableDictionary new];
[messageEntry setObject: changeList
forKey: @"PredecessorChangeList"];
[changeList release];
}
if (sizedXIDList) {
for (i = 0; i < length; i++)
{
xid = sizedXIDList[i].XID;
guid = [NSString stringWithGUID: &xid.NameSpaceGuid];
globCnt = [NSData dataWithBytes: xid.LocalId.data length: xid.LocalId.length];
oldGlobCnt = [changeList objectForKey: guid];
if (!oldGlobCnt || ([globCnt compare: oldGlobCnt] == NSOrderedDescending))
[changeList setObject: globCnt forKey: guid];
}
}
}
if (oldChangeKey)
{
givenChangeKey = [oldChangeKey asXIDInMemCtx: localMemCtx];
if (givenChangeKey) {
guid = [NSString stringWithGUID: &givenChangeKey->NameSpaceGuid];
globCnt = [NSData dataWithBytes: givenChangeKey->LocalId.data length: givenChangeKey->LocalId.length];
changeKeyDict = [messageEntry objectForKey: @"ChangeKey"];
if (!changeKeyDict ||
([guid isEqualToString: [changeKeyDict objectForKey: @"GUID"]]
&& ([globCnt compare: [changeKeyDict objectForKey: @"LocalId"]] == NSOrderedDescending)))
{
/* The given change key is greater than current one stored in
metadata or it does not exist */
[messageEntry setObject: [NSDictionary dictionaryWithObjectsAndKeys: guid, @"GUID",
globCnt, @"LocalId",
nil]
forKey: @"ChangeKey"];
}
}
}
talloc_free (localMemCtx);
}
- (EOQualifier *) componentQualifier
{
if (!componentQualifier)
@@ -532,7 +465,8 @@ static Class NSNumberK;
// A GLOBCNT structure is a 6-byte global namespace counter,
// we strip the first 2 bytes. The first two bytes is the ReplicaId
changeKey = [self getReplicaKeyFromGlobCnt: newChangeNum >> 16];
[self _setChangeKey: changeKey forMessageEntry: messageEntry];
[self _setChangeKey: changeKey forMessageEntry: messageEntry
inChangeListOnly: NO];
}
now = [NSCalendarDate date];
@@ -548,123 +482,13 @@ static Class NSNumberK;
return rc;
}
- (BOOL) synchroniseCacheFor: (NSString *) nameInContainer
{
/* Try to synchronise old messages in versions.plist cache using an
specific c_name. It returns a boolean indicating if the
synchronisation was carried out succesfully.
It should be used as last resort, keeping synchroniseCache as the
main sync entry point. */
uint64_t changeNumber;
NSString *changeNumberStr;
NSData *changeKey;
NSNumber *cLastModified, *cDeleted, *cVersion;
EOFetchSpecification *fs;
EOQualifier *searchQualifier, *fetchQualifier;
NSArray *fetchResults;
NSDictionary *result;
NSMutableDictionary *currentProperties, *messages, *mapping, *messageEntry;
GCSFolder *ocsFolder;
static NSArray *fields;
[versionsMessage reloadIfNeeded];
currentProperties = [versionsMessage properties];
messages = [currentProperties objectForKey: @"Messages"];
if (!messages)
{
messages = [NSMutableDictionary new];
[currentProperties setObject: messages forKey: @"Messages"];
[messages release];
}
messageEntry = [messages objectForKey: nameInContainer];
if (!messageEntry)
{
/* Fetch the message by its name */
if (!fields)
fields = [[NSArray alloc]
initWithObjects: @"c_name", @"c_version", @"c_lastmodified",
@"c_deleted", nil];
searchQualifier = [[EOKeyValueQualifier alloc] initWithKey: @"c_name"
operatorSelector: EOQualifierOperatorEqual
value: nameInContainer];
fetchQualifier = [[EOAndQualifier alloc]
initWithQualifiers: searchQualifier,
[self contentComponentQualifier],
nil];
[fetchQualifier autorelease];
[searchQualifier release];
ocsFolder = [sogoObject ocsFolder];
fs = [EOFetchSpecification
fetchSpecificationWithEntityName: [ocsFolder folderName]
qualifier: fetchQualifier
sortOrderings: nil];
fetchResults = [ocsFolder fetchFields: fields
fetchSpecification: fs
ignoreDeleted: NO];
if ([fetchResults count] == 1)
{
result = [fetchResults objectAtIndex: 0];
cLastModified = [result objectForKey: @"c_lastmodified"];
cDeleted = [result objectForKey: @"c_deleted"];
if ([cDeleted isKindOfClass: NSNumberK] && [cDeleted intValue])
cVersion = [NSNumber numberWithInt: -1];
else
cVersion = [result objectForKey: @"c_version"];
changeNumber = [[self context] getNewChangeNumber];
changeNumberStr = [NSString stringWithUnsignedLongLong: changeNumber];
/* Create new message entry in Messages dict */
messageEntry = [NSMutableDictionary new];
[messages setObject: messageEntry forKey: nameInContainer];
[messageEntry release];
/* Store cLastModified, cVersion and the change number */
[messageEntry setObject: cLastModified forKey: @"c_lastmodified"];
[messageEntry setObject: cVersion forKey: @"c_version"];
[messageEntry setObject: changeNumberStr forKey: @"version"];
/* Store the change key */
changeKey = [self getReplicaKeyFromGlobCnt: changeNumber >> 16];
[self _setChangeKey: changeKey forMessageEntry: messageEntry];
/* Store the changeNumber -> cLastModified mapping */
mapping = [currentProperties objectForKey: @"VersionMapping"];
if (!mapping)
{
mapping = [NSMutableDictionary new];
[currentProperties setObject: mapping forKey: @"VersionMapping"];
[mapping release];
}
[mapping setObject: cLastModified forKey: changeNumberStr];
/* Save the message */
[versionsMessage save];
return YES;
}
else
return NO;
}
/* If message entry exists, then synchroniseCache did its job */
return YES;
}
- (void) updateVersionsForMessageWithKey: (NSString *) messageKey
withChangeKey: (NSData *) oldChangeKey
andPredecessorChangeList: (NSData *) pcl
withChangeKey: (NSData *) newChangeKey
{
NSMutableDictionary *messages, *messageEntry;
[self synchroniseCache];
if (oldChangeKey || pcl)
if (newChangeKey)
{
messages = [[versionsMessage properties] objectForKey: @"Messages"];
messageEntry = [messages objectForKey: messageKey];
@@ -672,8 +496,8 @@ static Class NSNumberK;
[NSException raise: @"MAPIStoreIOException"
format: @"no version record found for message '%@'",
messageKey];
[self _updatePredecessorChangeList: pcl forMessageEntry: messageEntry
withOldChangeKey: oldChangeKey];
[self _setChangeKey: newChangeKey forMessageEntry: messageEntry
inChangeListOnly: YES];
[versionsMessage save];
}
}
@@ -681,12 +505,12 @@ static Class NSNumberK;
- (NSNumber *) lastModifiedFromMessageChangeNumber: (NSString *) changeNumber
{
NSDictionary *mapping;
NSNumber *lastModified;
NSNumber *modseq;
mapping = [[versionsMessage properties] objectForKey: @"VersionMapping"];
lastModified = [mapping objectForKey: changeNumber];
modseq = [mapping objectForKey: changeNumber];
return lastModified;
return modseq;
}
- (NSString *) changeNumberForMessageWithKey: (NSString *) messageKey
@@ -859,7 +683,6 @@ static Class NSNumberK;
woContext = [[self userContext] woContext];
activeUserRoles = [activeUser rolesForObject: sogoObject
inContext: woContext];
activeUserRoles = [self expandRoles: activeUserRoles];
[activeUserRoles retain];
}
-7
View File
@@ -23,8 +23,6 @@
#ifndef MAPISTOREGCSMESSAGE_H
#define MAPISTOREGCSMESSAGE_H
#import <SOGo/SOGoUser.h>
#import "MAPIStoreMessage.h"
@interface MAPIStoreGCSMessage : MAPIStoreMessage
@@ -32,11 +30,6 @@
}
/* subclass helpers */
/* Return the message original creator */
- (NSString *) creator;
- (NSString *) owner;
- (SOGoUser *) ownerUser;
- (void) updateVersions;
@end
+82 -125
View File
@@ -20,12 +20,10 @@
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSValue.h>
#import <NGObjWeb/SoSecurityManager.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSObject+Values.h>
#import <SOGo/SOGoContentObject.h>
@@ -37,7 +35,6 @@
#import "MAPIStoreTypes.h"
#import "MAPIStoreUserContext.h"
#import "NSData+MAPIStore.h"
#import "NSString+MAPIStore.h"
#import "MAPIStoreGCSMessage.h"
@@ -57,28 +54,76 @@
return [sogoObject lastModified];
}
- (enum mapistore_error) getPidTagCreatorName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAccess: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
NSString *creator;
MAPIStoreContext *context;
WOContext *woContext;
SoSecurityManager *sm;
MAPIStoreUserContext *userContext;
uint32_t access;
creator = [self creator];
if (creator)
{
*data = [creator asUnicodeInMemCtx: memCtx];
rc = MAPISTORE_SUCCESS;
}
context = [self context];
userContext = [self userContext];
if ([[context activeUser] isEqual: [userContext sogoUser]])
access = 0x03;
else
rc = MAPISTORE_ERR_NOT_FOUND;
{
sm = [SoSecurityManager sharedSecurityManager];
woContext = [userContext woContext];
return rc;
access = 0;
if (![sm validatePermission: SoPerm_ChangeImagesAndFiles
onObject: sogoObject
inContext: woContext])
access |= 1;
if (![sm validatePermission: SoPerm_AccessContentsInformation
onObject: sogoObject
inContext: woContext])
access |= 2;
if (![sm validatePermission: SOGoPerm_DeleteObject
onObject: sogoObject
inContext: woContext])
access |= 4;
}
*data = MAPILongValue (memCtx, access);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagChangeKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAccessLevel: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc = MAPISTORE_SUCCESS;
MAPIStoreContext *context;
MAPIStoreUserContext *userContext;
WOContext *woContext;
SoSecurityManager *sm;
uint32_t accessLvl;
context = [self context];
userContext = [self userContext];
if ([[context activeUser] isEqual: [userContext sogoUser]])
accessLvl = 1;
else
{
sm = [SoSecurityManager sharedSecurityManager];
woContext = [userContext woContext];
if (![sm validatePermission: SoPerm_ChangeImagesAndFiles
onObject: sogoObject
inContext: woContext])
accessLvl = 1;
else
accessLvl = 0;
}
*data = MAPILongValue (memCtx, accessLvl);
return MAPISTORE_SUCCESS;
}
- (int) getPidTagChangeKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
int rc = MAPISTORE_SUCCESS;
NSData *changeKey;
MAPIStoreGCSFolder *parentFolder;
NSString *nameInContainer;
@@ -95,25 +140,18 @@
[parentFolder synchroniseCache];
changeKey = [parentFolder changeKeyForMessageWithKey: nameInContainer];
}
if (changeKey)
*data = [changeKey asBinaryInMemCtx: memCtx];
else
{
[self warnWithFormat: @"No change key for %@ in folder %@",
nameInContainer,
[parentFolder url]
];
rc = MAPISTORE_ERR_NOT_FOUND;
}
if (!changeKey)
abort ();
*data = [changeKey asBinaryInMemCtx: memCtx];
}
return rc;
}
- (enum mapistore_error) getPidTagPredecessorChangeList: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagPredecessorChangeList: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc = MAPISTORE_SUCCESS;
int rc = MAPISTORE_SUCCESS;
NSData *changeList;
MAPIStoreGCSFolder *parentFolder;
@@ -142,8 +180,7 @@
{
uint64_t version = ULLONG_MAX;
NSString *changeNumber;
BOOL synced;
if (!isNew)
{
changeNumber = [(MAPIStoreGCSFolder *) container
@@ -152,28 +189,16 @@
{
[self warnWithFormat: @"attempting to get change number"
@" by synchronising folder..."];
synced = [(MAPIStoreGCSFolder *) container synchroniseCache];
if (synced)
[(MAPIStoreGCSFolder *) container synchroniseCache];
changeNumber = [(MAPIStoreGCSFolder *) container
changeNumberForMessageWithKey: [self nameInContainer]];
if (changeNumber)
[self logWithFormat: @"got one"];
else
{
changeNumber = [(MAPIStoreGCSFolder *) container
changeNumberForMessageWithKey: [self nameInContainer]];
}
if (!changeNumber)
{
[self warnWithFormat: @"attempting to get change number"
@" by synchronising this specific message..."];
synced = [(MAPIStoreGCSFolder *) container
synchroniseCacheFor: [self nameInContainer]];
if (synced)
{
changeNumber = [(MAPIStoreGCSFolder *) container
changeNumberForMessageWithKey: [self nameInContainer]];
}
if (!changeNumber)
{
[self errorWithFormat: @"still nothing. We crash!"];
abort();
}
[self errorWithFormat: @"still nothing. We crash!"];
abort();
}
}
version = [changeNumber unsignedLongLongValue] >> 16;
@@ -184,81 +209,13 @@
- (void) updateVersions
{
/* Update ChangeKey and PredecessorChangeList on message's save */
NSData *newChangeKey, *predecessorChangeList;
NSData *newChangeKey;
newChangeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)];
predecessorChangeList = [properties objectForKey: MAPIPropertyKey (PR_PREDECESSOR_CHANGE_LIST)];
[(MAPIStoreGCSFolder *) container
updateVersionsForMessageWithKey: [self nameInContainer]
withChangeKey: newChangeKey
andPredecessorChangeList: predecessorChangeList];
}
//----------------------
// Sharing
//----------------------
- (NSString *) creator
{
return [self owner];
}
- (NSString *) owner
{
return [sogoObject ownerInContext: nil];
}
- (SOGoUser *) ownerUser
{
NSString *ownerName;
SOGoUser *owner = nil;
ownerName = [self owner];
if ([ownerName length] != 0)
owner = [SOGoUser userWithLogin: ownerName];
return owner;
}
- (BOOL) subscriberCanModifyMessage
{
BOOL rc;
NSArray *roles;
roles = [self activeUserRoles];
if (isNew)
rc = [roles containsObject: SOGoRole_ObjectCreator];
else
rc = [roles containsObject: SOGoRole_ObjectEditor];
/* Check if the message is owned and it has permission to edit it */
if (!rc && [roles containsObject: MAPIStoreRightEditOwn])
rc = [[[container context] activeUser] isEqual: [self ownerUser]];
return rc;
}
- (BOOL) subscriberCanDeleteMessage
{
BOOL rc;
NSArray *roles;
roles = [self activeUserRoles];
rc = [roles containsObject: SOGoRole_ObjectEraser];
/* Check if the message is owned and it has permission to delete it */
if (!rc && [roles containsObject: MAPIStoreRightDeleteOwn])
{
NSString *currentUser;
currentUser = [[container context] activeUser];
rc = [currentUser isEqual: [self ownerUser]];
}
return rc;
updateVersionsForMessageWithKey: [self nameInContainer]
withChangeKey: newChangeKey];
}
@end
+4 -14
View File
@@ -27,7 +27,6 @@
#import <Foundation/NSString.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSObject+Values.h>
#import <EOControl/EOFetchSpecification.h>
#import <EOControl/EOQualifier.h>
@@ -39,6 +38,7 @@
#import "MAPIStoreTypes.h"
#import "MAPIStoreGCSFolder.h"
#import "MAPIStoreGCSMessageTable.h"
#undef DEBUG
@@ -89,31 +89,21 @@
if (res->ulPropTag == PidTagChangeNumber)
{
NSString *changeNumber;
value = NSObjectFromMAPISPropValue (&res->lpProp);
changeNumber = [NSString stringWithUnsignedLongLong: [(NSNumber *)value unsignedLongLongValue]];
lastModified = [(MAPIStoreGCSFolder *)
container lastModifiedFromMessageChangeNumber: changeNumber];
container lastModifiedFromMessageChangeNumber: value];
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
//[self logWithFormat: @" c_lastmodified: %@", lastModified];
if (lastModified)
{
SEL operator;
operator = [self operatorFromRestrictionOperator: res->relop];
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"c_lastmodified"
operatorSelector: operator
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
value: lastModified];
[*qualifier autorelease];
rc = MAPIRestrictionStateNeedsEval;
}
else
{
[self logWithFormat: @"No last modified found for: 0x%.16"PRIx64". Then no restriction applied",
[value unsignedLongLongValue]];
rc = MAPIRestrictionStateAlwaysTrue;
}
rc = MAPIRestrictionStateAlwaysTrue;
}
else
{
+35 -24
View File
@@ -30,7 +30,6 @@
#import <SOGo/NSArray+Utilities.h>
#import <Mailer/SOGoMailBodyPart.h>
#import <Mailer/SOGoMailObject.h>
#import <Mailer/NSDictionary+Mail.h>
#import "MAPIStoreTypes.h"
#import "MAPIStoreMailMessage.h"
@@ -76,24 +75,24 @@
ASSIGN (bodyPart, newBodyPart);
}
- (enum mapistore_error) getPidTagAttachMethod: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachMethod: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, 0x00000001); // afByValue
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachTag: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachTag: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[self mimeAttachTag] asBinaryInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachSize: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachSize: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
uint32_t longValue;
@@ -103,13 +102,13 @@
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagRecordKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagRecordKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
static char recordBytes[] = {0xd9, 0xd8, 0x11, 0xa3, 0xe2, 0x90, 0x18, 0x41,
0x9e, 0x04, 0x58, 0x46, 0x9d, 0x6d, 0x1b,
0x68};
*data = [[NSData dataWithBytes: recordBytes length: 16]
asBinaryInMemCtx: memCtx];
@@ -118,19 +117,31 @@
- (NSString *) _fileName
{
return [bodyInfo filename];
NSString *fileName;
NSDictionary *parameters;
fileName = [[bodyInfo objectForKey: @"parameterList"]
objectForKey: @"name"];
if (!fileName)
{
parameters = [[bodyInfo objectForKey: @"disposition"]
objectForKey: @"parameterList"];
fileName = [parameters objectForKey: @"filename"];
}
return fileName;
}
- (enum mapistore_error) getPidTagAttachLongFilename: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachLongFilename: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[self _fileName] asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachFilename: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachFilename: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSString *fileName, *baseName, *ext;
@@ -149,8 +160,8 @@
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSString *fileName;
@@ -165,17 +176,17 @@
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachContentId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
- (int) getPidTagAttachContentId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[bodyInfo objectForKey: @"bodyId"]
asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachMimeTag: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachMimeTag: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSString *mimeTag, *fileName;
@@ -193,8 +204,8 @@
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAttachDataBinary: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAttachDataBinary: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[bodyPart fetchBLOBWithPeek: YES] asBinaryInMemCtx: memCtx];
+11 -13
View File
@@ -160,25 +160,23 @@ MakeDisplayFolderName (NSString *folderName)
for (count = 0; count < max; count++)
{
context = talloc_zero (memCtx, struct mapistore_contexts_list);
// secondaryFolders has the names (1) Imap4Encoded ,(2) asCSSIdentifier and (3) "folder"-prefixed
// e.g.: folderProbl&AOg-mes_SP_de_SP_synchronisation
// secondaryFolders has the names (1) Imap4Encoded and (2) asCSSIdentifier
// e.g.: Probl&AOg-mes_SP_de_SP_synchronisation
currentName = [secondaryFolders objectAtIndex: count];
// To get the real name we have to revert that (applying the decode functions
// in reverse order)
// To get the real name we have to revert that (applying the decode functions)
// in reverse order
// e.g.: Problèmes de synchronisation
realName = [[[currentName substringFromIndex: 6]
fromCSSIdentifier]
stringByDecodingImap4FolderName];
realName = [[currentName fromCSSIdentifier]
stringByDecodingImap4FolderName];
// And finally to represent that as URI we have to (1) asCSSIdentifier,
// (2) Imap4Encode (3) AddPercentEscapes and (4) add the "folder" prefix
// e.g.: folderProbl&AOg-mes_SP_de_SP_synchronisation
// (2) Imap4Encode and (3) AddPercentEscapes
// e.g.: Probl&AOg-mes_SP_de_SP_synchronisation
// In the example there are no percent escapes added because is already ok
stringData = [[[realName asCSSIdentifier]
stringByEncodingImap4FolderName]
stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
stringData = [NSString stringWithFormat: @"folder%@", stringData];
context->url = [[NSString stringWithFormat: @"%@%@", urlBase, stringData] asUnicodeInMemCtx: context];
context->name = [realName asUnicodeInMemCtx: context];
context->name = [[realName substringFromIndex: 6] asUnicodeInMemCtx: context];
context->main_folder = false;
context->role = MAPISTORE_MAIL_ROLE;
context->tag = "tag";
@@ -202,7 +200,7 @@ MakeDisplayFolderName (NSString *folderName)
andTDBIndexing: NULL];
accountFolder = [[userContext rootFolders] objectForKey: @"mail"];
folderName = [NSString stringWithFormat: @"folder%@",
[[newFolderName stringByEncodingImap4FolderName] asCSSIdentifier]];
[newFolderName asCSSIdentifier]];
newFolder = [SOGoMailFolder objectWithName: folderName
inContainer: accountFolder];
if ([newFolder create])
@@ -211,7 +209,7 @@ MakeDisplayFolderName (NSString *folderName)
withString: @"%40"],
[userName stringByReplacingOccurrencesOfString: @"@"
withString: @"%40"],
[folderName stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
[[folderName stringByEncodingImap4FolderName] stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
else
mapistoreURI = nil;
-2
View File
@@ -52,8 +52,6 @@
- (NSString *) changeNumberForMessageUID: (NSString *) messageUid;
- (void) setChangeKey: (NSData *) changeKey
forMessageWithKey: (NSString *) messageKey;
- (BOOL) updatePredecessorChangeListWith: (NSData *) changeKey
forMessageWithKey: (NSString *) messageKey;
- (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey;
- (NSData *) predecessorChangeListForMessageWithKey: (NSString *) messageKey;
+124 -234
View File
@@ -68,13 +68,10 @@
static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
#include <gen_ndr/exchange.h>
#undef DEBUG
#include <util/attr.h>
#include <libmapi/libmapi.h>
#include <libmapiproxy.h>
#include <limits.h>
#include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h>
@@ -112,7 +109,6 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
[SOGoMAPIDBMessage objectWithName: @"versions.plist"
inContainer: dbFolder]);
[versionsMessage setObjectType: MAPIInternalCacheObject];
[versionsMessage reloadIfNeeded];
}
- (BOOL) ensureFolderExists
@@ -182,7 +178,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME_UNICODE)
folderName = [NSString stringWithUTF8String: aRow->lpProps[i].value.lpszW];
else if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME)
folderName = [NSString stringWithUTF8String: (const char *) aRow->lpProps[i].value.lpszA];
folderName = [NSString stringWithUTF8String: aRow->lpProps[i].value.lpszA];
}
if (folderName)
@@ -208,9 +204,9 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
return rc;
}
- (enum mapistore_error) deleteFolder
- (int) deleteFolder
{
enum mapistore_error rc;
int rc;
NSException *error;
NSString *name;
@@ -234,8 +230,8 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
return (rc == MAPISTORE_SUCCESS) ? [super deleteFolder] : rc;
}
- (enum mapistore_error) getPidTagContentUnreadCount: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagContentUnreadCount: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
EOQualifier *searchQualifier;
uint32_t longValue;
@@ -250,75 +246,14 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagContainerClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagContainerClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"IPF.Note" asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (EOQualifier *) simplifyQualifier: (EOQualifier *) qualifier
{
/* Hack: Reduce the number of MODSEQ constraints to a single one as
we assume the difference among MODSEQs will be small enough to
return a small number of UIDs.
This is the only case we do simplify:
MODSEQ >= x | MODSEQ >= y | MODSEQ >= z => MODSEQ >= min(x,y,z)
*/
if (qualifier && [qualifier isKindOfClass: [EOOrQualifier class]])
{
EOQualifier *simplifiedQualifier;
NSArray *quals;
NSNumber *minModseq;
NSUInteger i, count;
quals = [(EOOrQualifier *)qualifier qualifiers];
count = [quals count];
if (count < 2)
return qualifier;
minModseq = [NSNumber numberWithUnsignedLongLong: ULLONG_MAX];
for (i = 0; i < count; i++)
{
EOQualifier *subQualifier;
subQualifier = [quals objectAtIndex: i];
if ([subQualifier isKindOfClass: [EOAndQualifier class]]
&& [[(EOAndQualifier *)subQualifier qualifiers] count] == 1)
subQualifier = [[(EOAndQualifier *)subQualifier qualifiers] objectAtIndex: 0];
if ([subQualifier isKindOfClass: [EOKeyValueQualifier class]]
&& [[(EOKeyValueQualifier *)subQualifier key] isEqualToString: @"MODSEQ"])
{
NSNumber *value;
value = (NSNumber *)[(EOKeyValueQualifier *)subQualifier value];
if ([minModseq compare: value] == NSOrderedDescending
&& [value unsignedLongLongValue] > 0)
minModseq = (NSNumber *)[(EOKeyValueQualifier *)subQualifier value];
}
else
return qualifier;
}
if ([minModseq unsignedLongLongValue] > 0 && [minModseq unsignedLongLongValue] < ULLONG_MAX)
{
simplifiedQualifier = [[EOKeyValueQualifier alloc]
initWithKey: @"MODSEQ"
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
value: minModseq];
[simplifiedQualifier autorelease];
return simplifiedQualifier;
}
}
return qualifier;
}
- (EOQualifier *) nonDeletedQualifier
{
static EOQualifier *nonDeletedQualifier = nil;
@@ -343,7 +278,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
andSortOrderings: (NSArray *) sortOrderings
{
NSArray *uidKeys;
EOQualifier *fetchQualifier, *simplifiedQualifier;
EOQualifier *fetchQualifier;
if ([self ensureFolderExists])
{
@@ -352,10 +287,9 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
if (qualifier)
{
simplifiedQualifier = [self simplifyQualifier: qualifier];
fetchQualifier
= [[EOAndQualifier alloc] initWithQualifiers:
[self nonDeletedQualifier], simplifiedQualifier,
[self nonDeletedQualifier], qualifier,
nil];
[fetchQualifier autorelease];
}
@@ -582,44 +516,6 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
return [modseq1 compare: modseq2];
}
- (void) _updatePredecessorChangeListWith: (NSData *) predecessorChangeList
forMessageEntry: (NSMutableDictionary *) messageEntry
{
NSData *globCnt, *oldGlobCnt;
NSMutableDictionary *changeList;
NSString *guid;
struct SizedXid *sizedXIDList;
struct XID xid;
uint32_t i, length;
sizedXIDList = [predecessorChangeList asSizedXidArrayInMemCtx: NULL with: &length];
changeList = [messageEntry objectForKey: @"PredecessorChangeList"];
if (!changeList)
{
changeList = [NSMutableDictionary new];
[messageEntry setObject: changeList
forKey: @"PredecessorChangeList"];
[changeList release];
}
if (sizedXIDList) {
for (i = 0; i < length; i++)
{
xid = sizedXIDList[i].XID;
guid = [NSString stringWithGUID: &xid.NameSpaceGuid];
globCnt = [NSData dataWithBytes: xid.LocalId.data length: xid.LocalId.length];
oldGlobCnt = [changeList objectForKey: guid];
if (!oldGlobCnt || ([globCnt compare: oldGlobCnt] == NSOrderedDescending))
[changeList setObject: globCnt forKey: guid];
}
talloc_free (sizedXIDList);
}
[versionsMessage save];
}
- (void) _setChangeKey: (NSData *) changeKey
forMessageEntry: (NSMutableDictionary *) messageEntry
{
@@ -630,8 +526,8 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
NSMutableDictionary *changeList;
xid = [changeKey asXIDInMemCtx: NULL];
guid = [NSString stringWithGUID: &xid->NameSpaceGuid];
globCnt = [NSData dataWithBytes: xid->LocalId.data length: xid->LocalId.length];
guid = [NSString stringWithGUID: &xid->GUID];
globCnt = [NSData dataWithBytes: xid->Data length: xid->Size];
talloc_free (xid);
/* 1. set change key association */
@@ -657,12 +553,13 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
{
BOOL rc = YES;
uint64_t newChangeNum;
NSNumber *ti, *modseq, *lastModseq, *nextModseq;
NSNumber *ti, *modseq, *initialLastModseq, *lastModseq,
*nextModseq;
NSString *changeNumber, *uid, *messageKey;
uint64_t lastModseqNbr;
EOQualifier *searchQualifier;
NSArray *uids, *changeNumbers;
NSUInteger count, max, nFetched;
NSUInteger count, max;
NSArray *fetchResults;
NSDictionary *result;
NSData *changeKey;
@@ -696,6 +593,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
}
lastModseq = [currentProperties objectForKey: @"SyncLastModseq"];
initialLastModseq = lastModseq;
if (lastModseq)
{
lastModseqNbr = [lastModseq unsignedLongLongValue];
@@ -741,13 +639,6 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
= [fetchResults sortedArrayUsingFunction: _compareFetchResultsByMODSEQ
context: NULL];
nFetched = [fetchResults count];
if (nFetched != max) {
[self errorWithFormat: @"Error fetching UIDs. Asked: %d Received: %d."
@"Check the IMAP conversation for details", max, nFetched];
return NO;
}
for (count = 0; count < max; count++)
{
result = [fetchResults objectAtIndex: count];
@@ -786,37 +677,40 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
}
/* 2. we synchronise expunged UIDs */
fetchResults = [(SOGoMailFolder *) sogoObject
fetchUIDsOfVanishedItems: lastModseqNbr];
max = [fetchResults count];
changeNumber = nil;
for (count = 0; count < max; count++)
if (initialLastModseq)
{
uid = [[fetchResults objectAtIndex: count] stringValue];
if ([messages objectForKey: uid])
fetchResults = [(SOGoMailFolder *) sogoObject
fetchUIDsOfVanishedItems: lastModseqNbr];
max = [fetchResults count];
changeNumber = nil;
for (count = 0; count < max; count++)
{
if (!changeNumber)
uid = [[fetchResults objectAtIndex: count] stringValue];
if ([messages objectForKey: uid])
{
newChangeNum = [[self context] getNewChangeNumber];
changeNumber = [NSString stringWithUnsignedLongLong: newChangeNum];
if (!changeNumber)
{
newChangeNum = [[self context] getNewChangeNumber];
changeNumber = [NSString stringWithUnsignedLongLong: newChangeNum];
}
[messages removeObjectForKey: uid];
[self logWithFormat: @"Removed message entry for UID %@", uid];
}
else
{
[self logWithFormat:@"Message entry not found for UID %@", uid];
}
[messages removeObjectForKey: uid];
[self logWithFormat: @"Removed message entry for UID %@", uid];
}
else
if (changeNumber)
{
[self logWithFormat:@"Message entry not found for UID %@", uid];
[currentProperties setObject: changeNumber
forKey: @"SyncLastDeleteChangeNumber"];
[mapping setObject: lastModseq forKey: changeNumber];
foundChange = YES;
}
}
if (changeNumber)
{
[currentProperties setObject: changeNumber
forKey: @"SyncLastDeleteChangeNumber"];
[mapping setObject: lastModseq forKey: changeNumber];
foundChange = YES;
}
if (foundChange)
{
@@ -1030,7 +924,8 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
return changeNumber;
}
- (NSMutableDictionary *) _messageEntryFromMessageKey: (NSString *) messageKey
- (void) setChangeKey: (NSData *) changeKey
forMessageWithKey: (NSString *) messageKey
{
NSMutableDictionary *messages, *messageEntry;
NSString *messageUid;
@@ -1041,7 +936,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
messageEntry = [messages objectForKey: messageUid];
if (!messageEntry)
{
[self warnWithFormat: @"attempting to synchronise to get the message entry for "
[self warnWithFormat: @"attempting to synchronise to set the change key for "
@"this message %@", messageKey];
synced = [self synchroniseCacheForUID: messageUid];
if (synced)
@@ -1052,57 +947,11 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
abort ();
}
}
return messageEntry;
}
- (void) setChangeKey: (NSData *) changeKey
forMessageWithKey: (NSString *) messageKey
{
[self _setChangeKey: changeKey
forMessageEntry: [self _messageEntryFromMessageKey: messageKey]];
[self _setChangeKey: changeKey forMessageEntry: messageEntry];
[versionsMessage save];
}
- (BOOL) updatePredecessorChangeListWith: (NSData *) changeKey
forMessageWithKey: (NSString *) messageKey
{
/* Update predecessor change list property given the change key. It
returns if the change key has been added to the list or not */
BOOL added = NO;
NSData *globCnt, *oldGlobCnt;
NSDictionary *messageEntry;
NSMutableDictionary *changeList;
NSString *guid;
struct XID *xid;
xid = [changeKey asXIDInMemCtx: NULL];
guid = [NSString stringWithGUID: &xid->NameSpaceGuid];
globCnt = [NSData dataWithBytes: xid->LocalId.data length: xid->LocalId.length];
talloc_free (xid);
messageEntry = [self _messageEntryFromMessageKey: messageKey];
if (messageEntry)
{
changeList = [messageEntry objectForKey: @"PredecessorChangeList"];
if (changeList)
{
oldGlobCnt = [changeList objectForKey: guid];
if (!oldGlobCnt || ([globCnt compare: oldGlobCnt] == NSOrderedDescending))
{
[changeList setObject: globCnt forKey: guid];
[versionsMessage save];
added = YES;
}
}
else
[self errorWithFormat: @"Missing predecessor change list to update"];
}
return added;
}
- (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey
{
NSDictionary *messages, *changeKeyDict;
@@ -1363,14 +1212,14 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
// Move (or eventually copy) the mails identified by
// "srcMids" from the source folder into this folder.
//
- (enum mapistore_error) moveCopyMessagesWithMIDs: (uint64_t *) srcMids
andCount: (uint32_t) midCount
fromFolder: (MAPIStoreFolder *) sourceFolder
withMIDs: (uint64_t *) targetMids
andChangeKeys: (struct Binary_r **) targetChangeKeys
andPredecessorChangeLists: (struct Binary_r **) targetPredecessorChangeLists
wantCopy: (uint8_t) wantCopy
inMemCtx: (TALLOC_CTX *) memCtx
- (int) moveCopyMessagesWithMIDs: (uint64_t *) srcMids
andCount: (uint32_t) midCount
fromFolder: (MAPIStoreFolder *) sourceFolder
withMIDs: (uint64_t *) targetMids
andChangeKeys: (struct Binary_r **) targetChangeKeys
wantCopy: (uint8_t) wantCopy
inMemCtx: (TALLOC_CTX *) memCtx
{
NGImap4Connection *connection;
NGImap4Client *client;
@@ -1382,13 +1231,12 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
NSDictionary *result;
NSUInteger count;
NSArray *a;
NSData *changeList;
NSData *changeKey;
if (![sourceFolder isKindOfClass: [MAPIStoreMailFolder class]])
return [super moveCopyMessagesWithMIDs: srcMids andCount: midCount
fromFolder: sourceFolder withMIDs: targetMids
andChangeKeys: targetChangeKeys
andPredecessorChangeLists: targetPredecessorChangeLists
wantCopy: wantCopy
inMemCtx: memCtx];
@@ -1477,11 +1325,11 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
[self synchroniseCache];
for (count = 0; count < midCount; count++)
{
changeList = [NSData dataWithBinary: targetPredecessorChangeLists[count]];
changeKey = [NSData dataWithBinary: targetChangeKeys[count]];
messageKey = [NSString stringWithFormat: @"%@.eml",
[destUIDs objectAtIndex: count]];
[self _updatePredecessorChangeListWith: changeList
forMessageEntry: [self _messageEntryFromMessageKey: messageKey]];
[self setChangeKey: changeKey
forMessageWithKey: messageKey];
}
}
@@ -1656,7 +1504,7 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
- (id) lookupMessage: (NSString *) messageKey
{
MAPIStoreMailMessage *message;
NSArray *rawBodyData;
NSData *rawBodyData;
message = [super lookupMessage: messageKey];
if (message)
@@ -1710,10 +1558,10 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
rights |= RightsCreateItems;
if ([roles containsObject: SOGoRole_ObjectEraser]
&& [roles containsObject: SOGoRole_FolderEraser])
rights |= RightsDeleteAll | RightsDeleteOwn;
rights |= RightsDeleteAll;
if ([roles containsObject: SOGoRole_ObjectEditor])
rights |= RightsEditAll | RightsEditOwn;
rights |= RightsEditAll;
if ([roles containsObject: SOGoRole_ObjectViewer])
rights |= RightsReadItems;
if ([roles containsObject: SOGoRole_FolderCreator])
@@ -1730,31 +1578,73 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
- (enum mapistore_error) preloadMessageBodiesWithKeys: (NSArray *) keys
ofTableType: (enum mapistore_table_type) tableType
{
NSEnumerator *enumerator;
NSUInteger max;
NSString *messageKey;
MAPIStoreMailMessage *message;
NSArray* bodyContent;
NSMutableSet *bodyPartKeys;
NSMutableDictionary *keyAssoc;
NSDictionary *response;
NSUInteger count, max;
NSString *messageKey, *messageUid, *bodyPartKey;
NGImap4Client *client;
NSArray *fetch;
NSData *bodyContent;
if (tableType != MAPISTORE_MESSAGE_TABLE)
return MAPISTORE_SUCCESS;
[bodyData removeAllObjects];
max = [keys count];
if (max == 0)
return MAPISTORE_SUCCESS;
enumerator = [keys objectEnumerator];
while ((messageKey = [enumerator nextObject]))
if (tableType == MAPISTORE_MESSAGE_TABLE)
{
message = [self lookupMessage: messageKey];
if (message)
[bodyData removeAllObjects];
max = [keys count];
if (max > 0)
{
bodyContent = [message getBodyContent];
if (bodyContent)
bodyPartKeys = [NSMutableSet setWithCapacity: max];
keyAssoc = [NSMutableDictionary dictionaryWithCapacity: max];
for (count = 0; count < max; count++)
{
[bodyData setObject: bodyContent forKey: messageKey];
messageKey = [keys objectAtIndex: count];
message = [self lookupMessage: messageKey];
if (message)
{
bodyPartKey = [message bodyContentPartKey];
if (bodyPartKey)
{
[bodyPartKeys addObject: bodyPartKey];
messageUid = [self messageUIDFromMessageKey: messageKey];
/* If the bodyPartKey include peek, remove it as it is not returned
as key in the IMAP server response.
IMAP conversation example:
a4 UID FETCH 1 (UID BODY.PEEK[text])
* 1 FETCH (UID 1 BODY[TEXT] {1677}
*/
bodyPartKey = [bodyPartKey stringByReplacingOccurrencesOfString: @"body.peek"
withString: @"body"];
[keyAssoc setObject: bodyPartKey forKey: messageUid];
}
}
}
client = [[(SOGoMailFolder *) sogoObject imap4Connection] client];
[client select: [sogoObject absoluteImap4Name]];
response = [client fetchUids: [keyAssoc allKeys]
parts: [bodyPartKeys allObjects]];
fetch = [response objectForKey: @"fetch"];
max = [fetch count];
for (count = 0; count < max; count++)
{
response = [fetch objectAtIndex: count];
messageUid = [[response objectForKey: @"uid"] stringValue];
bodyPartKey = [keyAssoc objectForKey: messageUid];
if (bodyPartKey)
{
bodyContent = [[response objectForKey: bodyPartKey]
objectForKey: @"data"];
if (bodyContent)
{
messageKey = [NSString stringWithFormat: @"%@.eml",
messageUid];
[bodyData setObject: bodyContent forKey: messageKey];
}
}
}
}
}
@@ -1766,8 +1656,8 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
@implementation MAPIStoreOutboxFolder
- (enum mapistore_error) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"Outbox" asUnicodeInMemCtx: memCtx];
+26 -33
View File
@@ -25,10 +25,8 @@
#import "MAPIStoreMessage.h"
@class NSData;
@class NSString;
@class NSArray;
@class NSMutableArray;
@class NSMutableDictionary;
@class MAPIStoreAppointmentWrapper;
@class MAPIStoreMailFolder;
@@ -39,17 +37,12 @@
BOOL mailIsEvent;
BOOL mailIsMeetingRequest;
BOOL mailIsSharingObject;
NSMutableArray *bodyContentKeys;
NSMutableDictionary *bodyPartsEncodings;
NSMutableDictionary *bodyPartsCharsets;
NSMutableDictionary *bodyPartsMimeTypes;
NSMutableDictionary *bodyPartsMixed;
NSString *mimeKey;
NSString *headerCharset;
NSString *headerEncoding;
NSString *headerMimeType;
BOOL bodySetup;
NSArray *bodyContent;
NSData *bodyContent;
BOOL fetchedAttachments;
MAPIStoreAppointmentWrapper *appointmentWrapper;
@@ -57,31 +50,31 @@
- (NSString *) subject;
- (enum mapistore_error) getPidTagIconIndex: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagFlagStatus: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagIconIndex: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagFlagStatus: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagMessageFlags: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagFollowupIcon: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagImportance: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagReceivedByEmailAddress: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagSenderEmailAddress: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagDisplayTo: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagDisplayCc: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagDisplayBcc: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagMessageFlags: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagFollowupIcon: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagImportance: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagReceivedByEmailAddress: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagSenderEmailAddress: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagDisplayTo: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagDisplayCc: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagDisplayBcc: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
/* batch-mode helpers */
- (void) setBodyContentFromRawData: (NSArray *) rawContent;
- (NSArray *) getBodyContent;
- (NSString *) bodyContentPartKey;
- (void) setBodyContentFromRawData: (NSData *) rawContent;
@end
File diff suppressed because it is too large. Load diff
+13 -28
View File
@@ -161,30 +161,15 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
//[self logWithFormat: @" modseq: %.16lx", [modseq unsignedLongLongValue]];
if (modseq)
{
if (res->relop == RELOP_GT)
modseq = [NSNumber numberWithUnsignedLongLong:
[modseq unsignedLongLongValue] + 1];
}
modseq = [NSNumber numberWithUnsignedLongLong:
[modseq unsignedLongLongValue] + 1];
else
modseq = [NSNumber numberWithUnsignedLongLong: 0];
if (res->relop == RELOP_GT || res->relop == RELOP_GE)
{
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"MODSEQ"
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
value: modseq];
[*qualifier autorelease];
rc = MAPIRestrictionStateNeedsEval;
}
else
{
/* Ignore other operations as IMAP only support MODSEQ >= X */
[self warnWithFormat: @"Ignoring '%@' as only supported operators are > and >=",
NSStringFromSelector ([self operatorFromRestrictionOperator: res->relop])];
rc = MAPIRestrictionStateAlwaysTrue;
}
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"MODSEQ"
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
value: modseq];
[*qualifier autorelease];
rc = MAPIRestrictionStateNeedsEval;
}
break;
@@ -340,10 +325,10 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
[self cleanupCaches];
}
- (enum mapistore_error) getRow: (struct mapistore_property_data **) dataP
withRowID: (uint32_t) rowId
andQueryType: (enum mapistore_query_type) queryType
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getRow: (struct mapistore_property_data **) dataP
withRowID: (uint32_t) rowId
andQueryType: (enum mapistore_query_type) queryType
inMemCtx: (TALLOC_CTX *) memCtx
{
if (!fetchedCoreInfos)
{
@@ -352,8 +337,8 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
prefetchCoreInfosForMessageKeys: [self restrictedChildKeys]];
}
return [super getRow: dataP withRowID: rowId
andQueryType: queryType inMemCtx: memCtx];
return [super getRow: dataP withRowID: rowId
andQueryType: queryType inMemCtx: memCtx];
}
@end
+1 -1
View File
@@ -27,7 +27,7 @@
@interface MAPIStoreMailVolatileMessage : MAPIStoreMessage
- (enum mapistore_error) submitWithFlags: (enum SubmitFlags) flags;
- (int) submitWithFlags: (enum SubmitFlags) flags;
@end
+31 -54
View File
@@ -34,7 +34,6 @@
#import <NGExtensions/NGBase64Coding.h>
#import <NGExtensions/NGHashMap.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSObject+Values.h>
#import <NGExtensions/NSString+Encoding.h>
#import <NGMime/NGMimeBodyPart.h>
#import <NGMime/NGMimeMultipartBody.h>
@@ -167,9 +166,9 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
- (BOOL) hasContentId
{
NSString *contentId = [properties
objectForKey: MAPIPropertyKey (PR_ATTACH_CONTENT_ID_UNICODE)];
return contentId && [contentId length] > 0;
return ([properties
objectForKey: MAPIPropertyKey (PR_ATTACH_CONTENT_ID_UNICODE)]
!= nil);
}
- (NGMimeBodyPart *) asMIMEBodyPart
@@ -233,7 +232,7 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
[map addObject: contentDisposition forKey: @"content-disposition"];
contentId = [properties
objectForKey: MAPIPropertyKey (PR_ATTACH_CONTENT_ID_UNICODE)];
if (contentId && [contentId length] > 0)
if (contentId)
[map setObject: [NSString stringWithFormat: @"<%@>", contentId]
forKey: @"content-id"];
bodyPart = [NGMimeBodyPart bodyPartWithHeader: map];
@@ -286,21 +285,21 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
version = [properties objectForKey: @"version"];
return (version
? [version unsignedLongLongValue]
? exchange_globcnt ([version unsignedLongLongValue])
: ULLONG_MAX);
}
- (enum mapistore_error) getPidTagMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"IPM.Note" asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagChangeKey: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagChangeKey: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
NSData *changeKey;
enum mapistore_error rc;
int rc;
changeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)];
if (changeKey)
@@ -338,10 +337,13 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
NSData *entryId;
NSDictionary *allRecipients, *dict, *contactInfos;
SOGoUserManager *mgr;
struct ldb_context *samCtx;
struct mapistore_message *msgData;
struct mapistore_message_recipient *recipient;
enum ulRecipClass type;
samCtx = [[self context] connectionInfo]->sam_ctx;
// [super getMessageData: &msgData inMemCtx: memCtx];
msgData = talloc_zero (memCtx, struct mapistore_message);
@@ -386,7 +388,7 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
{
username = [contactInfos objectForKey: @"sAMAccountName"];
recipient->username = [username asUnicodeInMemCtx: msgData];
entryId = MAPIStoreInternalEntryId ([[self context] connectionInfo], username);
entryId = MAPIStoreInternalEntryId (samCtx, username);
}
else
{
@@ -679,14 +681,6 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
if (!fromResolved)
{
TALLOC_CTX *local_mem_ctx;
local_mem_ctx = talloc_new(NULL);
if (!local_mem_ctx)
{
NSLog (@"%s: Out of memory", __PRETTY_FUNCTION__);
return;
}
NSLog (@"Message without an orig from, try to guess it from PidTagSenderEntryId");
senderEntryId = [mailProperties objectForKey: MAPIPropertyKey (PR_SENDER_ENTRYID)];
if (senderEntryId)
@@ -700,12 +694,12 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
bin32.cb = [senderEntryId length];
bin32.lpb = (uint8_t *) [senderEntryId bytes];
addrBookEntryId = get_AddressBookEntryId (local_mem_ctx, &bin32);
addrBookEntryId = get_AddressBookEntryId (connInfo->sam_ctx, &bin32);
if (addrBookEntryId && [[NSString stringWithGUID: &addrBookEntryId->ProviderUID]
hasSuffix: @"08002b2fe182"])
{
/* TODO: better way to distinguish local and other ones */
username = MAPIStoreSamDBUserAttribute (connInfo, @"legacyExchangeDN",
username = MAPIStoreSamDBUserAttribute (connInfo->sam_ctx, @"legacyExchangeDN",
[NSString stringWithUTF8String: addrBookEntryId->X500DN], @"sAMAccountName");
if (username)
{
@@ -726,7 +720,7 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
/* Try with One-Off EntryId */
struct OneOffEntryId *oneOffEntryId;
oneOffEntryId = get_OneOffEntryId (local_mem_ctx, &bin32);
oneOffEntryId = get_OneOffEntryId (connInfo->sam_ctx, &bin32);
if (oneOffEntryId && [[NSString stringWithGUID: &oneOffEntryId->ProviderUID]
hasSuffix: @"00dd010f5402"])
{
@@ -735,7 +729,9 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
[fromRecipient setObject: [NSString stringWithUTF8String: oneOffEntryId->EmailAddress.lpszW]
forKey: @"email"];
}
talloc_free (oneOffEntryId);
}
talloc_free (addrBookEntryId);
if ([[fromRecipient allKeys] count] > 0)
{
@@ -745,8 +741,6 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
}
}
/* Free entryId */
talloc_free(local_mem_ctx);
}
if (!recipients)
@@ -1013,7 +1007,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
- (NGMimeMessage *) _generateMessageWithBcc: (BOOL) withBcc
{
NSString *contentType;
NGMimeMessage *message;
NGMimeMessage *message;
NGMutableHashMap *headers;
id messageBody;
@@ -1051,9 +1045,8 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
return messageData;
}
- (enum mapistore_error) submitWithFlags: (enum SubmitFlags) flags
- (int) submitWithFlags: (enum SubmitFlags) flags
{
enum mapistore_error rc = MAPISTORE_SUCCESS;
NSDictionary *recipients;
NSData *messageData;
NSMutableArray *recipientEmails;
@@ -1100,10 +1093,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
withAuthenticator: authenticator
inContext: woContext];
if (error)
{
[self errorWithFormat: @"an error occurred: '%@'", error];
rc = MAPISTORE_ERR_MSG_SEND;
}
[self logWithFormat: @"an error occurred: '%@'", error];
// mapping = [self mapping];
// [mapping unregisterURLWithID: [self objectId]];
@@ -1115,13 +1105,12 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
[self logWithFormat: @"skipping submit of message with class '%@'",
msgClass];
return rc;
return MAPISTORE_SUCCESS;
}
- (void) save: (TALLOC_CTX *) memCtx
{
BOOL updatedMetadata;
NSString *folderName, *flag, *newIdString, *messageKey, *changeNumber;
NSString *folderName, *flag, *newIdString, *messageKey;
NSData *changeKey, *messageData;
NGImap4Connection *connection;
NGImap4Client *client;
@@ -1157,33 +1146,21 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
[sogoObject setNameInContainer: messageKey];
[mapping registerURL: [self url] withID: mid];
/* synchronise the cache and update the predecessor change list
with the change key provided by the client. Before doing
this, lets issue a unselect/select combo because of timing
issues with Dovecot in obtaining the latest modseq.
Sometimes, Dovecot doesn't return the newly appended UID if
we do a "UID SORT (DATE) UTF-8 (MODSEQ XYZ) (NOT DELETED)"
command (where XYZ is the HIGHESTMODSEQ+1) immediately after
IMAP APPEND */
/* synchronise the cache and update the change key with the one provided
by the client. Before doing this, lets issue a unselect/select combo
because of timing issues with Dovecot in obtaining the latest modseq.
Sometimes, Dovecot doesn't return the newly appended UID if we do
a "UID SORT (DATE) UTF-8 (MODSEQ XYZ) (NOT DELETED)" command (where
XYZ is the HIGHESTMODSEQ+1) immediately after IMAP APPEND */
[client unselect];
[client select: folderName];
[(MAPIStoreMailFolder *) container synchroniseCache];
changeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)];
if (changeKey)
{
updatedMetadata = [(MAPIStoreMailFolder *) container updatePredecessorChangeListWith: changeKey
forMessageWithKey: messageKey];
if (!updatedMetadata)
[self warnWithFormat: @"Predecessor change list not updated with client data"];
}
/* Update version property (PR_CHANGE_KEY indeed) as it is
requested once it is saved */
changeNumber = [(MAPIStoreMailFolder *) container changeNumberForMessageUID: newIdString];
if (changeNumber)
[properties setObject: [NSNumber numberWithUnsignedLongLong: [changeNumber unsignedLongLongValue] >> 16]
forKey: @"version"];
[(MAPIStoreMailFolder *) container
setChangeKey: changeKey
forMessageWithKey: messageKey];
}
}
+2 -2
View File
@@ -258,7 +258,7 @@ MAPIStoreMappingKeyFromId (uint64_t idNbr)
if (oldURL != NULL)
{
[self errorWithFormat:
@"url with idNbr already registered: (oldUrl='%@', newUrl='%@', id=0x%.16"PRIx64")",
@"url with idNbr already registered: (oldUrl='%@', newUrl='%@', id=x%.16"PRIx64")",
oldURL, urlString, idNbr];
return NO;
}
@@ -306,7 +306,7 @@ MAPIStoreMappingKeyFromId (uint64_t idNbr)
}
else
[NSException raise: NSInvalidArgumentException
format: @"number of urls (%d) and ids (%d) do not match", max, [idNbrs count]];
format: @"number of urls and ids do not match"];
}
- (void) unregisterURLWithID: (uint64_t) idNbr
+10 -12
View File
@@ -48,28 +48,27 @@
- (void) getMessageData: (struct mapistore_message **) dataPtr
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) modifyRecipientsWithRecipients: (struct mapistore_message_recipient *) recipients
andCount: (NSUInteger) max
andColumns: (struct SPropTagArray *) columns;
- (int) modifyRecipientsWithRecipients: (struct mapistore_message_recipient *) recipients
andCount: (NSUInteger) max
andColumns: (struct SPropTagArray *) columns;
- (NSArray *) attachmentKeys;
- (NSArray *) attachmentKeysMatchingQualifier: (EOQualifier *) qualifier
andSortOrderings: (NSArray *) sortOrderings;
- (id) lookupAttachment: (NSString *) childKey;
/* backend methods */
- (enum mapistore_error) createAttachment: (MAPIStoreAttachment **) attachmentPtr
inAID: (uint32_t *) aidPtr;
- (enum mapistore_error) getAttachment: (MAPIStoreAttachment **) attachmentPtr
withAID: (uint32_t) aid;
- (enum mapistore_error) getAttachmentTable: (MAPIStoreAttachmentTable **) tablePtr
andRowCount: (uint32_t *) countPtr;
- (enum mapistore_error) setReadFlag: (uint8_t) flag;
- (int) createAttachment: (MAPIStoreAttachment **) attachmentPtr
inAID: (uint32_t *) aidPtr;
- (int) getAttachment: (MAPIStoreAttachment **) attachmentPtr
withAID: (uint32_t) aid;
- (int) getAttachmentTable: (MAPIStoreAttachmentTable **) tablePtr
andRowCount: (uint32_t *) countPtr;
- (int) setReadFlag: (uint8_t) flag;
- (enum mapistore_error) saveMessage: (TALLOC_CTX *) memCtx;
- (NSArray *) activeContainerMessageTables;
- (NSArray *) activeUserRoles;
- (NSArray *) expandRoles: (NSArray *) roles;
/* move & copy internal ops */
- (void) copyToMessage: (MAPIStoreMessage *) newMessage inMemCtx: (TALLOC_CTX *) memCtx;
@@ -83,7 +82,6 @@
- (BOOL) subscriberCanReadMessage;
- (BOOL) subscriberCanModifyMessage;
- (BOOL) subscriberCanDeleteMessage;
@end
+89 -108
View File
@@ -276,9 +276,9 @@ rtf2html (NSData *compressedRTF)
return recipientProperties;
}
- (enum mapistore_error) modifyRecipientsWithRecipients: (struct mapistore_message_recipient *) newRecipients
andCount: (NSUInteger) max
andColumns: (struct SPropTagArray *) columns;
- (int) modifyRecipientsWithRecipients: (struct mapistore_message_recipient *) newRecipients
andCount: (NSUInteger) max
andColumns: (struct SPropTagArray *) columns;
{
static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
NSDictionary *recipientProperties;
@@ -318,7 +318,7 @@ rtf2html (NSData *compressedRTF)
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) addPropertiesFromRow: (struct SRow *) aRow
- (int) addPropertiesFromRow: (struct SRow *) aRow
{
enum mapistore_error rc;
MAPIStoreContext *context;
@@ -397,11 +397,11 @@ rtf2html (NSData *compressedRTF)
return newAttachment;
}
- (enum mapistore_error) createAttachment: (MAPIStoreAttachment **) attachmentPtr
inAID: (uint32_t *) aidPtr
- (int) createAttachment: (MAPIStoreAttachment **) attachmentPtr
inAID: (uint32_t *) aidPtr
{
MAPIStoreAttachment *attachment;
enum mapistore_error rc = MAPISTORE_SUCCESS;
int rc = MAPISTORE_SUCCESS;
attachment = [self createAttachment];
if (attachment)
@@ -422,12 +422,12 @@ rtf2html (NSData *compressedRTF)
return nil;
}
- (enum mapistore_error) getAttachment: (MAPIStoreAttachment **) attachmentPtr
withAID: (uint32_t) aid
- (int) getAttachment: (MAPIStoreAttachment **) attachmentPtr
withAID: (uint32_t) aid
{
MAPIStoreAttachment *attachment;
NSArray *keys;
enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND;
int rc = MAPISTORE_ERR_NOT_FOUND;
keys = [self attachmentKeys];
if (aid < [keys count])
@@ -443,11 +443,11 @@ rtf2html (NSData *compressedRTF)
return rc;
}
- (enum mapistore_error) getAttachmentTable: (MAPIStoreAttachmentTable **) tablePtr
andRowCount: (uint32_t *) countPtr
- (int) getAttachmentTable: (MAPIStoreAttachmentTable **) tablePtr
andRowCount: (uint32_t *) countPtr
{
MAPIStoreAttachmentTable *attTable;
enum mapistore_error rc = MAPISTORE_SUCCESS;
int rc = MAPISTORE_SUCCESS;
attTable = [self attachmentTable];
if (attTable)
@@ -547,15 +547,13 @@ rtf2html (NSData *compressedRTF)
for (count = 0; count < max; count++)
[[containerTables objectAtIndex: count] restrictedChildKeys];
}
/* TODO: Check the save process succeeded */
[self save: memCtx];
/* We make sure that any change-related properties are removed from the
/* We make sure that any change-related properties are removes from the
properties dictionary, to make sure that related methods will be
invoked the next time they are requested. */
[properties removeObjectForKey: MAPIPropertyKey (PidTagChangeKey)];
[properties removeObjectForKey: MAPIPropertyKey (PidTagChangeNumber)];
[properties removeObjectForKey: MAPIPropertyKey (PidTagPredecessorChangeList)];
if ([container isKindOfClass: MAPIStoreFolderK])
{
@@ -583,8 +581,8 @@ rtf2html (NSData *compressedRTF)
}
/* getters */
- (enum mapistore_error) getPidTagInstID: (void **) data // TODO: DOUBT
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagInstID: (void **) data // TODO: DOUBT
inMemCtx: (TALLOC_CTX *) memCtx
{
/* we return a unique id based on the key */
*data = MAPILongLongValue (memCtx, [[sogoObject nameInContainer] hash]);
@@ -592,22 +590,22 @@ rtf2html (NSData *compressedRTF)
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagInstanceNum: (void **) data // TODO: DOUBT
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagInstanceNum: (void **) data // TODO: DOUBT
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getLongZero: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagRowType: (void **) data // TODO: DOUBT
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagRowType: (void **) data // TODO: DOUBT
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, TBL_LEAF_ROW);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagDepth: (void **) data // TODO: DOUBT
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagDepth: (void **) data // TODO: DOUBT
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongLongValue (memCtx, 0);
@@ -624,8 +622,8 @@ rtf2html (NSData *compressedRTF)
0x00000010 Create Contents Table
0x00000020 Create Associated Contents Table
*/
- (enum mapistore_error) getPidTagAccess: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAccess: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
uint32_t access = 0;
BOOL userIsOwner;
@@ -650,7 +648,8 @@ rtf2html (NSData *compressedRTF)
if (userIsOwner
|| ([self isKindOfClass: MAPIStoreEmbeddedMessageK]
&& [mainMessage subscriberCanModifyMessage])
|| [mainMessage subscriberCanDeleteMessage])
|| [(MAPIStoreFolder *)
[mainMessage container] subscriberCanDeleteMessages])
access |= 0x04;
*data = MAPILongValue (memCtx, access);
@@ -664,8 +663,8 @@ rtf2html (NSData *compressedRTF)
0x00000000 Read-Only
0x00000001 Modify
*/
- (enum mapistore_error) getPidTagAccessLevel: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAccessLevel: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
uint32_t access = 0;
BOOL userIsOwner;
@@ -684,20 +683,20 @@ rtf2html (NSData *compressedRTF)
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagHasNamedProperties: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int ) getPidTagHasNamedProperties: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getYes: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidLidSideEffects: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidLidSideEffects: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getLongZero: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidLidCurrentVersion: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidLidCurrentVersion: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
// *data = MAPILongValue (memCtx, 115608); // Outlook 11.5608
*data = MAPILongValue (memCtx, 0x1ce3a); // Outlook 11.8330
@@ -705,34 +704,34 @@ rtf2html (NSData *compressedRTF)
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidLidCurrentVersionName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidLidCurrentVersionName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"11.0" asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidLidAutoProcessState: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidLidAutoProcessState: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, 0x00000000);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagFolderId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagFolderId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongLongValue (memCtx, [container objectId]);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagMid: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagMid: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
int rc;
uint64_t obId;
obId = [self objectId];
@@ -747,24 +746,24 @@ rtf2html (NSData *compressedRTF)
return rc;
}
- (enum mapistore_error) getPidTagMessageLocaleId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagMessageLocaleId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, 0x0409);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagMessageFlags: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagMessageFlags: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, MSGFLAG_FROMME | MSGFLAG_READ | MSGFLAG_UNMODIFIED);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagMessageSize: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagMessageSize: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
{
/* TODO: choose another name in SOGo for that method */
*data = MAPILongValue (memCtx, [[sogoObject davContentLength] intValue]);
@@ -772,30 +771,30 @@ rtf2html (NSData *compressedRTF)
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagImportance: (void **) data // TODO -> subclass?
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagImportance: (void **) data // TODO -> subclass?
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, 1);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagPriority: (void **) data // TODO -> subclass?
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagPriority: (void **) data // TODO -> subclass?
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getLongZero: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagSensitivity: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagSensitivity: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getLongZero: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
int rc;
TALLOC_CTX *localMemCtx;
char *prefix, *normalizedSubject;
@@ -816,71 +815,71 @@ rtf2html (NSData *compressedRTF)
return rc;
}
- (enum mapistore_error) getPidTagNormalizedSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagNormalizedSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidTagOriginalSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagOriginalSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidTagSubject: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagConversationTopic: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagConversationTopic: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidTagNormalizedSubject: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagSubjectPrefix: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagSubjectPrefix: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getEmptyString: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagDeleteAfterSubmit: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagDeleteAfterSubmit: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagDisplayTo: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagDisplayTo: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getEmptyString: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagDisplayCc: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagDisplayCc: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getEmptyString: data inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagDisplayBcc: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagDisplayBcc: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getEmptyString: data inMemCtx: memCtx];
}
// - (enum mapistore_error) getPidTagOriginalDisplayTo: (void **) data
// - (int) getPidTagOriginalDisplayTo: (void **) data
// {
// return [self getPidTagDisplayTo: data];
// }
// - (enum mapistore_error) getPidTagOriginalDisplayCc: (void **) data
// - (int) getPidTagOriginalDisplayCc: (void **) data
// {
// return [self getPidTagDisplayCc: data];
// }
// - (enum mapistore_error) getPidTagOriginalDisplayBcc: (void **) data
// - (int) getPidTagOriginalDisplayBcc: (void **) data
// {
// return [self getPidTagDisplayBcc: data];
// }
- (enum mapistore_error) getPidTagLastModifierName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagLastModifierName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSURL *contextUrl;
@@ -890,22 +889,22 @@ rtf2html (NSData *compressedRTF)
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
[self subclassResponsibility: _cmd];
return MAPISTORE_ERR_NOT_FOUND;
}
- (enum mapistore_error) getPidTagOriginalMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagOriginalMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getProperty: data withTag: PidTagMessageClass inMemCtx: memCtx];
}
- (enum mapistore_error) getPidTagHasAttachments: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagHasAttachments: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPIBoolValue (memCtx,
[[self attachmentKeys] count] > 0);
@@ -913,13 +912,13 @@ rtf2html (NSData *compressedRTF)
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagAssociated: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagAssociated: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];;
}
- (enum mapistore_error) setReadFlag: (uint8_t) flag
- (int) setReadFlag: (uint8_t) flag
{
// [self subclassResponsibility: _cmd];
@@ -981,38 +980,20 @@ rtf2html (NSData *compressedRTF)
activeUserRoles = [[context activeUser]
rolesForObject: sogoObject
inContext: [userContext woContext]];
/* We use in this library the roles as flags, so we expand high
access rights with the lower ones */
activeUserRoles = [self expandRoles: activeUserRoles];
[activeUserRoles retain];
}
return activeUserRoles;
}
/* Expand current roles with lower access roles to transform them to
flags */
- (NSArray *) expandRoles: (NSArray *) roles
{
return roles;
}
/* Can the current active user read the message? */
- (BOOL) subscriberCanReadMessage
{
return NO;
}
/* Can the current active user modify the message? */
- (BOOL) subscriberCanModifyMessage
{
return NO;
}
/* Can the current active user delete the message? */
- (BOOL) subscriberCanDeleteMessage
{
return NO;
}
@end
-18
View File
@@ -1,7 +1,6 @@
/* MAPIStoreNotesContext.m - this file is part of SOGo
*
* Copyright (C) 2010-2012 Inverse inc.
* Copyright (C) 2016 Enrique J. Hernandez
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@@ -31,30 +30,13 @@
#undef DEBUG
#include <mapistore/mapistore.h>
static Class MAPIStoreNotesFolderK;
@implementation MAPIStoreNotesContext
+ (void) initialize
{
MAPIStoreNotesFolderK = [MAPIStoreNotesFolder class];
}
+ (NSString *) MAPIModuleName
{
return @"notes";
}
+ (enum mapistore_context_role) MAPIContextRole
{
return MAPISTORE_NOTES_ROLE;
}
- (Class) MAPIStoreFolderClass
{
return MAPIStoreNotesFolderK;
}
+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName
withIndexing: (struct indexing_context *) indexing
inMemCtx: (TALLOC_CTX *) memCtx
+2 -2
View File
@@ -30,8 +30,8 @@
@implementation MAPIStoreNotesFolder
- (enum mapistore_error) getPidTagDefaultPostMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagDefaultPostMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"IPM.StickyNote" asUnicodeInMemCtx: memCtx];
+3 -3
View File
@@ -32,8 +32,8 @@
@implementation MAPIStoreNotesMessage
- (enum mapistore_error) getPidTagIconIndex: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagIconIndex: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
{
/* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */
// *longValue = 0x00000300 for blue
@@ -46,7 +46,7 @@
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"IPM.StickyNote" asUnicodeInMemCtx: memCtx];
+15 -15
View File
@@ -68,27 +68,27 @@
- (NSMutableDictionary *) properties;
/* ops */
- (enum mapistore_error) getProperties: (struct mapistore_property_data *) data
withTags: (enum MAPITAGS *) tags
andCount: (uint16_t) columnCount
inMemCtx: (TALLOC_CTX *) localMemCtx;
- (int) getProperties: (struct mapistore_property_data *) data
withTags: (enum MAPITAGS *) tags
andCount: (uint16_t) columnCount
inMemCtx: (TALLOC_CTX *) localMemCtx;
- (enum mapistore_error) addPropertiesFromRow: (struct SRow *) aRow;
- (int) addPropertiesFromRow: (struct SRow *) aRow;
- (enum mapistore_error) getProperty: (void **) data
withTag: (enum MAPITAGS) propTag
inMemCtx: (TALLOC_CTX *) localMemCtx;
- (int) getProperty: (void **) data
withTag: (enum MAPITAGS) propTag
inMemCtx: (TALLOC_CTX *) localMemCtx;
/* helper getters */
- (NSData *) getReplicaKeyFromGlobCnt: (uint64_t) objectCnt;
- (enum mapistore_error) getReplicaKey: (void **) data
fromGlobCnt: (uint64_t) objectCnt
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getReplicaKey: (void **) data
fromGlobCnt: (uint64_t) objectCnt
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagCreationTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagLastModificationTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagCreationTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagLastModificationTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
/* move and copy operations */
- (void) copyPropertiesToObject: (MAPIStoreObject *) newObject inMemCtx: (TALLOC_CTX *) memCtx;
+16 -16
View File
@@ -150,15 +150,15 @@ static Class NSExceptionK, MAPIStoreFolderK;
return properties;
}
- (enum mapistore_error) getProperty: (void **) data
withTag: (enum MAPITAGS) propTag
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getProperty: (void **) data
withTag: (enum MAPITAGS) propTag
inMemCtx: (TALLOC_CTX *) memCtx
{
MAPIStorePropertyGetter method = NULL;
uint16_t propValue;
SEL methodSel;
id value;
enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND;
int rc = MAPISTORE_ERR_NOT_FOUND;
NSUInteger count, max;
value = [properties objectForKey: MAPIPropertyKey (propTag)];
@@ -186,16 +186,16 @@ static Class NSExceptionK, MAPIStoreFolderK;
return rc;
}
- (enum mapistore_error) getPidTagCreationTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagCreationTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[self creationTime] asFileTimeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagLastModificationTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagLastModificationTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[self lastModificationTime] asFileTimeInMemCtx: memCtx];
@@ -219,10 +219,10 @@ static Class NSExceptionK, MAPIStoreFolderK;
return canGetProperty;
}
- (enum mapistore_error) getProperties: (struct mapistore_property_data *) data
withTags: (enum MAPITAGS *) tags
andCount: (uint16_t) columnCount
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getProperties: (struct mapistore_property_data *) data
withTags: (enum MAPITAGS *) tags
andCount: (uint16_t) columnCount
inMemCtx: (TALLOC_CTX *) memCtx
{
uint16_t count;
@@ -239,7 +239,7 @@ static Class NSExceptionK, MAPIStoreFolderK;
[proxies addObject: newProxy];
}
- (enum mapistore_error) addPropertiesFromRow: (struct SRow *) aRow
- (int) addPropertiesFromRow: (struct SRow *) aRow
{
struct SPropValue *cValue;
NSUInteger counter;
@@ -298,9 +298,9 @@ static Class NSExceptionK, MAPIStoreFolderK;
return replicaKey;
}
- (enum mapistore_error) getReplicaKey: (void **) data
fromGlobCnt: (uint64_t) objectCnt
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getReplicaKey: (void **) data
fromGlobCnt: (uint64_t) objectCnt
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[self getReplicaKeyFromGlobCnt: objectCnt] asBinaryInMemCtx: memCtx];
+1 -1
View File
@@ -51,7 +51,7 @@
MAPIStorePropertyGetter method;
uint16_t propValue;
SEL methodSel;
enum mapistore_error rc;
int rc;
propValue = (propTag & 0xffff0000) >> 16;
methodSel = MAPIStoreSelectorForPropertyGetter (propValue);
+9 -10
View File
@@ -84,16 +84,16 @@
return memberId;
}
- (enum mapistore_error) getPidTagMemberId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagMemberId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongLongValue (memCtx, memberId);
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagEntryId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagEntryId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSData *entryId;
struct mapistore_connection_info *connInfo;
@@ -103,15 +103,15 @@
else
{
connInfo = [(MAPIStoreContext *) [container context] connectionInfo];
entryId = MAPIStoreInternalEntryId (connInfo, userId);
entryId = MAPIStoreInternalEntryId (connInfo->sam_ctx, userId);
}
*data = [entryId asBinaryInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagMemberName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagMemberName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSString *displayName;
@@ -127,14 +127,13 @@
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getPidTagMemberRights: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagMemberRights: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
uint32_t rights;
NSArray *roles;
roles = [[(MAPIStoreFolder *) container aclFolder] aclsForUser: userId];
roles = [(MAPIStoreFolder *) container expandRoles: roles];
rights = [(MAPIStoreFolder *) container exchangeRightsForRoles: roles];
*data = MAPILongValue (memCtx, rights);
+6 -2
View File
@@ -25,9 +25,12 @@
#include <talloc.h>
#import <Foundation/NSTimeZone.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalRecurrenceRule.h>
#import <NGCards/iCalTimeZone.h>
@class NSTimeZone;
@class iCalEvent;
@class iCalRepeatableEntityObject;
@@ -43,7 +46,7 @@
fromRecurrencePattern: (struct RecurrencePattern *) rp
withExceptions: (struct ExceptionInfo *) exInfos
andExceptionCount: (uint16_t) exInfoCount
inTimeZone: (iCalTimeZone *) tz;
inTimeZone: (NSTimeZone *) tz;
@end
@@ -51,6 +54,7 @@
- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp
withEvent: (iCalEvent *) event
inTimeZone: (NSTimeZone *) timeZone
inMemCtx: (TALLOC_CTX *) memCtx;
@end
Loaded 100 of 1912 files, more files were not shown because too many files have changed in this diff. Show more