diff --git a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m index a6f653f4b..9ac8c824d 100644 --- a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m +++ b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m @@ -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: @""]; + [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 0094f8210..06f922b65 100644 --- a/ActiveSync/SOGoActiveSyncDispatcher.m +++ b/ActiveSync/SOGoActiveSyncDispatcher.m @@ -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]]; 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 4907eb60d..6a34e7fce 100644 --- a/ActiveSync/SOGoMailObject+ActiveSync.m +++ b/ActiveSync/SOGoMailObject+ActiveSync.m @@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #import #import #import +#import #import #import @@ -46,9 +47,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #import #import #import +#import #import #import #import +#import +#import #import #import @@ -63,6 +67,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #import #import +#import #include "iCalTimeZone+ActiveSync.h" #include "NSData+ActiveSync.h" @@ -73,6 +78,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#import +#import +#import +#import +#import + #include #include @@ -962,7 +973,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]]; @@ -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 diff --git a/ActiveSync/SoObjectWebDAVDispatcher+ActiveSync.m b/ActiveSync/SoObjectWebDAVDispatcher+ActiveSync.m index 7196ff002..904dae0f1 100644 --- a/ActiveSync/SoObjectWebDAVDispatcher+ActiveSync.m +++ b/ActiveSync/SoObjectWebDAVDispatcher+ActiveSync.m @@ -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"]; } diff --git a/ActiveSync/iCalEvent+ActiveSync.m b/ActiveSync/iCalEvent+ActiveSync.m index a9988caed..755d2d20e 100644 --- a/ActiveSync/iCalEvent+ActiveSync.m +++ b/ActiveSync/iCalEvent+ActiveSync.m @@ -251,7 +251,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]; @@ -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]])