From 6f56522f89c771b468356382430e886ac00210cf Mon Sep 17 00:00:00 2001 From: Ludovic Marcotte Date: Thu, 1 Jun 2017 16:07:34 -0400 Subject: [PATCH] (feat) first pas at EAS v16 support and save in drafts --- ActiveSync/SOGoActiveSyncDispatcher+Sync.m | 34 +++++- ActiveSync/SOGoActiveSyncDispatcher.m | 2 +- ActiveSync/SOGoMailObject+ActiveSync.h | 2 + ActiveSync/SOGoMailObject+ActiveSync.m | 110 +++++++++++++++++- .../SoObjectWebDAVDispatcher+ActiveSync.m | 2 +- ActiveSync/iCalEvent+ActiveSync.m | 16 ++- 6 files changed, 153 insertions(+), 13 deletions(-) diff --git a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m index f311ea9a5..9bce415e1 100644 --- a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m +++ b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m @@ -331,8 +331,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]; @@ -367,9 +367,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: @""]; + [theBuffer appendFormat: @"%@", clientId]; + [theBuffer appendFormat: @"%@", serverId]; + [theBuffer appendFormat: @"%d", 1]; + [theBuffer appendString: @""]; + + 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(); + } } } diff --git a/ActiveSync/SOGoActiveSyncDispatcher.m b/ActiveSync/SOGoActiveSyncDispatcher.m index 6bdb6f471..ff51e22d3 100644 --- a/ActiveSync/SOGoActiveSyncDispatcher.m +++ b/ActiveSync/SOGoActiveSyncDispatcher.m @@ -4160,7 +4160,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]]; diff --git a/ActiveSync/SOGoMailObject+ActiveSync.h b/ActiveSync/SOGoMailObject+ActiveSync.h index 44ceec168..dc1633fbe 100644 --- a/ActiveSync/SOGoMailObject+ActiveSync.h +++ b/ActiveSync/SOGoMailObject+ActiveSync.h @@ -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 diff --git a/ActiveSync/SOGoMailObject+ActiveSync.m b/ActiveSync/SOGoMailObject+ActiveSync.m index 7cb58f06b..f0bca2d34 100644 --- a/ActiveSync/SOGoMailObject+ActiveSync.m +++ b/ActiveSync/SOGoMailObject+ActiveSync.m @@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #import #import #import +#import #import #import @@ -44,9 +45,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #import #import +#import #import #import #import +#import +#import #import #import #import @@ -60,6 +64,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #import #import +#import #include "iCalTimeZone+ActiveSync.h" #include "NSData+ActiveSync.h" @@ -71,6 +76,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#import +#import +#import +#import +#import + #include #include @@ -972,7 +983,12 @@ struct GlobalObjectId { // Location if ([[event location] length]) - [s appendFormat: @"%@", [[event location] activeSyncRepresentationInContext: context]]; + { + if ([[context objectForKey: @"ASProtocolVersion"] floatValue] >= 16.0) + [s appendFormat: @"%@", [[event location] activeSyncRepresentationInContext: context]]; + else + [s appendFormat: @"%@", [[event location] activeSyncRepresentationInContext: context]]; + } [s appendFormat: @"%@", [[[event organizer] mailAddress] activeSyncRepresentationInContext: context]]; @@ -1432,4 +1448,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 diff --git a/ActiveSync/SoObjectWebDAVDispatcher+ActiveSync.m b/ActiveSync/SoObjectWebDAVDispatcher+ActiveSync.m index 574786c20..fa7c181c1 100644 --- a/ActiveSync/SoObjectWebDAVDispatcher+ActiveSync.m +++ b/ActiveSync/SoObjectWebDAVDispatcher+ActiveSync.m @@ -64,7 +64,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"]; } diff --git a/ActiveSync/iCalEvent+ActiveSync.m b/ActiveSync/iCalEvent+ActiveSync.m index a739a4667..7a66adbd1 100644 --- a/ActiveSync/iCalEvent+ActiveSync.m +++ b/ActiveSync/iCalEvent+ActiveSync.m @@ -244,7 +244,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Location if ([[self location] length]) - [s appendFormat: @"%@", [[self location] activeSyncRepresentationInContext: context]]; + { + if ([[context objectForKey: @"ASProtocolVersion"] floatValue] >= 16.0) + [s appendFormat: @"%@", [[self location] activeSyncRepresentationInContext: context]]; + else + [s appendFormat: @"%@", [[self location] activeSyncRepresentationInContext: context]]; + } // Importance - NOT SUPPORTED - DO NOT ENABLE //o = [self priority]; @@ -451,7 +456,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 @@ -530,8 +535,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; @@ -582,7 +589,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) @@ -833,7 +840,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]])