(feat) first pas at EAS v16 support and save in drafts

Conflicts:
	ActiveSync/SOGoMailObject+ActiveSync.m
This commit is contained in:
Ludovic Marcotte
2017-06-01 16:09:17 -04:00
parent 71fe42e8c3
commit 1666048da5
6 changed files with 153 additions and 13 deletions
+29 -5
View File
@@ -366,8 +366,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// the case, let's just update it. This can happen if for example, an iOS based device receives the
// invitation email and choses "Add to calendar" BEFORE actually syncing the calendar. That would
// create a duplicate on the server.
if ([allValues objectForKey: @"UID"])
serverId = [allValues objectForKey: @"UID"];
if ([allValues objectForKey: ([[context objectForKey: @"ASProtocolVersion"] floatValue] >= 16.0) ? @"ClientUid" : @"UID"])
serverId = [allValues objectForKey: ([[context objectForKey: @"ASProtocolVersion"] floatValue] >= 16.0) ? @"ClientUid" : @"UID"];
else
serverId = [theCollection globallyUniqueObjectId];
@@ -402,9 +402,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
case ActiveSyncMailFolder:
default:
{
// FIXME - what to do?
[self errorWithFormat: @"Fatal error occured - tried to call -processSyncAddCommand: ... on a mail folder. We abort."];
abort();
// Support SMS to Exchange eMail sync.
NSString *serverId;
sogoObject = [SOGoMailObject objectWithName: @"Mail" inContainer: theCollection];
serverId = [sogoObject storeMail: allValues inContext: context];
if (serverId)
{
// Everything is fine, lets generate our response
// serverId = clientId - There is no furhter processing after adding the SMS to the inbox.
[theBuffer appendString: @"<Add>"];
[theBuffer appendFormat: @"<ClientId>%@</ClientId>", clientId];
[theBuffer appendFormat: @"<ServerId>%@</ServerId>", serverId];
[theBuffer appendFormat: @"<Status>%d</Status>", 1];
[theBuffer appendString: @"</Add>"];
folderMetadata = [self _folderMetadataForKey: [self _getNameInCache: theCollection withType: theFolderType]];
syncCache = [folderMetadata objectForKey: @"SyncCache"];
[syncCache setObject: @"0" forKey: serverId];
[self _setFolderMetadata: folderMetadata forKey: [self _getNameInCache: theCollection withType: theFolderType]];
continue;
}
else
{
// FIXME - what to do?
[self errorWithFormat: @"Fatal error occured - tried to call -processSyncAddCommand: ... on a mail folder. We abort."];
abort();
}
}
}
+1 -1
View File
@@ -4151,7 +4151,7 @@ void handle_eas_terminate(int signum)
return_response:
[theResponse setHeader: @"14.1" forKey: @"MS-Server-ActiveSync"];
[theResponse setHeader: @"Sync,SendMail,SmartForward,SmartReply,GetAttachment,GetHierarchy,CreateCollection,DeleteCollection,MoveCollection,FolderSync,FolderCreate,FolderDelete,FolderUpdate,MoveItems,GetItemEstimate,MeetingResponse,Search,Settings,Ping,ItemOperations,ResolveRecipients,ValidateCert" forKey: @"MS-ASProtocolCommands"];
[theResponse setHeader: @"2.5,12.0,12.1,14.0,14.1" forKey: @"MS-ASProtocolVersions"];
[theResponse setHeader: @"2.5,12.0,12.1,14.0,14.1,16.0" forKey: @"MS-ASProtocolVersions"];
if (debugOn && [[theResponse headerForKey: @"Content-Type"] isEqualToString:@"application/vnd.ms-sync.wbxml"] && [[theResponse content] length] && !([(WOResponse *)theResponse status] == 500))
[self logWithFormat: @"EAS - response for device %@: %@", [context objectForKey: @"DeviceId"], [[[NSString alloc] initWithData: [[theResponse content] wbxml2xml] encoding: NSUTF8StringEncoding] autorelease]];
+2
View File
@@ -42,6 +42,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context;
- (NSString *) storeMail: (NSDictionary *) theValues
inContext: (WOContext *) _context;
@end
+109 -1
View File
@@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <Foundation/NSException.h>
#import <Foundation/NSString.h>
#import <Foundation/NSCharacterSet.h>
#import <Foundation/NSTimeZone.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalDateTime.h>
@@ -46,9 +47,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <NGExtensions/NGQuotedPrintableCoding.h>
#import <NGExtensions/NSString+misc.h>
#import <NGExtensions/NSString+Encoding.h>
#import <NGExtensions/NGHashMap.h>
#import <NGImap4/NGImap4Envelope.h>
#import <NGImap4/NGImap4EnvelopeAddress.h>
#import <NGImap4/NSString+Imap4.h>
#import <NGImap4/NGImap4Connection.h>
#import <NGImap4/NGImap4Client.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WOApplication.h>
@@ -63,6 +67,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <Mailer/SOGoMailLabel.h>
#import <SOGo/SOGoUserDefaults.h>
#import <SOGo/SOGoUserFolder.h>
#include "iCalTimeZone+ActiveSync.h"
#include "NSData+ActiveSync.h"
@@ -73,6 +78,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <Appointments/iCalPerson+SOGo.h>
#include <Mailer/NSString+Mail.h>
#include <Mailer/SOGoMailBodyPart.h>
#import <Mailer/SOGoMailLabel.h>
#import <Mailer/SOGoMailFolder.h>
#import <Mailer/SOGoMailObject.h>
#import <Mailer/SOGoMailAccount.h>
#import <Mailer/SOGoMailAccounts.h>
#include <SOGo/SOGoUser.h>
#include <SOGo/NSString+Utilities.h>
@@ -962,7 +973,12 @@ struct GlobalObjectId {
// Location
if ([[event location] length])
[s appendFormat: @"<Location xmlns=\"Email:\">%@</Location>", [[event location] activeSyncRepresentationInContext: context]];
{
if ([[context objectForKey: @"ASProtocolVersion"] floatValue] >= 16.0)
[s appendFormat: @"<Location xmlns=\"AirSyncBase:\"><DisplayName>%@</DisplayName></Location>", [[event location] activeSyncRepresentationInContext: context]];
else
[s appendFormat: @"<Location xmlns=\"Email:\">%@</Location>", [[event location] activeSyncRepresentationInContext: context]];
}
[s appendFormat: @"<Organizer xmlns=\"Email:\">%@</Organizer>", [[[event organizer] mailAddress] activeSyncRepresentationInContext: context]];
@@ -1422,4 +1438,96 @@ struct GlobalObjectId {
}
}
- (NSString *) storeMail: (NSDictionary *) theValues
inContext: (WOContext *) _context
{
int bodyType;
NGImap4Client *client;
NSData *message_data;
NSString *folder, *s;
id o, result;
NSDictionary *identity;
NGMutableHashMap *map;
NGMimeMessage *bounceMessage;
NGMimeMessageGenerator *generator;
NSString *email, *dateReceived;
identity = [[context activeUser] primaryIdentity];
email = [identity objectForKey: @"email"];
bodyType = 1;
if ((o = [[theValues objectForKey: @"Body"] objectForKey: @"Type"]))
{
bodyType = [o intValue];
}
if (bodyType == 4)
{
s = [[theValues objectForKey: @"Body"] objectForKey: @"Data"];
message_data = [ s dataUsingEncoding: NSUTF8StringEncoding];
}
if (bodyType == 1)
{
map = [[[NGMutableHashMap alloc] initWithCapacity: 1] autorelease];
[map setObject: [NSString stringWithFormat: @"%@ <%@>", [theValues objectForKey: @"From"], email] forKey: @"from"];
[map setObject: [NSString stringWithFormat: @"%@ <%@>", [theValues objectForKey: @"To"], email] forKey: @"to"];
[map setObject: [NSString stringWithFormat: @"SMS: %@", [theValues objectForKey: @"From"]] forKey: @"subject"];
#if GNUSTEP_BASE_MINOR_VERSION < 21
dateReceived = [[[theValues objectForKey: @"DateReceived"] calendarDate] descriptionWithCalendarFormat: @"%a, %d %b %Y %H:%M:%S %z"
timeZone: [NSTimeZone timeZoneWithName: @"GMT"]
locale: nil];
#else
dateReceived = [[[theValues objectForKey: @"DateReceived"] calendarDate] descriptionWithCalendarFormat: @"%a, %d %b %Y %H:%M:%S %z"
timeZone: [NSTimeZone timeZoneWithName: @"GMT"]
locale: [NSDictionary dictionaryWithObjectsAndKeys:
[NSArray arrayWithObjects: @"Jan", @"Feb", @"Mar", @"Apr",
@"May", @"Jun", @"Jul", @"Aug",
@"Sep", @"Oct", @"Nov", @"Dec", nil],
@"NSShortMonthNameArray",
[NSArray arrayWithObjects: @"Sun", @"Mon", @"Tue", @"Wed", @"Thu",
@"Fri", @"Sat", nil],
@"NSShortWeekDayNameArray",
nil]];
#endif
[map setObject: dateReceived forKey: @"date"];
[map setObject: [NSString generateMessageID] forKey: @"message-id"];
[map setObject: @"text/plain; charset=utf-8" forKey: @"content-type"];
[map setObject: @"quoted-printable" forKey: @"content-transfer-encoding"];
bounceMessage = [[[NGMimeMessage alloc] initWithHeader: map] autorelease];
[bounceMessage setBody: [[NSString stringWithFormat: @"%@", [[theValues objectForKey: @"Body"] objectForKey: @"Data"] ] dataUsingEncoding: NSUTF8StringEncoding]];
generator = [[[NGMimeMessageGenerator alloc] init] autorelease];
message_data = [generator generateMimeFromPart: bounceMessage];
}
client = [[self imap4Connection] client];
if (![imap4 doesMailboxExistAtURL: [container imap4URL]])
{
[[self imap4Connection] createMailbox: [[self imap4Connection] imap4FolderNameForURL: [container imap4URL]]
atURL: [[self mailAccountFolder] imap4URL]];
[imap4 flushFolderHierarchyCache];
}
folder = [imap4 imap4FolderNameForURL: [container imap4URL]];
result = [client append: message_data toFolder: folder
withFlags: [NSArray arrayWithObjects: @"draft", nil]];
if ([[result objectForKey: @"result"] boolValue])
return [NSString stringWithFormat: @"%d", [self IMAP4IDFromAppendResult: result]];
return nil;
}
@end
@@ -61,7 +61,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[response setHeader: @"private" forKey: @"Cache-Control"];
[response setHeader: @"OPTIONS, POST" forKey: @"Allow"];
[response setHeader: @"14.1" forKey: @"MS-Server-ActiveSync"];
[response setHeader: @"2.5,12.0,12.1,14.0,14.1" forKey: @"MS-ASProtocolVersions"];
[response setHeader: @"2.5,12.0,12.1,14.0,14.1,16.0" forKey: @"MS-ASProtocolVersions"];
[response setHeader: @"Sync,SendMail,SmartForward,SmartReply,GetAttachment,GetHierarchy,CreateCollection,DeleteCollection,MoveCollection,FolderSync,FolderCreate,FolderDelete,FolderUpdate,MoveItems,GetItemEstimate,MeetingResponse,Search,Settings,Ping,ItemOperations,ResolveRecipients,ValidateCert" forKey: @"MS-ASProtocolCommands"];
[response setHeader: @"OPTIONS, POST" forKey: @"Public"];
}
+11 -5
View File
@@ -251,7 +251,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Location
if ([[self location] length])
[s appendFormat: @"<Location xmlns=\"Calendar:\">%@</Location>", [[self location] activeSyncRepresentationInContext: context]];
{
if ([[context objectForKey: @"ASProtocolVersion"] floatValue] >= 16.0)
[s appendFormat: @"<Location xmlns=\"AirSyncBase:\"><DisplayName>%@</DisplayName></Location>", [[self location] activeSyncRepresentationInContext: context]];
else
[s appendFormat: @"<Location xmlns=\"Calendar:\">%@</Location>", [[self location] activeSyncRepresentationInContext: context]];
}
// Importance - NOT SUPPORTED - DO NOT ENABLE
//o = [self priority];
@@ -458,7 +463,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
occurences = [NSMutableArray arrayWithArray: [[self parent] events]];
if ((o = [theValues objectForKey: @"UID"]))
if ((o = [theValues objectForKey: ([[context objectForKey: @"ASProtocolVersion"] floatValue] >= 16.0) ? @"ClientUid" : @"UID"]))
[self setUid: o];
// FIXME: merge with iCalToDo
@@ -537,8 +542,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[self setComment: o];
}
if ((o = [theValues objectForKey: @"Location"]))
if ([[context objectForKey: @"ASProtocolVersion"] floatValue] < 16.0 && (o = [theValues objectForKey: @"Location"]))
[self setLocation: o];
else if ([[context objectForKey: @"ASProtocolVersion"] floatValue] >= 16.0 && (o = [theValues objectForKey: @"Location"]) && [o isKindOfClass: [NSDictionary class]])
[self setLocation: [o objectForKey: @"DisplayName"]];
deltasecs = 0;
start = nil;
@@ -589,7 +596,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
// Ignore the alarm for now
}
else if ((o = [theValues objectForKey: @"Reminder"]))
else if ((o = [theValues objectForKey: @"Reminder"]) && [o length])
{
// NOTE: Outlook sends a 15 min reminder (18 hour for allday) if no reminder is specified
// although no default reminder is defined (File -> Options -> Clendar -> Calendar Options - > Default Reminders)
@@ -840,7 +847,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
}
// Attendees - we don't touch the values if we're an attendee. This is gonna
// be done automatically by the ActiveSync client when invoking MeetingResponse.
if (![self userIsAttendee: [context activeUser]])