Compare commits

...
603 Commits
Author SHA1 Message Date
Francis Lachapelle f0b4a05c70 Merge to 2.2.5 2014-06-05 13:35:45 -04:00
Francis Lachapelle 6b6ec8a2ae Update ChangeLog 2014-06-05 13:35:17 -04:00
Francis Lachapelle ad30df26af Preparation for release 2.2.5 2014-06-05 13:34:40 -04:00
Francis Lachapelle 6e56f46f86 Update Dutch, Finnish, German, Polish translations 2014-06-05 13:29:10 -04:00
Francis Lachapelle fe38518a36 Minor syntax and comments improvements 2014-06-05 12:14:34 -04:00
Francis Lachapelle e118a72eab Add meta tag to tell IE to use the highest mode 2014-06-05 10:32:13 -04:00
Ludovic Marcotte 72bec939d6 Fixed text/plain reencoding issues for Outlook 2014-06-04 15:56:22 -04:00
Ludovic Marcotte ba258ca806 Fixed repetitive events issues 2014-06-04 15:23:41 -04:00
Ludovic Marcotte 0c2e2f28f7 Don't try to add attachments during reply operations 2014-05-30 13:53:20 -04:00
Ludovic Marcotte f0dfe37a55 Avoid crashing when forwarding mails with no Subject header 2014-05-30 08:41:42 -04:00
Francis Lachapelle 95d6911f1a Merge to 2.2.4 2014-05-29 11:17:46 -04:00
Francis Lachapelle dace1439df Update ChangeLog 2014-05-29 11:16:59 -04:00
Francis Lachapelle d91b37413f Preparation for release 2.2.4 2014-05-29 11:16:40 -04:00
Francis Lachapelle bd916f06eb Update ChangeLog 2014-05-29 11:15:13 -04:00
Francis Lachapelle ecbe0858f7 Update translations 2014-05-29 11:14:23 -04:00
Francis Lachapelle 24095a464c Update CKEditor to version 4.4.1 2014-05-29 10:50:48 -04:00
Francis Lachapelle 9ce3b8ff8f Merge pull request #40 from dekkers/fix-unit-test
Fix unit test with gnustep 1.24
2014-05-29 10:32:30 -04:00
Jeroen Dekkers efc33d8174 Fix unit test by also checking for the different gnustep 1.24 ordering of elements 2014-05-29 15:53:13 +02:00
Jeroen Dekkers 93971dc434 Add $(TEST_TOOL) as dependency of make check 2014-05-29 15:35:46 +02:00
Francis Lachapelle fac9520f64 Fix update of participation status via CalDAV
Fixes #2786
2014-05-28 11:39:25 -04:00
Francis Lachapelle 9eb075cc3f Rename "Archive" to "Export" in Webmail
Fixes #2758
2014-05-28 11:24:10 -04:00
Francis Lachapelle c5922b07aa Restore options when editing a draft
Fixes #193
2014-05-28 11:21:11 -04:00
Ludovic Marcotte 51e07fc306 Fix over previous commit 2014-05-27 15:33:39 -04:00
Ludovic Marcotte d35c52bb38 Fix for bug #2688 2014-05-27 14:44:57 -04:00
Ludovic Marcotte 6bab4c94f2 Added an empty stub for the Provision command 2014-05-27 09:42:02 -04:00
Ludovic Marcotte c31429a5d5 Also include the BS character in non-safe ones. 2014-05-27 08:45:00 -04:00
Ludovic Marcotte 04bb88a470 Updated NEWS file regarding pull request #39 2014-05-26 13:25:39 -04:00
extrafu c79cd750d8 Merge pull request #39 from alexcloutier/fix/publicFolder_ConfigNaming
Added new SOGo configurable variable
2014-05-26 13:24:50 -04:00
Ludovic Marcotte 6fc81e61ec Fixed documentation: NGImap4ConnectionGroupPrefix -> NGImap4ConnectionGroupIdPrefix 2014-05-23 11:30:28 -04:00
Francis Lachapelle d9ad286650 Fix newline in signature of attachment
Fixes #2787
2014-05-23 11:23:02 -04:00
Alexandre Cloutier dd57d56cf9 remove crufts and applies comments 2014-05-23 10:15:21 -04:00
Ludovic Marcotte ab7780d617 Prevent a crash when someone tries to access /SOGo/Microsoft-Server-ActiveSync directly 2014-05-22 14:39:58 -04:00
Ludovic Marcotte cb9332f240 Updated NEWS file regarding #2775 2014-05-22 10:26:58 -04:00
Ludovic Marcotte 7b60ad4797 Added patch from #2775 2014-05-22 09:20:05 -04:00
Alexandre Cloutier 3261c21549 fix case where the displayed name for the subscribed folders is duplicated 2014-05-21 14:26:08 -04:00
Francis Lachapelle 364b409501 FIx mail templates for Brazilian Portuguese
Fixes #2738
2014-05-21 08:44:35 -04:00
Alexandre Cloutier 064565e1a9 Added new SOGo configurable variable for which you can change the default display when adding a shared calendar or a shared addressBook 2014-05-20 17:05:13 -04:00
Alexandre Cloutier f92d280fbb remove unneeded condition to fix navigation in print preview 2014-05-20 11:24:27 -04:00
Francis Lachapelle ea2bce706c Update NEWS file 2014-05-16 21:15:38 -04:00
Francis Lachapelle d74afaf295 Update French translation 2014-05-16 21:15:28 -04:00
Francis Lachapelle 5e7beb3345 Remove unused localizable strings 2014-05-16 21:14:59 -04:00
Francis Lachapelle 2df5887eec Merge pull request #36 from alexcloutier/feat/calendarPrint
New print option in Calendar module
2014-05-16 16:56:51 -04:00
Francis Lachapelle 3d1bdf1a09 Update French translation 2014-05-16 16:52:44 -04:00
Francis Lachapelle 5de1343506 Remove unused localizable string 2014-05-16 16:44:25 -04:00
Francis Lachapelle 1eaa3f3891 Update NEWS file 2014-05-16 16:34:17 -04:00
Francis Lachapelle c2d3a827bd Merge branch 'alexcloutier-feat/searchCapabilities' 2014-05-16 16:30:24 -04:00
Francis Lachapelle 6b72a8d126 Merge branch 'feat/searchCapabilities' 2014-05-16 16:28:43 -04:00
Francis Lachapelle 819d0641b7 Remove common localizable strings from UI/Contacts 2014-05-16 16:19:40 -04:00
Francis Lachapelle 5d7f4ba6c6 Restore localizable string
To avoid new translation ..
2014-05-16 15:59:52 -04:00
Francis Lachapelle 34a7e28858 Rename 'Properties' button of contacts to 'Edit' 2014-05-16 15:58:34 -04:00
Francis Lachapelle 87b010c700 Indentation 2014-05-16 15:57:33 -04:00
Francis Lachapelle a44b183b7e Merge pull request #38 from alexcloutier/fix/link_address
New AddressBook properties popup window
2014-05-16 15:33:23 -04:00
Alexandre Cloutier b488721f83 Reverse loop to make sure no objects is skipped 2014-05-16 15:00:47 -04:00
Alexandre Cloutier 8a03f3bd63 remove start date in tasks 2014-05-16 14:36:51 -04:00
Alexandre Cloutier f8c8abc989 Function isPublicAccessEnabled was missing 2014-05-16 13:50:52 -04:00
Alexandre Cloutier db8d9bb16c Repair broken logic 2014-05-16 11:29:37 -04:00
Alexandre Cloutier 2794425a3f added last changes from cgx 2014-05-16 10:04:37 -04:00
Ludovic Marcotte 2f7979c796 Fix for bug #2709 2014-05-16 08:33:06 -04:00
Ludovic Marcotte c426afd7f2 New cache subsystem for ActiveSync. 2014-05-15 15:03:24 -04:00
Alexandre Cloutier 07445eb069 Created a window for address book properties and add the cardDav URL 2014-05-15 14:45:53 -04:00
Ludovic Marcotte 93bf98c326 Fixed copyright 2014-05-15 14:45:32 -04:00
Ludovic Marcotte c08c3e27d5 Improved modseq code 2014-05-15 14:44:53 -04:00
Ludovic Marcotte c8860dc92b Dropped old user-settings for ActiveSync 2014-05-15 14:32:46 -04:00
Ludovic Marcotte 1a1543a380 Updated script to reflect new table names 2014-05-15 14:29:39 -04:00
Ludovic Marcotte d2d5467317 Removed unused fluff in the file. 2014-05-14 10:51:16 -04:00
Ludovic Marcotte 18443de9bf Updated copyright info 2014-05-14 09:58:05 -04:00
Ludovic Marcotte be72456a9a Renamed folder cache creation method 2014-05-14 09:56:10 -04:00
Ludovic Marcotte a54b3e4289 Renamed the default table name from socfs_ to sogo_cache_folder_ 2014-05-14 08:56:35 -04:00
Ludovic Marcotte 7a4feae8b8 Updated code to reflect cache regorg. 2014-05-14 06:56:05 -04:00
Ludovic Marcotte 99d49b9bd9 Updated code to use the category 2014-05-13 21:14:57 -04:00
Ludovic Marcotte 5f9fb4e1c4 Big refactor for new caching mechanism. 2014-05-13 21:06:59 -04:00
Ludovic Marcotte ef2188962a Renamed cache files for generalization.
The upcoming commit will rename the content.
2014-05-13 19:58:19 -04:00
Ludovic Marcotte 2922f15ca7 More rename 2014-05-13 18:03:37 -04:00
Ludovic Marcotte 41e6fb89d3 Renamed constants in preparation for the big cache cleanup 2014-05-13 17:54:02 -04:00
Ludovic Marcotte c4a3843695 Removed unused configuration parameters 2014-05-13 13:52:20 -04:00
Alexandre Cloutier bf67b6435f applies comments 2014-05-13 13:21:18 -04:00
Alexandre Cloutier b5319446db display and printing modification 2014-05-13 10:36:26 -04:00
Francis Lachapelle d58184af15 Fix synchronization of seen/unseen status of msgs 2014-05-13 10:15:02 -04:00
Francis Lachapelle fbc6856fd5 Improve contextual menu in events list 2014-05-12 16:06:49 -04:00
Francis Lachapelle 5c41915080 Fix focus of popup windows with FF on Windows 2014-05-12 15:25:50 -04:00
Francis Lachapelle 698524b39f Fix synchronization of seen/unseen status of msgs
Fixes #2715
2014-05-09 17:28:02 -04:00
Ludovic Marcotte 1f5a2a4c62 Fixed IMAP copy/move op between subfolder in different accounts 2014-05-09 15:40:57 -04:00
Alexandre Cloutier fc3cfa5484 applied comments 2014-05-08 19:14:39 -04:00
Alexandre Cloutier 593b44ed01 forgotten code 2014-05-08 17:53:20 -04:00
Alexandre Cloutier b2ed7e3f6b search capabilites 2014-05-08 17:17:05 -04:00
Ludovic Marcotte bc2b41f383 Fixed unit test. 2014-05-08 09:13:37 -04:00
Ludovic Marcotte 7d7961ffcf Fix for bug #2492 2014-05-02 13:35:21 -04:00
Francis Lachapelle 0b9afec635 Fix saving preferences with no Sieve requirements
Fixes #2746
2014-05-01 14:07:25 -04:00
Francis Lachapelle 4e42a6a689 Don't limit Sieve script to 8KB
Fixes #2745
2014-04-30 12:36:51 -04:00
Alexandre Cloutier da8febf138 Printing display appear on one page only, fix issues with browsers 2014-04-29 15:42:50 -04:00
Francis Lachapelle 8c563c2922 Fix possible exception when retrieving reminder
Fixes #2744
2014-04-29 14:26:18 -04:00
Alexandre Cloutier fa5cf55367 Update GNUmakefile 2014-04-28 15:42:17 -04:00
Alexandre Cloutier e43b704858 Update UIxCalViewPrint.js 2014-04-28 15:32:47 -04:00
Alexandre Cloutier 44a4baca7f fix the comments in the headers 2014-04-28 15:30:32 -04:00
Alexandre Cloutier 78447d81ae Code refactoring and retouch 2014-04-28 13:54:29 -04:00
Alexandre Cloutier 9dc07fccc0 It is now possible to print the calendar as a list, dayView or weekView 2014-04-25 18:04:24 -04:00
Ludovic Marcotte ba7b65cf7b Fix for bug #2733 2014-04-24 07:59:07 -04:00
Francis Lachapelle 66bfbeaac1 MailEditor: fix text conversion with HTML entities 2014-04-23 10:55:04 -04:00
Ludovic Marcotte 619cb2c0ec Fix for bug #2721 2014-04-23 09:22:20 -04:00
Alexandre Cloutier f9869d19b4 Finished the view, need to display the eventsblock 2014-04-22 17:47:29 -04:00
Alexandre Cloutier 57b747c24a Events list is done. 2014-04-17 17:33:30 -04:00
Alexandre Cloutier 8f6b0f80a7 Creation of the first version of the printing interface 2014-04-14 10:32:08 -04:00
Alexandre Cloutier cb5e6e7ef2 adding button print calendar toolbar, adding template for the print window, ajusting indentation 2014-04-14 10:32:08 -04:00
Francis Lachapelle 49363cfe36 Update datepicker to latest version
From https://github.com/eternicode/bootstrap-datepicker/
2014-04-11 21:37:55 -04:00
Francis Lachapelle c345fc2b8d Fix display of category of events
Fixes #2703
2014-04-10 12:25:42 -04:00
Francis Lachapelle d200629b01 Fix CSS in contact editor and preferences module 2014-04-10 10:05:28 -04:00
Francis Lachapelle cfc1ac6b3b Add missing localizable string 2014-04-10 10:02:51 -04:00
Ludovic Marcotte e66ceaad07 Fixed gcc warnings and added some rationale around yesterday's fix 2014-04-10 09:40:25 -04:00
Ludovic Marcotte f370ac114a Now include message/rfc822 parts as attachments when forwarding mails 2014-04-10 09:24:43 -04:00
Ludovic Marcotte 75ee6b4806 Fixed once more true/false errors 2014-04-10 08:44:44 -04:00
Ludovic Marcotte 0961fbbab3 Properly escape attendee names in case they contain HTML entities 2014-04-10 06:59:18 -04:00
Ludovic Marcotte 0d1c39ca71 Added new configuration parameter to limit the window size 2014-04-09 20:12:19 -04:00
Ludovic Marcotte 5739356f88 Fix tests to handle list-component 2014-04-09 19:27:38 -04:00
Ludovic Marcotte 33467093c1 Fix for #2695 2014-04-09 18:03:33 -04:00
Ludovic Marcotte 96ece873ca Fix for bug #2654 2014-04-09 14:49:31 -04:00
Ludovic Marcotte 8909775cf6 Fix for #2680 2014-04-09 12:19:23 -04:00
Ludovic Marcotte 0ba59de88e Fixed formatting/warnings in previous commit. 2014-04-09 11:09:13 -04:00
extrafu 4fbe937f6d Merge pull request #22 from alexcloutier/fix/1046
BugFix #1046; Whenever the sieve server is unavailable an error message will appear
2014-04-09 11:01:19 -04:00
Ludovic Marcotte ab80e87a3f Applied patches from #2700 2014-04-09 10:57:56 -04:00
Alexandre Cloutier 068eb921aa rebase and fix comments made by extrafu 2014-04-09 10:48:47 -04:00
Alexandre Cloutier 5c13fade22 Fix merge 2014-04-09 10:35:10 -04:00
Ludovic Marcotte 371e5ead08 Updated the doc in prepration for the release 2014-04-09 10:34:48 -04:00
Alexandre Cloutier c5e6ccf332 Fix function sieveClient and the way the iVar Client is handled. Change behaviour of saveMailAccounts()so sogo wont crash if the user tries to resave his preferences after a connection error. 2014-04-09 10:31:34 -04:00
Alexandre Cloutier ec9d48c3a9 Change the function name getClient to sieveClient 2014-04-09 10:29:23 -04:00
Alexandre Cloutier 877082f042 Added missing functions getClient and IsSieveServerConnected and the changes that comes with it 2014-04-09 10:24:35 -04:00
Alexandre Cloutier 342b68fd44 Erase the merging conflicts writings 2014-04-09 10:23:43 -04:00
Alexandre Cloutier e24c22e3dc BugFix #1046; Whenever the sieve server is unavailable an error message will appear. 2014-04-09 10:23:43 -04:00
Ludovic Marcotte 7997448d41 Fixed issus in previous commits 2014-04-09 06:33:02 -04:00
Ludovic Marcotte 3629670fca Fix for #2489 2014-04-08 15:35:36 -04:00
Alexandre Cloutier c250b9a6d4 Fix deleting calendar
Added a "/" inside the function: deletePersonalCalendarConfirm().
2014-04-08 15:32:13 -04:00
extrafu afa564a6a6 Merge pull request #23 from alexcloutier/fix/1636
BugFix#1636; fix the issue where the user could add any birthday for his contact.
2014-04-08 13:17:54 -04:00
Alexandre Cloutier d9b99f536c Erased strings no longer used 2014-04-08 12:48:59 -04:00
Alexandre Cloutier 5699e5e1b4 Add datepicker for contact birthday 2014-04-08 12:12:30 -04:00
Francis Lachapelle e869406081 Minor CSS improvement in mail headers 2014-04-08 11:51:47 -04:00
Ludovic Marcotte 3e221253ad Fix for feature #1496 2014-04-08 11:19:53 -04:00
Alexandre Cloutier 446ef3467a Fix typo 2014-04-08 09:14:00 -04:00
extrafu bf64076b87 Merge pull request #29 from alexcloutier/feat/1496
New feature : 1496

Don't forget to fix the typo.
2014-04-07 19:42:31 -04:00
Alexandre Cloutier c9cbcf2566 applied Morgan's law 2014-04-07 16:40:44 -04:00
extrafu 4fe0358581 Merge pull request #20 from alexcloutier/fix/2616
bugFix #0002616 : change the behavior of ApplicationBaseURL.
2014-04-07 15:44:07 -04:00
Francis Lachapelle 534e4e3d4d Fix text nodes of message with HTML entitites 2014-04-07 11:21:52 -04:00
Alexandre Cloutier 09bcd2aee2 fix code 2014-04-07 10:59:38 -04:00
extrafu 526e21e837 Merge pull request #32 from dekkers/cleanup-generated-files
Delete generated source files when running "make clean".
2014-04-06 17:34:22 -04:00
Jeroen Dekkers c80e222210 Delete generated source files when running "make clean". 2014-04-06 22:44:50 +02:00
Francis Lachapelle 6e60bbb553 Fix saved HTML content of draft uploading a file 2014-04-04 20:20:32 -04:00
Ludovic Marcotte 846212336a Make use of a local pool to avoid over-memory usage 2014-04-04 16:53:58 -04:00
Alexandre Cloutier 349f4d824a Fix function sieveClient and the way the iVar Client is handled. Change behaviour of saveMailAccounts()so sogo wont crash if the user tries to resave his preferences after a connection error. 2014-04-04 15:04:37 -04:00
Alexandre Cloutier 2f565d2ec9 fix variable name for UIxFilterEditor.js
FolderEncoding to sieveFolderEncoding
2014-04-04 14:56:14 -04:00
extrafu eb7cabac71 Merge pull request #19 from alexcloutier/fix/2622
BugFix #0002622: The server Dovecot use by default an UTF-8 and by doing...
2014-04-04 09:21:49 -04:00
Ludovic Marcotte 2ff4498983 Fixed previous commit 2014-04-04 08:44:50 -04:00
Ludovic Marcotte 3eec753b73 Slightly improved previous pull request merge. 2014-04-04 08:39:13 -04:00
extrafu 7b0ffacff0 Merge pull request #24 from alexcloutier/fix/2612
It is now possible to see the version on the general page of the preferences window
2014-04-04 08:33:39 -04:00
Alexandre Cloutier f999c87d4d added traduction in localstring french, added some specification in function sogoVersion 2014-04-03 17:09:00 -04:00
Francis Lachapelle 48f98ef34e Merge to 2.2.3 2014-04-03 10:06:08 -04:00
Francis Lachapelle 378f2b5876 Preparation for release 2.2.3 2014-04-03 10:05:43 -04:00
Francis Lachapelle d091b3d7cd Update ChangeLog 2014-04-03 10:01:40 -04:00
Francis Lachapelle 370e1e6d26 Update CKEditor to version 4.3.4 2014-04-03 10:01:01 -04:00
Francis Lachapelle e2b3d5a7ff Update translations 2014-04-03 09:54:27 -04:00
Ludovic Marcotte 078b88a396 Fix for #2686 2014-04-02 18:14:17 -04:00
Francis Lachapelle ee09b80fc3 Simplify [UIxContactEditor addressBookDisplayName]
We were trying to translate the default address book name to the user's
language, but the method [SOGoContactFolders defaultFolderName] is
already returning a translated string, making the whole logic useless.
2014-04-02 10:15:59 -04:00
Francis Lachapelle 99d9615c92 Update NEWS file 2014-04-02 10:09:09 -04:00
Francis Lachapelle 79c3fa8ad2 Merge pull request #30 from dekkers/remove-executable-permission-from-jquery
Remove executable permission from jQuery modules
2014-04-01 11:42:07 -04:00
Francis Lachapelle fd07112113 Merge pull request #31 from opensaucesystems/patch-1
Fix email validation regexp to allow gTLDs
2014-04-01 08:18:51 -04:00
opensaucesystems ce5d591d1d Fix email validation regexp to allow gTLDs
New generic TLDs can be as long as 13 characters.
2014-04-01 12:35:18 +01:00
Jeroen Dekkers e603742d71 Remove executable permission from jQuery 2014-03-29 17:11:05 +01:00
Ludovic Marcotte 585d224a15 Fixed the AS bundle common makefile 2014-03-28 16:44:33 -04:00
Ludovic Marcotte 6a39b48a37 Fix for bug #2691 2014-03-28 15:22:45 -04:00
Ludovic Marcotte 633723a470 Fix for bug #2681 2014-03-28 14:44:00 -04:00
Ludovic Marcotte ba32b95308 Fixed the ActiveSync issue marking mails as read when downloading them 2014-03-28 14:18:48 -04:00
Alexandre Cloutier 03d5975be3 Changed strings in french and change the instanciation of dictionary(addressBooksIDWithDisplayName) to release it manually 2014-03-28 10:28:33 -04:00
Alexandre Cloutier 1da1764aae The collected address book will be created only if the user select it in the preferences. Fix labels. 2014-03-27 15:27:48 -04:00
Francis Lachapelle 6e4f776d4b Fix detection of IMAP flags support in JavaScript
Fixes #2664
2014-03-27 12:06:24 -04:00
Alexandre Cloutier 365e271a84 Correct typo 2014-03-25 15:44:28 -04:00
Alexandre Cloutier bce701208a Added the modifications specified by extrafu 2014-03-25 14:53:42 -04:00
Alexandre Cloutier b16911edc1 Modified the displayed name of SOGo version and added the label in the .lproj 2014-03-24 13:55:52 -04:00
Alexandre Cloutier 76307cfaaf New feature : 1496; Unknown outgoing email addresses can now be automatically be added to your address books. 2014-03-24 13:41:57 -04:00
Francis Lachapelle e5fb7dc7b8 Fix JavaScript exception in Contacts module
Fixed calling unescapeHTML on null variables. Also fixed errors on IE7
(and possibly other versions).
2014-03-24 12:43:34 -04:00
Francis Lachapelle 50e7ea7188 Fix possible exception when retrieving reminder
Fixes #2678
2014-03-24 07:42:57 -04:00
Francis Lachapelle ae0c5eae77 Merge to 2.2.2 2014-03-21 15:39:00 -04:00
Ludovic Marcotte 89e61f6d5d Fixed SOPE include path 2014-03-21 15:37:14 -04:00
Francis Lachapelle 0c2d727057 Merge to 2.2.2 2014-03-21 15:33:55 -04:00
Francis Lachapelle 85f4af56e9 Update ChangeLog 2014-03-21 15:22:28 -04:00
Francis Lachapelle 04bdb22b00 Preparation for release 2.2.2 2014-03-21 15:20:45 -04:00
Ludovic Marcotte 874b1d9eba Added NEWS entry for previous commit 2014-03-21 14:08:53 -04:00
Ludovic Marcotte b143688419 Fix for bug #2669 2014-03-21 13:55:59 -04:00
Francis Lachapelle 5f3d2d988e Update translations 2014-03-21 13:51:36 -04:00
Francis Lachapelle 93f1540c17 Update jQuery File Upload to version 9.5.7 2014-03-21 13:47:40 -04:00
Francis Lachapelle 877e44c6d2 Update CKEditor to version 4.3.3 2014-03-21 13:32:28 -04:00
Ludovic Marcotte 4ca3d351e0 Fixed previous commit 2014-03-21 09:05:52 -04:00
Ludovic Marcotte 19b6704955 Only touch text/plain and text/html parts during Outlook sanitization 2014-03-21 09:02:39 -04:00
Francis Lachapelle 64787555ff Fix classification icon of events
Fixes #2664
2014-03-20 22:14:45 -04:00
Francis Lachapelle 27ffcf240f Fix handling of accents when filtering contacts
Fixes #2656
2014-03-20 15:29:32 -04:00
Francis Lachapelle 893d75bd5f Update Transifex configuration
Added new SoObjects/Mailer resource.
2014-03-20 14:18:03 -04:00
Ludovic Marcotte b0f26f1dcc Updated the doc regarding the isAddressBook parameter in sources. 2014-03-20 09:57:19 -04:00
Ludovic Marcotte a196ed210e Removed old values. 2014-03-19 17:04:04 -04:00
Ludovic Marcotte 1c28a4b4d2 Fixed translations for "OtherUsersFolderName" and "SharedFoldersName" (#2657) 2014-03-19 17:02:10 -04:00
Ludovic Marcotte fc56493b78 Added sanitization support for Outlook/ActiveSync 2014-03-19 11:44:36 -04:00
Ludovic Marcotte 3a33010918 Updated NEWS file regarding previous commit 2014-03-19 11:33:00 -04:00
Ludovic Marcotte 83bccda551 Avoid creating duplicates in Outlook on MoveItems (#2650) 2014-03-19 11:31:54 -04:00
Ludovic Marcotte 35d71f6150 Added deviceType capabilities to the code 2014-03-19 11:30:18 -04:00
Ludovic Marcotte e92a145325 Updated NEWS file regarding previous commit 2014-03-19 08:27:36 -04:00
Ludovic Marcotte c3062284e3 Disabled provisionning for now, as we don't support it. 2014-03-18 19:06:41 -04:00
Francis Lachapelle e2f192b793 Fix display of company/department of cards
Fixes #2662
2014-03-14 15:45:12 -04:00
Francis Lachapelle b8f239bf34 Fix construction of mail folders tree 2014-03-14 15:34:43 -04:00
Francis Lachapelle e968be8024 Bump version to 2.2.2 2014-03-14 13:02:27 -04:00
Francis Lachapelle 3c3bebeee3 Fix resource conflict check when creating event
Fixes #2541
2014-03-14 09:23:55 -04:00
Francis Lachapelle 26e9defdbd Update French translation 2014-03-14 09:17:52 -04:00
Francis Lachapelle 8742f28c29 Fix decoding of HTML entitities in reminder alert
Fixes #2659
2014-03-13 08:44:47 -04:00
Francis Lachapelle bd577fd513 Fix unseen count of folders beginning with a digit
Fixes #2652
2014-03-13 08:41:42 -04:00
Francis Lachapelle c8550c8a4a Fix copy/move to folder with numerical prefix
Fixes #2658
2014-03-12 16:35:22 -04:00
Ludovic Marcotte 1bdf88fb67 Don't try to delete an already non-existant object (#2653) 2014-03-11 13:21:05 -04:00
Alexandre Cloutier d108777e89 Display the version at the top of the general tap 2014-03-11 10:25:01 -04:00
Francis Lachapelle 167a06e3e9 Merge pull request #25 from dani/master
Disable file paste support in mail editor
Fixes #2641
2014-03-11 10:16:52 -04:00
Daniel B. af68f10115 Fix #2641
Disabling the pasteZone support (which only works in Chrome or Opera anyway) fixes the problem of unwanted PNG attachment when you paste the recipient list from Excel
2014-03-11 09:23:13 +01:00
Francis Lachapelle cbd22762c3 Fix possible exception when retrieving reminder
Fixes #2647
Fixes #2648
2014-03-10 14:47:01 -04:00
Alexandre Cloutier 8cc352fb28 It is now possible to see the version on the general page of the preferences window 2014-03-10 14:45:10 -04:00
Alexandre Cloutier 0d69a476bc add specific date for limiting the user to today's for his contact birthday 2014-03-10 12:16:12 -04:00
Alexandre Cloutier cee1e529f8 BugFix#1636; fix the issue where the user could add anything for the birthday of his contacts 2014-03-10 12:05:01 -04:00
Alexandre Cloutier 3a681bd5a5 Change the function name getClient to sieveClient 2014-03-10 10:53:44 -04:00
Alexandre Cloutier f5faa60814 Added missing functions getClient and IsSieveServerConnected and the changes that comes with it 2014-03-10 10:33:27 -04:00
Alexandre Cloutier f8939bfb3e Change the variable name for sieveFolderEncoding instead of folderEncoding 2014-03-10 10:07:47 -04:00
Ludovic Marcotte 78636f0396 Added default value for WOListenQueueSize 2014-03-09 15:58:11 -04:00
Ludovic Marcotte 037c2d3ddf Added documentation for WOListenQueueSize 2014-03-09 15:56:38 -04:00
Francis Lachapelle 072f5f5a15 Merge to 2.2.1 2014-03-07 14:03:41 -05:00
Francis Lachapelle 41fe9195f2 Update ChangeLog 2014-03-07 14:00:51 -05:00
Francis Lachapelle 23789b48bc Update Dutch translation 2014-03-07 14:00:08 -05:00
Francis Lachapelle 142296f71e Preparation for release 2.2.1 2014-03-07 10:53:17 -05:00
Francis Lachapelle 3bae2387d4 Fix contact autocompletion when UID is a digit 2014-03-06 22:13:17 -05:00
Francis Lachapelle 6cecca6c4f Fix CSS id for string prefixed with a digit
When encoding a string as a CSS identifier, we must add an underscore if
the strings starts with a digit.
2014-03-06 21:32:36 -05:00
Francis Lachapelle 28b1938bd9 Show folder name in dialog when renaming folder 2014-03-06 21:25:48 -05:00
Alexandre Cloutier f4d189ffc8 Erase the merging conflicts writings 2014-03-06 15:20:41 -05:00
Alexandre Cloutier 1b9ac03e94 BugFix #1046; Whenever the sieve server is unavailable an error message will appear. 2014-03-06 14:57:53 -05:00
Alexandre Cloutier 6ad87052ba bugFix #0002616 : change the behavior of ApplicationBaseURL. Now the object return a standard path(without a slash at the end of the path) That means every string added the URL ApplicationBaseURL must start with a Slash. 2014-03-06 14:47:54 -05:00
Alexandre Cloutier e7a16cba0d BugFix #0002622: The server Dovecot use by default an UTF-8 and by doing so it cause a wrong re-encoding in UTF-7 when reaching the sieve server (knowing that the foldername in sieve are encoded in UTF-7). Since it is not the case with a Cyrus server, I created a new variable available in the sogo.conf that let you specified the type of encoding you need. By default the encoding is set to UTF-7. ex : SOGoFolderEncoding = 'UTF-7' 2014-03-06 14:33:31 -05:00
Ludovic Marcotte 31ace947cb Fixed race condition when syncing huge amount of deleted messages using AS 2014-03-06 14:16:08 -05:00
Ludovic Marcotte 0cea36df2e Updated NEWS regarding previous commit 2014-03-06 14:10:47 -05:00
Ludovic Marcotte afd7452323 Fixed returned date format and fixing missing 'name part' in address 2014-03-06 14:05:59 -05:00
Francis Lachapelle e4a21bcef5 Webmail: fix encoding of subfolder name
Fixes #2637
2014-03-06 09:50:53 -05:00
Francis Lachapelle 0c99323db3 Fix possible exception when retrieving reminder
Fixes #2624
2014-03-05 13:42:38 -05:00
Ludovic Marcotte da208d5b4a Updated NEWS regarding previous commit 2014-03-05 09:09:33 -05:00
Ludovic Marcotte 158af71152 Fix for bug #2609 2014-03-05 09:07:39 -05:00
Francis Lachapelle 163bce39b5 Fix list sorting of events by calendar name
Fixes #2629
2014-03-04 22:03:28 -05:00
Francis Lachapelle 02c72fee6a Fix unsubscription when renaming an IMAP folder
Fixes #2630
2014-03-04 21:32:57 -05:00
Francis Lachapelle 8bef84bded Update translations 2014-03-04 09:23:17 -05:00
Francis Lachapelle 8db3b22eb9 Bump version to 2.2.0a 2014-03-03 22:08:29 -05:00
Francis Lachapelle 1aabcf04b5 Fix sogo-tool operations on Sieve script
Fixes #2617
2014-03-03 22:07:24 -05:00
Francis Lachapelle 1db85743a0 Merge to 2.2.0 2014-02-24 16:54:11 -05:00
Francis Lachapelle c6b227160c Update ChangeLog 2014-02-24 16:53:46 -05:00
Francis Lachapelle 5f2920db9b Update translations 2014-02-24 16:49:16 -05:00
Francis Lachapelle 761a7e2be1 Update Microsoft Outlook Configuration guide 2014-02-24 16:42:59 -05:00
Francis Lachapelle 9ed1d57ec2 Fix auto-acceptation of resources as attendees
Fixes #2541
2014-02-24 16:07:55 -05:00
Francis Lachapelle 2b6428efd0 Always check resource conflict for new events
Fixes #2541
2014-02-24 07:57:11 -05:00
Francis Lachapelle be36e0ceea Fix view changes in calendar module
Fixes #2613
2014-02-21 20:37:44 -05:00
Francis Lachapelle 070d3dd825 Extract node value with 'textValue' 2014-02-21 15:48:41 -05:00
Francis Lachapelle 96f2552b45 Preparation for release 2.2.0 2014-02-19 21:57:01 -05:00
Francis Lachapelle 2948920e0b Improve display of contact
Fixes #2350
2014-02-18 16:15:06 -05:00
Francis Lachapelle 212d7149ed Fix display of a contact's birthday
Fixes #2503
2014-02-18 10:13:34 -05:00
Ludovic Marcotte 668c7e8b49 Correctly handle email invitations as attendee/organizer 2014-02-17 16:08:29 -05:00
Ludovic Marcotte 9851c32a1e Fixed the handling of organizers 2014-02-17 15:49:22 -05:00
Francis Lachapelle e7f27427c8 Add missing import in UIxPreferences.m 2014-02-17 15:42:55 -05:00
Francis Lachapelle f0a29d3ca2 Fix debian dependencies for sogo-activesync 2014-02-17 15:05:31 -05:00
Ludovic Marcotte ec0a5ac4bf Properly handle event updates/pull when we are or not an attendee/organizer 2014-02-17 11:30:41 -05:00
Ludovic Marcotte 4ca8b9d0aa Copyright updates 2014-02-17 11:30:00 -05:00
Ludovic Marcotte d560d0e470 Always return a response avoiding iOS crashes on no-changes 2014-02-17 11:28:06 -05:00
Francis Lachapelle 401320e08b Contact: fix display of urls 2014-02-17 11:12:09 -05:00
Ludovic Marcotte 8083b41092 Added the context everywhere 2014-02-17 10:01:44 -05:00
Ludovic Marcotte 9218c7f253 Added missing recurrences support, improved MeetingResponse, added WindowSize support.
Also more bug fixes regarding event invitations, and ServerId handling for
calendar objects.
2014-02-17 08:46:05 -05:00
Ludovic Marcotte 4d1fdb33f5 Deleted wrongly added file 2014-02-17 08:42:35 -05:00
Ludovic Marcotte 2356562778 Added method to get synctag starting from an other one.
We also no longer fetch vanished items of modseq == 0
2014-02-17 08:41:12 -05:00
Ludovic Marcotte c686e3294d Added method to sanitize calendar "ServerId" 2014-02-17 08:39:48 -05:00
Ludovic Marcotte 1ff91f7b59 Added -activeSyncRepresentation to NSData objects 2014-02-17 08:38:34 -05:00
Francis Lachapelle b34c6324cd Fix custom mail labels in Sieve filter editor 2014-02-14 21:32:33 -05:00
Ludovic Marcotte 75c8362df8 Avoid over-using LDAP connections when decomposing groups 2014-02-14 16:39:26 -05:00
Ludovic Marcotte ae07de5f6f Updated the Active Sync documentation 2014-02-14 13:46:21 -05:00
Francis Lachapelle 06d2364ea2 Improve display of toolboor menus with checkmarks 2014-02-13 12:56:24 -05:00
Francis Lachapelle 29e081ec56 Add more parameters examples to sogo.conf 2014-02-13 12:53:07 -05:00
Francis Lachapelle 113b02fd71 Fix encoding of contact ID in Ajax requests 2014-02-13 12:12:31 -05:00
Francis Lachapelle 35b108e645 Contact: fix display of links 2014-02-13 12:11:25 -05:00
Ludovic Marcotte 70266155d3 Fix double return 2014-02-12 21:55:09 -05:00
Francis Lachapelle fcfd8be771 Improve URL handling in popup of events 2014-02-10 22:05:35 -05:00
Francis Lachapelle b91032db8e Cleanup common English Localizable.strings 2014-02-10 22:05:35 -05:00
Ludovic Marcotte f4874600fe Bumped to v14.1 2014-02-10 20:17:54 -05:00
Ludovic Marcotte b14e99b32a New prefs for intervals, fixed missing events in meeting requests, bumped v14.1 2014-02-10 20:16:43 -05:00
Francis Lachapelle ea4b21e991 Decode HTML entities in JSON of calendar module 2014-02-10 13:49:02 -05:00
Francis Lachapelle 0307b8339a Detect URLs in popup of events 2014-02-10 13:45:51 -05:00
Francis Lachapelle b5f1d3a19a Guide: add SOGoCalendarDefaultReminder paramter 2014-02-10 11:25:38 -05:00
Ludovic Marcotte 8225f76279 Fixed globalobjid so it doesn't contain \n characters! 2014-02-07 16:17:11 -05:00
Francis Lachapelle c94595ea7f Escape HTML in CSS dialogs 2014-02-07 16:12:14 -05:00
Francis Lachapelle 3a5e44e7eb Decode HTML entities in JSON of calendar module 2014-02-07 15:53:39 -05:00
Francis Lachapelle 80a0940765 Escape HTML in JSON of contacts module 2014-02-07 15:52:43 -05:00
Francis Lachapelle 7118bbe0ab Replace '/' by '-' in filenames of attachments
Fixes #2537
2014-02-07 14:00:36 -05:00
Francis Lachapelle eee5beb698 Add message-id header to appointment notification
Fixes #2535
2014-02-07 10:52:06 -05:00
Ludovic Marcotte 3363b253ac Set additional properties on meeting requests 2014-02-07 10:45:09 -05:00
Francis Lachapelle 4070b9222d Rework HTML of appointment notifications
Needed to simplify the HTML so it displays properly in Outlook.

Fixes #2233
2014-02-07 09:59:45 -05:00
Francis Lachapelle 5ea56a6f8a Enlarge the note field of the contact editor 2014-02-06 21:55:28 -05:00
Ludovic Marcotte 379258de59 Pimped the doc for AS support and dropped all references to Funambol. 2014-02-06 21:25:08 -05:00
Ludovic Marcotte 93b3685aa4 Added birthday support 2014-02-06 19:35:23 -05:00
Ludovic Marcotte c4dc4d4eda Fixed compilation warning 2014-02-06 17:59:33 -05:00
Ludovic Marcotte c6d104fac5 Fixed contact sync'ing on Android 2014-02-06 17:57:01 -05:00
Francis Lachapelle ef79c09642 Don't use the HTML editor with Internet Explorer 7 2014-02-06 14:43:05 -05:00
Francis Lachapelle aeb712083a Fix static array retain 2014-02-06 14:37:43 -05:00
Francis Lachapelle 2c678101fc Fix handling of ACLs with multiple groups
Fixes #1854
2014-02-06 14:23:09 -05:00
Ludovic Marcotte b95362f963 Now make use of a NGMimeFileData object to avoid broken SOPE behaviour 2014-02-06 14:05:00 -05:00
Ludovic Marcotte 3175a9169f Mapped lots of contact properties 2014-02-05 20:56:01 -05:00
Ludovic Marcotte 9311f05cc0 Fixed the non-filtering of recurrence exceptions 2014-02-05 17:30:34 -05:00
Francis Lachapelle 78cbcfb560 Update translations 2014-02-05 16:15:30 -05:00
Ludovic Marcotte b8610b3eca Extended GetItemEstimate to GCS collections 2014-02-05 16:12:08 -05:00
Francis Lachapelle 1a7fc2a0e9 Escape HTML in JSON of calendar module
Fixes #2598
2014-02-05 16:06:20 -05:00
Ludovic Marcotte f7a20d0a83 Fixed broken encoding of single-value element 2014-02-05 15:23:09 -05:00
Francis Lachapelle a1cf066828 Update translations 2014-02-05 11:43:25 -05:00
Francis Lachapelle 359b6a99aa Encode HTML entities for inline forwards in text
Fixes #2411
2014-02-05 11:17:22 -05:00
Francis Lachapelle 826537ed01 Fix caching of DN in LDAP source 2014-02-05 09:04:00 -05:00
Ludovic Marcotte 3950e9d4c3 Moved DN cache to SOGoCache 2014-02-04 21:03:11 -05:00
Francis Lachapelle 9885211a5b Replace VARCHAR(1000000) by TEXT field type
Fixes #2516
2014-02-04 17:55:49 -05:00
Francis Lachapelle ef1be5dc5f Improve deleting occurences of recurrent events 2014-02-04 17:55:49 -05:00
Ludovic Marcotte 4e42d5d410 Disabled debugging... 2014-02-04 15:07:23 -05:00
Ludovic Marcotte 31969d162d Properly escape some control chars (and generalized it) 2014-02-04 15:03:02 -05:00
Ludovic Marcotte 2ff3b5ef5f First pass at 'push' support for Ping and Sync 2014-02-04 11:19:33 -05:00
Ludovic Marcotte 7fe48a1555 Fix for bug #2544 2014-02-04 09:02:40 -05:00
Francis Lachapelle fcddeb4224 Visually identify users with no freebusy
Fixes #2565
2014-02-03 15:15:14 -05:00
Francis Lachapelle f1cb87aa02 Convert JS alerts to CSS dialogs in aptmt editor 2014-02-03 12:03:51 -05:00
Francis Lachapelle a6424680cc Respect max bookings of resources in freebusy data
Fixes #2560
2014-02-03 11:56:00 -05:00
Francis Lachapelle b3dc645282 Warn user when dnd failed with resource conflict
Fixes #1613
2014-02-03 11:09:03 -05:00
Francis Lachapelle 2f0419c18a Warn user when overbooking a resource
Fixes #2541
2014-02-03 11:03:23 -05:00
Ludovic Marcotte 9e9407cf30 First pass at event invitations support + few bug fixes. 2014-02-03 10:24:33 -05:00
Ludovic Marcotte d709a1216b Updated NEWS file 2014-02-03 09:54:21 -05:00
Ludovic Marcotte 588352be7d Fix for bug #2587 2014-02-03 09:53:47 -05:00
Ludovic Marcotte a40d7ca342 Updated NEWS file 2014-01-31 15:11:13 -05:00
Ludovic Marcotte e4ce687e29 Update the content when the request is from Active Sync 2014-01-31 15:05:33 -05:00
Ludovic Marcotte bcb0764b19 Fix for bug #2505 2014-01-31 15:04:49 -05:00
Ludovic Marcotte ddd7be4333 Fix for bug #2187 2014-01-31 15:03:40 -05:00
Ludovic Marcotte d9f4a9935a Properly escape all foldernames 2014-01-31 10:33:36 -05:00
Francis Lachapelle ae75fee512 Update NEWS file 2014-01-30 10:37:36 -05:00
Ludovic Marcotte 8cdacd065f Properly escape the filename 2014-01-30 08:25:55 -05:00
Ludovic Marcotte af6a69c9fc Expunge immediately after MoveItems to force the Delete response 2014-01-29 11:21:36 -05:00
Ludovic Marcotte dc41e29f05 Fixed the MoveItems response 2014-01-29 11:16:58 -05:00
Ludovic Marcotte afc7519beb Properly escape values 2014-01-29 10:30:31 -05:00
Ludovic Marcotte f2d5a76911 Type fix for recurrence rules. 2014-01-29 09:48:18 -05:00
Francis Lachapelle 342ad84a24 Fix issues with contextual menu in calendars
Creating an event or a task using the contextual menu will now consider
the day and hour of the menu position (fixes #2557).
The next/previous day/month menu options have been fixed.
The menu will now disappear when clicking outside the contextual menu on
the calendar area.
2014-01-28 15:42:02 -05:00
Ludovic Marcotte 9580a8f8ee Added initial support for recurring events. 2014-01-28 14:26:35 -05:00
Ludovic Marcotte a96380a0dc Fixed SyncKey issue not being updated during the sync operation 2014-01-28 13:51:21 -05:00
Ludovic Marcotte 2fed02da59 When creating a new object, mark it as new. 2014-01-28 13:21:34 -05:00
Francis Lachapelle 84dc08adb6 Fix display of folder names in filter editor
Fixes #2569
2014-01-27 15:43:48 -05:00
Francis Lachapelle c160edf20a Add support for Sieve body extension 2014-01-27 15:09:22 -05:00
Ludovic Marcotte 3b7a3c94d4 Properly escape fields and improved data dumps. 2014-01-27 11:30:43 -05:00
Ludovic Marcotte 7b97e28cff Fixed compiler warning 2014-01-24 16:33:31 -05:00
Ludovic Marcotte 81bf1b41e9 Fixed the rename operation to force a FolderSync 2014-01-24 16:28:08 -05:00
Ludovic Marcotte ea86f136b7 Properly escape folder/file names and fixed date representation in emails 2014-01-24 14:10:19 -05:00
Francis Lachapelle fc0c580fe1 Fix validation of subscribed folders
Fixes #2583
2014-01-24 13:48:01 -05:00
Ludovic Marcotte 42a7bcb9ac Added verbosity in case wbxml <-> xml conversions fail 2014-01-24 11:44:12 -05:00
Ludovic Marcotte 9669f2bbba Added more props and fixed the NativeBodyType preventing OL2013 to work 2014-01-24 11:09:37 -05:00
Ludovic Marcotte 2563408872 Improved the README regarding MS licensing 2014-01-24 07:38:03 -05:00
Ludovic Marcotte dbea244f49 Merge branch 'master' of https://github.com/inverse-inc/sogo 2014-01-24 07:37:52 -05:00
Francis Lachapelle 0f9d8cdd2c Remove xml tag before doctype declaration 2014-01-23 14:48:36 -05:00
Francis Lachapelle 5105dbb342 Make all attachments available when re/fwd'ing
To do so, we save the draft to the mailstore.
2014-01-23 14:39:03 -05:00
Francis Lachapelle b26e767a10 Respect signature placement when forwarding a msg 2014-01-23 14:34:44 -05:00
Francis Lachapelle 940f85fde2 Add missing localizable string to webmail 2014-01-23 11:25:14 -05:00
Ludovic Marcotte adee80529e Added more event props and fixed date issues 2014-01-23 11:09:32 -05:00
Francis Lachapelle 295dfcfdd5 Webmail: allow the backspace on any platform 2014-01-23 10:21:22 -05:00
Ludovic Marcotte aa18abd842 Added more props and cleaned up the code 2014-01-23 09:41:41 -05:00
Francis Lachapelle feb398d59c Fix IE11 issue with mail editor 2014-01-23 09:15:34 -05:00
Francis Lachapelle 19b404de45 Update French translation 2014-01-23 08:17:16 -05:00
Jean Raby d1a384e539 Send IMIP responses if the event is in the future
Avoids sending responses for past events when importing events into
a new calendar from thunderbird or any DAV client.
2014-01-22 11:40:04 -05:00
Ludovic Marcotte e7f38f940e Moved the cards' logic into a category and added support for more AS ones 2014-01-22 11:27:27 -05:00
Ludovic Marcotte f7ba5d2346 Don't add DateCompleted if none exist 2014-01-22 11:25:18 -05:00
Ludovic Marcotte eeddf43a78 Add the milliseconds 2014-01-22 11:22:52 -05:00
Ludovic Marcotte eabe829236 Don't add empty <Commands> and specify the folder Class 2014-01-22 11:02:12 -05:00
Ludovic Marcotte 762b841249 Avoid crashes on broken configurations 2014-01-21 16:40:57 -05:00
Francis Lachapelle 3090448fcb Update prototype.js to fix IE 10 issues
Updated to commit @8c9ead49ec of
https://github.com/sstephenson/prototype/
2014-01-20 15:43:33 -05:00
Ludovic Marcotte a3e1d4813a Removed debug + refactored NSDate class 2014-01-20 10:21:33 -05:00
Ludovic Marcotte 046a645119 Refactored the code and added support for FilterType 2014-01-20 10:13:16 -05:00
Ludovic Marcotte 07d4b2bae2 Merge branch 'master' of https://github.com/inverse-inc/sogo 2014-01-16 15:13:29 -05:00
Ludovic Marcotte 343f2d8bfe Fixed the GetChanges detection and added FilterType decoding 2014-01-16 15:13:09 -05:00
Jean Raby 65276f7dc0 Add dependency on tmpwatch. The cronjob uses it.
Fixes #2577
2014-01-15 16:37:24 -05:00
Jean Raby 24663682d6 New package: sogo-activesync + sogo-tool fixes
Added dependency on sogo = %version for sogo-tool
2014-01-15 12:08:29 -05:00
Jean Raby 57cd315f2a explicitly list all *.SOGo folders
Otherwise, ActiveSync.SOGo would be listed twice, once in sogo-activesync and
once in sogo.
2014-01-15 11:07:14 -05:00
Ludovic Marcotte 29fcfda118 Implemented FolderDelete for mail folders 2014-01-15 09:36:25 -05:00
Ludovic Marcotte ada90677e1 Correctly update the SyncKey when creating or updating folders 2014-01-14 16:08:04 -05:00
Ludovic Marcotte 4c9c07e358 Merge branch 'master' of https://github.com/inverse-inc/sogo 2014-01-14 15:47:52 -05:00
Ludovic Marcotte b71180b006 Use the right DeviceId 2014-01-14 15:47:33 -05:00
Jean Raby 1ed41e2831 New deb package: sogo-activesync 2014-01-14 14:39:51 -05:00
Ludovic Marcotte 948553dce3 Properly extract the foldername 2014-01-14 13:50:17 -05:00
Jean Raby 74adf78446 Fix include directories for libwbxml 2014-01-14 13:37:51 -05:00
Ludovic Marcotte ee0ae8a1c0 Correctly add the folder type prefix when creating them 2014-01-14 11:44:33 -05:00
Ludovic Marcotte 38c649751c If GetChanges is omitted, consider it as YES 2014-01-14 11:41:26 -05:00
Ludovic Marcotte 645c718dfa Fixed broken comparison and added stub for processMeeting... 2014-01-14 10:49:55 -05:00
Ludovic Marcotte 02992a7018 Correctly decode base64 text parts before returning them 2014-01-14 10:42:15 -05:00
Ludovic Marcotte 0ffa0649c5 Wrap Fetch responses into <Responses> tags so iOS works correctly 2014-01-14 10:09:10 -05:00
Ludovic Marcotte 7c7cabe432 First pass at organizer/attendees support 2014-01-13 16:25:14 -05:00
Ludovic Marcotte bb9c4cf039 Handle not found objects and correctly get all "Collection" 2014-01-13 16:24:15 -05:00
Ludovic Marcotte c252f5b7a8 Fixed the license indent 2014-01-13 11:46:32 -05:00
Ludovic Marcotte 2e44ac0f9b Fixed MoveItems and also fixed Ping with no content 2014-01-13 10:19:00 -05:00
Ludovic Marcotte 2a9ccf8122 Now able to grab the command from the URI 2014-01-13 10:18:20 -05:00
Ludovic Marcotte f74066c9a6 Support for more props 2014-01-11 19:31:39 -05:00
Ludovic Marcotte ee49836f2e Disabled debugging... 2014-01-10 16:49:40 -05:00
Ludovic Marcotte bf798061d3 Fixed timezones support for events and added more supported props 2014-01-10 16:48:39 -05:00
Ludovic Marcotte 834e05bab1 Fixed typo messing up adds 2014-01-10 15:29:57 -05:00
Ludovic Marcotte e8438a6235 Don't write decoded stuff if not needed 2014-01-10 14:53:49 -05:00
Ludovic Marcotte 68dafdfdeb Removed old comments 2014-01-10 14:25:00 -05:00
Ludovic Marcotte e5bc46710c Initial Active Sync Support! 2014-01-10 14:12:53 -05:00
Ludovic Marcotte 7355eae1dc Now able to set Active Sync metadata in the user settings 2014-01-10 14:10:53 -05:00
Ludovic Marcotte 1d9febb511 Correctly handle the Active Sync requests 2014-01-10 14:10:16 -05:00
Ludovic Marcotte e21b30d768 Code cleanups 2014-01-10 14:09:32 -05:00
Ludovic Marcotte ae200360ba Code cleanups 2014-01-10 14:09:02 -05:00
Ludovic Marcotte e217ffb6c4 Code generalization to be usable from the ActiveSync bundle 2014-01-10 14:08:12 -05:00
Ludovic Marcotte a4a3a735b4 Moved the folder metadata generation to SoObject and added 'tag based' sync'ing support for IMAP 2014-01-10 14:06:53 -05:00
Ludovic Marcotte 13721b961b Add an easy way to get the personal contact folder, just like we have for calendars 2014-01-10 14:03:50 -05:00
Ludovic Marcotte 689a1e94e0 Sample Active Sync configuration 2014-01-10 14:02:32 -05:00
Ludovic Marcotte afcd92fb71 Load the ActiveSync bundle code and bind it 2014-01-10 14:01:39 -05:00
Ludovic Marcotte 7260c07628 More cleanups 2014-01-09 21:10:48 -05:00
Ludovic Marcotte a24d809e40 Minor code/copyright/authors cleanups 2014-01-09 21:06:31 -05:00
Ludovic Marcotte ed97407578 Dropped old data types 2014-01-09 20:42:16 -05:00
Ludovic Marcotte ca541d7299 Cleanups in conf file 2014-01-09 20:41:16 -05:00
Ludovic Marcotte 2d683ffc77 Always capitalize HTTP headers 2014-01-09 20:40:25 -05:00
Francis Lachapelle d603a8672e Consider 'background' attribute as unsafe
When loading a message, background attributes will be disabled if the
user as chosen to not automatically load external images.

Fixes #2437
2014-01-09 09:15:49 -05:00
Francis Lachapelle d51e1da57f Increase height of signature editor 2014-01-08 15:02:41 -05:00
Francis Lachapelle 80fd439dea Fix message forwarding as attachment
Restored the filename of the message source in the body part
content-disposition header.
Also forced the mail to be saved to the mailstore immediately in order
to have a clickable link to the attached message.
2014-01-08 14:40:39 -05:00
Francis Lachapelle a0d7f184fe Update French translation 2014-01-07 11:51:35 -05:00
Francis Lachapelle fe2826ca76 Draft: Improve error handling when attaching files 2014-01-07 11:11:39 -05:00
Francis Lachapelle ff9ea3b779 Don't alter the draft when saving it
We must not extract inline HTML images when simply saving a draft. The
images extraction process must only be performed when sending the
message.
2014-01-07 10:28:53 -05:00
Francis Lachapelle e70793e7ae Don't follow link of attachment not yet uploaded 2014-01-06 15:09:09 -05:00
Francis Lachapelle 0fdea48ce8 Restore CSS of disabled menu options 2014-01-06 15:08:45 -05:00
Francis Lachapelle 2b53705d44 Untabify 2014-01-06 14:32:58 -05:00
Francis Lachapelle b716331d8e Append tags when using a sanitizerContentHandler 2014-01-06 14:23:11 -05:00
Jean Raby 586d66b113 Updated description of SOGoUIAdditionalJSFiles
Document that the files must be placed under the  WebServerResources directory
2014-01-06 13:28:47 -05:00
Francis Lachapelle 5756defbf1 Mail editor: don't give focus to file input field. 2014-01-06 11:10:28 -05:00
Francis Lachapelle 7130cec4d1 Move & copy messages between different accounts 2014-01-03 16:57:37 -05:00
Francis Lachapelle 009cfccb2c Fix JS error when saving/sending plain text msg 2014-01-03 14:33:27 -05:00
Francis Lachapelle 09e14df79b Preferences: fix display of calendar categories 2014-01-03 14:32:48 -05:00
Francis Lachapelle ba29e7620d Update French translation 2014-01-03 14:32:01 -05:00
Francis Lachapelle 32516b162e Update textarea before saving/sending HTML message 2013-12-31 15:52:15 -05:00
Francis Lachapelle a8e780516b Fix display of "edit draft" and "load images"
The buttons were placed one over the other.
2013-12-23 15:54:22 -05:00
Francis Lachapelle bd7ad5be16 Fix initialization of arrays in NSString+Mail.m 2013-12-23 15:51:36 -05:00
Francis Lachapelle bed57af015 Improve display of linked attachments 2013-12-20 16:18:19 -05:00
Francis Lachapelle 5f369f201d Add links to download one or all attachments
Also removed the contextual menu over file attachments and changed the
label color when moving over the file attachments.
2013-12-20 15:41:18 -05:00
Francis Lachapelle dc21c723f6 Move method fetchFileAttachmentKeys from category
Moved fetchFileAttachmentKeys from SOGoDraftObjectExtensions to
SOGoDraftObject. Renamed fetchAttachmentIds to fetchFileAttachmentIds
for consistency.
2013-12-20 15:20:16 -05:00
Francis Lachapelle 1f7994d1bf Respect locale in time format of attendees window 2013-12-18 22:18:08 -05:00
Francis Lachapelle 7369a82bab Improve upload of attachments to messages 2013-12-18 22:18:08 -05:00
Francis Lachapelle 1a900b05d9 DraftObject: return more attachments attributes 2013-12-18 22:18:08 -05:00
Francis Lachapelle a8e3418a4c Use the UIxMailSizeFormatter in messages listing 2013-12-18 22:18:08 -05:00
Francis Lachapelle 59ce12a51b Load XMLHttpRequest conditionally (< IE9) 2013-12-18 22:18:08 -05:00
Ludovic Marcotte a1bec0e995 Merge branch 'master' of https://github.com/inverse-inc/sogo 2013-12-16 17:48:50 -05:00
Ludovic Marcotte 08ab36244c Improved the logic behind refusing too-many submitted mails. 2013-12-16 17:48:23 -05:00
Jean Raby 9ea880e80b fix backup path 2013-12-11 14:36:28 -05:00
Ludovic Marcotte 7d0a9aa1b7 Cleanups. 2013-12-10 20:09:32 -05:00
Jean Raby 2fa654fadb sogo.conf: fix typo and add AD/Samba4 example 2013-12-10 15:55:44 -05:00
Ludovic Marcotte 4a98e5b521 Don't append unknown objects to the REPORT result. 2013-12-09 10:31:34 -05:00
Francis Lachapelle e5103faed4 Update Finnish translation 2013-12-05 21:33:09 -05:00
Francis Lachapelle f9ad9ea815 Bump version to 2.1.2 2013-12-05 21:10:03 -05:00
Francis Lachapelle cfbd53e374 Fix initialization of preferences module
Don't try to initialize the tabs controller on the mail options tab if
the mail module is disabled.
2013-12-05 09:00:01 -05:00
Jean Raby f2beabec88 document organization and country ldap mapping 2013-12-04 19:50:22 -05:00
Jean Raby eaa0fb3cf1 Update NEWS CKEditor is in 2.1.1b 2013-12-04 11:11:10 -05:00
Jean Raby db56d1fa6c Bump version to 2.1.1b + adjust NEWS 2013-12-04 10:33:48 -05:00
Francis Lachapelle 37de8c6141 CKEditor: don't filter tags 2013-12-02 13:42:34 -05:00
Francis Lachapelle b0eb34f6b7 Add 'div' plugin to CKEditor 2013-12-02 11:58:28 -05:00
Francis Lachapelle 1cf696f57c Mail composition: add text part before html part
Fixes #2512
2013-11-25 09:52:18 -05:00
Francis Lachapelle 2114a48222 Update NEWS file 2013-11-22 15:03:57 -05:00
Francis Lachapelle 384d998c47 Cleanup wox templates 2013-11-22 14:42:16 -05:00
Francis Lachapelle 2211f6d168 Move mail tags strings to UI/Common 2013-11-22 14:39:24 -05:00
Ludovic Marcotte 32ba01315f Init local variable to avoid potential crasher. 2013-11-22 11:29:24 -05:00
Francis Lachapelle 682ed767d9 Fix the Sieve filters editor with new mail flags 2013-11-21 08:52:55 -05:00
Jean Raby 5536f8967e don't escape html in label names 2013-11-21 07:11:05 -05:00
Ludovic Marcotte df3e9033f3 Added calendar default reminder support. 2013-11-20 17:42:11 -05:00
Francis Lachapelle f167475c91 Update CKEditor to version 4.3.0 2013-11-20 11:17:42 -05:00
Ludovic Marcotte e4aedbac08 <img src=data...> conversion to file attachments + CIDs. 2013-11-20 08:56:29 -05:00
Jean Raby 2cf66e037d Merge to 2.1.1 2013-11-19 14:00:22 -05:00
Jean Raby 6587f4f193 Update ChangeLog 2013-11-19 13:59:20 -05:00
Francis Lachapelle c8a4ea5548 Update translations 2013-11-19 13:57:18 -05:00
Jean Raby 148fd4936c Update Version to 2.1.1 and update news 2013-11-19 13:43:45 -05:00
Jean Raby a7fef39448 Update to 2.1.1 2013-11-19 13:43:22 -05:00
Francis Lachapelle 5a3d0d27e0 Fix bug following mail tags management CSS changes 2013-11-19 13:39:48 -05:00
Ludovic Marcotte eb9111b5fa Updated news for the recent bug fix 2013-11-19 11:40:33 -05:00
Ludovic Marcotte eb7d1f08bc Fix for bug #2482 2013-11-19 11:39:45 -05:00
Ludovic Marcotte 854fed529c Added SOGoMailAuxiliaryUserAccountsEnabled 2013-11-19 09:52:53 -05:00
Jean Raby 3c29e0724d update news file 2013-11-15 16:12:15 -05:00
Jean Raby cebaed9059 Merge branch 'master' of https://github.com/inverse-inc/sogo 2013-11-15 16:09:52 -05:00
Jean Raby aae26602b0 Use raw (utf7) name when checking folder type 2013-11-15 16:04:09 -05:00
Jean Raby 05233d9c53 Use modified utf7 for special folder names 2013-11-15 16:02:59 -05:00
Francis Lachapelle e862194b32 Convert color picker to an inline widget
The colors are now limited to the colors offered in Thunderbird.
2013-11-15 15:50:46 -05:00
Jean Raby 884fbfdb73 Bump copyright and fix whitespace (tab kill) 2013-11-15 13:17:37 -05:00
Ludovic Marcotte c05cf00db7 Update standard tag colors to match TB and improve tags id generation. 2013-11-14 09:00:19 -05:00
Ludovic Marcotte 198db855f6 Specify color in which TB can grok it. 2013-11-13 15:55:25 -05:00
Ludovic Marcotte 1c439c866e Added DAV support for mails labels. 2013-11-13 15:44:57 -05:00
Francis Lachapelle 616ee7c6e4 GUI changes for mail labels management 2013-11-13 14:46:08 -05:00
Ludovic Marcotte 37d3234b60 Added support for dynamic mail labels/tags management.
The CSS in the UIxPreferences remains to be done.
2013-11-11 10:49:58 -05:00
Francis Lachapelle 449d838dc2 Merge to 2.1.0 2013-11-07 14:43:19 -05:00
Francis Lachapelle 6a9bcfda68 Update ChangeLog 2013-11-07 14:42:48 -05:00
Francis Lachapelle d0b09ebe35 Update translations 2013-11-07 14:14:39 -05:00
Francis Lachapelle 0361b7dfdb Documentation - bump version to 2.1.0 2013-11-07 11:09:41 -05:00
Francis Lachapelle 38b350382a Update NEWS file 2013-11-07 10:13:30 -05:00
Francis Lachapelle 73141a645e Update translations 2013-11-06 21:36:09 -05:00
Francis Lachapelle f07526423f Fix display of ICal event in message 2013-11-06 15:25:36 -05:00
Francis Lachapelle ba35a4b003 Update CKEditor to version 4.2.2 2013-11-06 11:29:15 -05:00
Ludovic Marcotte 47c4ad5807 Make sure the var is initilized to nil. 2013-10-29 20:58:26 -04:00
Ludovic Marcotte 0f3e31ebf1 Added more tags to skip 2013-10-23 16:37:03 -04:00
Ludovic Marcotte 87261f3280 Fix for bug #2468. 2013-10-23 16:04:37 -04:00
Ludovic Marcotte bd2759ecdf Fix for bug #2433 2013-10-22 11:44:26 -04:00
Ludovic Marcotte be1bcf3c9b Fix for bug #2461 2013-10-22 11:25:24 -04:00
Ludovic Marcotte 053b090aff Fix for bug #2235 2013-10-21 15:37:01 -04:00
Ludovic Marcotte 189f2218a8 Fix for bug #2459 2013-10-21 15:26:43 -04:00
Ludovic Marcotte 656869a4a2 Fix for bug #1328 2013-10-18 13:16:30 -04:00
Ludovic Marcotte 16f62e2393 Fix for bug #2434 2013-10-18 10:30:43 -04:00
Jean Raby 9289615996 Added https vhost example for apple carddav 2013-10-17 11:45:07 -04:00
Jean Raby fdea04c08c Added some verbose logging for expire-autoreply 2013-10-15 10:49:21 -04:00
Jean Raby edca3638ec Fixup backup_dir to use sogo's home directory 2013-10-11 13:41:44 -04:00
Ludovic Marcotte 05990e9a14 Fix for bug 2007 2013-09-30 10:50:27 -04:00
Jean Raby 3cce9b2012 Fix file permissions 2013-09-30 09:39:29 -04:00
Ludovic Marcotte 7dc65af300 Fix for bug #2386 2013-09-27 15:54:11 -04:00
Ludovic Marcotte 84e999229b Fix for bug #2270 2013-09-27 15:36:46 -04:00
Francis Lachapelle 3dbfb0ed2d Add Underline option to HTML editor 2013-09-27 14:43:05 -04:00
Francis Lachapelle d1f3417c3a Update CKEditor to version 4.2.1
And added the table-related modules.
2013-09-27 14:25:22 -04:00
Ludovic Marcotte 7c7031333e Fix for bug #2221 2013-09-27 10:00:39 -04:00
Jean Raby 1e48481426 Updated description/default value for WOPort 2013-09-26 08:51:42 -04:00
Jean Raby 8ae1624604 Added --noexpiry for administrator 2013-09-26 08:49:17 -04:00
Ludovic Marcotte 7166f5a597 Fix for bug #2399 2013-09-25 16:02:13 -04:00
Ludovic Marcotte 55052ea36f Fix for bug #2240 2013-09-25 14:40:48 -04:00
Ludovic Marcotte 99d38417cc Fix for bug #2354 2013-09-25 13:51:42 -04:00
Ludovic Marcotte 29eed182a7 Updated the OpenChange code related to UTF-7 changes for IMAP folders 2013-09-25 10:41:07 -04:00
Ludovic Marcotte 744610dbe1 Fixed tests regarding new WebDAV sync responses 2013-09-25 08:46:34 -04:00
Ludovic Marcotte d2b739d261 Fix for bug #2318 2013-09-24 16:01:23 -04:00
Ludovic Marcotte 2ba8254ecc Fix for bug #1275 2013-09-24 09:29:46 -04:00
Jean Raby 28e600a4e6 Set default listening address to 127.0.0.1:20000
No reason to listen on 0.0.0.0 by default
2013-09-20 15:37:34 -04:00
Ludovic Marcotte ab6e4841ba Merge branch 'master' of https://github.com/inverse-inc/sogo
Conflicts:
	NEWS
2013-09-19 16:14:41 -04:00
Ludovic Marcotte 91f1ab6a60 Fix for bug #2217 2013-09-19 16:14:08 -04:00
Jean Raby 32a534919d update NEWS. ldap fixes 2013-09-19 11:11:29 -04:00
Ludovic Marcotte 5b77c2b724 Stability fix when we're untable to determine the message class type 2013-09-19 10:49:42 -04:00
Ludovic Marcotte 70086e5ee6 Fix for bug #1935 2013-09-19 09:56:28 -04:00
Ludovic Marcotte 7ddc1b9e2d Avoid type-issues generating wrong GlobCnt - leading to OpenChange crashes during the sync process. 2013-09-18 14:03:07 -04:00
Francis Lachapelle 6d93db96e4 Update NEWS file 2013-09-17 11:17:40 -04:00
Jean Raby 27445d3b85 update news 2013-09-17 09:27:46 -04:00
Jean Raby 60d6abe542 Use HTTP/1.0 to avoid chunked replies
Fixes^WWorkaround #2408
2013-09-17 09:07:53 -04:00
Ludovic Marcotte baacf8516d Updated NEWS file regarding previous commit 2013-09-16 11:21:23 -04:00
Ludovic Marcotte 46a48faf23 Merge branch 'master' of https://github.com/inverse-inc/sogo 2013-09-16 11:00:40 -04:00
Ludovic Marcotte 193720cfbb Fix for s/mime verification issues with some openssl versions 2013-09-16 10:59:45 -04:00
Jean Raby f40580d632 Merge branch 'master' of https://github.com/inverse-inc/sogo 2013-09-13 11:25:08 -04:00
Jean Raby ca4d89fb08 update with latest fixes 2013-09-13 11:24:16 -04:00
Jean Raby 906985c1f3 Call MSExchangeHostname on SOGoDNSource only
Fixes #2418
2013-09-13 11:19:44 -04:00
Jean Raby de8bf64c70 Local pool when appending contacts to response
Avoids using too much memory when doing a contact lookup with many matches
2013-09-13 11:16:28 -04:00
Jean Raby 0c38a9e555 whitespace tabkill 2013-09-13 11:13:02 -04:00
Francis Lachapelle 3c6c90d434 Reload webmail when changing "remote images" pref 2013-09-13 09:33:28 -04:00
Francis Lachapelle 72a4b075d6 Mail popup: respect "remote inline images" prefs
Fixes #2417
2013-09-12 17:08:02 -04:00
Francis Lachapelle 24c0fb1cc4 Fix change listener on calendar list select input
Fixes #2353
2013-09-12 16:33:44 -04:00
Jean Raby 7241e3e30e Added rewrite rule for apple autoconfiguration url
Rewrite rules are no inherited by virtualhosts when they are declared in conf.d
This means that you'll have to explicitly include SOGo.conf from 000-default
on debian/ubuntu for this redirection to work properly.
2013-09-12 10:14:47 -04:00
Jean Raby 1d705dc00b Next version: 2.1.0 2013-09-10 13:58:04 -04:00
Jean Raby df42ab2a46 Run 3 sogod process by default instead on only 1 2013-09-09 10:07:07 -04:00
Ludovic Marcotte 53f9d0d7f5 Merge branch 'master' of https://github.com/inverse-inc/sogo 2013-09-06 13:49:25 -04:00
Jean Raby f59c77a950 Update news 2013-09-06 13:49:04 -04:00
Ludovic Marcotte cd4abe4b5b Fix for bug 2398 2013-09-06 13:48:44 -04:00
Francis Lachapelle 69b0f9fcbf Mail notifications: Escape HTML in wox templates
We don't escape the values in the classes but in the templates.
2013-09-03 12:05:13 -04:00
Jean Raby dceead3997 Fixup sogo spool cleanup cronjob
Add -user sogo to be on the safe side.
Change call to /bin/rmdir by -delete to avoid error messages.
Find would call rmdir and then do an openat() on the deleted directory,
which would obviously fail.

Fixes #2372
2013-09-03 09:59:01 -04:00
Jean Raby 573c2ec114 updated News 2013-08-29 15:51:05 -04:00
Jean Raby 6a68c255bd Merge branch 'fix/ldap-password-change' 2013-08-29 15:15:07 -04:00
Jean Raby e9d8b729b6 Bump version file to 2.0.8 for nightly builds 2013-08-29 14:34:25 -04:00
Jean Raby 1e7dfc0934 Updated cron sections for credentials files
Added a note regarding password change against AD/Samba4
2013-08-29 14:32:34 -04:00
Jean Raby d7e6648396 Reworked password change logic and add AD support 2013-08-28 17:11:07 -04:00
Jean Raby 65603201f7 ignore pyc files and config.py 2013-08-28 10:05:36 -04:00
Jean Raby 9fd6f75c4e Update crontab for SMTP AUTH credentials 2013-08-28 09:47:10 -04:00
Jean Raby b96f25f99f updated NEWS 2013-08-27 14:44:28 -04:00
Jean Raby d7851999da Merge branch 'fix/email-notif-auth' 2013-08-27 14:37:52 -04:00
Jean Raby e6ab0a590a Support using SMTP AUTH creds for email alarms
Credentials must be supplied using '-p /path/to/credsFile'.
The credentials file should contain a single line with the format 'user:pass'

While there, add a usage message
2013-08-27 13:12:03 -04:00
Jean Raby be531100c6 Use SOGoCredentialsFile to avoid duplicated code 2013-08-27 13:04:08 -04:00
Jean Raby e946a67ddf Special case for auth with SOGoStaticAuthenticator 2013-08-27 13:02:06 -04:00
Jean Raby 2fe87f14fd Add SOGoStaticAuthenticator
New authenticator that is not linked to a SOGoUser.
Will be used for SMTP AUTH by sogo-elalarm-notify.
2013-08-27 12:59:03 -04:00
Jean Raby b2f012cae2 Add SOGoCredentialsFile
New class to read credentials files as used by sogo-tool and sogo-ealarm-notify
2013-08-27 12:56:07 -04:00
Francis Lachapelle 33659aa947 Increase height of alarm editor
Only when email alarms are enabled.
2013-08-27 12:01:41 -04:00
Francis Lachapelle df1ab29872 Fix position of red "now" line
Fixes #2373
2013-08-27 09:06:48 -04:00
Jean Raby 61e59b864e Bump copyright 2013-08-27 08:33:50 -04:00
Francis Lachapelle 0a590ba388 Fix Finnish mail reply/forward templates 2013-08-26 08:59:43 -04:00
Ludovic Marcotte ab92516dd0 Fix for bug #1431 2013-08-09 11:39:15 -04:00
Ludovic Marcotte 7b90b892fc Fix for bug #2385 2013-08-07 08:49:59 -04:00
Jean Raby b654ffb806 add webdavsync-tool.py
first draft of a small tool to simulate a TB calendar sync
2013-08-02 16:56:36 -04:00
Jean Raby 6de689bbe2 Add depth support to CalendarMultiget 2013-08-02 15:41:24 -04:00
Jean Raby 7eb8b9c2c3 Add SxVMemLimit to sogo.conf 2013-08-02 09:51:41 -04:00
Jean Raby 3877f3001f replace xml.dom.ext by xml.dom.minidom 2013-08-01 12:48:42 -04:00
Ludovic Marcotte 4d2c734781 Revert "Try to use a local pool to avoid huge memory consumption"
This reverts commit e57d875e0a.
2013-07-29 14:32:58 -04:00
Ludovic Marcotte e57d875e0a Try to use a local pool to avoid huge memory consumption 2013-07-29 09:43:21 -04:00
Ludovic Marcotte b1df03adc7 Fix for old runtimes. 2013-07-24 10:54:55 -04:00
Francis Lachapelle c4bc215a47 Merge to 2.0.7 2013-07-23 10:02:39 -04:00
Francis Lachapelle bd776152db Update ChangeLog 2013-07-23 10:02:13 -04:00
Ludovic Marcotte c6374b52ec Merge branch 'master' of https://github.com/inverse-inc/sogo 2013-07-23 09:26:55 -04:00
Ludovic Marcotte 734c164ae0 Reverted broken patch in #2360 and tried to fix it cleanly 2013-07-23 09:25:24 -04:00
Francis Lachapelle c9936d7ecf Merge to 2.0.7 2013-07-23 08:38:44 -04:00
Francis Lachapelle 9f381e768d Update ChangeLog 2013-07-23 08:38:09 -04:00
Ludovic Marcotte b531b6160c Fixed compilation ordering to avoid bug in gnustep-make 2013-07-23 08:31:38 -04:00
Francis Lachapelle 885e59a2af Merge to 2.0.7 2013-07-19 13:46:37 -04:00
Francis Lachapelle 8a041860a0 Update ChangeLog 2013-07-19 13:40:33 -04:00
Francis Lachapelle d5f76ac832 Improve CSS print media 2013-07-19 13:39:18 -04:00
Francis Lachapelle 12b7fea825 Documentation - bump version to 2.0.7 2013-07-19 13:37:13 -04:00
Francis Lachapelle 1c82af8842 Updated pt_BR, cs, nl, de, pl and ru translations 2013-07-19 11:29:10 -04:00
Francis Lachapelle 6cef5245e1 Bump version to 2.0.7 2013-07-19 11:27:17 -04:00
Francis Lachapelle 0069a4200b Handle possible jQuery error with DnD of contacts 2013-07-19 10:51:41 -04:00
Ludovic Marcotte e24c20c48a Reverted patch 2013-07-19 10:11:08 -04:00
Ludovic Marcotte 256b679798 Bug fix for #2366 2013-07-18 11:46:49 -04:00
Francis Lachapelle b85ed0db1c Fix blur of active element on click on a draggable
This bug has yet to be officially part of jQuery UI, therefore this
commit updates jquery-ui to version 1.10.3 patched with commit fcd1caf:

https://github.com/jquery/jquery-ui/commit/fcd1cafac8afe3a947676ec018e844eeada5b9de
2013-07-18 11:32:29 -04:00
Ludovic Marcotte 048bae2fc5 Applied patch from bug #2235 2013-07-18 10:52:37 -04:00
Ludovic Marcotte 19e542396b Applied patch from bug #2360 2013-07-18 10:25:39 -04:00
Francis Lachapelle 249a1fcf14 Bubble box of event should not overlap event cell 2013-07-17 14:57:07 -04:00
Ludovic Marcotte 7dad5ad84e Updated for v2.0.7 2013-07-16 15:20:26 -04:00
Ludovic Marcotte 16105d37b8 Properly handle RFC2231 everywhere 2013-07-16 15:18:04 -04:00
Ludovic Marcotte e08ebd2390 Fix for bugs #2368 and #2369 2013-07-16 11:31:08 -04:00
Francis Lachapelle 03553980fd Update NEWS file and add missing image 2013-07-11 13:55:03 -04:00
Francis Lachapelle 33fd60efb3 Calendar: print gridlines to 15-minute intervals 2013-07-11 13:50:44 -04:00
Francis Lachapelle b8e2255a07 Set the events/tasks list collapsable 2013-07-11 13:46:38 -04:00
Ludovic Marcotte e687dbf155 If the organizer's name is non-existent, use the email address 2013-07-04 13:11:02 -04:00
677 changed files with 34079 additions and 9402 deletions

No files matched your search

+5
View File
@@ -1,6 +1,8 @@
config.make
tags
*._*
*/obj/
*._*
*/*/obj/
*/*/*/obj/
*/*/*.SOGo/
@@ -9,3 +11,6 @@ tags
*.swp
SoObjects/SOGo/SOGo.framework/
SoObjects/SOGo/derived_src/
Tests/*/config.py
*.pyc
._*
+27 -1
View File
@@ -1,5 +1,5 @@
[main]
host = https://www.transifex.net
host = https://www.transifex.com
[sogo.ui-mailerui]
source_file = UI/MailerUI/English.lproj/Localizable.strings
@@ -235,6 +235,32 @@ trans.sk = SoObjects/Contacts/Slovak.lproj/Localizable.strings
trans.sv = SoObjects/Contacts/Swedish.lproj/Localizable.strings
trans.uk = SoObjects/Contacts/Ukrainian.lproj/Localizable.strings
[sogo.soobjects-mailer]
source_file = SoObjects/Mailer/English.lproj/Localizable.strings
source_lang = en
trans.ar = SoObjects/Mailer/Arabic.lproj/Localizable.strings
trans.ca = SoObjects/Mailer/Catalan.lproj/Localizable.strings
trans.cs = SoObjects/Mailer/Czech.lproj/Localizable.strings
trans.cy = SoObjects/Mailer/Welsh.lproj/Localizable.strings
trans.da_DK = SoObjects/Mailer/Danish.lproj/Localizable.strings
trans.de = SoObjects/Mailer/German.lproj/Localizable.strings
trans.es_AR = SoObjects/Mailer/SpanishArgentina.lproj/Localizable.strings
trans.es_ES = SoObjects/Mailer/SpanishSpain.lproj/Localizable.strings
trans.fi = SoObjects/Mailer/Finnish.lproj/Localizable.strings
trans.fr = SoObjects/Mailer/French.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.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_BR = SoObjects/Mailer/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = SoObjects/Mailer/Russian.lproj/Localizable.strings
trans.sk = SoObjects/Mailer/Slovak.lproj/Localizable.strings
trans.sv = SoObjects/Mailer/Swedish.lproj/Localizable.strings
trans.uk = SoObjects/Mailer/Ukrainian.lproj/Localizable.strings
[sogo.ui-mailpartviewers]
source_file = UI/MailPartViewers/English.lproj/Localizable.strings
source_lang = en
+40
View File
@@ -0,0 +1,40 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <Foundation/NSObject.h>
@interface ActiveSyncProduct : NSObject
{
}
@end
@implementation ActiveSyncProduct
@end /* ActiveSyncProduct */
+42
View File
@@ -0,0 +1,42 @@
# GNUstep makefile
include common.make
BUNDLE_NAME = ActiveSync
ActiveSync_PRINCIPAL_CLASS = ActiveSyncProduct
ActiveSync_OBJC_FILES = \
ActiveSyncProduct.m \
iCalAlarm+ActiveSync.m \
iCalEvent+ActiveSync.m \
iCalRecurrenceRule+ActiveSync.m \
iCalTimeZone+ActiveSync.m \
iCalToDo+ActiveSync.m \
NSCalendarDate+ActiveSync.m \
NSData+ActiveSync.m \
NSDate+ActiveSync.m \
NGDOMElement+ActiveSync.m \
NGMimeMessage+ActiveSync.m \
NGVCard+ActiveSync.m \
NSArray+SyncCache.m \
NSString+ActiveSync.m \
SOGoActiveSyncDispatcher.m \
SOGoActiveSyncDispatcher+Sync.m \
SOGoMailObject+ActiveSync.m \
SOGoSyncCacheObject.m \
SoObjectWebDAVDispatcher+ActiveSync.m
ActiveSync_RESOURCE_FILES += \
product.plist
ADDITIONAL_OBJCFLAGS += -Wno-deprecated-declarations
ADDITIONAL_INCLUDE_DIRS += -I../SOPE/ -I../SoObjects/
ADDITIONAL_LIB_DIRS += -L../SOPE/GDLContentStore/obj/ -L../SOPE/NGCards/obj/
ADDITIONAL_INCLUDE_DIRS += -I/usr/include/libwbxml-1.0/
ADDITIONAL_LDFLAGS += -Wl,--no-as-needed -lwbxml2
-include GNUmakefile.preamble
include $(GNUSTEP_MAKEFILES)/bundle.make
-include GNUmakefile.postamble
+1
View File
@@ -0,0 +1 @@
# compilation settings
+25
View File
@@ -0,0 +1,25 @@
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+44
View File
@@ -0,0 +1,44 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __NGDOMELEMENTACTIVESYNC_H__
#define __NGDOMELEMENTACTIVESYNC_H__
#import <DOM/DOMElement.h>
#import <DOM/DOMProtocols.h>
@class NSDictionary;
@interface NGDOMElement (ActiveSync)
- (NSDictionary *) applicationData;
@end
#endif // NGDOMELEMENTACTIVESYNC
+190
View File
@@ -0,0 +1,190 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "NGDOMElement+ActiveSync.h"
#import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
static NSArray *asElementArray = nil;
@implementation NGDOMElement (ActiveSync)
- (BOOL) isTextNode
{
id <DOMNodeList> children;
id <DOMElement> element;
int i;
if ([self nodeType] == DOM_TEXT_NODE)
return YES;
children = [self childNodes];
for (i = 0; i < [children length]; i++)
{
element = [children objectAtIndex: i];
if ([element nodeType] != DOM_TEXT_NODE)
return NO;
}
return YES;
}
//
// We must handle "inner data" like this:
//
// <ApplicationData>
// <Flag xmlns="Email:">
// <FlagStatus>2</FlagStatus>
// <FlagType>Flag for follow up</FlagType>
// </Flag>
// </ApplicationData>
//
// and stuff like that:
//
// <Attendees xmlns="Calendar:">
// <Attendee>
// <Attendee_Email>sogo1@example.com</Attendee_Email>
// <Attendee_Name>John Doe</Attendee_Name>
// <Attendee_Status>5</Attendee_Status>
// <Attendee_Type>1</Attendee_Type>
// </Attendee>
// <Attendee>
// <Attendee_Email>sogo2@example.com</Attendee_Email>
// <Attendee_Name>Balthazar César</Attendee_Name>
// <Attendee_Status>5</Attendee_Status>
// <Attendee_Type>1</Attendee_Type>
// </Attendee>
// <Attendee>
// <Attendee_Email>sogo3@example.com</Attendee_Email>
// <Attendee_Name>Wolfgang Fritz</Attendee_Name>
// <Attendee_Status>5</Attendee_Status>
// <Attendee_Type>1</Attendee_Type>
// </Attendee>
// </Attendees>
//
- (NSDictionary *) applicationData
{
NSMutableDictionary *data;
id <DOMNodeList> children;
id <DOMElement> element;
int i, count;
if (!asElementArray)
asElementArray = [[NSArray alloc] initWithObjects: @"Attendee", @"Category", nil];
data = [NSMutableDictionary dictionary];
children = [self childNodes];
for (i = 0; i < [children length]; i++)
{
element = [children objectAtIndex: i];
if ([element nodeType] == DOM_ELEMENT_NODE)
{
NSString *tag;
id value;
tag = [element tagName];
count = [(NSArray *)[element childNodes] count];
// We check if the node is a text one or if all its
// children are text nodes. This is important to avoid side-effects
// in SOPE where "foo & bar" would result into 3 childnodes instead
// of just one.
if ([(id)element isTextNode])
{
value = [(id)element textValue];
}
// Handle inner data - see above for samples
else
{
NSMutableArray *innerElements;
id <DOMElement> innerElement;
NSArray *childNodes;
NSString *innerTag;
BOOL same;
int j;
childNodes = (NSArray *)[element childNodes];
innerElements = [NSMutableArray array];
innerTag = nil;
same = YES;
for (j = 1; j < count; j++)
{
innerElement = [childNodes objectAtIndex: j];
if ([innerElement nodeType] == DOM_ELEMENT_NODE)
{
if (!innerTag)
innerTag = [innerElement tagName];
if ([innerTag isEqualToString: [innerElement tagName]])
{
if ([(id)innerElement isTextNode])
[innerElements addObject: [(NGDOMElement *)innerElement textValue]];
else
[innerElements addObject: [(NGDOMElement *)innerElement applicationData]];
}
else
{
same = NO;
break;
}
}
}
if (same && [asElementArray containsObject: innerTag])
value = innerElements;
else
{
value = [(NGDOMElement *)element applicationData];
// Don't set empty values like Foo = {}
if (![value count])
value = nil;
}
}
if (value && tag)
[data setObject: value forKey: tag];
} // if ([element nodeType] == DOM_ELEMENT_NODE)
}
return data;
}
@end
+43
View File
@@ -0,0 +1,43 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __NGMIMEMESSAGEACTIVESYNC_H__
#define __NGMIMEMESSAGEACTIVESYNC_H__
#import <NGMail/NGMimeMessage.h>
@class NSArray;
@interface NGMimeMessage (ActiveSync)
- (NSArray *) allRecipients;
@end
#endif
+62
View File
@@ -0,0 +1,62 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
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 <SOGo/NSString+Utilities.h>
@implementation NGMimeMessage (ActiveSync)
- (NSArray *) allRecipients
{
NSMutableArray *recipients;
NSEnumerator *enumerator;
NSString *s;
recipients = [NSMutableArray array];
enumerator = [[self headersForKey: @"to"] objectEnumerator];
while ((s = [enumerator nextObject]))
{
[recipients addObject: [s pureEMailAddress]];
}
enumerator = [[self headersForKey: @"cc"] objectEnumerator];
while ((s = [enumerator nextObject]))
{
[recipients addObject: [s pureEMailAddress]];
}
return recipients;
}
@end
+47
View File
@@ -0,0 +1,47 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __NGVCARDACTIVESYNC_H__
#define __NGVCARDACTIVESYNC_H__
#import <NGCards/NGVCard.h>
@class NSDictionary;
@class NSString;
@class WOContext;
@interface NGVCard (ActiveSync)
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context;
@end
#endif
+351
View File
@@ -0,0 +1,351 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
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 <NGExtensions/NSString+misc.h>
#import <NGCards/CardElement.h>
#import <Contacts/NGVCard+SOGo.h>
#include "NSDate+ActiveSync.h"
#include "NSString+ActiveSync.h"
@implementation NGVCard (ActiveSync)
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
{
NSArray *emails, *addresses, *categories, *elements;
CardElement *n, *homeAdr, *workAdr;
NSMutableString *s;
NSString *url;
id o;
int i;
s = [NSMutableString string];
n = [self n];
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]];
if ((o = [self workCompany]))
[s appendFormat: @"<CompanyName xmlns=\"Contacts:\">%@</CompanyName>", [o activeSyncRepresentationInContext: context]];
if ((o = [[self org] flattenedValueAtIndex: 1 forKey: @""]))
[s appendFormat: @"<Department xmlns=\"Contacts:\">%@</Department>", [o activeSyncRepresentationInContext: context]];
categories = [self categories];
if ([categories count])
{
[s appendFormat: @"<Categories xmlns=\"Contacts:\">"];
for (i = 0; i < [categories count]; i++)
{
[s appendFormat: @"<Category xmlns=\"Contacts:\">%@</Category>", [[categories objectAtIndex: i] activeSyncRepresentationInContext: context]];
}
[s appendFormat: @"</Categories>"];
}
elements = [self childrenWithTag: @"url"
andAttribute: @"type"
havingValue: @"work"];
if ([elements count] > 0)
{
url = [[elements objectAtIndex: 0] flattenedValuesForKey: @""];
[s appendFormat: @"<WebPage xmlns=\"Contacts:\">%@</WebPage>", [url activeSyncRepresentationInContext: context]];
}
if ((o = [[self uniqueChildWithTag: @"x-aim"] flattenedValuesForKey: @""]))
[s appendFormat: @"<IMAddress xmlns=\"Contacts:\">%@</IMAddress>", [o activeSyncRepresentationInContext: context]];
if ((o = [self nickname]))
[s appendFormat: @"<NickName xmlns=\"Contacts:\">%@</NickName>", [o activeSyncRepresentationInContext: context]];
if ((o = [self title]))
[s appendFormat: @"<JobTitle xmlns=\"Contacts:\">%@</JobTitle>", [o activeSyncRepresentationInContext: context]];
if ((o = [self preferredEMail]))
[s appendFormat: @"<Email1Address xmlns=\"Contacts:\">%@</Email1Address>", o];
// Secondary email addresses (2 and 3)
emails = [self secondaryEmails];
for (i = 0; i < [emails count]; i++)
{
o = [[emails objectAtIndex: i] flattenedValuesForKey: @""];
[s appendFormat: @"<Email%dAddress xmlns=\"Contacts:\">%@</Email%dAddress>", i+2, o, i+2];
if (i == 1)
break;
}
// Telephone numbers
if ((o = [self workPhone]) && [o length])
[s appendFormat: @"<BusinessPhoneNumber xmlns=\"Contacts:\">%@</BusinessPhoneNumber>", [o activeSyncRepresentationInContext: context]];
if ((o = [self homePhone]) && [o length])
[s appendFormat: @"<HomePhoneNumber xmlns=\"Contacts:\">%@</HomePhoneNumber>", [o activeSyncRepresentationInContext: context]];
if ((o = [self fax]) && [o length])
[s appendFormat: @"<BusinessFaxNumber xmlns=\"Contacts:\">%@</BusinessFaxNumber>", [o activeSyncRepresentationInContext: context]];
if ((o = [self mobile]) && [o length])
[s appendFormat: @"<MobilePhoneNumber xmlns=\"Contacts:\">%@</MobilePhoneNumber>", [o activeSyncRepresentationInContext: context]];
if ((o = [self pager]) && [o length])
[s appendFormat: @"<PagerNumber xmlns=\"Contacts:\">%@</PagerNumber>", [o activeSyncRepresentationInContext: context]];
// Home Address
addresses = [self childrenWithTag: @"adr"
andAttribute: @"type"
havingValue: @"home"];
if ([addresses count])
{
homeAdr = [addresses objectAtIndex: 0];
if ((o = [homeAdr flattenedValueAtIndex: 2 forKey: @""]))
[s appendFormat: @"<HomeStreet xmlns=\"Contacts:\">%@</HomeStreet>", [o 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]];
if ((o = [homeAdr flattenedValueAtIndex: 6 forKey: @""]))
[s appendFormat: @"<HomeCountry xmlns=\"Contacts:\">%@</HomeCountry>", [o activeSyncRepresentationInContext: context]];
}
// Work Address
addresses = [self childrenWithTag: @"adr"
andAttribute: @"type"
havingValue: @"work"];
if ([addresses count])
{
workAdr = [addresses objectAtIndex: 0];
if ((o = [workAdr flattenedValueAtIndex: 2 forKey: @""]))
[s appendFormat: @"<BusinessStreet xmlns=\"Contacts:\">%@</BusinessStreet>", [o activeSyncRepresentationInContext: context]];
if ((o = [workAdr flattenedValueAtIndex: 3 forKey: @""]))
[s appendFormat: @"<BusinessCity xmlns=\"Contacts:\">%@</BusinessCity>", [o activeSyncRepresentationInContext: context]];
if ((o = [workAdr flattenedValueAtIndex: 4 forKey: @""]))
[s appendFormat: @"<BusinessState xmlns=\"Contacts:\">%@</BusinessState>", [o activeSyncRepresentationInContext: context]];
if ((o = [workAdr flattenedValueAtIndex: 5 forKey: @""]))
[s appendFormat: @"<BusinessPostalCode xmlns=\"Contacts:\">%@</BusinessPostalCode>", [o activeSyncRepresentationInContext: context]];
if ((o = [workAdr flattenedValueAtIndex: 6 forKey: @""]))
[s appendFormat: @"<BusinessCountry xmlns=\"Contacts:\">%@</BusinessCountry>", [o activeSyncRepresentationInContext: context]];
}
// Other, less important fields
if ((o = [self birthday]))
[s appendFormat: @"<Birthday xmlns=\"Contacts:\">%@</Birthday>", [o activeSyncRepresentationInContext: context]];
if ((o = [self note]))
{
o = [o activeSyncRepresentationInContext: context];
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];
[s appendFormat: @"<Truncated>%d</Truncated>", 0];
[s appendFormat: @"<Data>%@</Data>", o];
[s appendString: @"</Body>"];
}
return s;
}
//
//
//
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context
{
CardElement *element;
id o;
// Contact's note
if ((o = [[theValues objectForKey: @"Body"] objectForKey: @"Data"]))
[self setNote: o];
// Categories
if ((o = [theValues objectForKey: @"Categories"]))
[self setCategories: o];
// Birthday
if ((o = [theValues objectForKey: @"Birthday"]))
{
o = [o calendarDate];
[self setBday: [o descriptionWithCalendarFormat: @"%Y-%m-%d"]];
}
//
// Business address information
//
// BusinessStreet
// BusinessCity
// BusinessPostalCode
// BusinessState
// BusinessCountry
//
element = [self elementWithTag: @"adr" ofType: @"work"];
[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
//
// HomeStreet
// HomeCity
// HomePostalCode
// HomeState
// HomeCountry
//
element = [self elementWithTag: @"adr" ofType: @"home"];
[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];
// Department
if ((o = [theValues objectForKey: @"Department"]))
[self setOrg: nil units: [NSArray arrayWithObjects:o,nil]];
// Email addresses
if ((o = [theValues objectForKey: @"Email1Address"]))
{
element = [self elementWithTag: @"email" ofType: @"work"];
[element setSingleValue: o forKey: @""];
}
if ((o = [theValues objectForKey: @"Email2Address"]))
{
element = [self elementWithTag: @"email" ofType: @"home"];
[element setSingleValue: o forKey: @""];
}
// 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"]))
{
element = [self elementWithTag: @"email" ofType: @"three"];
[element setSingleValue: o forKey: @""];
}
// Formatted name
// MiddleName
// Suffix (II)
// Title (Mr.)
[self setFn: [theValues objectForKey: @"FileAs"]];
[self setNWithFamily: [theValues objectForKey: @"LastName"]
given: [theValues objectForKey: @"FirstName"]
additional: nil prefixes: nil suffixes: nil];
// IM information
[[self uniqueChildWithTag: @"x-aim"]
setSingleValue: [theValues objectForKey: @"IMAddress"]
forKey: @""];
//
// Phone numbrrs
//
element = [self elementWithTag: @"tel" ofType: @"work"];
[element setSingleValue: [theValues objectForKey: @"BusinessPhoneNumber"] forKey: @""];
element = [self elementWithTag: @"tel" ofType: @"home"];
[element setSingleValue: [theValues objectForKey: @"HomePhoneNumber"] forKey: @""];
element = [self elementWithTag: @"tel" ofType: @"cell"];
[element setSingleValue: [theValues objectForKey: @"MobilePhoneNumber"] forKey: @""];
element = [self elementWithTag: @"tel" ofType: @"fax"];
[element setSingleValue: [theValues objectForKey: @"BusinessFaxNumber"] forKey: @""];
element = [self elementWithTag: @"tel" ofType: @"pager"];
[element setSingleValue: [theValues objectForKey: @"PagerNumber"] forKey: @""];
// Job's title
if ((o = [theValues objectForKey: @"JobTitle"]))
[self setTitle: o];
// WebPage (work)
if ((o = [theValues objectForKey: @"WebPage"]))
[[self elementWithTag: @"url" ofType: @"work"]
setSingleValue: o forKey: @""];
if ((o = [theValues objectForKey: @"NickName"]))
[self setNickname: o];
}
@end
+49
View File
@@ -0,0 +1,49 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __NSARRAYSYNCCACHE_H__
#define __NSARRAYSYNCCACHE_H__
#import <Foundation/NSArray.h>
@class NSDictionary;
@interface NSMutableArray (SyncCache)
- (id) initWithDictionary: (NSDictionary *) theDictionary;
@end
@interface NSArray (SyncCache)
- (NSDictionary *) dictionaryValue;
@end
#endif
+84
View File
@@ -0,0 +1,84 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "NSArray+SyncCache.h"
#import <Foundation/NSDictionary.h>
#include "SOGoSyncCacheObject.h"
@implementation NSMutableArray (SyncCache)
- (id) initWithDictionary: (NSDictionary *) theDictionary
{
SOGoSyncCacheObject *o;
NSArray *allKeys;
id key;
int i;
self = [self initWithCapacity: [theDictionary count]];
allKeys = [theDictionary allKeys];
for (i = 0; i < [allKeys count]; i++)
{
key = [allKeys objectAtIndex: i];
o = [SOGoSyncCacheObject syncCacheObjectWithUID: key
sequence: [theDictionary objectForKey: key]];
[self addObject: o];
}
return self;
}
@end
//
//
//
@implementation NSArray (SyncCache)
- (NSDictionary *) dictionaryValue
{
NSMutableDictionary *d;
SOGoSyncCacheObject *o;
int i;
d = [NSMutableDictionary dictionary];
for (i = 0; i < [self count]; i++)
{
o = [self objectAtIndex: i];
[d setObject: [o sequence] forKey: [o uid]];
}
return d;
}
@end
+43
View File
@@ -0,0 +1,43 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __NSCALENDARDATEACTIVESYNC_H__
#define __NSCALENDARDATEACTIVESYNC_H__
#import <Foundation/NSCalendarDate.h>
@class NSString;
@interface NSCalendarDate (ActiveSync)
+ (NSCalendarDate *) dateFromFilterType: (NSString *) theFilterType;
@end
#endif
+87
View File
@@ -0,0 +1,87 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
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
@implementation NSCalendarDate (ActiveSync)
//
// See http://msdn.microsoft.com/en-us/library/gg709713(v=exchg.80).aspx for available types
//
+ (NSCalendarDate *) dateFromFilterType: (NSString *) theFilterType
{
NSCalendarDate *d;
d = [NSCalendarDate calendarDate];
if (d)
{
int value;
switch ([theFilterType intValue])
{
case 1:
value = ONE_DAY;
break;
case 2:
value = 3 * ONE_DAY;
break;
case 3:
value = 7 * ONE_DAY;
break;
case 4:
value = 14 * ONE_DAY;
break;
case 5:
value = 30 * ONE_DAY;
break;
case 6:
value = 90 * ONE_DAY;
break;
case 7:
value = 180 * ONE_DAY;
break;
case 0:
case 8:
default:
return nil;
}
return [d initWithTimeIntervalSinceNow: -value];
}
return d;
}
@end
+46
View File
@@ -0,0 +1,46 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __NSDATAACTIVESYNC_H__
#define __NSDATAACTIVESYNC_H__
#import <Foundation/NSData.h>
@class NSString;
@class WOContext;
@interface NSData (ActiveSync)
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
- (NSData *) wbxml2xml;
- (NSData *) xml2wbxml;
@end
#endif
+152
View File
@@ -0,0 +1,152 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "NSData+ActiveSync.h"
#import <Foundation/NSProcessInfo.h>
#import <Foundation/NSString.h>
#import <NGExtensions/NGBase64Coding.h>
#include <wbxml/wbxml.h>
#include <wbxml/wbxml_conv.h>
#include <wbxml/wbxml_errors.h>
#define WBXMLDEBUG 0
@implementation NSData (ActiveSync)
- (void) _dumpToFile
{
NSString *path;
path = [NSString stringWithFormat: @"/tmp/%@.data", [[NSProcessInfo processInfo] globallyUniqueString]];
[self writeToFile: path atomically: YES];
NSLog(@"Original data written to: %@", path);
}
//
// Encodes the data in base64 and strip newline characters
//
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
{
return [[self stringByEncodingBase64] stringByReplacingString: @"\n" withString: @""];
}
- (NSData *) wbxml2xml
{
WBXMLGenXMLParams params;
NSData *data;
unsigned int wbxml_len, xml_len, ret;
unsigned char *wbxml, *xml;
wbxml = (unsigned char*)[self bytes];
wbxml_len = [self length];
xml = NULL;
xml_len = 0;
params.lang = WBXML_LANG_ACTIVESYNC;
params.gen_type = WBXML_GEN_XML_INDENT;
params.indent = 1;
params.keep_ignorable_ws = FALSE;
ret = wbxml_conv_wbxml2xml_withlen(wbxml, wbxml_len, &xml, &xml_len, &params);
if (ret != WBXML_OK)
{
NSLog(@"wbxml2xmlFromContent: failed: %s\n", wbxml_errors_string(ret));
[self _dumpToFile];
return nil;
}
data = [[NSData alloc] initWithBytes: xml length: xml_len];
#if WBXMLDEBUG
[data writeToFile: @"/tmp/protocol.decoded" atomically: YES];
#endif
free(xml);
return AUTORELEASE(data);
}
- (NSData *) xml2wbxml
{
WBXMLConvXML2WBXML *conv;
NSData *data;
unsigned int wbxml_len, xml_len, ret;
unsigned char *wbxml, *xml;
xml = (unsigned char*)[self bytes];
xml_len = [self length];
wbxml = NULL;
wbxml_len = 0;
conv = NULL;
ret = wbxml_conv_xml2wbxml_create(&conv);
if (ret != WBXML_OK)
{
NSLog(@"xml2wbxmlFromContent: failed: %s\n", wbxml_errors_string(ret));
[self _dumpToFile];
return nil;
}
wbxml_conv_xml2wbxml_enable_preserve_whitespaces(conv);
// From libwbxml's changelog in v0.11.0: "The public ID is set to unknown and the DTD is not included. This is required for Microsoft ActiveSync."
wbxml_conv_xml2wbxml_disable_public_id(conv);
wbxml_conv_xml2wbxml_disable_string_table(conv);
ret = wbxml_conv_xml2wbxml_run(conv, xml, xml_len, &wbxml, &wbxml_len);
if (ret != WBXML_OK)
{
NSLog(@"xml2wbxmlFromContent: failed: %s\n", wbxml_errors_string(ret));
[self _dumpToFile];
free(wbxml);
wbxml_conv_xml2wbxml_destroy(conv);
return nil;
}
data = [[NSData alloc] initWithBytes: wbxml length: wbxml_len];
#if WBXMLDEBUG
[data writeToFile: @"/tmp/protocol.encoded" atomically: YES];
#endif
free(wbxml);
wbxml_conv_xml2wbxml_destroy(conv);
return AUTORELEASE(data);
}
@end
+45
View File
@@ -0,0 +1,45 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __NSDATEACTIVESYNC_H__
#define __NSDATEACTIVESYNC_H__
#import <Foundation/NSDate.h>
@class NSString;
@class WOContext;
@interface NSDate (ActiveSync)
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
- (NSString *) activeSyncRepresentationWithoutSeparatorsInContext: (WOContext *) context;
@end
#endif
+52
View File
@@ -0,0 +1,52 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "NSDate+ActiveSync.h"
#import <Foundation/NSString.h>
#import <Foundation/NSTimeZone.h>
@implementation NSDate (ActiveSync)
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
{
return [self descriptionWithCalendarFormat: @"%Y-%m-%dT%H:%M:%S.%FZ" timeZone: [NSTimeZone timeZoneWithName: @"GMT"] locale: nil];
}
//
// From [MS-ASDTYPE].pdf - section 2.3 "Dates and times in calendar items MUST NOT include punctuation separators."
//
- (NSString *) activeSyncRepresentationWithoutSeparatorsInContext: (WOContext *) context
{
return [self descriptionWithCalendarFormat: @"%Y%m%dT%H%M%SZ" timeZone: [NSTimeZone timeZoneWithName: @"GMT"] locale: nil];
}
@end
+55
View File
@@ -0,0 +1,55 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __NSSTRINGACTIVESYNC_H__
#define __NSSTRINGACTIVESYNC_H__
#import <Foundation/NSString.h>
#include "SOGoActiveSyncConstants.h"
@class NSCalendarDate;
@class NSData;
@class WOContext;
@interface NSString (ActiveSync)
- (NSString *) sanitizedServerIdWithType: (SOGoMicrosoftActiveSyncFolderType) folderType;
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
- (int) activeSyncFolderType;
- (NSString *) realCollectionIdWithFolderType: (SOGoMicrosoftActiveSyncFolderType *) folderType;
- (NSCalendarDate *) calendarDate;
- (NSString *) deviceId;
- (NSString *) deviceType;
- (NSString *) command;
- (NSData *) convertHexStringToBytes;
@end
#endif
+300
View File
@@ -0,0 +1,300 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "NSString+ActiveSync.h"
#include <Foundation/NSArray.h>
#include <Foundation/NSCalendarDate.h>
#include <Foundation/NSData.h>
#include <Foundation/NSDate.h>
#include <SOGo/NSString+Utilities.h>
#include <NGExtensions/NSString+misc.h>
@implementation NSString (ActiveSync)
- (NSString *) sanitizedServerIdWithType: (SOGoMicrosoftActiveSyncFolderType) folderType
{
if (folderType == ActiveSyncEventFolder)
{
int len;
len = [self length];
if (len > 4 && [self hasSuffix: @".ics"])
return [self substringToIndex: len-4];
else
return [NSString stringWithFormat: @"%@.ics", self];
}
return self;
}
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
{
NSString *s;
s = [self stringByEscapingHTMLString];
return [[s componentsSeparatedByCharactersInSet: [self safeCharacterSet]]
componentsJoinedByString: @""];
}
- (int) activeSyncFolderType
{
if ([self isEqualToString: @"inbox"])
return 2;
else if ([self isEqualToString: @"draft"])
return 3;
else if ([self isEqualToString: @"sent"])
return 5;
else if ([self isEqualToString: @"trash"])
return 4;
return 12;
}
- (NSString *) realCollectionIdWithFolderType: (SOGoMicrosoftActiveSyncFolderType *) folderType;
{
NSString *realCollectionId, *v;
*folderType = ActiveSyncGenericFolder;
v = [self stringByUnescapingURL];
if ([v hasPrefix: @"vevent/"])
{
realCollectionId = [v substringFromIndex: 7];
*folderType = ActiveSyncEventFolder;
}
else if ([v hasPrefix: @"vtodo/"])
{
realCollectionId = [v substringFromIndex: 6];
*folderType = ActiveSyncTaskFolder;
}
else if ([v hasPrefix: @"vcard/"])
{
realCollectionId = [v substringFromIndex: 6];
*folderType = ActiveSyncContactFolder;
}
else if ([v hasPrefix: @"mail/"])
{
realCollectionId = [[v stringByUnescapingURL] substringFromIndex: 5];
*folderType = ActiveSyncMailFolder;
}
else
{
realCollectionId = nil;
}
return realCollectionId;
}
//
// 2014-01-16T05:00:00.000Z
//
// See http://www.gnustep.org/resources/documentation/Developer/Base/Reference/NSCalendarDate.html#method$NSCalendarDate-initWithString$calendarFormat$ for the format details.
//
- (NSCalendarDate *) calendarDate
{
id o;
o = [NSCalendarDate dateWithString: self calendarFormat: @"%Y%m%dT%H%M%SZ"];
if (!o)
o = [NSCalendarDate dateWithString: self calendarFormat: @"%Y-%m-%dT%H:%M:%S.%FZ"];
return o;
}
- (NSString *) _valueForParameter: (NSString *) theParameter
{
NSArray *components;
NSString *s;
int i;
components = [[[self componentsSeparatedByString: @"?"] lastObject] componentsSeparatedByString: @"&"];
for (i = 0; i < [components count]; i++)
{
s = [components objectAtIndex: i];
if ([[s uppercaseString] hasPrefix: theParameter])
return [s substringFromIndex: [theParameter length]];
}
return nil;
}
//
// This method extracts the "DeviceId" from a URI:
//
// /SOGo/Microsoft-Server-ActiveSync?Cmd=FolderSync&User=sogo10&DeviceId=SEC17CD1A3E9E3F2&DeviceType=SAMSUNGSGHI317M
//
- (NSString *) deviceId
{
NSString *s;
s = [self _valueForParameter: @"DEVICEID="];
if (!s)
s = @"Unknown";
return s;
}
//
// This method extracts the "DeviceType" from a URI:
//
// /SOGo/Microsoft-Server-ActiveSync?Cmd=FolderSync&User=sogo10&DeviceId=SEC17CD1A3E9E3F2&DeviceType=SAMSUNGSGHI317M
//
- (NSString *) deviceType
{
NSString *s;
s = [self _valueForParameter: @"DEVICETYPE="];
if (!s)
s = @"Unknown";
return s;
}
//
//
//
- (NSString *) command
{
NSString *s;
s = [self _valueForParameter: @"CMD="];
if (!s)
s = @"Unknown";
return s;
}
//
// FIXME: combine with our OpenChange code.
//
- (char) _decodeHexByte: (char) byteChar
{
char newByte;
if (byteChar >= 48 && byteChar <= 57)
newByte = (uint8_t) byteChar - 48;
else if (byteChar >= 65 && byteChar <= 70)
newByte = (uint8_t) byteChar - 55;
else if (byteChar >= 97 && byteChar <= 102)
newByte = (uint8_t) byteChar - 87;
else
newByte = -1;
return newByte;
}
//
// FIXME: combine with our OpenChange code.
//
- (BOOL) _decodeHexByte: (uint8_t *) byte
atPos: (NSUInteger) pos
{
BOOL error = NO;
char newByte;
unichar byteChar;
byteChar = [self characterAtIndex: pos];
if (byteChar < 256)
{
newByte = [self _decodeHexByte: (char) byteChar];
if (newByte == -1)
error = YES;
else
*byte = newByte;
}
else
error = YES;
return error;
}
//
// FIXME: combine with our OpenChange code.
//
- (BOOL) _decodeHexPair: (uint8_t *) byte
atPos: (NSUInteger) pos
{
BOOL error;
uint8_t lowValue, highValue;
error = [self _decodeHexByte: &highValue atPos: pos];
if (!error)
{
error = [self _decodeHexByte: &lowValue atPos: pos + 1];
if (!error)
*byte = highValue << 4 | lowValue;
}
return error;
}
//
// FIXME: combine with our OpenChange code.
//
- (NSData *) convertHexStringToBytes
{
NSUInteger count, strLen, bytesLen;
uint8_t *bytes, *currentByte;
NSData *decoded = nil;
BOOL error = NO;
strLen = [self length];
if ((strLen % 2) == 0)
{
bytesLen = strLen / 2;
bytes = NSZoneCalloc (NULL, bytesLen, sizeof (uint8_t));
currentByte = bytes;
for (count = 0; !error && count < strLen; count += 2)
{
error = [self _decodeHexPair: currentByte atPos: count];
currentByte++;
}
if (error)
NSZoneFree (NULL, bytes);
else
decoded = [NSData dataWithBytesNoCopy: bytes
length: bytesLen
freeWhenDone: YES];
}
return decoded;
}
@end
+12
View File
@@ -0,0 +1,12 @@
In order to use this software in production environments, you need to
get a proper usage license from Microsoft. Please contact them directly
to negotiate the fees associated to your user base.
To contact Microsoft, please visit:
http://www.microsoft.com/en-us/legal/intellectualproperty/IPLicensing/Programs/exchangeactivesyncprotocol.aspx
and send an email to iplicreq@microsoft.com
Inverse inc. provides this software for free, but is not responsible
for anything related to its usage.
+42
View File
@@ -0,0 +1,42 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __SOGOACTIVESYNCCONSTANTS_H__
#define __SOGOACTIVESYNCCONSTANTS_H__
typedef enum
{
ActiveSyncGenericFolder = 0,
ActiveSyncMailFolder = 1,
ActiveSyncContactFolder = 2,
ActiveSyncEventFolder = 3,
ActiveSyncTaskFolder = 4,
} SOGoMicrosoftActiveSyncFolderType;
#endif
@@ -0,0 +1,47 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __SOGOACTIVESYNCDISPATCHERSYNC_H__
#define __SOGOACTIVESYNCDISPATCHERSYNC_H__
#import "SOGoActiveSyncDispatcher.h"
#import <DOM/DOMElement.h>
#import <DOM/DOMProtocols.h>
@class WOResponse;
@interface SOGoActiveSyncDispatcher (Sync)
- (void) processSync: (id <DOMElement>) theDocumentElement
inResponse: (WOResponse *) theResponse;
@end
#endif // SOGOACTIVESYNCDISPATCHERSYNC
File diff suppressed because it is too large. Load diff
+56
View File
@@ -0,0 +1,56 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <Foundation/NSObject.h>
#include "SOGoActiveSyncConstants.h"
@class NSException;
@class NSURL;
@interface SOGoActiveSyncDispatcher : NSObject
{
NSURL *folderTableURL;
id context;
}
- (id) collectionFromId: (NSString *) theCollectionId
type: (SOGoMicrosoftActiveSyncFolderType) theFolderType;
- (id) globallyUniqueIDToIMAPFolderName: (NSString *) theIdToTranslate
type: (SOGoMicrosoftActiveSyncFolderType) theFolderType;
- (NSException *) dispatchRequest: (id) theRequest
inResponse: (id) theResponse
context: (id) theContext;
- (NSURL *) folderTableURL;
- (void) ensureFolderTableExists;
@end
File diff suppressed because it is too large. Load diff
+48
View File
@@ -0,0 +1,48 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __SOGOMAILOBJECTACTIVESYNC_H__
#define __SOGOMAILOBJECTACTIVESYNC_H__
#import <Mailer/SOGoMailObject.h>
@class iCalCalendar;
@class NSDictionary;
@class WOContext;
@interface SOGoMailObject (ActiveSync)
- (iCalCalendar *) calendarFromIMIPMessage;
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context;
@end
#endif
+819
View File
@@ -0,0 +1,819 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "SOGoMailObject+ActiveSync.h"
#import <Foundation/NSArray.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
#import <Foundation/NSString.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>
#import <NGImap4/NGImap4EnvelopeAddress.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGMime/NGMimeBodyPart.h>
#import <NGMime/NGMimeFileData.h>
#import <NGMime/NGMimeMultipartBody.h>
#import <NGMime/NGMimeType.h>
#import <NGMail/NGMimeMessageParser.h>
#import <NGMail/NGMimeMessage.h>
#import <NGMail/NGMimeMessageGenerator.h>
#include "iCalTimeZone+ActiveSync.h"
#include "NSData+ActiveSync.h"
#include "NSDate+ActiveSync.h"
#include "NSString+ActiveSync.h"
#include <Appointments/iCalEntityObject+SOGo.h>
#include <Appointments/iCalPerson+SOGo.h>
#include <Mailer/NSString+Mail.h>
#include <Mailer/SOGoMailBodyPart.h>
#include <SOGo/SOGoUser.h>
typedef struct {
uint32_t dwLowDateTime;
uint32_t dwHighDateTime;
} FILETIME;
struct GlobalObjectId {
uint8_t ByteArrayID[16];
uint8_t YH;
uint8_t YL;
uint8_t Month;
uint8_t D;
FILETIME CreationTime;
uint8_t X[8];
uint32_t Size;
uint8_t* Data;
};
@implementation SOGoMailObject (ActiveSync)
//
//
//
- (void) _setInstanceDate: (struct GlobalObjectId *) newGlobalId
fromDate: (NSCalendarDate *) instanceDate
{
uint16_t year;
if (instanceDate)
{
//[instanceDate setTimeZone: timeZone];
year = [instanceDate yearOfCommonEra];
newGlobalId->YH = year >> 8;
newGlobalId->YL = year & 0xff;
newGlobalId->Month = [instanceDate monthOfYear];
newGlobalId->D = [instanceDate dayOfMonth];
}
}
//
// The GlobalObjId is documented here: http://msdn.microsoft.com/en-us/library/ee160198(v=EXCHG.80).aspx
//
- (NSData *) _computeGlobalObjectIdFromEvent: (iCalEvent *) event
{
NSData *binPrefix, *globalObjectId, *uidAsASCII;
NSString *prefix, *uid;
struct GlobalObjectId newGlobalId;
const char *bytes;
prefix = @"040000008200e00074c5b7101a82e008";
// dataPrefix is "vCal-Uid %x01 %x00 %x00 %x00"
uint8_t dataPrefix[] = { 0x76, 0x43, 0x61, 0x6c, 0x2d, 0x55, 0x69, 0x64, 0x01, 0x00, 0x00, 0x00 };
uid = [event uid];
binPrefix = [prefix convertHexStringToBytes];
[binPrefix getBytes: &newGlobalId.ByteArrayID];
[self _setInstanceDate: &newGlobalId
fromDate: [event recurrenceId]];
uidAsASCII = [uid dataUsingEncoding: NSASCIIStringEncoding];
bytes = [uidAsASCII bytes];
// 0x0c is the size of our dataPrefix
newGlobalId.Size = 0x0c + [uidAsASCII length];
newGlobalId.Data = malloc(newGlobalId.Size * sizeof(uint8_t));
memcpy(newGlobalId.Data, dataPrefix, 0x0c);
memcpy(newGlobalId.Data + 0x0c, bytes, newGlobalId.Size - 0x0c);
globalObjectId = [[NSData alloc] initWithBytes: &newGlobalId length: 40 + newGlobalId.Size*sizeof(uint8_t)];
free(newGlobalId.Data);
return [globalObjectId autorelease];
}
//
// For debugging purposes...
//
- (NSString *) _uidFromGlobalObjectId: (NSData *) objectId
{
NSString *uid;
struct GlobalObjectId *newGlobalId;
NSUInteger length;
uint8_t *bytes;
length = [objectId length];
uid = nil;
bytes = malloc(length*sizeof(uint8_t));
[objectId getBytes: bytes length: length];
newGlobalId = (struct GlobalObjectId *)bytes;
// We must take the offset (dataPrefix) into account
uid = [[NSString alloc] initWithBytes: newGlobalId->Data+12 length: newGlobalId->Size-12 encoding: NSASCIIStringEncoding];
free(bytes);
return AUTORELEASE(uid);
}
//
//
//
- (NSString *) _emailAddressesFrom: (NSArray *) enveloppeAddresses
{
NGImap4EnvelopeAddress *address;
NSString *email, *rc, *name;
NSMutableArray *addresses;
int i, max;
rc = nil;
max = [enveloppeAddresses count];
if (max > 0)
{
addresses = [NSMutableArray array];
for (i = 0; i < max; i++)
{
address = [enveloppeAddresses objectAtIndex: i];
name = [address personalName];
email = [NSString stringWithFormat: @"\"%@\" <%@>", (name ? name : [address baseEMail]), [address baseEMail]];
if (email)
[addresses addObject: email];
}
rc = [addresses componentsJoinedByString: @", "];
}
return rc;
}
//
//
//
- (NSData *) _preferredBodyDataInMultipartUsingType: (int) theType
{
NSString *encoding, *key, *plainKey, *htmlKey, *type, *subtype;
NSDictionary *textParts, *part;
NSEnumerator *e;
NSData *d;
textParts = [self fetchPlainTextParts];
e = [textParts keyEnumerator];
plainKey = nil;
htmlKey = nil;
d = nil;
while ((key = [e nextObject]))
{
part = [self lookupInfoForBodyPart: key];
type = [part valueForKey: @"type"];
subtype = [part valueForKey: @"subtype"];
if ([type isEqualToString: @"text"] && [subtype isEqualToString: @"html"])
htmlKey = key;
else if ([type isEqualToString: @"text"] && [subtype isEqualToString: @"plain"])
plainKey = key;
}
key = nil;
if (theType == 2)
key = htmlKey;
else if (theType == 1)
key = plainKey;
if (key)
{
d = [[self fetchPlainTextParts] objectForKey: key];
encoding = [[self lookupInfoForBodyPart: key] objectForKey: @"encoding"];
if ([encoding caseInsensitiveCompare: @"base64"] == NSOrderedSame)
d = [d dataByDecodingBase64];
else if ([encoding caseInsensitiveCompare: @"quoted-printable"] == NSOrderedSame)
d = [d dataByDecodingQuotedPrintableTransferEncoding];
}
return d;
}
//
//
//
- (void) _sanitizedMIMEPart: (id) thePart
performed: (BOOL *) b
{
if ([thePart isKindOfClass: [NGMimeMultipartBody class]])
{
NGMimeBodyPart *part;
NSArray *parts;
int i;
parts = [thePart parts];
for (i = 0; i < [parts count]; i++)
{
part = [parts objectAtIndex: i];
[self _sanitizedMIMEPart: part
performed: b];
}
}
else if ([thePart isKindOfClass: [NGMimeBodyPart class]])
{
NGMimeFileData *fdata;
id body;
body = [thePart body];
if ([body isKindOfClass: [NGMimeMultipartBody class]])
{
[self _sanitizedMIMEPart: body
performed: b];
}
else if (([body isKindOfClass: [NSData class]] || [body isKindOfClass: [NSString class]]) &&
[[[thePart contentType] type] isEqualToString: @"text"] &&
([[[thePart contentType] subType] isEqualToString: @"plain"] || [[[thePart contentType] subType] isEqualToString: @"html"]))
{
// We make sure everything is encoded in UTF-8
NGMimeType *mimeType;
NSString *s;
if ([body isKindOfClass: [NSData class]])
{
NSString *charset;
int encoding;
charset = [[thePart contentType] valueOfParameter: @"charset"];
encoding = [NGMimeType stringEncodingForCharset: charset];
s = [[NSString alloc] initWithData: body encoding: encoding];
AUTORELEASE(s);
}
else
{
// Handle situations when SOPE stupidly returns us a NSString
// This can happen for Content-Type: text/plain, Content-Transfer-Encoding: 8bit
s = body;
}
if (s)
{
body = [s dataUsingEncoding: NSUTF8StringEncoding];
}
mimeType = [NGMimeType mimeType: [[thePart contentType] type]
subType: [[thePart contentType] subType]
parameters: [NSDictionary dictionaryWithObject: @"utf-8" forKey: @"charset"]];
[thePart setHeader: mimeType forKey: @"content-type"];
fdata = [[NGMimeFileData alloc] initWithBytes: [body bytes]
length: [body length]];
[thePart setBody: fdata];
RELEASE(fdata);
*b = YES;
}
}
}
//
//
//
- (NSData *) _sanitizedMIMEMessage
{
NGMimeMessageParser *parser;
NGMimeMessage *message;
NSData *d;
BOOL b;
d = [self content];
parser = [[NGMimeMessageParser alloc] init];
AUTORELEASE(parser);
message = [parser parsePartFromData: d];
b = NO;
if (message)
{
[self _sanitizedMIMEPart: [message body]
performed: &b];
if (b)
{
NGMimeMessageGenerator *generator;
generator = [[NGMimeMessageGenerator alloc] init];
AUTORELEASE(generator);
d = [generator generateMimeFromPart: message];
}
}
return d;
}
//
//
//
- (NSData *) _preferredBodyDataUsingType: (int) theType
nativeType: (int *) theNativeType
{
NSString *type, *subtype, *encoding;
NSData *d;
type = [[[self bodyStructure] valueForKey: @"type"] lowercaseString];
subtype = [[[self bodyStructure] valueForKey: @"subtype"] lowercaseString];
d = nil;
// We determine the native type
if ([type isEqualToString: @"text"] && [subtype isEqualToString: @"plain"])
*theNativeType = 1;
else if ([type isEqualToString: @"text"] && [subtype isEqualToString: @"html"])
*theNativeType = 2;
else if ([type isEqualToString: @"multipart"])
*theNativeType = 4;
// We get the right part based on the preference
if (theType == 1 || theType == 2)
{
if ([type isEqualToString: @"text"])
{
d = [[self fetchPlainTextParts] objectForKey: @""];
// We check if we have base64 encoded parts. If so, we just
// un-encode them before using them
encoding = [[self lookupInfoForBodyPart: @""] objectForKey: @"encoding"];
if ([encoding caseInsensitiveCompare: @"base64"] == NSOrderedSame)
d = [d dataByDecodingBase64];
else if ([encoding caseInsensitiveCompare: @"quoted-printable"] == NSOrderedSame)
d = [d dataByDecodingQuotedPrintableTransferEncoding];
// Check if we must convert html->plain
if (theType == 1 && [subtype isEqualToString: @"html"])
{
NSString *s;
s = [[NSString alloc] initWithData: d encoding: NSUTF8StringEncoding];
AUTORELEASE(s);
s = [s htmlToText];
d = [s dataUsingEncoding: NSUTF8StringEncoding];
}
}
else if ([type isEqualToString: @"multipart"])
{
d = [self _preferredBodyDataInMultipartUsingType: theType];
}
}
else if (theType == 4)
{
// We sanitize the content *ONLY* for Outlook clients. Outlook has strange issues
// with quoted-printable/base64 encoded text parts. It just doesn't decode them.
if ([[context objectForKey: @"DeviceType"] isEqualToString: @"WindowsOutlook15"])
d = [self _sanitizedMIMEMessage];
else
d = [self content];
}
return d;
}
//
//
//
- (iCalCalendar *) calendarFromIMIPMessage
{
NSDictionary *part;
NSArray *parts;
int i;
// We check if we have at least 2 parts and if one of them is a text/calendar
parts = [[self bodyStructure] objectForKey: @"parts"];
if ([parts count] > 1)
{
for (i = 0; i < [parts count]; i++)
{
part = [parts objectAtIndex: i];
if ([[part objectForKey: @"type"] isEqualToString: @"text"] &&
[[part objectForKey: @"subtype"] isEqualToString: @"calendar"])
{
id bodyPart;
bodyPart = [self lookupImap4BodyPartKey: [NSString stringWithFormat: @"%d", i+1]
inContext: self->context];
if (bodyPart)
{
iCalCalendar *calendar;
NSData *calendarData;
calendarData = [bodyPart fetchBLOB];
calendar = nil;
NS_DURING
calendar = [iCalCalendar parseSingleFromSource: calendarData];
NS_HANDLER
calendar = nil;
NS_ENDHANDLER
return calendar;
}
}
}
}
return nil;
}
//
//
//
- (NSString *) activeSyncRepresentationInContext: (WOContext *) _context
{
NSAutoreleasePool *pool;
NSData *d, *globalObjId;
NSArray *attachmentKeys;
NSMutableString *s;
id value;
iCalCalendar *calendar;
int preferredBodyType, nativeBodyType;
s = [NSMutableString string];
// To - "The value of this element contains one or more e-mail addresses.
// If there are multiple e-mail addresses, they are separated by commas."
value = [self _emailAddressesFrom: [[self envelope] to]];
if (value)
[s appendFormat: @"<To xmlns=\"Email:\">%@</To>", [value activeSyncRepresentationInContext: context]];
// From
value = [self _emailAddressesFrom: [[self envelope] from]];
if (value)
[s appendFormat: @"<From xmlns=\"Email:\">%@</From>", [value activeSyncRepresentationInContext: context]];
// Subject
value = [self decodedSubject];
if (value)
{
[s appendFormat: @"<Subject xmlns=\"Email:\">%@</Subject>", [value activeSyncRepresentationInContext: context]];
[s appendFormat: @"<ThreadTopic xmlns=\"Email:\">%@</ThreadTopic>", [value activeSyncRepresentationInContext: context]];
}
// DateReceived
value = [self date];
if (value)
[s appendFormat: @"<DateReceived xmlns=\"Email:\">%@</DateReceived>", [value activeSyncRepresentationInContext: context]];
// DisplayTo
[s appendFormat: @"<DisplayTo xmlns=\"Email:\">%@</DisplayTo>", [[context activeUser] login]];
// Cc - same syntax as the To field
value = [self _emailAddressesFrom: [[self envelope] cc]];
if (value)
[s appendFormat: @"<Cc xmlns=\"Email:\">%@</Cc>", [value activeSyncRepresentationInContext: context]];
// Importance - FIXME
[s appendFormat: @"<Importance xmlns=\"Email:\">%@</Importance>", @"1"];
// Read
[s appendFormat: @"<Read xmlns=\"Email:\">%d</Read>", ([self read] ? 1 : 0)];
// We handle MeetingRequest
calendar = [self calendarFromIMIPMessage];
if (calendar)
{
NSString *method, *className;
iCalPerson *attendee;
iCalTimeZone *tz;
iCalEvent *event;
iCalPersonPartStat partstat;
int v;
event = [[calendar events] lastObject];
method = [[event parent] method];
// If we are the organizer, let's pick the attendee based on the From address
if ([event userIsOrganizer: [context activeUser]])
attendee = [event findAttendeeWithEmail: [[[[self envelope] from] lastObject] baseEMail]];
else
attendee = [event findAttendeeWithEmail: [[[context activeUser] allEmails] objectAtIndex: 0]];
partstat = [attendee participationStatus];
// We generate the correct MessageClass
if ([method isEqualToString: @"REQUEST"])
className = @"IPM.Schedule.Meeting.Request";
else if ([method isEqualToString: @"REPLY"])
{
switch (partstat)
{
case iCalPersonPartStatAccepted:
className = @"IPM.Schedule.Meeting.Resp.Pos";
break;
case iCalPersonPartStatDeclined:
className = @"IPM.Schedule.Meeting.Resp.Neg";
break;
case iCalPersonPartStatTentative:
case iCalPersonPartStatNeedsAction:
className = @"IPM.Schedule.Meeting.Resp.Tent";
break;
default:
className = @"IPM.Appointment";
NSLog(@"unhandled part stat");
}
}
else if ([method isEqualToString: @"COUNTER"])
className = @"IPM.Schedule.Meeting.Resp.Tent";
else if ([method isEqualToString: @"CANCEL"])
className = @"IPM.Schedule.Meeting.Cancelled";
else
className = @"IPM.Appointment";
[s appendFormat: @"<MessageClass xmlns=\"Email:\">%@</MessageClass>", className];
[s appendString: @"<MeetingRequest xmlns=\"Email:\">"];
[s appendFormat: @"<AllDayEvent xmlns=\"Email:\">%d</AllDayEvent>", ([event isAllDay] ? 1 : 0)];
// StartTime -- http://msdn.microsoft.com/en-us/library/ee157132(v=exchg.80).aspx
if ([event startDate])
[s appendFormat: @"<StartTime xmlns=\"Email:\">%@</StartTime>", [[event startDate] activeSyncRepresentationWithoutSeparatorsInContext: context]];
if ([event timeStampAsDate])
[s appendFormat: @"<DTStamp xmlns=\"Email:\">%@</DTStamp>", [[event timeStampAsDate] activeSyncRepresentationWithoutSeparatorsInContext: context]];
else if ([event created])
[s appendFormat: @"<DTStamp xmlns=\"Email:\">%@</DTStamp>", [[event created] activeSyncRepresentationWithoutSeparatorsInContext: context]];
// EndTime -- http://msdn.microsoft.com/en-us/library/ee157945(v=exchg.80).aspx
if ([event endDate])
[s appendFormat: @"<EndTime xmlns=\"Email:\">%@</EndTime>", [[event endDate] activeSyncRepresentationWithoutSeparatorsInContext: context]];
// FIXME: Single appointment - others are not supported right now
[s appendFormat: @"<InstanceType xmlns=\"Email:\">%d</InstanceType>", 0];
// Location
if ([[event location] length])
[s appendFormat: @"<Location xmlns=\"Email:\">%@</Location>", [[event location] activeSyncRepresentationInContext: context]];
[s appendFormat: @"<Organizer xmlns=\"Email:\">%@</Organizer>", [[[event organizer] mailAddress] activeSyncRepresentationInContext: context]];
// This will trigger the SendMail command. We set it to no for email invitations as
// SOGo will send emails when MeetingResponse is called.
[s appendFormat: @"<ResponseRequested xmlns=\"Email:\">%d</ResponseRequested>", 0];
// Sensitivity
if ([[event accessClass] isEqualToString: @"PRIVATE"])
v = 2;
if ([[event accessClass] isEqualToString: @"CONFIDENTIAL"])
v = 3;
else
v = 0;
[s appendFormat: @"<Sensitivity xmlns=\"Email:\">%d</Sensitivity>", v];
[s appendFormat: @"<BusyStatus xmlns=\"Email:\">%d</BusyStatus>", 2];
// Timezone
tz = [(iCalDateTime *)[event firstChildWithTag: @"dtstart"] timeZone];
if (!tz)
tz = [iCalTimeZone timeZoneForName: @"Europe/London"];
[s appendFormat: @"<TimeZone xmlns=\"Email:\">%@</TimeZone>", [tz activeSyncRepresentationInContext: context]];
// We disallow new time proposals
[s appendFormat: @"<DisallowNewTimeProposal xmlns=\"Email:\">%d</DisallowNewTimeProposal>", 1];
// From http://blogs.msdn.com/b/exchangedev/archive/2011/07/22/working-with-meeting-requests-in-exchange-activesync.aspx:
//
// "Clients that need to determine whether the GlobalObjId element for a meeting request corresponds to an existing Calendar
// object in the Calendar folder have to convert the GlobalObjId element value to a UID element value to make the comparison."
//
globalObjId = [self _computeGlobalObjectIdFromEvent: event];
[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
[s appendFormat: @"<MeetingMessageType xmlns=\"Email2:\">%d</MeetingMessageType>", 1];
[s appendString: @"</MeetingRequest>"];
// ContentClass
[s appendFormat: @"<ContentClass xmlns=\"Email:\">%@</ContentClass>", @"urn:content-classes:calendarmessage"];
}
else
{
// MesssageClass and ContentClass
[s appendFormat: @"<MessageClass xmlns=\"Email:\">%@</MessageClass>", @"IPM.Note"];
[s appendFormat: @"<ContentClass xmlns=\"Email:\">%@</ContentClass>", @"urn:content-classes:message"];
}
// Reply-To - FIXME
//NSArray *replyTo = [[message objectForKey: @"envelope"] replyTo];
//if ([replyTo count])
// [s appendFormat: @"<Reply-To xmlns=\"Email:\">%@</Reply-To>", [addressFormatter stringForArray: replyTo]];
// InternetCPID - 65001 == UTF-8, we use this all the time for now.
// - 20127 == US-ASCII
[s appendFormat: @"<InternetCPID xmlns=\"Email:\">%@</InternetCPID>", @"65001"];
// Body - namespace 17
preferredBodyType = [[context objectForKey: @"BodyPreferenceType"] intValue];
// Make use of a local pool here as _preferredBodyDataUsingType:nativeType: will consume
// a significant amout of RAM and file descriptors
pool = [[NSAutoreleasePool alloc] init];
nativeBodyType = 1;
d = [self _preferredBodyDataUsingType: preferredBodyType nativeType: &nativeBodyType];
if (d)
{
NSString *content;
int len, truncated;
content = [[NSString alloc] initWithData: d encoding: NSUTF8StringEncoding];
// FIXME: This is a hack. We should normally avoid doing this as we might get
// broken encodings. We should rather tell that the data was truncated and expect
// a ItemOperations call to download the whole base64 encoding multipart.
//
// See http://social.msdn.microsoft.com/Forums/en-US/b9944e49-9bc9-4ab8-ba33-a9fc08557c5b/mime-raw-data-in-eas-sync-response?forum=os_exchangeprotocols
// for an "interesting" discussion around this.
//
if (!content)
content = [[NSString alloc] initWithData: d encoding: NSISOLatin1StringEncoding];
AUTORELEASE(content);
content = [content activeSyncRepresentationInContext: context];
truncated = 0;
len = [content length];
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", preferredBodyType];
[s appendFormat: @"<Truncated>%d</Truncated>", truncated];
[s appendFormat: @"<Preview></Preview>"];
if (!truncated)
{
[s appendFormat: @"<Data>%@</Data>", content];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", len];
}
[s appendString: @"</Body>"];
}
DESTROY(pool);
// Attachments -namespace 16
attachmentKeys = [self fetchFileAttachmentKeys];
if ([attachmentKeys count])
{
int i;
[s appendString: @"<Attachments xmlns=\"AirSyncBase:\">"];
for (i = 0; i < [attachmentKeys count]; i++)
{
value = [attachmentKeys objectAtIndex: i];
[s appendString: @"<Attachment>"];
[s appendFormat: @"<DisplayName>%@</DisplayName>", [[value objectForKey: @"filename"] activeSyncRepresentationInContext: context]];
// FileReference must be a unique identifier across the whole store. We use the following structure:
// mail/<foldername>/<message UID/<pathofpart>
// mail/INBOX/2
[s appendFormat: @"<FileReference>mail/%@/%@/%@</FileReference>", [[[self container] relativeImap4Name] stringByEscapingURL], [self nameInContainer], [value objectForKey: @"path"]];
[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];
[s appendString: @"</Attachment>"];
}
[s appendString: @"</Attachments>"];
}
// Flags
[s appendString: @"<Flag xmlns=\"Email:\">"];
[s appendFormat: @"<FlagStatus>%d</FlagStatus>", 0];
[s appendString: @"</Flag>"];
// FIXME - support these in the future
//[s appendString: @"<ConversationId xmlns=\"Email2:\">foobar</ConversationId>"];
//[s appendString: @"<ConversationIndex xmlns=\"Email2:\">zot=</ConversationIndex>"];
// NativeBodyType -- http://msdn.microsoft.com/en-us/library/ee218276(v=exchg.80).aspx
// This is a required child element.
// 1 -> plain/text, 2 -> HTML and 3 -> RTF
if (nativeBodyType == 4)
nativeBodyType = 1;
[s appendFormat: @"<NativeBodyType xmlns=\"AirSyncBase:\">%d</NativeBodyType>", nativeBodyType];
return s;
}
//
//
//
// Exemple for a message being marked as read:
//
// <Change>
// <ServerId>607</ServerId>
// <ApplicationData>
// <Read xmlns="Email:">1</Read>
// </ApplicationData>
// </Change>
// </Commands>
//
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) _context
{
id o;
if ((o = [theValues objectForKey: @"Flag"]))
{
o = [o objectForKey: @"FlagStatus"];
if ([o intValue])
[self addFlags: @"\\Flagged"];
else
[self removeFlags: @"\\Flagged"];
}
if ((o = [theValues objectForKey: @"Read"]))
{
if ([o intValue])
[self addFlags: @"seen"];
else
[self removeFlags: @"seen"];;
}
}
@end
+55
View File
@@ -0,0 +1,55 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __SOGOSYNCCACHEOBJECT_H__
#define __SOGOSYNCCACHEOBJECT_H__
#import <Foundation/NSObject.h>
@class NSNull;
@interface SOGoSyncCacheObject : NSObject
{
id _uid;
id _sequence;
}
+ (id) syncCacheObjectWithUID: (id) theUID sequence: (id) theSequence;
- (id) uid;
- (void) setUID: (id) theUID;
- (id) sequence;
- (void) setSequence: (id) theSequence;
- (NSComparisonResult) compareUID: (SOGoSyncCacheObject *) theSyncCacheObject;
- (NSComparisonResult) compareSequence: (SOGoSyncCacheObject *) theSyncCacheObject;
@end
#endif
+122
View File
@@ -0,0 +1,122 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "SOGoSyncCacheObject.h"
#import <Foundation/NSNull.h>
#import <Foundation/NSString.h>
@implementation SOGoSyncCacheObject
- (id) init
{
if ((self = [super init]))
{
_uid = nil;
_sequence = nil;
}
return self;
}
+ (id) syncCacheObjectWithUID: (id) theUID sequence: (id) theSequence;
{
id o;
o = [[self alloc] init];
[o setUID: theUID];
[o setSequence: theSequence];
return o;
}
- (void) dealloc
{
RELEASE(_uid);
RELEASE(_sequence);
[super dealloc];
}
- (id) uid
{
return _uid;
}
- (void) setUID: (id) theUID
{
ASSIGN(_uid, theUID);
}
- (id) sequence
{
return _sequence;
}
- (void) setSequence: (id) theSequence
{
ASSIGN(_sequence, theSequence);
}
- (NSComparisonResult) compareUID: (SOGoSyncCacheObject *) theSyncCacheObject
{
return [[self uid] compare: [theSyncCacheObject uid]];
}
//
// We might get NSNull values here, so if both are NSNull instances,
// we sort by UID. If both sequences are equal, we also sort by UID.
//
- (NSComparisonResult) compareSequence: (SOGoSyncCacheObject *) theSyncCacheObject
{
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]])
return NSOrderedDescending;
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)
return [self compareUID: theSyncCacheObject];
return [[self sequence] compare: [theSyncCacheObject sequence]];
}
- (NSString *) description
{
return [NSString stringWithFormat: @"%@-%@", _uid, _sequence];
}
@end
@@ -0,0 +1,101 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
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>
#include <NGObjWeb/WOResponse.h>
#import <Foundation/NSArray.h>
@interface SoObjectWebDAVDispatcher (ActiveSync)
- (id)_callObjectMethod:(NSString *)_method inContext:(WOContext *)_ctx;
- (id) doOPTIONS:(WOContext *)_ctx;
@end
@implementation SoObjectWebDAVDispatcher (ActiveSync)
- (id) doOPTIONS:(WOContext *)_ctx
{
WOResponse *response;
/*
See example: http://msdn.microsoft.com/en-us/library/ee204257(v=exchg.80).aspx
*/
if ([[[_ctx request] requestHandlerKey] isEqualToString: @"Microsoft-Server-ActiveSync"])
{
response = [_ctx response];
[response setStatus: 200];
[response setHeader: @"private" forKey: @"Cache-Control"];
[response setHeader: @"OPTIONS, POST" forKey: @"Allow"];
[response setHeader: @"14.1" forKey: @"MS-Server-ActiveSync"];
[response setHeader: @"2.0,2.1,2.5,12.0,12.1,14.0,14.1" 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"];
}
else
{
NSArray *tmp;
id result;
/* this checks whether the object provides a specific OPTIONS method */
if ((result = [self _callObjectMethod:@"OPTIONS" inContext:_ctx]) != nil)
return result;
response = [_ctx response];
[response setStatus:200 /* OK */];
if ((tmp = [self->object davAllowedMethodsInContext:_ctx]) != nil)
[response setHeader:[tmp componentsJoinedByString:@", "] forKey:@"allow"];
if ([[[_ctx request] clientCapabilities] isWebFolder]) {
/*
As described over here:
http://teyc.editthispage.com/2005/06/02
This page also says that: "MS-Auth-Via header is not required to work
with Web Folders".
*/
[response setHeader:[tmp componentsJoinedByString:@", "] forKey:@"public"];
}
if ((tmp = [self->object davComplianceClassesInContext:_ctx]) != nil)
[response setHeader:[tmp componentsJoinedByString:@", "] forKey:@"dav"];
}
return response;
}
@end
+34
View File
@@ -0,0 +1,34 @@
include ../config.make
include $(GNUSTEP_MAKEFILES)/common.make
include ../Version
NEEDS_GUI=no
BUNDLE_EXTENSION = .SOGo
BUNDLE_INSTALL_DIR = $(SOGO_LIBDIR)
WOBUNDLE_EXTENSION = $(BUNDLE_EXTENSION)
WOBUNDLE_INSTALL_DIR = $(BUNDLE_INSTALL_DIR)
# SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib
ADDITIONAL_INCLUDE_DIRS += \
-I.. \
-I../.. \
-I../../SOPE
ADDITIONAL_LIB_DIRS += \
-L../SoObjects/SOGo/SOGo.framework/ \
-L../SoObjects/SOGo/$(GNUSTEP_OBJ_DIR)/ \
-L../OGoContentStore/$(GNUSTEP_OBJ_DIR)/ \
-L../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ \
-L/usr/local/lib
BUNDLE_LIBS += \
-lSOGo \
-lGDLContentStore \
-lGDLAccess \
-lNGObjWeb \
-lNGCards -lNGMime -lNGLdap \
-lNGStreams -lNGExtensions -lEOControl \
-lDOM -lSaxObjC -lSBJson
ADDITIONAL_BUNDLE_LIBS += $(BUNDLE_LIBS)
+46
View File
@@ -0,0 +1,46 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ICALALARMACTIVESYNC_H__
#define __ICALALARMACTIVESYNC_H__
#import <NGCards/iCalAlarm.h>
@class NSString;
@class WOContext;
@interface iCalAlarm (ActiveSync)
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context;
@end
#endif
+106
View File
@@ -0,0 +1,106 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "iCalAlarm+ActiveSync.h"
#import <Foundation/NSDictionary.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>
@implementation iCalAlarm (ActiveSync)
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
{
NSMutableString *s;
s = [NSMutableString string];
if ([[self action] caseInsensitiveCompare: @"DISPLAY"] == NSOrderedSame)
{
NSCalendarDate *nextAlarmDate;
NSInteger delta;
nextAlarmDate = [self nextAlarmDate];
delta = (int)(([[(iCalEvent *)parent startDate] timeIntervalSince1970] - [nextAlarmDate timeIntervalSince1970])/60);
// don't send negative reminder - not supported
if (delta > 0)
[s appendFormat: @"<Reminder xmlns=\"Calendar:\">%d</Reminder>", delta];
}
return s;
}
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context
{
iCalTrigger *trigger;
id o;
o = [theValues objectForKey: @"Reminder"];
// Outlook: if reminder is set to 0 minutes before start save it as 1 minute since -> 0 minutes in not accepted by SOGo
if ([o isEqualToString: @"0"])
o = @"1";
trigger = [iCalTrigger elementWithTag: @"TRIGGER"];
[trigger setValueType: @"DURATION"];
[self setTrigger: trigger];
[self setAction: @"DISPLAY"];
// SOGo web ui only supports 1w but not 2w (custom reminder only supports min/hours/days)
// 1week = -P1W
// 2weeks > -PxD
// xdays > -PxD
// xhours -> -PTxH
// xmin -> -PTxM
if ([o intValue] == 10080)
[trigger setSingleValue: [NSString stringWithFormat: @"-P1W" ] forKey: @""];
else
{
if (([o intValue] % 1440) == 0)
[trigger setSingleValue: [NSString stringWithFormat: @"-P%dD", ([o intValue] / 1440)] forKey: @""];
else
{
if (([o intValue] % 60) == 0)
[trigger setSingleValue: [NSString stringWithFormat: @"-PT%dH", ([o intValue] / 60)] forKey: @""];
else
[trigger setSingleValue: [NSString stringWithFormat: @"-PT%@M", o] forKey: @""];
}
}
}
@end
+47
View File
@@ -0,0 +1,47 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ICALEVENTACTIVESYNC_H__
#define __ICALEVENTACTIVESYNC_H__
#import <NGCards/iCalEvent.h>
@class NSString;
@class WOContext;
@interface iCalEvent (ActiveSync)
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context;
@end
#endif
+537
View File
@@ -0,0 +1,537 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
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 <NGObjWeb/WOContext.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalDateTime.h>
#import <NGCards/iCalPerson.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserDefaults.h>
#import <Appointments/iCalEntityObject+SOGo.h>
#include "iCalAlarm+ActiveSync.h"
#include "iCalRecurrenceRule+ActiveSync.h"
#include "iCalTimeZone+ActiveSync.h"
#include "NSDate+ActiveSync.h"
#include "NSString+ActiveSync.h"
@implementation iCalEvent (ActiveSync)
- (int) _attendeeStatus: (iCalPerson *) attendee
{
int attendee_status;
attendee_status = 5;
if ([[attendee partStat] caseInsensitiveCompare: @"ACCEPTED"] == NSOrderedSame)
attendee_status = 3;
else if ([[attendee partStat] caseInsensitiveCompare: @"DECLINED"] == NSOrderedSame)
attendee_status = 4;
else if ([[attendee partStat] caseInsensitiveCompare: @"TENTATIVE"] == NSOrderedSame)
attendee_status = 2;
return attendee_status;
}
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
{
NSMutableString *s;
NSArray *attendees;
iCalPerson *organizer, *attendee;
iCalTimeZone *tz;
id o;
int v;
NSTimeZone *userTimeZone;
userTimeZone = [[[context activeUser] userDefaults] timeZone];
s = [NSMutableString string];
[s appendFormat: @"<AllDayEvent xmlns=\"Calendar:\">%d</AllDayEvent>", ([self isAllDay] ? 1 : 0)];
// DTStamp -- http://msdn.microsoft.com/en-us/library/ee219470(v=exchg.80).aspx
if ([self timeStampAsDate])
[s appendFormat: @"<DTStamp xmlns=\"Calendar:\">%@</DTStamp>", [[self timeStampAsDate] activeSyncRepresentationWithoutSeparatorsInContext: context]];
else if ([self created])
[s appendFormat: @"<DTStamp xmlns=\"Calendar:\">%@</DTStamp>", [[self created] activeSyncRepresentationWithoutSeparatorsInContext: context]];
// StartTime -- http://msdn.microsoft.com/en-us/library/ee157132(v=exchg.80).aspx
if ([self startDate])
{
if ([self isAllDay])
[s appendFormat: @"<StartTime xmlns=\"Calendar:\">%@</StartTime>",
[[[self startDate] dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: ([userTimeZone secondsFromGMTForDate: [self startDate]])*-1]
activeSyncRepresentationWithoutSeparatorsInContext: context]];
else
[s appendFormat: @"<StartTime xmlns=\"Calendar:\">%@</StartTime>", [[self startDate] activeSyncRepresentationWithoutSeparatorsInContext: context]];
}
// EndTime -- http://msdn.microsoft.com/en-us/library/ee157945(v=exchg.80).aspx
if ([self endDate])
{
if ([self isAllDay])
[s appendFormat: @"<EndTime xmlns=\"Calendar:\">%@</EndTime>",
[[[self endDate] dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: ([userTimeZone secondsFromGMTForDate: [self endDate]])*-1]
activeSyncRepresentationWithoutSeparatorsInContext: context]];
else
[s appendFormat: @"<EndTime xmlns=\"Calendar:\">%@</EndTime>", [[self endDate] activeSyncRepresentationWithoutSeparatorsInContext: context]];
}
// Timezone
tz = [(iCalDateTime *)[self firstChildWithTag: @"dtstart"] timeZone];
if (!tz)
tz = [iCalTimeZone timeZoneForName: @"Europe/London"];
[s appendFormat: @"<TimeZone xmlns=\"Calendar:\">%@</TimeZone>", [tz activeSyncRepresentationInContext: context]];
// Organizer and other invitations related properties
if ((organizer = [self organizer]))
{
o = [organizer rfc822Email];
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];
}
}
// Attendees
attendees = [self attendees];
if ([attendees count])
{
int i, attendee_status, attendee_type;
[s appendString: @"<Attendees xmlns=\"Calendar:\">"];
for (i = 0; i < [attendees count]; i++)
{
[s appendString: @"<Attendee xmlns=\"Calendar:\">"];
attendee = [attendees objectAtIndex: i];
[s appendFormat: @"<Attendee_Email xmlns=\"Calendar:\">%@</Attendee_Email>", [attendee rfc822Email]];
[s appendFormat: @"<Attendee_Name xmlns=\"Calendar:\">%@</Attendee_Name>", [[attendee cn] activeSyncRepresentationInContext: context]];
attendee_status = [self _attendeeStatus: attendee];
[s appendFormat: @"<Attendee_Status xmlns=\"Calendar:\">%d</Attendee_Status>", attendee_status];
// FIXME: handle resource
if ([[attendee role] caseInsensitiveCompare: @"REQ-PARTICIPANT"] == NSOrderedSame)
attendee_type = 1;
else
attendee_type = 2;
[s appendFormat: @"<Attendee_Type xmlns=\"Calendar:\">%d</Attendee_Type>", attendee_type];
[s appendString: @"</Attendee>"];
}
[s appendString: @"</Attendees>"];
}
// This depends on the 'NEEDS-ACTION' parameter.
// This will trigger the SendMail command
if ([self userIsAttendee: [context activeUser]])
{
iCalPerson *attendee;
int attendee_status;
attendee = [self userAsAttendee: [context activeUser]];
attendee_status = [self _attendeeStatus: attendee];
[s appendFormat: @"<ResponseRequested xmlns=\"Calendar:\">%d</ResponseRequested>", 1];
[s appendFormat: @"<ResponseType xmlns=\"Calendar:\">%d</ResponseType>", attendee_status];
[s appendFormat: @"<MeetingStatus xmlns=\"Calendar:\">%d</MeetingStatus>", 3];
[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>", 2];
}
// Subject -- http://msdn.microsoft.com/en-us/library/ee157192(v=exchg.80).aspx
if ([[self summary] length])
[s appendFormat: @"<Subject xmlns=\"Calendar:\">%@</Subject>", [[self summary] activeSyncRepresentationInContext: context]];
// Location
if ([[self location] length])
[s appendFormat: @"<Location xmlns=\"Calendar:\">%@</Location>", [[self location] activeSyncRepresentationInContext: context]];
// Importance - NOT SUPPORTED - DO NOT ENABLE
//o = [self priority];
//if ([o isEqualToString: @"9"])
// v = 0;
//else if ([o isEqualToString: @"1"])
// v = 2;
//else
// v = 1;
//[s appendFormat: @"<Importance xmlns=\"Calendar:\">%d</Importance>", v];
// UID -- http://msdn.microsoft.com/en-us/library/ee159919(v=exchg.80).aspx
if ([[self uid] length])
[s appendFormat: @"<UID xmlns=\"Calendar:\">%@</UID>", [self uid]];
// Sensitivity
if ([[self accessClass] isEqualToString: @"PRIVATE"])
v = 2;
if ([[self accessClass] isEqualToString: @"CONFIDENTIAL"])
v = 3;
else
v = 0;
[s appendFormat: @"<Sensitivity xmlns=\"Calendar:\">%d</Sensitivity>", v];
// Reminder -- http://msdn.microsoft.com/en-us/library/ee219691(v=exchg.80).aspx
// TODO: improve this to handle more alarm types
if ([self hasAlarms])
{
iCalAlarm *alarm;
alarm = [[self alarms] objectAtIndex: 0];
[s appendString: [alarm activeSyncRepresentationInContext: context]];
}
// Recurrence rules
if ([self isRecurrent])
{
[s appendString: [[[self recurrenceRules] lastObject] activeSyncRepresentationInContext: context]];
}
// Comment
o = [self comment];
if ([o length])
{
o = [o activeSyncRepresentationInContext: context];
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];
[s appendFormat: @"<Truncated>%d</Truncated>", 0];
[s appendFormat: @"<Data>%@</Data>", o];
[s appendString: @"</Body>"];
}
[s appendFormat: @"<NativeBodyType xmlns=\"AirSyncBase:\">%d</NativeBodyType>", 1];
return s;
}
//
// To understand meeting requests/responses, see:
//
// http://blogs.msdn.com/b/exchangedev/archive/2011/07/22/working-with-meeting-requests-in-exchange-activesync.aspx
// http://blogs.msdn.com/b/exchangedev/archive/2011/07/29/working-with-meeting-responses-in-exchange-activesync.aspx
//
//
// Here is an example of a Sync call when sogo10 accepts an invitation from sogo3:
//
// <Change>
// <ServerId>2978-52EA9D00-1-A253E70.ics</ServerId>
// <ApplicationData>
// <TimeZone xmlns="Calendar:">LAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAIAAAAAAAAAxP///w==</TimeZone>
// <AllDayEvent xmlns="Calendar:">0</AllDayEvent>
// <StartTime xmlns="Calendar:">20140207T130000Z</StartTime>
// <EndTime xmlns="Calendar:">20140207T140000Z</EndTime>
// <DTStamp xmlns="Calendar:">20140130T185245Z</DTStamp>
// <Subject xmlns="Calendar:">test 8</Subject>
// <Sensitivity xmlns="Calendar:">0</Sensitivity>
// <Body xmlns="AirSyncBase:">
// <Type>1</Type>
// <Data/>
// </Body>
// <Organizer_Email xmlns="Calendar:">sogo3@example.com</Organizer_Email>
// <UID xmlns="Calendar:">2978-52EA9D00-1-A253E70</UID>
// <Attendees xmlns="Calendar:">
// <Attendee>
// <Attendee_Name>sogo10</Attendee_Name>
// <Attendee_Email>sogo10@example.com</Attendee_Email>
// <Attendee_Type>1</Attendee_Type>
// </Attendee>
// </Attendees>
// <BusyStatus xmlns="Calendar:">2</BusyStatus>
// <MeetingStatus xmlns="Calendar:">3</MeetingStatus>
// <Organizer_Name xmlns="Calendar:">Wolfgang Fritz</Organizer_Name>
// </ApplicationData>
// </Change>
//
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context
{
iCalDateTime *start, *end;
NSTimeZone *userTimeZone;
iCalTimeZone *tz;
id o;
NSInteger tzOffset;
BOOL isAllDay;
if ((o = [theValues objectForKey: @"UID"]))
[self setUid: o];
// FIXME: merge with iCalToDo
if ((o = [theValues objectForKey: @"Subject"]))
[self setSummary: o];
isAllDay = NO;
if ([[theValues objectForKey: @"AllDayEvent"] intValue])
{
isAllDay = YES;
}
//
// 0- free, 1- tentative, 2- busy and 3- out of office
//
if ((o = [theValues objectForKey: @"BusyStatus"]))
{
[o intValue];
}
//
//
//
if ((o = [theValues objectForKey: @"MeetingStatus"]))
{
[o intValue];
}
//
// 0- normal, 1- personal, 2- private and 3-confidential
//
if ((o = [theValues objectForKey: @"Sensitivy"]))
{
switch ([o intValue])
{
case 2:
[self setAccessClass: @"PRIVATE"];
break;
case 3:
[self setAccessClass: @"CONFIDENTIAL"];
break;
case 0:
case 1:
default:
[self setAccessClass: @"PUBLIC"];
}
}
if ((o = [theValues objectForKey: @"TimeZone"]))
{
// Ugh, we ignore it for now.
userTimeZone = [[[context activeUser] userDefaults] timeZone];
tz = [iCalTimeZone timeZoneForName: [userTimeZone name]];
[(iCalCalendar *) parent addTimeZone: tz];
}
// FIXME: merge with iCalToDo
if ((o = [[theValues objectForKey: @"Body"] objectForKey: @"Data"]))
[self setComment: o];
if ((o = [theValues objectForKey: @"Location"]))
[self setLocation: o];
if ((o = [theValues objectForKey: @"StartTime"]))
{
o = [o calendarDate];
start = (iCalDateTime *) [self uniqueChildWithTag: @"dtstart"];
[start setTimeZone: tz];
if (isAllDay)
{
tzOffset = [userTimeZone secondsFromGMTForDate: o];
o = [o dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: tzOffset];
[start setDate: o];
[start setTimeZone: nil];
}
else
{
tzOffset = [userTimeZone secondsFromGMTForDate: o];
o = [o dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: tzOffset];
[start setDateTime: o];
}
}
if ((o = [theValues objectForKey: @"EndTime"]))
{
o = [o calendarDate];
end = (iCalDateTime *) [self uniqueChildWithTag: @"dtend"];
[end setTimeZone: tz];
if (isAllDay)
{
tzOffset = [userTimeZone secondsFromGMTForDate: o];
o = [o dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: tzOffset];
[end setDate: o];
[end setTimeZone: nil];
}
else
{
tzOffset = [userTimeZone secondsFromGMTForDate: o];
o = [o dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: tzOffset];
[end setDateTime: o];
}
}
//
// If an alarm is deinfed with an action != DISPLAY, we ignore the alarm - don't want to overwrite.
//
if ([self hasAlarms] && [[[[self alarms] objectAtIndex: 0] action] caseInsensitiveCompare: @"DISPLAY"] != NSOrderedSame)
{
// Ignore the alarm for now
}
else if ((o = [theValues objectForKey: @"Reminder"]))
{
// 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)
//
// http://answers.microsoft.com/en-us/office/forum/office_2013_release-outlook/desktop-outlook-calendar-creates-entries-with/9aef72d8-81bb-4a32-a6ab-bf7d216fb811?page=5&tm=1395690285088
//
iCalAlarm *alarm;
alarm = [[iCalAlarm alloc] init];
[alarm takeActiveSyncValues: theValues inContext: context];
[self removeAllAlarms];
[self addToAlarms: alarm];
RELEASE(alarm);
}
else
{
// We remove existing alarm since no reminder in the ActiveSync payload
[self removeAllAlarms];
}
// Recurrence
if ((o = [theValues objectForKey: @"Recurrence"]))
{
iCalRecurrenceRule *rule;
rule = [[iCalRecurrenceRule alloc] init];
[self setRecurrenceRules: [NSArray arrayWithObject: rule]];
RELEASE(rule);
[rule takeActiveSyncValues: o inContext: context];
}
// Organizer - we don't touch the value unless we're the organizer
if ((o = [theValues objectForKey: @"Organizer_Email"]) &&
([self userIsOrganizer: [context activeUser]] || [[context activeUser] hasEmail: o]))
{
iCalPerson *person;
person = [iCalPerson elementWithTag: @"organizer"];
[person setEmail: o];
[person setCn: [theValues objectForKey: @"Organizer_Name"]];
[person setPartStat: @"ACCEPTED"];
[self setOrganizer: person];
}
// 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]])
{
if ((o = [theValues objectForKey: @"Attendees"]))
{
NSMutableArray *attendees;
NSDictionary *attendee;
iCalPerson *person;
int status, i;
attendees = [NSMutableArray array];
for (i = 0; i < [o count]; i++)
{
// Each attendee has is a dictionary similar to this:
// { "Attendee_Email" = "sogo3@example.com"; "Attendee_Name" = "Wolfgang Fritz"; "Attendee_Status" = 5; "Attendee_Type" = 1; }
attendee = [o objectAtIndex: i];
person = [iCalPerson elementWithTag: @"attendee"];
[person setCn: [attendee objectForKey: @"Attendee_Name"]];
[person setEmail: [attendee objectForKey: @"Attendee_Email"]];
status = [[attendee objectForKey: @"Attendee_Status"] intValue];
switch (status)
{
case 2:
[person setPartStat: @"TENTATIVE"];
break;
case 3:
[person setPartStat: @"ACCEPTED"];
break;
case 4:
[person setPartStat: @"DECLINED"];
break;
case 0:
case 5:
default:
[person setPartStat: @"NEEDS-ACTION"];
break;
}
// FIXME: handle Attendee_Type
[attendees addObject: person];
}
[self setAttendees: attendees];
}
}
}
@end
@@ -0,0 +1,48 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ICALRECURRENCERULEACTIVESYNC_H__
#define __ICALRECURRENCERULEACTIVESYNC_H__
#import <NGCards/iCalRecurrenceRule.h>
@class NSDictionary;
@class NSString;
@class WOContext;
@interface iCalRecurrenceRule (ActiveSync)
- (NSString *) activeSyncRepresentationInContext:(WOContext *) context;
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context;
@end
#endif
+372
View File
@@ -0,0 +1,372 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "iCalRecurrenceRule+ActiveSync.h"
#import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <NGCards/iCalEvent.h>
#import <NGCards/iCalByDayMask.h>
#import "NSCalendarDate+ActiveSync.h"
#import "NSDate+ActiveSync.h"
@implementation iCalRecurrenceRule (ActiveSync)
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
{
NSMutableString *s;
int type;
s = [NSMutableString string];
[s appendString: @"<Recurrence xmlns=\"Calendar:\">"];
// 0 -> daily, 1 -> weekly, 2 -> montly, 5 -> yearly
type = 0;
if ([self frequency] == iCalRecurrenceFrequenceDaily)
{
type = 0;
// 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=\"Calendar:\">%d</Recurrence_DayOfWeek>", (2|4|8|16|32)];
}
else
{
[s appendFormat: @"<Recurrence_Interval xmlns=\"Calendar:\">%d</Recurrence_Interval>", [self repeatInterval]];
}
}
else if ([self frequency] == iCalRecurrenceFrequenceWeekly)
{
iCalWeekOccurrences *occurrences;
int i, v;
type = 1;
occurrences = [[self byDayMask] weekDayOccurrences];
v = 0;
if (occurrences)
{
for (i = 0; i < 7; i++)
{
if (occurrences[0][i])
v += (1 << i);
}
}
else
{
// No byDayMask, we take the event's start date to compute the DayOfWeek
// 0 == Sunday, 6 == Saturday
v = (1 << [[[self parent] startDate] dayOfWeek]);
}
[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)
{
if ([[self byDay] length])
{
int firstOccurrence;
iCalByDayMask *dm;
type = 3; // recurs monthly on the nth day
dm = [self byDayMask];
firstOccurrence = [dayMask firstOccurrence];
// Handle the case for "Last day of the month"
if (firstOccurrence < 0)
firstOccurrence = 5;
[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])
{
NSArray *days;
type = 2; // recurs monthly
days = [self byMonthDay];
if ([days count] > 0 && [[days objectAtIndex: 0] intValue] < 0)
{
// Last day of the month
iCalByDayMask *dm;
dm = [self byDayMask];
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"Calendar:\">%d</Recurrence_DayOfWeek>", (1 << [dm firstDay])];
[s appendFormat: @"<Recurrence_WeekOfMonth xmlns=\"Calendar:\">%d</Recurrence_WeekOfMonth>", 5];
}
else
{
// Unsupported rule in ActiveSync/Outlook. Rule that says "Repeat on the 7th and 8th of each month".
// FIXME
}
}
else
{
// Simple reccurrence rule of type "Monthly"
type = 2;
[s appendFormat: @"<Recurrence_DayOfMonth xmlns=\"Calendar:\">%d</Recurrence_DayOfMonth>",
[[[self parent] startDate] dayOfMonth]];
}
}
else if ([self frequency] == iCalRecurrenceFrequenceYearly)
{
type = 6; // Yearly on the nth day
if ([[self flattenedValuesForKey: @"bymonth"] length])
{
if ([[self byDay] length])
{
int firstOccurrence;
iCalByDayMask *dm;
dm = [self byDayMask];
firstOccurrence = [dm firstOccurrence];
if (firstOccurrence < 0)
firstOccurrence = 5;
[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=\"Calendar:\">%@</Recurrence_DayOfMonth>",
[self flattenedValuesForKey: @"bymonthday"]];
[s appendFormat: @"<Recurrence_MonthOfYear xmlns=\"Calendar:\">%@</Recurrence_MonthOfYear>",
[self flattenedValuesForKey: @"bymonth"]];
}
}
else
type = 5;
}
[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=\"Calendar:\">%@</Recurrence_Occurrences>",
[self flattenedValuesForKey: @"count"]];
}
else if ([self untilDate])
{
NSCalendarDate *date;
date = [self untilDate];
//ud = [[context activeUser] userDefaults];
//[date setTimeZone: [ud timeZone]];
[s appendFormat: @"<Recurrence_Until xmlns=\"Calendar:\">%@</Recurrence_Until>",
[date activeSyncRepresentationWithoutSeparatorsInContext: context]];
}
[s appendString: @"</Recurrence>"];
return s;
}
//
//
//
- (void) _setByDayFromValues: (NSDictionary *) theValues
{
NSString *day;
id o;
unsigned int day_of_week;
int i, week_of_month;
o = [theValues objectForKey: @"Recurrence_DayOfWeek"];
// The documentation says WeekOfMonth must be between 1 and 5. The value
// 5 means "last week of month"
week_of_month = [[theValues objectForKey: @"Recurrence_WeekOfMonth"] intValue];
if (week_of_month > 4)
week_of_month = -1;
// We find the correct day of the week
day_of_week = [o intValue];
for (i = 0; i < 7; i++)
{
if ((1<<i) == day_of_week)
{
day_of_week = i;
break;
}
}
day = [self iCalRepresentationForWeekDay: i];
[self setSingleValue: [NSString stringWithFormat: @"%d%@",
week_of_month, day]
forKey: @"byday"];
}
- (void) _setByMonthFromValues: (NSDictionary *) theValues
{
unsigned int month_of_year;
month_of_year = [[theValues objectForKey: @"Recurrence_MonthOfYear"] intValue];
[self setSingleValue: [NSString stringWithFormat: @"%d", month_of_year]
forKey: @"bymonth"];
}
//
//
//
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context
{
id o;
int recurrenceType;
recurrenceType = [[theValues objectForKey: @"Recurrence_Type"] intValue];
if ((o = [theValues objectForKey: @"Recurrence_Interval"]))
{
[self setRepeatInterval: [o intValue]];
}
else
[self setRepeatInterval: 1];
switch (recurrenceType)
{
//
// Daily
//
case 0:
[self setFrequency: iCalRecurrenceFrequenceDaily];
// Every weekday
if ((o = [theValues objectForKey: @"Recurrence_DayOfWeek"]))
{
[self setByDayMask: [iCalByDayMask byDayMaskWithWeekDays]];
}
break;
//
// Weekly
//
case 1:
[self setFrequency: iCalRecurrenceFrequenceWeekly];
// 42 == Every Monday, Wednesday and Friday, for example
if ((o = [theValues objectForKey: @"Recurrence_DayOfWeek"]))
{
iCalWeekOccurrences days;
unsigned int i, v;
memset(days, 0, 7 * sizeof(iCalWeekOccurrence));
v = [o intValue];
for (i = 0; i < 7; i++)
{
if (v & (1<<i))
days[i] = iCalWeekOccurrenceAll;
}
[self setByDayMask: [iCalByDayMask byDayMaskWithDays: days]];
}
break;
//
// Montly
//
case 2:
case 3:
[self setFrequency: iCalRecurrenceFrequenceMonthly];
// The 5th of every X month(s)
if ((o = [theValues objectForKey: @"Recurrence_DayOfMonth"]))
{
[self setValues: [NSArray arrayWithObject: o]
atIndex: 0 forKey: @"bymonthday"];
}
// The 3rd Thursay every X month(s)
else if ((o = [theValues objectForKey: @"Recurrence_DayOfWeek"]))
{
[self _setByDayFromValues: theValues];
}
break;
//
// Yearly
//
case 5:
case 6:
default:
[self setFrequency: iCalRecurrenceFrequenceYearly];
// On April 19th
if ((o = [theValues objectForKey: @"Recurrence_DayOfMonth"]))
{
[self setValues: [NSArray arrayWithObject: o] atIndex: 0
forKey: @"bymonthday"];
[self _setByMonthFromValues: theValues];
}
else
{
// On the Second Wednesday of April
[self _setByDayFromValues: theValues];
[self _setByMonthFromValues: theValues];
}
break;
}
if ((o = [theValues objectForKey: @"Recurrence_Occurrences"]))
{
[self setRepeatCount: [o intValue]];
}
else if ((o = [theValues objectForKey: @"Recurrence_Until"]))
{
[self setUntilDate: [o calendarDate]];
}
}
@end
+44
View File
@@ -0,0 +1,44 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ICALTIMEZONEACTIVESYNC_H__
#define __ICALTIMEZONEACTIVESYNC_H__
#import <NGCards/iCalTimeZone.h>
@class NSString;
@class WOContext;
@interface iCalTimeZone (ActiveSync)
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
@end
#endif
+165
View File
@@ -0,0 +1,165 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "iCalTimeZone+ActiveSync.h"
#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"
struct SYSTEMTIME {
uint16_t wYear;
uint16_t wMonth;
uint16_t wDayOfWeek;
uint16_t wDay;
uint16_t wHour;
uint16_t wMinute;
uint16_t wSecond;
uint16_t wMilliseconds;
};
@interface iCalTimeZonePeriod (ActiveSync)
- (void) _fillTZDate: (struct SYSTEMTIME *) tzData;
@end
@implementation iCalTimeZonePeriod (ActiveSync)
//
// FIXME - combine with iCalTimeZone+MAPIStore.m
//
- (void) _fillTZDate: (struct SYSTEMTIME *) tzData
{
iCalRecurrenceRule *rrule;
NSArray *byMonth;
iCalByDayMask *mask;
NSCalendarDate *dateValue;
rrule = [self recurrenceRule];
byMonth = [rrule byMonth];
if ([byMonth count] > 0)
{
tzData->wMonth = [[byMonth objectAtIndex: 0] intValue];
mask = [rrule byDayMask];
tzData->wDayOfWeek = [mask firstDay];
tzData->wDay = [mask firstOccurrence];
dateValue = [self startDate];
tzData->wHour = [dateValue hourOfDay];
tzData->wMinute = [dateValue minuteOfHour];
tzData->wSecond = [dateValue secondOfMinute];
}
}
@end
@implementation iCalTimeZone (ActiveSync)
//
// FIXME - combine with iCalTimeZone+MAPIStore.m
//
- (iCalTimeZonePeriod *) _mostRecentPeriodWithName: (NSString *) periodName
{
NSArray *periods;
iCalTimeZonePeriod *period;
NSUInteger max;
periods = [self childrenWithTag: periodName];
max = [periods count];
if (max > 0)
{
periods = [periods sortedArrayUsingSelector: @selector (compare:)];
period = (iCalTimeZonePeriod *) [periods objectAtIndex: (max - 1)];
}
else
period = nil;
return period;
}
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
{
iCalTimeZonePeriod *period;
NSMutableData *bytes;
uint32_t lBias;
uint32_t lStandardBias;
uint32_t lDaylightBias;
//uint16_t wStandardYear;
struct SYSTEMTIME stStandardDate;
//uint16_t wDaylightYear;
struct SYSTEMTIME stDaylightDate;
char standardName[64], daylightName[64];
bytes = [NSMutableData data];
memset(standardName, 0, 64);
memset(daylightName, 0, 64);
lStandardBias = 0;
period = [self _mostRecentPeriodWithName: @"STANDARD"];
lBias = -[period secondsOffsetFromGMT] / 60;
[period _fillTZDate: &stStandardDate];
period = [self _mostRecentPeriodWithName: @"DAYLIGHT"];
if (!period)
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];
[bytes appendBytes: standardName length: 64];
[bytes appendBytes: &stStandardDate length: 16];
[bytes appendBytes: &lStandardBias length: 4];
[bytes appendBytes: daylightName length: 64];
[bytes appendBytes: &stDaylightDate length: 16];
[bytes appendBytes: &lDaylightBias length: 4];
return [bytes activeSyncRepresentationInContext: context];
}
@end
+46
View File
@@ -0,0 +1,46 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ICALTODOACTIVESYNC_H__
#define __ICALTODOACTIVESYNC_H__
#import <NGCards/iCalToDo.h>
@class NSString;
@class WOContext;
@interface iCalToDo (ActiveSync)
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context;
@end
#endif
+192
View File
@@ -0,0 +1,192 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
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 <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserDefaults.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalDateTime.h>
#import <NGCards/iCalTimeZone.h>
#include "NSDate+ActiveSync.h"
#include "NSString+ActiveSync.h"
@implementation iCalToDo (ActiveSync)
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
{
NSMutableString *s;
id o;
int v;
s = [NSMutableString string];
// Complete
o = [self completed];
[s appendFormat: @"<Complete xmlns=\"Tasks:\">%d</Complete>", (o ? 1 : 0)];
// DateCompleted
if (o)
[s appendFormat: @"<DateCompleted xmlns=\"Tasks:\">%@</DateCompleted>", [o activeSyncRepresentationInContext: context]];
// Start date
if ((o = [self startDate]))
{
[s appendFormat: @"<StartDate xmlns=\"Tasks:\">%@</StartDate>", [o activeSyncRepresentationInContext: context]];
[s appendFormat: @"<UTCStartDate xmlns=\"Tasks:\">%@</UTCStartDate>", [o activeSyncRepresentationInContext: context]];
}
// Due date
if ((o = [self due]))
{
[s appendFormat: @"<DueDate xmlns=\"Tasks:\">%@</DueDate>", [o activeSyncRepresentationInContext: context]];
[s appendFormat: @"<UTCDueDate xmlns=\"Tasks:\">%@</UTCDueDate>", [o activeSyncRepresentationInContext: context]];
}
// Importance
o = [self priority];
if ([o isEqualToString: @"9"])
v = 0;
else if ([o isEqualToString: @"1"])
v = 2;
else
v = 1;
[s appendFormat: @"<Importance xmlns=\"Tasks:\">%d</Importance>", v];
// Reminder - FIXME
[s appendFormat: @"<ReminderSet xmlns=\"Tasks:\">%d</ReminderSet>", 0];
// Sensitivity - FIXME
[s appendFormat: @"<Sensitivity xmlns=\"Tasks:\">%d</Sensitivity>", 0];
// Subject
o = [self summary];
if ([o length])
[s appendFormat: @"<Subject xmlns=\"Tasks:\">%@</Subject>", [[self summary] activeSyncRepresentationInContext: context]];
if ((o = [self comment]))
{
o = [o activeSyncRepresentationInContext: context];
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];
[s appendFormat: @"<Truncated>%d</Truncated>", 0];
[s appendFormat: @"<Data>%@</Data>", o];
[s appendString: @"</Body>"];
}
return s;
}
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context
{
NSTimeZone *userTimeZone;
iCalTimeZone *tz;
id o;
NSInteger tzOffset;
userTimeZone = [[[context activeUser] userDefaults] timeZone];
tz = [iCalTimeZone timeZoneForName: [userTimeZone name]];
[(iCalCalendar *) parent addTimeZone: tz];
// FIXME: merge with iCalEvent
if ((o = [theValues objectForKey: @"Subject"]))
[self setSummary: o];
// FIXME: merge with iCalEvent
if ((o = [[theValues objectForKey: @"Body"] objectForKey: @"Data"]))
[self setComment: o];
if ([[theValues objectForKey: @"Complete"] intValue] &&
((o = [theValues objectForKey: @"DateCompleted"])) )
{
iCalDateTime *completed;
o = [o calendarDate];
completed = (iCalDateTime *) [self uniqueChildWithTag: @"completed"];
//tzOffset = [[o timeZone] secondsFromGMTForDate: o];
//o = [o dateByAddingYears: 0 months: 0 days: 0
// hours: 0 minutes: 0
// seconds: -tzOffset];
[completed setDate: o];
[self setStatus: @"COMPLETED"];
}
if ((o = [theValues objectForKey: @"DueDate"]))
{
iCalDateTime *due;
o = [o calendarDate];
due = (iCalDateTime *) [self uniqueChildWithTag: @"due"];
[due setTimeZone: tz];
tzOffset = [userTimeZone secondsFromGMTForDate: o];
o = [o dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: tzOffset];
[due setDateTime: o];
}
// 2 == high, 1 == normal, 0 == low
if ((o = [theValues objectForKey: @"Importance"]))
{
if ([o intValue] == 2)
[self setPriority: @"1"];
else if ([o intValue] == 1)
[self setPriority: @"5"];
else
[self setPriority: @"9"];
}
if ((o = [theValues objectForKey: @"ReminderTime"]))
{
}
}
@end
+3
View File
@@ -0,0 +1,3 @@
{
requires = ( MAIN, Appointments, Contacts, Mailer );
}
+49 -1
View File
@@ -1,4 +1,52 @@
# use *:8843 for SSL
#
#
# Keep only one of those vhost definition, comment out the other one
#
#
# for https
# don't forget to add a Listen parameter for port 8843:
# Listen 8843
<VirtualHost *:8843>
ServerName YOUR.SERVER.NAME
SSLEngine on
SSLProtocol -ALL +SSLv3 +TLSv1
SSLHonorCipherOrder On
SSLCipherSuite HIGH:MEDIUM:!ADH:!aNULL:!eNULL:!NULL
SSLCertificateFile /path/to/your/cert/cert.pem
SSLCertificateChainFile /path/to/your/cert/cert-chain-file.pem
SSLCertificateKeyFile /path/to/your/key/file.key
RewriteEngine Off
ProxyRequests Off
SetEnv proxy-nokeepalive 1
ProxyPreserveHost On
ProxyPassInterpolateEnv On
ProxyPass /principals http://127.0.0.1:20000/SOGo/dav/ interpolate
ProxyPass /SOGo http://127.0.0.1:20000/SOGo interpolate
ProxyPass / http://127.0.0.1:20000/SOGo/dav/ interpolate
<Location />
Order allow,deny
Allow from all
</Location>
<Proxy http://127.0.0.1:20000>
RequestHeader set "x-webobjects-server-port" "8843"
RequestHeader set "x-webobjects-server-name" "CHANGETHIS:8843"
RequestHeader set "x-webobjects-server-url" "http://CHANGETHIS:8843"
RequestHeader set "x-webobjects-server-protocol" "HTTP/1.0"
AddDefaultCharset UTF-8
</Proxy>
ErrorLog /var/log/apache2/ab-error.log
CustomLog /var/log/apache2/ab-access.log combined
</VirtualHost>
# plain http
# Same here, don't forget to add a Listen parameter for port 8800:
# Listen 8800
<VirtualHost *:8800>
RewriteEngine Off
ProxyRequests Off
+14 -6
View File
@@ -2,8 +2,6 @@ Alias /SOGo.woa/WebServerResources/ \
/usr/lib/GNUstep/SOGo/WebServerResources/
Alias /SOGo/WebServerResources/ \
/usr/lib/GNUstep/SOGo/WebServerResources/
AliasMatch /SOGo/so/ControlPanel/Products/(.*)/Resources/(.*) \
/usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2
<Directory /usr/lib/GNUstep/SOGo/>
AllowOverride None
@@ -18,10 +16,6 @@ AliasMatch /SOGo/so/ControlPanel/Products/(.*)/Resources/(.*) \
</IfModule>
</Directory>
<LocationMatch "^/SOGo/so/ControlPanel/Products/.*UI/Resources/.*\.(jpg|png|gif|css|js)">
SetHandler default-handler
</LocationMatch>
## Uncomment the following to enable proxy-side authentication, you will then
## need to set the "SOGoTrustProxyAuthentication" SOGo user default to YES and
## adjust the "x-webobjects-remote-user" proxy header in the "Proxy" section
@@ -48,6 +42,14 @@ ProxyPreserveHost On
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.
#
#ProxyPass /Microsoft-Server-ActiveSync \
# http://127.0.0.1:20000/SOGo/Microsoft-Server-ActiveSync \
# retry=60 connectiontimeout=5 timeout=360
<Proxy http://127.0.0.1:20000/SOGo>
## adjust the following to your configuration
RequestHeader set "x-webobjects-server-port" "443"
@@ -66,3 +68,9 @@ ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0
Allow from all
</Proxy>
# For Apple autoconfiguration
<IfModule rewrite_module>
RewriteEngine On
RewriteRule ^/.well-known/caldav/?$ /SOGo/dav [R=301]
</IfModule>
+6204
View File
File diff suppressed because it is too large. Load diff
Binary file not shown.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 433 KiB

After

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 768 KiB

After

Width:  |  Height:  |  Size: 311 KiB

+1 -3
View File
@@ -1,8 +1,6 @@
/* SOGo+DAV.m - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* 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
+1 -1
View File
@@ -1,5 +1,5 @@
/*
Copyright (C) 2005-2011 Inverse inc.
Copyright (C) 2005-2014 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of SOGo
+280 -6
View File
@@ -1,16 +1,290 @@
2.2.5 (2014-06-05)
------------------
Enhancements
- new meta tag to tell IE to use the highest mode available
- updated Dutch, Finnish, German, and Polish translations
Bug fixes
- avoid crashing when we forward an email with no Subject header
- we no longer try to include attachments when replying to a mail
- fixed ActiveSync repetitive events issues with "Weekly" and "Monthly" ones
- fixed ActiveSync text/plain parts re-encoding issues for Outlook
2.2.4 (2014-05-29)
------------------
New features
- new print option in Calendar module
- now able to save unknown recipient emails to address book on send (#1496)
Enhancements
- Sieve folder encoding is now configurable (#2622)
- SOGo version is now displayed in preferences window (#2612)
- report Sieve error when saving preferences (#1046)
- added the SOGoMaximumSyncWindowSize system default to overwrite the
maximum number of items returned during an ActiveSync sync operation
- updated datepicker
- addressbooks properties are now accessible from a popup window
- extended events and tasks searches
- updated Czech, French, Hungarian, Polish, Russian, Slovak, Spanish (Argentina), and Spanish (Spain) translations
- added more sycned contact properties when using ActiveSync (#2775)
- now possible to configure the default subscribed resource name using SOGoSubscriptionFolderFormat
- now handle server-side folder updates using ActiveSync (#2688)
- updated CKEditor to version 4.4.1
Bug fixes
- fixed saved HTML content of draft when attaching a file
- fixed text nodes of HTML content handler by encoding HTML entities
- fixed iCal7 delegation issue with the "inbox" folder (#2489)
- fixed birth date validity checks (#1636)
- fixed URL handling (#2616)
- improved folder rename operations using ActiveSync (#2700)
- fixed SmartReply/Forward when ReplaceMime was omitted (#2680)
- fixed wrong generation of weekly repetitive events with ActiveSync (#2654)
- fixed incorrect XML data conversion with ActiveSync (#2695)
- fixed display of events having a category with HTML entities (#2703)
- fixed display of images in CSS background (#2437)
- fixed limitation of Sieve script size (#2745)
- fixed sync-token generation when no change was returned (#2492)
- fixed the IMAP copy/move operation between subfolders in different accounts
- fixed synchronization of seen/unseen status of msgs in Webmail (#2715)
- fixed focus of popup windows open through a contextual menu with Firefox on Windows 7
- fixed missing characters in shared folder names over ActiveSync (#2709)
- fixed reply and forward mail templates for Brazilian Portuguese (#2738)
- fixed newline in signature when forwarding a message as attachment in HTML mode (#2787)
- fixed restoration of options (priority & return receipt) when editing a draft (#193)
- fixed update of participation status via CalDAV (#2786)
2.2.3 (2014-04-03)
------------------
Enhancements
- updated Dutch, Hungarian, Russian and Spanish (Argentina) translations
- initial support for ActiveSync event reminders support (#2681)
- updated CKEditor to version 4.3.4
Bug fixes
- fixed possible exception when retrieving the default event reminder value on 64bit architectures (#2678)
- fixed calling unescapeHTML on null variables to avoid JavaScript exceptions in Contacts module
- fixed detection of IMAP flags support on the client side (#2664)
- fixed the ActiveSync issue marking all mails as read when downloading them
- fixed ActiveSync's move operations not working for multiple selections (#2691)
- fixed email validation regexp to allow gTLDs
- improved all-day events support for ActiveSync (#2686)
2.2.2 (2014-03-21)
------------------
Enhancements
- updated French, Finnish, German and Spanish (Spain) translations
- added sanitization support for Outlook/ActiveSync to circumvent Outlook bugs (#2667)
- updated CKEditor to version 4.3.3
- updated jQuery File Upload to version 9.5.7
Bug fixes
- fixed possible exception when retrieving the default event reminder value on 64bit architectures (#2647, #2648)
- disable file paste support in mail editor (#2641)
- fixed copying/moving messages to a mail folder begining with a digit (#2658)
- fixed unseen count for folders beginning with a digit and used in Sieve filters (#2652)
- fixed decoding of HTML entities in reminder alerts (#2659)
- fixed check for resource conflict when creating an event in the resource's calendar (#2541)
- fixed construction of mail folders tree
- fixed parsing of ORG attribute in cards (#2662)
- disabled ActiveSync provisioning for now (#2663)
- fixed messages move in Outlook which would create duplicates (#2650)
- fixed translations for OtherUsersFolderName and SharedFoldersName folders (#2657)
- fixed handling of accentuated characters when filtering contacts (#2656)
- fixed classification icon of events (#2651)
- fixed ActiveSync's SendMail with client version <= 12.1 (#2669)
2.2.1 (2014-03-07)
------------------
Enhancements
- updated Czech, Dutch, Finnish, and Hungarian translations
- show current folder name in prompt dialog when renaming a mail folder
Bug fixes
- fixed an issue with ActiveSync when the number of messages in the mailbox was greater than the window-size specified by the client
- fixed sogo-tool operations on Sieve script (#2617)
- fixed unsubscription when renaming an IMAP folder (#2630)
- fixed sorting of events list by calendar name (#2629)
- fixed wrong date format leading to Android email syncing issues (#2609)
- fixed possible exception when retrieving the default event reminder value (#2624)
- fixed encoding of mail folder name when creating a subfolder (#2637)
- fixed returned date format for email messages in ActiveSync
- fixed missing 'name part' in address for email messages in ActiveSync
- fixed race condition when syncing huge amount of deleted messages over ActiveSync
- fixed encoding of string as CSS identifier when the string starts with a digit
- fixed auto-completion popupmenu when UID is a digit
2.2.0 (2014-02-24)
------------------
New features
- initial implementation of Microsoft ActiveSync protocol
- it's now possible to set a default reminder for calendar components
using SOGoCalendarDefaultReminder
- select multiple files to attach to a message or drag'n'drop files onto the
mail editor; will also now display progress of uploads
- new popup menu to download all attachments of a mail
- move & copy messages between different accounts
- support for the Sieve 'body' extension (mail filter based on the body content)
Enhancements
- we now automatically convert <img src=data...> into file attachments
using CIDs to prevent Outlook issues
- updated French, Finnish, Polish, German, Russian, and Spanish (Spain) translations
- XMLHttpRequest.js is now loaded conditionaly (< IE9)
- format time in attendees invitation window according to the user's locale
- improved IE11 support
- respect signature placement when forwarding a message
- respect Sieve server capabilities
- encode messages in quoted-printable when content is bigger than 72 bytes
- we now use binary encoding in memcached (#2587)
- warn user when overbooking a resource by creating an event in its calendar (#2541)
- converted JavaScript alerts to inline CSS dialogs in appointment editor
- visually identify users with no freebusy information in autocompletion widget of attendees editor (#2565)
- respect occurences of recurrent events when deleting selected events (#1950)
- improved confirmation dialog box when deleting events and tasks
- moved the DN cache to SOGoCache - avoiding sogod restarts after RDN operations
- don't use the HTML editor with Internet Explorer 7
- add message-id header to appointment notifications (#2535)
- detect URLs in popup of events
- improved display of a contact (#2350)
Bug fixes
- don't load 'background' attribute (#2437)
- fixed validation of subscribed folders (#2583)
- fixed display of folder names in messages filter editor (#2569)
- fixed contextual menu of the current calendar view (#2557)
- fixed handling of the '=' character in cards/events/tasks (#2505)
- simplify searches in the address book (#2187)
- warn user when dnd failed because of a resource conflict (#1613)
- respect the maximum number of bookings when viewing the freebusy information of a resource (#2560)
- encode HTML entities when forwarding an HTML message inline in plain text composition mode (#2411)
- encode HTML entities in JSON data (#2598)
- fixed handling of ACLs on shared calendars with multiple groups (#1854)
- fixed HTML formatting of appointment notifications for Outlook (#2233)
- replace slashes by dashes in filenames of attachments to avoid a 404 return code (#2537)
- avoid over-using LDAP connections when decomposing groups
- fixed display of a contact's birthday when not defined (#2503)
- fixed JavaScript error when switching views in calendar module (#2613)
2.1.1b (2013-12-04)
-------------------
Enhancements
- updated CKEditor to version 4.3.0 and added tab module
Bug fixes
- HTML formatting is now retained when forwarding/replying to a mail using the HTML editor
- put the text part before the HTML part when composing mail to fix a display issue with Thunderbird (#2512)
2.1.1a (2013-11-22)
-------------------
Bug fixes
- fixed Sieve filters editor (#2504)
- moved missing translation to UI/Common (#2499)
- fixed potential crasher in OpenChange
2.1.1 (2013-11-19)
------------------
New features
- creation and modification of mail labels
Enhancements
- the color picker is no longer a popup window
Bug fixes
- fixed utf8 character handling in special folder names
Special folder names can now be set as UTF8 or modified UTF7 in sogo.conf
- fixed reply-to header not being set for auxiliary IMAP accounts
- fixed handling of broken/invalid email addresses
2.1.0 (2013-11-07)
------------------
Enhancements
- improved order of user rights in calendar module (#1431)
- increased height of alarm editor when email alarms are enabled
- added SMTP AUTH support for sogo-ealarms-notify
- added support for LDAP password change against AD/Samba4
- added Apache configuration for Apple autoconfiguration (#2248)
- the init scripts now start 3 sogod processes by default instead of 1
- SOGo now also sends a plain/text parts when sending HTML mails (#2217)
- SOGo now listens on 127.0.0.1:20000 by default (instead of *:20000)
- SOGo new uses the latest WebDAV sync response type (#1275)
- updated CKEditor to version 4.2.2 and added the tables-related modules (#2410)
- improved display of vEvents in messages
Bug fixes
- fixed handling of an incomplete attachment filename (#2385)
- fixed Finnish mail reply/forward templates (#2401)
- fixed position of red line of current time (#2373)
- fixed crontab error (#2372)
- avoid using too many LDAP connections while looping through LDAP results
- don't encode HTML entities in mail subject of notification (#2402)
- fixed crash of Samba when sending an invitation (#2398)
- fixed selection of destination calendar when saving a task or an event (#2353)
- fixed "display remote images" preference for message in a popup (#2417)
- avoid crash when handling malformed or non-ASCII HTTP credentials (#2358)
- fixed crash in DAV free-busy lookups when using SQL addressbooks (#2418)
- disabled verbose logging of SMTP sessions by default
- fixed high CPU usage when there are no available child processes and added logging when such a condition occurs
- fixed memory consumption issues when doing dav lookups with huge result set
- fixed S/MIME verification issues with certain OpenSSL versions
- worked around an issue with chunked encoding of CAS replies (#2408)
- fixed OpenChange corruption issue regarding predecessors change list (#2405)
- avoid unnecessary UTF-7 conversions (#2318)
- improved RTF parser to fix vCards (#2354)
- fixed definition of the COMPLETED attribute of vTODO (#2240)
- fixed DAV:resource-id property when sharing calendars (#2399)
- fixed reload of multiple external web calendars (#2221)
- fixed display of PDF files sent from Thunderbird (#2270)
- fixed TLS support for IMAP (#2386)
- fixed creation of web calendar when added using sogo-tool (#2007)
- avoid crash when parsing HTML tags of a message (#2434)
- fixed handling of LDAP groups with no email address (#1328)
- fixed encoding of messages with non-ASCII characters (#2459)
- fixed compilation with clang 3.2 (#2235)
- truncated long fields of quick records to avoid an SQL error (#2461)
- fixed IMAP ACLs (#2433)
- removed inline JavaScript when viewing HTML messages (#2468)
2.0.7 (2013-07-19)
------------------
New features
- print gridlines of calendar in 15-minute intervals
- allow the events/tasks lists to be collapsable
Enhancements
- bubble box of events no longer overlaps the current event
- now pass the x-originating-ip using the IMAP ID extension (#2366)
- updated BrazilianPortuguese, Czech, Dutch, German, Polish and Russian translations
Bug fixes
- properly handle RFC2231 everywhere
- fixed minor XSS issues
- fixed jquery-ui not bluring the active element when clicking on a draggable
2.0.6b (2013-06-27)
------------------
Bug fixes
- Properly escape the foldername to avoid XSS issues
- Fix loading of MSExchangeFreeBusySOAPResponseMap
- properly escape the foldername to avoid XSS issues
- fixed loading of MSExchangeFreeBusySOAPResponseMap
2.0.6a (2013-06-25)
------------------
Bug fixes
- Documentation fixes
- Added missing file for CAS single logout
- documentation fixes
- added missing file for CAS single logout
2.0.6 (2013-06-21)
------------------
@@ -41,8 +315,8 @@ Bug fixes
------------------
Bug fixes
- Fixed an issue when parsing user CN with leading or trailing spaces (#2287)
- Fixed a crash that occured when saving contacts or tasks via Outlook
- fixed an issue when parsing user CN with leading or trailing spaces (#2287)
- fixed a crash that occured when saving contacts or tasks via Outlook
2.0.5 (2013-04-11)
------------------
+3 -3
View File
@@ -76,7 +76,7 @@
},
{
columnName = c_participants;
sqlType = "VARCHAR(1000000)";
sqlType = "TEXT";
allowsNull = YES;
},
{
@@ -91,7 +91,7 @@
},
{
columnName = c_cycleinfo;
sqlType = "VARCHAR(1000000)";
sqlType = "TEXT";
allowsNull = YES;
},
{
@@ -126,7 +126,7 @@
},
{
columnName = c_partmails;
sqlType = "VARCHAR(100000)";
sqlType = "TEXT";
allowsNull = YES;
},
{
+1 -11
View File
@@ -46,11 +46,8 @@ $(SOGOBACKEND)_OBJC_FILES += \
MAPIStoreSamDBUtils.m \
MAPIStoreUserContext.m \
\
SOGoMAPIObject.m \
\
SOGoMAPIDBObject.m \
SOGoMAPIDBMessage.m \
SOGoMAPIDBFolder.m \
SOGoCacheGCSObject+MAPIStore.m \
\
MAPIStoreAppointmentWrapper.m \
MAPIStoreAttachment.m \
@@ -123,13 +120,6 @@ $(SOGOBACKEND)_OBJC_FILES += \
iCalEvent+MAPIStore.m \
iCalTimeZone+MAPIStore.m \
\
GCSSpecialQueries+OpenChange.m\
\
EOQualifier+MAPI.m \
\
EOBitmaskQualifier.m \
\
BSONCodec.m \
RTFHandler.m
+3
View File
@@ -3,3 +3,6 @@ all:: MAPIStorePropertySelectors.m MAPIStorePropertySelectors.h
MAPIStorePropertySelectors.m MAPIStorePropertySelectors.h: gen-property-selectors.py code-MAPIStorePropertySelectors.m code-MAPIStorePropertySelectors.h
@echo " Auto-generating MAPIStorePropertySelectors.[hm]..."
@$(PYTHON) ./gen-property-selectors.py -o MAPIStorePropertySelectors $(LIBMAPISTORE_CFLAGS)
distclean clean::
-rm -f MAPIStorePropertySelectors.m MAPIStorePropertySelectors.h
+6 -8
View File
@@ -1,8 +1,6 @@
/* MAPIStoreDBBaseContext.m - this file is part of SOGo
*
* Copyright (C) 2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2012-2014 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
@@ -32,7 +30,7 @@
#import "MAPIStoreDBFolder.h"
#import "MAPIStoreMapping.h"
#import "MAPIStoreUserContext.h"
#import "SOGoMAPIDBFolder.h"
#import <SOGo/SOGoCacheGCSFolder.h>
#import "MAPIStoreDBBaseContext.h"
@@ -60,7 +58,7 @@ static Class MAPIStoreDBFolderK;
- (void) ensureContextFolder
{
SOGoMAPIDBFolder *currentFolder;
SOGoCacheGCSFolder *currentFolder;
NSArray *parts;
NSMutableArray *folders;
NSString *folderName;
@@ -78,7 +76,7 @@ static Class MAPIStoreDBFolderK;
folderName = [parts objectAtIndex: count];
if ([folderName length] > 0)
{
currentFolder = [SOGoMAPIDBFolder objectWithName: folderName
currentFolder = [SOGoCacheGCSFolder objectWithName: folderName
inContainer: currentFolder];
[folders addObject: currentFolder];
}
@@ -98,11 +96,11 @@ static Class MAPIStoreDBFolderK;
- (id) rootSOGoFolder
{
SOGoMAPIDBFolder *folder;
SOGoCacheGCSFolder *folder;
[userContext ensureFolderTableExists];
folder = [SOGoMAPIDBFolder objectWithName: [isa MAPIModuleName]
folder = [SOGoCacheGCSFolder objectWithName: [isa MAPIModuleName]
inContainer: nil];
[folder setTableUrl: [userContext folderTableURL]];
// [folder reloadIfNeeded];
+9 -9
View File
@@ -32,7 +32,7 @@
#import <EOControl/EOQualifier.h>
#import <SOGo/SOGoFolder.h>
#import <SOGo/SOGoUser.h>
#import "EOQualifier+MAPI.h"
#import <SOGo/EOQualifier+SOGoCacheObject.h>
#import "MAPIStoreContext.h"
#import "MAPIStoreDBFolderTable.h"
#import "MAPIStoreDBMessage.h"
@@ -40,7 +40,7 @@
#import "MAPIStoreMapping.h"
#import "MAPIStoreTypes.h"
#import "MAPIStoreUserContext.h"
#import "SOGoMAPIDBFolder.h"
#import <SOGo/SOGoCacheGCSFolder.h>
#import "SOGoMAPIDBMessage.h"
#import "MAPIStoreDBFolder.h"
@@ -49,7 +49,7 @@
#include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h>
static Class EOKeyValueQualifierK, SOGoMAPIDBFolderK, MAPIStoreDBFolderK;
static Class EOKeyValueQualifierK, SOGoCacheGCSFolderK, MAPIStoreDBFolderK;
static NSString *MAPIStoreRightReadItems = @"RightsReadItems";
static NSString *MAPIStoreRightCreateItems = @"RightsCreateItems";
@@ -66,7 +66,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
+ (void) initialize
{
EOKeyValueQualifierK = [EOKeyValueQualifier class];
SOGoMAPIDBFolderK = [SOGoMAPIDBFolder class];
SOGoCacheGCSFolderK = [SOGoCacheGCSFolder class];
MAPIStoreDBFolderK = [MAPIStoreDBFolder class];
}
@@ -92,7 +92,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
{
enum mapistore_error rc;
NSString *folderName, *nameInContainer;
SOGoMAPIDBFolder *newFolder;
SOGoCacheGCSFolder *newFolder;
struct SPropValue *value;
value = get_SPropValue_SRow (aRow, PidTagDisplayName);
@@ -111,7 +111,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
{
nameInContainer = [NSString stringWithFormat: @"0x%.16"PRIx64,
(unsigned long long) newFID];
newFolder = [SOGoMAPIDBFolderK objectWithName: nameInContainer
newFolder = [SOGoCacheGCSFolderK objectWithName: nameInContainer
inContainer: sogoObject];
[newFolder reloadIfNeeded];
[[newFolder properties] setObject: folderName
@@ -181,7 +181,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
[SOGoObject globallyUniqueObjectId]];
fsObject = [SOGoMAPIDBMessage objectWithName: newKey
inContainer: sogoObject];
[fsObject setObjectType: MAPIDBObjectTypeMessage];
[fsObject setObjectType: MAPIMessageCacheObject];
[fsObject reloadIfNeeded];
newMessage = [MAPIStoreDBMessage mapiStoreObjectWithSOGoObject: fsObject
inContainer: self];
@@ -198,7 +198,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
ownerUser = [[self userContext] sogoUser];
if ([[context activeUser] isEqual: ownerUser]
|| [self subscriberCanReadMessages])
keys = [(SOGoMAPIDBFolder *) sogoObject childKeysOfType: MAPIDBObjectTypeMessage
keys = [(SOGoCacheGCSFolder *) sogoObject childKeysOfType: MAPIMessageCacheObject
includeDeleted: NO
matchingQualifier: qualifier
andSortOrderings: sortOrderings];
@@ -211,7 +211,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
- (NSArray *) folderKeysMatchingQualifier: (EOQualifier *) qualifier
andSortOrderings: (NSArray *) sortOrderings
{
return [dbFolder childKeysOfType: MAPIDBObjectTypeFolder
return [dbFolder childKeysOfType: MAPIFolderCacheObject
includeDeleted: NO
matchingQualifier: qualifier
andSortOrderings: sortOrderings];
+17
View File
@@ -23,6 +23,7 @@
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#import <NGExtensions/NSObject+Logs.h>
@@ -34,6 +35,7 @@
#import "MAPIStoreDBMessage.h"
#import "MAPIStoreTypes.h"
#import "NSObject+MAPIStore.h"
#import "NSString+MAPIStore.h"
#undef DEBUG
#include <mapistore/mapistore.h>
@@ -99,6 +101,21 @@
return objectVersion;
}
//
// FIXME: how this can happen?
//
// We might get there if for some reasons, all classes weren't able
// to tell us the message class.
//
- (int) getPidTagMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"IPM.Note" asUnicodeInMemCtx: memCtx];
[self logWithFormat: @"METHOD '%s' - unable to determine message class. Falling back to IPM.Note", __FUNCTION__];
return MAPISTORE_SUCCESS;
}
- (int) getProperties: (struct mapistore_property_data *) data
withTags: (enum MAPITAGS *) tags
andCount: (uint16_t) columnCount
+4 -6
View File
@@ -1,8 +1,6 @@
/* MAPIStoreFallbackContext.m - this file is part of SOGo
*
* Copyright (C) 2011-2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2011-2014 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
@@ -26,7 +24,7 @@
#import "MAPIStoreUserContext.h"
#import "NSString+MAPIStore.h"
#import "SOGoMAPIDBFolder.h"
#import <SOGo/SOGoCacheGCSFolder.h>
#import "MAPIStoreFallbackContext.h"
@@ -51,7 +49,7 @@
inMemCtx: (TALLOC_CTX *) memCtx
{
struct mapistore_contexts_list *firstContext = NULL, *context;
SOGoMAPIDBFolder *root;
SOGoCacheGCSFolder *root;
NSArray *names;
NSUInteger count, max;
NSString *baseURL, *url, *name;
@@ -70,7 +68,7 @@
/* Maybe emsmdbp_provisioning should be fixed in order to only take the uri
returned above to avoid deleting its entries... */
root = [SOGoMAPIDBFolder objectWithName: [self MAPIModuleName]
root = [SOGoCacheGCSFolder objectWithName: [self MAPIModuleName]
inContainer: nil];
[root setOwner: userName];
userContext = [MAPIStoreUserContext userContextWithUsername: userName
+4 -6
View File
@@ -1,8 +1,6 @@
/* MAPIStoreFolder.h - this file is part of SOGo
*
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2011-2014 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
@@ -38,7 +36,7 @@
@class MAPIStoreMessageTable;
@class MAPIStorePermissionsTable;
@class SOGoFolder;
@class SOGoMAPIDBFolder;
@class SOGoCacheGCSFolder;
@class SOGoMAPIDBMessage;
#import "MAPIStoreSOGoObject.h"
@@ -50,7 +48,7 @@
// NSArray *faiMessageKeys;
// NSArray *folderKeys;
SOGoMAPIDBFolder *dbFolder;
SOGoCacheGCSFolder *dbFolder;
// SOGoMAPIDBFolder *faiFolder;
// SOGoMAPIDBFolder *propsFolder;
// SOGoMAPIDBMessage *propsMessage;
@@ -60,7 +58,7 @@
- (void) setupAuxiliaryObjects;
- (SOGoMAPIDBFolder *) dbFolder;
- (SOGoCacheGCSFolder *) dbFolder;
- (NSArray *) activeMessageTables;
- (NSArray *) activeFAIMessageTables;
+8 -9
View File
@@ -1,8 +1,6 @@
/* MAPIStoreFolder.m - this file is part of SOGo
*
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2011-2014 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
@@ -51,8 +49,9 @@
#import "NSDate+MAPIStore.h"
#import "NSString+MAPIStore.h"
#import "NSObject+MAPIStore.h"
#import "SOGoMAPIDBFolder.h"
#import <SOGo/SOGoCacheGCSFolder.h>
#import "SOGoMAPIDBMessage.h"
#import "SOGoCacheGCSObject+MAPIStore.h"
#include <gen_ndr/exchange.h>
@@ -120,7 +119,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
[userContext ensureFolderTableExists];
ASSIGN (dbFolder,
[SOGoMAPIDBFolder objectWithName: folderName
[SOGoCacheGCSFolder objectWithName: folderName
inContainer: [container dbFolder]]);
[dbFolder setTableUrl: [userContext folderTableURL]];
if (!container && [path length] > 0)
@@ -138,7 +137,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
// ASSIGN (propsMessage,
// [SOGoMAPIDBMessage objectWithName: @"properties.plist"
// inContainer: dbFolder]);
// [propsMessage setObjectType: MAPIDBObjectTypeInternal];
// [propsMessage setObjectType: MAPIInternalCacheObject];
// [propsMessage reloadIfNeeded];
[properties release];
properties = [dbFolder properties];
@@ -192,7 +191,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
[super dealloc];
}
- (SOGoMAPIDBFolder *) dbFolder
- (SOGoCacheGCSFolder *) dbFolder
{
return dbFolder;
}
@@ -1221,7 +1220,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
- (NSArray *) faiMessageKeysMatchingQualifier: (EOQualifier *) qualifier
andSortOrderings: (NSArray *) sortOrderings
{
return [dbFolder childKeysOfType: MAPIDBObjectTypeFAI
return [dbFolder childKeysOfType: MAPIFAICacheObject
includeDeleted: NO
matchingQualifier: qualifier
andSortOrderings: sortOrderings];
@@ -1531,7 +1530,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
newKey = [NSString stringWithFormat: @"%@.plist",
[SOGoObject globallyUniqueObjectId]];
dbObject = [SOGoMAPIDBMessage objectWithName: newKey inContainer: dbFolder];
[dbObject setObjectType: MAPIDBObjectTypeFAI];
[dbObject setObjectType: MAPIFAICacheObject];
[dbObject setIsNew: YES];
newMessage = [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: dbObject
inContainer: self];
+2
View File
@@ -122,6 +122,8 @@
[MAPIApp setUserContext: userContext];
moduleName = [self MAPIModuleName];
parentFolder = [[userContext rootFolders] objectForKey: moduleName];
nameInContainer = nil;
if (![parentFolder newFolderWithName: folderName
nameInContainer: &nameInContainer])
mapistoreURI = [NSString stringWithFormat: @"sogo://%@@%@/%@/",
+4 -2
View File
@@ -74,7 +74,7 @@ static Class NSNumberK;
ASSIGN (versionsMessage,
[SOGoMAPIDBMessage objectWithName: @"versions.plist"
inContainer: dbFolder]);
[versionsMessage setObjectType: MAPIDBObjectTypeInternal];
[versionsMessage setObjectType: MAPIInternalCacheObject];
}
- (void) dealloc
@@ -259,7 +259,6 @@ static Class NSNumberK;
}
}
*/
- (void) _setChangeKey: (NSData *) changeKey
forMessageEntry: (NSMutableDictionary *) messageEntry
inChangeListOnly: (BOOL) inChangeListOnly
@@ -462,6 +461,9 @@ static Class NSNumberK;
[messageEntry setObject: changeNumber forKey: @"version"];
newChangeNum = [changeNumber unsignedLongLongValue];
// 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
inChangeListOnly: NO];
+3 -2
View File
@@ -24,6 +24,7 @@
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSURL.h>
#import <NGImap4/NSString+Imap4.h>
#import <NGExtensions/NSString+misc.h>
#import <Mailer/SOGoMailAccount.h>
#import <Mailer/SOGoMailFolder.h>
@@ -156,7 +157,7 @@ MakeDisplayFolderName (NSString *folderName)
stringData = [NSString stringWithFormat: @"%@%@",
urlBase, [currentName stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
context->url = [stringData asUnicodeInMemCtx: context];
stringData = [[currentName substringFromIndex: 6] fromCSSIdentifier];
stringData = [[[currentName substringFromIndex: 6] fromCSSIdentifier] stringByDecodingImap4FolderName];
context->name = [stringData asUnicodeInMemCtx: context];
context->main_folder = false;
context->role = MAPISTORE_MAIL_ROLE;
@@ -188,7 +189,7 @@ MakeDisplayFolderName (NSString *folderName)
if ([newFolder create])
mapistoreURI = [NSString stringWithFormat: @"sogo://%@:%@@mail/%@/",
userName, userName,
[folderName stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
[[folderName stringByEncodingImap4FolderName] stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
else
mapistoreURI = nil;
[MAPIApp setUserContext: nil];
+8 -9
View File
@@ -1,8 +1,6 @@
/* MAPIStoreMailFolder.m - this file is part of SOGo
*
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2011-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
@@ -36,6 +34,7 @@
#import <NGExtensions/NSString+misc.h>
#import <NGImap4/NGImap4Connection.h>
#import <NGImap4/NGImap4Client.h>
#import <NGImap4/NSString+Imap4.h>
#import <Mailer/SOGoDraftsFolder.h>
#import <Mailer/SOGoMailAccount.h>
#import <Mailer/SOGoMailAccounts.h>
@@ -60,7 +59,7 @@
#import "NSData+MAPIStore.h"
#import "NSString+MAPIStore.h"
#import "SOGoMAPIDBMessage.h"
#import "SOGoMAPIDBFolder.h"
#import <SOGo/SOGoCacheGCSFolder.h>
#import "MAPIStoreMailVolatileMessage.h"
@@ -107,7 +106,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
ASSIGN (versionsMessage,
[SOGoMAPIDBMessage objectWithName: @"versions.plist"
inContainer: dbFolder]);
[versionsMessage setObjectType: MAPIDBObjectTypeInternal];
[versionsMessage setObjectType: MAPIInternalCacheObject];
}
- (BOOL) ensureFolderExists
@@ -177,7 +176,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
if (folderName)
{
nameInContainer = [NSString stringWithFormat: @"folder%@",
[folderName asCSSIdentifier]];
[[folderName stringByEncodingImap4FolderName] asCSSIdentifier]];
newFolder = [SOGoMailFolderK objectWithName: nameInContainer
inContainer: sogoObject];
if ([newFolder create])
@@ -315,7 +314,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
if (![subfolderName hasPrefix: @"folder"])
abort ();
strippedName = [subfolderName substringFromIndex: 6];
strippedName = [[subfolderName substringFromIndex: 6] stringByDecodingImap4FolderName];
[representation appendFormat: @"/%@", strippedName];
return representation;
@@ -1173,9 +1172,9 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
- (MAPIStoreMessage *) createMessage
{
SOGoMAPIObject *childObject;
SOGoCacheObject *childObject;
childObject = [SOGoMAPIObject objectWithName: [SOGoMAPIObject
childObject = [SOGoCacheObject objectWithName: [SOGoCacheObject
globallyUniqueObjectId]
inContainer: sogoObject];
return [MAPIStoreMailVolatileMessage
+17 -1
View File
@@ -62,7 +62,7 @@
#import "NSData+MAPIStore.h"
#import "NSObject+MAPIStore.h"
#import "NSString+MAPIStore.h"
#import "SOGoMAPIObject.h"
#import <SOGo/SOGoCacheObject.h>
#import "MAPIStoreMailVolatileMessage.h"
@@ -543,6 +543,7 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
NSDictionary *recipients;
NSUInteger type, bccLimit;
SOGoUser *activeUser;
NSNumber *priority;
activeUser
= [SOGoUser
@@ -596,6 +597,21 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
[headers addObject: [date rfc822DateString] forKey: @"date"];
}
[headers addObject: @"1.0" forKey: @"MIME-Version"];
priority = [mailProperties objectForKey: MAPIPropertyKey (PidTagImportance)];
if ([priority intValue] == 2)
{
[headers addObject: @"1 (Highest)" forKey: @"X-Priority"];
}
else if ([priority intValue] == 1)
{
[headers removeAllObjectsForKey: @"X-Priority"];
}
else
{
[headers addObject: @"5 (Lowest)" forKey: @"X-Priority"];
}
}
static NSArray *
+3
View File
@@ -284,6 +284,9 @@ static Class NSExceptionK, MAPIStoreFolderK;
return MAPISTORE_SUCCESS;
}
//
// The GlobCnt is 6 bytes long.
//
- (NSData *) getReplicaKeyFromGlobCnt: (uint64_t) objectCnt
{
struct mapistore_connection_info *connInfo;
+1 -1
View File
@@ -25,7 +25,7 @@
#import <NGExtensions/NSObject+Logs.h>
#import <EOControl/EOQualifier.h>
#import "EOBitmaskQualifier.h"
#import <SOGo/EOBitmaskQualifier.h>
#import "MAPIStoreActiveTables.h"
#import "MAPIStoreObject.h"
#import "MAPIStoreTypes.h"
+3 -3
View File
@@ -42,7 +42,7 @@
#import <Mailer/SOGoMailAccount.h>
#import <Mailer/SOGoMailAccounts.h>
#import "GCSSpecialQueries+OpenChange.h"
#import <SOGo/GCSSpecialQueries+SOGoCacheObject.h>
#import "MAPIApplication.h"
#import "MAPIStoreAuthenticator.h"
#import "MAPIStoreMapping.h"
@@ -295,7 +295,7 @@ static NSMapTable *contextsTable = nil;
{
/* If "OCSFolderInfoURL" is properly configured, we must have 5
parts in this url. */
ocFSTableName = [NSString stringWithFormat: @"socfs_%@",
ocFSTableName = [NSString stringWithFormat: @"sogo_cache_folder_%@",
[username asCSSIdentifier]];
[parts replaceObjectAtIndex: 4 withObject: ocFSTableName];
folderTableURL
@@ -329,7 +329,7 @@ static NSMapTable *contextsTable = nil;
tableName]])
{
queries = [channel specialQueries];
query = [queries createOpenChangeFSTableWithName: tableName];
query = [queries createSOGoCacheGCSFolderTableWithName: tableName];
if ([channel evaluateExpressionX: query])
[NSException raise: @"MAPIStoreIOException"
format: @"could not create special table '%@'", tableName];
+4 -1
View File
@@ -148,6 +148,7 @@ static void _fillFlatUIDWithGUID (struct FlatUID_r *flatUID, const struct GUID *
- (struct XID *) asXIDInMemCtx: (void *) memCtx
{
struct XID *xid;
uint8_t *bytes;
NSUInteger max;
max = [self length];
@@ -158,7 +159,9 @@ static void _fillFlatUIDWithGUID (struct FlatUID_r *flatUID, const struct GUID *
[self _extractGUID: &xid->GUID];
xid->Size = max - 16;
xid->Data = talloc_memdup (xid, [self bytes] + 16, xid->Size);
bytes = (uint8_t *) [self bytes];
xid->Data = talloc_memdup (xid, (bytes+16), xid->Size);
}
else
{
+2 -4
View File
@@ -1,8 +1,6 @@
/* dbmsgdump.m - this file is part of SOGo
*
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2011-2014 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
@@ -33,7 +31,7 @@
#import <Foundation/NSValue.h>
#import <NGExtensions/NSNull+misc.h>
#import "BSONCodec.h"
#import <SOGo/BSONCodec.h>
const char *indentationStep = " ";
+13 -1
View File
@@ -694,10 +694,18 @@ const unsigned short ansicpg874[256] = {
}
else if (*(_bytes+1) == '*')
{
while (*_bytes != '}')
int cc = 1;
do
{
if (*_bytes == '{')
cc++;
if (*_bytes == '}')
cc--;
ADVANCE;
}
while (cc != 0);
continue;
}
@@ -793,6 +801,10 @@ const unsigned short ansicpg874[256] = {
{
// ignore
}
else if ([s hasPrefix: @"fromtext"])
{
// ignore
}
else if ([s hasPrefix: @"f"] && [s length] > 1)
{
RTFFontInfo *fontInfo;
+32
View File
@@ -0,0 +1,32 @@
/* SOGoCacheGCSObject+MAPIStore.h - this file is part of SOGo
*
* Copyright (C) 2014 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
* 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.
*/
#ifndef SOGOCACHEGCSOBJECTMAPISTORE
#define SOGOCACHEGCSOBJECTMAPISTORE
#include <SOGo/SOGoCacheGCSObject.h>
@interface SOGoCacheGCSObject (MAPIStore)
- (Class) mapistoreMessageClass;
@end
#endif // SOGOCACHEGCSOBJECTMAPISTORE
+68
View File
@@ -0,0 +1,68 @@
/* SOGoCacheGCSObject+MAPIStore.m - this file is part of SOGo
*
* Copyright (C) 2014 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
* 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/NSDictionary.h>
#import <Foundation/NSException.h>
#import <Foundation/NSString.h>
#include "MAPIStoreTypes.h"
#include "SOGoCacheGCSObject+MAPIStore.h"
@implementation SOGoCacheGCSObject (MAPIStore)
- (Class) mapistoreMessageClass
{
NSString *className, *mapiMsgClass;
switch (objectType)
{
case MAPIMessageCacheObject:
mapiMsgClass = [properties
objectForKey: MAPIPropertyKey (PidTagMessageClass)];
if (mapiMsgClass)
{
if ([mapiMsgClass isEqualToString: @"IPM.StickyNote"])
className = @"MAPIStoreNotesMessage";
else
className = @"MAPIStoreDBMessage";
//[self logWithFormat: @"PidTagMessageClass = '%@', returning '%@'",
// mapiMsgClass, className];
}
else
{
//[self warnWithFormat: @"PidTagMessageClass is not set, falling back"
// @" to 'MAPIStoreDBMessage'"];
className = @"MAPIStoreDBMessage";
}
break;
case MAPIFAICacheObject:
className = @"MAPIStoreFAIMessage";
break;
default:
[NSException raise: @"MAPIStoreIOException"
format: @"message class should not be queried for objects"
@" of type '%d'", objectType];
}
return NSClassFromString (className);
}
@end
+3 -5
View File
@@ -1,8 +1,6 @@
/* SOGoMAPIDBMessage.h - this file is part of SOGo
*
* Copyright (C) 2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2012-2014 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
@@ -23,12 +21,12 @@
#ifndef SOGOMAPIDBMESSAGE_H
#define SOGOMAPIDBMESSAGE_H
#import "SOGoMAPIDBObject.h"
#import <SOGo/SOGoCacheGCSObject.h>
@class NSDate;
@class NSString;
@interface SOGoMAPIDBMessage : SOGoMAPIDBObject
@interface SOGoMAPIDBMessage : SOGoCacheGCSObject
@end
#endif /* SOGOMAPIDBMESSAGE_H */
+1 -1
View File
@@ -30,7 +30,7 @@
#import <NGExtensions/NSObject+Logs.h>
#import "SOGoMAPIDBFolder.h"
#import <SOGo/SOGoCacheGCSFolder.h>
#import "SOGoMAPIDBMessage.h"
+1 -1
View File
@@ -34,7 +34,7 @@
#import <SOGo/SOGoSystemDefaults.h>
#import "MAPIStoreUserContext.h"
#import "SOGoMAPIDBObject.h"
#import <SOGo/SOGoCacheGCSObject.h>
#import "NSObject+PropertyList.m"
+1 -1
View File
@@ -27,7 +27,7 @@
#import "EOQualifier+GCS.h"
#if __GNU_LIBOBJC__ >= 20100911
#if (defined(__GNU_LIBOBJC__) && (__GNU_LIBOBJC__ >= 20100911)) || defined(APPLE_RUNTIME) || defined(__GNUSTEP_RUNTIME__)
# define sel_eq(__A__,__B__) sel_isEqual(__A__,__B__)
#endif
+1 -1
View File
@@ -44,7 +44,7 @@
#import "EOQualifier+GCS.h"
#import "GCSStringFormatter.h"
#if __GNU_LIBOBJC__ >= 20100911
#if (defined(__GNU_LIBOBJC__) && (__GNU_LIBOBJC__ >= 20100911)) || defined(APPLE_RUNTIME) || defined(__GNUSTEP_RUNTIME__)
# define sel_eq(__A__,__B__) sel_isEqual(__A__,__B__)
#endif
+14 -2
View File
@@ -35,6 +35,8 @@
@"http://www.ietf.org/internet-drafts/draft-dawson-vcard-xml-dtd-03.txt"
#endif
static NSArray *privilegedTagNames = nil;
@implementation NGCardsSaxHandler
- (id) init
@@ -42,6 +44,12 @@
if ((self = [super init]))
topGroupClass = nil;
if (!privilegedTagNames)
{
privilegedTagNames = [NSArray arrayWithObjects: @"ADR", @"N", @"RRULE", @"ORG", nil];
RETAIN(privilegedTagNames);
}
return self;
}
@@ -210,8 +218,12 @@
length: contentLength];
free (content);
content = NULL;
// NSLog (@"content: '%@'", s);
contentValues = [s vCardSubvalues];
//NSLog(@"content: '%@'", s);
if ([privilegedTagNames containsObject: [currentElement tag]])
contentValues = [s vCardSubvalues];
else
contentValues = [NSMutableDictionary dictionaryWithObject: [NSMutableArray arrayWithObject: [s asCardAttributeValues]]
forKey: @""];
}
else
contentValues = nil;
+1 -1
View File
@@ -72,7 +72,7 @@
- (void) setCompleted: (NSCalendarDate *) newCompletedDate
{
[(iCalDateTime *) [self uniqueChildWithTag: @"completed"]
setDate: newCompletedDate];
setDateTime: newCompletedDate];
if (newCompletedDate)
[self setStatus: @"COMPLETED"];
else
+4 -4
View File
@@ -22,7 +22,7 @@ sogoUserDefaultsFile = os.path.expanduser("~sogo/GNUstep/Defaults/.GNUstepDefaul
# - removes the entry in samba's ldap tree via ldbedit (NOTYET)
# - remove the user's directory under mapistore/ and mapistore/SOGo
# - cleanup Junk Folders and Sync Issues imap folders
# - Delete the socfs_ table for the username.
# - Delete the sogo_cache_folder_ table for the username.
def usage():
print """
@@ -210,7 +210,7 @@ On RHEL, install it using 'yum install MySQL-python'"""
conn = MySQLdb.connect(host=dbhost, port=int(dbport), user=dbuser, passwd=dbpass, db=dbname)
c=conn.cursor()
tablename="socfs_%s" % (username)
tablename="sogo_cache_folder_%s" % (username)
c.execute("TRUNCATE TABLE %s" % tablename)
print "Table %s emptied"
@@ -225,7 +225,7 @@ On RHEL, install it using 'yum install python-pgsql'"""
raise Exception(msg)
conn = pg.connect(host=dbhost, port=int(dbport), user=dbuser, passwd=dbpass, dbname=dbname)
tablename = "socfs_%s" % username
tablename = "sogo_cache_folder_%s" % username
conn.query("DELETE FROM %s" % tablename)
print "Table '%s' emptied" % tablename
@@ -278,7 +278,7 @@ def sqlCleanup(username):
print "Starting SQL cleanup"
OCSFolderInfoURL = getOCSFolderInfoURL()
if OCSFolderInfoURL is None:
raise Exception("Couldn't fetch OCSFolderInfoURL or it is not set. the socfs_%s table should be truncated manually" % (username))
raise Exception("Couldn't fetch OCSFolderInfoURL or it is not set. the sogo_cache_folder_%s table should be truncated manually" % (username))
# postgresql://sogo:sogo@127.0.0.1:5432/sogo/sogo_folder_info
m = re.search("(.+)://(.+):(.+)@(.+):(\d+)/(.+)/(.+)", OCSFolderInfoURL)
+1 -1
View File
@@ -4,7 +4,7 @@ set -o pipefail
#set -x
PROGNAME="$(basename $0)"
BACKUP_DIR=/home/sogo/backups
BACKUP_DIR=~sogo/backups
SOGO_TOOL=/usr/sbin/sogo-tool
DAYS_TO_KEEP="30"
+2 -2
View File
@@ -1,5 +1,5 @@
# The amount of processes that should be spawned (Default: 1)
# PREFORK=1
# The amount of processes that should be spawned (Default: 3)
# PREFORK=3
# The name of the account under which SOGo will be running (Default: sogo)
# USER=sogo
+1 -1
View File
@@ -34,7 +34,7 @@ DAEMON=/usr/sbin/sogod
DESC="SOGo"
USER=$NAME
PREFORK=1
PREFORK=3
PIDFILE=/var/run/$NAME/$NAME.pid
LOGFILE=/var/log/$NAME/$NAME.log
+1 -1
View File
@@ -37,7 +37,7 @@ DAEMON=/usr/sbin/sogod
DESC="SOGo"
USER=$NAME
PREFORK=1
PREFORK=3
PIDFILE=/var/run/$NAME/$NAME.pid
LOGFILE=/var/log/$NAME/$NAME.log
+30 -3
View File
@@ -33,8 +33,10 @@
//SOGoMailSpoolPath = /var/spool/sogo;
//NGImap4ConnectionStringSeparator = "/";
/* Notifications */
//SOGoAppointmentSendEMailNotifications = NO;
//SOGoACLsSendEMailNotifications = NO;
//SOGoFoldersSendEMailNotifications = NO;
/* Authentication */
//SOGoPasswordChangeEnabled = YES;
@@ -58,13 +60,33 @@
// }
//);
/* LDAP AD/Samba4 example */
//SOGoUserSources = (
// {
// type = ldap;
// CNFieldName = cn;
// UIDFieldName = sAMAccountName;
// baseDN = "CN=users,dc=domain,dc=tld";
// bindDN = "CN=sogo,CN=users,DC=domain,DC=tld";
// bindFields = (sAMAccountName, mail);
// bindPassword = password;
// canAuthenticate = YES;
// displayName = "Public";
// hostname = ldap://127.0.0.1:389;
// filter = "mail = '*'";
// id = directory;
// isAddressBook = YES;
// }
//);
/* SQL authentication example */
/* These database columns MUST be present in the view/table:
* 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 uniquely identify entries
* 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
* mail - the user's mail address
* See the installation guide for more details
*/
//SOGoUserSources =
@@ -84,6 +106,8 @@
//SOGoVacationEnabled = YES;
//SOGoForwardEnabled = YES;
//SOGoSieveScriptsEnabled = YES;
//SOGoMailAuxiliaryUserAccountsEnabled = YES;
//SOGoTrustProxyAuthentication = NO;
/* General */
//SOGoLanguage = English;
@@ -92,13 +116,16 @@
// PublicDAndTViewer,
// ConfidentialDAndTViewer
//);
//SOGoSuperUsernames = (sogo1, sogo2); //This is an array - keep the parens!
//SOGoSuperUsernames = (sogo1, sogo2); // This is an array - keep the parens!
//SxVMemLimit = 384;
//WOPidFile = "/var/run/sogo/sogo.pid";
//SOGoMemcachedHost = "/var/run/memcached.sock";
/* Debug */
//SOGoDebugRequests = YES;
//SoDebugBaseURL = YES;
//ImapDebugEnabled = YES;
//LDAPDebugEnabled = YES;
//SOGoDebugRequests = YES;
//PGDebugEnabled = YES;
//MySQL4DebugEnabled = YES;
//SOGoUIxDebugEnabled = YES;
+3 -1
View File
@@ -10,10 +10,12 @@
#* * * * * sogo /usr/sbin/sogo-tool expire-sessions 60
# Email alarms - runs every minutes
# If you need to use SMTP AUTH for outgoing mails, specify credentials to use
# with '-p /path/to/credentialsFile' (same format as the sieve credentials)
#* * * * * sogo /usr/sbin/sogo-ealarms-notify
# Daily backups
# - writes to /home/sogo/backups/ by default
# - writes to ~sogo/backups/ by default
# - will keep 31 days worth of backups by default
# - runs once a day by default, but can run more frequently
# - make sure to set the path to sogo-backup.sh correctly
+1 -1
View File
@@ -4,4 +4,4 @@
SOGOSPOOL=/var/spool/sogo
/usr/sbin/tmpwatch 24 "$SOGOSPOOL"
find "$SOGOSPOOL" -depth -mindepth 1 -type d -empty -exec /bin/rmdir {} \; 2> /dev/null
find "$SOGOSPOOL" -mindepth 1 -type d -user sogo -empty -delete > /dev/null
+8 -8
View File
@@ -28,22 +28,22 @@ $plugins
= array(
"sogo-connector@inverse.ca"
=> array( "application" => "thunderbird",
"version" => "17.0.3",
"filename" => "sogo-connector-17.0.3.xpi" ),
"version" => "24.0.4",
"filename" => "sogo-connector-24.0.4.xpi" ),
"sogo-integrator@inverse.ca"
=> array( "application" => "thunderbird",
"version" => "17.0.3",
"filename" => "sogo-integrator-17.0.3.xpi" ),
"version" => "24.0.4",
"filename" => "sogo-integrator-24.0.4.xpi" ),
"{e2fda1a4-762b-4020-b5ad-a41df1933103}"
=> array( "application" => "thunderbird",
"version" => "1.9",
"filename" => "lightning-1.9.xpi" )
"version" => "2.6.4",
"filename" => "lightning-2.6.4.xpi" )
);
$applications
= array( "thunderbird" => "<em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id>
<em:minVersion>17.0</em:minVersion>
<em:maxVersion>17.*</em:maxVersion>" );
<em:minVersion>24.0</em:minVersion>
<em:maxVersion>24.*</em:maxVersion>" );
$pluginname = $_GET["plugin"];
$plugin =& $plugins[$pluginname];
@@ -27,13 +27,13 @@ vtodo_class2 = "(Vertrauliche Aufgabe)";
/* Invitation */
"Event Invitation: \"%{Summary}\"" = "Termineinladung: \"%{Summary}\"";
"(sent by %{SentBy}) " = "(gesendet von %{SentBy}) ";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" = "%{Organizer} %{SentByText} Hat Sie eingeladen zu %{Summary}.\n\nBeginn: %{StartDate}\nEnde: %{EndDate}\nBeschreibung: %{Description}";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" = "%{Organizer} %{SentByText} Hat Sie eingeladen zu \"%{Summary}\".\n\nBeginn: %{StartDate}\nEnde: %{EndDate}\nBeschreibung: %{Description}";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" = "%{Organizer} %{SentByText} hat Sie eingeladen zu \"%{Summary}\".\n\nBeginn: %{StartDate} um %{StartTime}\nEnde: %{EndDate} um %{EndTime}\nBeschreibung: %{Description}";
/* Deletion */
"Event Cancelled: \"%{Summary}\"" = "Termin abgesagt: \"%{Summary}\"";
"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}"
= "%{Organizer} %{SentByText} hat den folgenden Termin abgesagt: %{Summary}.\n\nBeginn: %{StartDate}\nEnde: %{EndDate}\nBeschreibung: %{Description}";
= "%{Organizer} %{SentByText} hat den folgenden Termin abgesagt: \"%{Summary}\".\n\nBeginn: %{StartDate}\nEnde: %{EndDate}\nBeschreibung: %{Description}";
"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}"
= "%{Organizer} %{SentByText} hat diesen Termin abgesagt: \"%{Summary}\".\n\nBeginn: %{StartDate} um %{StartTime}\nEnde: %{EndDate} um %{EndTime}\nBeschreibung: %{Description}";
@@ -45,7 +45,7 @@ vtodo_class2 = "(Vertrauliche Aufgabe)";
"The following parameters have changed in the \"%{Summary}\" meeting:"
= "Folgendes wurde am Termin \"%{Summary}\" geändert:";
"Please accept or decline those changes."
= "Bitte akzeptieren Sie diese Änderung oder lehnen Sie ab.";
= "Bitte akzeptieren Sie diese Änderung oder lehnen Sie diese ab.";
/* Reply */
"Accepted invitation: \"%{Summary}\"" = "Einladung zugestimmt: \"%{Summary}\"";
+1 -3
View File
@@ -1,8 +1,6 @@
/* MSExchangeFreeBusy.m - this file is part of SOGo
*
* Copyright (C) 2012 Inverse inc.
*
* Author: Francis Lachapelle <flachapelle@inverse.ca>
* Copyright (C) 2012-2014 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
@@ -8,23 +8,15 @@ vtodo_class1 = "(Privat oppgave)";
vtodo_class2 = "(Konfidensiell oppgave)";
/* Receipts */
"Title:" = "Tittel:";
"Start:" = "Start:";
"End:" = "Slutt:";
"Receipt: users invited to a meeting" = "Kvittering: brukere invitert til et møte";
"You have invited the following attendees(s):" = "Du har invitert følende deltagere:";
"... to attend the following event:" = "... til å delta i følgende hendelse:";
"Receipt: invitation updated" = "Kvittering: invitasjon oppdatert";
"The following attendees(s):" = "Følgende deltager(e):";
"... have been notified of the changes to the following event:" = "... har blitt informert om endringene i følgende hendelse:";
"Receipt: attendees removed from an event" = "Kvittering: deltagere fjernet fra en hendelse";
"You have removed the following attendees(s):" = "Du har tatt bort følgende deltagere:";
"... from the following event:" = "... fra følgende hendelse:";
"The event \"%{Summary}\" was created" = "Hendelsen \"%{Summary}\" ble opprettet";
"The event \"%{Summary}\" was deleted" = "Hendelsen \"%{Summary}\" ble slettet";
"The event \"%{Summary}\" was updated" = "Hendelsen \"%{Summary}\" ble oppdatert";
"The following attendees(s) were notified:" = "Følgende deltaker(e) ble varslet:";
"The following attendees(s) were added:" = "Følgende deltaker(e) ble lagt til:";
"The following attendees(s) were removed:" = "Følgende deltaker(e) ble fjernet:";
/* IMIP messages */
"calendar_label" = "Kalender:";
"startDate_label" = "Start:";
"endDate_label" = "Slutt:";
"due_label" = "Forfallsdato:";
@@ -35,27 +27,31 @@ vtodo_class2 = "(Konfidensiell oppgave)";
/* Invitation */
"Event Invitation: \"%{Summary}\"" = "Hendelseinvitasjon: \"%{Summary}\"";
"(sent by %{SentBy}) " = "(sendt av %{SentBy})";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" = "";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" = "%{Organizer} %{SentByText} har invitert deg til %{Summary}.\n\nStart: %{StartDate} %{StartTime}\nSlutt: %{EndDate} %{EndTime}\nBeskrivelse: %{Description}";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" = "%{Organizer} %{SentByText} har invitert deg til %{Summary}.⏎ ⏎ Start: %{StartDate}⏎ Slutt: %{EndDate}⏎ Beskrivelse: %{Description}";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" = "%{Organizer} %{SentByText} har invitert deg til %{Summary}.\n\nStart: %{StartDate} klokken %{StartTime}\nSlutt: %{EndDate} klokken %{EndTime}\nBeskrivelse: %{Description}";
/* Deletion */
"Event Cancelled: \"%{Summary}\"" = "Hendelse avlyst: \"%{Summary}\"";
"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}"
= "";
= "%{Organizer} %{SentByText} har avlyst hendelsen: %{Summary}.⏎ ⏎ Start: %{StartDate}⏎ Slutt: %{EndDate}⏎ Beskrivelse: %{Description}";
"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}"
= "%{Organizer} %{SentByText} har avlyst : %{Summary}.\n\nStart: %{StartDate} %{StartTime}\nEnd: %{EndDate} %{EndTime}\nBeskrivelse: %{Description}";
= "%{Organizer} %{SentByText} har avlyst : %{Summary}.\n\nStart: %{StartDate} klokken %{StartTime}\nEnd: %{EndDate} klokken %{EndTime}\nBeskrivelse: %{Description}";
/* Update */
"The appointment \"%{Summary}\" for the %{OldStartDate} has changed"
= "";
= "Avtalen \"%{Summary}\", %{OldStartDate} er endret";
"The appointment \"%{Summary}\" for the %{OldStartDate} at %{OldStartTime} has changed"
= "Avtalen \"%{Summary}\" for %{OldStartDate} klokken %{OldStartTime} er endret.";
"The following parameters have changed in the \"%{Summary}\" meeting:"
= "Følgende parametre er endret for \"%{Summary}\" møtet:";
= "Følgende parametre er endret for \"%{Summary}\"-møtet:";
"Please accept or decline those changes."
= "Vennligst godta eller avvis endringene.";
/* Reply */
"Accepted invitation: \"%{Summary}\"" = "Aksepterte invitasjonen: \"%{Summary}\"";
"Declined invitation: \"%{Summary}\"" = "Avviste invitasjonen: \"%{Summary}\"";
"Delegated invitation: \"%{Summary}\"" = "Delegerte invitasjonen: \"%{Summary}\"";
"Not yet decided on invitation: \"%{Summary}\"" = "Fortsatt ikke svart på invitasjonen: \"%{Summary}";
"%{Attendee} %{SentByText}has accepted your event invitation."
= "%{Attendee} %{SentByText} har godtatt invitasjonen.";
"%{Attendee} %{SentByText}has declined your event invitation."
@@ -63,7 +59,8 @@ vtodo_class2 = "(Konfidensiell oppgave)";
"%{Attendee} %{SentByText}has delegated the invitation to %{Delegate}."
= "%{Attendee} %{SentByText} har delegert invitasjonen til %{Delegate}.";
"%{Attendee} %{SentByText}has not yet decided upon your event invitation."
= "%{Attendee} %{SentByText} had ends ikke var på invitasjonen.";
= "%{Attendee} %{SentByText} har ikke svart på invitasjonen.";
/* Resources */
"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\"." = "Maksimalt antall samtidige bookinger (%{NumberOfSimultaneousBookings}) er nåd for ressurs \"%{Cn} %{SystemEmail}\".";
"Cannot access resource: \"%{Cn} %{SystemEmail}\"" = "Kan ikke få tilgang til ressurs: \"%{Cn} %{SystemEmail}\"";
"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}." = "Maksimum antall samtidige reservasjoner (%{NumberOfSimultaneousBookings}) er nådd for ressursen \"%{Cn} %{SystemEmail}\". Kolliderende hendelse er \"%{EventTitle}\", som starter %{StartDate}.";
+104 -21
View File
@@ -1,5 +1,5 @@
/*
Copyright (C) 2007-2013 Inverse inc.
Copyright (C) 2007-2014 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of SOGo.
@@ -573,17 +573,27 @@ static iCalEvent *iCalEventK = nil;
}
grantedCount = [grantedClasses count];
if (grantedCount == 3)
filter = @"";
{
// User have access to all three classifications
filter = @"";
}
else if (grantedCount == 2)
filter
= [NSString stringWithFormat: @"c_classification != %@",
[deniedClasses objectAtIndex: 0]];
{
// User has access to all but one of the classifications
filter = [NSString stringWithFormat: @"c_classification != %@",
[deniedClasses objectAtIndex: 0]];
}
else if (grantedCount == 1)
filter
= [NSString stringWithFormat: @"c_classification = %@",
[grantedClasses objectAtIndex: 0]];
{
// User has access to only one classification
filter = [NSString stringWithFormat: @"c_classification = %@",
[grantedClasses objectAtIndex: 0]];
}
else
filter = nil;
{
// User has access to no classification
filter = nil;
}
return filter;
}
@@ -676,7 +686,6 @@ static iCalEvent *iCalEventK = nil;
qualifier = nil;
/* fetch non-recurrent apts first */
records = [folder fetchFields: fields matchingQualifier: qualifier];
}
else
@@ -871,7 +880,6 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
{
NSCalendarDate *recurrenceId;
NSMutableDictionary *newRecord;
NSDictionary *oldRecord;
NGCalendarDateRange *newRecordRange;
NSComparisonResult compare;
int recordIndex, secondsOffsetFromGMT;
@@ -1272,13 +1280,20 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
[baseWhere addObject: privacySQLString];
if ([title length])
[baseWhere
addObject: [NSString stringWithFormat: @"c_title isCaseInsensitiveLike: '%%%@%%'",
if ([filters length])
{
if ([filters isEqualToString:@"title_Category_Location"] || [filters isEqualToString:@"entireContent"])
{
[baseWhere addObject: [NSString stringWithFormat: @"(c_title isCaseInsensitiveLike: '%%%@%%' OR c_category isCaseInsensitiveLike: '%%%@%%' OR c_location isCaseInsensitiveLike: '%%%@%%')",
[title stringByReplacingString: @"'" withString: @"\\'\\'"],
[title stringByReplacingString: @"'" withString: @"\\'\\'"],
[title stringByReplacingString: @"'" withString: @"\\'\\'"]]];
}
}
else
[baseWhere addObject: [NSString stringWithFormat: @"c_title isCaseInsensitiveLike: '%%%@%%'",
[title stringByReplacingString: @"'" withString: @"\\'\\'"]]];
if ([filters length])
[baseWhere addObject: [NSString stringWithFormat: @"(%@)", filters]];
/* prepare mandatory fields */
fields = [NSMutableArray arrayWithArray: _fields];
@@ -2236,10 +2251,39 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
return @"";
}
/*
RFC5842 states:
3.1. DAV:resource-id Property
The DAV:resource-id property is a REQUIRED property that enables
clients to determine whether two bindings are to the same resource.
The value of DAV:resource-id is a URI, and may use any registered URI
scheme that guarantees the uniqueness of the value across all
resources for all time (e.g., the urn:uuid: URN namespace defined in
[RFC4122] or the opaquelocktoken: URI scheme defined in [RFC4918]).
<!ELEMENT resource-id (href)>
...
so we must STRIP any username prefix, to make the ID global.
*/
- (NSString *) davResourceId
{
NSString *name, *prefix;
prefix = [NSString stringWithFormat: @"%@_", [self ownerInContext: context]];
name = [self nameInContainer];
if ([name hasPrefix: prefix])
{
name = [name substringFromIndex: [prefix length]];
}
return [NSString stringWithFormat: @"urn:uuid:%@:calendars:%@",
[self ownerInContext: context], [self nameInContainer]];
[self ownerInContext: context], name];
}
- (NSArray *) davScheduleCalendarTransparency
@@ -2504,7 +2548,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
unsigned int permStrIndex;
[super initializeQuickTablesAclsInContext: localContext];
/* We assume "userIsOwner" will be set after calling the super method. */
/* We assume "userCanAccessAllObjects" will be set after calling the super method. */
if (!userCanAccessAllObjects)
{
login = [[localContext activeUser] login];
@@ -3094,6 +3138,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
{
NSMutableArray *aclsForUser;
NSArray *superAcls;
static NSArray *rolesClassifications = nil;
superAcls = [super aclsForUser: uid forObjectAtPath: objectPathArray];
if ([uid isEqualToString: [self defaultUserID]])
@@ -3108,14 +3153,52 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
[aclsForUser addObject: SoRole_Authenticated];
}
else
aclsForUser = (NSMutableArray *) superAcls;
{
aclsForUser = [NSMutableArray array];
if (!rolesClassifications)
{
rolesClassifications =
[NSArray arrayWithObjects:
[NSArray arrayWithObjects:
SOGoCalendarRole_PublicModifier,
SOGoCalendarRole_PublicResponder,
SOGoCalendarRole_PublicViewer,
SOGoCalendarRole_PublicDAndTViewer,
nil],
[NSArray arrayWithObjects:
SOGoCalendarRole_ConfidentialModifier,
SOGoCalendarRole_ConfidentialResponder,
SOGoCalendarRole_ConfidentialViewer,
SOGoCalendarRole_ConfidentialDAndTViewer,
nil],
[NSArray arrayWithObjects:
SOGoCalendarRole_PrivateModifier,
SOGoCalendarRole_PrivateResponder,
SOGoCalendarRole_PrivateViewer,
SOGoCalendarRole_PrivateDAndTViewer,
nil],
[NSArray arrayWithObject: SOGoRole_ObjectCreator],
[NSArray arrayWithObject: SOGoRole_ObjectEraser],
nil];
[rolesClassifications retain];
}
// When a user is a member of many groups for which there are access rights, multiple access rights
// can be returned for each classification. In this case, we only keep the highest access right.
int i, count = [rolesClassifications count];
NSString *role;
for (i = 0; i < count; i++)
{
role = [[rolesClassifications objectAtIndex: i] firstObjectCommonWithArray: superAcls];
if (role)
[aclsForUser addObject: role];
}
}
return aclsForUser;
}
/* caldav-proxy */
- (SOGoAppointmentProxyPermission)
proxyPermissionForUserWithLogin: (NSString *) login
- (SOGoAppointmentProxyPermission) proxyPermissionForUserWithLogin: (NSString *) login
{
SOGoAppointmentProxyPermission permission;
NSArray *roles;
@@ -1,8 +1,6 @@
/* SOGoAppointmentFolders.h - this file is part of SOGo
*
* Copyright (C) 2007 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2007-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
@@ -35,8 +33,8 @@
NSMutableArray *folderObjectKeys;
}
- (SOGoWebAppointmentFolder *) newWebCalendarWithName: (NSString *) folderDisplayName
atURL: (NSString *) url;
- (SOGoWebAppointmentFolder *) newWebCalendarWithURL: (NSString *) urlString
nameInContainer: (NSString *) name;
- (void) reloadWebCalendars: (BOOL) forceReload;
Loaded 100 of 677 files, more files were not shown because too many files have changed in this diff. Show more