Compare commits

...
543 Commits
Author SHA1 Message Date
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
Jean Raby bf398889bf Merge to 2.0.6b 2013-06-27 11:36:30 -04:00
Jean Raby f42d52743d bump version to 2.0.6b 2013-06-27 11:35:17 -04:00
Jean Raby 70cd64a626 Update ChangeLog 2013-06-27 11:34:06 -04:00
Jean Raby 4359b05da8 updated NEWS 2013-06-27 11:33:44 -04:00
Ludovic Marcotte e26e3d7307 Revert "Properly escape the foldername to avoid XSS issues"
This reverts commit 045b275b27.
2013-06-27 11:15:41 -04:00
Ludovic Marcotte 25dbd4849d Properly escape the foldername to avoid XSS issues 2013-06-27 11:14:50 -04:00
Ludovic Marcotte 045b275b27 Properly escape the foldername to avoid XSS issues 2013-06-27 11:06:07 -04:00
Jean Raby a2a89e8720 Fix loading of MSExchangeFreeBusySOAPResponseMap 2013-06-26 16:55:39 -04:00
Jean Raby 7ec1973e0f Merge to 2.0.6a 2013-06-25 09:22:35 -04:00
Jean Raby 2581f6c568 Update for 2.0.6a 2013-06-25 09:19:37 -04:00
Jean Raby 20369631c9 Update ChangeLog 2013-06-25 09:17:03 -04:00
Jean Raby 1221da2443 Add CASLogoutRequestMap.plist 2013-06-25 09:12:27 -04:00
Jean Raby f27b8b6a54 Document SOGoCASLogoutEnabled 2013-06-25 09:06:28 -04:00
Ludovic Marcotte a79a9c4eff Merge to 2.0.6
Conflicts:
	Documentation/SOGo Installation Guide.odt
2013-06-21 12:44:35 -04:00
Ludovic Marcotte a6b393c2c1 Update ChangeLog 2013-06-21 11:26:42 -04:00
Ludovic Marcotte faf228022a Updated for the release 2013-06-21 11:25:55 -04:00
Ludovic Marcotte 3e87ba92db Updated french translation 2013-06-21 10:45:03 -04:00
Jean Raby 0a87ff97b6 cosmetic fix, no functional change
added a POST payload to test this code
2013-06-21 09:36:54 -04:00
Ludovic Marcotte 031cd210f7 Better description 2013-06-20 20:29:16 -04:00
Ludovic Marcotte 9d9a434fdc Avoid crashing when reading fcs crap. 2013-06-20 15:44:35 -04:00
Jean Raby 41ed498d65 Add support for CAS LogoutRequests
Fixes #2346
This changes the serviceURL sent by SOGo to the CAS server:
  /SOGo/so/ -> /SOGo/so/index
2013-06-20 14:32:14 -04:00
Ludovic Marcotte d28482557f Fix for bug 2285 2013-06-20 13:43:45 -04:00
Ludovic Marcotte 4c97d54939 Fix for bug #2119 2013-06-20 09:10:09 -04:00
Ludovic Marcotte c08263d1c3 Updated patch 2013-06-19 17:36:43 -04:00
Ludovic Marcotte dc96466462 Updated for the release 2013-06-19 16:06:12 -04:00
Ludovic Marcotte 1734b387a3 Fix for bug #2237 2013-06-19 15:45:40 -04:00
Ludovic Marcotte 871115e349 Fixed bug #2294 2013-06-19 15:07:19 -04:00
Ludovic Marcotte a764286879 Fix for bug #2313 2013-06-19 14:09:20 -04:00
Ludovic Marcotte 5304461e4c now possible to see who created a event/task in a delegated calendar 2013-06-19 10:23:47 -04:00
Jean Raby 6b25f08943 Use domainDefaults to get imapCASServiceName 2013-06-18 19:33:36 -04:00
Jean Raby a0022e06f7 New preference: SOGoIMAPCASServiceName
Reworked CAS section a bit and add some information regarding casifying sieve.
2013-06-18 17:57:17 -04:00
Jean Raby f24e65b6d8 Merge branch 'fix/cas-service-names' 2013-06-18 16:44:05 -04:00
Jean Raby 0fb006c19f New domain preference: SOGoIMAPCASServiceName
Set this to the service name expected by the CAS server if it differs
from SOGoIMAPServer. This is useful to request a CAS ticket for service
imap://imap.domain.com while connecting through imapproxy on imap://127.0.0.1:1143

SOGoDAVAuthenticator is not updated since it doesn't really use the imap code.
2013-06-18 16:36:11 -04:00
Ludovic Marcotte 47a3f1a19d toggle to send or not notifications 2013-06-18 14:14:42 -04:00
Ludovic Marcotte f25344182d Rewrote escapedForCards so it's 10 times faster. 2013-06-14 14:58:16 -04:00
Jean Raby f24e3a0a31 whitespace fixes. tabkill 2013-06-12 02:36:50 -04:00
Ludovic Marcotte afb7bc309c Added message submissions rate-limiting support 2013-06-11 11:21:58 -04:00
Ludovic Marcotte cfee5aa3f4 Added new failed login rate-limiting options 2013-06-11 09:41:17 -04:00
Francis Lachapelle 2a51f6f385 Update CKEditor to version 4.1.2
Also added the blockquote plugin.
2013-06-10 21:07:52 -04:00
Jean Raby 4cffea43eb French translation of Sync Issues 2013-06-07 15:16:12 -04:00
Jean Raby cafce5753d update description of MultipleBookingsFieldName 2013-06-06 16:04:47 -04:00
Francis Lachapelle 5d6a5f5d5e Update CKEditor to version 4.1.1 2013-06-06 13:21:26 -04:00
Francis Lachapelle 8e5a26dfb1 Remove unicode separators from JSON
Fixes #2309
2013-06-05 15:55:52 -04:00
Ludovic Marcotte 4cb0facd72 Fixed bug #2206 2013-06-04 08:51:38 -04:00
Francis Lachapelle 854bce28fb Fix condition in UIxMailPartHTMLViewer 2013-06-03 12:07:18 -04:00
Francis Lachapelle 49e964c529 Fix decoding charset parameter
To avoid a libxml bug/limitation, we were already stripping the charset
parameter, but we were not considering the single quote as valid
delimiter.
2013-06-03 11:47:48 -04:00
Jean Raby 3281cea2a2 Add bindFields to the sample configuration file 2013-05-31 15:54:22 -04:00
Jean Raby 82253e91d2 don't use -M when creating the sogo user on debian
-M was not available in lenny. It is not actually needed since useradd
won't create the homedir when adding a system user (-r)
2013-05-24 15:00:05 -04:00
Jean Raby 1d1ed9a031 Update ldap filter description, example and syntax 2013-05-15 14:51:15 -04:00
Francis Lachapelle 2bd8a2935f Change default value of SOGoMailSpoolPath
Set the spool path to /var/spool/sogo and modified the installation
guide to point to the tmpwatch cronjob when changing SOGoMailSpoolPath.
2013-05-09 08:12:27 -04:00
Francis Lachapelle 8a25e38827 Add indent group to ckeditor toolbar 2013-05-02 09:07:17 -04:00
Ludovic Marcotte 4ec19d46fa Removed left-over code that would cause the logic from bug #2035 to not work. 2013-04-25 14:46:00 -04:00
Jean Raby d46a39e252 TOC links 2013-04-22 13:22:16 -04:00
Jean Raby 23e10d30be Added ldap attribute mapping table 2013-04-22 12:31:18 -04:00
Jean Raby f049e2430a Added ldap attribute mapping table 2013-04-22 12:25:22 -04:00
Jean Raby a53c66e8a4 Install openchange_user_cleanup in usr/sbin/
Instead of usr/share/doc/sogo/
2013-04-18 14:35:56 -04:00
Jean Raby 4fb3492ea8 openchange_cleanup.py -> openchange_user_cleanup 2013-04-18 14:28:55 -04:00
Jean Raby 353f40ac3e try to cleanup under INBOX too (altnamespace = no) 2013-04-18 14:15:35 -04:00
Jean Raby 96c831f726 Use separator sent by the imap server, not '/' 2013-04-18 14:11:36 -04:00
Jean Raby 59b3219f2d Merge to 2.05a 2013-04-16 15:20:19 -04:00
Jean Raby d7fdfc6cb2 Update NEWS + bump version 2013-04-16 15:16:54 -04:00
Jean Raby d02f58b3cd Update ChangeLog 2013-04-16 15:12:29 -04:00
Ludovic Marcotte 62fee93d86 Fix for bug #2287 2013-04-16 14:33:57 -04:00
Jean Raby 139c14d9e1 save: memCtx
Same fix as for MAPIStoreContactMessage
2013-04-16 12:06:17 -04:00
Francis Lachapelle 8ee15c6f77 Update Installation Guide
Improved the description of the parameters IMAPHostFieldName and
SieveHostFieldName.
2013-04-16 08:34:10 -04:00
Jean Raby 5d17414018 [MAPIStoreContactsMessage save] needs memCtx
From extrafu
2013-04-15 14:13:07 -04:00
Francis Lachapelle 3cd91846a6 Fix CSS color refresh of calendars 2013-04-11 16:32:17 -04:00
Francis Lachapelle e9eb8bdc86 Merge to 2.0.5 2013-04-11 12:56:34 -04:00
Francis Lachapelle 3739cb1536 Update ChangeLog 2013-04-11 12:55:11 -04:00
Francis Lachapelle 30f10ee8f0 Update translations 2013-04-11 11:30:23 -04:00
Jean Raby dfb8788270 don't build SAML support on debian yet 2013-04-11 10:37:34 -04:00
Jean Raby 3810833e1b remove unrtf leftovers 2013-04-11 10:22:28 -04:00
Francis Lachapelle 29e05c7c81 Bump version to 2.0.5 2013-04-11 10:20:10 -04:00
Jean Raby 0a08285fac Add note regarding precedence of .GNUstepDefaults 2013-04-11 10:09:02 -04:00
Jean Raby 01f20a42ad packaging fixups 2013-04-11 09:18:43 -04:00
Francis Lachapelle 3a61a2566b Updated installation guide: version 2.0.5 2013-04-10 18:24:03 -04:00
Jean Raby d2dda86529 ... dir fixup again 2013-04-10 16:30:16 -04:00
Jean Raby cc125d2192 directory fixup 2013-04-10 16:27:03 -04:00
Jean Raby 4da1e41d93 deb: install a sample sogo.conf in /etc/sogo
While there, replace mkdir + cp combo with 'install'
2013-04-10 16:20:47 -04:00
Jean Raby e24eb10c4f rpm: install a sample sogo.conf in /etc/sogo 2013-04-10 16:20:16 -04:00
Jean Raby dd9e51fd16 sogo.conf - new example configuration file 2013-04-10 16:16:30 -04:00
Jean Raby 9932d1413b update NEWS 2013-04-10 12:29:48 -04:00
Jean Raby ff13c49540 updated NEWS 2013-04-10 12:16:26 -04:00
Jean Raby 1e33b4bf26 Add notes regarding UIDField: value must be unique 2013-04-10 12:05:44 -04:00
Francis Lachapelle e23a7df125 Update NEWS file 2013-04-10 11:33:41 -04:00
Ludovic Marcotte 4ca476db9e Updated NEWS file 2013-04-10 11:30:40 -04:00
Ludovic Marcotte 33840c71cd Changed noop by unselect/select. 2013-04-10 10:48:25 -04:00
Ludovic Marcotte 1b983ef691 Fixed a potential timing issue with Dovecot when getting the modseq 2013-04-10 09:56:23 -04:00
Ludovic Marcotte eec8c07d4f Avoid appending the domain if already present. 2013-04-09 11:35:53 -04:00
Ludovic Marcotte 84ba93fc0a Now set ForceAuthn to false by default 2013-04-08 13:58:55 -04:00
Francis Lachapelle 37a6f82659 Initial Arabic translation 2013-04-08 11:05:45 -04:00
Ludovic Marcotte b4aaa68d85 Also consider the "mail" attribute in order to get the user's login 2013-04-05 10:26:17 -04:00
Ludovic Marcotte 5487f34b9e Disable hint verification for now. 2013-04-05 08:57:47 -04:00
Jean Raby e07734fa5f Filter sql source entries based on the user domain
When using dynamic domains with SQL sources (DomainFieldName),
let WebUI and dav lookups return entries from current domain
and other domains visible from the originating domain.

Fixes #2269

SQLSource.m: _visibleDomainsQualifierFromDomain:
  returns a EOQualifier OR'ing all visible domains from specified domain
  (including specified domain)

SQLSource.m: allEntryIDsVisibleFromDomain
  Replacement for allEntryIDs.
  Instead of returning all entries from the sql source,
  only return the entries visible from the specified domain.

SoObjects/SOGo/SQLSource.m: allEntryIDs
  Changed to call allEntryIDsVisibleFromDomain with an empty domain.

SQLSource.m fetchContactsMatching:inDomain:
  Use _visibleDomainsQualifierFromDomain to filter entries

LDAPSource.m: allEntryIDsVisibleFromDomain
  Simply call allEntryIDs, discarding the domain.
  LDAP does need to do the extra domain filtering

SOGoContactSourceFolder.m: toOneRelationshipKeys
   Call new method: allEntryIDsVisibleFromDomain
2013-03-29 10:38:52 -04:00
Ludovic Marcotte 6a8e6cd762 Fixed the GNUmakfile and const's for charset tables. 2013-03-28 08:32:00 -04:00
Ludovic Marcotte 663351029a Replaced unrtf by our own RTF to HTML converter.
Faster, thread safe, a hell lot cleaner.
2013-03-26 19:32:08 -04:00
Jean Raby c26e5fa7fe semi-colon 2013-03-26 14:01:04 -04:00
Jean Raby 74c01dc448 gen-charset-table.py: script to import ms charmaps
For example: http://msdn.microsoft.com/en-us/goglobal/cc305147
2013-03-26 13:42:22 -04:00
Ludovic Marcotte a009c71034 Fixed table initialization. 2013-03-25 15:58:36 -04:00
Jean Raby b4ebc90dd0 replace subprocess.check_output with Popen magic
check_output isn't available in py 2.6...
2013-03-25 14:12:12 -04:00
Jean Raby 95dc134ca6 Revamped openchange_cleanup.py
This is now usable again.

  - Don't delete password files in mapistoreCleanup()
  - reworked the ldb cleanup and enabled it
  - sql cleanup should now be able to figure out the db info from the config
    regardless of the format used (xml, plist, sogo.conf or GNUstepDefaults)
    (We really need a python plist parser.. the current solution is not elegant)
  - Inform user of missing python packages
2013-03-22 15:13:39 -04:00
Jean Raby 9c4b7d8481 Add notes regarding html mails and mod_reqtimeout 2013-03-21 15:39:02 -04:00
Jean Raby 9fb9f2cae6 Enable saml2 support on squeeze (temporary fix) 2013-03-20 11:51:37 -04:00
Francis Lachapelle 15f9b7d22e Fix comments in UIxContactFolderActions.* 2013-03-15 11:23:27 -04:00
Francis Lachapelle 5f179ed6b0 Activate the menu option "Mark Folder Read"
Fixes #1473
2013-03-15 11:06:26 -04:00
Ludovic Marcotte 93f9a7273e Now handle mem context when saving messages and removed useless debugging. 2013-03-13 15:04:11 -04:00
Jean Raby 15e082896c Update sogo-tool expire-autoreply syntax in cron 2013-03-12 09:08:19 -04:00
Jean Raby 63ff9751d7 Add ics_compare and use it in _testRespondTo()
This new class uses vobject.ics_diff() to compare 2 VCALENDAR components.
We should use this instead of textually comparing events for equality
in future tests.
2013-03-11 11:37:59 -04:00
Francis Lachapelle d12c651d59 New system default SOGoEncryptionKey
To be used to encrypt the passwords of remote Web calendars when
SOGoTrustProxyAuthentication is enabled.
2013-03-11 09:34:36 -04:00
Jean Raby 41a6c02aa3 Rework web services section
State that HTTPS is mandatory for autodiscovery services.
Add example named config for SRV record.
2013-03-08 16:20:27 -05:00
Jean Raby a026e75c0e Removed note about linefeed in password files
This is handled by the code now
2013-03-08 15:57:10 -05:00
Ludovic Marcotte 46815042c9 Fixed bug when modifying/deleting exceptions of recurring events. 2013-03-07 09:29:56 -05:00
Jean Raby c79af52b67 Fix BSONCodec.m includes
include objc.h instead of runtime.h so that it works on older gcc objc runtime
2013-03-06 11:03:19 -05:00
Jean Raby e882dedac9 Update News 2013-03-05 11:01:51 -05:00
Jean Raby 13277bbdb9 c_content TEXT to LONGTEXT for OpenChange tables
Add an script to update existing tables.
Note that if a row already have 65535 char in it,
the data is most likely broken.
2013-03-05 10:47:09 -05:00
Francis Lachapelle 7e8a83aefb Fix Slovak templates for mail reply/forward 2013-03-05 10:22:20 -05:00
Jean Raby f1846191d5 Use an autorelease pool in member expansion
Otherwise, we would hold one ldap connection for each member of a group.
And close them all later. With large groups, we could hit the open file limit
(or the open file limit of the ldap server).

Fixes #2256
2013-03-01 16:24:16 -05:00
Jean Raby a7c3f33447 Whitespace 2013-03-01 01:26:15 -05:00
Ludovic Marcotte a8d67edb44 Merge branch 'master' of https://github.com/inverse-inc/sogo 2013-02-20 12:11:17 -05:00
Ludovic Marcotte 89766b2e7e Temporary fix for unsigned long long values. 2013-02-20 12:10:34 -05:00
Jean Raby 7d65d808f6 Strip newline characters from user password files
Makes it easier to create those files with a regular editor.
2013-02-20 10:50:58 -05:00
Ludovic Marcotte fa5e99d58d Much better fix over previous commit. 2013-02-19 15:54:52 -05:00
Ludovic Marcotte 67c2d508ea Added rationale around previous commit. 2013-02-19 15:42:05 -05:00
Ludovic Marcotte 19923d10db Also handle date-strings as date objects.
Dates are stored as string in BSON - might change in the future.
2013-02-19 15:30:29 -05:00
Ludovic Marcotte e57b6835e6 Fix for objective-c runtimes. 2013-02-18 16:50:54 -05:00
Ludovic Marcotte bcab7e7dc9 C99 style fixes. 2013-02-18 16:42:59 -05:00
Ludovic Marcotte 2572eedd89 Added BSON encoder/decoder for Outlook cache files. 2013-02-18 16:28:06 -05:00
Francis Lachapelle efb45bfba6 Fix issue with exceptions in repeating events
Fixed the display of an exception when its recurrence id is outside the
current view.
2013-02-15 15:17:08 -05:00
Ludovic Marcotte 4f38b5cf3f Alse use hex-formatted keys for deleted mails. 2013-02-14 15:59:19 -05:00
Ludovic Marcotte 71b9772546 Ensure we hit the cache with hex-formatted keys. 2013-02-14 15:22:48 -05:00
Francis Lachapelle c13c389ae5 Update Danish translation 2013-02-12 08:42:47 -05:00
Jean Raby caf6f0ec6c Add example apache configuration for apple AB 2013-02-11 10:41:50 -05:00
Jean Raby 4952ff7914 Use SOGoSystemDefaults in all tools
sogo-ealarms-notify and sogo-slapd-sockd will now be able to use sogo.conf
Fixes #2226
2013-02-08 16:22:14 -05:00
Francis Lachapelle 8981dcd645 Fix segfault in SOGoSieveManager.m 2013-02-08 09:42:31 -05:00
Jean Raby 470a53a548 Add example configuration for fail2ban
From Arnd Brandes. (#2229)
2013-02-07 13:00:27 -05:00
Francis Lachapelle 7b65b7400e Update Finnish translation 2013-02-07 09:00:16 -05:00
Francis Lachapelle 90c61abdb6 Update Polish translation 2013-02-06 15:16:09 -05:00
Jean Raby f8387b90ff Log x-webobjects-remote-host in login process
Most of the time, the remote-host will contain data from the x-forwarded-for header.
Which could have more than one ip in it if the request went through multiple proxies.
eg. x-forwarded-for: real.client.ip, load.balancer.ip
2013-02-06 09:23:47 -05:00
Francis Lachapelle feb02c54b9 Add missing localizable string 2013-02-05 16:13:18 -05:00
Ludovic Marcotte 49a2299414 Avoid going out of bounds for special URL chars ending mail contents. 2013-02-05 16:11:37 -05:00
Jean Raby 43044bf88f Plug sieve connection leak
Fixes #2228
Fix from 'bofhus'
2013-02-05 15:09:55 -05:00
Jean Raby 0532d331a3 whitespace (tabkill) 2013-02-05 15:09:20 -05:00
Jean Raby 70fc05091f Remove x-webobjects-remote-host from apache conf
SOPE now handles this on its own by setting x-webobjects-remote-host
to the content of the x-forward or x-forwarded-for headers if it wasn't defined
2013-02-05 14:27:16 -05:00
Jean Raby 469e5c647e Updated NEWS 2013-02-05 11:52:26 -05:00
Jean Raby 4bfb43a4ad Merge 'tests/authcache' - don't use cache on login 2013-02-05 11:40:47 -05:00
Francis Lachapelle 5e0c7ae4f2 Merge to 2.0.4b 2013-02-04 14:24:46 -05:00
Francis Lachapelle 3daa7e55b7 Update ChangeLog 2013-02-04 14:24:03 -05:00
Francis Lachapelle 6913502810 Bump version to 2.0.4b 2013-02-04 14:22:37 -05:00
Jean Raby 24971070f6 Updated NEWS 2013-02-04 14:03:28 -05:00
Jean Raby 3d90e3a539 Bump userkey length from 64 to 160 bytes
Allows for much longer username@domain:password strings.
Fixes #2212

To bump it further, the database schema will have to be updated
to allow a longer c_value (currently 255 chars)
2013-02-04 13:55:53 -05:00
Francis Lachapelle b5fdaa78cd Add missing strings to mail module
The two columns names of the contacts pane were missing. They have
been copied from the contact module.
2013-02-04 08:58:37 -05:00
Francis Lachapelle f94adb5473 Update NEWS file 2013-02-03 20:42:20 -05:00
Francis Lachapelle e34ba5689c Fix saving prefs with disabled mail module 2013-02-03 20:40:06 -05:00
Jean Raby 7b5da8a2c9 don't use cache for login page 2013-02-01 19:58:25 -05:00
Jean Raby 451c82c815 Don't use user/password cache from the login page
The idea is to always use memcached for credentials to avoid hitting
the authentication backend on every click but to check with the auth backend
for every login requests.

This should fix #2169

While there, fix whitespace (killtab)
2013-02-01 18:35:10 -05:00
Jean Raby 488a76c5e3 Merge branch 'test/userdefaults' 2013-02-01 16:31:56 -05:00
Jean Raby a4bd966cc0 Revisit option handling
Really fix #2166
The previous fix (46b53b3) was wrong since SOPE was able to override
the 'final' config with its defaults.

This now uses a new approach using a volatile domain and a reordering
of the search list :
  *   NSArgumentDomain (command line arguments)
  *   sogodRuntimeDomain (config from all config files)
  *   GSPrimaryDomain
  *   NSGlobalDomain
  *   GSConfigDomain
  *   (languages)
  *   NSRegistrationDomain (SOPE loads its defaults in this one)
2013-02-01 16:26:01 -05:00
Francis Lachapelle ecc36c9025 Fix classification menu in component editor 2013-02-01 14:47:37 -05:00
Francis Lachapelle 716daf027d Fix link to ACL editor for any authenticated user 2013-02-01 14:46:05 -05:00
Jean Raby 0b7c32510b news file update for 2.0.4b 2013-02-01 10:40:59 -05:00
jraby 547dfa0d90 Merge pull request #9 from inverse-inc/fix/2066_options-precedence
Fix/2066 options precedence
2013-01-31 18:42:09 -08:00
Jean Raby 225a28258f Read credential files using dataWithContentsOfFile
Again, to cope with older gnusteps which don't have
stringWithContentsOfFile:encoding:error:
2013-01-31 16:44:14 -05:00
Jean Raby e01b190e57 Fixup handling NSArgumentDomain arguments
would fix #2216
2013-01-31 15:42:48 -05:00
Francis Lachapelle cd7d410262 Fix tooltips in contacts list 2013-01-31 13:55:57 -05:00
Francis Lachapelle 4bcf90c693 Fix "Send Anyway" string wrt localizable strings 2013-01-31 09:44:29 -05:00
Francis Lachapelle 0408415c61 Remove control characters before returning JSON 2013-01-30 15:47:20 -05:00
Francis Lachapelle c1c0c1ab44 Merge to 2.0.4a 2013-01-30 08:54:00 -05:00
Francis Lachapelle 3ea94940c2 Update ChangeLog 2013-01-30 08:52:32 -05:00
Francis Lachapelle 321675ba99 Bump version to 2.0.4a 2013-01-30 08:51:10 -05:00
Francis Lachapelle 9eb1418e36 Update French translation 2013-01-30 08:49:16 -05:00
Francis Lachapelle d8804c699d Format birthday on contact card 2013-01-30 08:43:02 -05:00
Francis Lachapelle 4e9db74e29 Update NEWS file 2013-01-29 15:04:57 -05:00
Francis Lachapelle 7150ebde6b Update updates.php 2013-01-29 15:03:37 -05:00
Francis Lachapelle 6fbd975e00 Update NEWS file 2013-01-29 15:02:51 -05:00
Francis Lachapelle e0a1a47953 Code cleanup in UIxAppointmentEditor.m 2013-01-29 14:53:57 -05:00
Francis Lachapelle da757a19c6 Fix handling of decoding contacts UID
A problem occurs when the contact UID contains a special character that
was HTML encoded (ex: space, &, ").
2013-01-28 22:05:54 -05:00
Jean Raby ea13fd14c9 Use older NSPropertyListSerialization methods
dataWithPropertyList and propertyListWithData didn't exist in gnustep 1.20
which is shipped with debian-squeeze.
2013-01-29 10:31:16 -05:00
Francis Lachapelle 902a5d8f70 Fix saving all-day event in appointment editor 2013-01-28 18:43:45 -05:00
Francis Lachapelle be0090be06 Fix until date in component editor 2013-01-28 16:44:14 -05:00
Francis Lachapelle 2d455bf0ca Fix possible infinite loop in repeataable object 2013-01-28 09:51:42 -05:00
Francis Lachapelle 1d8e72646c Update Czech translation 2013-01-28 08:43:58 -05:00
Ludovic Marcotte c066136a06 Reverted code that was causing issues with groups (#2090) 2013-01-28 08:34:40 -05:00
Jean Raby 46b53b31fd Fix order of precedence for options
Fixes #2066 and #2166
Enforce the following order of precedence for options, first match wins:
  1. Command line arguments
  2. .GNUstepDefaults
  3. /etc/sogo/{debconf,sogo}.conf
  4. SOGoDefaults.plist
2013-01-24 22:43:38 -05:00
Jean Raby 6093c4dd2e Axe handling of sogo 0.9 gnustep domain migration 2013-01-24 20:37:30 -05:00
Jean Raby 61ded01171 whitespace - tabkill 2013-01-24 20:35:03 -05:00
672 changed files with 31241 additions and 19745 deletions

No files matched your search

+2
View File
@@ -9,3 +9,5 @@ tags
*.swp
SoObjects/SOGo/SOGo.framework/
SoObjects/SOGo/derived_src/
Tests/*/config.py
*.pyc
+11 -1
View File
@@ -1,9 +1,10 @@
[main]
host = https://www.transifex.net
host = https://www.transifex.com
[sogo.ui-mailerui]
source_file = UI/MailerUI/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/MailerUI/Arabic.lproj/Localizable.strings
trans.ca = UI/MailerUI/Catalan.lproj/Localizable.strings
trans.cs = UI/MailerUI/Czech.lproj/Localizable.strings
trans.cy = UI/MailerUI/Welsh.lproj/Localizable.strings
@@ -29,6 +30,7 @@ trans.uk = UI/MailerUI/Ukrainian.lproj/Localizable.strings
[sogo.ui-preferencesui]
source_file = UI/PreferencesUI/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/PreferencesUI/Arabic.lproj/Localizable.strings
trans.ca = UI/PreferencesUI/Catalan.lproj/Localizable.strings
trans.cs = UI/PreferencesUI/Czech.lproj/Localizable.strings
trans.cy = UI/PreferencesUI/Welsh.lproj/Localizable.strings
@@ -54,6 +56,7 @@ trans.uk = UI/PreferencesUI/Ukrainian.lproj/Localizable.strings
[sogo.ui-scheduler]
source_file = UI/Scheduler/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/Scheduler/Arabic.lproj/Localizable.strings
trans.ca = UI/Scheduler/Catalan.lproj/Localizable.strings
trans.cs = UI/Scheduler/Czech.lproj/Localizable.strings
trans.cy = UI/Scheduler/Welsh.lproj/Localizable.strings
@@ -79,6 +82,7 @@ trans.uk = UI/Scheduler/Ukrainian.lproj/Localizable.strings
[sogo.ui-contacts]
source_file = UI/Contacts/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/Contacts/Arabic.lproj/Localizable.strings
trans.ca = UI/Contacts/Catalan.lproj/Localizable.strings
trans.cs = UI/Contacts/Czech.lproj/Localizable.strings
trans.cy = UI/Contacts/Welsh.lproj/Localizable.strings
@@ -104,6 +108,7 @@ trans.uk = UI/Contacts/Ukrainian.lproj/Localizable.strings
[sogo.ui-mainui]
source_file = UI/MainUI/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/MainUI/Arabic.lproj/Localizable.strings
trans.ca = UI/MainUI/Catalan.lproj/Localizable.strings
trans.cs = UI/MainUI/Czech.lproj/Localizable.strings
trans.cy = UI/MainUI/Welsh.lproj/Localizable.strings
@@ -129,6 +134,7 @@ trans.uk = UI/MainUI/Ukrainian.lproj/Localizable.strings
[sogo.ui-common]
source_file = UI/Common/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/Common/Arabic.lproj/Localizable.strings
trans.ca = UI/Common/Catalan.lproj/Localizable.strings
trans.cs = UI/Common/Czech.lproj/Localizable.strings
trans.cy = UI/Common/Welsh.lproj/Localizable.strings
@@ -154,6 +160,7 @@ trans.uk = UI/Common/Ukrainian.lproj/Localizable.strings
[sogo.ui-administrationui]
source_file = UI/AdministrationUI/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/AdministrationUI/Arabic.lproj/Localizable.strings
trans.ca = UI/AdministrationUI/Catalan.lproj/Localizable.strings
trans.cs = UI/AdministrationUI/Czech.lproj/Localizable.strings
trans.cy = UI/AdministrationUI/Welsh.lproj/Localizable.strings
@@ -179,6 +186,7 @@ trans.uk = UI/AdministrationUI/Ukrainian.lproj/Localizable.strings
[sogo.soobjects-appointments]
source_file = SoObjects/Appointments/English.lproj/Localizable.strings
source_lang = en
trans.ar = SoObjects/Appointments/Arabic.lproj/Localizable.strings
trans.ca = SoObjects/Appointments/Catalan.lproj/Localizable.strings
trans.cs = SoObjects/Appointments/Czech.lproj/Localizable.strings
trans.cy = SoObjects/Appointments/Welsh.lproj/Localizable.strings
@@ -204,6 +212,7 @@ trans.uk = SoObjects/Appointments/Ukrainian.lproj/Localizable.strings
[sogo.soobjects-contacts]
source_file = SoObjects/Contacts/English.lproj/Localizable.strings
source_lang = en
trans.ar = SoObjects/Contacts/Arabic.lproj/Localizable.strings
trans.ca = SoObjects/Contacts/Catalan.lproj/Localizable.strings
trans.cs = SoObjects/Contacts/Czech.lproj/Localizable.strings
trans.cy = SoObjects/Contacts/Welsh.lproj/Localizable.strings
@@ -229,6 +238,7 @@ trans.uk = SoObjects/Contacts/Ukrainian.lproj/Localizable.strings
[sogo.ui-mailpartviewers]
source_file = UI/MailPartViewers/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/MailPartViewers/Arabic.lproj/Localizable.strings
trans.ca = UI/MailPartViewers/Catalan.lproj/Localizable.strings
trans.cs = UI/MailPartViewers/Czech.lproj/Localizable.strings
trans.cy = UI/MailPartViewers/Welsh.lproj/Localizable.strings
+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 */
+39
View File
@@ -0,0 +1,39 @@
# GNUstep makefile
include common.make
BUNDLE_NAME = ActiveSync
ActiveSync_PRINCIPAL_CLASS = ActiveSyncProduct
ActiveSync_OBJC_FILES = \
ActiveSyncProduct.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 \
NSString+ActiveSync.m \
SOGoActiveSyncDispatcher.m \
SOGoActiveSyncDispatcher+Sync.m \
SOGoMailObject+ActiveSync.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/
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
+158
View File
@@ -0,0 +1,158 @@
/*
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)
//
// 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", 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];
// Handle inner data - see above for samples
if (count > 2)
{
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]])
{
[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;
}
}
else
value = [[element firstChild] textValue];
if (value && tag)
[data setObject: value forKey: tag];
}
}
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
+308
View File
@@ -0,0 +1,308 @@
/*
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
{
CardElement *n, *homeAdr, *workAdr;
NSArray *emails, *addresses;
NSMutableString *s;
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 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 activeSyncRepresentationWithoutSeparatorsInContext: 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];
// 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];
}
// Email addresses
if ((o = [theValues objectForKey: @"Email1Address"]))
{
[self addEmail: o types: [NSArray arrayWithObject: @"pref"]];
}
if ((o = [theValues objectForKey: @"Email2Address"]))
{
[self addEmail: o types: nil];
}
if ((o = [theValues objectForKey: @"Email3Address"]))
{
[self addEmail: o types: nil];
}
// 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: @""];
}
}
@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-%d-T%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
+54
View File
@@ -0,0 +1,54 @@
/*
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 *) command;
- (NSData *) convertHexStringToBytes;
@end
#endif
+283
View File
@@ -0,0 +1,283 @@
/*
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;
}
//
//
//
- (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
+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.
*/
#import <Foundation/NSObject.h>
#include "SOGoActiveSyncConstants.h"
@class NSException;
@interface SOGoActiveSyncDispatcher : NSObject
{
id context;
}
- (id) collectionFromId: (NSString *) theCollectionId
type: (SOGoMicrosoftActiveSyncFolderType) theFolderType;
- (NSException *) dispatchRequest: (id) theRequest
inResponse: (id) theResponse
context: (id) theContext;
@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
+638
View File
@@ -0,0 +1,638 @@
/*
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/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/NSString+misc.h>
#import <NGExtensions/NSString+Encoding.h>
#import <NGImap4/NGImap4Envelope.h>
#import <NGImap4/NGImap4EnvelopeAddress.h>
#import <NGObjWeb/WOContext+SoObjects.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;
NSMutableArray *addresses;
NSString *email, *rc;
int i, max;
rc = nil;
max = [enveloppeAddresses count];
if (max > 0)
{
addresses = [NSMutableArray array];
for (i = 0; i < max; i++)
{
address = [enveloppeAddresses objectAtIndex: i];
email = [NSString stringWithFormat: @"\"%@\" <%@>", [address personalName], [address baseEMail]];
if (email)
[addresses addObject: email];
}
rc = [addresses componentsJoinedByString: @", "];
}
return rc;
}
//
//
//
- (NSData *) _preferredBodyDataInMultipartUsingType: (int) theType
{
NSString *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;
}
if (theType == 2)
{
d = [[self fetchPlainTextParts] objectForKey: htmlKey];
}
else if (theType == 1)
{
d = [[self fetchPlainTextParts] objectForKey: plainKey];
}
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];
// 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)
{
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
{
NSData *d, *globalObjId;
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 activeSyncRepresentationWithoutSeparatorsInContext: 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.
[s appendFormat: @"<InternetCPID xmlns=\"Email:\">%@</InternetCPID>", @"65001"];
// Body - namespace 17
preferredBodyType = [[context objectForKey: @"BodyPreferenceType"] intValue];
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.
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: @"<EstimatedDataSize>%d</EstimatedDataSize>", len];
[s appendFormat: @"<Truncated>%d</Truncated>", 0];
if (!truncated)
[s appendFormat: @"<Data>%@</Data>", content];
[s appendString: @"</Body>"];
}
// Attachments -namespace 16
NSArray *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;
}
//
//
//
- (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"];
}
}
@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,Provision,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
+36
View File
@@ -0,0 +1,36 @@
# common make file for SoObject bundles
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../SOGo/SOGo.framework/ \
-L../../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)
+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
+471
View File
@@ -0,0 +1,471 @@
/*
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 "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;
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])
[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])
[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]];
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
// 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)
{
[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)
{
[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];
}
}
// 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
+355
View File
@@ -0,0 +1,355 @@
/*
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/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;
for (i = 0; i < 7; i++)
{
if (occurrences[i])
v += (1 << i);
}
[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 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 );
}
+74
View File
@@ -0,0 +1,74 @@
#
#
# 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
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" "8800"
RequestHeader set "x-webobjects-server-name" "changethis:8800"
RequestHeader set "x-webobjects-server-url" "http://changethis:8800"
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>
+14 -12
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"
@@ -59,7 +61,6 @@ ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0
# RequestHeader set "x-webobjects-remote-user" "%{REMOTE_USER}e"
RequestHeader set "x-webobjects-server-protocol" "HTTP/1.0"
RequestHeader set "x-webobjects-remote-host" %{REMOTE_HOST}e env=REMOTE_HOST
AddDefaultCharset UTF-8
@@ -67,8 +68,9 @@ ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0
Allow from all
</Proxy>
## We use mod_rewrite to pass remote address to the SOGo proxy.
# The remote address will appear in SOGo's log files and in the X-Forward
# header of emails.
RewriteEngine On
RewriteRule ^/SOGo/(.*)$ /SOGo/$1 [env=REMOTE_HOST:%{REMOTE_ADDR},PT]
# For Apple autoconfiguration
<IfModule rewrite_module>
RewriteEngine On
RewriteRule ^/.well-known/caldav/?$ /SOGo/dav [R=301]
</IfModule>
+5662
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
+268 -1
View File
@@ -1,4 +1,270 @@
2.0.4 (2013-01-DD)
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
- fixed loading of MSExchangeFreeBusySOAPResponseMap
2.0.6a (2013-06-25)
------------------
Bug fixes
- documentation fixes
- added missing file for CAS single logout
2.0.6 (2013-06-21)
------------------
Enhancements
- updated CKEditor to version 4.1.1 (#2333)
- new failed login attemps rate-limiting options. See the new
SOGoMaximumFailedLoginCount, SOGoMaximumFailedLoginInterval and
SOGoFailedLoginBlockInterval defaults
- new message submissions rate-limiting options. See the new
SOGoMaximumMessageSubmissionCount, SOGoMaximumRecipientCount,
SOGoMaximumSubmissionInterval and SOGoMessageSubmissionBlockInterval defaults
- now possible to send or not event notifications on a per-event basis
- now possible to see who created an event/task in a delegated calendar
- multi-domain support in OpenChange (implemented using a trick)
Bug fixes
- fixed decoding of the charset parameter when using single quotes (#2306)
- fixed potential crash when sending MDN from Sent folder (#2209)
- fixed handling of unicode separators (#2309)
- fixed public access when SOGoTrustProxyAuthentication is used (#2237)
- fixed access right issues with import feature (#2294)
- fixed IMAP ACL issue when SOGoForceExternalLoginWithEmail is used (#2313)
- fixed handling of CAS logoutRequest (#2346)
- fixed many major OpenChange stability issues
2.0.5a (2013-04-17)
------------------
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
2.0.5 (2013-04-11)
------------------
New features
- new system default SOGoEncryptionKey to be used to encrypt the passwords of
remote Web calendars when SOGoTrustProxyAuthentication is enabled
- activated the menu option "Mark Folder Read" in the Webmail (#1473)
Enhancements
- added logging of the X-Forwarded-For HTTP header (#2229)
- now use BSON instead of GNUstep's binary format for serializing
Outlook related cache files
- updated Danish, Finnish, Polish and Slovak translations
- added Arabic translation - thanks to Anass Ahmed
Bug fixes
- don't use the cache for password lookups from login page (#2169)
- fixed issue with exceptions in repeating events
- avoid data truncation issue in OpenChange with mysql backend
run sql-update-2.0.4b_to_2.0.5-mysql.sh to update existing tables
- avoid random crashes in OpenChange due to RTF conversion
- fixed issue when modifying/deleting exceptions of recurring events
- fixed major cache miss issue leading to slow Outlook resynchronizations
- fixed major memory corruption issue when Outlook was saving "messages"
- fixed filtering of sql contact entries when using dynamic domains (#2269)
- sogo.conf can now be used by all tools (#2226)
- SOPE: fixed handling of sieve capabilities after starttls (#2132)
- OpenChange: fixed 'stuck email' problem when sending a mail
- OpenChange NTLMAuthHandler: avoid tightloop when samba isn't available.
- OpenChange NTLMAuthHandler: avoid crash while parsing cookies
- OpenChange ocsmanager: a LOT of fixes, see git log
2.0.4b (2013-02-04)
------------------
Bug fixes
- Fixed order of precedence for options (#2166)
The following order is enforced - first match wins
1. Command line arguments
2. .GNUstepDefaults
3. /etc/sogo/{debconf,sogo}.conf
4. SOGoDefaults.plist
- fixed handling of LDAP DN containing special characters (#2152, #2207)
- fixed handling of credential files for older GNUsteps (#2216)
- fixed display of messages with control characters (#2079, #2177)
- fixed tooltips in contacts list (#2211)
- fixed classification menu in component editor (#2223)
- fixed link to ACL editor for 'any authenticated user' (#2222, #2224)
- fixed saving preferences when mail module is disabled
- fixed handling for long credential strings (#2212)
2.0.4a (2013-01-30)
------------------
Enhancements
- updated Czech translation
- birthday is now properly formatted in addressbook module
Bug fixes
- fixed handling of groups with spaces in their UID
- fixed possible infinite loop in repeatable object
- fixed until date in component editor
- fixed saving all-day event in appointment editor
- fixed handling of decoding contacts UID
- fixed support of GNUstep 1.20 / Debian Squeeze
2.0.4 (2013-01-25)
------------------
New features
@@ -18,6 +284,7 @@ Enhancements
- updated translations
- recurrence-id of all-day events is now set as a proper date with no time
- 'show completed tasks' is now persistent
- fixed memory usage consumption for remote ICS subscriptions
Bug fixes
- fixed usage of browser's language for the login page
+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;
},
{
+50
View File
@@ -0,0 +1,50 @@
//
// BSONCodec.h
// BSON Codec for Objective-C.
//
// Created by Martin Kou on 8/17/10.
// MIT License, see LICENSE file for details.
//
#import <Foundation/Foundation.h>
#import <stdint.h>
@protocol BSONCoding
- (uint8_t) BSONTypeID;
- (NSData *) BSONEncode;
- (NSData *) BSONRepresentation;
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) typeID;
@end
@protocol BSONObjectCoding
- (id) initWithBSONDictionary: (NSDictionary *) data;
- (NSDictionary *) BSONDictionary;
@end
@interface NSObject (BSONObjectCoding)
- (NSData *) BSONEncode;
- (NSData *) BSONRepresentation;
@end
@interface NSDictionary (BSON) <BSONCoding>
@end
@interface NSData (BSON) <BSONCoding>
- (NSDictionary *) BSONValue;
@end
@interface NSNumber (BSON) <BSONCoding>
@end
@interface NSString (BSON) <BSONCoding>
@end
@interface NSArray (BSON) <BSONCoding>
@end
@interface NSNull (BSON) <BSONCoding>
@end
@interface NSCalendarDate (BSON) <BSONCoding>
@end
+589
View File
@@ -0,0 +1,589 @@
//
// BSONCodec.m
// BSON Codec for Objective-C.
//
// Created by Martin Kou on 8/17/10.
// MIT License, see LICENSE file for details.
//
#import "BSONCodec.h"
#import <ctype.h>
#import <string.h>
#import <objc/objc.h>
#define BSONTYPE(tag,className) [className class], [NSNumber numberWithChar: (tag)]
#ifndef objc_msgSend
#define objc_msgSend(obj, sel, ...) \
objc_msg_lookup(obj, sel)(obj, sel, ## __VA_ARGS__)
#endif
static NSDictionary *BSONTypes()
{
static NSDictionary *retval = nil;
if (retval == nil)
{
retval = [[NSDictionary dictionaryWithObjectsAndKeys:
BSONTYPE(0x01, NSNumber),
BSONTYPE(0x02, NSString),
BSONTYPE(0x03, NSDictionary),
BSONTYPE(0x04, NSArray),
BSONTYPE(0x05, NSData),
BSONTYPE(0x08, NSNumber),
BSONTYPE(0x0A, NSNull),
BSONTYPE(0x10, NSNumber),
BSONTYPE(0x11, NSCalendarDate),
BSONTYPE(0x12, NSNumber),
nil] retain];
}
return retval;
}
#define SWAP16(x) \
((uint16_t)((((uint16_t)(x) & 0xff00) >> 8) | \
(((uint16_t)(x) & 0x00ff) << 8)))
#define SWAP32(x) \
((uint32_t)((((uint32_t)(x) & 0xff000000) >> 24) | \
(((uint32_t)(x) & 0x00ff0000) >> 8) | \
(((uint32_t)(x) & 0x0000ff00) << 8) | \
(((uint32_t)(x) & 0x000000ff) << 24)))
#define SWAP64(x) \
((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \
(((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \
(((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \
(((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \
(((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \
(((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \
(((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \
(((uint64_t)(x) & 0x00000000000000ffULL) << 56)))
#if BYTE_ORDER == LITTLE_ENDIAN
#define BSONTOHOST16(x) (x)
#define BSONTOHOST32(x) (x)
#define BSONTOHOST64(x) (x)
#define HOSTTOBSON16(x) (x)
#define HOSTTOBSON32(x) (x)
#define HOSTTOBSON64(x) (x)
#elif BYTE_ORDER == BIG_ENDIAN
#define BSONTOHOST16(x) SWAP16(x)
#define BSONTOHOST32(x) SWAP32(x)
#define BSONTOHOST64(x) SWAP64(x)
#define HOSTTOBSON16(x) SWAP16(x)
#define HOSTTOBSON32(x) SWAP16(x)
#define HOSTTOBSON64(x) SWAP16(x)
#endif
#define CLASS_NAME_MARKER @"$$__CLASS_NAME__$$"
@implementation NSObject (BSONObjectCoding)
- (NSData *) BSONEncode
{
if (![self conformsToProtocol: @protocol(BSONObjectCoding)])
[NSException raise: NSInvalidArgumentException format: @"BSON encoding is only valid on objects conforming to the BSONObjectEncoding protocol."];
id <BSONObjectCoding> myself = (id <BSONObjectCoding>) self;
NSMutableDictionary *values = [[myself BSONDictionary] mutableCopy];
#if (defined(__GNU_LIBOBJC__) && (__GNU_LIBOBJC__ >= 20100911)) || defined(APPLE_RUNTIME) || defined(__GNUSTEP_RUNTIME__)
const char* className = class_getName([self class]);
#else
const char* className = [self class]->name;
#endif
[values setObject: [NSData dataWithBytes: (void *)className length: strlen(className)] forKey: CLASS_NAME_MARKER];
NSData *retval = [values BSONEncode];
[values release];
return retval;
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
@end
@implementation NSDictionary (BSON)
- (uint8_t) BSONTypeID
{
return 0x03;
}
- (NSData *) BSONEncode
{
// Initialize the components structure.
NSMutableArray *components = [[NSMutableArray alloc] init];
NSMutableData *lengthData = [[NSMutableData alloc] initWithLength: 4];
[components addObject: lengthData];
[lengthData release];
NSMutableData *contentsData = [[NSMutableData alloc] init];
[components addObject: contentsData];
[contentsData release];
[components addObject: [NSData dataWithBytes: "\x00" length: 1]];
// Ensure ordered keys. not in BSON spec, but ensures all BSONRepresentations
// of the same dict will be the same.
NSMutableArray *keys = [[NSMutableArray alloc] init];
[keys addObjectsFromArray: [self allKeys]];
//[keys sortUsingSelector: @selector(caseInsensitiveCompare:)];
// Encode data.- (NSData *) BSONEncode;
uint8_t elementType = 0;
int i;
for (i = 0; i < [keys count]; i++)
{
NSString *key = [keys objectAtIndex: i];
NSObject *value = [self objectForKey: key];
if ([value respondsToSelector: @selector(BSONTypeID)])
elementType = [(id <BSONCoding>) value BSONTypeID];
else
elementType = 3;
[contentsData appendBytes: &elementType length: 1];
[contentsData appendData: [key dataUsingEncoding: NSUTF8StringEncoding]];
[contentsData appendBytes: "\x00" length: 1];
[contentsData appendData: [value BSONEncode]];
}
[keys release];
// Write length.
uint32_t *length = (uint32_t *)[lengthData mutableBytes];
*length = HOSTTOBSON32([contentsData length]) + 4 + 1;
// Assemble the output data.
NSMutableData *retval = [NSMutableData data];
for (i = 0; i < [components count]; i++)
[retval appendData: [components objectAtIndex: i]];
[components release];
return retval;
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) t
{
const void *current = [data bytes];
if ((id)base != nil)
current = *base;
else
base = &current;
uint32_t length = BSONTOHOST32(*((uint32_t *)current));
const void *endPoint = current + length;
current += 4;
NSMutableDictionary *retval = [NSMutableDictionary dictionary];
while (current < endPoint - 1)
{
uint8_t typeID = *((uint8_t *)current);
current++;
char *utf8Key = (char *) current;
while (*((char *)current) != 0 && current < endPoint - 1)
current++;
current++;
NSString *key = [NSString stringWithUTF8String: utf8Key];
*base = current;
Class typeClass = [BSONTypes() objectForKey: [NSNumber numberWithChar: typeID]];
id value = objc_msgSend(typeClass, @selector(BSONFragment:at:ofType:), data, base, typeID);
current = *base;
[retval setObject: value forKey: key];
}
*base = current + 1;
// If the dictionary has a class name marker, then it is to be converted to an object.
if ([retval objectForKey: CLASS_NAME_MARKER] != nil)
{
NSData *classNameData = [retval objectForKey: CLASS_NAME_MARKER];
char *className = malloc([classNameData length] + 1);
memcpy(className, [classNameData bytes], [classNameData length]);
className[[classNameData length]] = 0;
Class targetClass = objc_getClass(className);
if (targetClass == nil)
[NSException raise: NSInvalidArgumentException format: @"Class %s found in incoming data is undefined.", className];
id obj = [[targetClass alloc] initWithBSONDictionary: retval];
return obj;
}
return retval;
}
@end
@implementation NSData (BSON)
- (uint8_t) BSONTypeID
{
return 0x05;
}
- (NSData *) BSONEncode
{
uint32_t length = HOSTTOBSON32([self length]);
NSMutableData *retval = [NSMutableData data];
[retval appendBytes: &length length: 4];
[retval appendBytes: "\x00" length: 1];
[retval appendData: self];
return retval;
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) t
{
const void *current = [data bytes];
if ((id)base != nil)
current = *base;
else
base = &current;
uint32_t length = BSONTOHOST32(*((uint32_t *)current));
current += 4 + 1;
NSData *retval = [NSData dataWithBytes: current length: length];
current += length;
*base = current;
return retval;
}
- (NSDictionary *) BSONValue
{
return [NSDictionary BSONFragment: self at: NULL ofType: 0x03];
}
@end
@implementation NSNumber (BSON)
- (uint8_t) BSONTypeID
{
const char encoding = tolower(*([self objCType]));
switch (encoding) {
case 'f':
case 'd': return 0x01;
case 'b': return 0x08;
case 'c':
case 's': return 0x10;
case 'i':
// Ok, if you're running Objective-C on 16-bit platforms...
// Then YOU have issues.
// So, yeah, we won't handle that case.
if (sizeof(int) == 4)
return 0x10;
else if (sizeof(int) == 8)
return 0x12;
case 'l':
if (sizeof(long) == 4)
return 0x10;
else if (sizeof(long) == 8)
return 0x12;
case 'q': return 0x12;
default:
[NSException raise: NSInvalidArgumentException format: @"%@::%s - invalid encoding type '%c'", [self class], _cmd, encoding];
}
return 0;
}
- (NSData *) BSONEncode
{
const char encoding = *([self objCType]);
if (encoding == 'd' || encoding == 'D')
{
double value = [self doubleValue];
return [NSData dataWithBytes: &value length: 8];
}
if (encoding == 'f' || encoding == 'F')
{
double value = [self floatValue];
return [NSData dataWithBytes: &value length: 8];
}
if (encoding == 'b' || encoding == 'B')
{
char value = [self boolValue];
return [NSData dataWithBytes: &value length: 1];
}
if (encoding == 'c' || encoding == 'C')
{
int32_t value = [self charValue];
value = HOSTTOBSON32(value);
return [NSData dataWithBytes: &value length: 4];
}
if (encoding == 's' || encoding == 'S')
{
int32_t value = [self shortValue];
value = HOSTTOBSON32(value);
return [NSData dataWithBytes: &value length: 4];
}
if (encoding == 'i' || encoding == 'I')
{
int value = [self intValue];
if (sizeof(int) == 4)
value = HOSTTOBSON32(value);
else if (sizeof(int) == 8)
value = HOSTTOBSON64(value);
return [NSData dataWithBytes: &value length: sizeof(int)];
}
if (encoding == 'l' || encoding == 'L')
{
long value = [self longValue];
if (sizeof(long) == 4)
value = HOSTTOBSON32(value);
else if (sizeof(long) == 8)
value = HOSTTOBSON64(value);
return [NSData dataWithBytes: &value length: sizeof(long)];
}
if (encoding == 'q')
{
long long value = HOSTTOBSON64([self longLongValue]);
return [NSData dataWithBytes: &value length: 8];
}
if (encoding == 'Q')
{
long long value = HOSTTOBSON64([self unsignedLongLongValue]);
return [NSData dataWithBytes: &value length: 8];
}
[NSException raise: NSInvalidArgumentException format: @"%@::%s - invalid encoding type '%c'", [self class], _cmd, encoding];
return nil;
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) t
{
if (t == 0x01)
{
// #5: LLVM GCC requires double pointers to have a certain alignment in ARM CPUs.
// So we can't just read the double off directly from the data - need to copy it.
double value;
memcpy(&value, *base, sizeof(double));
*base += 8;
return [NSNumber numberWithDouble: value];
}
if (t == 0x08)
{
char value = ((char *) *base)[0];
*base += 1;
return [NSNumber numberWithBool: value];
}
if (t == 0x10)
{
int32_t value = BSONTOHOST32(((int32_t *) *base)[0]);
*base += 4;
if (sizeof(int) == 4)
return [NSNumber numberWithInt: value];
return [NSNumber numberWithLong: value];
}
if (t == 0x12)
{
int64_t value = BSONTOHOST64(((int64_t *) *base)[0]);
*base += 8;
return [NSNumber numberWithUnsignedLongLong: value];
}
return nil;
}
@end
@implementation NSString (BSON)
- (uint8_t) BSONTypeID
{
return 0x02;
}
- (NSData *) BSONEncode
{
NSData *utf8Data = [self dataUsingEncoding: NSUTF8StringEncoding];
uint32_t length = HOSTTOBSON32([utf8Data length] + 1);
NSMutableData *retval = [NSMutableData data];
[retval appendBytes: &length length: 4];
[retval appendData: utf8Data];
[retval appendBytes: "\x00" length: 1];
return retval;
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) typeID
{
uint32_t length = BSONTOHOST32(((const uint32_t *) *base)[0]);
*base += 4;
const char *utf8Str = (const char *) *base;
*base += length;
return [NSString stringWithUTF8String: utf8Str];
}
@end
@implementation NSArray (BSON)
- (uint8_t) BSONTypeID
{
return 0x04;
}
- (NSData *) BSONEncode
{
// Initialize the components structure.
NSMutableArray *components = [[NSMutableArray alloc] init];
NSMutableData *lengthData = [[NSMutableData alloc] initWithLength: 4];
[components addObject: lengthData];
[lengthData release];
NSMutableData *contentsData = [[NSMutableData alloc] init];
[components addObject: contentsData];
[contentsData release];
[components addObject: [NSData dataWithBytes: "\x00" length: 1]];
// Encode data.
uint8_t elementType = 0;
int i, count = [self count];
for (i = 0 ; i < count ; i++)
{
NSObject *value = [self objectAtIndex: i];
if ([value respondsToSelector: @selector(BSONTypeID)])
elementType = [(id <BSONCoding>) value BSONTypeID];
else
elementType = 3;
[contentsData appendBytes: &elementType length: 1];
[contentsData appendData: [[NSString stringWithFormat: @"%d", i] dataUsingEncoding: NSUTF8StringEncoding]];
[contentsData appendBytes: "\x00" length: 1];
[contentsData appendData: [value BSONEncode]];
}
// Write length.
uint32_t *length = (uint32_t *)[lengthData mutableBytes];
*length = HOSTTOBSON32([contentsData length]) + 4 + 1;
// Assemble the output data.
NSMutableData *retval = [NSMutableData data];
for (i = 0; i < [components count]; i++)
[retval appendData: [components objectAtIndex: i]];
[components release];
return retval;
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) typeID
{
NSDictionary *tmp = [NSDictionary BSONFragment: data at: base ofType: 0x03];
NSMutableArray *retval = [NSMutableArray arrayWithCapacity: [tmp count]];
int i;
for (i = 0; i < [tmp count]; i++)
[retval addObject: [tmp objectForKey: [NSString stringWithFormat: @"%d", i]]];
return retval;
}
@end
@implementation NSNull (BSON)
- (uint8_t) BSONTypeID
{
return 0x0a;
}
- (NSData *) BSONEncode
{
return [NSData data];
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) typeID
{
return [NSNull null];
}
@end
@implementation NSCalendarDate (BSON)
- (uint8_t) BSONTypeID
{
return 0x11;
}
- (NSData *) BSONEncode
{
NSString *v;
v = [self descriptionWithCalendarFormat: @"%Y-%m-%d %H:%M:%S %Z"
locale: nil];
return [v BSONEncode];
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) typeID
{
NSString *v;
v = [NSString BSONFragment: data at: base ofType: 0x02];
return [NSCalendarDate dateWithString: v
calendarFormat: @"%Y-%m-%d %H:%M:%S %Z"];
}
@end
+5 -5
View File
@@ -46,12 +46,12 @@
NSDictionary *properties;
BOOL rc;
[self logWithFormat: @"evaluating object '%@'", object];
//[self logWithFormat: @"evaluating object '%@'", object];
properties = [object properties];
rc = [self _evaluateSOGoMAPIDBObject: properties];
[self logWithFormat: @" evaluation result: %d", rc];
//[self logWithFormat: @" evaluation result: %d", rc];
return rc;
}
@@ -150,9 +150,9 @@ typedef BOOL (*EOComparator) (id, SEL, id);
rc = ((isZero && (intValue & mask) == 0)
|| (!isZero && (intValue & mask) != 0));
[self logWithFormat: @"evaluation of bitmask qualifier:"
@" (%.8x & %.8x) %s 0: %d",
intValue, mask, (isZero ? "==" : "!="), rc];
//[self logWithFormat: @"evaluation of bitmask qualifier:"
// @" (%.8x & %.8x) %s 0: %d",
// intValue, mask, (isZero ? "==" : "!="), rc];
return rc;
}
+1 -1
View File
@@ -79,7 +79,7 @@
@" c_lastmodified INT NOT NULL,"
@" c_version INT NOT NULL DEFAULT 0,"
@" c_deleted TINYINT NOT NULL DEFAULT 0,"
@" c_content TEXT)");
@" c_content LONGTEXT)");
return [NSString stringWithFormat: sqlFolderFormat, tableName];
}
+5 -30
View File
@@ -7,8 +7,6 @@ include ../Version
BACKEND_VERSION = 1.0.0
UNRTF_VERSION = 0.21.2
### bootstrap library
MAPISTORESOGO = MAPIStoreSOGo
LIBRARY_NAME = $(MAPISTORESOGO)
@@ -24,8 +22,6 @@ BUNDLE_NAME = $(SOGOBACKEND)
BUNDLE_EXTENSION = .MAPIStore
BUNDLE_INSTALL_DIR = $(SOGO_LIBDIR)
UNRTF_DIR = unrtf-$(UNRTF_VERSION)
PYTHON = /usr/bin/python
PYTHON_IS_GOOD = $(shell $(PYTHON) -c 'from sys import version_info; a=version_info; print a[0] == 2 and a[1] >= 6')
ifeq (${PYTHON_IS_GOOD},False)
@@ -37,8 +33,6 @@ all::
SAMBA_PRIVATE_DIR = $(shell $(PYTHON) ./samba-get-config.py "private dir")
$(SOGOBACKEND)_SUBPROJECTS += $(UNRTF_DIR)/src
$(SOGOBACKEND)_PRINCIPAL_CLASS = MAPIApplication
$(SOGOBACKEND)_OBJC_FILES += \
@@ -133,32 +127,14 @@ $(SOGOBACKEND)_OBJC_FILES += \
\
EOQualifier+MAPI.m \
\
EOBitmaskQualifier.m
EOBitmaskQualifier.m \
\
BSONCodec.m \
RTFHandler.m
$(SOGOBACKEND)_RESOURCE_FILES += \
product.plist \
$(UNRTF_DIR)/charmaps/SYMBOL.charmap \
$(UNRTF_DIR)/outputs/html.conf
### unrtf
all:: $(UNRTF_DIR)/config.h $(UNRTF_DIR)/src/GNUmakefile
$(UNRTF_DIR): $(UNRTF_DIR).tar.gz $(UNRTF_DIR).diff
@echo " Extracting and patching $(UNRTF_DIR)..."
@rm -rf $(UNRTF_DIR)
@$(TAR) -xvzf $< > /dev/null
@(cd $(UNRTF_DIR) && patch -p1 < ../$(UNRTF_DIR).diff) > /dev/null
@touch $(UNRTF_DIR)
$(UNRTF_DIR)-stamp: $(UNRTF_DIR)
@touch $@
$(UNRTF_DIR)/config.h: $(UNRTF_DIR)-stamp unrtf_config_h
@cp unrtf_config_h $(UNRTF_DIR)/config.h
$(UNRTF_DIR)/src/GNUmakefile: $(UNRTF_DIR)-stamp GNUmakefile.unrtf
@cp GNUmakefile.unrtf $@
product.plist
### pl reader
PLREADER_TOOL = plreader
@@ -210,7 +186,6 @@ ADDITIONAL_INCLUDE_DIRS += \
-DSAMBA_PRIVATE_DIR=@"\"$(SAMBA_PRIVATE_DIR)\"" \
$(LIBMAPI_CFLAGS) \
$(LIBMAPISTORE_CFLAGS) \
-I$(UNRTF_DIR)/src \
-I../SoObjects -I../SOPE \
-DBACKEND_BUNDLE_NAME="@\"$(BUNDLE_NAME)$(BUNDLE_EXTENSION)\"" \
-DSOGO_BUNDLES_DIR="@\"$(BUNDLE_INSTALL_DIR)\""
-34
View File
@@ -1,34 +0,0 @@
# -*-makefile-*-
# GNUstep makefile
include $(GNUSTEP_MAKEFILES)/common.make
UNRTF = unrtf
SUBPROJECT_NAME = $(UNRTF)
$(UNRTF)_C_FILES = \
attr.c \
convert.c \
error.c \
hash.c \
malloc.c \
my_iconv.c \
output.c \
parse.c \
unicode.c \
user.c \
util.c \
word.c
$(UNRTF)_CFLAGS = -DHAVE_CONFIG_H=1 -I. -I../
# Option include to set any additional variables
-include GNUmakefile.preamble
# Include in the rules for making libraries
include $(GNUSTEP_MAKEFILES)/subproject.make
# Option include to define any additional rules
-include GNUmakefile.postamble
@@ -161,7 +161,7 @@
return [self getNo: data inMemCtx: memCtx];
}
- (void) save
- (void) save: (TALLOC_CTX *) memCtx
{
// (gdb) po embeddedMessage->properties
// 2442592320 = "2012-07-11 22:30:00 +0000";
@@ -208,7 +208,8 @@
[[container event] updateFromMAPIProperties: properties
inUserContext: [self userContext]
withActiveUser: activeUser];
withActiveUser: activeUser
inMemCtx: memCtx];
}
@end
+1 -1
View File
@@ -63,7 +63,7 @@
SOGoAppointmentObject *newEntry;
NSString *name;
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
name = [NSString stringWithFormat: @"%@.ics",
[SOGoObject globallyUniqueObjectId]];
+7 -6
View File
@@ -200,6 +200,7 @@ static Class NSArrayK;
- (void) dealloc
{
//NSLog(@"MAPIStoreCalendarMessage: -dealloc (%p)", self);
[calendar release];
[super dealloc];
}
@@ -417,7 +418,7 @@ static Class NSArrayK;
return [self getYes: data inMemCtx: memCtx];
}
- (NSString *) _uidFromGlobalObjectId
- (NSString *) _uidFromGlobalObjectId: (TALLOC_CTX *) memCtx
{
NSData *objectId;
NSString *uid = nil;
@@ -431,7 +432,7 @@ static Class NSArrayK;
if (objectId)
{
length = [objectId length];
bytesDup = talloc_array (NULL, char, length + 1);
bytesDup = talloc_array (memCtx, char, length + 1);
memcpy (bytesDup, [objectId bytes], length);
bytesDup[length] = 0;
uidStart = bytesDup + length - 1;
@@ -596,7 +597,7 @@ static Class NSArrayK;
}
}
- (void) save
- (void) save: (TALLOC_CTX *) memCtx
{
// iCalCalendar *vCalendar;
// NSCalendarDate *now;
@@ -608,7 +609,7 @@ static Class NSArrayK;
if (isNew)
{
uid = [self _uidFromGlobalObjectId];
uid = [self _uidFromGlobalObjectId: memCtx];
if (uid)
{
/* Hack required because of what's explained in oxocal 3.1.4.7.1:
@@ -650,12 +651,12 @@ static Class NSArrayK;
activeUser = [[self context] activeUser];
[masterEvent updateFromMAPIProperties: properties
inUserContext: [self userContext]
withActiveUser: activeUser];
withActiveUser: activeUser
inMemCtx: memCtx];
[self _updateAttachedEvents];
[[self userContext] activateWithUser: activeUser];
[sogoObject updateContentWithCalendar: calendar
fromRequest: nil];
[self updateVersions];
}
+1 -1
View File
@@ -911,7 +911,7 @@ fromProperties: (NSDictionary *) attachmentProps
//
//
//
- (void) save
- (void) save:(TALLOC_CTX *) memCtx
{
NSArray *elements, *units;
CardElement *element;
+3 -3
View File
@@ -224,7 +224,7 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
NSURL *baseURL;
int rc = MAPISTORE_ERR_NOT_FOUND;
NSLog (@"METHOD '%s' (%d) -- uri: '%s'", __FUNCTION__, __LINE__, newUri);
//NSLog (@"METHOD '%s' (%d) -- uri: '%s'", __FUNCTION__, __LINE__, newUri);
context = nil;
@@ -532,8 +532,8 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
mappingId = [mapping idFromURL: childURL];
if (mappingId == NSNotFound)
{
[self warnWithFormat: @"no id exist yet for '%@', requesting one...",
childURL];
//[self warnWithFormat: @"no id exist yet for '%@', requesting one...",
// childURL];
openchangedb_get_new_folderID (connInfo->oc_ctx, &mappingId);
[mapping registerURL: childURL withID: mappingId];
contextId = 0;
+2 -2
View File
@@ -236,7 +236,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
messageKeys = [self messageKeys];
date = [NSCalendarDate date];
[self logWithFormat: @"current date: %@", date];
//[self logWithFormat: @"current date: %@", date];
max = [messageKeys count];
for (count = 0; count < max; count++)
@@ -245,7 +245,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
fileDate = [msg lastModificationTime];
if ([date laterDate: fileDate] == fileDate)
{
[self logWithFormat: @"current date: %@", date];
//[self logWithFormat: @"current date: %@", date];
date = fileDate;
}
+18 -1
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
@@ -135,7 +152,7 @@
[super addProperties: newNewProperties];
}
- (void) save
- (void) save: (TALLOC_CTX *) memCtx
{
uint64_t newVersion;
+1 -1
View File
@@ -65,7 +65,7 @@ static Class MAPIStoreDBMessageK = Nil;
cVersion = exchange_globcnt (([value unsignedLongLongValue] >> 16)
& 0x0000ffffffffffffLL);
version = [NSNumber numberWithUnsignedLongLong: cVersion];
[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
[self logWithFormat: @" version: %.16lx", cVersion];
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"version"
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
+1 -1
View File
@@ -146,7 +146,7 @@ static Class MAPIStoreAttachmentK;
return ULLONG_MAX;
}
- (void) save
- (void) save: (TALLOC_CTX *) memCtx
{
[self subclassResponsibility: _cmd];
}
+2 -2
View File
@@ -51,7 +51,7 @@
return [self getYes: data inMemCtx: memCtx];
}
- (enum mapistore_error) saveMessage
- (enum mapistore_error) saveMessage: (TALLOC_CTX *) memCtx;
{
enum mapistore_error rc;
MAPIStoreContext *context;
@@ -60,7 +60,7 @@
context = [self context];
ownerUser = [[self userContext] sogoUser];
if ([[context activeUser] isEqual: ownerUser])
rc = [super saveMessage];
rc = [super saveMessage: memCtx];
else
rc = MAPISTORE_ERR_DENIED;
+10 -10
View File
@@ -180,7 +180,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
- (void) dealloc
{
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
// [messageKeys release];
// [faiMessageKeys release];
@@ -366,7 +366,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
MAPIStoreMapping *mapping;
NSString *childURL;
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
mapping = [self mapping];
childURL = [mapping urlFromID: fid];
@@ -393,7 +393,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
MAPIStoreFolder *childFolder;
SOGoUser *ownerUser;
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
ownerUser = [[self userContext] sogoUser];
if ([[context activeUser] isEqual: ownerUser]
@@ -450,8 +450,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
NSArray *keys;
int rc = MAPISTORE_SUCCESS;
[self logWithFormat: @"METHOD '%s' (%d) -- tableType: %d",
__FUNCTION__, __LINE__, tableType];
//[self logWithFormat: @"METHOD '%s' (%d) -- tableType: %d",
//__FUNCTION__, __LINE__, tableType];
if (tableType == MAPISTORE_MESSAGE_TABLE)
keys = [self messageKeys];
@@ -513,8 +513,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
MAPIStoreMapping *mapping;
SOGoUser *ownerUser;
[self logWithFormat: @"METHOD '%s' -- mid: 0x%.16llx associated: %d",
__FUNCTION__, mid, isAssociated];
//[self logWithFormat: @"METHOD '%s' -- mid: 0x%.16llx associated: %d",
// __FUNCTION__, mid, isAssociated];
context = [self context];
ownerUser = [[self userContext] sogoUser];
@@ -699,7 +699,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
if (rc != MAPISTORE_SUCCESS)
goto end;
}
[destMsg save];
[destMsg save: memCtx];
if (!wantCopy)
rc = [sourceFolder deleteMessageWithMID: srcMid andFlags: 0];
@@ -844,7 +844,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
[mapping registerURL: [targetMessage url]
withID: fmid];
}
[targetMessage save];
[targetMessage save: memCtx];
}
[pool release];
@@ -865,7 +865,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
[mapping registerURL: [targetMessage url]
withID: fmid];
}
[targetMessage save];
[targetMessage save: memCtx];
}
[pool release];
+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
@@ -259,7 +259,6 @@ static Class NSNumberK;
}
}
*/
- (void) _setChangeKey: (NSData *) changeKey
forMessageEntry: (NSMutableDictionary *) messageEntry
inChangeListOnly: (BOOL) inChangeListOnly
@@ -461,7 +460,10 @@ static Class NSNumberK;
[mapping setObject: cLastModified forKey: changeNumber];
[messageEntry setObject: changeNumber forKey: @"version"];
newChangeNum = [changeNumber unsignedLongValue];
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];
+2 -2
View File
@@ -92,8 +92,8 @@
value = NSObjectFromMAPISPropValue (&res->lpProp);
lastModified = [(MAPIStoreGCSFolder *)
container lastModifiedFromMessageChangeNumber: value];
[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
[self logWithFormat: @" c_lastmodified: %@", lastModified];
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
//[self logWithFormat: @" c_lastmodified: %@", lastModified];
if (lastModified)
{
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"c_lastmodified"
+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>
@@ -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;
@@ -390,7 +389,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
else
value = [NSDate date];
[self logWithFormat: @"lastMessageModificationTime: %@", value];
//[self logWithFormat: @"lastMessageModificationTime: %@", value];
return value;
}
@@ -613,8 +612,8 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
[messageEntry setObject: modseq forKey: @"modseq"];
[messageEntry setObject: changeNumber forKey: @"version"];
[self logWithFormat: @"added message entry for uid %@, modseq %@,"
@" version %@", uid, modseq, changeNumber];
//[self logWithFormat: @"added message entry for uid %@, modseq %@,"
// @" version %@", uid, modseq, changeNumber];
changeKey = [self getReplicaKeyFromGlobCnt: newChangeNum >> 16];
[self _setChangeKey: changeKey forMessageEntry: messageEntry];
@@ -796,7 +795,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
if (tableType == MAPISTORE_MESSAGE_TABLE)
{
changeNumber = [NSString stringWithUnsignedLongLong: changeNum];
changeNumber = [NSString stringWithFormat: @"0x%.16llx", changeNum];
modseq = [[self modseqFromMessageChangeNumber: changeNumber]
unsignedLongLongValue];
if (modseq > 0)
+10 -2
View File
@@ -693,7 +693,15 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
ngAddress = [[NGMailAddressParser mailAddressParserWithString: fullMail]
parse];
if ([ngAddress isKindOfClass: [NGMailAddress class]])
cn = [ngAddress displayName];
{
cn = [ngAddress displayName];
// If we don't have a displayName, we use the email address instead. This
// avoid bug #2119 - where Outlook won't display anything in the "From" field,
// nor in the recipient field if we reply to the email.
if (![cn length])
cn = [ngAddress address];
}
else
cn = @"";
@@ -1576,7 +1584,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
bodySetup = YES;
}
- (void) save
- (void) save: (TALLOC_CTX *) memCtx
{
NSNumber *value;
+5 -4
View File
@@ -120,7 +120,7 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
case PidLidAppointmentStartWhole:
case PidLidAppointmentEndWhole:
case PidLidRecurring:
[self logWithFormat: @"apt restriction on mail folder?"];
//[self logWithFormat: @"apt restriction on mail folder?"];
rc = MAPIRestrictionStateAlwaysFalse;
break;
@@ -155,10 +155,11 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
case PidTagChangeNumber:
{
value = [NSString stringWithFormat: @"0x%.16llx", [value unsignedLongLongValue]];
modseq = [(MAPIStoreMailFolder *)
container modseqFromMessageChangeNumber: value];
[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
[self logWithFormat: @" modseq: %.16lx", [modseq unsignedLongLongValue]];
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
//[self logWithFormat: @" modseq: %.16lx", [modseq unsignedLongLongValue]];
if (modseq)
modseq = [NSNumber numberWithUnsignedLongLong:
[modseq unsignedLongLongValue] + 1];
@@ -316,7 +317,7 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
ASSIGN (sortOrderings, newSortOrderings);
else
ASSIGN (sortOrderings, [NSArray arrayWithObject: @"ARRIVAL"]);
[self logWithFormat: @"new sort orderings: '%@'", sortOrderings];
//[self logWithFormat: @"new sort orderings: '%@'", sortOrderings];
}
else
ASSIGN (sortOrderings, [NSArray arrayWithObject: @"ARRIVAL"]);
+25 -2
View File
@@ -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 *
@@ -904,7 +920,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
return MAPISTORE_SUCCESS;
}
- (void) save
- (void) save: (TALLOC_CTX *) memCtx
{
NSString *folderName, *flag, *newIdString, *messageKey;
NSData *changeKey, *messageData;
@@ -943,7 +959,14 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
[mapping registerURL: [self url] withID: mid];
/* synchronise the cache and update the change key with the one provided
by the client */
by the client. Before doing this, lets issue a unselect/select combo
because of timing issues with Dovecot in obtaining the latest modseq.
Sometimes, Dovecot doesn't return the newly appended UID if we do
a "UID SORT (DATE) UTF-8 (MODSEQ XYZ) (NOT DELETED)" command (where
XYZ is the HIGHESTMODSEQ+1) immediately after IMAP APPEND */
[client unselect];
[client select: folderName];
[(MAPIStoreMailFolder *) container synchroniseCache];
changeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)];
if (changeKey)
+2 -2
View File
@@ -64,7 +64,7 @@
- (int) getAttachmentTable: (MAPIStoreAttachmentTable **) tablePtr
andRowCount: (uint32_t *) countPtr;
- (int) setReadFlag: (uint8_t) flag;
- (enum mapistore_error) saveMessage;
- (enum mapistore_error) saveMessage: (TALLOC_CTX *) memCtx;
- (NSArray *) activeContainerMessageTables;
@@ -74,7 +74,7 @@
- (void) copyToMessage: (MAPIStoreMessage *) newMessage inMemCtx: (TALLOC_CTX *) memCtx;
/* subclasses */
- (void) save;
- (void) save: (TALLOC_CTX *) memCtx;
/* attachments (subclasses) */
- (MAPIStoreAttachment *) createAttachment;
+18 -35
View File
@@ -45,11 +45,10 @@
#import "NSData+MAPIStore.h"
#import "NSObject+MAPIStore.h"
#import "NSString+MAPIStore.h"
#import "RTFHandler.h"
#import "MAPIStoreMessage.h"
#include <unrtf.h>
#undef DEBUG
#include <stdbool.h>
#include <gen_ndr/exchange.h>
@@ -60,17 +59,6 @@ static Class MAPIStoreFolderK, MAPIStoreEmbeddedMessageK;
static NSString *resourcesDir = nil;
/* rtf conversion via unrtf */
static int
unrtf_data_output (void *data, const char *str, size_t str_len)
{
NSMutableData *rtfData = data;
[rtfData appendBytes: str length: str_len];
return str_len;
}
static NSData *
uncompressRTF (NSData *compressedRTF)
{
@@ -97,22 +85,17 @@ rtf2html (NSData *compressedRTF)
{
NSData *rtf;
NSMutableData *html = nil;
int rc;
struct unRTFOptions unrtfOptions;
rtf = uncompressRTF (compressedRTF);
if (rtf)
{
html = [NSMutableData data];
memset (&unrtfOptions, 0, sizeof (struct unRTFOptions));
unrtf_set_output_device (&unrtfOptions, unrtf_data_output, html);
unrtfOptions.config_directory = [resourcesDir UTF8String];
unrtfOptions.output_format = "html";
unrtfOptions.nopict_mode = YES;
rc = unrtf_convert_from_string (&unrtfOptions,
[rtf bytes], [rtf length]);
if (!rc)
html = nil;
//html = [NSMutableData data];
RTFHandler *handler;
handler = [[RTFHandler alloc] initWithData: rtf];
AUTORELEASE(handler);
html = [handler parse];
}
return html;
@@ -139,7 +122,7 @@ rtf2html (NSData *compressedRTF)
- (id) init
{
[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
//[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
if ((self = [super init]))
{
@@ -153,7 +136,7 @@ rtf2html (NSData *compressedRTF)
- (void) dealloc
{
[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
//[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
[activeUserRoles release];
[attachmentKeys release];
[attachmentParts release];
@@ -260,7 +243,7 @@ rtf2html (NSData *compressedRTF)
struct mapistore_message_recipient *recipient;
NSUInteger count;
[self logWithFormat: @"METHOD '%s'", __FUNCTION__];
//[self logWithFormat: @"METHOD '%s'", __FUNCTION__];
recipients = [NSMutableDictionary new];
recipientProperties = [NSDictionary dictionaryWithObject: recipients
@@ -450,7 +433,7 @@ rtf2html (NSData *compressedRTF)
NSString *key;
MAPIStoreAttachment *attachment, *newAttachment;
[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
//[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
//memCtx = talloc_zero (NULL, TALLOC_CTX);
@@ -477,7 +460,7 @@ rtf2html (NSData *compressedRTF)
//talloc_free (memCtx);
}
- (enum mapistore_error) saveMessage
- (enum mapistore_error) saveMessage: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
NSArray *containerTables;
@@ -490,7 +473,7 @@ rtf2html (NSData *compressedRTF)
BOOL userIsOwner;
MAPIStoreMessage *mainMessage;
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
context = [self context];
ownerUser = [[self userContext] sogoUser];
@@ -518,7 +501,7 @@ rtf2html (NSData *compressedRTF)
/* folder modified */
notif_parameters
= talloc_zero(NULL, struct mapistore_object_notification_parameters);
= talloc_zero(memCtx, struct mapistore_object_notification_parameters);
notif_parameters->object_id = folderId;
if (isNew)
{
@@ -542,7 +525,7 @@ rtf2html (NSData *compressedRTF)
if (isNew)
{
notif_parameters
= talloc_zero(NULL,
= talloc_zero(memCtx,
struct mapistore_object_notification_parameters);
notif_parameters->object_id = [self objectId];
notif_parameters->folder_id = folderId;
@@ -562,7 +545,7 @@ rtf2html (NSData *compressedRTF)
[[containerTables objectAtIndex: count] restrictedChildKeys];
}
[self save];
[self save: memCtx];
/* We make sure that any change-related properties are removes from the
properties dictionary, to make sure that related methods will be
invoked the next time they are requested. */
@@ -937,7 +920,7 @@ rtf2html (NSData *compressedRTF)
return MAPISTORE_ERROR;
}
- (void) save
- (void) save: (TALLOC_CTX *) memCtx
{
[self subclassResponsibility: _cmd];
}
+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;
+4 -4
View File
@@ -68,7 +68,7 @@ sogo_backend_atexit (void)
GSRegisterCurrentThread ();
pool = [NSAutoreleasePool new];
NSLog (@"allocated classes:\n%s", GSDebugAllocationList (YES));
//NSLog (@"allocated classes:\n%s", GSDebugAllocationList (YES));
[pool release];
GSUnregisterCurrentThread ();
}
@@ -1024,7 +1024,7 @@ sogo_message_set_read_flag (void *message_object, uint8_t flag)
}
static enum mapistore_error
sogo_message_save (void *message_object)
sogo_message_save (void *message_object, TALLOC_CTX *mem_ctx)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
@@ -1039,7 +1039,7 @@ sogo_message_save (void *message_object)
message = wrapper->instance;
GSRegisterCurrentThread ();
pool = [NSAutoreleasePool new];
rc = [message saveMessage];
rc = [message saveMessage: mem_ctx];
// [context tearDownRequest];
[pool release];
GSUnregisterCurrentThread ();
@@ -1229,7 +1229,7 @@ sogo_table_set_restrictions (void *table_object, struct mapi_SRestriction *restr
GSRegisterCurrentThread ();
pool = [NSAutoreleasePool new];
[table setRestrictions: restrictions];
[table cleanupCaches];
//[table cleanupCaches];
rc = MAPISTORE_SUCCESS;
*table_status = TBLSTAT_COMPLETE;
[pool release];
+7 -7
View File
@@ -375,12 +375,12 @@ static Class NSDataK, NSStringK;
- (void) setRestrictions: (const struct mapi_SRestriction *) res
{
EOQualifier *oldRestriction;
//EOQualifier *oldRestriction;
// [self logWithFormat: @"set restriction to (table type: %d): %@",
// type, MAPIStringForRestriction (res)];
oldRestriction = restriction;
//oldRestriction = restriction;
[restriction autorelease];
if (res)
restrictionState = [self evaluateRestriction: res
@@ -396,11 +396,11 @@ static Class NSDataK, NSStringK;
// FIXME: we should not flush the caches if the restrictions matches
[self cleanupCaches];
if (restriction)
[self logWithFormat: @"restriction set to EOQualifier: %@",
restriction];
else if (oldRestriction)
[self logWithFormat: @"restriction unset (was %@)", oldRestriction];
//if (restriction)
// [self logWithFormat: @"restriction set to EOQualifier: %@",
// restriction];
// else if (oldRestriction)
// [self logWithFormat: @"restriction unset (was %@)", oldRestriction];
}
- (MAPIRestrictionState) evaluateNotRestriction: (struct mapi_SNotRestriction *) res
+1 -1
View File
@@ -357,7 +357,7 @@
return rc;
}
- (void) save
- (void) save:(TALLOC_CTX *) memCtx
{
iCalCalendar *vCalendar;
iCalToDo *vToDo;
+2 -2
View File
@@ -52,9 +52,9 @@ static inline NSNumber *
MAPIPropertyKey (enum MAPITAGS propTag)
{
#if (GS_SIZEOF_LONG == 4)
return [NSNumber numberWithUnsignedLong: propTag];
return [NSString stringWithFormat: @"%ul", propTag];
#elif (GS_SIZEOF_INT == 4)
return [NSNumber numberWithUnsignedInt: propTag];
return [NSString stringWithFormat: @"%u", propTag];
#else
#error No suitable type for 4 bytes integers
#endif
+4 -3
View File
@@ -342,7 +342,8 @@ MAPIStoreDumpMessageProperties (NSDictionary *properties)
{
NSNumber *key;
NSArray *allKeys;
NSUInteger keyAsInt, count, max;
NSUInteger count, max;
NSUInteger keyAsInt;
id value;
allKeys = [properties allKeys];
@@ -351,7 +352,7 @@ MAPIStoreDumpMessageProperties (NSDictionary *properties)
NSLog (@"message properties (%d):", max);
value = [properties objectForKey: @"recipients"];
if (value)
if (value)
NSLog (@" recipients: %@", value);
for (count = 0; count < max; count++)
@@ -363,7 +364,7 @@ MAPIStoreDumpMessageProperties (NSDictionary *properties)
value = [properties objectForKey: key];
NSLog (@" 0x%.4x: %@ (%@)",
keyAsInt, value,
NSStringFromClass ([value class]));
NSStringFromClass ([value class]));
}
}
}
+5 -2
View File
@@ -20,6 +20,7 @@
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSCharacterSet.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSMapTable.h>
@@ -107,15 +108,17 @@ static NSMapTable *contextsTable = nil;
password = nil;
path = [NSString stringWithFormat: SAMBA_PRIVATE_DIR
@"/mapistore/%@/password", newUsername];
@"/mapistore/%@/password", newUsername];
content = [NSData dataWithContentsOfFile: path];
if (content)
{
password = [[NSString alloc] initWithData: content
encoding: NSUTF8StringEncoding];
encoding: NSUTF8StringEncoding];
[password autorelease];
password = [password stringByTrimmingCharactersInSet:
[NSCharacterSet characterSetWithCharactersInString: @"\r\n"]];
}
return password;
+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
@@ -50,8 +50,7 @@ MAPIStoreTallocWrapperDestroy (void *data)
GSRegisterCurrentThread ();
pool = [NSAutoreleasePool new];
wrapper = data;
//NSLog (@"destroying wrapped object (wrapper: %p; object: %p)...\n", wrapper, wrapper->MAPIStoreSOGoObject);
NSLog (@"destroying wrapped object (wrapper: %p)", wrapper);
//NSLog (@"destroying wrapped object (wrapper: %p; object: %p (%@))...\n", wrapper, wrapper->instance, NSStringFromClass([wrapper->instance class]));
[wrapper->instance release];
[pool release];
GSUnregisterCurrentThread ();
@@ -67,8 +66,7 @@ MAPIStoreTallocWrapperDestroy (void *data)
talloc_set_destructor ((void *) wrapper, MAPIStoreTallocWrapperDestroy);
wrapper->instance = self;
[self retain];
NSLog (@"returning wrapper: %p; object: %p", wrapper, self);
//NSLog (@"returning wrapper: %p; object: %p (%@)", wrapper, self, NSStringFromClass([self class]));
return wrapper;
}
+39 -35
View File
@@ -33,6 +33,8 @@
#import <Foundation/NSValue.h>
#import <NGExtensions/NSNull+misc.h>
#import "BSONCodec.h"
const char *indentationStep = " ";
@interface NSObject (plext)
@@ -142,41 +144,43 @@ const char *indentationStep = " ";
static void
OCDumpPListData (NSData *content)
{
NSDictionary *d;
NSPropertyListFormat format;
NSString *error = nil;
const char *formatName;
//NSDictionary *d;
//NSPropertyListFormat format;
//NSString *error = nil;
//const char *formatName;
d = [NSPropertyListSerialization propertyListFromData: content
mutabilityOption: NSPropertyListImmutable
format: &format
errorDescription: &error];
if (d)
{
switch (format)
{
case NSPropertyListOpenStepFormat:
formatName = "OpenStep";
break;
case NSPropertyListXMLFormat_v1_0:
formatName = "XML";
break;
case NSPropertyListBinaryFormat_v1_0:
formatName = "Binary";
break;
case NSPropertyListGNUstepFormat:
formatName = "GNUstep";
break;
case NSPropertyListGNUstepBinaryFormat:
formatName = "GNUstep binary";
break;
default: formatName = "unknown";
}
//d = [NSPropertyListSerialization propertyListFromData: content
// mutabilityOption: NSPropertyListImmutable
// format: &format
// errorDescription: &error];
//d = [content BSONValue];
printf ("File format is: %s\n", formatName);
[d displayWithIndentation: 0];
printf ("\n");
}
else
printf ("an error occurred: %s\n", [error UTF8String]);
// if (d)
// {
// switch (format)
// {
// case NSPropertyListOpenStepFormat:
// formatName = "OpenStep";
// break;
// case NSPropertyListXMLFormat_v1_0:
// formatName = "XML";
// break;
// case NSPropertyListBinaryFormat_v1_0:
// formatName = "Binary";
// break;
// case NSPropertyListGNUstepFormat:
// formatName = "GNUstep";
// break;
// case NSPropertyListGNUstepBinaryFormat:
// formatName = "GNUstep binary";
// break;
// default: formatName = "unknown";
// }
// printf ("File format is: %s\n", formatName);
// [d displayWithIndentation: 0];
// printf ("\n");
// }
// else
// printf ("an error occurred: %s\n", [error UTF8String]);
}
+132
View File
@@ -0,0 +1,132 @@
/*
Copyright (C) 2005-2012 Inverse inc.
This file is part of SOGo.
SOGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
SOGo 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 Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include <Foundation/NSArray.h>
#include <Foundation/NSData.h>
#include <Foundation/NSMapTable.h>
#include <Foundation/NSObject.h>
#include <Foundation/NSString.h>
//
//
//
@interface RTFHandler : NSObject
{
NSMapTable *_charsets;
NSMutableData *_html;
NSData *_data;
const char *_bytes;
int _current_pos;
int _len;
}
- (id) initWithData: (NSData *) theData;
- (NSMutableData *) parse;
@end
//
//
//
@interface RTFStack: NSObject
{
NSMutableArray *a;
}
- (void) push: (id) theObject;
- (id) pop;
@end
//
//
//
@interface RTFFormattingOptions : NSObject
{
@public
BOOL bold;
BOOL italic;
BOOL underline;
BOOL strikethrough;
int font_index;
int color_index;
int start_pos;
}
@end
//
//
//
@interface RTFFontInfo : NSObject
{
@public
NSString *family;
NSString *charset;
NSString *name;
unsigned int pitch;
unsigned int index;
}
@end
//
// \fX - font, index in font table
//
@interface RTFFontTable : NSObject
{
@public
NSMapTable *fontInfos;
}
- (void) addFontInfo: (RTFFontInfo *) theFontInfo
atIndex: (unsigned int ) theIndex;
- (RTFFontInfo *) fontInfoAtIndex: (unsigned int ) theIndex;
@end
//
//
//
@interface RTFColorDef : NSObject
{
@public
unsigned char red;
unsigned char green;
unsigned char blue;
}
@end
//
// {\colortbl\red0\green0\blue0;\red128\green0\blue0;\red255\green0\blue0;}
//
// \cfX - color/foreground - index
// \cbX - color/background - index
//
//
@interface RTFColorTable : NSObject
{
@public
NSMutableArray *colorDefs;
}
- (void) addColorDef: (RTFColorDef *) theColorDef;
@end
+961
View File
@@ -0,0 +1,961 @@
/*
Copyright (C) 2005-2013 Inverse inc.
This file is part of SOGo.
SOGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
SOGo 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 Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include "RTFHandler.h"
#include <Foundation/NSValue.h>
//
// Useful macros
//
#define ADVANCE _bytes++; _current_pos++;
#define REWIND _bytes--; _current_pos--;
//
// Charset definitions. See http://msdn.microsoft.com/en-us/goglobal/bb964654 for all details.
//
const unsigned short ansicpg1250[256] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
0x20ac, 0x0000, 0x201a, 0x0000, 0x201e, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179,
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a,
0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b,
0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c,
0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9 };
const unsigned short ansicpg1251[256] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,
0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f,
0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407,
0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457,
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f };
const unsigned short ansicpg1252[256] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017d, 0x0000,
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x0000, 0x017e, 0x0178,
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff };
const unsigned short ansicpg1253[256] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0000, 0x203a, 0x0000, 0x0000, 0x0000, 0x0000,
0x00a0, 0x0385, 0x0386, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x0000, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x2015,
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x00b5, 0x00b6, 0x00b7, 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f,
0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
0x03a0, 0x03a1, 0x0000, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af,
0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0000 };
const unsigned short ansicpg1254[256] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x0000, 0x0000, 0x0178,
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df,
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff };
const unsigned short ansicpg1255[256] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0000, 0x203a, 0x0000, 0x0000, 0x0000, 0x0000,
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20aa, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7, 0x05b8, 0x05b9, 0x0000, 0x05bb, 0x05bc, 0x05bd, 0x05be, 0x05bf,
0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05f0, 0x05f1, 0x05f2, 0x05f3, 0x05f4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df,
0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x0000, 0x0000, 0x200e, 0x200f, 0x0000 };
const unsigned short ansicpg1256[256] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
0x20ac, 0x067e, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
0x06af, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x06a9, 0x2122, 0x0691, 0x203a, 0x0153, 0x200c, 0x200d, 0x06ba,
0x00a0, 0x060c, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x06be, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x061b, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x061f,
0x06c1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f,
0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00d7, 0x0637, 0x0638, 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643,
0x00e0, 0x0644, 0x00e2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0649, 0x064a, 0x00ee, 0x00ef,
0x064b, 0x064c, 0x064d, 0x064e, 0x00f4, 0x064f, 0x0650, 0x00f7, 0x0651, 0x00f9, 0x0652, 0x00fb, 0x00fc, 0x200e, 0x200f, 0x06d2 };
const unsigned short ansicpg1257[256] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
0x20ac, 0x0000, 0x201a, 0x0000, 0x201e, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00a8, 0x02c7, 0x00b8,
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0000, 0x203a, 0x0000, 0x00af, 0x02db, 0x0000,
0x00a0, 0x0000, 0x00a2, 0x00a3, 0x00a4, 0x0000, 0x00a6, 0x00a7, 0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6,
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6,
0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112, 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b,
0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7, 0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df,
0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113, 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c,
0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7, 0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x02d9 };
const unsigned short ansicpg1258[256] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0000, 0x203a, 0x0153, 0x0000, 0x0000, 0x0178,
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
0x00c0, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x0300, 0x00cd, 0x00ce, 0x00cf,
0x0110, 0x00d1, 0x0309, 0x00d3, 0x00d4, 0x01a0, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x01af, 0x0303, 0x00df,
0x00e0, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0301, 0x00ed, 0x00ee, 0x00ef,
0x0111, 0x00f1, 0x0323, 0x00f3, 0x00f4, 0x01a1, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x01b0, 0x20ab, 0x00ff };
const unsigned short ansicpg874[256] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
0x20ac, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, 0x0e38, 0x0e39, 0x0e3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0e3f,
0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0x0000, 0x0000, 0x0000, 0x0000 };
//
//
//
@implementation RTFStack
- (id) init
{
if ((self = [super init]))
{
a = [[NSMutableArray alloc] init];
}
return self;
}
- (void) dealloc
{
RELEASE(a);
[super dealloc];
}
- (void) push: (id) theObject
{
[a addObject: theObject];
}
- (id) pop
{
id o = nil;
if ([a count])
{
o = AUTORELEASE([[a lastObject] retain]);
[a removeLastObject];
}
return o;
}
- (id) top
{
id o = nil;
if ([a count])
{
o = AUTORELEASE([[a lastObject] retain]);
}
return o;
}
@end
//
//
//
@implementation RTFFormattingOptions
@end
//
//
//
@implementation RTFFontInfo
- (id) init
{
if ((self = [super init]))
{
}
return self;
}
- (void) dealloc
{
RELEASE(family);
RELEASE(charset);
RELEASE(name);
[super dealloc];
}
@end
//
//
//
@implementation RTFFontTable
- (id) init
{
if ((self = [super init]))
{
fontInfos = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 128);
}
return self;
}
- (void) dealloc
{
NSFreeMapTable(fontInfos);
[super dealloc];
}
- (void) addFontInfo: (RTFFontInfo *) theFontInfo
atIndex: (unsigned int) theIndex
{
NSNumber *key;
key = [NSNumber numberWithInt: theIndex];
NSMapInsert(fontInfos, key, (void*) theFontInfo);
}
- (RTFFontInfo *) fontInfoAtIndex: (unsigned int) theIndex
{
NSNumber *key;
key = [NSNumber numberWithInt: theIndex];
return NSMapGet(fontInfos, key);
}
@end
//
//
//
@implementation RTFColorDef
@end
//
//
//
@implementation RTFColorTable
- (id) init
{
if ((self = [super init]))
{
colorDefs = [[NSMutableArray alloc] init];
}
return self;
}
- (void) dealloc
{
RELEASE(colorDefs);
[super dealloc];
}
- (void) addColorDef: (RTFColorDef *) theColorDef
{
[colorDefs addObject: theColorDef];
}
- (RTFColorDef *) colorDefAtIndex: (unsigned int) theIndex
{
return [colorDefs objectAtIndex: theIndex];
}
@end
//
//
//
@implementation RTFHandler
- (id) initWithData: (NSData *) theData
{
if ((self = [super init]))
{
ASSIGN(_data, theData);
_bytes = (char *)[_data bytes];
_len = [_data length];
_current_pos = 0;
_charsets = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 10);
NSMapInsert(_charsets, @"ansicpg1250", ansicpg1250);
NSMapInsert(_charsets, @"ansicpg1251", ansicpg1251);
NSMapInsert(_charsets, @"ansicpg1252", ansicpg1252);
NSMapInsert(_charsets, @"ansicpg1253", ansicpg1253);
NSMapInsert(_charsets, @"ansicpg1254", ansicpg1254);
NSMapInsert(_charsets, @"ansicpg1255", ansicpg1255);
NSMapInsert(_charsets, @"ansicpg1256", ansicpg1256);
NSMapInsert(_charsets, @"ansicpg1257", ansicpg1257);
NSMapInsert(_charsets, @"ansicpg1258", ansicpg1258);
NSMapInsert(_charsets, @"ansicpg874", ansicpg874);
}
return self;
}
- (void) dealloc
{
NSFreeMapTable(_charsets);
RELEASE(_data);
[super dealloc];
}
- (const char *) parseControlWord: (unsigned int *) len
{
const char *start, *end;
start = ADVANCE;
while (isalnum(*_bytes) || *_bytes == '-')
{
ADVANCE;
}
end = _bytes;
*len = end-start-1;
return start+1;
}
//
// {\colortbl\red0\green0\blue0;\red128\green0\blue0;\red255\green0\blue0;}
//
- (RTFColorTable *) parseColorTable
{
RTFColorTable *colorTable;
RTFColorDef *colorDef;
colorTable = [[[RTFColorTable alloc] init] autorelease];
colorDef = [[[RTFColorDef alloc] init] autorelease];
while (*_bytes != '}')
{
if (*_bytes == ';')
{
[colorTable addColorDef: colorDef];
colorDef = [[[RTFColorDef alloc] init] autorelease];
ADVANCE;
}
else if (*_bytes == '\\')
{
const char *cw;
unsigned int len;
NSString *s;
cw = [self parseControlWord: &len];
// Skip our control word
//if (strncmp(start+1, "colortbl", len) == 0)
// continue;
s = [[NSString alloc] initWithBytesNoCopy: (void *)cw
length: len
encoding: NSASCIIStringEncoding
freeWhenDone: NO];
[s autorelease];
if ([s hasPrefix: @"red"])
{
colorDef->red = [[s substringFromIndex: 3] intValue];
}
else if ([s hasPrefix: @"green"])
{
colorDef->green = [[s substringFromIndex: 4] intValue];
}
else
{
colorDef->blue = [[s substringFromIndex: 4] intValue];
}
}
else
{
ADVANCE;
}
}
return colorTable;
}
//
// Possible formats:
//
// {\fonttbl\f0\fswiss Helvetica;}
// {\fonttbl{\f0\froman\fcharset0\fprq2 Arial;}{\f1\fswiss\fprq2\fcharset0 Arial;}}
//
// FIXME: Complex ones not handled right now:
//
// {\fonttbl{\f2\fnil\fcharset256\fprq2{\*\panose 00020703090202050204}Courier New;}{...
// {\fonttbl{\f31\fnil\fcharset0\fprq0 Times New Roman Monotype{\*\falt Times New Roman};}{...
//
// We receive the full string.
//
- (RTFFontTable *) parseFontTable
{
NSMutableString *fontName;
RTFFontTable *fontTable;
RTFFontInfo *fontInfo;
unsigned int count;
fontTable = [[[RTFFontTable alloc] init] autorelease];
fontName = nil;
count = 0;
do
{
if (*_bytes == '{')
{
if (fontTable)
{
fontInfo = [[[RTFFontInfo alloc] init] autorelease];
fontName = [[[NSMutableString alloc] init] autorelease];
}
ADVANCE;
count++;
}
else if (*_bytes == '}')
{
if (fontTable) //&& ![NSAllMapTableValues(fontTable->fontInfos) containsObject: fontInfo])
{
ASSIGN(fontInfo->name, fontName);
[fontTable addFontInfo: fontInfo atIndex: fontInfo->index];
}
ADVANCE;
count--;
}
else if (*_bytes == '\\')
{
const char *cw;
unsigned int len;
NSString *s;
cw = [self parseControlWord: &len];
// Skip our control word
if (strncmp((const char*)cw, "fonttbl", len) == 0)
continue;
// We must at least parse <fontnum><fontfamily><fcharset>
s = [[NSString alloc] initWithBytesNoCopy: (void *)cw+1
length: len-1
encoding: NSASCIIStringEncoding
freeWhenDone: NO];
[s autorelease];
// If we got a fontnum, let's parse all three fields at once)
if (isdigit(*(cw+1)))
{
fontInfo->index = [s intValue];
// We now parse <fontfamily><fcharset>
cw = [self parseControlWord: &len];
fontInfo->family = [[NSString alloc] initWithBytesNoCopy: (void *)cw+1
length: len-1
encoding: NSASCIIStringEncoding
freeWhenDone: NO];
cw = [self parseControlWord: &len];
fontInfo->charset = [[NSString alloc] initWithBytesNoCopy: (void *)cw+1
length: len-1
encoding: NSASCIIStringEncoding
freeWhenDone: NO];
// We now skip everything until we find our final group closer ('}')
int cc = 1;
do
{
if (*_bytes == '{')
cc++;
if (*_bytes == '}')
cc--;
ADVANCE;
}
while (cc != 0);
// move back our buffer;
REWIND;
}
}
else
{
if (isalnum(*_bytes))
[fontName appendFormat: @"%c", *_bytes];
ADVANCE;
}
} while (count != 0);
return fontTable;
}
//
//
//
- (void) parseStyleSheet
{
unsigned int count;
count = 0;
do
{
if (*_bytes == '{')
{
count++;
}
else if (*_bytes == '}')
{
count--;
}
ADVANCE;
} while (count != 0);
}
//
//
//
- (void) parsePicture
{
// Do the same as -parseStyleSheet for now, that is, ignore everything.
[self parseStyleSheet];
}
//
//
//
- (NSMutableData *) parse
{
RTFFormattingOptions *formattingOptions;
RTFColorTable *colorTable;
RTFFontTable *fontTable;
RTFStack *stack;
unsigned short *charset;
char c;
stack = [[RTFStack alloc] init];
fontTable = nil;
colorTable = nil;
charset = NULL;
_html = [[NSMutableData alloc] init];
[_html appendBytes: "<html><meta charset='utf-8'><body>" length: 34];
// Check if we got RTF data
if (_len > 4 && strncmp((const char*)_bytes, "{\\rtf", 4) != 0)
return NO;
while (_current_pos < _len)
{
c = *_bytes;
// RTF control code
if (c == '\\')
{
unsigned int len;
const char *cw;
NSString *s;
if (*(_bytes+1) == '\'' && charset)
{
// A hexadecimal value, based on the specified character set (may be used to identify 8-bit values).
NSString *s;
NSData *d;
const char *b1, *b2;
unsigned short index;
ADVANCE;
ADVANCE;
b1 = ADVANCE;
b2 = ADVANCE;
index = (isdigit(*b1) ? *b1 - 48 : toupper(*b1) - 55) * 16;
index += (isdigit(*b2) ? *b2 - 48 : toupper(*b2) - 55);
s = [NSString stringWithCharacters: &(charset[index]) length: 1];
d = [s dataUsingEncoding: NSUTF8StringEncoding];
[_html appendData: d];
continue;
}
else if (*(_bytes+1) == '*')
{
int cc = 1;
do
{
if (*_bytes == '{')
cc++;
if (*_bytes == '}')
cc--;
ADVANCE;
}
while (cc != 0);
continue;
}
cw = [self parseControlWord: &len];
s = [[NSString alloc] initWithBytesNoCopy: (void *)cw
length: len
encoding: NSASCIIStringEncoding
freeWhenDone: NO];
[s autorelease];
if (strncmp(cw, "ansicpg", 7) == 0)
{
charset = NSMapGet(_charsets, s);
}
else if (strncmp(cw, "fonttbl", 7) == 0)
{
// We rewind our buffer so we start at the beginning of {\fonttbl...
_bytes = cw-2;
_current_pos -= 10;
fontTable = [self parseFontTable];
// We go back 1 byte in order to end our section properly ('}' character
REWIND;
}
else if (strncmp(cw, "stylesheet", 10) == 0)
{
_bytes = cw-2;
_current_pos -= 13;
[self parseStyleSheet];
REWIND;
}
else if (strncmp(cw, "colortbl", 8) == 0)
{
colorTable = [self parseColorTable];
}
else if (strncmp(cw, "pict", 4) == 0)
{
_bytes = cw-2;
_current_pos -= 7;
[self parsePicture];
REWIND;
}
else if ([s isEqualToString: @"b"] && formattingOptions)
{
[_html appendBytes: "<b>" length: 3];
formattingOptions->bold = YES;
}
else if ([s isEqualToString: @"b0"] && formattingOptions)
{
[_html appendBytes: "</b>" length: 4];
formattingOptions->bold = NO;
}
else if ([s hasPrefix: @"cf"] && [s length] > 2)
{
RTFColorDef *colorDef;
int color_index;
char *v;
color_index = [[s substringFromIndex: 2] intValue];
if (!formattingOptions)
continue;
if (formattingOptions->color_index >= 0) // && color_index != formattingOptions->color_index)
{
[_html appendBytes: "</font>" length: 7];
}
formattingOptions->color_index = color_index;
colorDef = [colorTable colorDefAtIndex: color_index];
v = malloc(23*sizeof(char));
memset(v, 0, 23);
sprintf(v, "<font color=\"#%02x%02x%02x\">", colorDef->red, colorDef->green, colorDef->blue);
[_html appendBytes: v length: strlen(v)];
free(v);
}
else if ([s hasPrefix: @"fcs"])
{
// ignore
}
else if ([s hasPrefix: @"fs"])
{
// ignore
}
else if ([s hasPrefix: @"fbidis"])
{
// ignore
}
else if ([s hasPrefix: @"fromhtml"])
{
// ignore
}
else if ([s hasPrefix: @"fromtext"])
{
// ignore
}
else if ([s hasPrefix: @"f"] && [s length] > 1)
{
RTFFontInfo *fontInfo;
int font_index;
font_index = [[s substringFromIndex: 1] intValue];
if (!formattingOptions)
continue;
if (formattingOptions->font_index >= 0 &&
font_index != formattingOptions->font_index)
{
[_html appendBytes: "</font>" length: 7];
}
formattingOptions->font_index = font_index;
fontInfo = [fontTable fontInfoAtIndex: font_index];
char *v = malloc(128*sizeof(char));
memset(v, 0, 128);
sprintf(v, "<font face=\"%s\">", [fontInfo->name UTF8String]);
[_html appendBytes: v length: strlen(v)];
free(v);
}
else if ([s isEqualToString: @"i"] && formattingOptions)
{
[_html appendBytes: "<i>" length: 3];
formattingOptions->italic = YES;
}
else if ([s isEqualToString: @"i0"] && formattingOptions)
{
[_html appendBytes: "</i>" length: 4];
formattingOptions->italic = NO;
}
else if ([s isEqualToString: @"tab"])
{
[_html appendBytes: "&nbsp;&nbsp;" length: 12];
}
else if ([s isEqualToString: @"softline"] || [s isEqualToString: @"par"])
{
[_html appendBytes: "<br>" length: 4];
}
else if ([s isEqualToString: @"strike"] && formattingOptions)
{
[_html appendBytes: "<strike>" length: 8];
formattingOptions->strikethrough = YES;
}
else if ([s isEqualToString: @"strike0"] && formattingOptions)
{
[_html appendBytes: "</strike>" length: 9];
formattingOptions->strikethrough = NO;
}
else if ([s hasPrefix: @"u"] && [s length] > 1 && isdigit([s characterAtIndex: 1]))
{
NSData *d;
unichar ch;
ch = (unichar)[[s substringFromIndex: 1] intValue];
s = [NSString stringWithCharacters: &ch length: 1];
d = [s dataUsingEncoding: NSUTF8StringEncoding];
[_html appendData: d];
}
else if ([s isEqualToString: @"ul"] && formattingOptions)
{
[_html appendBytes: "<u>" length: 3];
formattingOptions->underline = YES;
}
else if (([s isEqualToString: @"ul0"] || [s isEqualToString: @"ulnone"])
&& formattingOptions)
{
[_html appendBytes: "</u>" length: 4];
formattingOptions->underline = NO;
}
// If a space delimits the control word, the space does not appear in the document.
// Any characters following the delimiter, including spaces, will appear in the document.
if (*_bytes == ' ')
{
ADVANCE;
}
}
else if (c == '{')
{
formattingOptions = [[[RTFFormattingOptions alloc] init] autorelease];
formattingOptions->bold = NO;
formattingOptions->italic = NO;
formattingOptions->strikethrough = NO;
formattingOptions->underline = NO;
formattingOptions->font_index = -1;
formattingOptions->color_index = -1;
formattingOptions->start_pos = [_html length];
[stack push: formattingOptions];
ADVANCE;
}
else if (c == '}')
{
formattingOptions = [stack pop];
if (formattingOptions)
{
// Handle {\b bold} vs. \b bold \b0
if (formattingOptions->bold)
{
[_html appendBytes: "</b>" length: 4];
}
if (formattingOptions->italic)
{
[_html appendBytes: "</i>" length: 4];
}
if (formattingOptions->strikethrough)
{
[_html appendBytes: "</strike>" length: 9];
}
if (formattingOptions->underline)
{
[_html appendBytes: "</u>" length: 4];
}
if (formattingOptions->font_index >= 0)
{
[_html appendBytes: "</font>" length: 7];
}
if (formattingOptions->color_index >= 0)
{
[_html appendBytes: "</font>" length: 7];
}
}
formattingOptions = [stack top];
ADVANCE;
}
else
{
// We avoid appending NULL bytes
if (*_bytes)
[_html appendBytes: _bytes length: 1];
ADVANCE;
}
}
[_html appendBytes: "</body></html>" length: 14];
RELEASE(stack);
return AUTORELEASE(_html);
}
@end
+9 -16
View File
@@ -46,6 +46,7 @@
#import "GCSSpecialQueries+OpenChange.h"
#import "MAPIStoreTypes.h"
#import "SOGoMAPIDBFolder.h"
#import "BSONCodec.h"
#import "SOGoMAPIDBObject.h"
@@ -156,9 +157,9 @@ static EOAttribute *textColumn = nil;
- (void) setupFromRecord: (NSDictionary *) record
{
NSInteger intValue;
NSString *propsValue, *error;
NSString *propsValue;//, *error;
NSDictionary *newValues;
NSPropertyListFormat format;
//NSPropertyListFormat format;
objectType = [[record objectForKey: @"c_type"] intValue];
intValue = [[record objectForKey: @"c_creationdate"] intValue];
@@ -174,13 +175,8 @@ static EOAttribute *textColumn = nil;
propsValue = [record objectForKey: @"c_content"];
if ([propsValue isNotNull])
{
newValues = [NSPropertyListSerialization propertyListFromData: [propsValue dataByDecodingBase64]
mutabilityOption: NSPropertyListMutableContainers
format: &format
errorDescription: &error];
newValues = [[propsValue dataByDecodingBase64] BSONValue];
[properties addEntriesFromDictionary: newValues];
// [properties addEntriesFromDictionary: [propsValue
// objectFromJSONString]];
}
else
[properties removeAllObjects];
@@ -255,13 +251,13 @@ static EOAttribute *textColumn = nil;
className = @"MAPIStoreNotesMessage";
else
className = @"MAPIStoreDBMessage";
[self logWithFormat: @"PidTagMessageClass = '%@', returning '%@'",
mapiMsgClass, className];
//[self logWithFormat: @"PidTagMessageClass = '%@', returning '%@'",
// mapiMsgClass, className];
}
else
{
[self warnWithFormat: @"PidTagMessageClass is not set, falling back"
@" to 'MAPIStoreDBMessage'"];
//[self warnWithFormat: @"PidTagMessageClass is not set, falling back"
// @" to 'MAPIStoreDBMessage'"];
className = @"MAPIStoreDBMessage";
}
break;
@@ -526,10 +522,7 @@ static EOAttribute *textColumn = nil;
if ([properties count] > 0)
{
content = [NSPropertyListSerialization
dataFromPropertyList: properties
format: plistFormat
errorDescription: NULL];
content = [properties BSONRepresentation];
propsValue = [adaptor formatValue: [content stringByEncodingBase64]
forAttribute: textColumn];
}
+84
View File
@@ -0,0 +1,84 @@
#!/usr/bin/python
import getopt
import os
import re
import string
import sys
h_template = """unsigned short %(charsetName)s[%(len)d] = { %(values)s };"""
CHAR_UNDEF = "0x0000"
MAP_LEN = 256
itemsPerLine = 16
def usage():
usageMsg = """
Usage: %s -f inputFile
""" % (os.path.basename(sys.argv[0]))
sys.stderr.write(usageMsg)
def parseCharsetFile(file = None):
if file is None:
return None
charmap = [CHAR_UNDEF] * MAP_LEN
# Sample line:
# FD = U+200E : LEFT-TO-RIGHT MARK
for line in file.xreadlines():
m = re.search("(\w{2}) = U\+(\w{4}) :", line)
if not m:
sys.stderr.write("Skipping weird line: %s" % line)
continue
ind = int(m.group(1), base=16)
unicodeValue = str(m.group(2)).lower()
charmap[ind] = "0x%s" % (unicodeValue)
return charmap
def formatCharacterMap(charmap = None):
if not charmap:
return None
value = ""
for i in xrange(0,MAP_LEN-1):
char = charmap[i]
if i % itemsPerLine == 0:
value += "\n "
value += "%s, " % (char)
i += 1
value += charmap[MAP_LEN-1]
return value
if __name__ == '__main__':
inputFile = None
try:
opts, args = getopt.getopt(sys.argv[1:], "f:")
except getopt.GetoptError, err:
sys.stderr.write(str(err))
usage()
sys.exit(2)
for o, a in opts:
if o == "-f":
inputFile = a
else:
assert False, "unhandled option"
if not inputFile:
usage()
sys.exit(1)
f = open(inputFile, "r", 1)
charsetMap = parseCharsetFile(f)
charsetValues = formatCharacterMap(charsetMap)
print h_template % {"len": len(charsetMap),
"charsetName": os.path.basename(inputFile),
"values": charsetValues}
+4 -2
View File
@@ -23,6 +23,8 @@
#ifndef ICALEVENT_MAPISTORE_H
#define ICALEVENT_MAPISTORE_H
#include <talloc.h>
#import <NGCards/iCalEvent.h>
@class MAPIStoreUserContext;
@@ -34,8 +36,8 @@
- (void) updateFromMAPIProperties: (NSDictionary *) properties
inUserContext: (MAPIStoreUserContext *) userContext
withActiveUser: (SOGoUser *) activeUser;
withActiveUser: (SOGoUser *) activeUser
inMemCtx: (TALLOC_CTX *) memCtx;
@end
#endif /* ICALEVENT_MAPISTORE_H */
+6 -5
View File
@@ -20,7 +20,6 @@
* Boston, MA 02111-1307, USA.
*/
#include <talloc.h>
#include <util/attr.h>
#import <Foundation/NSArray.h>
@@ -75,16 +74,17 @@
@implementation iCalEvent (MAPIStoreProperties)
- (void) _setupEventRecurrence: (NSData *) mapiRecurrenceData
inMemCtx: (TALLOC_CTX *) memCtx
{
struct Binary_r *blob;
struct AppointmentRecurrencePattern *pattern;
blob = [mapiRecurrenceData asBinaryInMemCtx: NULL];
pattern = get_AppointmentRecurrencePattern (blob, blob);
blob = [mapiRecurrenceData asBinaryInMemCtx: memCtx];
pattern = get_AppointmentRecurrencePattern (memCtx, blob);
[(iCalCalendar *) parent
setupRecurrenceWithMasterEntity: self
fromRecurrencePattern: &pattern->RecurrencePattern];
talloc_free (blob);
//talloc_free (blob);
}
- (void) _setupEventAlarmFromProperties: (NSDictionary *) properties
@@ -134,6 +134,7 @@
- (void) updateFromMAPIProperties: (NSDictionary *) properties
inUserContext: (MAPIStoreUserContext *) userContext
withActiveUser: (SOGoUser *) activeUser
inMemCtx: (TALLOC_CTX *) memCtx
{
BOOL isAllDay;
iCalDateTime *start, *end;
@@ -328,7 +329,7 @@
value = [properties
objectForKey: MAPIPropertyKey (PidLidAppointmentRecur)];
if (value)
[self _setupEventRecurrence: value];
[self _setupEventRecurrence: value inMemCtx: memCtx];
/* alarm */
[self _setupEventAlarmFromProperties: properties];
File diff suppressed because it is too large. Load diff
Binary file not shown.
-75
View File
@@ -1,75 +0,0 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <ctype.h> header file. */
#define HAVE_CTYPE_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#define HAVE_MALLOC 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `memset' function. */
#define HAVE_MEMSET 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdio.h> header file. */
#define HAVE_STDIO_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strchr' function. */
#define HAVE_STRCHR 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strstr' function. */
#define HAVE_STRSTR 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Name of package */
#define PACKAGE "unrtf"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "bug-unrtf@gnu.org"
/* Define to the full name of this package. */
#define PACKAGE_NAME "unrtf"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "unrtf 0.21.2"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "unrtf"
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.21.2"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "0.21.2"
/* Define to rpl_malloc if the replacement function should be used. */
/* #undef malloc */
+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
Loaded 100 of 672 files, more files were not shown because too many files have changed in this diff. Show more