Compare commits

..
Author SHA1 Message Date
Luc Charland 7bb551a4ad Added saving of sort order for Events and Tasks 2015-08-06 13:48:39 -04:00
Luc Charland 31b959a7dc Added saving of Calendar Sort to jsonSettings 2015-08-06 12:17:48 -04:00
Francis Lachapelle 2a132b4e8f (css) Cleanup directives already in material 2015-08-06 11:48:42 -04:00
Francis Lachapelle ff1a1e6f59 (html) Cleanup UIxContactFoldersView.wox 2015-08-06 11:26:26 -04:00
Francis Lachapelle a4a75607fa (js,html) Improve sgSubscribe directive 2015-08-06 11:23:16 -04:00
Francis Lachapelle 6641bbded2 (js) Improve User.$filter function 2015-08-06 11:23:16 -04:00
Ludovic Marcotte 78975b9e68 (fix) add proper class to avoid displaying the chips' line 2015-08-06 09:36:43 -04:00
Ludovic Marcotte 2f122f12b6 (fix) don't show a dialog on top of a dialog for acl confirmation 2015-08-05 20:23:11 -04:00
Francis Lachapelle 5e19a889c2 (feat) Handle invitations in appointment viewer 2015-08-05 17:31:22 -04:00
Ludovic Marcotte 87aec2fc01 (feat) added batch export option to cards 2015-08-05 16:02:57 -04:00
Ludovic Marcotte 5327df4c7a (feat) added select all feature to contacts module 2015-08-05 15:04:47 -04:00
Ludovic Marcotte a220ee67b7 (feat) reworked batch menu + added save messages option 2015-08-05 14:39:58 -04:00
Ludovic Marcotte 124ca5d8cf (fix) escape the HTML content from the raw source before returning it 2015-08-05 11:08:36 -04:00
Francis Lachapelle 9dac8e55ff (js) Avoid accidentally closing the composer 2015-08-05 10:14:32 -04:00
Francis Lachapelle 4539fd4c5e (html) Internationalized labels in message viewer 2015-08-05 10:12:51 -04:00
Luc Charland 923ab97309 Added tooltips for saving/view attachments 2015-08-05 10:05:21 -04:00
Luc Charland c56644f0e5 Added tooltips to Contacts 2015-08-05 09:40:12 -04:00
Ludovic Marcotte da119ef3ad (feat) raw source support in contact module 2015-08-04 20:32:43 -04:00
Ludovic Marcotte 6e114b84be (feat) reorganized menu + added view raw source feature 2015-08-04 16:51:33 -04:00
Ludovic Marcotte dff7b59036 (fix) wrong tagging for dialog content 2015-08-04 16:39:02 -04:00
Ludovic Marcotte 7f43f894b0 (fix) update the unseenCount when reading messages 2015-08-04 16:08:17 -04:00
Ludovic Marcotte a27f106a4a (fix) pimped ical viewer 2015-08-04 13:52:31 -04:00
Francis Lachapelle 95a360dd36 (fix) Variable test in Component service 2015-08-04 13:46:55 -04:00
Luc Charland 09224f587f Added a few tooltips for the mail view 2015-08-04 12:54:58 -04:00
Francis Lachapelle ff1b9e7ed1 (fix) Draft initialization 2015-08-04 10:56:55 -04:00
Francis Lachapelle 6d260c58c7 (js) Update Gruntfile.js for changes in vendor js 2015-08-04 10:37:07 -04:00
Francis Lachapelle ba69bd4c82 (css) Improve color picker inside md-avatar 2015-08-04 08:31:40 -04:00
Francis Lachapelle 2a45a2133b (fix) Padding of mail account delegation dialog 2015-08-04 08:31:40 -04:00
Francis Lachapelle 57fbc453a6 (html) Add avatars to ACL editor 2015-08-04 08:31:39 -04:00
Francis Lachapelle f17b3638d7 (js) Fix usage of Settings.activeUser 2015-08-04 08:31:39 -04:00
extrafu 67517e0b28 Update README.md 2015-08-03 20:40:59 -04:00
extrafu 0038ce03fa Merge pull request #12 from vDevices/master
Created README & 'tutorials' subdirectory
2015-08-03 20:39:03 -04:00
Francis Lachapelle d2b2cb186e (js) Fix usage of Settings.activeUser 2015-08-03 16:18:23 -04:00
Francis Lachapelle ca8b64bd88 (js) Fix error when deleting an ACL user 2015-08-03 16:17:02 -04:00
Francis Lachapelle 732b8c9d8a (css) Fullscreen dialogs on small screens 2015-08-03 16:15:59 -04:00
Francis Lachapelle ba6418fb93 (html) Review the toolbar of dialog boxes 2015-08-03 14:44:11 -04:00
Francis Lachapelle ab1cd36c77 Review delegation dialog in Mail app module 2015-08-03 14:40:18 -04:00
Ludovic Marcotte 9f2c5b5f50 (fix) added bg icon 2015-08-03 12:48:29 -04:00
Ludovic Marcotte b6ea1de4c0 (fix) improved message editor 2015-08-03 12:43:21 -04:00
Francis Lachapelle 21f214659e (fix) Some compilation warnings 2015-08-03 12:16:16 -04:00
Francis Lachapelle 82720d341c (fix) Some compilation warnings 2015-08-03 12:03:56 -04:00
Francis Lachapelle a330ff7320 (js) Move Settings to a value in Common ng module
Also removed explicit settings and defaults that were imported in
various app modules. We now always use the Preferences ng service.
2015-08-03 11:57:04 -04:00
extrafu 375eac2be0 Merge pull request #94 from inverse-inc/feature/trailing_spaces
Feature/trailing spaces
2015-08-03 11:00:58 -04:00
Luc Charland 4cf82bd41c removed trailing space to strings 2015-08-03 10:56:24 -04:00
Luc Charland 9f202cfcdc cleaned up a few comments 2015-08-03 10:24:15 -04:00
extrafu 393321b223 Merge pull request #92 from inverse-inc/feature/remove_colon
Feature/remove colon
2015-08-03 09:54:48 -04:00
Luc Charland 6835cd5319 removed double Name translation in 5 languages 2015-08-03 09:51:31 -04:00
Ludovic Marcotte 31bc88d9d3 Updated NEWS file regarding PR93
Conflicts:

	NEWS
2015-08-03 09:19:35 -04:00
Ludovic Marcotte f515106bcc (fix) added patch from PR93 2015-08-03 09:16:55 -04:00
Ludovic Marcotte ec1420c19b (feat) now use mdDialog for message composition 2015-08-02 13:25:38 -04:00
Ludovic Marcotte f44af10cdd (feat) integrated the color picker in the pref module 2015-07-31 15:40:00 -04:00
Ludovic Marcotte e25305980f (fix) improved the account delegation dialog 2015-07-31 14:54:55 -04:00
Ludovic Marcotte 0c7bdac091 (fix) refactored code and we now return the unseenCount when fetching uids 2015-07-31 14:31:38 -04:00
Luc Charland 2f8f8c78f7 Removing colons 2015-07-31 14:14:30 -04:00
Luc Charland 90b7ce7ec3 fixed Appointments path 2015-07-31 13:57:41 -04:00
Luc Charland 6ecea9d702 cleaned up a few comments 2015-07-31 13:57:41 -04:00
Luc Charland a54b8780a8 added first draft of verify_translation 2015-07-31 13:57:41 -04:00
Ludovic Marcotte 40d269c504 (feat) unseen count support folder all accounts/mailboxes 2015-07-31 13:32:14 -04:00
Francis Lachapelle 1d52be415f (html) Improve Calendar properties dialog 2015-07-31 11:18:29 -04:00
Francis Lachapelle 3b9a989abd (js) New color picker directive 2015-07-31 11:16:34 -04:00
Ludovic Marcotte a728616bca (fix) comment typo 2015-07-31 09:05:56 -04:00
Ludovic Marcotte 65b8382020 (fix) move refresh timeout to service classes and enabled repeating timers 2015-07-30 19:47:53 -04:00
Ludovic Marcotte 85f4efab46 (fix) refactored to code 2015-07-30 14:51:14 -04:00
Ludovic Marcotte af7fb1c6ee (fix) modified the template so it shares the same l&f as the contacts one 2015-07-30 13:25:50 -04:00
Ludovic Marcotte a52d42f6b2 (feat) manual+auto refresh support for addressbooks/mailboxes 2015-07-30 13:06:28 -04:00
Francis Lachapelle 1f8edbdd1f (js) Respect SOGoCalendarDefaultReminder in editor 2015-07-30 12:05:33 -04:00
Francis Lachapelle b61eb00b99 (js) Reload lists when (en|dis)abling a calendar
Only the displayed list was refresh. Now we invalidate the hidden list.
2015-07-30 11:55:02 -04:00
Francis Lachapelle 449093c3f0 (fix) Calendar destination of new task
Also removed the possibility to use the "moveToCalendar" parameter. We
should eventually create UIxTaskActions.m as we have
UIxAppointmentActions.m for this kind of actions.
2015-07-30 11:51:02 -04:00
Ludovic Marcotte 0fc7c96924 (fix) use proper values for short/long date formats 2015-07-29 19:10:03 -04:00
Francis Lachapelle b73450e992 (fix) Label color of pseudo-input
It now matches the one of ng-material.
2015-07-29 16:45:16 -04:00
Francis Lachapelle 8e00387152 (fix) CSS padding style of toolbar 2015-07-29 16:44:18 -04:00
Francis Lachapelle b6a5eb0b60 (fix) Disable frequency when editing an occurrence 2015-07-29 16:43:10 -04:00
Francis Lachapelle d7b7824aad Improve display of attendees in event viewer 2015-07-29 16:42:20 -04:00
Francis Lachapelle 3e6c50b7dc (cleanup) Remove ionic templates 2015-07-29 15:54:13 -04:00
Ludovic Marcotte 9291dc29b6 Removed old file 2015-07-29 15:51:52 -04:00
Francis Lachapelle f5927944fa (fix) Missing header file import 2015-07-29 15:48:29 -04:00
Ludovic Marcotte 16885f4ebf (fix) properly handle subparts compilation for message/rfc822 message parts 2015-07-29 15:37:55 -04:00
Francis Lachapelle d3a233b222 (js) Improve Angular modules initialization 2015-07-29 15:16:43 -04:00
Francis Lachapelle 7e10cff395 (js) Restore user's last Calendar view
Also reviewed the handling of Angular modules dependencies.
2015-07-29 11:47:01 -04:00
Francis Lachapelle 762f305914 (cleanup) No longer used JavasScript 2015-07-29 10:11:28 -04:00
Francis Lachapelle e208ee3fde (feat) Open events from day and week views 2015-07-28 20:45:46 -04:00
Francis Lachapelle 571be37c1d (scss) Indentation 2015-07-28 15:53:48 -04:00
Francis Lachapelle 433983e7c4 (fix) DI annotation of sgIMAP controller 2015-07-28 14:37:49 -04:00
Francis Lachapelle d7aae0e667 (fix) _.allKeys doesn't exist in lodash 2015-07-28 14:21:19 -04:00
Francis Lachapelle e87a6de46b (html) Remove previous "hack" for ng-material
The md-menu positioned as a secondary action in a list can now be
properly hidden. ng-material is just getting better :)
2015-07-28 14:16:56 -04:00
Francis Lachapelle 13a779019b (html) Add toolbar to dialog boxes 2015-07-28 14:13:48 -04:00
Ludovic Marcotte 17432deaa7 (fix) reset alarm after popping it 2015-07-28 13:05:05 -04:00
Ludovic Marcotte 7365f77dd5 (feat) new Alarm service + alarms support in all modules 2015-07-28 11:54:49 -04:00
Francis Lachapelle e8dcc6df37 (js) New common ACL Controller 2015-07-28 10:53:29 -04:00
Francis Lachapelle a8765eb41b (fix) Autocompletion in mail editor 2015-07-27 20:43:43 -04:00
Francis Lachapelle c700608f0f (fix) Sidenav list items display of Preferences 2015-07-27 20:11:57 -04:00
Francis Lachapelle 86a0032cc1 Handle the edition of recurring event occurrences 2015-07-27 16:02:05 -04:00
Francis Lachapelle 049c1385d6 (fix) Event propagation when saving component 2015-07-27 13:50:14 -04:00
Francis Lachapelle a168d0227d (js) Use lodash and remove old dependencies
Replaced underscore by lodash
2015-07-27 13:27:12 -04:00
Ludovic Marcotte 40dd3e5875 (fix) reworked c_ prefixes on givenname,cn,sn,o and component.
This makes it easier to map to the quick table and avoid
fields duplications.
2015-07-27 12:47:40 -04:00
Francis Lachapelle dc9a0896e5 (js) Fix possible errors (help from jsjint) 2015-07-24 16:14:53 -04:00
Francis Lachapelle e064dc4a46 (js) Add support for local URL in sgAvatarImage
Directive was previously named sgGravatarImage.

The local URL will be used before falling back to Gravatar.
2015-07-24 15:48:28 -04:00
Francis Lachapelle 843a689094 (js) Enable jshint and uglify 2015-07-24 15:47:29 -04:00
Ludovic Marcotte f09c06f8c4 (feat) show folders stats 2015-07-24 15:35:29 -04:00
Ludovic Marcotte c365d646a2 (feat) ability to set folders as drafts/trash/sent 2015-07-24 14:40:07 -04:00
Ludovic Marcotte cbbb3dd9d4 (feat) show error message (like submission max) when sending mails 2015-07-24 11:21:04 -04:00
Ludovic Marcotte c5a35a64a2 (fix) SOGoMaximumMessageSubmissionCount should be independant from SOGoMaximumRecipientCount 2015-07-24 11:20:51 -04:00
Ludovic Marcotte a03715f74a (fix) show proper icon for shared mailboxes 2015-07-24 10:21:33 -04:00
Francis Lachapelle 51b8ce7400 (doc) Improve documentation of angular filters 2015-07-23 15:33:34 -04:00
Francis Lachapelle 2981b0af00 (js) New 'range' filter for angular 2015-07-23 15:33:33 -04:00
Ludovic Marcotte 194c5635b5 Updates for the release 2015-07-23 13:13:02 -04:00
Francis Lachapelle 73d62800e8 Update Spanish (Argentina) translation 2015-07-23 12:08:25 -04:00
Francis Lachapelle c5834e2f89 Add missing templates for Basque language 2015-07-23 12:08:15 -04:00
Francis Lachapelle ab28476e7e Add missing template for Slovenian language 2015-07-23 12:08:11 -04:00
Francis Lachapelle 538e6fa4b1 Add Chinese (Taiwan) translation 2015-07-23 12:08:04 -04:00
Francis Lachapelle c3aa601f3c (fix) Return value of [iCalPerson+SOGo uidInDomain:] 2015-07-23 12:07:57 -04:00
Francis Lachapelle 613f05ac02 Calendar module optimizations in multidomain setup
Conflicts:
	NEWS
	UI/Common/UIxUserRightsEditor.m
2015-07-23 12:06:54 -04:00
Francis Lachapelle 8f49778501 Fix .wod files for English and Basque 2015-07-23 12:03:45 -04:00
Francis Lachapelle f0b88811d6 Add Slovenian translation 2015-07-23 12:02:42 -04:00
Francis Lachapelle c1d744e47a (js) Reset "selectedCard" when cancelling new card 2015-07-23 12:01:14 -04:00
Ludovic Marcotte 12875539bb (fix) fallback to utf-8/latin1 in rare decoding error cases - this is ugly 2015-07-23 11:21:25 -04:00
Ludovic Marcotte a8dd698425 (feat) added "select all" capability, just an idea 2015-07-23 10:54:46 -04:00
Francis Lachapelle f8b6864553 (js) Remove Mailbox dependency in Preferences 2015-07-22 17:27:46 -04:00
Francis Lachapelle 01f213e65e (fix) Main toolbar of contacts module 2015-07-22 12:11:19 -04:00
Ludovic Marcotte 22ead81c48 (doc) ModuleConstraints for EAS 2015-07-22 11:55:26 -04:00
Francis Lachapelle a7afcbf4a0 (js) Use user's settings when sorting messages 2015-07-22 11:28:08 -04:00
Ludovic Marcotte a8ab01a5eb (fix) fixed EAS conversation ID issues on BB10 (#3152) 2015-07-22 10:27:24 -04:00
Ludovic Marcotte 731264d9dc (fix) make sure ActiveSync is always usable with SQL-based auth sources 2015-07-22 10:14:03 -04:00
Ludovic Marcotte 046c4db2e8 (fix) fixed computation of GlobalObjectId (#3235) 2015-07-22 10:00:28 -04:00
Ludovic Marcotte ac21649633 (feat) added support for DeletesAsMoves over EAS
Conflicts:

	ActiveSync/SOGoActiveSyncDispatcher+Sync.m
2015-07-22 09:56:36 -04:00
Ludovic Marcotte efd182f145 (fix) improved EAS email flagging handling (#3140) 2015-07-22 09:46:44 -04:00
Ludovic Marcotte b6c6e09a5a (fix) compilation warning 2015-07-22 09:26:00 -04:00
Ludovic Marcotte 83a8f388ce Android EAS Lollipop fixes (#3268 and #3269)
Conflicts:

	NEWS
2015-07-22 09:16:49 -04:00
Ludovic Marcotte 8650492989 Applied PR90 as a patch due to too-many merge conflicts when cherry-picking 2015-07-22 09:05:17 -04:00
Francis Lachapelle cc03430ac6 (fix) Don't hide "new" button on small screens 2015-07-21 15:54:26 -04:00
Francis Lachapelle 9c464c15ad (fix) Show/hide completed tasks in list 2015-07-21 15:54:26 -04:00
Ludovic Marcotte 82ed44ee31 (fix) added more proper menu activation for the mailer 2015-07-21 15:48:31 -04:00
Ludovic Marcotte d7c008f2d9 (feat) timezones are now using md-autocomplete 2015-07-21 15:21:57 -04:00
Ludovic Marcotte ea68715f59 (feat) support for drafts autosaving 2015-07-21 11:19:47 -04:00
Francis Lachapelle 601ed94d77 Update product.plist for new component templates 2015-07-21 10:15:02 -04:00
Ludovic Marcotte bee36814e5 (feat) added many missing actions on mail folders 2015-07-21 09:28:54 -04:00
Francis Lachapelle a75524af9f Review task/event viewer/editor
Components will now appear in dialogs instead of a right sidenav.

This commit also introduces read-only viewers for tasks and events.
2015-07-21 08:29:28 -04:00
Ludovic Marcotte 5eeb473fe8 (feat) initial sort/search feature for mails 2015-07-20 16:44:26 -04:00
Francis Lachapelle dfb750caf4 (fix) Resolve addressbook before rendering view 2015-07-20 15:33:51 -04:00
Ludovic Marcotte cdd449fec9 (feat) search capabilities in the addressbook module 2015-07-20 15:03:29 -04:00
Ludovic Marcotte 7c2cb259a2 (feat) sorting capabilities in the addressbook module 2015-07-20 14:24:36 -04:00
Ludovic Marcotte e7a73413d5 (fix) SOGo adjustment regarding https://github.com/angular/material/commit/dbafaa14473b41e262d55f8f6d06f818f4d88654 2015-07-19 08:39:56 -04:00
Francis Lachapelle 4c51d4702f (fix) List members auto-completion 2015-07-16 16:29:54 -04:00
Francis Lachapelle 191a1afe23 (fix) Filtering components lists 2015-07-16 16:29:00 -04:00
Francis Lachapelle 8c8070ff16 (fix) Respect order of cards list 2015-07-16 16:26:09 -04:00
Francis Lachapelle ee0e45cad6 (js) Respect user's default classification 2015-07-16 11:21:55 -04:00
Francis Lachapelle d58030a475 (css) Cleanup and fixes for latest md changes 2015-07-15 16:30:19 -04:00
Francis Lachapelle d1e1d11e4a (html) Move close button of card & msg viewer
The close button is only displayed on small devices (show-sm).
2015-07-15 15:27:51 -04:00
Francis Lachapelle f09f1a4282 (fix) Respect order in list of cards 2015-07-15 15:20:08 -04:00
Francis Lachapelle 25f364991e (fix) Creation of card/list in Contacts module 2015-07-15 15:18:23 -04:00
Francis Lachapelle 730b803ad6 (js) Replace vs-repeat by md-virtual-repeat
There're some issues with mdVirtualRepeat that required some changes to
our app:

1. Having multiple directives with md-virtual-repeat doesn't work well.
That why I added a dedicated div for the md-virtual-repeat directive.
2. ui-sref-active doesn't work well for child nodes of the
md-virtual-repeat element. The class was applied repetitively to a
visible child. I now save which message or card is selected and use the
ng-class directive to highlight the selected list item.
2015-07-15 13:44:17 -04:00
Francis Lachapelle dbb8acca9a (js) Expose 'activeUser' through navController 2015-07-14 16:12:07 -04:00
Francis Lachapelle aee229e700 (js) Make use of 'controllerAs' in Mailer module 2015-07-13 15:22:58 -04:00
Francis Lachapelle 7c6716784e (feat) Events/tasks sorting in Calendar module 2015-07-09 16:35:19 -04:00
Francis Lachapelle 9a3aeb0004 (fix) Tasks list sorting 2015-07-09 16:18:03 -04:00
Ludovic Marcotte 6f6ec58a09 (html) wrap checkbox inside md-button 2015-07-09 16:08:14 -04:00
Ludovic Marcotte 88860e2e38 (fix) don't show "end repeat" for non-repetitive events/tasks 2015-07-08 21:27:24 -04:00
Francis Lachapelle 5bbb768fe8 (html) Improve event editor 2015-07-08 21:16:33 -04:00
Francis Lachapelle 396bc3b0f6 (css) Lower icon button width to 36px 2015-07-08 21:14:25 -04:00
Francis Lachapelle 164654f784 (css) Icon modifiers (rotation) for animation 2015-07-08 21:08:51 -04:00
Francis Lachapelle 9514103031 (js) Improve search toolbar in Calendar module
- new distinct search toolbar
- restored filtering options
- honor user's settings
2015-07-08 14:49:42 -04:00
Francis Lachapelle 4d4458a183 (js) Set focus to title field in component editor 2015-07-08 14:49:42 -04:00
Francis Lachapelle 5a2eb67cb7 (fix) Alignment in bottomSheet 2015-07-08 14:49:41 -04:00
Francis Lachapelle 9bdc365bf0 (js) Allow cancelling of sgSearch 2015-07-08 14:49:41 -04:00
Francis Lachapelle 066bdc5f3f (js) New 'ready' method for Preferences service
This method returns a promise that succeeds when the user's defaults and
settings have been received from the server.
2015-07-08 14:49:40 -04:00
Francis Lachapelle 396892b0e1 (js) Simplify PreferencesController 2015-07-08 14:49:40 -04:00
Francis Lachapelle dd5b325864 (js) Simplify promises handling in User.$filter 2015-07-08 14:49:39 -04:00
Francis Lachapelle fe20cc220f (js) Improve sgSearch directive
The directive now relies on transclusion to compile its content. This
way, we don't limit the directives used inside the content.
2015-07-08 14:49:38 -04:00
Ludovic Marcotte 02112dea8a (feat) can now send out MDN responses 2015-07-08 13:19:16 -04:00
Ludovic Marcotte f369eabd06 (fix) arial labels + icon classes 2015-07-07 09:50:44 -04:00
Ludovic Marcotte 4ab2c57903 (feat) handle priority and return receipt in mail editor (needs layout work) 2015-07-07 08:35:53 -04:00
Francis Lachapelle 9015f82413 (html) Improve events/tasks lists 2015-07-06 15:16:49 -04:00
Francis Lachapelle 44b8dab9c4 (css) Left-align list items in sidenav 2015-07-06 11:14:46 -04:00
Francis Lachapelle 9814a8cd0e (css) No bg-color change in :hover of bottom sheet 2015-07-06 11:11:38 -04:00
Francis Lachapelle ecce179a2f (css) Allow .sg-child-level-[1-12] everywhere 2015-07-06 11:08:50 -04:00
Ludovic Marcotte cf0aded1a4 (feat) show the 'right' folder icons 2015-07-06 11:05:19 -04:00
Ludovic Marcotte a49687fe41 (fix) make use of floating labels 2015-07-04 20:14:32 -04:00
Ludovic Marcotte 3bfc47d105 (fix) fixed icons and controller regarding mailbox delegates 2015-07-04 07:51:20 -04:00
Ludovic Marcotte 01750fa98e (fix) small syntax error 2015-07-04 07:36:15 -04:00
Francis Lachapelle b948384ec9 (js) Preload ACL users in Calendar module 2015-07-03 21:45:59 -04:00
Francis Lachapelle 1c34e71cdc (js) Remove unused dependency on $q in controllers 2015-07-03 21:44:28 -04:00
Francis Lachapelle 2337d4057f Integrate md-icon using the Material Icons font 2015-07-03 21:42:21 -04:00
Francis Lachapelle b39dedd2d2 Add attachUrls to task editor 2015-07-03 21:42:20 -04:00
Ludovic Marcotte 05d59df68b (feat) added mailbox delegation support 2015-07-03 20:40:06 -04:00
Ludovic Marcotte 9225f2b908 (fix) layout improvements when text is folding 2015-07-03 20:07:17 -04:00
Francis Lachapelle e4e18dea5e (js) Rename variable in scope of recurrence editor 2015-07-03 16:02:47 -04:00
Francis Lachapelle b0d8148ca6 (font) Add official Material Design Icons font 2015-07-03 16:02:47 -04:00
Ludovic Marcotte 52253d8c10 (fix) fixed path handling 2015-07-03 15:17:02 -04:00
Ludovic Marcotte 94a34f41b8 (fix) some layout improvements 2015-07-03 14:46:25 -04:00
Ludovic Marcotte d1636314f1 (fix) first big pass at floating label support in all md-selects 2015-07-03 11:29:40 -04:00
Ludovic Marcotte 1ae7cddf09 Silenced NSLog calls 2015-07-03 10:22:48 -04:00
Ludovic Marcotte 5ef2db59f7 (fix) a bit more error handling 2015-07-02 16:11:11 -04:00
Ludovic Marcotte 1a78882c51 (fix) floating label for select on the login page 2015-07-02 13:20:13 -04:00
Ludovic Marcotte 6471524627 (fix) also use floating label for mail composer 2015-07-02 10:54:33 -04:00
Ludovic Marcotte bc9e1f9558 (fix) use md-select floating labels 2015-07-02 10:45:13 -04:00
Francis Lachapelle a408fdff52 (js) Minor JavaScript improvements 2015-07-01 15:21:22 -04:00
Francis Lachapelle cc7eeca2c4 (js) Improve calendar lists controller
- preload both lists (events & tasks)
- don't reload list when switching tab
2015-07-01 15:17:55 -04:00
Francis Lachapelle 35ff82710a Handle attach URLs in appointment editor 2015-07-01 15:00:12 -04:00
Francis Lachapelle ba5f6410ed Return recurrence rule only if frequency is known 2015-07-01 14:11:53 -04:00
Francis Lachapelle 763ce37f8c Allow multiple "attach" values in iCalEntityObject 2015-07-01 14:09:12 -04:00
Ludovic Marcotte f449f0456b (feat) can now copy mails 2015-06-30 17:13:55 -04:00
Francis Lachapelle 06cb06fce6 New UIxTaskEditorTemplate class 2015-06-29 21:04:41 -04:00
Ludovic Marcotte 647f052486 Fix for dfecce7381
Conflicts:

	ActiveSync/SOGoActiveSyncDispatcher+Sync.m
2015-06-29 13:55:12 -04:00
Ludovic Marcotte 013e316e7d re-enabled forwardConstraints code 2015-06-29 09:22:12 -04:00
Ludovic Marcotte 33345ed1f0 (feat) new mailbox sharing capabilities and mailbox menu 2015-06-26 13:13:25 -04:00
Ludovic Marcotte 0b5146655d (fix) do now show the subscribe options for non-GCS folders 2015-06-26 13:01:32 -04:00
Francis Lachapelle d674b33a20 (css) Review cards display in sharing dialog box 2015-06-25 11:31:53 -04:00
Francis Lachapelle c524782395 Initial task editor 2015-06-25 11:30:44 -04:00
Francis Lachapelle c144f736dc Improve JSON API documentation 2015-06-25 11:23:18 -04:00
Francis Lachapelle f4a8638fb4 (json) Add c_iscycle and c_nextalarm in tasks list 2015-06-25 11:21:24 -04:00
Francis Lachapelle 69424be245 Return attributes of iCalEntity if non-empty
Only include classification and status if theyr are not empty.
2015-06-25 11:17:53 -04:00
Francis Lachapelle c3d364558e (html) Remove line under categories in card view 2015-06-23 11:23:51 -04:00
Francis Lachapelle aa6741ee4b Move categories to top in contact editor 2015-06-23 11:22:35 -04:00
Francis Lachapelle 412dca053a (css) Fix for md-cards in ACL editor 2015-06-23 11:21:50 -04:00
Francis Lachapelle b41828a7f1 (html,js) Add reminder/alarm to event editor 2015-06-22 15:49:27 -04:00
Francis Lachapelle bb8c32a77e (html) Minor improvement to preferences module 2015-06-22 10:03:41 -04:00
Francis Lachapelle 1a5763d468 (css) Remove reference to unused font 2015-06-22 10:02:53 -04:00
Francis Lachapelle 8402152a59 Load alarm from UIxComponentEditor
The alarm attributes are now loaded from UIxComponentEditor and not
iCalEntityObject so we can determine if the component's owner is part of
the alarm's attendees.
2015-06-22 09:20:35 -04:00
Francis Lachapelle d89f02ff53 Change signature of [iCalAlarm alarmForEvent:..]
The first argument doesn't have to be a iCalRepeatableEntity; a simple
iCalEntity is enough.
2015-06-19 22:08:08 -04:00
Francis Lachapelle 94cded35d2 Revert "(fix) Adjust md-tabs for latest material"
This reverts commit 6041a9c009.
2015-06-19 14:52:00 -04:00
Francis Lachapelle ba4520da51 Use node-sass 3.x 2015-06-19 13:52:18 -04:00
Francis Lachapelle 92c4ee50fa (css) Remove reference to uninstalled font 2015-06-19 13:46:14 -04:00
Francis Lachapelle 4249d6cc5b Don't use md iconic font v2.0.0 (yet)
We need to evaluate the pros and cons of moving to font ligatures now
available with Angular Material
(https://material.angularjs.org/latest/#/api/material.components.icon/directive/mdIcon).
2015-06-19 13:43:18 -04:00
Ludovic Marcotte e65ff2105e Revert "(fix) ensure calendar objects have a (fake) filename"
This reverts commit a145fdbb53.
2015-06-17 15:57:53 -04:00
Ludovic Marcotte e5c4907aba (fix) improved memory usage 2015-06-17 08:47:15 -04:00
Ludovic Marcotte a49032a6bd (fix) show only the URL of web calendars, when asked 2015-06-15 12:03:38 -04:00
Francis Lachapelle f7f83ae1c7 (css) Review cards display in sharing dialog box 2015-06-15 11:35:20 -04:00
Francis Lachapelle 6b31e3d3b9 (fix) Remove useless ng-show directive (Contacts) 2015-06-15 11:34:48 -04:00
Francis Lachapelle 0ed67f1355 (doc) Improve Angular services documentation 2015-06-15 11:33:21 -04:00
Francis Lachapelle abe8f8f93c (doc) Improve JSON API documentation 2015-06-15 11:32:09 -04:00
Francis Lachapelle 6041a9c009 (fix) Adjust md-tabs for latest material directive 2015-06-15 11:25:32 -04:00
Francis Lachapelle da95a810d4 (fix) Avoid triggering checkbox with md-menu
When clicking on the "more" secondary button of a calendar, trick the
md-list directive to consider the 'md-secondary' class of the md-menu so
the click doesn't trigger the checkbox of the list item.
2015-06-15 11:02:59 -04:00
Ludovic Marcotte f1fc78c71b (fix) invalid scope for notification prefs 2015-06-15 10:10:58 -04:00
Ludovic Marcotte d41458dfdc (fix) hide the dialog after save 2015-06-15 10:07:56 -04:00
Ludovic Marcotte 406e9a3df2 (fix) dropped old calendar sync/tag properties 2015-06-15 10:05:39 -04:00
Ludovic Marcotte b4f9b9095d (feat) first pass at the calendar properties dialog 2015-06-15 09:53:10 -04:00
Francis Lachapelle e18b61f180 Improve API documentation /Calendar/calendarslist 2015-06-15 09:19:21 -04:00
Francis Lachapelle af6e20d627 (fix) Restore methods in UIxCalUserRightsEditor 2015-06-12 16:12:14 -04:00
Francis Lachapelle 8100dfa797 Update {variables,content}.scss for latest md 2015-06-12 15:59:26 -04:00
Ludovic Marcotte 4514d7ce32 (fix) md-content -> md-dialog-content in templates 2015-06-12 15:26:22 -04:00
Ludovic Marcotte 0612c3dff1 Fixed templates 2015-06-12 14:44:33 -04:00
Ludovic Marcotte ee9e559765 (feat) links to calendars 2015-06-12 14:24:33 -04:00
Ludovic Marcotte a89b116940 (feat) allow showing links to address books 2015-06-12 14:24:23 -04:00
Ludovic Marcotte 942c972942 (feat) re-enabled export cards feature 2015-06-12 14:23:51 -04:00
Francis Lachapelle 20914a8812 Improve and fix SASS preprocessing 2015-06-12 14:12:51 -04:00
Francis Lachapelle b85b2ed416 Update angular-material 2015-06-12 12:26:17 -04:00
Ludovic Marcotte 3a1c1226bc (feat) added menu in list of address books 2015-06-12 12:06:00 -04:00
Ludovic Marcotte 6d12c2a2c8 (feat) enabled menu and fabdial support 2015-06-12 12:06:00 -04:00
Ludovic Marcotte 23d7c06829 (feat) improved the attachments handling code for the message editor 2015-06-12 12:06:00 -04:00
Francis Lachapelle 290264262c (js) Improve autocomplete of attendees editor 2015-06-12 12:05:07 -04:00
Francis Lachapelle a95ed0f8e6 Initial ng/md version of the attendees editor 2015-06-12 12:05:06 -04:00
Francis Lachapelle a2383db454 (js) Improve recurrence editor 2015-06-12 12:05:06 -04:00
Francis Lachapelle 1d1f7445cb (html) Remove upper div from image part viewer 2015-06-12 12:05:06 -04:00
Francis Lachapelle b469045de8 (js) Simplify Dialog service 2015-06-12 12:05:05 -04:00
Francis Lachapelle a1c493358f Improve API documentation for appointment editor 2015-06-12 12:05:05 -04:00
Francis Lachapelle 4cece88a42 JSONinfy [SOGoUserHomePage readFreeBusyAction] 2015-06-12 12:05:05 -04:00
Ludovic Marcotte 8124faa6d4 (feat) "Materialization" of the IMIP handling template 2015-06-12 12:03:59 -04:00
Francis Lachapelle fb992db5ad Improve ACL editor (Scheduler & Contacts) 2015-06-12 12:03:58 -04:00
Luc Charland e385bf34d5 added simple event testing json->dav 2015-06-12 12:03:57 -04:00
Ludovic Marcotte 4f75499439 (fix) Materalized link and image templates 2015-06-12 12:03:57 -04:00
Francis Lachapelle 34140e77fc (html) Improve ACL editor 2015-06-12 12:03:56 -04:00
Francis Lachapelle 04b992e1f1 (js) Make use of 'controllerAs' in Contacts module 2015-06-12 12:03:56 -04:00
Francis Lachapelle 11cf483e2c (js) Set height/width of gravatar's image 2015-06-12 12:03:56 -04:00
Francis Lachapelle 6a835c745f (js) Fix resource URL of Acl service 2015-06-12 12:03:56 -04:00
Francis Lachapelle af353fb73f (js) Improve contact chips in card list editor
Exclude list members from auto-completion results.
2015-06-12 12:03:56 -04:00
Francis Lachapelle d159e12b3f (js) Improve contact chips in Preferences module
Exclude users already in the prevent invitations whitelist.
2015-06-12 12:03:55 -04:00
Francis Lachapelle 28477e9709 Add apidoc.json 2015-06-12 12:03:55 -04:00
Luc Charland 9a3f4080c0 test adding single and multiple phones with JSON and getting it with DAV 2015-06-12 12:03:54 -04:00
Francis Lachapelle cdd52a0b37 (css) Cleanup card.scss 2015-06-12 12:03:54 -04:00
Francis Lachapelle e226a32413 Improve login page
Used ngCloak directive to display the form only once AngularJS/Angular
Material is loaded and all components initialized.
2015-06-12 12:03:54 -04:00
Francis Lachapelle 1f83680e12 Add aria attributes in Preferences module 2015-06-12 12:03:54 -04:00
Francis Lachapelle d5f4da3934 (fix) Don't return duplicated timezones 2015-06-12 12:03:53 -04:00
Francis Lachapelle dc91be3c0d Initial recurrence editor for appointments 2015-06-12 12:03:53 -04:00
Francis Lachapelle 7e96f37809 (wox) Add classification to event editor 2015-06-12 12:03:53 -04:00
Francis Lachapelle 0ac27aab50 (js) Improve coding style of Card.service.js 2015-06-12 12:03:53 -04:00
Francis Lachapelle 3350e2fa12 (fix) Syntax of word "occurrence" 2015-06-12 12:03:52 -04:00
Francis Lachapelle e4e5106f97 Set editor mode of Sass files 2015-06-12 12:03:52 -04:00
Francis Lachapelle ed7f979635 (js) Fix dependency injection in Dialog service 2015-06-12 12:03:51 -04:00
Francis Lachapelle 46bfe6befb (fix) Resolve component data completely 2015-06-12 12:03:51 -04:00
Francis Lachapelle 22db835036 Compress production version of CSS 2015-06-12 12:03:51 -04:00
Francis Lachapelle f6f704ddd8 (js) New sgToggleGrid directive
This directive allows to transform the tiles of a md-grid-list to toggle
buttons.
2015-06-12 12:03:51 -04:00
Francis Lachapelle 9222bf80ef (js) Fix mdContactChips in preferencs module
By keeping the same array reference throughout the auto-completion, we
fix the ng-click on a list item. It also avoids constant redraws of the
list.
2015-06-12 12:03:50 -04:00
Francis Lachapelle b017cb1711 Update variables.scss for latest md version 2015-06-12 12:03:50 -04:00
Francis Lachapelle 9db7d3b85d (fix) Show/save whitelisted users for invitations 2015-06-12 12:03:50 -04:00
Francis Lachapelle 18cf3d5f9c (wox) Improve layout of Preferences module 2015-06-12 12:03:49 -04:00
Francis Lachapelle 8e286b5d15 (css) Drop unused "theme" Sass files
Only the original ng-material theme files are used in the build process
of ng-material (using gulp).
2015-06-12 12:03:07 -04:00
Francis Lachapelle ec2b52bf7b (fix) Save event to a different calendar 2015-06-12 12:03:07 -04:00
Francis Lachapelle ac705547e8 (js) Colorize the bg of calendars checkboxes
The background color was affecting only checked checkboxes. Now the
color is applied even for uncheck checkboxes.
2015-06-12 12:02:19 -04:00
Francis Lachapelle a9ad21b395 (js) Improve handling of message flags
We now call the model's methods from the template. Uncluttered the
message controller. Fixed the synchronization of the flags with the
messages list.
2015-06-12 12:02:19 -04:00
Francis Lachapelle ec123b4512 Improve tags chips of message viewer 2015-06-12 12:02:18 -04:00
Francis Lachapelle f27544c72c (js) New sgCompile directive to render mail parts 2015-06-12 12:02:18 -04:00
Francis Lachapelle 9ed65e34ad JSONify mail parts 2015-06-12 12:02:18 -04:00
Ludovic Marcotte 6cd02043af (feat) can now batch delete messages 2015-06-12 12:02:17 -04:00
Ludovic Marcotte 0edc2c1217 Added email button for selected contacts (to be implemented) 2015-06-12 12:02:17 -04:00
Francis Lachapelle 2fa0e91ca7 (js) AddressBook service: Improve documentation 2015-06-12 12:02:17 -04:00
Francis Lachapelle b37892e033 (js) Card service: Improve initialization 2015-06-12 12:02:17 -04:00
Francis Lachapelle 2b6d9db83a API documentation for batchDelete
Also return a proper JSON-payload in case of an error
2015-06-12 12:02:17 -04:00
Ludovic Marcotte 7d54bd5e86 Initial work for muliple selections + new toolbar with ops 2015-06-12 12:02:16 -04:00
Francis Lachapelle 499e66ffe9 (css) Improve contacts and messages lists 2015-06-12 12:02:16 -04:00
Francis Lachapelle 395f3585ca (js) Improve user search in AddressBook ACL editor 2015-06-12 12:02:15 -04:00
Francis Lachapelle 9f9cd68997 (fix) Partial fix for md-contact-chips
Those fixes resolve the JavaScript errors, but the behavior is wrong;
the displayed results are delayed with respect to the search string.
md-contact-chips is expected to change (for the best) soon.
2015-06-12 12:02:15 -04:00
Francis Lachapelle ab38134ba9 Improve user search auto-completion 2015-06-12 12:02:14 -04:00
Francis Lachapelle a52e6604c1 Improve contact list auto-completion 2015-06-12 12:02:14 -04:00
Francis Lachapelle b65573472e Don't use node-sass 3.0.0, yet 2015-06-12 12:02:14 -04:00
Francis Lachapelle 160055a874 Remove unused CSS files 2015-06-12 12:02:13 -04:00
Francis Lachapelle 2d46f4fd33 (js) Improve Contacts controllers 2015-06-12 12:02:13 -04:00
Francis Lachapelle 0eb2ecd2f2 (js) Improve Gravatar support 2015-06-12 12:02:13 -04:00
Francis Lachapelle 8568094266 (wox) Improve mobile display of Contacts 2015-06-12 12:02:12 -04:00
Ludovic Marcotte 5e2bdcd2ba (fix) pimped the login form and added SOGoLoginDomains support 2015-06-12 12:02:12 -04:00
Francis Lachapelle 2095df7865 Update .gitignore 2015-06-12 12:02:12 -04:00
Francis Lachapelle 618d3d9cc0 (js) Fix dependency injections 2015-06-12 12:02:12 -04:00
Francis Lachapelle 874e393948 (js) New file structure for login page (RootPage) 2015-06-12 12:02:11 -04:00
Ludovic Marcotte d056f5581a (fix) do not autocapitalize the username field 2015-06-12 12:02:11 -04:00
Ludovic Marcotte a8f52b30b8 (fix) adjusted the template after refactoring 2015-06-12 12:02:11 -04:00
Francis Lachapelle 1dc5f0d412 (js) New file structure for Angular modules
JavaScript files are now merged by the 'js' Grunt task.
2015-06-12 12:01:21 -04:00
Ludovic Marcotte b1ff1d4365 (fix) many UI improvements in the pref panel 2015-06-12 12:01:19 -04:00
Ludovic Marcotte 7e82ece74c (fix) hide the detail view when we have nothing to show 2015-06-12 11:59:05 -04:00
Francis Lachapelle a5cf7659eb (js) Fix Message service initialization 2015-06-12 11:59:04 -04:00
Luc Charland 43b6006a86 removed the unneeded sleep 2015-06-12 11:59:04 -04:00
Ludovic Marcotte 7eb58db949 (fix) also remove the Draft flag 2015-06-12 11:59:04 -04:00
Ludovic Marcotte 12c8207836 (feat) flag/unflag messages 2015-06-12 11:59:04 -04:00
Ludovic Marcotte b16c17457e (fix) disabled the toggles for priority/return receipt for now 2015-06-12 11:59:04 -04:00
Ludovic Marcotte 2d22c56efe (feat) added replied/forwarded message status support + pimped UI a bit 2015-06-12 11:59:04 -04:00
Ludovic Marcotte 8a74c9f9e0 (fix) recipients handling was broken since moving to chips 2015-06-12 11:59:03 -04:00
Ludovic Marcotte c09e76f2d1 (feat) handle show cc/bcc/attachments in mail composition 2015-06-12 11:59:03 -04:00
Luc Charland 4fa33c0bc2 All tests now pass in version 3 2015-06-12 11:59:03 -04:00
Ludovic Marcotte b0318ca7b6 (feat) chips for mail labels 2015-06-12 11:59:03 -04:00
Francis Lachapelle 8e0230488f (css) Remove Compass dependency 2015-06-12 11:59:02 -04:00
Francis Lachapelle b20707d0ed (css) Add rem function from ng's variables.scss 2015-06-12 11:59:02 -04:00
Ludovic Marcotte cc7c7f7dc7 Fixed wrong subheader name 2015-06-12 11:59:02 -04:00
Francis Lachapelle 8b483136d0 Fix compilation warning in UIxJSONPreferences.m 2015-06-12 11:59:02 -04:00
Francis Lachapelle 2888034ea6 (js) Create new appointment from Calendar module 2015-06-12 11:59:02 -04:00
Francis Lachapelle 520103cffe (js) Extend String with method 'capitalize' 2015-06-12 11:59:01 -04:00
Francis Lachapelle 12d5b57624 (js) Handle web calendars in Calendar model 2015-06-12 11:59:01 -04:00
Francis Lachapelle 523532b153 (js) Resource.post: argument 'id' is optional 2015-06-12 11:59:01 -04:00
Francis Lachapelle fc3c362515 (css) Grow width of message viewer 2015-06-12 11:59:00 -04:00
Francis Lachapelle 0c213c9e66 (js) Improve code of Calendar module
Integrated usage of 'controllerAs'.
2015-06-12 11:59:00 -04:00
Francis Lachapelle 494e2be680 (js) Save addressbook search string
This allow to show the email address that matches the search string (if
it does)
2015-06-12 11:59:00 -04:00
Francis Lachapelle d9184d2363 Format HTML + remove fab button from mail viewer 2015-06-12 11:59:00 -04:00
Francis Lachapelle d9b67a85f2 Return the proper HTTP code when saving an event 2015-06-12 11:59:00 -04:00
Francis Lachapelle e59a4b4246 Use of Dialog.prompt service in Contacts module 2015-06-12 11:58:59 -04:00
Francis Lachapelle 666d36736f Fix/improve search filter of Contacts module 2015-06-12 11:58:59 -04:00
Francis Lachapelle 33b035b360 LDIF to vCard: Handle multiple emails & phones 2015-06-12 11:58:59 -04:00
Ludovic Marcotte 41bc68946d Improved the UI of the bottom sheet content 2015-06-12 11:58:59 -04:00
Ludovic Marcotte f515543e33 (fix) many adjustments regarding auxiliary accounts 2015-06-12 11:58:58 -04:00
Francis Lachapelle 6d64242382 (fix) Restore radio-button.scss 2015-06-12 11:58:58 -04:00
Francis Lachapelle d3916e6e5e Improve API documentation 2015-06-12 11:58:57 -04:00
Francis Lachapelle f2833a2781 JSONify [UIxCalMainActions addWebCalendarAction] 2015-06-12 11:58:57 -04:00
Francis Lachapelle 9e8d991099 Display relative dates in Calendar module 2015-06-12 11:58:57 -04:00
Ludovic Marcotte 1e3cb57567 (fix) removal of mail account 2015-06-12 11:58:57 -04:00
Ludovic Marcotte bc67ffe20d (feat) Gravatar support for mail/contacts 2015-06-12 11:58:57 -04:00
Francis Lachapelle d0ee85e77a Add button to create new mailbox from account root 2015-06-12 11:58:57 -04:00
Francis Lachapelle b390a4b117 (css) Enlarge width of "detail" view 2015-06-12 11:58:56 -04:00
Francis Lachapelle bb05ce89c9 (js) Improve Dialog service 2015-06-12 11:58:56 -04:00
Francis Lachapelle 16b75b1deb Improve lists in sidenav
- the ripple effect is now visible when clicking on list items;
- the fab icon has been moved over the items list;
- colorized the checkboxes of the calendars list.
2015-06-12 11:58:56 -04:00
Ludovic Marcotte 4dbd796fd5 Added color "avatar" for mail labels 2015-06-12 11:58:55 -04:00
Ludovic Marcotte affa6ba656 (fix) new calendar category now showing color too 2015-06-12 11:58:54 -04:00
Ludovic Marcotte 8074e67b84 (fix) default calendar category colors 2015-06-12 11:58:54 -04:00
Ludovic Marcotte d43d31d144 (fix) correctly initialize arrays 2015-06-12 11:58:54 -04:00
Ludovic Marcotte 966a088a0f (fix) correctly initialize the PreventInvitationsWhitelist array 2015-06-12 11:58:53 -04:00
Ludovic Marcotte ebf4c1a9c7 (fix) also handle forwardAddress 2015-06-12 11:58:53 -04:00
Ludovic Marcotte dd13abd701 Fixed pref module 2015-06-12 11:58:53 -04:00
Ludovic Marcotte aa4dc45aa7 fix over previous commit 2015-06-12 11:50:50 -04:00
Ludovic Marcotte e1d8854d10 (fix) correctly generate the Sieve script 2015-06-12 11:50:50 -04:00
Luc Charland 243726f096 Changed preferences to use JSON for v3 2015-06-12 11:50:50 -04:00
Ludovic Marcotte f49610f058 (fix) renamed md-content -> md-dialog-content regarding changes in angular-material 2015-06-12 11:49:37 -04:00
Ludovic Marcotte a166d1b4cf Using chips for adding/viewing contact categories 2015-06-12 11:47:50 -04:00
Francis Lachapelle 8557b2a161 (fix) Reset button of contact and event editors 2015-06-12 11:47:50 -04:00
Francis Lachapelle d77f75da49 (fix) Save card in Contacts module 2015-06-12 11:47:50 -04:00
Ludovic Marcotte 0f1b0bfbbe Fixed ui routing for card editor 2015-06-12 11:47:50 -04:00
Ludovic Marcotte 91c92e3a11 added new calendar feature 2015-06-12 11:47:50 -04:00
Ludovic Marcotte 1f5248371c Disabled unuseful md-select for now 2015-06-12 11:47:49 -04:00
Ludovic Marcotte dbf614a2dc Re-enabled textures 2015-06-12 11:47:49 -04:00
Francis Lachapelle c957b4b45f Initial component editor in Scheduler module 2015-06-12 11:47:49 -04:00
Ludovic Marcotte feee156c0a Added calendar sharing capability 2015-06-12 11:47:48 -04:00
Francis Lachapelle 0d62ec0bea (js) Split Calendars list by type
The list of calendars is now splitted by type: personal calendars and
other's calendars (subscriptions).

The constructor of the Calendar model has been improved.
2015-06-12 11:47:48 -04:00
Francis Lachapelle 550fc09ee4 Add attribute isReadOnly to event/task JSON view 2015-06-12 11:47:47 -04:00
Ludovic Marcotte 5e3b3e6987 Added ACL sharing capabilities for address books 2015-06-12 11:47:47 -04:00
Ludovic Marcotte 77269e5cd6 Used the avatar for consistency with other dialogs 2015-06-12 11:47:46 -04:00
Francis Lachapelle 8c9a074688 (css) Add sticky component for subheaders 2015-06-12 11:47:46 -04:00
Francis Lachapelle 5247200bf0 (css) Improve lists and subheaders components 2015-06-12 11:47:46 -04:00
Francis Lachapelle 96ebc32d8a Split AddressBooks list by type
The list of addressbook books is now splitted by type: personal
addressbooks, other's addressbooks (subscriptions) and global
addressbooks (from sogo.conf, per domain).

The main ui-view has been splitted and therefore an additional
controller has been created.

The constructor of the AddressBook model has been improved.
2015-06-12 11:47:46 -04:00
Ludovic Marcotte 19c12add73 Added the capability to create address books 2015-06-12 11:47:46 -04:00
Ludovic Marcotte ecf30daaf3 Removed useless file 2015-06-12 11:47:45 -04:00
Ludovic Marcotte 47e7201eb6 added list avatar, make use of it 2015-06-12 11:47:45 -04:00
Ludovic Marcotte 174accdb23 Display category color 2015-06-12 11:47:45 -04:00
Francis Lachapelle 62468d21ef Improve template for sgSubscribe directive 2015-06-12 11:46:50 -04:00
Ludovic Marcotte 9571befbfd Added logoff feature 2015-06-12 11:46:50 -04:00
Ludovic Marcotte 36189e4203 Added calendar subscription 2015-06-12 11:46:50 -04:00
Ludovic Marcotte 428f2586c7 Added addressbook subscription support 2015-06-12 11:46:49 -04:00
Ludovic Marcotte 5ea57f195b Allow creation or list/contact 2015-06-12 11:46:49 -04:00
Ludovic Marcotte 11179cf27d Use a label instead of subheader, it's more sexy 2015-06-12 11:46:49 -04:00
Ludovic Marcotte 2ff6131483 Added list editor/viewer, fixed contact editor 2015-06-12 11:46:49 -04:00
Francis Lachapelle 7b874d08d4 Improve sidenav lists 2015-06-12 11:46:48 -04:00
Luc Charland 3858911007 Changed login from urlencoded to json 2015-06-12 11:46:48 -04:00
Ludovic Marcotte a25a01495f Added chips for prevent invitations 2015-06-12 11:46:48 -04:00
Francis Lachapelle 781d55cc37 Force colors of sgFolderStylesheet 2015-06-12 11:46:06 -04:00
Francis Lachapelle 5d5d8bc201 (html) Fix list of messages of selected mailbox 2015-06-12 11:46:06 -04:00
Luc Charland 0cdd19e3aa fixed a missing semi-colon 2015-06-12 11:46:05 -04:00
Francis Lachapelle 0f21c02a5f (html) Fix template of sgFolderTree directive 2015-06-12 11:46:05 -04:00
Francis Lachapelle ecad0c367f (html) Fix list of messages of selected mailbox 2015-06-12 11:46:05 -04:00
Francis Lachapelle eeca191103 (css) Cleanup sidenav component
Remove duplicated definitions from angular material source and prepare
for right sidenav.
2015-06-12 11:46:05 -04:00
Francis Lachapelle 3f27e5b775 (css) Dirty fix for vs-repeat damages 2015-06-12 11:46:04 -04:00
Ludovic Marcotte 991351999e Removed unused statement 2015-06-12 11:46:04 -04:00
Ludovic Marcotte c76bca3f68 arial label 2015-06-12 11:46:04 -04:00
Ludovic Marcotte 0529de2c1c Removed useless stuff 2015-06-12 11:46:03 -04:00
Francis Lachapelle b141031ccd Initialize arrays of new message instance 2015-06-12 11:46:03 -04:00
Francis Lachapelle 6971632165 (scss) Remove deprecated textfield component 2015-06-12 11:46:02 -04:00
Francis Lachapelle b9eb0f9a69 (scss) Integrate md-chips 2015-06-12 11:46:02 -04:00
Francis Lachapelle 0924b5154e Replace ngTagsInput by md-chips + md-autocomplete 2015-06-12 11:46:02 -04:00
Benoit Favreault 14597f8f16 Update angular-material to commit 96559458633f90dafd543d3a88f9a2165fd76ac3 2015-06-12 11:46:01 -04:00
Benoit Favreault fc69d6b1d4 Change paper palette defaults hues
Fix mobile show-hide
2015-06-12 11:46:01 -04:00
Benoit Favreault 321cfb8467 Update angular-material to commit 77504e9ff178abf02c0886d7f6cfad7d68239fca 2015-06-12 11:46:01 -04:00
Francis Lachapelle da9dbd8ad5 (fix) Restore checkbox.scss 2015-06-12 11:46:01 -04:00
Francis Lachapelle 4626039e5c (fix) JavaScript errors on Mail preferences tab 2015-06-12 11:46:01 -04:00
Benoit Favreault 41f598c9ed Reset SchdulerUI.scss to [6ee715d] 2015-06-12 11:45:38 -04:00
Benoit Favreault f080536b3f Resolve conflict 2015-06-12 11:45:38 -04:00
Benoit Favreault af57fa84e4 Update angular-material [commit 42db19dd5571eb88ba8d2a9667d183d9f3d61da7] 2015-06-12 11:45:38 -04:00
Benoit Favreault 46a262acfa Cleaning unused scss files 2015-06-12 11:45:38 -04:00
Francis Lachapelle a276ac366e Set width/position of events blocks and add colors 2015-06-12 11:45:10 -04:00
Francis Lachapelle 82d1d5e701 Review calendar views templates
Changed month view to a md-grid-list.
Added some colors.
2015-06-12 11:45:10 -04:00
Francis Lachapelle 305c13d720 Add common template UIxTopnavToolbarTemplate.wox 2015-06-12 11:45:09 -04:00
Ludovic Marcotte 0de02262d0 (fix) make sure we can always add filters 2015-06-12 11:45:09 -04:00
Ludovic Marcotte d581054214 (fix) fixed default values for many prefs 2015-06-12 11:45:09 -04:00
Francis Lachapelle e8acb225e4 Add md-grid-list and md-autocomplete components 2015-06-12 11:45:08 -04:00
Ludovic Marcotte 6e36154b1b (fix) retagged properly for latest angular-material changes 2015-06-12 11:45:08 -04:00
Francis Lachapelle 8f47e62dd2 Calendar module: add month view 2015-06-12 11:44:35 -04:00
Ludovic Marcotte a2c469d46a (fix) correctly handle PreventInvitationsWhitelist 2015-06-12 11:44:35 -04:00
Ludovic Marcotte 6f59955340 (fix) sanitize autoReplyEmailAddresses 2015-06-12 11:44:35 -04:00
Ludovic Marcotte 70e5b1d4aa (fix) pref template now looks like others 2015-06-12 11:44:34 -04:00
Ludovic Marcotte f262347149 (fix) more defaults values in the prefs 2015-06-12 11:44:34 -04:00
Ludovic Marcotte 7168779684 (feat) added password change support 2015-06-12 11:44:34 -04:00
Ludovic Marcotte d21715d8f1 (fix) right localized string + one for account locked 2015-06-12 11:43:53 -04:00
Ludovic Marcotte 1fe5e39254 Default value for short date format 2015-06-12 11:43:52 -04:00
Ludovic Marcotte 023362797b Icons and flexbox additions to the guide 2015-06-12 11:43:52 -04:00
Ludovic Marcotte 772a682655 (fix) correctly localize mail labels from common bundle 2015-06-12 11:43:52 -04:00
Francis Lachapelle 4252b66b6e Initial SOGo developer's guide 2015-06-12 11:43:52 -04:00
Francis Lachapelle 91acb9d0c5 Integrate UIxSidenavToolbarTemplate in all modules 2015-06-12 11:43:51 -04:00
Francis Lachapelle 171b5085ab Fix GNUmakefile for latest underscore package 2015-06-12 11:42:40 -04:00
Benoit Favreault c38a23d9b1 Hot-fix for build problem 2015-06-12 11:42:39 -04:00
Benoit Favreault 92ecdd52ad Hot-fix for build problem (commit/74dda0206595acb1c48f7d328fd96b64025542bb) 2015-06-12 11:42:39 -04:00
Ludovic Marcotte 8b093f9001 (fix) broken template, additional </div> closing tag 2015-06-12 11:42:39 -04:00
Benoit Favreault 5797e70358 Made bottom sheet opaque 2015-06-12 11:42:39 -04:00
Benoit Favreault a75719e151 Fix fab-button positionning 2015-06-12 11:42:38 -04:00
Benoit Favreault a5c9f41375 Fixed "fantom account" 2015-06-12 11:42:38 -04:00
Benoit Favreault 00d2154c0e fix card background color (angular-material regression)
Change views container justification
hide sg-menu components
2015-06-12 11:42:38 -04:00
Francis Lachapelle 0fc027e5e9 Set the doctype to HTML5 2015-06-12 11:42:37 -04:00
Francis Lachapelle 5f7abec980 Gruntfile.js: add postcss:dist to build task 2015-06-12 11:42:37 -04:00
Francis Lachapelle 6c4a82571c Calendar module: add day view 2015-06-12 11:42:37 -04:00
Francis Lachapelle 7ef01304ee Add debounce to sgSearch Angular directive 2015-06-12 11:42:37 -04:00
Francis Lachapelle 8d66f62cad [fix] JS syntax error on login page 2015-06-12 11:42:37 -04:00
Benoit Favreault eaeae77be4 Fix (tried to) regressions introduced by angular-material update 2015-06-12 11:42:08 -04:00
Benoit Favreault 1477bd6eae Regression fixes 2015-06-12 11:42:08 -04:00
Benoit Favreault fe8c1b927c Fix mobile transitions (sort of) 2015-06-12 11:42:07 -04:00
Benoit Favreault a554158686 Fix mobile transitions (sort of) 2015-06-12 11:42:07 -04:00
Benoit Favreault f6cb8f226a Edit scss-lint to prevent false positive warnings 2015-06-12 11:42:07 -04:00
Benoit Favreault 5224a7b304 Fix fab-button positioning (still some strange corner-cases from md sources) 2015-06-12 11:42:07 -04:00
Benoit Favreault b5bea16abb Add sassyJSON library 2015-06-12 11:42:07 -04:00
Benoit Favreault 3441a66040 Add paper texture to toolbar and sidenav 2015-06-12 11:42:06 -04:00
Benoit Favreault e69c47854a Fine-tune layout 2015-06-12 11:41:28 -04:00
Benoit Favreault 2c8d1b5db7 Alternate mobile transitions 2015-06-12 11:41:27 -04:00
Francis Lachapelle 2446677172 [fix] Add definition of UIxSidenavToolbarTemplate 2015-06-12 11:41:27 -04:00
Francis Lachapelle abe9a85c4f SOGo.SchedulerUI AngularJS module 2015-06-12 11:41:26 -04:00
Francis Lachapelle a57bf56165 [fix] Possible exception in UIxCalendarSelector.m 2015-06-12 11:41:26 -04:00
Francis Lachapelle 9a1c2b6a11 New ng directives for Calendar module
- sgCalendarDayTable
- sgCalendarDayBlock
2015-06-12 11:41:26 -04:00
Francis Lachapelle 4b47e5de83 Calendar module: initial AngularJS-based templates 2015-06-12 11:41:25 -04:00
Francis Lachapelle 22c9b61246 Extend String and Date native JS objects 2015-06-12 11:41:25 -04:00
Francis Lachapelle e9db6cda61 UIxCalListingActions: improve style and syntax 2015-06-12 11:41:25 -04:00
Francis Lachapelle 44c49abbec Calendar list: use 'name' instead of 'displayName' 2015-06-12 11:41:25 -04:00
Francis Lachapelle 8b6a3d0e3f Initial JavaScript models for calendar module 2015-06-12 11:41:25 -04:00
Francis Lachapelle d72f83ee95 Save calendar: use 'name' instead of 'displayName' 2015-06-12 11:41:24 -04:00
Benoit Favreault ba35bc801f Add a grunt task target postcss:dev (no minification) 2015-06-12 11:41:24 -04:00
Ludovic Marcotte 10a017503e Now enforce SOGoMailCustomFromEnabled 2015-06-12 11:41:24 -04:00
Ludovic Marcotte bb1977fa93 Wiped unused scss file 2015-06-12 11:40:07 -04:00
Ludovic Marcotte cf4593917f More form validation 2015-06-12 11:40:07 -04:00
Francis Lachapelle ae2990d8d6 Review core scss following ng-material changes 2015-06-12 11:40:06 -04:00
Benoit Favreault 05e58b30cc Replace mobile detail-view transitions
Minor adjustments to layout
2015-06-12 11:39:49 -04:00
Ludovic Marcotte 2bc44dec9b Improved preferences module (save/load, checks on enabled modules, etc.) 2015-06-12 11:38:08 -04:00
Benoit Favreault 48b74b0f6b Add responsiveness (First draft) 2015-06-12 11:35:54 -04:00
Francis Lachapelle 516e5fd303 Add current date in top bar 2015-06-12 11:35:54 -04:00
Ludovic Marcotte 0241cacbf9 Added some data validation 2015-06-12 11:35:53 -04:00
Benoit Favreault 78da72f3cb Replace specific list-view by generic (class-based) view 2015-06-12 11:35:52 -04:00
Benoit Favreault 660af9abfd Amend previous:
Add a view-detail class (for more generic use)
Fix the regression (scroll) problem on contact editor
2015-06-12 11:35:52 -04:00
Benoit Favreault b4f2b470dc Add a scss-lint config file 2015-06-12 11:35:52 -04:00
Benoit Favreault f99dae331d Add a view-detail class (for more generic use)
Fix the regression (scroll) problem on contact editor
2015-06-12 11:35:52 -04:00
Benoit Favreault 655fe5f731 Fix regression on Contact editor 2015-06-12 11:35:52 -04:00
Francis Lachapelle 72968f2e6e Indentation of Gruntfile.js 2015-06-12 11:35:51 -04:00
Ludovic Marcotte 0f2e3df164 More cleanups, defaults values for mail/contact/calendar labels and data validation 2015-06-12 11:35:51 -04:00
Benoit Favreault 818af41ea6 Add breakpoints management librairies
Add grunt-contrib-compass (required)
Edit gruntfile.js (add compass tasks)

--don't forget to update bower components
2015-06-12 11:34:29 -04:00
Benoit Favreault 6153e88f62 Add animation params 2015-06-12 11:34:29 -04:00
Ludovic Marcotte 6636fe3625 Disabled lots of unused code (to be removed) in v3/prefs 2015-06-12 11:34:28 -04:00
Ludovic Marcotte 96d2a4cea8 Preferences saving support 2015-06-12 11:27:17 -04:00
Francis Lachapelle 2edfd1863b Addressbook module: improve routing views handling 2015-06-12 11:26:07 -04:00
Benoit Favreault 766c421b53 Remove margin from date in msg list 2015-06-12 11:26:07 -04:00
Francis Lachapelle f909fe657f Webmail: fix cancel button of message editor 2015-06-12 11:26:07 -04:00
Francis Lachapelle 885140c92a Addressbook module: fix edit button 2015-06-12 11:26:07 -04:00
Francis Lachapelle 6bf22795f3 Improve bower.json 2015-06-12 11:26:07 -04:00
Francis Lachapelle 3864264787 JS Card model: initialize birthday as Date object 2015-06-12 11:26:06 -04:00
Francis Lachapelle a3aaf36477 Contact editor: remove extra bottom padding 2015-06-12 11:26:06 -04:00
Francis Lachapelle 4f6babcdcc Add cancel button to Webmail editor 2015-06-12 11:26:06 -04:00
Ludovic Marcotte 56763e1aca Removed dead code, support for adding calendar categories, disabled unused tab 2015-06-12 11:26:05 -04:00
Francis Lachapelle a787521977 Restore md-button in sgSearch directive 2015-06-12 11:22:46 -04:00
Benoit Favreault ca1831271b Make iconButton round to display a more elegant ripple-effect 2015-06-12 11:22:45 -04:00
Benoit Favreault d6a294b89f Fix breakpoints in scss and js (in await for a more elegant solution) 2015-06-12 11:22:45 -04:00
Francis Lachapelle 6b1fe301a6 Fix mail search criteria 2015-06-12 11:22:45 -04:00
Francis Lachapelle 8d003a7c35 Return used space of quota as a number in JSON 2015-06-12 11:22:45 -04:00
Francis Lachapelle db9e3a5401 Use sgSearch directive in Webmail module 2015-06-12 11:22:45 -04:00
Francis Lachapelle 01d4134a23 Use sgSearch directive in addressbook module 2015-06-12 11:22:44 -04:00
Francis Lachapelle 44164c0f43 Improve and document Webmail search options 2015-06-12 11:22:44 -04:00
Francis Lachapelle 68eec08de6 New sgSearch Angular directive 2015-06-12 11:22:44 -04:00
Francis Lachapelle 0e3cbe8c98 Improve "load images" button from Webmail 2015-06-12 11:22:44 -04:00
Benoit Favreault 4ab4ac0f11 Fix card.view template to prevent useless element (<ui-view="undefined">) injection 2015-06-12 11:22:43 -04:00
Benoit Favreault 8cebc00f7a Polish UI (Contact and Mail)
- Unifiy & simplify markup
- Add visual consistency
2015-06-12 11:22:43 -04:00
Benoit Favreault 01f1cbbd75 Fix minor deprecations in Preferences template 2015-06-12 11:22:43 -04:00
Benoit Favreault 6a304b3e07 Fix sidenav icon-button 2015-06-12 11:22:43 -04:00
Ludovic Marcotte 5b674abcf1 Fixed preferences module wrt recent changes 2015-06-12 11:22:43 -04:00
Benoit Favreault e756053f8b Replace bottom-bar by bottom-sheet
Adjust sidenav layout
Unify background colors
2015-06-12 11:18:00 -04:00
Benoit Favreault 69d0a3ad57 Minor adjustment to toolbar date 2015-06-12 11:17:59 -04:00
Benoit Favreault a57713523b Finish the toolbars
Add an app button on sidenav
Add a logout select on sidenav
2015-06-12 11:17:59 -04:00
Benoit Favreault 9fc713dc5f Create a 'css' grunt task (sass + postcss) 2015-06-12 11:17:59 -04:00
Benoit Favreault 31bb97aaec Update angular-material [dc2d204] master 2015-06-12 11:17:58 -04:00
Francis Lachapelle 1d8dbbfe2c Restore compose mail button 2015-06-12 11:17:58 -04:00
Francis Lachapelle fc72d3b12a Cleanup references to ZURB Foundation 2015-06-12 11:17:58 -04:00
iRouge bdbbc5be47 Fix login window according to specs 2015-06-12 11:17:57 -04:00
Francis Lachapelle f1cdb3a472 Cleanup dead code from js/Common/ui.js 2015-06-12 11:17:57 -04:00
iRouge fdb4cd71eb Fix sidenav toolbar (logo and buttons) 2015-06-12 11:17:56 -04:00
iRouge 90cd79a21b Adjust Contact view (center card in right container) 2015-06-12 11:17:55 -04:00
iRouge 90c359779e Fix Contact editor layout 2015-06-12 11:17:55 -04:00
iRouge 0cd4688e64 Update material-angular (release 0.8.3) 2015-06-12 11:17:55 -04:00
iRouge 9c42350caa Add aria-label to iconButtons 2015-06-12 11:17:55 -04:00
iRouge 1ac49415d1 Remove (useless) "close" button on sidenav 2015-06-12 11:17:54 -04:00
iRouge bed46ba2eb Correct sources to prevent angular.js deprecation Warning
Correct scss to prevent 404 server response
2015-06-12 11:17:54 -04:00
iRouge 02cdc869be Apply iconButton to Contact and Mail 2015-06-12 11:17:54 -04:00
iRouge 4264d054ca Create Sass component: iconButton 2015-06-12 11:17:53 -04:00
iRouge b6f83f3275 Update angular-material 2015-06-12 11:17:53 -04:00
iRouge 1fc846bf5c Update angular-material 2015-06-12 11:17:53 -04:00
iRouge 2d2edabb18 Add action "create new contact" to button 2015-06-12 11:17:53 -04:00
iRouge dcfa43ab28 Update angular-material 2015-06-12 11:17:53 -04:00
iRouge b0d7fff56a Add Selected-state to lists elements (Contacts and Messages) -- Amend previous 2015-06-12 11:17:52 -04:00
iRouge be4d56b7e1 Add Selected-state to lists elements (Contacts and Messages) 2015-06-12 11:17:52 -04:00
Francis Lachapelle fefd4fc7c7 Fix md-select 2015-06-12 11:17:52 -04:00
iRouge 855acccd6d Update angular-material 2015-06-12 11:17:52 -04:00
iRouge 80d6c0226a Adjust UI for Contact, Contact editor, Messages and Message editor 2015-06-12 11:17:51 -04:00
Francis Lachapelle 15dab4dfe5 Add placeholder to type selects of contact editor 2015-06-12 11:17:51 -04:00
Francis Lachapelle dbb08a762a Fix "add" buttons of contact editor 2015-06-12 11:17:51 -04:00
Francis Lachapelle af144585a5 Cleanup formatting of attributes in HTML templates 2015-06-12 11:17:50 -04:00
Francis Lachapelle 6a25ccfe96 Remove data- prefix in attributes of HTML tags 2015-06-12 11:17:50 -04:00
Francis Lachapelle dd84782427 Cleanup .gitignore 2015-06-12 11:17:49 -04:00
iRouge 012d953d65 Add an input-container to search field in Contact toolbar 2015-06-12 11:17:49 -04:00
iRouge 5819cc75d3 Style Contact Editor UI: Ready to test
Some functional bugs remaining
2015-06-12 11:17:49 -04:00
Ludovic Marcotte 5c3f0138f5 First pass at the v3 pref module
The UI needs to be styled. We also need to properly load "default"
values from the system/domain/user defaults and save them correctly
too.
2015-06-12 11:17:49 -04:00
Francis Lachapelle 575676deb8 Add search field in AddressBook module 2015-06-12 10:50:10 -04:00
Francis Lachapelle 4b9eb44790 Initial integration of md-select in contact editor 2015-06-12 10:50:10 -04:00
Francis Lachapelle dc538f969e Cleanup dependencies in bower.json 2015-06-12 10:50:10 -04:00
iRouge e32f6d3086 Update angular-material 2015-06-12 10:50:09 -04:00
Francis Lachapelle 4bce4ff988 Update angular-material 2015-06-12 10:50:09 -04:00
iRouge fe071a5435 Style contact editor (email addresses with select) 2015-06-12 10:50:09 -04:00
iRouge 6b58f3a080 Style contact editor (model for add and remove) 2015-06-12 10:50:08 -04:00
iRouge 1d61e33a51 Update angular-material (select are fixed !) 2015-06-12 10:50:08 -04:00
iRouge 79dc49b905 Style contact editor layout (needs more work) 2015-06-12 10:50:08 -04:00
iRouge b81f98236c Style contact-view layout 2015-06-12 10:50:08 -04:00
iRouge b7adf2814d Refactor:
- use lowercase and hyphen name for new component according to Sass Guidelines
- change every uses by hand (thanks to my stupid IDE WebStorm)
2015-06-12 10:50:07 -04:00
iRouge 5980f8e90e Create new Sass component: pseudo-input 2015-06-12 10:50:07 -04:00
iRouge cfed9c2058 Update angular-material 2015-06-12 10:50:07 -04:00
iRouge 16440998de Fix Messages editor:
- textarea field
- labels and placeholders color
2015-06-12 10:50:07 -04:00
iRouge 1264dbad73 Skin Contact editor according to Material Design specs (still buggy) 2015-06-12 10:50:06 -04:00
iRouge 3fb8a42856 Fix login layout ;-) (md-select are still buggy) 2015-06-12 10:50:06 -04:00
Francis Lachapelle 4a4658e29d Add missing npm modules for grunt postcss 2015-06-12 10:50:06 -04:00
Francis Lachapelle 7ff934a5cb Remove dependency of hammer.js 2015-06-12 10:50:06 -04:00
Ludovic Marcotte 6d4147fa34 fixed templates 2015-06-12 10:50:05 -04:00
iRouge b2c71ceae9 Add box-shadow to Mail editor 2015-06-12 10:50:05 -04:00
iRouge 4185cc37fe Style the plain-text Mail editor
Style Contacts
Style Contact editor (buggy)
Change postcss config
2015-06-12 10:50:05 -04:00
Ludovic Marcotte 79a0a3684c Use md-select on the root page 2015-06-12 10:50:04 -04:00
Benoit Favreault dcd6c5fd5a Add autoprefixer and its dependancies (fix the buggy flex boxes in Safari and some older browsers) 2015-06-12 10:50:04 -04:00
Francis Lachapelle cc24b9b599 Add md-select SASS component 2015-06-12 10:50:04 -04:00
Francis Lachapelle 1569306ea0 Update angular-material subrepo 2015-06-12 10:50:04 -04:00
iRouge a1f0c9fd6e Update angular-material 2015-06-12 10:50:03 -04:00
Francis Lachapelle da22cd854b Fix compilation of UIxTaskEditor.m 2015-06-12 10:50:03 -04:00
Francis Lachapelle 94105e937a Improve JSON getter/setter for todos 2015-06-12 10:50:03 -04:00
Francis Lachapelle f47a22068f JSON: fix handling of dates of all-day events 2015-06-12 10:50:03 -04:00
Francis Lachapelle 177c933af4 Lowercase the status property of vEvent & vToDo 2015-06-12 10:50:02 -04:00
Francis Lachapelle bbc5a2a048 Fix compilation warning of SOGoAppointmentObject.m 2015-06-12 10:50:02 -04:00
Ludovic Marcotte 48ffe8fb7e Minor improvement to the template 2015-06-12 10:50:01 -04:00
Ludovic Marcotte e3d4a7a373 Deleted old CSS 2015-06-12 10:50:01 -04:00
Francis Lachapelle 4ddf92aadb JSON: Return ISO8601 dates in calendar components 2015-06-12 10:50:01 -04:00
Francis Lachapelle e226825bde Add [NSCalendarDate+SOGo iso8601DateString] 2015-06-12 10:50:01 -04:00
iRouge d8a816a335 Add toolbars Icons (several bugs, some remaining) 2015-06-12 10:50:00 -04:00
Ludovic Marcotte b9e7e24344 Fixed remember login option 2015-06-12 10:50:00 -04:00
Francis Lachapelle 23ce8904a9 Restore color transistion in sidenav.scss 2015-06-12 10:49:59 -04:00
Francis Lachapelle d1271799f4 Update angular-material version in bower.json 2015-06-12 10:49:59 -04:00
Ludovic Marcotte e5726d2840 WiP - some improvements to the login form 2015-06-12 10:49:58 -04:00
iRouge fcd5abfafc Update angular-material version 0.8.0-rc1 2015-06-12 10:49:57 -04:00
Francis Lachapelle 67c62fe85c Fix compilation of UIxComponentEditor.m 2015-06-12 10:49:57 -04:00
Francis Lachapelle f9271b747c Initial JSON actions to get/set an event 2015-06-12 10:48:00 -04:00
iRouge f694f57638 Minor tweaks to Mailer UI 2015-06-11 15:57:27 -04:00
iRouge 522108bdd3 [Amend previous commit]Styled ngTags for Mail editor and propose a chip-like version of tags 2015-06-11 15:57:27 -04:00
iRouge 780d757d6b Styled ngTags for Mail editor and propose a chip-like version of tags 2015-06-11 15:57:27 -04:00
iRouge df8b4e302f Styled ngTags but no hasFocus state 2015-06-11 15:57:27 -04:00
iRouge 1bb66bbf7d Skin the Mail editor except ng-tags 2015-06-11 15:57:26 -04:00
iRouge a1299fea97 Skin the Mail editor 2015-06-11 15:57:26 -04:00
Francis Lachapelle 221e49a5d1 Improve [iCalTrigger asDictionary] 2015-06-11 15:57:26 -04:00
iRouge d123b2d5d4 Change PseudoField-label font-weight 2015-06-11 15:57:26 -04:00
iRouge 4f2fc5c99e Fixed the message headers design (markup and scss)
Create a "PseudoField" component that mimics Material Design input fields
2015-06-11 15:57:25 -04:00
Francis Lachapelle e429dc3ff1 Add [iCalByDayMask initWithDaysAndOccurences:] 2015-06-11 15:57:25 -04:00
iRouge 9e7a051d25 Update angular-material 2015-06-11 15:57:25 -04:00
iRouge 75f38173c5 Adjust Messages header view
Add ngMaterial directives tomessage composer
2015-06-11 15:57:24 -04:00
Francis Lachapelle 4cd6ffcaec Messages list: add ng directives to icons 2015-06-11 15:57:24 -04:00
iRouge 12807457d4 Update angular-material 2015-06-11 15:57:24 -04:00
Ludovic Marcotte aefb27fc5c Initial (and fugly) materialization of the login page 2015-06-11 15:57:23 -04:00
iRouge cd32bcf961 Fine-tune presentation of Mailer UI
- Colors
- Icons
- Dimmensions
- Typography
2015-06-11 15:57:22 -04:00
iRouge 16f275af52 Add SOGo logo 2015-06-11 15:57:22 -04:00
iRouge 419f1bd698 Adjust containers width according to Google's specs 2015-06-11 15:57:21 -04:00
iRouge e00416e1b8 Apply colours to components 2015-06-11 15:57:21 -04:00
iRouge daaa4284cb Add Sass version of SOGo's palettes, mixin to generate theme-class and a getter function for convenient access to colours trough any scss 2015-06-11 15:57:20 -04:00
Francis Lachapelle 33e70cd3f3 Remove dependancy to angular-material.css 2015-06-11 15:57:20 -04:00
iRouge 44e56c92d0 Update Angular-Material to 0.7.1 : HEAD origin/master origin/HEAD master 2015-06-11 15:57:19 -04:00
iRouge 6404536d19 Add md-colors module 2015-06-11 15:57:19 -04:00
iRouge e7b7e9cefe Adjust z-indexes and box-shadows 2015-06-11 15:57:19 -04:00
iRouge 174b6f365b Typograpy : Messages list subheader 2015-06-11 15:57:18 -04:00
iRouge 08a76aef97 Adapt markup to typographic styles
- Mail Messages List
2015-06-11 15:57:18 -04:00
Francis Lachapelle bd61c354f0 Fix references to font files in typography.scss 2015-06-11 15:57:17 -04:00
Francis Lachapelle 13144aad3b Preparation for build of a unique CSS 2015-06-11 15:57:17 -04:00
iRouge b163e59563 Adjust typography for autoSrollList 2015-06-11 15:57:17 -04:00
iRouge 09fa2be5bd Typography auto-scroll List 2015-06-11 15:57:17 -04:00
Francis Lachapelle 36c931b596 Preparation for build of a unique CSS 2015-06-11 15:57:16 -04:00
Francis Lachapelle 6040838396 Don't use bower package of the font Fira 2015-06-11 15:57:16 -04:00
Francis Lachapelle 1a81abebaa Remove unused files from scss directory 2015-06-11 15:57:16 -04:00
iRouge a191c7a382 Typography : Google Material Design standard styles
- Layout is broken
2015-06-11 15:57:15 -04:00
iRouge 907df81436 Typography-2 2015-06-11 15:57:14 -04:00
iRouge 8f01b0c739 Add Fira Sans to font folder 2015-06-11 15:57:14 -04:00
Francis Lachapelle 8c974e6c1a Add Fira font 2015-06-11 15:57:10 -04:00
iRouge e73ed8ae44 Add bower sass-cache to gitignore 2015-06-11 15:57:10 -04:00
iRouge f59b078faa Typography 2 2015-06-11 15:57:09 -04:00
iRouge 6319b6f531 Typography 2015-06-11 15:57:09 -04:00
Francis Lachapelle 9671fbf506 Remove .sass-cache directory 2015-06-11 15:57:09 -04:00
iRouge 670d2bc382 Generate basic font-size according to Google Material design specs 2015-06-11 15:57:08 -04:00
Francis Lachapelle 6f6338bb64 Fix font file name in SASS 2015-06-11 15:57:06 -04:00
iRouge 1528b32cc7 Update fontes icônes 2015-06-11 15:57:06 -04:00
Francis Lachapelle e1b155b455 Remove fonts managed by bower & grunt 2015-06-11 15:57:06 -04:00
iRouge 72ae466541 Embedded Icon font source has base64 data URI in CSS 2015-06-11 15:57:06 -04:00
Francis Lachapelle 5cc14bb729 Remove reference to bower_components in CSS 2015-06-11 15:57:02 -04:00
Francis Lachapelle 79a5d61efb Improve sgFolderTree
Replaced the A link by a button and renamed the childLevel# CSS class by
a more appropriate sg-child-level-# class.
2015-06-11 15:57:02 -04:00
Francis Lachapelle c664648eb6 Fix processing of SCSS with Grunt
We now use the Ruby implementation of SASS (grunt-contrib-sass) since
libsass is not compatible with Compass.
2015-06-11 15:57:01 -04:00
Francis Lachapelle df6d957721 Fix mailbox rename operation 2015-06-11 15:57:01 -04:00
Francis Lachapelle ee9ef2f0e4 Remove unused SASS files 2015-06-11 15:57:01 -04:00
Francis Lachapelle 383ccdbc82 Add CSS animation to mailboxes tree 2015-06-11 15:57:00 -04:00
Francis Lachapelle 225d039f89 Improve sgFolderTree directive (mailboxes tree) 2015-06-11 15:57:00 -04:00
Francis Lachapelle 7f74d5a3d9 New sgEnter Angular directive 2015-06-11 15:57:00 -04:00
Francis Lachapelle 862068eeb5 Improve JSON getters for events 2015-06-11 15:56:59 -04:00
iRouge 56607a1baf Refactor contact editor form element templates markup and style 2015-06-11 15:56:34 -04:00
iRouge 750a41f19a CSS files for convenience 2015-06-11 15:56:34 -04:00
iRouge 6651b02ba2 Replace valueless attributes by classes 2015-06-11 15:56:33 -04:00
iRouge 3054c04261 Add a utility to replace attributes without values by classes 2015-06-11 15:56:33 -04:00
iRouge 04132023e6 Clean-up markup in templates 2015-06-11 15:56:33 -04:00
iRouge 60bd406eac Add import to bower_components ngMaterial 2015-06-11 15:56:33 -04:00
iRouge 7dc7662adf Fix a broken tag in UIxPageEditorTemplate 2015-06-11 15:56:33 -04:00
iRouge 047138984a Fix an update version issue 2015-06-11 15:56:32 -04:00
iRouge 1a7bfee6b6 define base theme : add palette definitions to module initialization 2015-06-11 15:56:32 -04:00
iRouge ee4c1c0706 define theme 2015-06-11 15:56:32 -04:00
iRouge eea5cf8d0b Edit gitignore to ignore built API doc 2015-06-11 15:56:32 -04:00
iRouge 67076cdffb Update angular-material 2015-06-11 15:56:31 -04:00
Francis Lachapelle 80785304f1 JSONify [UIxCalendarProperties saveAction] 2015-06-11 15:56:31 -04:00
Francis Lachapelle c934b3d9c0 Improve API doc of UIxContactEditor 2015-06-11 15:54:15 -04:00
Francis Lachapelle 794c1999bc Add bower package "material-design-iconic-font"
We actually don't use "material-design-fonticons"
2015-06-11 15:54:14 -04:00
Francis Lachapelle aaed279c50 Extend JSON response of calendar properties 2015-06-11 15:54:14 -04:00
Francis Lachapelle bd6a430d3a Add bower package "material-design-fonticons" 2015-06-11 15:54:14 -04:00
iRouge 746afe0f60 Add scss devtools 2015-06-11 15:54:13 -04:00
iRouge 1b807bd6f3 Icons to the message-template toolbar 2015-06-11 15:54:13 -04:00
iRouge 6e26040e19 Icon component (zavoloklom.github.io/material-design-iconic-font/index.html) 2015-06-11 15:54:13 -04:00
iRouge 6fde77ac3f Bottombar visibility 2015-06-11 15:54:13 -04:00
iRouge 296e8f09e5 Reformat code (indent) 2015-06-11 15:54:12 -04:00
iRouge 3b43cabc68 Revert [a5ba017bc3] (Regression fix) 2015-06-11 15:54:12 -04:00
Francis Lachapelle cc34d56a0e FIx compilation of UIxMailUserRightsEditor.m 2015-06-11 15:54:11 -04:00
Francis Lachapelle 6080e800d7 Improve API documentation 2015-06-11 15:54:11 -04:00
Francis Lachapelle f2587aa385 JSON-based getter operations for Calendar module 2015-06-11 15:54:11 -04:00
Francis Lachapelle cf8c4c482d Add static method in iCalPerson for partstate 2015-06-11 15:54:11 -04:00
Francis Lachapelle 8986a18dac Review mail user rights editor 2015-06-11 15:54:10 -04:00
Francis Lachapelle 9829cd4027 Minor improvements to Contacts user rights editor 2015-06-11 15:54:10 -04:00
Francis Lachapelle 2e2da46d84 JSON-based Contacts list: don't escape HTML
HTML is now sanitized on the client-side by AngularJS.
2015-06-11 15:54:10 -04:00
Francis Lachapelle 37e91733ca Improve API documentation 2015-06-11 15:54:09 -04:00
Francis Lachapelle c29719f49d Remove newAction from UIx{Appointment,Task}Editor
We now rely on [UIxFolderActions newguidAction]
2015-06-11 15:54:09 -04:00
iRouge a5a2028da7 Contact Form 2015-06-11 15:54:08 -04:00
Francis Lachapelle b8ad85b2e2 Rename ng-templates to match names of .wox files 2015-06-11 15:54:08 -04:00
iRouge 50b45678e3 Regression fix 2015-06-11 15:54:08 -04:00
iRouge bcce9ac76a Report body inline style in Sass
Create bottombar component
2015-06-11 15:54:08 -04:00
Francis Lachapelle 137e8e7290 Add [iCal(Repeatable)EntityObject attribtues]
Those methods are used to get the common attributes of a iCalendar
component (vEvent or vTodo).
2015-06-11 15:54:07 -04:00
Francis Lachapelle a22195beec Add method [iCalTrigger asDictionary]
This method is used to get a JSON representation of an alarm trigger.
2015-06-11 15:54:07 -04:00
Francis Lachapelle 99af190e29 Remove used .ttf font files 2015-06-11 15:54:07 -04:00
Francis Lachapelle 01736318d8 Expose [iCalRecurrenceRule frequencyForValue:]
This method was missing from its header file.
2015-06-11 15:49:38 -04:00
Francis Lachapelle f0108a5069 Add method [iCalByDayMask asRuleArray]
This method is used to get a JSON representation of a BYDAY attribute of
a recurrence rule.
2015-06-11 15:49:37 -04:00
iRouge f4f53ec21e Report body inline style in Sass
Create bottombar component
2015-06-11 15:49:37 -04:00
iRouge 8e76c699dd Restructure Sass files and folders for proper application Sass development 2015-06-11 15:49:37 -04:00
iRouge 256d5e1bac Restructure Sass files and folders for proper application Sass development 2015-06-11 15:49:37 -04:00
iRouge 5217c0ac64 Restructure Sass files and folders for proper application Sass development 2015-06-11 15:49:36 -04:00
Francis Lachapelle a87bbc2de5 Enable toggleCtrl in Webmail 2015-06-11 15:49:33 -04:00
Francis Lachapelle d3f0abf3ef Simplify links to modules in UIxPageFrame.wox 2015-06-11 15:49:32 -04:00
Francis Lachapelle 9b73d4e9a5 Add user identification in sgSettings constant 2015-06-11 15:49:32 -04:00
Francis Lachapelle 4f632174ce Initial integration of ngMaterial in Contacts 2015-06-11 15:49:32 -04:00
Francis Lachapelle 263ff962a1 Update .gitignore 2015-06-11 15:49:32 -04:00
Francis Lachapelle b9414a77ab Move md theming config to ui.js (SOGo.UI) 2015-06-11 15:49:31 -04:00
iRouge f180617a3f Update Angular-material 2015-06-11 15:49:31 -04:00
iRouge 5919580b5d MODULE-TYPO
- Ajustements, message-view
2015-06-11 15:49:31 -04:00
iRouge 25213605bb MODULE-TYPO
- Sass set-up
- md-list
- md-theming (install)
2015-06-11 15:49:31 -04:00
iRouge c7309d7dc8 Views tweaking and todos 2015-06-11 15:49:28 -04:00
iRouge 7e2c60e495 Should had been include with preceeding 2015-06-11 15:49:28 -04:00
iRouge a98320783f Fought with ms-layouts (and they won) 2015-06-11 15:49:27 -04:00
iRouge c196e11fde Correct Bottom-Bar Buttons url 2015-06-11 15:49:27 -04:00
iRouge 414f0fbb26 Rows adjustments 2015-06-11 15:49:27 -04:00
Francis Lachapelle 8286fb68a4 Improve JSON API documentation 2015-06-11 15:49:27 -04:00
Francis Lachapelle 64615ea6fa Update .gitignore 2015-06-11 15:49:26 -04:00
iRouge aa64e86a43 Theme css & fonts 2015-06-11 15:49:26 -04:00
Francis Lachapelle 2cd3920532 Add angular-material as a git module 2015-06-11 15:49:22 -04:00
Benoit Favreault 23bd56a854 Edit gitignore (add .idea) 2015-06-11 15:49:21 -04:00
Francis Lachapelle 307d38c13d Populate bottom navigation bar 2015-06-11 15:49:21 -04:00
Francis Lachapelle f1490e7b92 Initial integration of ngMaterial in Webmail 2015-06-11 15:49:21 -04:00
Francis Lachapelle 8148209fc8 Improve instanciation of Resource in Card model 2015-06-11 15:49:21 -04:00
Francis Lachapelle f3597616ea Minor improvements to SOGo.ContactsUI ng module 2015-06-11 15:49:20 -04:00
Francis Lachapelle 34d7a3bf52 Improve error handling in JavaScript promises 2015-06-11 15:49:20 -04:00
Francis Lachapelle 1a1d51f427 Contacts module: optimize ng-repeat directives 2015-06-11 15:49:20 -04:00
Francis Lachapelle 0d9c78c60b Contacts module: add tooltips to icon buttons 2015-06-11 15:49:20 -04:00
Francis Lachapelle 2644dc9305 Webmail: add possibility to rename a mailbox 2015-06-11 15:49:20 -04:00
Francis Lachapelle c00e09f40b JSONify [UIxMailFolderActions renameFolderAction]
This commit also introduces an initial effort to have a documentation
for the JSON-based Web API following the apiDoc format
(http://apidocjs.com/).
2015-06-11 15:49:19 -04:00
Francis Lachapelle 3526cadc96 Webmail: add "load images" button to mail viewer 2015-06-11 15:49:19 -04:00
Francis Lachapelle c514cb64bc Webmail: Add forward button to messages 2015-06-11 15:49:19 -04:00
Francis Lachapelle 225c998a97 Add CC field to mail editor 2015-06-11 15:49:18 -04:00
Francis Lachapelle 90f07c28f9 JSONify [UIxMailActions forwardAction] 2015-06-11 15:49:18 -04:00
Francis Lachapelle ad012cfd60 Save message to IMAP server before saving plist
By first appending the message to the mailbox, we obtain the IMAP ID and
save it to the local plist. Having the message ID, we can delete it when
saving/appending a new version of the draft to the mailbox.
2015-06-11 15:49:18 -04:00
Francis Lachapelle 5bbdecbec2 Webmail: add reply button 2015-06-11 15:48:15 -04:00
Francis Lachapelle 9065a8038a JSONify [UIxMailActions replyToAll:] 2015-06-11 15:48:14 -04:00
Francis Lachapelle 8c2bcc92b5 Update JavaScript dependencies
Upgrading to AngularJS 1.3.
2015-06-11 15:48:14 -04:00
Francis Lachapelle bc86ff1e04 Fix position of new or renamed addressbook 2015-06-11 15:48:14 -04:00
Francis Lachapelle 4248cbcb16 Webmail: new option to create subfolder 2015-06-11 15:48:14 -04:00
Francis Lachapelle 2d076358d3 Improve Mail module
- JSONinfied mail folder create and delete actions
- restored sgFolderTree directive
- extended folder types with "shared" and "otherUsers"
- added mailbox creation at the account level
2015-06-11 15:48:14 -04:00
Francis Lachapelle 2d026b5ca5 JSONify [UIxMailFolderActions createFolderAction] 2015-06-11 15:48:13 -04:00
Francis Lachapelle b552882011 Fix template reference when creating new card 2015-06-11 15:42:35 -04:00
Francis Lachapelle de273973b4 Add wox templates to Mail and Contacts modules 2015-06-11 15:42:35 -04:00
Francis Lachapelle 3aec2828b4 Improve JavaScript of Mail module
- activated file uploader of mail editor
- renamed method $update to $reload
- automatically mark messages as read
- use ui-sref-active from ui-router instead of ng-class
2015-06-11 15:42:34 -04:00
Francis Lachapelle 533d7110c7 Improve webmail editor
- Fixed handling of saving drafts
- Fixed handling of message type (HTML/plain)
- Added primitive handling of attachments
2015-06-11 15:42:34 -04:00
Francis Lachapelle 32196b56db Fix short formatting of cards for mail editor 2015-06-11 15:42:34 -04:00
Francis Lachapelle 5db79ce218 Mail draft: use JSON in edit action 2015-06-11 15:42:33 -04:00
Francis Lachapelle 9e97c11401 Don't store draft on disk when not required 2015-06-11 15:42:33 -04:00
Francis Lachapelle af09691964 Auto-completion of mail addresses in mail editor 2015-06-11 15:42:33 -04:00
Francis Lachapelle fe41798b19 Fix handling of recipient addresses in mail editor 2015-06-11 15:42:33 -04:00
Francis Lachapelle 09d469927f Add tags input to edit mail recipients 2015-06-11 15:42:32 -04:00
Francis Lachapelle e01e0adac8 Fix mailto links in mail viewer 2015-06-11 15:42:32 -04:00
Francis Lachapelle fb63689573 Initial mail editor 2015-06-11 15:42:32 -04:00
Francis Lachapelle 74177e4d04 Change key for envelope addresses metadata 2015-06-11 15:40:27 -04:00
Francis Lachapelle ac06a4d4ce Fix detection of mailbox type 2015-06-11 15:40:26 -04:00
Francis Lachapelle fd40cb71ac Fix premature nil in JSON dict of UIxMailView.m 2015-06-11 15:40:26 -04:00
Francis Lachapelle df019f515f Webmail: normalize format of addresses in JSON 2015-06-11 15:40:26 -04:00
Francis Lachapelle 5a106e1613 Address formatter returns metadata as a dictionary 2015-06-11 15:40:26 -04:00
Francis Lachapelle 6d899008ca Improve SOGoDraftObject to avoid crash when saving 2015-06-11 15:40:25 -04:00
Francis Lachapelle ee1f56ad27 Improve sgFolderTree directive for mobile 2015-06-11 15:40:25 -04:00
Ludovic Marcotte 61e25184fc Added Delete and Export features for mailboxes. Initial work for the mobile version. 2015-06-11 15:40:24 -04:00
Francis Lachapelle 4e9a187c85 Fix resolution of mailboxes with a special purpose 2015-06-11 15:40:24 -04:00
Francis Lachapelle 60ae5f0eb2 Improve CSS of AddressBook module 2015-06-11 15:40:24 -04:00
Francis Lachapelle 28f7811e86 Improve CSS of AddressBook module 2015-06-11 15:40:24 -04:00
Francis Lachapelle 876b21437f Fix JavaScript of login page of mobile version 2015-06-11 15:40:23 -04:00
Francis Lachapelle 1ca1a8c249 Add mobile version to webmail and improvements 2015-06-11 15:40:23 -04:00
Francis Lachapelle cdd1131699 Add sgFocus directive + factory 2015-06-11 15:40:23 -04:00
Francis Lachapelle 6ce64828e8 AngularJS module SOGo.MailerUI 2015-06-11 15:40:23 -04:00
Francis Lachapelle 1fc15061ed Webmail: Use a relative date in messages list 2015-06-11 15:40:23 -04:00
Francis Lachapelle 0ee725b945 Contacts JS models: improve documentation 2015-06-11 15:40:22 -04:00
Francis Lachapelle 2f17e94fef Initial AngularJS version of Webmail (desktop) 2015-06-11 15:40:22 -04:00
Francis Lachapelle 1c9da902d3 Add JSON payload to webmail "headers" action 2015-06-11 15:40:22 -04:00
Ludovic Marcotte 7e11806bf9 We can now show links to the address book 2015-06-11 15:40:21 -04:00
Francis Lachapelle f2efd3fb49 Add new AngularJS modules
- external module for recursion
- external module for virtual scrolling
- internal module for common UI services
2015-06-11 15:40:21 -04:00
Francis Lachapelle 54444ddf3b AngularJS SOGo.UICommon module 2015-06-11 15:40:21 -04:00
Francis Lachapelle a64a8172be Webmail: include all accounts metadata 2015-06-11 15:40:20 -04:00
Francis Lachapelle 3b4731d6b7 Add virtual scrolling AngularJS module
Integrated virtual scrolling in contacts.
2015-06-11 15:40:20 -04:00
Francis Lachapelle 2cb5aecdcb Add sgFolderTree directive 2015-06-11 15:40:20 -04:00
Francis Lachapelle 277bdd2b1c Mailer: replace HTML view by JSON object 2015-06-11 15:40:20 -04:00
Francis Lachapelle bd9da51e83 Mailer: remove HTML from list of messages in JSON 2015-06-11 15:40:20 -04:00
Francis Lachapelle e5ce053a62 Convert allFoldersMetadata to a tree structure
When parsing the mailboxes list, we now generated a hierarchical
structure of the metadata. Each mailbox (a dictionary) can now have a
'children' key that is an array of mailboxes.
2015-06-11 15:40:20 -04:00
Francis Lachapelle ec56079635 Address Book module: Fix selection of card 2015-06-11 15:38:16 -04:00
Francis Lachapelle 78a349fecd Improve CSS of addressbooks list 2015-06-11 15:38:16 -04:00
Francis Lachapelle 8c7846a1fa Propagate theme in modules relative URLs 2015-06-11 15:38:16 -04:00
Francis Lachapelle 2af7e85f81 Move SOGoContactGCSFolder->save to SOGoGCSFolder 2015-06-11 15:38:16 -04:00
Francis Lachapelle 441834edbf Mobile version: move ng template 'menu'
The 'menu.html' AngularJS template is moved to UIxPageFrame.wox to be
used by all modules.
2015-06-11 15:38:15 -04:00
Ludovic Marcotte 28f9963f87 Adjusted the minimum version of Foundation 2015-06-11 15:38:15 -04:00
Ludovic Marcotte e964496759 Revert "Added required patch for previous commit"
This reverts commit 18a363a07b.
2015-06-11 15:38:15 -04:00
Francis Lachapelle ca14a0d4b3 Improve folder subscription widget 2015-06-11 15:38:14 -04:00
Francis Lachapelle 989cb0bca2 Fix overflow of subscriptions dropdown 2015-06-11 15:38:14 -04:00
Francis Lachapelle 25b0d872c0 Add addressbook subscriptions widget 2015-06-11 15:38:14 -04:00
Francis Lachapelle 4016fdd430 New AngularJS directives
sgDropdownContentToggle, sgUserTypeahead, sgSubscribe
2015-06-11 15:38:13 -04:00
Francis Lachapelle 55f0d5a959 Add verification of parameter for "foldersSearch" 2015-06-11 15:38:13 -04:00
Francis Lachapelle 6395d7cd6a New Resource.prototype.userResource function 2015-06-11 15:38:13 -04:00
Francis Lachapelle 7812e3757d Return properties of folder upon subscribe (JSON) 2015-06-11 15:38:12 -04:00
Francis Lachapelle 93540b4fc6 Improve ACL editor template 2015-06-11 15:38:12 -04:00
Francis Lachapelle c063832d0d Move ACL editor into a separate template
The user rights remain dynamic, based on the object type (addressbook vs
mailbox vs calendar).
2015-06-11 15:38:12 -04:00
Francis Lachapelle 97ce3e6b72 Multiple improvements regarding ACLs 2015-06-11 15:38:12 -04:00
Francis Lachapelle bd39312b19 Fix compilation warnings regarding ACLs
Also change the data structure of the JSON returned by [UIxAclEditor
aclsAction]. The user's displayName has been removed and replace by the
"cn" and "c_email" attributes. This will probably affect the Thunderbird
extensions.
2015-06-11 15:38:12 -04:00
Alexandre Cloutier 22faf5c285 refactor codes and applied comments 2015-06-11 15:38:11 -04:00
Alexandre Cloutier c82143fd2e Refactor acl object and applied comments 2015-06-11 15:38:11 -04:00
Alexandre Cloutier 9b026ebbcd Contacts - export addressBook 2015-06-11 15:38:10 -04:00
Alexandre Cloutier 4e8d3ce900 add dialog window for public and allusers access 2015-06-11 15:38:10 -04:00
Alexandre Cloutier df3ad5445c Modification for ContactsUserRightsEditor 2015-06-11 15:38:10 -04:00
Alexandre Cloutier 9113ca54f7 Created user-modal.js, code refactoring
Conflicts:

	UI/Common/UIxAclEditor.m
	UI/Common/UIxUserRightsEditor.m
	UI/Common/product.plist
	UI/Contacts/UIxContactsUserRightsEditor.m
	UI/Templates/ContactsUI/UIxContactFoldersView.wox
	UI/WebServerResources/js/Common/resource.js
	UI/WebServerResources/js/ContactsUI.js
2015-06-11 15:38:10 -04:00
Alexandre Cloutier f3c26671af GUI for mobile version of AclUsers
Conflicts:

	UI/Common/UIxAclEditor.m
	UI/Common/UIxUserRightsEditor.m
	UI/WebServerResources/js/Common/acl-model.js
2015-06-11 15:38:09 -04:00
Francis Lachapelle e4b1c0d5b9 Fix buttons in card editor 2015-06-11 15:27:09 -04:00
Francis Lachapelle 3364263247 Improve handling of contact lists 2015-06-11 15:27:09 -04:00
Francis Lachapelle 61c48d37e4 Fix creation of new contacts when editing a list 2015-06-11 15:27:09 -04:00
Alexandre Cloutier 5b83b0c7b6 Enable search by fullname and email 2015-06-11 15:27:09 -04:00
Alexandre Cloutier 7e43b13f21 GUI contact list creation 2015-06-11 15:27:08 -04:00
Francis Lachapelle 57791e384b Revert "Creation of aclUsers window"
This reverts commit ee5ef02f50.
2015-06-11 15:27:08 -04:00
Francis Lachapelle 63b20c4ba2 Revert "rebase modification"
This reverts commit 45c5bbd36a.
2015-06-11 15:27:08 -04:00
Francis Lachapelle e11eea7548 Revert "file lost through rebasing"
This reverts commit a952402c39.
2015-06-11 15:27:08 -04:00
Francis Lachapelle f7df4c1fa0 Allow reverting edition of addressbook name w/ESC 2015-06-11 15:27:07 -04:00
Francis Lachapelle 4457997276 AngularJS sgEscape directive for SOGo.UIDesktop 2015-06-11 15:27:07 -04:00
Francis Lachapelle 16628ab104 Fix installation of ionic JS in Gruntfile.js 2015-06-11 15:27:07 -04:00
Alexandre Cloutier 56b765c6a5 delete unused .png 2015-06-11 15:27:06 -04:00
Alexandre Cloutier 3bf1224c9b file lost through rebasing 2015-06-11 15:27:06 -04:00
Alexandre Cloutier edbd661104 rebase modification 2015-06-11 15:27:05 -04:00
Alexandre Cloutier 8ef222ab44 Creation of aclUsers window 2015-06-11 15:27:05 -04:00
Francis Lachapelle 654c8d26b7 Contact editor: fix cancel and reset buttons 2015-06-11 15:27:05 -04:00
Francis Lachapelle 31ea7a5ab5 Improve contact module models
- Fixed reset behavior
- Created an abstract state for the card viewer and editor
- Moved the card instance from the $rootScope.addressbook to the $scope
2015-06-11 15:27:05 -04:00
Francis Lachapelle 342441ecf8 Improve JavaScript coding style
To comitted code now passes the Airbnb pattern using jscs
2015-06-11 15:27:03 -04:00
Francis Lachapelle df37fd8b92 AddressBook JS model: rename $all to $findAll 2015-06-11 15:27:03 -04:00
Francis Lachapelle 32d732caf0 Update GNUmakefile for WebServerResources 2015-06-11 15:27:02 -04:00
Francis Lachapelle 3e2173db7a Improve JavaScript coding style
To comitted code now passes the Airbnb pattern using jscs
2015-06-11 15:27:02 -04:00
Francis Lachapelle 17ee62f4de Improve usage of ui.router with "resolve" 2015-06-11 15:27:02 -04:00
Francis Lachapelle f363257e51 Use angularModule variable in mobile templates 2015-06-11 15:27:02 -04:00
Francis Lachapelle 865bf096f5 Don't add an empty category to a contact 2015-06-11 15:27:01 -04:00
Francis Lachapelle c4802df024 Remove debugging output 2015-06-11 15:27:01 -04:00
Francis Lachapelle 130194a740 Update GNUmakefile for WebServerResources 2015-06-11 15:27:01 -04:00
Francis Lachapelle 21f63c15fc Cleanup of Web server resources 2015-06-11 15:27:00 -04:00
Francis Lachapelle bb9e8c0348 Remove trailing slash from template theme name 2015-06-11 15:26:38 -04:00
Francis Lachapelle 16cd231ce3 New .button.outline CSS style 2015-06-11 15:26:37 -04:00
Francis Lachapelle 20497e49e3 Add creation & deletion of addressbooks 2015-06-11 15:26:37 -04:00
Francis Lachapelle b97bf2b25f JSON'ed [UIxParentFolderActions createFolder] 2015-06-11 15:26:37 -04:00
Francis Lachapelle 4f7a5d6ef5 Rename ng module SOGo.RootPage to SOGo.MainUI 2015-06-11 15:26:37 -04:00
Francis Lachapelle f321abc63a Desktop list editor, mobile contact editor 2015-06-11 15:26:36 -04:00
Francis Lachapelle 4b0ef6086a Cleanup contact and list viewers 2015-06-11 15:26:36 -04:00
Francis Lachapelle b57a8163fe Add link to switch to mobile version 2015-06-11 15:26:36 -04:00
Francis Lachapelle 86a6f5c67b Add Angular module assignation in page frame 2015-06-11 15:26:35 -04:00
Francis Lachapelle e40b42c213 Move setAttributes from NGVCard to UIx*Editors 2015-06-11 15:26:35 -04:00
Francis Lachapelle 2f6bc1c4ff Update .gitignore 2015-06-11 15:25:31 -04:00
Francis Lachapelle 958f0b4958 Contacts: Add possibility to add/delete objects 2015-06-11 15:25:31 -04:00
Francis Lachapelle 0c720bb902 New ng-module for common desktop widgets 2015-06-11 15:25:30 -04:00
Francis Lachapelle 34b3f2ac0c Improve build scripts of Web frontend 2015-06-11 15:25:30 -04:00
Francis Lachapelle ef4de28ed4 ContactView: lowercase the card tag 2015-06-11 15:25:30 -04:00
Francis Lachapelle c98d580b29 Return contact UID when saving contact 2015-06-11 15:25:30 -04:00
Francis Lachapelle a2460f9368 Add "newguid" action accessible from any folder 2015-06-11 15:25:29 -04:00
Francis Lachapelle c0eac04437 Adapt SOGoContactGCSFolder contact representation
To match [UIxContactViewer dataAction].
2015-06-11 15:25:29 -04:00
Francis Lachapelle 7f9be26541 Improve localization func to support placeholders 2015-06-11 15:25:28 -04:00
Francis Lachapelle c8ea3da5bc Improve detection of theme-specific JavaScript 2015-06-11 15:25:28 -04:00
Francis Lachapelle a70287870b Improve build scripts of Web frontend 2015-06-11 15:25:28 -04:00
Francis Lachapelle e4ec5313db Improve grunt tasks to copy fonts files 2015-06-11 15:25:27 -04:00
Francis Lachapelle a07d918fbf Add category to CardElement
New method to return a JSON representation of the element.
2015-06-11 15:25:27 -04:00
Francis Lachapelle 8da98367db Fix path to ionic scss files 2015-06-11 15:25:26 -04:00
Francis Lachapelle af5489bf57 Fix redirection URLs in JavaScript 2015-06-11 15:25:26 -04:00
Francis Lachapelle 54103124e8 Restore/move missing images 2015-06-11 15:25:25 -04:00
Francis Lachapelle 459c040d8a Initial mobile theme using ionic 2015-06-11 15:25:25 -04:00
Francis Lachapelle f248f81583 Improve template of Contacts module 2015-06-11 15:25:25 -04:00
Francis Lachapelle a6d8dcc5b6 Common JavaScript utlity functions 2015-06-11 15:25:25 -04:00
Francis Lachapelle b4d6667f88 Remove duplicated method 2015-06-11 15:25:24 -04:00
Francis Lachapelle 77b80e27c6 Add support for themes 2015-06-11 15:25:24 -04:00
Francis Lachapelle 16d04e998f Improve Sass of SOGoRootPage & Contacts modules 2015-06-11 15:25:24 -04:00
Francis Lachapelle d52d7582ca Improve build scripts of Web frontend 2015-06-11 15:25:23 -04:00
Francis Lachapelle e817a3b3d0 Improve JavaScript of SOGoRootPage module 2015-06-11 15:25:23 -04:00
Francis Lachapelle 2d6f8e4ea6 Improve JavaScript for Contacts module 2015-06-11 15:25:23 -04:00
Francis Lachapelle fbe412db08 Allow js/img/css subfolders in WebServerResources 2015-06-11 15:25:22 -04:00
Francis Lachapelle 24f01e72c2 JSON-based operations for root page 2015-06-11 15:25:22 -04:00
Francis Lachapelle 6970acfaa4 AngularJS-based templates 2015-06-11 15:25:22 -04:00
Francis Lachapelle 0a49031b01 JSON-based operations on contacts 2015-06-11 15:23:27 -04:00
Francis Lachapelle 29e147ee86 Initial Sass and JavaScript files 2015-06-11 15:19:22 -04:00
Francis Lachapelle c21ec86365 Icons font 2015-06-11 15:19:21 -04:00
Francis Lachapelle 825c45f872 Initial JavaScript models for addressbooks module 2015-06-11 15:19:21 -04:00
Francis Lachapelle 3ad4352ffe Initial cleanup of Web server resources 2015-06-11 15:19:21 -04:00
Alexandre Cloutier a45dc96885 applied comments 2015-06-11 15:17:26 -04:00
Alexandre Cloutier b041ec6e65 activeTasks updates dynamically 2015-06-11 15:15:39 -04:00
Alexandre Cloutier 257d731e04 multiColumns print view + bugFixes 2015-06-11 15:15:39 -04:00
Alexandre Cloutier 720a946d39 The multiColumns view 2015-06-11 15:15:39 -04:00
Pablo Carranza 2d5f2d88fa Revert "Started Ubuntu w/PostgreSQL tutorial"
This reverts commit 51d2372976.
2013-11-05 22:32:35 -06:00
Pablo Carranza eb5ca2cba6 Revert "Update ubuntu_postgresql.md"
This reverts commit 92d68de332.
2013-11-05 22:31:54 -06:00
Pablo Carranza 54cd55ebef Update README.md 2013-10-19 13:15:13 -05:00
Pablo Carranza 5f4ab6eaaf Update README.md 2013-10-19 13:11:36 -05:00
Pablo Carranza 1d8e6b6295 Update README.md 2013-10-19 13:03:40 -05:00
Pablo Carranza aa791b2571 Create README.md 2013-10-19 12:42:31 -05:00
Pablo Carranza 92d68de332 Update ubuntu_postgresql.md 2013-10-19 12:25:19 -05:00
Pablo Carranza 51d2372976 Started Ubuntu w/PostgreSQL tutorial 2013-10-19 12:17:39 -05:00
1583 changed files with 43198 additions and 97801 deletions

No files matched your search

+27 -12
View File
@@ -1,18 +1,33 @@
config.make
tags
*._*
*/obj/
*._*
*/*/obj/
*/*/*/obj/
*/*/*.SOGo/
*.css
*.pyc
*.sax
*.wox/
*.swp
*.wox/
*/*/*.SOGo/
*/*/*/obj/
*/*/obj/
*/obj/
.scss-lint-config.yml_
Documentation/*.docbook
Documentation/*.pdf
SoObjects/SOGo/SOGo.framework/
SoObjects/SOGo/derived_src/
Tests/*/config.py
*.pyc
._*
Documentation/*.docbook
Documentation/*.pdf
UI/WebServerResources/.bowerrc
UI/WebServerResources/.sass-cache/
UI/WebServerResources/bower_components/
UI/WebServerResources/css/
UI/WebServerResources/css/styles.css
UI/WebServerResources/css/styles.css.map
UI/WebServerResources/js/Common.js*
UI/WebServerResources/js/Contacts.js*
UI/WebServerResources/js/Mailer.js*
UI/WebServerResources/js/Preferences.js*
UI/WebServerResources/js/Scheduler.js*
UI/WebServerResources/js/vendor/
UI/WebServerResources/node_modules/
UI/WebServerResources/scss/.sass-cache/
config.make
doc
tags
+3
View File
@@ -0,0 +1,3 @@
[submodule "UI/WebServerResources/angular-material"]
path = UI/WebServerResources/angular-material
url = https://github.com/angular/material
-44
View File
@@ -15,17 +15,13 @@ trans.es_ES = UI/MailerUI/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/MailerUI/Basque.lproj/Localizable.strings
trans.fi = UI/MailerUI/Finnish.lproj/Localizable.strings
trans.fr = UI/MailerUI/French.lproj/Localizable.strings
trans.hr_HR = UI/MailerUI/Croatian.lproj/Localizable.strings
trans.hu = UI/MailerUI/Hungarian.lproj/Localizable.strings
trans.is = UI/MailerUI/Icelandic.lproj/Localizable.strings
trans.it = UI/MailerUI/Italian.lproj/Localizable.strings
trans.lt = UI/MailerUI/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/MailerUI/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/MailerUI/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/MailerUI/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/MailerUI/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/MailerUI/Polish.lproj/Localizable.strings
trans.pt = UI/MailerUI/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/MailerUI/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/MailerUI/Russian.lproj/Localizable.strings
trans.sk = UI/MailerUI/Slovak.lproj/Localizable.strings
@@ -48,17 +44,13 @@ trans.es_ES = UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/PreferencesUI/Basque.lproj/Localizable.strings
trans.fi = UI/PreferencesUI/Finnish.lproj/Localizable.strings
trans.fr = UI/PreferencesUI/French.lproj/Localizable.strings
trans.hr_HR = UI/PreferencesUI/Croatian.lproj/Localizable.strings
trans.hu = UI/PreferencesUI/Hungarian.lproj/Localizable.strings
trans.is = UI/PreferencesUI/Icelandic.lproj/Localizable.strings
trans.it = UI/PreferencesUI/Italian.lproj/Localizable.strings
trans.lt = UI/PreferencesUI/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/PreferencesUI/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/PreferencesUI/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/PreferencesUI/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/PreferencesUI/Polish.lproj/Localizable.strings
trans.pt = UI/PreferencesUI/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/PreferencesUI/Russian.lproj/Localizable.strings
trans.sk = UI/PreferencesUI/Slovak.lproj/Localizable.strings
@@ -81,17 +73,13 @@ trans.es_ES = UI/Scheduler/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/Scheduler/Basque.lproj/Localizable.strings
trans.fi = UI/Scheduler/Finnish.lproj/Localizable.strings
trans.fr = UI/Scheduler/French.lproj/Localizable.strings
trans.hr_HR = UI/Scheduler/Croatian.lproj/Localizable.strings
trans.hu = UI/Scheduler/Hungarian.lproj/Localizable.strings
trans.is = UI/Scheduler/Icelandic.lproj/Localizable.strings
trans.it = UI/Scheduler/Italian.lproj/Localizable.strings
trans.lt = UI/Scheduler/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/Scheduler/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/Scheduler/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/Scheduler/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/Scheduler/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/Scheduler/Polish.lproj/Localizable.strings
trans.pt = UI/Scheduler/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/Scheduler/Russian.lproj/Localizable.strings
trans.sk = UI/Scheduler/Slovak.lproj/Localizable.strings
@@ -114,17 +102,13 @@ trans.es_ES = UI/Contacts/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/Contacts/Basque.lproj/Localizable.strings
trans.fi = UI/Contacts/Finnish.lproj/Localizable.strings
trans.fr = UI/Contacts/French.lproj/Localizable.strings
trans.hr_HR = UI/Contacts/Croatian.lproj/Localizable.strings
trans.hu = UI/Contacts/Hungarian.lproj/Localizable.strings
trans.is = UI/Contacts/Icelandic.lproj/Localizable.strings
trans.it = UI/Contacts/Italian.lproj/Localizable.strings
trans.lt = UI/Contacts/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/Contacts/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/Contacts/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/Contacts/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/Contacts/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/Contacts/Polish.lproj/Localizable.strings
trans.pt = UI/Contacts/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/Contacts/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/Contacts/Russian.lproj/Localizable.strings
trans.sk = UI/Contacts/Slovak.lproj/Localizable.strings
@@ -147,17 +131,13 @@ trans.es_ES = UI/MainUI/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/MainUI/Basque.lproj/Localizable.strings
trans.fi = UI/MainUI/Finnish.lproj/Localizable.strings
trans.fr = UI/MainUI/French.lproj/Localizable.strings
trans.hr_HR = UI/MainUI/Croatian.lproj/Localizable.strings
trans.hu = UI/MainUI/Hungarian.lproj/Localizable.strings
trans.is = UI/MainUI/Icelandic.lproj/Localizable.strings
trans.it = UI/MainUI/Italian.lproj/Localizable.strings
trans.lt = UI/MainUI/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/MainUI/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/MainUI/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/MainUI/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/MainUI/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/MainUI/Polish.lproj/Localizable.strings
trans.pt = UI/MainUI/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/MainUI/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/MainUI/Russian.lproj/Localizable.strings
trans.sk = UI/MainUI/Slovak.lproj/Localizable.strings
@@ -180,17 +160,13 @@ trans.es_ES = UI/Common/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/Common/Basque.lproj/Localizable.strings
trans.fi = UI/Common/Finnish.lproj/Localizable.strings
trans.fr = UI/Common/French.lproj/Localizable.strings
trans.hr_HR = UI/Common/Croatian.lproj/Localizable.strings
trans.hu = UI/Common/Hungarian.lproj/Localizable.strings
trans.is = UI/Common/Icelandic.lproj/Localizable.strings
trans.it = UI/Common/Italian.lproj/Localizable.strings
trans.lt = UI/Common/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/Common/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/Common/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/Common/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/Common/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/Common/Polish.lproj/Localizable.strings
trans.pt = UI/Common/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/Common/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/Common/Russian.lproj/Localizable.strings
trans.sk = UI/Common/Slovak.lproj/Localizable.strings
@@ -213,17 +189,13 @@ trans.es_ES = UI/AdministrationUI/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/AdministrationUI/Basque.lproj/Localizable.strings
trans.fi = UI/AdministrationUI/Finnish.lproj/Localizable.strings
trans.fr = UI/AdministrationUI/French.lproj/Localizable.strings
trans.hr_HR = UI/AdministrationUI/Croatian.lproj/Localizable.strings
trans.hu = UI/AdministrationUI/Hungarian.lproj/Localizable.strings
trans.is = UI/AdministrationUI/Icelandic.lproj/Localizable.strings
trans.it = UI/AdministrationUI/Italian.lproj/Localizable.strings
trans.lt = UI/AdministrationUI/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/AdministrationUI/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/AdministrationUI/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/AdministrationUI/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/AdministrationUI/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/AdministrationUI/Polish.lproj/Localizable.strings
trans.pt = UI/AdministrationUI/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/AdministrationUI/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/AdministrationUI/Russian.lproj/Localizable.strings
trans.sk = UI/AdministrationUI/Slovak.lproj/Localizable.strings
@@ -246,17 +218,13 @@ trans.es_ES = SoObjects/Appointments/SpanishSpain.lproj/Localizable.strings
trans.eu = SoObjects/Appointments/Basque.lproj/Localizable.strings
trans.fi = SoObjects/Appointments/Finnish.lproj/Localizable.strings
trans.fr = SoObjects/Appointments/French.lproj/Localizable.strings
trans.hr_HR = SoObjects/Appointments/Croatian.lproj/Localizable.strings
trans.hu = SoObjects/Appointments/Hungarian.lproj/Localizable.strings
trans.is = SoObjects/Appointments/Icelandic.lproj/Localizable.strings
trans.it = SoObjects/Appointments/Italian.lproj/Localizable.strings
trans.lt = SoObjects/Appointments/Lithuanian.lproj/Localizable.strings
trans.mk_MK = SoObjects/Appointments/Macedonian.lproj/Localizable.strings
trans.nb_NO = SoObjects/Appointments/NorwegianBokmal.lproj/Localizable.strings
trans.nl = SoObjects/Appointments/Dutch.lproj/Localizable.strings
trans.nn_NO = SoObjects/Appointments/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = SoObjects/Appointments/Polish.lproj/Localizable.strings
trans.pt = SoObjects/Appointments/Portuguese.lproj/Localizable.strings
trans.pt_BR = SoObjects/Appointments/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = SoObjects/Appointments/Russian.lproj/Localizable.strings
trans.sk = SoObjects/Appointments/Slovak.lproj/Localizable.strings
@@ -279,17 +247,13 @@ trans.es_ES = SoObjects/Contacts/SpanishSpain.lproj/Localizable.strings
trans.eu = SoObjects/Contacts/Basque.lproj/Localizable.strings
trans.fi = SoObjects/Contacts/Finnish.lproj/Localizable.strings
trans.fr = SoObjects/Contacts/French.lproj/Localizable.strings
trans.hr_HR = SoObjects/Contacts/Croatian.lproj/Localizable.strings
trans.hu = SoObjects/Contacts/Hungarian.lproj/Localizable.strings
trans.is = SoObjects/Contacts/Icelandic.lproj/Localizable.strings
trans.it = SoObjects/Contacts/Italian.lproj/Localizable.strings
trans.lt = SoObjects/Contacts/Lithuanian.lproj/Localizable.strings
trans.mk_MK = SoObjects/Contacts/Macedonian.lproj/Localizable.strings
trans.nb_NO = SoObjects/Contacts/NorwegianBokmal.lproj/Localizable.strings
trans.nl = SoObjects/Contacts/Dutch.lproj/Localizable.strings
trans.nn_NO = SoObjects/Contacts/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = SoObjects/Contacts/Polish.lproj/Localizable.strings
trans.pt = SoObjects/Contacts/Portuguese.lproj/Localizable.strings
trans.pt_BR = SoObjects/Contacts/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = SoObjects/Contacts/Russian.lproj/Localizable.strings
trans.sk = SoObjects/Contacts/Slovak.lproj/Localizable.strings
@@ -312,17 +276,13 @@ trans.es_ES = SoObjects/Mailer/SpanishSpain.lproj/Localizable.strings
trans.eu = SoObjects/Mailer/Basque.lproj/Localizable.strings
trans.fi = SoObjects/Mailer/Finnish.lproj/Localizable.strings
trans.fr = SoObjects/Mailer/French.lproj/Localizable.strings
trans.hr_HR = SoObjects/Mailer/Croatian.lproj/Localizable.strings
trans.hu = SoObjects/Mailer/Hungarian.lproj/Localizable.strings
trans.is = SoObjects/Mailer/Icelandic.lproj/Localizable.strings
trans.it = SoObjects/Mailer/Italian.lproj/Localizable.strings
trans.lt = SoObjects/Mailer/Lithuanian.lproj/Localizable.strings
trans.mk_MK = SoObjects/Mailer/Macedonian.lproj/Localizable.strings
trans.nb_NO = SoObjects/Mailer/NorwegianBokmal.lproj/Localizable.strings
trans.nl = SoObjects/Mailer/Dutch.lproj/Localizable.strings
trans.nn_NO = SoObjects/Mailer/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = SoObjects/Mailer/Polish.lproj/Localizable.strings
trans.pt = SoObjects/Mailer/Portuguese.lproj/Localizable.strings
trans.pt_BR = SoObjects/Mailer/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = SoObjects/Mailer/Russian.lproj/Localizable.strings
trans.sk = SoObjects/Mailer/Slovak.lproj/Localizable.strings
@@ -345,17 +305,13 @@ trans.es_ES = UI/MailPartViewers/SpanishSpain.lproj/Localizable.strings
trans.eu = UI/MailPartViewers/Basque.lproj/Localizable.strings
trans.fi = UI/MailPartViewers/Finnish.lproj/Localizable.strings
trans.fr = UI/MailPartViewers/French.lproj/Localizable.strings
trans.hr_HR = UI/MailPartViewers/Croatian.lproj/Localizable.strings
trans.hu = UI/MailPartViewers/Hungarian.lproj/Localizable.strings
trans.is = UI/MailPartViewers/Icelandic.lproj/Localizable.strings
trans.it = UI/MailPartViewers/Italian.lproj/Localizable.strings
trans.lt = UI/MailPartViewers/Lithuanian.lproj/Localizable.strings
trans.mk_MK = UI/MailPartViewers/Macedonian.lproj/Localizable.strings
trans.nb_NO = UI/MailPartViewers/NorwegianBokmal.lproj/Localizable.strings
trans.nl = UI/MailPartViewers/Dutch.lproj/Localizable.strings
trans.nn_NO = UI/MailPartViewers/NorwegianNynorsk.lproj/Localizable.strings
trans.pl = UI/MailPartViewers/Polish.lproj/Localizable.strings
trans.pt = UI/MailPartViewers/Portuguese.lproj/Localizable.strings
trans.pt_BR = UI/MailPartViewers/BrazilianPortuguese.lproj/Localizable.strings
trans.ru = UI/MailPartViewers/Russian.lproj/Localizable.strings
trans.sk = UI/MailPartViewers/Slovak.lproj/Localizable.strings
+1 -4
View File
@@ -1,4 +1 @@
ifeq ($(HAS_LIBRARY_ssl),yes)
ADDITIONAL_CPPFLAGS += -DHAVE_OPENSSL=1
BUNDLE_LIBS += -lcrypto
endif
# compilation settings
+1 -1
View File
@@ -101,7 +101,7 @@ static NSArray *asElementArray = nil;
int i, count;
if (!asElementArray)
asElementArray = [[NSArray alloc] initWithObjects: @"Attendee", @"Category", @"Exception", nil];
asElementArray = [[NSArray alloc] initWithObjects: @"Attendee", @"Category", nil];
data = [NSMutableDictionary dictionary];
+50 -196
View File
@@ -46,49 +46,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "NSDate+ActiveSync.h"
#include "NSString+ActiveSync.h"
#import <NGObjWeb/WOContext+SoObjects.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserDefaults.h>
@implementation NGVCard (ActiveSync)
//
// This function is called for each elements which can be ghosted according to specs.
// https://msdn.microsoft.com/en-us/library/gg650908%28v=exchg.80%29.aspx
//
- (BOOL) _isGhosted: (NSString *) element
inContext: (WOContext *) context
{
NSArray *supportedElements;
supportedElements = [context objectForKey: @"SupportedElements"];
// If the client does not include a Supported element in the initial Sync command request for
// a folder, then all of the elements that can be ghosted are considered not ghosted.
if (!supportedElements)
return NO;
// If the client includes an empty Supported element in the initial Sync command request for
// a folder, then all elements that can be ghosted are considered ghosted.
if (![supportedElements count])
return YES;
// If the client includes a Supported element that contains child elements in the initial
// Sync command request for a folder, then each child element of that Supported element is
// considered not ghosted. All elements that can be ghosted that are not included as child
// elements of the Supported element are considered ghosted.
if (!([supportedElements indexOfObject: element] == NSNotFound))
return YES;
return NO;
}
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
{
NSArray *emails, *addresses, *categories, *elements;
CardElement *n, *homeAdr, *workAdr;
NSMutableString *s, *a;
NSMutableString *s;
NSString *url;
id o;
@@ -99,7 +63,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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]];
@@ -182,22 +146,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if ([addresses count])
{
homeAdr = [addresses objectAtIndex: 0];
a = [NSMutableString string];
if ((o = [homeAdr flattenedValueAtIndex: 2 forKey: @""]))
[a appendString: o];
if ((o = [homeAdr flattenedValueAtIndex: 1 forKey: @""]) && [o length])
[a appendFormat: @"\n%@", o];
[s appendFormat: @"<HomeStreet xmlns=\"Contacts:\">%@</HomeStreet>", [o activeSyncRepresentationInContext: context]];
[s appendFormat: @"<HomeStreet xmlns=\"Contacts:\">%@</HomeStreet>", [a 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]];
@@ -213,15 +171,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if ([addresses count])
{
workAdr = [addresses objectAtIndex: 0];
a = [NSMutableString string];
if ((o = [workAdr flattenedValueAtIndex: 2 forKey: @""]))
[a appendString: o];
if ((o = [workAdr flattenedValueAtIndex: 1 forKey: @""]) && [o length])
[a appendFormat: @"\n%@", o];
[s appendFormat: @"<BusinessStreet xmlns=\"Contacts:\">%@</BusinessStreet>", [a activeSyncRepresentationInContext: context]];
[s appendFormat: @"<BusinessStreet xmlns=\"Contacts:\">%@</BusinessStreet>", [o activeSyncRepresentationInContext: context]];
if ((o = [workAdr flattenedValueAtIndex: 3 forKey: @""]))
[s appendFormat: @"<BusinessCity xmlns=\"Contacts:\">%@</BusinessCity>", [o activeSyncRepresentationInContext: context]];
@@ -238,16 +190,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Other, less important fields
if ((o = [self birthday]))
{
NSTimeZone *userTimeZone;
userTimeZone = [[[context activeUser] userDefaults] timeZone];
[s appendFormat: @"<Birthday xmlns=\"Contacts:\">%@</Birthday>",
[[o dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: ([userTimeZone secondsFromGMTForDate: o])*-1]
activeSyncRepresentationInContext: context]];
}
[s appendFormat: @"<Birthday xmlns=\"Contacts:\">%@</Birthday>", [o activeSyncRepresentationInContext: context]];
if ((o = [self note]))
{
@@ -274,7 +217,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
inContext: (WOContext *) context
{
CardElement *element;
NSMutableArray *addressLines;
id o;
// Contact's note
@@ -284,8 +226,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Categories
if ((o = [theValues objectForKey: @"Categories"]) && [o length])
[self setCategories: o];
else
[[self children] removeObjectsInArray: [self childrenWithTag: @"Categories"]];
// Birthday
if ((o = [theValues objectForKey: @"Birthday"]))
@@ -293,11 +233,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
o = [o calendarDate];
[self setBday: [o descriptionWithCalendarFormat: @"%Y-%m-%d" timeZone: nil locale: nil]];
}
else if (![self _isGhosted: @"Birthday" inContext: context])
{
[self setBday: @""];
}
//
// Business address information
@@ -309,48 +244,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// BusinessCountry
//
element = [self elementWithTag: @"adr" ofType: @"work"];
if ((o = [theValues objectForKey: @"BusinessStreet"]) || ![self _isGhosted: @"BusinessStreet" inContext: context])
{
addressLines = [NSMutableArray arrayWithArray: [o componentsSeparatedByString: @"\n"]];
[element setSingleValue: @""
atIndex: 1 forKey: @""];
[element setSingleValue: [addressLines count] ? [addressLines objectAtIndex: 0] : @""
atIndex: 2 forKey: @""];
// Extended address line. If there are more than 2 address lines we add them to the extended address line.
if ([addressLines count] > 1)
{
[addressLines removeObjectAtIndex: 0];
[element setSingleValue: [addressLines componentsJoinedByString: @" "]
atIndex: 1 forKey: @""];
}
}
if ((o = [theValues objectForKey: @"BusinessCity"]) || ![self _isGhosted: @"BusinessCity" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"BusinessCity"]
atIndex: 3 forKey: @""];
}
if ((o = [theValues objectForKey: @"BusinessState"]) || ![self _isGhosted: @"BusinessState" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"BusinessState"]
atIndex: 4 forKey: @""];
}
if ((o = [theValues objectForKey: @"BusinessPostalCode"]) || ![self _isGhosted: @"BusinessPostalCode" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"BusinessPostalCode"]
atIndex: 5 forKey: @""];
}
if ((o = [theValues objectForKey: @"BusinessCountry"]) || ![self _isGhosted: @"BusinessCountry" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"BusinessCountry"]
atIndex: 6 forKey: @""];
}
[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
@@ -362,69 +267,35 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// HomeCountry
//
element = [self elementWithTag: @"adr" ofType: @"home"];
if ((o = [theValues objectForKey: @"HomeStreet"]) || ![self _isGhosted: @"HomeStreet" inContext: context])
{
addressLines = [NSMutableArray arrayWithArray: [o componentsSeparatedByString: @"\n"]];
[element setSingleValue: @""
atIndex: 1 forKey: @""];
[element setSingleValue: [addressLines count] ? [addressLines objectAtIndex: 0] : @""
atIndex: 2 forKey: @""];
// Extended address line. If there are more then 2 address lines we add them to the extended address line.
if ([addressLines count] > 1)
{
[addressLines removeObjectAtIndex: 0];
[element setSingleValue: [addressLines componentsJoinedByString: @" "]
atIndex: 1 forKey: @""];
}
}
if ((o = [theValues objectForKey: @"HomeCity"]) || ![self _isGhosted: @"HomeCity" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"HomeCity"]
atIndex: 3 forKey: @""];
}
if ((o = [theValues objectForKey: @"HomeState"]) || ![self _isGhosted: @"HomeState" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"HomeState"]
atIndex: 4 forKey: @""];
}
if ((o = [theValues objectForKey: @"HomePostalCode"]) || ![self _isGhosted: @"HomePostalCode" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"HomePostalCode"]
atIndex: 5 forKey: @""];
}
if ((o = [theValues objectForKey: @"HomeCountry"]) || ![self _isGhosted: @"HomeCountry" inContext: context])
{
[element setSingleValue: [theValues objectForKey: @"HomeCountry"]
atIndex: 6 forKey: @""];
}
[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];
else if (![self _isGhosted: @"CompanyName" inContext: context])
[self setOrg: @"" units: nil];
// Department
if ((o = [theValues objectForKey: @"Department"]))
[self setOrg: nil units: [NSArray arrayWithObjects:o,nil]];
else if (![self _isGhosted: @"Department" inContext: context])
[self setOrg: nil units: [NSArray arrayWithObjects:@"",nil]];
// Email addresses
if ((o = [theValues objectForKey: @"Email1Address"]) || ![self _isGhosted: @"Email1Address" inContext: context])
if ((o = [theValues objectForKey: @"Email1Address"]))
{
element = [self elementWithTag: @"email" ofType: @"work"];
[element setSingleValue: [o pureEMailAddress] forKey: @""];
}
if ((o = [theValues objectForKey: @"Email2Address"]) || ![self _isGhosted: @"Email2Address" inContext: context])
if ((o = [theValues objectForKey: @"Email2Address"]))
{
element = [self elementWithTag: @"email" ofType: @"home"];
[element setSingleValue: [o pureEMailAddress] forKey: @""];
@@ -432,7 +303,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// SOGo currently only supports 2 email addresses ... but AS clients might send 3
// FIXME: revise this when the GUI revamp is done in SOGo
if ((o = [theValues objectForKey: @"Email3Address"]) || ![self _isGhosted: @"Email3Address" inContext: context])
if ((o = [theValues objectForKey: @"Email3Address"]))
{
element = [self elementWithTag: @"email" ofType: @"three"];
[element setSingleValue: [o pureEMailAddress] forKey: @""];
@@ -442,62 +313,45 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// MiddleName
// Suffix (II)
// Title (Mr.)
if ((o = [theValues objectForKey: @"FileAs"]) || ![self _isGhosted: @"FileAs" inContext: context])
[self setFn: [theValues objectForKey: @"FileAs"]];
[self setFn: [theValues objectForKey: @"FileAs"]];
[self setNWithFamily: [theValues objectForKey: @"LastName"]
given: [theValues objectForKey: @"FirstName"]
additional: nil prefixes: nil suffixes: nil];
// IM information
if ((o = [theValues objectForKey: @"IMAddress"]) || ![self _isGhosted: @"IMAddress" inContext: context])
[[self uniqueChildWithTag: @"x-aim"]
setSingleValue: [theValues objectForKey: @"IMAddress"]
forKey: @""];
[[self uniqueChildWithTag: @"x-aim"]
setSingleValue: [theValues objectForKey: @"IMAddress"]
forKey: @""];
//
// Phone numbrrs
//
if ((o = [theValues objectForKey: @"BusinessPhoneNumber"]) || ![self _isGhosted: @"BusinessPhoneNumber" inContext: context])
{
element = [self elementWithTag: @"tel" ofType: @"work"];
[element setSingleValue: [theValues objectForKey: @"BusinessPhoneNumber"] forKey: @""];
}
element = [self elementWithTag: @"tel" ofType: @"work"];
[element setSingleValue: [theValues objectForKey: @"BusinessPhoneNumber"] forKey: @""];
if ((o = [theValues objectForKey: @"HomePhoneNumber"]) || ![self _isGhosted: @"HomePhoneNumber" inContext: context])
{
element = [self elementWithTag: @"tel" ofType: @"home"];
[element setSingleValue: [theValues objectForKey: @"HomePhoneNumber"] forKey: @""];
}
element = [self elementWithTag: @"tel" ofType: @"home"];
[element setSingleValue: [theValues objectForKey: @"HomePhoneNumber"] forKey: @""];
if ((o = [theValues objectForKey: @"MobilePhoneNumber"]) || ![self _isGhosted: @"MobilePhoneNumber" inContext: context])
{
element = [self elementWithTag: @"tel" ofType: @"cell"];
[element setSingleValue: [theValues objectForKey: @"MobilePhoneNumber"] forKey: @""];
}
element = [self elementWithTag: @"tel" ofType: @"cell"];
[element setSingleValue: [theValues objectForKey: @"MobilePhoneNumber"] forKey: @""];
if ((o = [theValues objectForKey: @"BusinessFaxNumber"]) || ![self _isGhosted: @"BusinessFaxNumber" inContext: context])
{
element = [self elementWithTag: @"tel" ofType: @"fax"];
[element setSingleValue: [theValues objectForKey: @"BusinessFaxNumber"] forKey: @""];
}
element = [self elementWithTag: @"tel" ofType: @"fax"];
[element setSingleValue: [theValues objectForKey: @"BusinessFaxNumber"] forKey: @""];
if ((o = [theValues objectForKey: @"PagerNumber"]) || ![self _isGhosted: @"PagerNumber" inContext: context])
{
element = [self elementWithTag: @"tel" ofType: @"pager"];
[element setSingleValue: [theValues objectForKey: @"PagerNumber"] forKey: @""];
}
element = [self elementWithTag: @"tel" ofType: @"pager"];
[element setSingleValue: [theValues objectForKey: @"PagerNumber"] forKey: @""];
// Job's title
if ((o = [theValues objectForKey: @"JobTitle"]) || ![self _isGhosted: @"JobTitle" inContext: context])
if ((o = [theValues objectForKey: @"JobTitle"]))
[self setTitle: o];
// WebPage (work)
if ((o = [theValues objectForKey: @"WebPage"]) || ![self _isGhosted: @"WebPage" inContext: context])
if ((o = [theValues objectForKey: @"WebPage"]))
[[self elementWithTag: @"url" ofType: @"work"]
setSingleValue: o forKey: @""];
if ((o = [theValues objectForKey: @"NickName"]) || ![self _isGhosted: @"NickName" inContext: context])
if ((o = [theValues objectForKey: @"NickName"]))
[self setNickname: o];
if ((o = [theValues objectForKey: @"Picture"]))
+1 -1
View File
@@ -75,7 +75,7 @@ static NSArray *easCommandParameters = nil;
escapeCount++;
break;
default:
if (chars[i] < 0x20 || chars[i] > 127)
if (chars[i] > 127)
escapeCount++;
break;
}
File diff suppressed because it is too large. Load diff
+1 -12
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2014-2015, Inverse inc.
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -31,26 +31,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SOGoActiveSyncConstants.h"
@class NSCalendarDate;
@class NSException;
@class NSMutableDictionary;
@class NSURL;
@class NSNumber;
static volatile BOOL shouldTerminate = NO;
@interface SOGoActiveSyncDispatcher : NSObject
{
NSURL *folderTableURL;
NSDictionary *imapFolderGUIDS;
id context;
NSNumber *syncRequest;
BOOL debugOn;
}
- (NSMutableDictionary *) globalMetadataForDevice;
- (id) collectionFromId: (NSString *) theCollectionId
type: (SOGoMicrosoftActiveSyncFolderType) theFolderType;
+110 -477
View File
@@ -30,12 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SOGoActiveSyncDispatcher.h"
#import <Foundation/NSArray.h>
#import <Foundation/NSData.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSCalendarDate.h>
#if GNUSTEP_BASE_MINOR_VERSION >= 21
#import <Foundation/NSLocale.h>
#endif
#import <Foundation/NSProcessInfo.h>
#import <Foundation/NSTimeZone.h>
#import <Foundation/NSURL.h>
@@ -52,7 +48,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <NGObjWeb/WODirectAction.h>
#import <NGObjWeb/WORequest.h>
#import <NGObjWeb/WOResponse.h>
#import <NGObjWeb/WOCoreApplication.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalEntityObject.h>
@@ -137,22 +132,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <GDLContentStore/GCSChannelManager.h>
#include <signal.h>
#include <unistd.h>
#ifdef HAVE_OPENSSL
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#endif
void handle_eas_terminate(int signum)
{
NSLog(@"Forcing termination of EAS loop.");
shouldTerminate = YES;
[[WOCoreApplication application] terminateAfterTimeInterval: 1];
}
@interface SOGoActiveSyncDispatcher (Sync)
- (NSMutableDictionary *) _folderMetadataForKey: (NSString *) theFolderKey;
@@ -162,41 +143,23 @@ void handle_eas_terminate(int signum)
@implementation SOGoActiveSyncDispatcher
static BOOL debugOn = NO;
- (id) init
{
[super init];
debugOn = [[SOGoSystemDefaults sharedSystemDefaults] easDebugEnabled];
folderTableURL = nil;
imapFolderGUIDS = nil;
syncRequest = nil;
shouldTerminate = NO;
signal(SIGTERM, handle_eas_terminate);
return self;
}
- (void) dealloc
{
RELEASE(folderTableURL);
RELEASE(imapFolderGUIDS);
RELEASE(syncRequest);
[super dealloc];
}
- (void) _ensureFolder: (SOGoMailFolder *) mailFolder
{
BOOL rc;
if (![mailFolder isKindOfClass: [NSException class]])
{
rc = [mailFolder exists];
if (!rc)
rc = [mailFolder create];
}
}
- (void) _setFolderSyncKey: (NSString *) theSyncKey
{
SOGoCacheGCSObject *o;
@@ -206,16 +169,16 @@ void handle_eas_terminate(int signum)
[o setTableUrl: [self folderTableURL]];
[o reloadIfNeeded];
[[o properties] setObject: theSyncKey
forKey: @"FolderSyncKey"];
[[o properties] removeAllObjects];
[[o properties] addEntriesFromDictionary: [NSDictionary dictionaryWithObject: theSyncKey forKey: @"FolderSyncKey"]];
[o save];
}
- (NSMutableDictionary *) globalMetadataForDevice
- (NSMutableDictionary *) _globalMetadataForDevice
{
SOGoCacheGCSObject *o;
o = [SOGoCacheGCSObject objectWithName: [context objectForKey: @"DeviceId"] inContainer: nil useCache: NO];
o = [SOGoCacheGCSObject objectWithName: [context objectForKey: @"DeviceId"] inContainer: nil];
[o setObjectType: ActiveSyncGlobalCacheObject];
[o setTableUrl: [self folderTableURL]];
[o reloadIfNeeded];
@@ -239,7 +202,7 @@ void handle_eas_terminate(int signum)
if (theFilter)
{
o = [SOGoCacheGCSObject objectWithName: [NSString stringWithFormat: @"%@+%@", [context objectForKey: @"DeviceId"], theCollectionId] inContainer: nil];
[o setObjectType: ActiveSyncFolderCacheObject];
[o setObjectType: ActiveSyncGlobalCacheObject];
[o setTableUrl: [self folderTableURL]];
[o reloadIfNeeded];
@@ -266,27 +229,23 @@ void handle_eas_terminate(int signum)
SOGoMailAccounts *accountsFolder;
SOGoMailAccount *accountFolder;
SOGoUserFolder *userFolder;
NSDictionary *imapGUIDs;
if (!imapFolderGUIDS)
{
userFolder = [[context activeUser] homeFolderInContext: context];
accountsFolder = [userFolder lookupName: @"Mail" inContext: context acquire: NO];
accountFolder = [accountsFolder lookupName: @"0" inContext: context acquire: NO];
// Get the GUID of the IMAP folder
imapFolderGUIDS = [accountFolder imapFolderGUIDs];
[imapFolderGUIDS retain];
}
return [[[imapFolderGUIDS allKeysForObject: [NSString stringWithFormat: @"folder%@", theIdToTranslate]] objectAtIndex: 0] substringFromIndex: 6] ;
userFolder = [[context activeUser] homeFolderInContext: context];
accountsFolder = [userFolder lookupName: @"Mail" inContext: context acquire: NO];
accountFolder = [accountsFolder lookupName: @"0" inContext: context acquire: NO];
// Get the GUID of the IMAP folder
imapGUIDs = [accountFolder imapFolderGUIDs];
//return [[imapGUIDs allKeysForObject: theIdToTranslate] objectAtIndex: 0];
return [[[imapGUIDs allKeysForObject: [NSString stringWithFormat: @"folder%@", theIdToTranslate]] objectAtIndex: 0] substringFromIndex: 6] ;
}
return theIdToTranslate;
}
//
//
//
@@ -412,7 +371,7 @@ void handle_eas_terminate(int signum)
[[o properties ] setObject: [[newFolder nameInContainer] substringFromIndex: 6] forKey: @"displayName"];
[o save];
nameInContainer = [NSString stringWithFormat: @"mail/%@", [nameInContainer substringFromIndex: 6]];
nameInContainer = [[NSString stringWithFormat: @"mail/%@", [nameInContainer substringFromIndex: 6]] stringByEscapingURL];
}
else
{
@@ -428,24 +387,17 @@ void handle_eas_terminate(int signum)
SOGoAppointmentFolders *appointmentFolders;
SOGoCacheGCSObject *o;
NSString *key;
id newFolder;
nameInContainer = nil;
appointmentFolders = [userFolder privateCalendars: @"Calendar" inContext: context];
[appointmentFolders newFolderWithName: displayName
nameInContainer: &nameInContainer];
newFolder = [appointmentFolders lookupName: nameInContainer
inContext: context
acquire: NO];
[newFolder setSynchronize: YES];
if (type == 13)
nameInContainer = [NSString stringWithFormat: @"vevent/%@", nameInContainer];
else
nameInContainer = [NSString stringWithFormat: @"vtodo/%@", nameInContainer];
key = [NSString stringWithFormat: @"%@+%@", [context objectForKey: @"DeviceId"], nameInContainer ];
o = [SOGoCacheGCSObject objectWithName: key inContainer: nil];
[o setObjectType: ActiveSyncFolderCacheObject];
@@ -460,19 +412,12 @@ void handle_eas_terminate(int signum)
SOGoContactFolders *contactFolders;
SOGoCacheGCSObject *o;
NSString *key;
id newFolder;
nameInContainer = nil;
contactFolders = [userFolder privateContacts: @"Contacts" inContext: context];
[contactFolders newFolderWithName: displayName
nameInContainer: &nameInContainer];
newFolder = [contactFolders lookupName: nameInContainer
inContext: context
acquire: NO];
[newFolder setSynchronize: YES];
nameInContainer = [NSString stringWithFormat: @"vcard/%@", nameInContainer];
key = [NSString stringWithFormat: @"%@+%@", [context objectForKey: @"DeviceId"], nameInContainer ];
@@ -746,25 +691,26 @@ void handle_eas_terminate(int signum)
- (void) processFolderSync: (id <DOMElement>) theDocumentElement
inResponse: (WOResponse *) theResponse
{
NSString *key, *cKey, *nkey, *name, *serverId, *parentId, *nameInCache, *personalFolderName, *syncKey, *folderType, *operation;
NSMutableDictionary *cachedGUIDs, *metadata;
NSMutableArray *folders, *processedFolders;
NSString *key, *cKey, *nkey, *name, *serverId, *parentId, *nameInCache, *personalFolderName, *syncKey, *folderType;
NSDictionary *folderMetadata, *imapGUIDs;
NSArray *allFoldersMetadata, *allKeys;
NSMutableDictionary *cachedGUIDs, *metadata;
SOGoMailAccounts *accountsFolder;
SOGoMailAccount *accountFolder;
NSMutableString *s, *commands;
SOGoUserFolder *userFolder;
NSMutableArray *folders, *processedFolders;
SoSecurityManager *sm;
SOGoCacheGCSObject *o;
id currentFolder;
NSData *d;
int status, command_count, i, type, fi, count;
BOOL first_sync;
sm = [SoSecurityManager sharedSecurityManager];
metadata = [self globalMetadataForDevice];
metadata = [self _globalMetadataForDevice];
syncKey = [[(id)[theDocumentElement getElementsByTagName: @"SyncKey"] lastObject] textValue];
s = [NSMutableString string];
@@ -798,13 +744,6 @@ void handle_eas_terminate(int signum)
accountsFolder = [userFolder lookupName: @"Mail" inContext: context acquire: NO];
accountFolder = [accountsFolder lookupName: @"0" inContext: context acquire: NO];
if (first_sync)
{
[self _ensureFolder: (SOGoMailFolder *)[accountFolder draftsFolderInContext: context]];
[self _ensureFolder: (SOGoMailFolder *)[accountFolder sentFolderInContext: context]];
[self _ensureFolder: (SOGoMailFolder *)[accountFolder trashFolderInContext: context]];
}
allFoldersMetadata = [accountFolder allFoldersMetadata];
// Get GUIDs of folder (IMAP)
@@ -885,38 +824,32 @@ void handle_eas_terminate(int signum)
}
else
{
if ([cKey rangeOfString: @"vevent" options: NSCaseInsensitiveSearch].location != NSNotFound ||
[cKey rangeOfString: @"vtodo" options: NSCaseInsensitiveSearch].location != NSNotFound)
folderType = @"Calendar";
else
folderType = @"Contacts";
if ([cKey rangeOfString: @"vevent" options: NSCaseInsensitiveSearch].location != NSNotFound ||
[cKey rangeOfString: @"vtodo" options: NSCaseInsensitiveSearch].location != NSNotFound)
folderType = @"Calendar";
else
folderType = @"Contacts";
if ([ cKey rangeOfString: @"/"].location != NSNotFound)
currentFolder = [[[[context activeUser] homeFolderInContext: context] lookupName: folderType inContext: context acquire: NO]
if ([ cKey rangeOfString: @"/"].location != NSNotFound)
currentFolder = [[[[context activeUser] homeFolderInContext: context] lookupName: folderType inContext: context acquire: NO]
lookupName: [cKey substringFromIndex: [cKey rangeOfString: @"/"].location+1] inContext: context acquire: NO];
// We skip personal GCS folders - we always want to synchronize these
if ([currentFolder isKindOfClass: [SOGoGCSFolder class]] &&
[[currentFolder nameInContainer] isEqualToString: @"personal"])
continue;
// Remove the folder from device if it doesn't exist, we don't want to sync it, or it doesn't have the proper permissions
if (!currentFolder ||
![currentFolder synchronize] ||
[sm validatePermission: SoPerm_DeleteObjects
onObject: currentFolder
inContext: context] ||
[sm validatePermission: SoPerm_AddDocumentsImagesAndFiles
onObject: currentFolder
inContext: context])
{
[commands appendFormat: @"<Delete><ServerId>%@</ServerId></Delete>", [cKey stringByEscapingURL] ];
command_count++;
[o destroy];
}
}
}
}
// remove the folder from device if it doesn't exists or it has not the proper permissions
if (!currentFolder ||
[sm validatePermission: SoPerm_DeleteObjects
onObject: currentFolder
inContext: context] ||
[sm validatePermission: SoPerm_AddDocumentsImagesAndFiles
onObject: currentFolder
inContext: context])
{
[commands appendFormat: @"<Delete><ServerId>%@</ServerId></Delete>", [cKey stringByEscapingURL] ];
command_count++;
[o destroy];
}
}
}
}
// Handle addition and changes
for (i = 0; i < [allFoldersMetadata count]; i++)
@@ -1004,12 +937,7 @@ void handle_eas_terminate(int signum)
[[o properties] removeObjectForKey: @"DateCache"];
[[o properties] removeObjectForKey: @"MoreAvailable"];
[[o properties] removeObjectForKey: @"BodyPreferenceType"];
[[o properties] removeObjectForKey: @"SupportedElements"];
[[o properties] removeObjectForKey: @"SuccessfulMoveItemsOps"];
[[o properties] removeObjectForKey: @"InitialLoadSequence"];
[[o properties] removeObjectForKey: @"FirstIdInCache"];
[[o properties] removeObjectForKey: @"LastIdInCache"];
[o save];
command_count++;
@@ -1018,29 +946,17 @@ void handle_eas_terminate(int signum)
personalFolderName = [[[context activeUser] personalCalendarFolderInContext: context] nameInContainer];
folders = [[[[[context activeUser] homeFolderInContext: context] lookupName: @"Calendar" inContext: context acquire: NO] subFolders] mutableCopy];
[folders autorelease];
[folders addObjectsFromArray: [[[[context activeUser] homeFolderInContext: context] lookupName: @"Contacts" inContext: context acquire: NO] subFolders]];
// We remove all the folders that aren't GCS-ones, that we don't want to synchronize and
// the ones without write/delete permissions.
// Inside this loop we remove all the folder without write/delete permissions
count = [folders count]-1;
for (; count >= 0; count--)
{
currentFolder = [folders objectAtIndex: count];
// We skip personal GCS folders - we always want to synchronize these
if ([currentFolder isKindOfClass: [SOGoGCSFolder class]] &&
[[currentFolder nameInContainer] isEqualToString: @"personal"])
continue;
if (![currentFolder isKindOfClass: [SOGoGCSFolder class]] ||
![currentFolder synchronize] ||
[sm validatePermission: SoPerm_DeleteObjects
onObject: currentFolder
if ([sm validatePermission: SoPerm_DeleteObjects
onObject: [folders objectAtIndex: count]
inContext: context] ||
[sm validatePermission: SoPerm_AddDocumentsImagesAndFiles
onObject: currentFolder
onObject: [folders objectAtIndex: count]
inContext: context])
{
[folders removeObjectAtIndex: count];
@@ -1048,6 +964,7 @@ void handle_eas_terminate(int signum)
}
count = [folders count]-1;
NSString *operation;
for (fi = 0; fi <= count ; fi++)
{
@@ -1105,11 +1022,7 @@ void handle_eas_terminate(int signum)
[[o properties] removeObjectForKey: @"DateCache"];
[[o properties] removeObjectForKey: @"MoreAvailable"];
[[o properties] removeObjectForKey: @"BodyPreferenceType"];
[[o properties] removeObjectForKey: @"SupportedElements"];
[[o properties] removeObjectForKey: @"SuccessfulMoveItemsOps"];
[[o properties] removeObjectForKey: @"InitialLoadSequence"];
[[o properties] removeObjectForKey: @"FirstIdInCache"];
[[o properties] removeObjectForKey: @"LastIdInCache"];
}
[o save];
@@ -1132,11 +1045,7 @@ void handle_eas_terminate(int signum)
[[o properties] removeObjectForKey: @"DateCache"];
[[o properties] removeObjectForKey: @"MoreAvailable"];
[[o properties] removeObjectForKey: @"BodyPreferenceType"];
[[o properties] removeObjectForKey: @"SupportedElements"];
[[o properties] removeObjectForKey: @"SuccessfulMoveItemsOps"];
[[o properties] removeObjectForKey: @"InitialLoadSequence"];
[[o properties] removeObjectForKey: @"FirstIdInCache"];
[[o properties] removeObjectForKey: @"LastIdInCache"];
}
[o save];
@@ -1186,18 +1095,17 @@ void handle_eas_terminate(int signum)
SOGoMailAccounts *accountsFolder;
SOGoUserFolder *userFolder;
SOGoMailObject *mailObject;
NSMutableArray *a;
NSArray *partKeys;
int p;
NSRange r1, r2;
a = [[realCollectionId componentsSeparatedByString: @"/"] mutableCopy];
[a autorelease];
pathToPart = [a lastObject];
[a removeLastObject];
messageName = [a lastObject];
[a removeLastObject];
folderName = [a componentsJoinedByString: @"/"];
r1 = [realCollectionId rangeOfString: @"/"];
r2 = [realCollectionId rangeOfString: @"/" options: 0 range: NSMakeRange(NSMaxRange(r1)+1, [realCollectionId length]-NSMaxRange(r1)-1)];
folderName = [realCollectionId substringToIndex: r1.location];
messageName = [realCollectionId substringWithRange: NSMakeRange(NSMaxRange(r1), r2.location-r1.location-1)];
pathToPart = [realCollectionId substringFromIndex: r2.location+1];
userFolder = [[context activeUser] homeFolderInContext: context];
accountsFolder = [userFolder lookupName: @"Mail" inContext: context acquire: NO];
@@ -1296,7 +1204,7 @@ void handle_eas_terminate(int signum)
filter = [NSCalendarDate dateFromFilterType: [[(id)[[allCollections objectAtIndex: j] getElementsByTagName: @"FilterType"] lastObject] textValue]];
syncKey = [[(id)[[allCollections objectAtIndex: j] getElementsByTagName: @"SyncKey"] lastObject] textValue];
allMessages = [currentCollection syncTokenFieldsWithProperties: nil matchingSyncToken: syncKey fromDate: filter initialLoad: NO];
allMessages = [currentCollection syncTokenFieldsWithProperties: nil matchingSyncToken: syncKey fromDate: filter];
count = [allMessages count];
@@ -1346,7 +1254,7 @@ void handle_eas_terminate(int signum)
- (void) processItemOperations: (id <DOMElement>) theDocumentElement
inResponse: (WOResponse *) theResponse
{
NSString *fileReference, *realCollectionId, *serverId, *bodyPreferenceType, *mimeSupport, *collectionId;
NSString *fileReference, *realCollectionId, *serverId, *bodyPreferenceType, *collectionId;
NSMutableString *s;
NSArray *fetchRequests;
id aFetch;
@@ -1394,21 +1302,20 @@ void handle_eas_terminate(int signum)
SOGoMailAccounts *accountsFolder;
SOGoUserFolder *userFolder;
SOGoMailObject *mailObject;
NSMutableArray *a;
if ([fileReference length])
{
// fetch attachment
NSRange r1, r2;
NSArray *partKeys;
int p;
a = [[realCollectionId componentsSeparatedByString: @"/"] mutableCopy];
[a autorelease];
pathToPart = [a lastObject];
[a removeLastObject];
messageName = [a lastObject];
[a removeLastObject];
folderName = [a componentsJoinedByString: @"/"];
r1 = [realCollectionId rangeOfString: @"/"];
r2 = [realCollectionId rangeOfString: @"/" options: 0 range: NSMakeRange(NSMaxRange(r1)+1, [realCollectionId length]-NSMaxRange(r1)-1)];
folderName = [realCollectionId substringToIndex: r1.location];
messageName = [realCollectionId substringWithRange: NSMakeRange(NSMaxRange(r1), r2.location-r1.location-1)];
pathToPart = [realCollectionId substringFromIndex: r2.location+1];
userFolder = [[context activeUser] homeFolderInContext: context];
accountsFolder = [userFolder lookupName: @"Mail" inContext: context acquire: NO];
@@ -1424,13 +1331,13 @@ void handle_eas_terminate(int signum)
currentBodyPart = [mailObject lookupImap4BodyPartKey: [partKeys objectAtIndex:0] inContext: context];
for (p = 1; p < [partKeys count]; p++)
{
currentBodyPart = [currentBodyPart lookupImap4BodyPartKey: [partKeys objectAtIndex:p] inContext: context];
}
{
currentBodyPart = [currentBodyPart lookupImap4BodyPartKey: [partKeys objectAtIndex:p] inContext: context];
}
[s appendString: @"<Fetch>"];
[s appendString: @"<Status>1</Status>"];
[s appendFormat: @"<FileReference xmlns=\"AirSyncBase:\">mail/%@/%@/%@</FileReference>", [folderName stringByEscapingURL], messageName, pathToPart];
[s appendFormat: @"<FileReference xmlns=\"AirSyncBase:\">%@</FileReference>", [fileReference stringByEscapingURL]];
[s appendString: @"<Properties>"];
[s appendFormat: @"<ContentType xmlns=\"AirSyncBase:\">%@/%@</ContentType>", [[currentBodyPart partInfo] objectForKey: @"type"], [[currentBodyPart partInfo] objectForKey: @"subtype"]];
@@ -1460,13 +1367,6 @@ void handle_eas_terminate(int signum)
serverId = [[(id)[theDocumentElement getElementsByTagName: @"ServerId"] lastObject] textValue];
bodyPreferenceType = [[(id)[[(id)[theDocumentElement getElementsByTagName: @"BodyPreference"] lastObject] getElementsByTagName: @"Type"] lastObject] textValue];
[context setObject: bodyPreferenceType forKey: @"BodyPreferenceType"];
mimeSupport = [[(id)[theDocumentElement getElementsByTagName: @"MIMESupport"] lastObject] textValue];
[context setObject: mimeSupport forKey: @"MIMESupport"];
// https://msdn.microsoft.com/en-us/library/gg675490%28v=exchg.80%29.aspx
// The fetch element is used to request the application data of an item that was truncated in a synchronization response from the server.
// The complete item is then returned to the client in a server response.
[context setObject: @"8" forKey: @"MIMETruncation"];
currentCollection = [self collectionFromId: realCollectionId type: folderType];
@@ -2027,35 +1927,24 @@ void handle_eas_terminate(int signum)
- (void) processPing: (id <DOMElement>) theDocumentElement
inResponse: (WOResponse *) theResponse
{
NSString *collectionId, *realCollectionId, *syncKey, *processIdentifier, *pingRequestInCache;
NSString *collectionId, *realCollectionId, *syncKey;
NSMutableArray *foldersWithChanges, *allFoldersID;
SOGoMicrosoftActiveSyncFolderType folderType;
NSMutableDictionary *folderMetadata;
SOGoSystemDefaults *defaults;
SOGoCacheGCSObject *o;
id <DOMElement> aCollection;
NSArray *allCollections;
NSMutableString *s;
id collection;
NSData *d;
NSAutoreleasePool *pool;
int i, j, heartbeatInterval, defaultInterval, internalInterval, status, total_sleep, sleepInterval;
// Let other ping requests know that a new request has arrived.
processIdentifier = [NSString stringWithFormat: @"%d", [[NSProcessInfo processInfo] processIdentifier]];
o = [SOGoCacheGCSObject objectWithName: [context objectForKey: @"DeviceId"] inContainer: nil useCache: NO];
[o setObjectType: ActiveSyncGlobalCacheObject];
[o setTableUrl: [self folderTableURL]];
[o reloadIfNeeded];
[[o properties] setObject: processIdentifier forKey: @"PingRequest"];
[o save];
int i, j, heartbeatInterval, defaultInterval, internalInterval, status;
defaults = [SOGoSystemDefaults sharedSystemDefaults];
defaultInterval = [defaults maximumPingInterval];
internalInterval = [defaults internalSyncInterval];
sleepInterval = (internalInterval < 5) ? internalInterval : 5;
if (theDocumentElement)
heartbeatInterval = [[[(id)[theDocumentElement getElementsByTagName: @"HeartbeatInterval"] lastObject] textValue] intValue];
@@ -2069,9 +1958,6 @@ void handle_eas_terminate(int signum)
}
else
{
if (heartbeatInterval < internalInterval)
heartbeatInterval = internalInterval;
status = 1;
}
@@ -2082,37 +1968,19 @@ void handle_eas_terminate(int signum)
if (![allCollections count])
{
heartbeatInterval = [[[o properties] objectForKey: @"PingHeartbeatInterval"] intValue];
// We received an empty Ping request. Return status '3' to ask client to resend the request with complete body.
s = [NSMutableString string];
[s appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
[s appendString: @"<!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\">"];
[s appendString: @"<Ping xmlns=\"Ping:\">"];
[s appendString: @"<Status>3</Status>"];
[s appendString: @"</Ping>"];
if (debugOn)
[self logWithFormat: @"EAS - Empty Ping request - using cached HeatbeatInterval (%d)", heartbeatInterval];
d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml];
if (heartbeatInterval > defaultInterval || heartbeatInterval == 0)
{
heartbeatInterval = defaultInterval;
status = 5;
}
[theResponse setContent: d];
allFoldersID = [[o properties] objectForKey: @"PingCachedFolders"];
if (![allFoldersID count])
{
// We received an empty Ping request. Return status '3' to ask client to resend the request with complete body.
s = [NSMutableString string];
[s appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
[s appendString: @"<!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\">"];
[s appendString: @"<Ping xmlns=\"Ping:\">"];
[s appendString: @"<Status>3</Status>"];
[s appendString: @"</Ping>"];
d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml];
[theResponse setContent: d];
return;
}
if (debugOn)
[self logWithFormat: @"EAS - Empty Ping request - using cached folders %@", allFoldersID];
return;
}
else
{
@@ -2122,16 +1990,6 @@ void handle_eas_terminate(int signum)
collectionId = [[(id) [aCollection getElementsByTagName: @"Id"] lastObject] textValue];
[allFoldersID addObject: collectionId];
}
if (![allFoldersID isEqualToArray: [[o properties] objectForKey: @"PingCachedFolders"]])
{
if (debugOn)
[self logWithFormat: @"EAS - Ping - Save folderlist to cache (HeartbeatInterval: %d) (%@)", heartbeatInterval, allFoldersID];
[[o properties] setObject: [NSNumber numberWithInteger: heartbeatInterval] forKey: @"PingHeartbeatInterval"];
[[o properties] setObject: allFoldersID forKey: @"PingCachedFolders"];
[o save];
}
}
foldersWithChanges = [NSMutableArray array];
@@ -2139,10 +1997,6 @@ void handle_eas_terminate(int signum)
// We enter our loop detection change
for (i = 0; i < (heartbeatInterval/internalInterval); i++)
{
if (shouldTerminate)
break;
pool = [[NSAutoreleasePool alloc] init];
for (j = 0; j < [allFoldersID count]; j++)
{
collectionId = [allFoldersID objectAtIndex: j];
@@ -2167,40 +2021,17 @@ void handle_eas_terminate(int signum)
[foldersWithChanges addObject: collectionId];
}
}
DESTROY(pool);
if ([foldersWithChanges count])
{
[self logWithFormat: @"Change detected using Ping, we let the EAS client know to send a Sync."];
[self logWithFormat: @"Change detected, we push the content."];
status = 2;
break;
}
else
{
total_sleep = 0;
while (!shouldTerminate && total_sleep < internalInterval)
{
// We check if we must break the current ping request since an other ping request
// has just arrived.
pingRequestInCache = [[self globalMetadataForDevice] objectForKey: @"PingRequest"];
if (pingRequestInCache && ![pingRequestInCache isEqualToString: processIdentifier])
{
if (debugOn)
[self logWithFormat: @"EAS - Ping request canceled (%@)", pingRequestInCache];
// Make sure we end the heardbeat-loop.
internalInterval = heartbeatInterval;
break;
}
else
{
[self logWithFormat: @"Sleeping %d seconds while detecting changes in Ping...", internalInterval-total_sleep];
sleep(sleepInterval);
total_sleep += sleepInterval;
}
}
[self logWithFormat: @"Sleeping %d seconds while detecting changes...", internalInterval];
sleep(internalInterval);
}
}
@@ -2263,123 +2094,6 @@ void handle_eas_terminate(int signum)
[theResponse setContent: d];
}
//
//
//
#ifdef HAVE_OPENSSL
- (unsigned int) validateCert: (NSString *) theCert
{
NSData *d;
const unsigned char *data;
X509_STORE_CTX *ctx;
X509_LOOKUP *lookup;
X509_STORE *store;
X509 *cert;
BOOL success;
size_t len;
int rc;
success = NO;
d = [theCert dataByDecodingBase64];
data = (unsigned char *)[d bytes];
len = [d length];
cert = d2i_X509(NULL, &data, len);
if (!cert)
{
[self logWithFormat: @"EAS - validateCert failed for device %@: d2i_X509 failed", [context objectForKey: @"DeviceId"]];
return 17;
}
store = X509_STORE_new();
OpenSSL_add_all_algorithms();
if (store)
{
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
if (lookup)
{
X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
if (lookup)
{
X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
ERR_clear_error();
success = YES;
}
}
}
if (!success)
{
if (store)
{
X509_STORE_free(store);
store = NULL;
}
}
ctx = X509_STORE_CTX_new();
if (!ctx)
{
[self logWithFormat: @"EAS - validateCert failed for device %@: X509_STORE_CTX_new failed", [context objectForKey: @"DeviceId"]];
return 17;
}
if (X509_STORE_CTX_init(ctx, store, cert, NULL) != 1)
{
[self logWithFormat: @"EAS - validateCert failed for device %@: X509_STORE_CTX_init failed", [context objectForKey: @"DeviceId"]];
X509_STORE_CTX_free(ctx);
return 17;
}
rc = X509_verify_cert(ctx);
X509_STORE_CTX_free(ctx);
X509_free(cert);
if (rc)
{
return 1;
}
else
{
[self logWithFormat: @"EAS - validateCert failed for device %@: err=%d", [context objectForKey: @"DeviceId"], X509_STORE_CTX_get_error(ctx)];
return 17;
}
}
#else
- (unsigned int) validateCert: (NSString *) theCert
{
return 17;
}
#endif
- (void) processValidateCert: (id <DOMElement>) theDocumentElement
inResponse: (WOResponse *) theResponse
{
NSMutableString *s;
NSString *cert;
NSData *d;
cert = [[(id)[theDocumentElement getElementsByTagName: @"Certificate"] lastObject] textValue];
s = [NSMutableString string];
[s appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
[s appendString: @"<!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\">"];
[s appendString: @"<ValidateCert xmlns=\"ValidateCert:\">"];
[s appendString: @"<Status>1</Status><Certificate>"];
[s appendFormat: @"<Status>%d</Status>", [self validateCert: cert]];
[s appendString: @"</Certificate></ValidateCert>"];
d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml];
[theResponse setContent: d];
}
//
// <?xml version="1.0"?>
// <!DOCTYPE ActiveSync PUBLIC "-//MICROSOFT//DTD ActiveSync//EN" "http://www.microsoft.com/">
@@ -2696,100 +2410,39 @@ void handle_eas_terminate(int signum)
NGMimeMessageParser *parser;
NGMimeMessage *message;
NSException *error;
NSMutableData *data;
NSData *new_from_header;
NSData *data;
NGMutableHashMap *map;
NGMimeMessage *messageToSend;
NGMimeMessageGenerator *generator;
NSDictionary *identity;
NSString *fullName, *email;
const char *bytes;
int i, e, len;
BOOL found_header;
// We get the mail's data
data = [NSMutableData dataWithData: [[[[(id)[theDocumentElement getElementsByTagName: @"MIME"] lastObject] textValue] stringByDecodingBase64] dataUsingEncoding: NSUTF8StringEncoding]];
data = [[[[(id)[theDocumentElement getElementsByTagName: @"MIME"] lastObject] textValue] stringByDecodingBase64] dataUsingEncoding: NSUTF8StringEncoding];
// We extract the recipients
parser = [[NGMimeMessageParser alloc] init];
message = [parser parsePartFromData: data];
RELEASE(parser);
map = [NGHashMap hashMapWithDictionary: [message headers]];
identity = [[context activeUser] primaryIdentity];
fullName = [identity objectForKey: @"fullName"];
email = [identity objectForKey: @"email"];
if ([fullName length])
new_from_header = [[NSString stringWithFormat: @"From: %@ <%@>\r\n", [fullName asQPSubjectString: @"utf-8"], email] dataUsingEncoding:NSUTF8StringEncoding];
[map setObject: [NSString stringWithFormat: @"%@ <%@>", fullName, email] forKey: @"from"];
else
new_from_header = [[NSString stringWithFormat: @"From: %@\r\n", email] dataUsingEncoding:NSUTF8StringEncoding];
[map setObject: email forKey: @"from"];
bytes = [data bytes];
len = [data length];
i = 0;
found_header = NO;
messageToSend = [[[NGMimeMessage alloc] initWithHeader: map] autorelease];
// Search for the from-header
while (i < len)
{
if (i == 0 &&
(*bytes == 'f' || *bytes == 'F') &&
(*(bytes+1) == 'r' || *(bytes+1) == 'R') &&
(*(bytes+2) == 'o' || *(bytes+2) == 'O') &&
(*(bytes+3) == 'm' || *(bytes+3) == 'M') &&
(*(bytes+4) == ':'))
{
found_header = YES;
break;
}
if (((*bytes == '\r') && (*(bytes+1) == '\n')) &&
(*(bytes+2) == 'f' || *(bytes+2) == 'F') &&
(*(bytes+3) == 'r' || *(bytes+3) == 'R') &&
(*(bytes+4) == 'o' || *(bytes+4) == 'O') &&
(*(bytes+5) == 'm' || *(bytes+5) == 'M') &&
(*(bytes+6) == ':'))
{
found_header = YES;
i = i + 2; // \r\n
bytes = bytes + 2;
break;
}
bytes++;
i++;
}
// We search for the first \r\n AFTER the From: header to get the length of the string to replace.
e = i;
while (e < len)
{
if ((*bytes == '\r') && (*(bytes+1) == '\n'))
{
e = e + 2;
break;
}
bytes++;
e++;
}
// Update/Add the From header in the MIMEBody of the SendMail request.
// Any other way to modify the mail body would break s/mime emails.
if (found_header)
{
// Change the From header
[data replaceBytesInRange: NSMakeRange(i, (NSUInteger)(e-i))
withBytes: [new_from_header bytes]
length: [new_from_header length]];
}
else
{
// Add a From header
[data replaceBytesInRange: NSMakeRange(0, 0)
withBytes: [new_from_header bytes]
length: [new_from_header length]];
}
[messageToSend setBody: [message body]];
generator = [[[NGMimeMessageGenerator alloc] init] autorelease];
data = [generator generateMimeFromPart: messageToSend];
error = [self _sendMail: data
recipients: [message allRecipients]
saveInSentItems: ([(id)[theDocumentElement getElementsByTagName: @"SaveInSentItems"] count] ? YES : NO)];
@@ -2965,12 +2618,7 @@ void handle_eas_terminate(int signum)
{
[map setObject: [mailObject messageId] forKey: @"in-reply-to"];
references = [[[[[mailObject mailHeaders] objectForKey: @"references"] componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] mutableCopy] autorelease];
// If there is no References: header, initialize it with In-Reply-To.
if ([mailObject inReplyTo] && ![references count])
references = [NSMutableArray arrayWithObject: [mailObject inReplyTo]];
references = [[[[[mailObject mailHeaders] objectForKey: @"references"] componentsSeparatedByString: @" "] mutableCopy] autorelease];
if ([references count] > 0)
{
// If there are more than ten identifiers listed, we eliminate the second one.
@@ -3286,25 +2934,9 @@ void handle_eas_terminate(int signum)
options: NSCaseInsensitiveSearch].location == NSNotFound)
{
NSString *value;
#if GNUSTEP_BASE_MINOR_VERSION < 21
value = [[NSDate date] descriptionWithCalendarFormat: @"%a, %d %b %Y %H:%M:%S %z"
timeZone: [NSTimeZone timeZoneWithName: @"GMT"]
locale: nil];
#else
value = [[NSDate date] descriptionWithCalendarFormat: @"%a, %d %b %Y %H:%M:%S %z"
timeZone: [NSTimeZone timeZoneWithName: @"GMT"]
locale: [NSDictionary dictionaryWithObjectsAndKeys:
[NSArray arrayWithObjects: @"Jan", @"Feb", @"Mar", @"Apr",
@"May", @"Jun", @"Jul", @"Aug",
@"Sep", @"Oct", @"Nov", @"Dec", nil],
@"NSShortMonthNameArray",
[NSArray arrayWithObjects: @"Sun", @"Mon", @"Tue", @"Wed", @"Thu",
@"Fri", @"Sat", nil],
@"NSShortWeekDayNameArray",
nil]];
#endif
s = [NSString stringWithFormat: @"Date: %@\r\n%@", value, [theRequest contentAsString]];
value = [[NSDate date] descriptionWithCalendarFormat: @"%a, %d %b %Y %H:%M:%S %z" timeZone: [NSTimeZone timeZoneWithName: @"GMT"] locale: nil];
s = [NSString stringWithFormat: @"Date: %@\n%@", value, [theRequest contentAsString]];
}
else
{
@@ -3370,7 +3002,7 @@ void handle_eas_terminate(int signum)
[theResponse setHeader: @"Sync,SendMail,SmartForward,SmartReply,GetAttachment,GetHierarchy,CreateCollection,DeleteCollection,MoveCollection,FolderSync,FolderCreate,FolderDelete,FolderUpdate,MoveItems,GetItemEstimate,MeetingResponse,Search,Settings,Ping,ItemOperations,ResolveRecipients,ValidateCert" forKey: @"MS-ASProtocolCommands"];
[theResponse setHeader: @"2.5,12.0,12.1,14.0,14.1" forKey: @"MS-ASProtocolVersions"];
if (debugOn && [[theResponse headerForKey: @"Content-Type"] isEqualToString:@"application/vnd.ms-sync.wbxml"] && [[theResponse content] length])
if (debugOn && [[theResponse content] length])
[self logWithFormat: @"EAS - response for device %@: %@", [context objectForKey: @"DeviceId"], [[[NSString alloc] initWithData: [[theResponse content] wbxml2xml] encoding: NSUTF8StringEncoding] autorelease]];
RELEASE(context);
@@ -3394,7 +3026,8 @@ void handle_eas_terminate(int signum)
return nil;
urlString = [[user domainDefaults] folderInfoURL];
parts = [[urlString componentsSeparatedByString: @"/"] mutableCopy];
parts = [[urlString componentsSeparatedByString: @"/"]
mutableCopy];
[parts autorelease];
if ([parts count] == 5)
{
+33 -238
View File
@@ -34,7 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
#import <Foundation/NSString.h>
#import <Foundation/NSCharacterSet.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalDateTime.h>
@@ -473,131 +472,18 @@ struct GlobalObjectId {
return d;
}
//
//
//
- (BOOL) _sanitinizeNeeded: (NSArray *) theParts
{
NSString *encoding, *charset;
int i;
for (i = 0; i < [theParts count]; i++)
{
encoding = [[theParts objectAtIndex: i ] objectForKey: @"encoding"];
charset = [[[theParts objectAtIndex: i ] objectForKey: @"parameterList"] objectForKey: @"charset"];
if (encoding && ([encoding caseInsensitiveCompare: @"7bit"] == NSOrderedSame || [encoding caseInsensitiveCompare: @"8bit"] == NSOrderedSame) &&
charset && ![charset caseInsensitiveCompare: @"utf-8"] == NSOrderedSame
&& ![charset caseInsensitiveCompare: @"us-ascii"] == NSOrderedSame)
{
return YES;
}
if ([self _sanitinizeNeeded: [[theParts objectAtIndex: i ] objectForKey: @"parts"]])
return YES;
}
return NO;
}
- (BOOL) _isSigned: (NSDictionary *) thePart
{
NSMutableDictionary *currentPart;
NSArray *subparts;
NSString *type, *subtype;
NSUInteger i;
type = [[thePart objectForKey: @"type"] lowercaseString];
subtype = [[thePart objectForKey: @"subtype"] lowercaseString];
if ([type isEqualToString: @"multipart"])
{
if ([subtype isEqualToString: @"signed"])
return YES;
subparts = [thePart objectForKey: @"parts"];
for (i = 0; i < [subparts count]; i++)
{
currentPart = [subparts objectAtIndex: i];
if ([self _isSigned: currentPart])
return YES;
}
}
return NO;
}
- (BOOL) _isSmimeEncrypted: (NSDictionary *) thePart
{
NSMutableDictionary *currentPart;
NSArray *subparts;
NSString *type, *subtype;
NSUInteger i;
type = [[thePart objectForKey: @"type"] lowercaseString];
subtype = [[thePart objectForKey: @"subtype"] lowercaseString];
if ([type isEqualToString: @"multipart"])
{
subparts = [thePart objectForKey: @"parts"];
for (i = 0; i < [subparts count]; i++)
{
currentPart = [subparts objectAtIndex: i];
if ([self _isSmimeEncrypted: currentPart])
return YES;
}
}
else if ([type isEqualToString: @"application"] && ([subtype isEqualToString: @"pkcs7-mime"] ||
[subtype isEqualToString: @"x-pkcs7-mime"]))
return YES;
return NO;
}
- (BOOL) _isPGP: (NSDictionary *) thePart
{
NSMutableDictionary *currentPart;
NSArray *subparts;
NSString *type, *subtype, *protocol;
NSUInteger i;
type = [[thePart objectForKey: @"type"] lowercaseString];
subtype = [[thePart objectForKey: @"subtype"] lowercaseString];
protocol = [[[thePart objectForKey: @"parameterList"] objectForKey: @"protocol"] lowercaseString];
if ([type isEqualToString: @"multipart"])
{
if (([protocol isEqualToString: @"application/pgp-signature"] || [protocol isEqualToString: @"application/pgp-encrypted"]))
return YES;
subparts = [thePart objectForKey: @"parts"];
for (i = 0; i < [subparts count]; i++)
{
currentPart = [subparts objectAtIndex: i];
if ([self _isPGP: currentPart])
return YES;
}
}
else if ([type isEqualToString: @"application"] && [subtype isEqualToString: @"pgp-encrypted"])
return YES;
return NO;
}
//
//
//
- (NSData *) _preferredBodyDataUsingType: (int) theType
mimeSupport: (int) theMimeSupport
nativeType: (int *) theNativeType
{
NSString *type, *subtype, *encoding;
NSData *d;
BOOL isSMIME, sanitinizeNeeded;
type = [[[self bodyStructure] valueForKey: @"type"] lowercaseString];
subtype = [[[self bodyStructure] valueForKey: @"subtype"] lowercaseString];
isSMIME = NO;
d = nil;
// We determine the native type
@@ -608,16 +494,8 @@ struct GlobalObjectId {
else if ([type isEqualToString: @"multipart"])
*theNativeType = 4;
if (([self _isSigned: [self bodyStructure]] ||
[self _isSmimeEncrypted: [self bodyStructure]] ||
[self _isPGP: [self bodyStructure]]) && theMimeSupport > 0)
{
*theNativeType = 4;
isSMIME = YES;
}
// We get the right part based on the preference
if ((theType == 1 || theType == 2) && !isSMIME)
if (theType == 1 || theType == 2)
{
if ([type isEqualToString: @"text"] && ![subtype isEqualToString: @"calendar"])
{
@@ -658,12 +536,12 @@ struct GlobalObjectId {
d = [self _preferredBodyDataInMultipartUsingType: theType nativeTypeFound: theNativeType];
}
}
else if (theType == 4 || isSMIME)
else if (theType == 4)
{
// We sanitize the content if the content-transfer-encoding is 8bit and charset is not utf-8 or us-ascii.
sanitinizeNeeded = [self _sanitinizeNeeded: [NSArray arrayWithObject: [self bodyStructure]]];
if (sanitinizeNeeded && !isSMIME)
// We sanitize the content *ONLY* for Outlook clients and if the content-transfer-encoding is 8bit. Outlook has strange issues
// with quoted-printable/base64 encoded text parts. It just doesn't decode them.
encoding = [[self lookupInfoForBodyPart: @""] objectForKey: @"encoding"];
if ([[context objectForKey: @"DeviceType"] isEqualToString: @"WindowsOutlook15"] || ([encoding caseInsensitiveCompare: @"8bit"] == NSOrderedSame))
d = [self _sanitizedMIMEMessage];
else
d = [self content];
@@ -694,35 +572,6 @@ struct GlobalObjectId {
}
- (NSString *) _truncateContent: (NSString *) theContent
limit: (int) theLimit
truncated: (int *) wasTruncated
{
if ([theContent length] > theLimit)
{
int i, len;
theContent = [theContent substringToIndex: theLimit];
*wasTruncated = 1;
// We search for the first "space" character starting from the
// end and we truncate the string once more. We do this to avoid
// truncating the content in the middle of a XML entity
len = theLimit-1;
for (i = len; i >= 0; i--)
{
if (isspace([theContent characterAtIndex: i]))
break;
}
return [theContent substringToIndex: i];
}
*wasTruncated = 0;
return theContent;
}
//
//
//
@@ -807,17 +656,16 @@ struct GlobalObjectId {
{
NSData *d, *globalObjId;
NSArray *attachmentKeys;
iCalCalendar *calendar;
NSString *p;
NSMutableString *s;
id value;
int preferredBodyType, mimeSupport, mimeTruncation, nativeBodyType;
uint32_t v;
preferredBodyType = [[context objectForKey: @"BodyPreferenceType"] intValue];
mimeSupport = [[context objectForKey: @"MIMESupport"] intValue];
mimeTruncation = [[context objectForKey: @"MIMETruncation"] intValue];
uint32_t v;
NSString *p;
id value;
iCalCalendar *calendar;
int preferredBodyType, nativeBodyType;
s = [NSMutableString string];
@@ -1014,13 +862,7 @@ struct GlobalObjectId {
else
{
// MesssageClass and ContentClass
if ([self _isSigned: [self bodyStructure]])
[s appendFormat: @"<MessageClass xmlns=\"Email:\">%@</MessageClass>", @"IPM.Note.SMIME.MultipartSigned"];
else if ([self _isSmimeEncrypted: [self bodyStructure]])
[s appendFormat: @"<MessageClass xmlns=\"Email:\">%@</MessageClass>", @"IPM.Note.SMIME"];
else
[s appendFormat: @"<MessageClass xmlns=\"Email:\">%@</MessageClass>", @"IPM.Note"];
[s appendFormat: @"<MessageClass xmlns=\"Email:\">%@</MessageClass>", @"IPM.Note"];
[s appendFormat: @"<ContentClass xmlns=\"Email:\">%@</ContentClass>", @"urn:content-classes:message"];
}
@@ -1034,8 +876,10 @@ struct GlobalObjectId {
[s appendFormat: @"<InternetCPID xmlns=\"Email:\">%@</InternetCPID>", @"65001"];
// Body - namespace 17
preferredBodyType = [[context objectForKey: @"BodyPreferenceType"] intValue];
nativeBodyType = 1;
d = [self _preferredBodyDataUsingType: preferredBodyType mimeSupport: mimeSupport nativeType: &nativeBodyType];
d = [self _preferredBodyDataUsingType: preferredBodyType nativeType: &nativeBodyType];
if (calendar && !d)
{
@@ -1124,50 +968,9 @@ struct GlobalObjectId {
AUTORELEASE(content);
content = [content activeSyncRepresentationInContext: context];
len = [content length];
truncated = 0;
// We handle MIMETruncation
switch (mimeTruncation)
{
case 0:
{
content = @"";
len = 0; truncated = 1;
}
break;
case 1:
content = [self _truncateContent: content limit: 4096 truncated: &truncated];
len = [content length];
break;
case 2:
content = [self _truncateContent: content limit: 5120 truncated: &truncated];
len = [content length];
break;
case 3:
content = [self _truncateContent: content limit: 7168 truncated: &truncated];
len = [content length];
break;
case 4:
content = [self _truncateContent: content limit: 10240 truncated: &truncated];
len = [content length];
break;
case 5:
content = [self _truncateContent: content limit: 20480 truncated: &truncated];
len = [content length];
break;
case 6:
content = [self _truncateContent: content limit: 51200 truncated: &truncated];
len = [content length];
break;
case 7:
content = [self _truncateContent: content limit: 102400 truncated: &truncated];
len = [content length];
break;
case 8:
default:
truncated = 0;
}
len = [content length];
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
{
@@ -1175,32 +978,30 @@ struct GlobalObjectId {
[s appendFormat: @"<BodyTruncated xmlns=\"Email:\">%d</BodyTruncated>", truncated];
}
else
{
{
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
// Set the correct type if client requested text/html but we got text/plain.
// For s/mime mails type is always 4 if mimeSupport is 1 or 2.
// Set the correct type if client requested text/html but we got text/plain
if (preferredBodyType == 2 && nativeBodyType == 1)
[s appendString: @"<Type>1</Type>"];
else if (([self _isSigned: [self bodyStructure]] ||
[self _isSmimeEncrypted: [self bodyStructure]] ||
[self _isPGP: [self bodyStructure]]) && mimeSupport > 0)
[s appendString: @"<Type>4</Type>"];
else
[s appendFormat: @"<Type>%d</Type>", preferredBodyType];
[s appendFormat: @"<Truncated>%d</Truncated>", truncated];
[s appendFormat: @"<Preview></Preview>"];
[s appendFormat: @"<Data>%@</Data>", content];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", len];
if (!truncated)
{
[s appendFormat: @"<Data>%@</Data>", content];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", len];
}
[s appendString: @"</Body>"];
}
}
// Attachments -namespace 16
attachmentKeys = [self fetchFileAttachmentKeys];
if ([attachmentKeys count] && !([self _isSigned: [self bodyStructure]]))
if ([attachmentKeys count])
{
int i;
@@ -1270,21 +1071,15 @@ struct GlobalObjectId {
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"14.0"] ||
[[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"14.1"])
{
id value;
NSString *reference;
value = [[self mailHeaders] objectForKey: @"references"];
if ([value isKindOfClass: [NSArray class]])
reference = [[[value objectAtIndex: 0] componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] objectAtIndex: 0];
else
reference = [[value componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] objectAtIndex: 0];
reference = [[[[self mailHeaders] objectForKey: @"references"] componentsSeparatedByString: @" "] objectAtIndex: 0];
if ([reference length] > 0)
[s appendFormat: @"<ConversationId xmlns=\"Email2:\">%@</ConversationId>", [[reference dataUsingEncoding: NSUTF8StringEncoding] activeSyncRepresentationInContext: context]];
else if ([[self inReplyTo] length] > 0)
else if ([self inReplyTo])
[s appendFormat: @"<ConversationId xmlns=\"Email2:\">%@</ConversationId>", [[[self inReplyTo] dataUsingEncoding: NSUTF8StringEncoding] activeSyncRepresentationInContext: context]];
else if ([[self messageId] length] > 0)
else if ([self messageId])
[s appendFormat: @"<ConversationId xmlns=\"Email2:\">%@</ConversationId>", [[[self messageId] dataUsingEncoding: NSUTF8StringEncoding] activeSyncRepresentationInContext: context]];
}
-1
View File
@@ -37,7 +37,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@interface SOGoSyncCacheObject : NSObject
{
@public
id _uid;
id _sequence;
}
+13 -22
View File
@@ -32,17 +32,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <Foundation/NSNull.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
static Class NSNullK;
@implementation SOGoSyncCacheObject
+ (void) initialize
{
NSNullK = [NSNull class];
}
- (id) init
{
if ((self = [super init]))
@@ -54,14 +46,14 @@ static Class NSNullK;
return self;
}
+ (id) syncCacheObjectWithUID: (id) theUID sequence: (id) theSequence
+ (id) syncCacheObjectWithUID: (id) theUID sequence: (id) theSequence;
{
id o;
o = [[self alloc] init];
[o setUID: [NSNumber numberWithInt: [theUID intValue]]];
[o setSequence: ([theSequence isKindOfClass: NSNullK] ? theSequence : [NSNumber numberWithInt: [theSequence intValue]])];
[o setUID: theUID];
[o setSequence: theSequence];
return [o autorelease];
}
@@ -75,7 +67,7 @@ static Class NSNullK;
- (id) uid
{
return [_uid description];
return _uid;
}
- (void) setUID: (id) theUID
@@ -85,7 +77,7 @@ static Class NSNullK;
- (id) sequence
{
return ([_sequence isKindOfClass: NSNullK] ? _sequence : [_sequence description]);
return _sequence;
}
- (void) setSequence: (id) theSequence
@@ -96,7 +88,7 @@ static Class NSNullK;
- (NSComparisonResult) compareUID: (SOGoSyncCacheObject *) theSyncCacheObject
{
return [self->_uid compare: theSyncCacheObject->_uid];
return [[self uid] compare: [theSyncCacheObject uid]];
}
//
@@ -105,21 +97,21 @@ static Class NSNullK;
//
- (NSComparisonResult) compareSequence: (SOGoSyncCacheObject *) theSyncCacheObject
{
if ([self->_sequence isEqual: [NSNull null]] &&
[theSyncCacheObject->_sequence isEqual: [NSNull null]])
if ([[self sequence] isEqual: [NSNull null]] &&
[[theSyncCacheObject sequence] isEqual: [NSNull null]])
return [self compareUID: theSyncCacheObject];
if (![self->_sequence isEqual: [NSNull null]] && [theSyncCacheObject->_sequence isEqual: [NSNull null]])
if (![[self sequence] isEqual: [NSNull null]] && [[theSyncCacheObject sequence] isEqual: [NSNull null]])
return NSOrderedDescending;
if ([self->_sequence isEqual: [NSNull null]] && ![theSyncCacheObject->_sequence isEqual: [NSNull null]])
if ([[self sequence] isEqual: [NSNull null]] && ![[theSyncCacheObject sequence] isEqual: [NSNull null]])
return NSOrderedAscending;
// Must check this here, to avoid comparing NSNull objects
if ([self->_sequence compare: theSyncCacheObject->_sequence] == NSOrderedSame)
if ([[self sequence] compare: [theSyncCacheObject sequence]] == NSOrderedSame)
return [self compareUID: theSyncCacheObject];
return [self->_sequence compare: theSyncCacheObject->_sequence];
return [[self sequence] compare: [theSyncCacheObject sequence]];
}
- (NSString *) description
@@ -128,4 +120,3 @@ static Class NSNullK;
}
@end
+1 -1
View File
@@ -58,7 +58,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// don't send negative reminder - not supported
if (delta > 0)
[s appendFormat: @"<Reminder xmlns=\"Calendar:\">%d</Reminder>", (int)delta];
[s appendFormat: @"<Reminder xmlns=\"Calendar:\">%d</Reminder>", delta];
}
return s;
+1 -3
View File
@@ -41,9 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context;
- (void) changeParticipationStatus: (NSDictionary *) theValues
inContext: (WOContext *) context
component: (id) component;
@end
#endif
+41 -341
View File
@@ -38,8 +38,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <Foundation/NSTimeZone.h>
#import <NGExtensions/NSString+misc.h>
#import <NGExtensions/NSCalendarDate+misc.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WORequest.h>
@@ -47,17 +45,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalDateTime.h>
#import <NGCards/iCalPerson.h>
#import <NGCards/NSCalendarDate+NGCards.h>
#import <NGCards/NSString+NGCards.h>
#import <NGCards/iCalCalendar.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserDefaults.h>
#import <SOGo/WORequest+SOGo.h>
#import <Appointments/iCalEntityObject+SOGo.h>
#import <Appointments/iCalRepeatableEntityObject+SOGo.h>
#import <Appointments/SOGoAppointmentObject.h>
#include "iCalAlarm+ActiveSync.h"
#include "iCalRecurrenceRule+ActiveSync.h"
@@ -106,13 +98,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
else if ([self created])
[s appendFormat: @"<DTStamp xmlns=\"Calendar:\">%@</DTStamp>", [[self created] activeSyncRepresentationWithoutSeparatorsInContext: context]];
// Timezone
tz = [(iCalDateTime *)[self firstChildWithTag: @"dtstart"] timeZone];
// StartTime -- http://msdn.microsoft.com/en-us/library/ee157132(v=exchg.80).aspx
if ([self startDate])
{
if ([self isAllDay] && !tz)
if ([self isAllDay])
[s appendFormat: @"<StartTime xmlns=\"Calendar:\">%@</StartTime>",
[[[self startDate] dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
@@ -125,7 +114,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// EndTime -- http://msdn.microsoft.com/en-us/library/ee157945(v=exchg.80).aspx
if ([self endDate])
{
if ([self isAllDay] && !tz)
if ([self isAllDay])
[s appendFormat: @"<EndTime xmlns=\"Calendar:\">%@</EndTime>",
[[[self endDate] dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
@@ -135,18 +124,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendFormat: @"<EndTime xmlns=\"Calendar:\">%@</EndTime>", [[self endDate] activeSyncRepresentationWithoutSeparatorsInContext: context]];
}
// Timezone
tz = [(iCalDateTime *)[self firstChildWithTag: @"dtstart"] timeZone];
if (!tz)
tz = [iCalTimeZone timeZoneForName: [userTimeZone name]];
if (![self recurrenceId])
[s appendFormat: @"<TimeZone xmlns=\"Calendar:\">%@</TimeZone>", [tz activeSyncRepresentationInContext: context]];
[s appendFormat: @"<TimeZone xmlns=\"Calendar:\">%@</TimeZone>", [tz activeSyncRepresentationInContext: context]];
// Organizer and other invitations related properties
if ((organizer = [self organizer]))
{
meetingStatus = 1; // meeting and the user is the meeting organizer.
o = [organizer rfc822Email];
if (![self recurrenceId] && [o length])
if ([o length])
{
[s appendFormat: @"<Organizer_Email xmlns=\"Calendar:\">%@</Organizer_Email>", o];
@@ -235,37 +226,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//[s appendFormat: @"<Importance xmlns=\"Calendar:\">%d</Importance>", v];
// UID -- http://msdn.microsoft.com/en-us/library/ee159919(v=exchg.80).aspx
if (![self recurrenceId] && [[self uid] length])
[s appendFormat: @"<UID xmlns=\"Calendar:\">%@</UID>", [[self uid] activeSyncRepresentationInContext: context]];
// Recurrence rules
if ([self isRecurrent])
[s appendString: [[[self recurrenceRules] lastObject] activeSyncRepresentationInContext: context]];
// Comment
o = [self comment];
//if (![self recurrenceId] && [o length])
if ([o length])
{
// It is very important here to NOT set <Truncated>0</Truncated> in the response,
// otherwise it'll prevent WP8 phones from sync'ing. See #3028 for details.
o = [o activeSyncRepresentationInContext: context];
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
{
[s appendFormat: @"<Body xmlns=\"Calendar:\">%@</Body>", o];
[s appendString: @"<BodyTruncated xmlns=\"Calendar:\">0</BodyTruncated>"];
}
else
{
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", (int)[o length]];
[s appendFormat: @"<Data>%@</Data>", o];
[s appendString: @"</Body>"];
}
}
if ([[self uid] length])
[s appendFormat: @"<UID xmlns=\"Calendar:\">%@</UID>", [self uid]];
// Sensitivity
if ([[self accessClass] isEqualToString: @"PRIVATE"])
v = 2;
@@ -288,6 +251,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendFormat: @"</Categories>"];
}
// Reminder -- http://msdn.microsoft.com/en-us/library/ee219691(v=exchg.80).aspx
// TODO: improve this to handle more alarm types
if ([self hasAlarms])
@@ -298,79 +262,36 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendString: [alarm activeSyncRepresentationInContext: context]];
}
// Exceptions
// Recurrence rules
if ([self isRecurrent])
{
NSMutableArray *components, *exdates;
iCalEvent *current_component;
NSString *recurrence_id;
unsigned int count, max, i;
components = [NSMutableArray arrayWithArray: [[self parent] events]];
max = [components count];
if (max > 1 || [self hasExceptionDates])
{
exdates = [NSMutableArray arrayWithArray: [self exceptionDates]];
[s appendString: @"<Exceptions xmlns=\"Calendar:\">"];
for (count = 1; count < max; count++)
{
current_component = [components objectAtIndex: count] ;
if ([self isAllDay])
{
recurrence_id = [NSString stringWithFormat: @"%@",
[[[current_component recurrenceId] dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: -[userTimeZone secondsFromGMTForDate:
[current_component recurrenceId]]]
activeSyncRepresentationWithoutSeparatorsInContext: context]];
}
else
{
recurrence_id = [NSString stringWithFormat: @"%@", [[current_component recurrenceId]
activeSyncRepresentationWithoutSeparatorsInContext: context]];
}
[s appendString: @"<Exception>"];
[s appendFormat: @"<Exception_StartTime xmlns=\"Calendar:\">%@</Exception_StartTime>", recurrence_id];
[s appendFormat: @"%@", [current_component activeSyncRepresentationInContext: context]];
[s appendString: @"</Exception>"];
}
for (i = 0; i < [exdates count]; i++)
{
[s appendString: @"<Exception>"];
[s appendString: @"<Exception_Deleted>1</Exception_Deleted>"];
if ([self isAllDay])
{
recurrence_id = [NSString stringWithFormat: @"%@",
[[[[exdates objectAtIndex: i] asCalendarDate] dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: -[userTimeZone secondsFromGMTForDate:
[[exdates objectAtIndex: i] asCalendarDate]]]
activeSyncRepresentationWithoutSeparatorsInContext: context]];
}
else
{
recurrence_id = [NSString stringWithFormat: @"%@", [[[exdates objectAtIndex: i] asCalendarDate]
activeSyncRepresentationWithoutSeparatorsInContext: context]];
}
[s appendFormat: @"<Exception_StartTime xmlns=\"Calendar:\">%@</Exception_StartTime>", recurrence_id];
[s appendString: @"</Exception>"];
}
[s appendString: @"</Exceptions>"];
}
[s appendString: [[[self recurrenceRules] lastObject] activeSyncRepresentationInContext: context]];
}
if (![self recurrenceId])
[s appendFormat: @"<NativeBodyType xmlns=\"AirSyncBase:\">%d</NativeBodyType>", 1];
// Comment
o = [self comment];
if ([o length])
{
// It is very important here to NOT set <Truncated>0</Truncated> in the response,
// otherwise it'll prevent WP8 phones from sync'ing. See #3028 for details.
o = [o activeSyncRepresentationInContext: context];
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
{
[s appendFormat: @"<Body xmlns=\"Calendar:\">%@</Body>", o];
[s appendString: @"<BodyTruncated xmlns=\"Calendar:\">0</BodyTruncated>"];
}
else
{
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];
[s appendFormat: @"<Data>%@</Data>", o];
[s appendString: @"</Body>"];
}
}
[s appendFormat: @"<NativeBodyType xmlns=\"AirSyncBase:\">%d</NativeBodyType>", 1];
return s;
}
@@ -416,19 +337,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- (void) takeActiveSyncValues: (NSDictionary *) theValues
inContext: (WOContext *) context
{
iCalDateTime *start, *end; //, *oldstart;
NSCalendarDate *oldstart;
iCalDateTime *start, *end;
NSTimeZone *userTimeZone;
iCalTimeZone *tz;
id o;
int deltasecs;
BOOL isAllDay;
NSMutableArray *occurences;
occurences = [NSMutableArray arrayWithArray: [[self parent] events]];
if ((o = [theValues objectForKey: @"UID"]))
[self setUid: o];
@@ -441,11 +356,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
isAllDay = YES;
}
else if ([occurences count] && !([theValues objectForKey: @"AllDayEvent"]))
{
// If the occurence has no AllDay tag use it from master.
isAllDay = [[occurences objectAtIndex: 0] isAllDay];
}
//
// 0- free, 1- tentative, 2- busy and 3- out of office
@@ -512,7 +422,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
o = [o calendarDate];
start = (iCalDateTime *) [self uniqueChildWithTag: @"dtstart"];
oldstart = [start dateTime];
[start setTimeZone: tz];
if (isAllDay)
@@ -524,12 +433,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
[start setDateTime: o];
}
// Calculate delta if start date has been changed.
if (oldstart)
deltasecs = [[start dateTime ] timeIntervalSinceDate: oldstart] * -1;
else
deltasecs = 0;
}
if ((o = [theValues objectForKey: @"EndTime"]))
@@ -588,177 +491,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
RELEASE(rule);
[rule takeActiveSyncValues: o inContext: context];
// Exceptions
if ((o = [theValues objectForKey: @"Exceptions"]) && [o isKindOfClass: [NSArray class]])
{
NSCalendarDate *recurrenceId, *adjustedRecurrenceId, *currentId;
NSMutableArray *exdates, *exceptionstouched;
iCalEvent *currentOccurence;
NSDictionary *exception;
unsigned int i, count, max;
[self removeAllExceptionDates];
exdates = [NSMutableArray array];
exceptionstouched = [NSMutableArray array];
for (i = 0; i < [o count]; i++)
{
exception = [o objectAtIndex: i];
if (![[exception objectForKey: @"Exception_Deleted"] intValue])
{
recurrenceId = [[exception objectForKey: @"Exception_StartTime"] asCalendarDate];
if (isAllDay)
recurrenceId = [recurrenceId dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: [userTimeZone secondsFromGMTForDate:recurrenceId]];
// When moving the calendar entry (i.e. changing the startDate) iOS and Android sometimes send a value for
// Exception_StartTime which is not what we expect.
// With this we make sure the recurrenceId is always correct.
//
// iOS problem - If the master is a no-allday-event but the exception is, an invalid Exception_StartTime is in the request.
// e.g. it sends 20150409T040000Z instead of 20150409T060000Z;
// This might be a special case since iPhone doesn't allow an allday-exception on a non-allday-event.
if (!([[start dateTime] compare: [[start dateTime] hour:[recurrenceId hourOfDay] minute:[recurrenceId minuteOfHour]]] == NSOrderedSame))
recurrenceId = [recurrenceId hour:[[start dateTime] hourOfDay] minute:[[start dateTime] minuteOfHour]];
// We need to store the recurrenceIds and exception dates adjusted by deltasecs.
// This ensures that the adjustment in SOGoCalendarComponent->updateComponent->_updateRecurrenceIDsWithEvent gives the correct dates.
adjustedRecurrenceId = [recurrenceId dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0 seconds: deltasecs];
// search for an existing occurence and update it
max = [occurences count];
currentOccurence = nil;
count = 1;
while (count < max)
{
currentOccurence = [occurences objectAtIndex: count] ;
currentId = [currentOccurence recurrenceId];
if ([currentId compare: adjustedRecurrenceId] == NSOrderedSame)
{
[exceptionstouched addObject: adjustedRecurrenceId];
[currentOccurence takeActiveSyncValues: exception inContext: context];
break;
}
count++;
currentOccurence = nil;
}
// Create a new occurence if we found none to update.
if (!currentOccurence)
{
iCalDateTime *recid;
currentOccurence = [self mutableCopy];
[currentOccurence removeAllRecurrenceRules];
[currentOccurence removeAllExceptionRules];
[currentOccurence removeAllExceptionDates];
[[self parent] addToEvents: currentOccurence];
[currentOccurence takeActiveSyncValues: exception inContext: context];
recid = (iCalDateTime *)[currentOccurence uniqueChildWithTag: @"recurrence-id"];
if (isAllDay)
[recid setDate: adjustedRecurrenceId];
else
[recid setDateTime: adjustedRecurrenceId];
[exceptionstouched addObject: [recid dateTime]];
}
}
else if ([[exception objectForKey: @"Exception_Deleted"] intValue])
{
recurrenceId = [[exception objectForKey: @"Exception_StartTime"] asCalendarDate];
if (isAllDay)
recurrenceId = [recurrenceId dateByAddingYears: 0 months: 0
days: 0 hours: 0 minutes: 0
seconds: [userTimeZone secondsFromGMTForDate:recurrenceId]];
// We add only valid exception dates.
if ([self doesOccurOnDate: recurrenceId] &&
([[start dateTime] compare: [[start dateTime] hour:[recurrenceId hourOfDay]
minute:[recurrenceId minuteOfHour]]] == NSOrderedSame))
{
// We need to store the recurrenceIds and exception dates adjusted by deltasecs.
// This ensures that the adjustment in SOGoCalendarComponent->updateComponent->_updateRecurrenceIDsWithEvent gives the correct dates.
[exdates addObject: [recurrenceId dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: deltasecs]];
}
}
}
// Update exception dates in master event.
max = [exdates count];
if (max > 0)
{
for (count = 0; count < max; count++)
{
if (([exceptionstouched indexOfObject: [exdates objectAtIndex: count]] == NSNotFound))
[self addToExceptionDates: [exdates objectAtIndex: count]];
}
}
// Remove all exceptions included in the request.
max = [occurences count];
count = 1; // skip the master event
while (count < max)
{
currentOccurence = [occurences objectAtIndex: count] ;
currentId = [currentOccurence recurrenceId];
// Delete all occurences which are not touched (modified/added).
if (([exceptionstouched indexOfObject: currentId] == NSNotFound))
[[[self parent] children] removeObject: currentOccurence];
count++;
}
}
else if ([self isRecurrent])
{
// We have no exceptions in request but there is a recurrence rule.
// Remove all excpetions and exception dates.
iCalEvent *currentOccurence;
unsigned int count, max;
[self removeAllExceptionDates];
max = [occurences count];
count = 1; // skip the master event
while (count < max)
{
currentOccurence = [occurences objectAtIndex: count];
[[[self parent] children] removeObject: currentOccurence];
count++;
}
}
}
else if ([self isRecurrent])
{
// We have no recurrence rule in request.
// Remove all exceptions, exception dates and recurrence rules.
iCalEvent *currentOccurence;
unsigned int count, max;
[self removeAllRecurrenceRules];
[self removeAllExceptionRules];
[self removeAllExceptionDates];
max = [occurences count];
count = 1; // skip the master event
while (count < max)
{
currentOccurence = [occurences objectAtIndex: count];
[[[self parent] children] removeObject: currentOccurence];
count++;
}
}
// Organizer - we don't touch the value unless we're the organizer
@@ -766,7 +498,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
([self userIsOrganizer: [context activeUser]] || [[context activeUser] hasEmail: o]))
{
iCalPerson *person;
person = [iCalPerson elementWithTag: @"organizer"];
[person setEmail: o];
[person setCn: [theValues objectForKey: @"Organizer_Name"]];
@@ -814,7 +546,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
// Windows phones sens sometimes an empty Attendees tag.
// We check it's an array before processing it.
if ((o = [theValues objectForKey: @"Attendees"]) && [o isKindOfClass: [NSArray class]])
if ((o = [theValues objectForKey: @"Attendees"])&& [o isKindOfClass: [NSArray class]])
{
NSMutableArray *attendees;
NSDictionary *attendee;
@@ -863,36 +595,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
}
- (void) changeParticipationStatus: (NSDictionary *) theValues
inContext: (WOContext *) context
component: (id) component
{
NSString *status;
id o;
// See: https://msdn.microsoft.com/en-us/library/ee202290(v=exchg.80).aspx
//
// 0 == Free
// 1 == Tentative
// 2 == Busy
// 3 == Out of Office
// 4 == Working elsehwere
//
if ((o = [theValues objectForKey: @"BusyStatus"]))
{
// We translate >= 2 into ACCEPTED
if ([o intValue] == 0)
status = @"NEEDS-ACTION";
else if ([o intValue] >= 2)
status = @"ACCEPTED";
else
status = @"TENTATIVE";
// There's no delegate in EAS
[(SOGoAppointmentObject *) component changeParticipationStatus: status
withDelegate: nil
alarm: nil];
}
}
@end
+1 -1
View File
@@ -140,7 +140,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Simple reccurrence rule of type "Monthly"
type = 2;
[s appendFormat: @"<Recurrence_DayOfMonth xmlns=\"Calendar:\">%d</Recurrence_DayOfMonth>",
(int)[[[self parent] startDate] dayOfMonth]];
[[[self parent] startDate] dayOfMonth]];
}
}
else if ([self frequency] == iCalRecurrenceFrequenceYearly)
+1 -1
View File
@@ -140,7 +140,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", (int)[o length]];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];
[s appendFormat: @"<Data>%@</Data>", o];
[s appendString: @"</Body>"];
}
+4 -5
View File
@@ -57,6 +57,8 @@ ProxyPreserveHost On
# Allow from your-cas-host-addr
# </Proxy>
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.
@@ -65,13 +67,11 @@ ProxyPreserveHost On
# http://127.0.0.1:20000/SOGo/Microsoft-Server-ActiveSync \
# retry=60 connectiontimeout=5 timeout=360
ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0
<Proxy http://127.0.0.1:20000/SOGo>
## adjust the following to your configuration
RequestHeader set "x-webobjects-server-port" "443"
# RequestHeader set "x-webobjects-server-name" "yourhostname"
# RequestHeader set "x-webobjects-server-url" "https://yourhostname"
RequestHeader set "x-webobjects-server-name" "yourhostname"
RequestHeader set "x-webobjects-server-url" "https://yourhostname"
## When using proxy-side autentication, you need to uncomment and
## adjust the following line:
@@ -90,6 +90,5 @@ ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0
<IfModule rewrite_module>
RewriteEngine On
RewriteRule ^/.well-known/caldav/?$ /SOGo/dav [R=301]
RewriteRule ^/.well-known/carddav/?$ /SOGo/dav [R=301]
</IfModule>
-5636
View File
File diff suppressed because it is too large. Load diff
-5655
View File
File diff suppressed because it is too large. Load diff
+157
View File
@@ -0,0 +1,157 @@
https://wiki.inverse.ca/focus/SOGo/CodingStyle
https://wiki.inverse.ca/focus/SOGo/D%C3%A9veloppement
https://wiki.inverse.ca/focus/PacketFence/Devel/BestPractices
UI and UX
---------
* http://www.google.com/design/spec/material-design/
* http://goodui.org/
* Try Repeating Your Primary Action instead of showing it just once.
* Try Distinct Clickable/Selected Styles instead of blurring them.
* Try Undos instead of prompting for confirmation.
* Try More Contrast instead of similarity.
* Try Exposing Options instead of hiding them.
* Try Showing State instead of being state agnostic.
* Try Direct Manipulation instead of contextless menus.
* Try Exposing Fields instead of creating extra pages.
* Try Transitions instead of showing changes instantly.
* Try Fewer Borders instead of wasting attention.
* Try Designing For Zero Data instead of just data heavy cases.
* Try Consistency instead of making people relearn.
* Try Conventions instead of reinventing the wheel.
* Try Visual Hierarchy instead of dullness.
* Try Grouping Related Items instead of disordering.
* Try Inline Validation instead of delaying errors.
* Try Forgiving Inputs instead of being strict with data.
* Try Bigger Click Areas instead of tiny ones.
* Try Faster Load Times instead of making people wait.
* Try Keyboard Shortcuts instead of buttons only.
* Try Upfront Progress instead of starting with a blank.
* Try Softer Prompts instead of modal windows.
* Try Multifunctional Controls instead of more parts.
* Try Icon Labels instead of opening for interpretation.
* http://designmodo.com/create-style-guides/
* http://uxmyths.com/
Frameworks & Tools
------------------
GNUstep
~~~~~~~
SOPE
~~~~
AngularJS
~~~~~~~~~
* https://angularjs.org/
* http://angular-ui.github.io/ui-router/
* https://www.airpair.com/angularjs/posts/angularjs-tutorial
Angular Material
~~~~~~~~~~~~~~~~
* https://material.angularjs.org/
Lo-Dash
~~~~~~~
* http://lodash.com/
* http://underscorejs.org/
Code Style
----------
Objective-C
~~~~~~~~~~~
* To document the Web APIs, we follow the http://apidocjs.com/[APIDOC] standards.
apidoc -f ".*\\.m" -i UI -o Documentation/JSON-API
HTML
~~~~
* Localize your strings:
<var:string label:value="I'm localized!"/>
* Localize your attributes:
<input type="text" label:placeholder="I'm localized!"/>
* Reuse existing localized strings as much as possible. Otherwise don't forget to update the English Localizable.strings file of the appropriate module.
JavaScript
~~~~~~~~~~
* http://eslint.org/
* https://github.com/toddmotto/angularjs-styleguide
* https://github.com/angular/material/blob/master/docs/guides/CODING.md
* We conform to https://github.com/airbnb/javascript[Airbnb coding standards]. Use https://github.com/jscs-dev/node-jscs[jscs] with the 'airbnb' preset to validate your code style:
jscs -p airbnb *.js
* For documentation, we follow the http://usejsdoc.org/[JSDoc3] standards:
jsdoc UI/WebServerResources/js/{Appointments,Common,Contacts,Mailer}/*.js -d Documentation/JavaScript-API
Models (facades)
^^^^^^^^^^^^^^^^
////
http://trochette.github.io/Angular-Design-Patterns-Best-Practices/
////
* Move business logic into models and share them.
* Keep it simple, separate server interaction and error handling from the model. That way model only handle data processing and code is easier to maintain.
SASS/CSS
~~~~~~~~
* http://componentcss.com/
* https://github.com/styleguide/css
* https://smacss.com/
* For documentation, we follow http://sassdoc.com/[SassDoc] annotations.
* We need the SASS files of Angular Material to build our CSS. The git repository of Angular Material is included as a submodule of SOGo:
git submodule init
git submodule update
* FlexBox compatibility http://caniuse.com/#feat=flexbox
Fonts
^^^^^
* We build a custom icons font using the online app https://icomoon.io/app/#/select[icomoon].
* http://www.carrois.com/fira-4-0/
* Material Design Iconic Font http://zavoloklom.github.io/material-design-iconic-font/icons.html
Version Control
---------------
* https://devcharm.com/articles/46/improve-your-git-workflow/
* Each commit should cover only one thing;
* Begin the commit message with a single short (less than 50 characters) line summarizing the change, followed by a blank line and then a more thorough description;
* When fixing a bug, commit to the devel branch as well as the maintenance branch of the latest release version (named maintenance/x.y). When a ticket is associated to the bug, add to the description a line saying *Fixes #1234*.
* `git pull` may introduce http://stackoverflow.com/questions/15316601/in-what-cases-could-git-pull-be-harmful[inconsistencies and problems]. Replace it with the following alias:
git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'
Testing
-------
* https://github.com/angular/protractor
* http://karma-runner.github.io/
JSON API
~~~~~~~~
One practical way to test the JSON API is to use `curl`. To do so, you need to enable `SOGoTrustProxyAuthentication` and configure HTTP authentifcation in Apache. You can pipe the result to [jq](http://stedolan.github.io/jq/) to nicely format and filter the output:
curl -u username:password http://localhost/SOGo/so/username/Calendar/calendarslist | jq '.'
curl -u username:password -H 'Content-Type: application/json' -d '{}' http://localhost/SOGo/so/francis/Calendar/personal/71B6-54904400-1-7C308500.ics/save
+10 -80
View File
@@ -1,7 +1,5 @@
Installation and Configuration Guide
====================================
:toc: left
:icons: font
////
@@ -56,7 +54,7 @@ at http://www.sogo.nu/
Architecture and Compatibility
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
image::images/architecture.png[System Architecture, 400, 964]
image::images/architecture.png[System Architecture]
Standard protocols such as CalDAV, CardDAV, GroupDAV, HTTP, IMAP and
SMTP are used to communicate with the SOGo platform or its
@@ -172,7 +170,7 @@ supported by SOGo:
* Red Hat Enterprise Linux (RHEL) Server 5, 6 and 7
* Community ENTerprise Operating System (CentOS) 5, 6 and 7
* Debian GNU/Linux 6.0 (Squeeze) to 8.0 (Jessie)
* Ubuntu 12.04 (Precise) to 14.04 (Trusty)
* Ubuntu 10.04 (Lucid) to 14.04 (Trusty)
Make sure the required components are started automatically at boot time
and that they are running before proceeding with the SOGo configuration.
@@ -181,7 +179,7 @@ standard distribution. For example, if you are using Red Hat Enterprise
Linux 5, you have to be subscribed to the Red Hat Network before
continuing with the SOGo software installation.
NOTE: This document covers the installation of SOGo under RHEL 6.
This document covers the installation of SOGo under RHEL 6.
For installation instructions on Debian and Ubuntu, please refer
directly to the SOGo website at http://www.sogo.nu/.
@@ -216,10 +214,12 @@ gpgcheck=0
Some of the softwares on which SOGo depends are available from the
repository of RepoForge (previously known as RPMforge). To add RepoForge
to your packages sources, download and install the appropriate RPM
package from http://packages.sw.be/rpmforge-release/.
package
from http://packages.sw.be/rpmforge-release/.
Also make sure you enabled the "rpmforge-extras" repository.
For more information on using RepoForge, visit http://repoforge.org/use/.
For more information on using RepoForge,
visit http://repoforge.org/use/.
Software Installation
~~~~~~~~~~~~~~~~~~~~~
@@ -294,7 +294,7 @@ associated to a domain is limited to access only the users data from the
same domain. Consequently, the configuration parameters of SOGo are
defined on three levels:
image::images/preferences-hierarchy.png[Preferences Hierarchy, 400, 400]
image::images/preferences-hierarchy.png[Preferences Hierarchy]
Each level inherits the preferences of the parent level. Therefore,
domain preferences define the defaults values of the user preferences,
@@ -368,13 +368,6 @@ Defaults to 10 (minutes).
Do not set this too low as child processes replying to clients on a slow
internet connection could be killed prematurely.
|S |WOMaxUploadSize
|Parameter used to set the maximum allowed size for content being
sent to SOGo using a PUT or a POST call. This can also limit the file
attachment size being uploaded to SOGo when composing a mail. The
value is in kilobyte. By default, the value is 0, or disabled so no
limit will be set.
|S |SxVMemLimit
|Parameter used to set the maximum amount of memory (in
megabytes) that a child can use. Reaching that value will force children
@@ -721,21 +714,6 @@ Default value is `0`, or disabled.
|Number of seconds, default to `300` (or 5 minutes). Note that
_SOGoCacheCleanupInterval_ must be set to a value equal or higher than
_SOGoFailedLoginBlockInterval_.
|S |SOGoMaximumRequestCount
|Parameter used to control the number of requests a user can send to the SOGo
server in _SOGoMaximumRequestInterval_ seconds or more. If conditions are met
or exceeded, the user will not be able to perform requests on the SOGo server
for _SOGoRequestBlockInterval_ seconds and will receive 429 HTTP responses for
any requests being made. Default value is 0, or disabled
|S |SOGoMaximumRequestInterval
|Number of seconds, defaults to `30`.
|S |SOGoRequestBlockInterval
|Number of seconds, defaults to 300 (or 5 minutes). Note that _SOGoCacheCleanupInterval_
must be set to a value equal or higher than _SOGoRequestBlockInterval_.
|=======================================================================
Authentication using LDAP
@@ -1147,7 +1125,7 @@ fax number, one could map it to the _facsimiletelephonenumber_ attribute
like this:
----
mapping = {
mapping = \{
  facsimiletelephonenumber = ("fax", "facsimiletelephonenumber");
};
----
@@ -1344,29 +1322,6 @@ supported, such as MySQL and Oracle.
First, make sure that your PostgreSQL server has TCP/IP connections
support enabled.
[TIP]
===============================
SOGo stores the database hostname together with table references inside
several database tables. To prevent possible future issues when moving
the database to another host, it is best practice to add a local alias name to
your `/etc/hosts` file, and using this in `/etc/sogo/sogo.conf` instead of the
actual name of your server or localhost. When the database host name changes,
you can now simply change the hosts file instead of updating several table
columns replacing the old hostname. An example entry for `/etc/hosts` when
running the database on the same host, registering `127.0.0.1` not only for
`localhost`, but also the `db-alias` alias:
127.0.0.1 localhost db-alias
In the SOGo configuration, use the alias name instead of the real IP address or
host name, for example
----
SOGoProfileURL =
"postgresql://sogo:sogo@db-alias:5432/sogo/sogo_user_profile";
----
===============================
Create the database user and schema using the following commands:
----
@@ -1673,16 +1628,6 @@ Defaults to `Trash` when unset.
Use a `/` as a hierarchy separator if referring to an IMAP subfolder.
For example: `INBOX/Trash`.
|U |SOGoJunkFolderName
|Parameter used to set the IMAP folder name used to store junk
messages.
Defaults to `Junk` when unset.
Use a `/` as a hierarchy separator if referring to an IMAP subfolder.
For example: `INBOX/Junk`. Also see the SOGoMailJunkSettings for
more options regarding junk/not-junk actions.
|D |SOGoIMAPCASServiceName
|Parameter used to set the CAS service name (URL) of the imap service.
This is useful if SOGo is connecting to the IMAP service through a
@@ -2137,21 +2082,7 @@ Defaults to `%{FolderName} (%{UserName} <%{Email}>)` when unset.
the template named `UIxAdditionalPreferences.wox`. This template should
be put under `~sogo/GNUstep/Library/SOGo/Templates/PreferencesUI/`.
|D |SOGoMailJunkSettings
|Parameter used to enable email junk settings. The value is a dictionary
and the follow keys are supported: `vendor` (which must be set to "generic"
for now), `junkEmailAddress` which sets the email address to whom SOGo will
send junk mails to, `notJunkEmailAddress` which sets the email address to
whome SOGo will send non-junk mails to and `limit`, which is an integer value
and sets the maximum number of mails that will be attached to a
junk/not junk report sent by SOGo. Example: `SOGoMailJunkSettings = {
vendor = "generic"; junkEmailAddress = "spam@foo.com";
notJunkEmailAddress = "ham@foo.com"; limit = 10;
};`
|D |SOGoMailKeepDraftsAfterSend
|Parameter used to keep mails in the drafts folder once they have been
sent by SOGo. Defaults to `NO` when unset.
Defaults to `NO` when unset.
|=======================================================================
SOGo Configuration Summary
@@ -2180,7 +2111,6 @@ like this:
SOGoDraftsFolderName = Drafts;
SOGoSentFolderName = Sent;
SOGoTrashFolderName = Trash;
SOGoJunkFolderName = Junk;
SOGoMailingMechanism = smtp;
SOGoSMTPServer = 127.0.0.1;
SOGoUserSources = (
@@ -233,7 +233,6 @@ Installation
This section will guide you through the installation of the native
Microsoft Outlook compatibility layer SOGo offers.
////
Red Hat Enterprise Linux v6 x86_64
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -317,7 +316,7 @@ from this guide.
On Ubuntu 12.04, the Samba init scripts need to be modified to
disable the upstart check. For more details, refer to:
https://wiki.samba.org/index.php/Samba4/InitScript
////
Debian 8 (Jessie) and Ubuntu 14.04 (Trusty Tahr)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -388,7 +387,7 @@ Run the following commands as root: 
----
samba-tool domain provision --realm=example.com \
--domain=EXAMPLE \
--domain=OPENCHANGE \
--adminpass='%1OpenChange' \
--server-role='domain controller'
@@ -396,7 +395,7 @@ samba-tool user setexpiry administrator --noexpiry
----
You might consider changing the realm and domain used, to suit your
environment.
enviroment.
You might also have to
remove `/etc/samba/smb.conf` prior running this command.
@@ -442,7 +441,7 @@ Your Samba 4 configuration file should look like this:
OpenChange Configuration
~~~~~~~~~~~~~~~~~~~~~~~~
Since v2.2, OpenChange stores its metadata in MySQL so you need to have it installed.
OpenChange 2.2 stores its metadata in MySQL so you need to have it installed.
First, create the OpenChange MySQL user:
@@ -513,11 +512,9 @@ mapistore:indexing_backend = mysql://openchange-user:openchange$123@localhost/op
mapiproxy:openchangedb = mysql://openchange-user:openchange$123@localhost/openchange
----
////
On RHEL, make sure SELinux is disabled:
setenforce 0
////
Next, you can start Samba using the usual command:
@@ -548,11 +545,9 @@ This service runs as a WSGI application under apache (mod_wsgi).
While HTTPS is not required to access this service, it is strongly
recommended.
////
On RHEL-based distributions, the apache configuration required by these
services can be found in `/etc/httpd/conf.d/ocsmanager.conf` and
`/etc/httpd/conf.d/rpcproxy.conf`.
////
For Debian-based distributions, these files can be found
in `/etc/apache2/conf.d/` or `/etc/apache2/conf-available`.
@@ -568,10 +563,8 @@ The OCS Manager and RPC Proxy configuration module can be enabled using:
a2enconf ocsmanager
a2enconf rpcproxy
////
On RHEL-based distributions, make sure the `LoadModule` directive is
uncommented in `/etc/httpd/conf.d/wsgi.conf`.
////
The _reqtimeout_ apache module is known to cause problems when using the
default configuration shipped with Debian-based systems. On such
@@ -587,12 +580,10 @@ To avoid this problem, use a much higher timeout or disable the module:
a2dismod reqtimeout
You should now restart the Apache service and make sure it will start on
boot.
////
On RHEL-based distributions, do:
boot. On RHEL-based distributions, do:
chkconfig httpd on && /etc/init.d/httpd restart
////
On Debian-based distributions, do:
update-rc.d apache2 defaults && /etc/init.d/apache2 restart
@@ -818,10 +809,11 @@ can be ignored for now. This feature is currently not supported.
remove any data associated with the user from the SOGo server and
recreate a Microsoft Outlook profile.
To remove any data associated to a user, use
the `openchange_user_cleanup` script distributed with OpenChange. The script
can be found in `/usr/share/openchange/`.
the `openchange_user_cleanup` script distributed with SOGo. The script
can be found in `/usr/share/doc/sogo/` (`/usr/share/sogo-VERSION/` on
RHEL).
To reset a user, run the script as root:
`openchange_user_cleanup username`. See the usage output for additional options.
`python openchange_user_cleanup username`. See the usage output for additional options.
* The "Out of Office Assistant" will not currently work. This feature
has not been implemented.
* Creating folders below INBOX (when not normally permitted by the IMAP
+3 -3
View File
@@ -1,7 +1,7 @@
<!-- TODO have the build system take care of this -->
<releaseinfo>Version 2.3.10 - April 2016</releaseinfo>
<subtitle>for version 2.3.10</subtitle>
<date>2016-04-05</date>
<releaseinfo>Version 2.3.1 - July 2015</releaseinfo>
<subtitle>for version 2.3.1</subtitle>
<date>2015-07-23</date>
<legalnotice>
<para>Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".</para>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

@@ -6,13 +6,13 @@
Authors:
- Inverse inc. <info@inverse.ca>
Copyright (C) 2008-2016 Inverse inc.
Copyright (C) 2008-2015 Inverse inc.
License: GFDL 1.2 or later. http://www.gnu.org/licenses/fdl.html
////
// TODO have the build system take care of this
:release_version: 2.3.10
:release_version: 2.3.1
// vim: set syntax=asciidoc tabstop=2 shiftwidth=2 expandtab:
+1 -1
View File
@@ -267,7 +267,7 @@
NSObject <DOMNodeList> *list;
NSObject <DOMNode> *valueNode;
NSArray *elements;
NSString *property=nil, *match=nil;
NSString *property, *match;
list = [searchElement getElementsByTagName: @"prop"];
if ([list length])
-63
View File
@@ -425,12 +425,8 @@ static BOOL debugLeaks;
{
static NSArray *runLoopModes = nil;
static BOOL debugOn = NO;
SOGoSystemDefaults *sd;
WOResponse *resp;
NSDate *startDate;
NSString *path;
NSTimeInterval timeDelta;
if (debugRequests)
@@ -440,7 +436,6 @@ static BOOL debugLeaks;
startDate = [NSDate date];
}
sd = [SOGoSystemDefaults sharedSystemDefaults];
cache = [SOGoCache sharedCache];
#ifdef GNUSTEP_BASE_LIBRARY
if (debugLeaks)
@@ -455,64 +450,6 @@ static BOOL debugLeaks;
}
#endif
// We check for rate-limiting settings - ignore anything actually
// sent to /SOGo/ (so unauthenticated requests).
path = [_request requestHandlerPath];
if ([path length] && [sd maximumRequestCount] > 0)
{
NSDictionary *requestCount;
NSString *username;
NSRange r;
r = [path rangeOfString: @"/"];
// We handle /sogo1/Calendar/.../ and "sogo1" as paths
if (r.length)
username = [path substringWithRange: NSMakeRange(0, r.location)];
else
username = path;
requestCount = [cache requestCountForLogin: username];
if (requestCount)
{
unsigned int current_time, start_time, delta, block_time, request_count;
current_time = [[NSCalendarDate date] timeIntervalSince1970];
start_time = [[requestCount objectForKey: @"InitialDate"] unsignedIntValue];
delta = current_time - start_time;
block_time = [sd requestBlockInterval];
request_count = [[requestCount objectForKey: @"RequestCount"] intValue];
if ( request_count >= [sd maximumRequestCount] &&
delta < [sd maximumRequestInterval] &&
delta <= block_time )
{
resp = [WOResponse responseWithRequest: _request];
[resp setStatus: 429];
return resp;
}
if (delta > block_time)
{
[cache setRequestCount: 1
forLogin: username
interval: current_time];
}
else
[cache setRequestCount: (request_count+1)
forLogin: username
interval: start_time];
}
else
{
[cache setRequestCount: 1
forLogin: username
interval: 0];
}
}
resp = [super dispatchRequest: _request];
[cache killCache];
+5 -189
View File
@@ -1,195 +1,12 @@
2.3.10 (2016-04-05)
-------------------
New features
- new user-based rate-limiting support for all SOGo requests (#3188)
Bug fixes
- respect the LDAP attributes mapping in the list view
- handle empty body data when forwarding mails (#3581)
- correctly set EAS message class for S/MIME messages (#3576)
- we now handle the default classifications for tasks (#3541)
- handle FilterType changes using EAS (#3543)
- handle Dovecot's mail_shared_explicit_inbox parameter when using EAS
- prevent concurrent Sync ops from same EAS device (#3603)
- handle EAS loop termination when SOGo is being shutdown (#3604)
- avoid marking mails as read when archiving a folder (#2792)
- now cache heartbeat interval and folders list during EAS Ping ops (#3606)
- sanitize non-us-ascii 7bit emails when using EAS (#3592)
2.3.9 (2016-03-16)
2.3.x (2015-MM-DD)
------------------
New features
- you can now limit the file upload size using the WOMaxUploadSize
configuration parameter (integer value in kilobytes) (#3510, #3135)
Enhancements
- allow resources to prevent invitations (#3410)
- now support EAS MIME truncation
- added Lithuanan (lt) translation - thanks to Mantas Liobė
Bug fixes
- allow EAS attachments get on 2nd-level mailboxes (#3505)
- fixed EAS bday shift (#3518)
- prefer SOGoRefreshViewCheck to SOGoMailMessageCheck (#3465)
- properly unfold long mail headers (#3152)
2.3.8 (2016-02-05)
------------------
Enhancements
- updated CKEditor to version 4.5.7
Bug fixes
- correctly encode filename of attachments over EAS (#3491)
- correctly encode square brackets for IMAP folder names (#3321)
- add shared/public namespaces in the list or returned folders
2.3.7 (2016-01-25)
------------------
New features
- new junk/not junk capability with generic SMTP integration
Enhancements
- newly created folders using EAS are always sync'ed by default (#3454)
- added Croatian (hr_HR) translation - thanks to Jens Riecken
Bug fixes
- now always generate invitation updates when using EAS
- rewrote the string sanitization to be 32-bit Unicode safe
- do not try to decode non-wbxml responses for debug output (#3444)
2.3.6 (2016-01-18)
------------------
New features
- now able to sync only default mail folders when using EAS
Enhancements
- unit testing for RTFHandler
- JUnit output for sogo-tests
Bug fixes
- don't unescape twice mail folder names (#3423)
- don't consider mobile Outlook EAS clients as DAV ones (#3431)
- we now follow 301 redirects when fetching ICS calendars
- when deleting an event using EAS, properly invoke the auto-scheduling code
- do not include failure attachments (really long filenames)
- fix encoding of email subjects with non-ASCII characters
- fix appointment notification mails using SOGoEnableDomainBasedUID configuration
- fix shifts in event times on Outlook
2.3.5 (2016-01-05)
------------------
Enhancements
- return an error to openchange if mail message delivery fails
- return the requested elements on complex requests from Outlook when downloading changes
- user sources can be loaded dynamically
- unify user sources API
- updated Russian translation (#3383)
Bug fixes
- properly compute the last week number for the year (#1010)
- share calendar, tasks and contacts folders in Outlook 2013 with editor permissions
- priorize filename in Content-Disposition against name in Content-Type to get the filename of an attachment in mail
- request all contacts when there is no filter in Contacts menu in Webmail
- personal contacts working properly on Outlook
- fixes on RTF parsing used by event/contact description and mail as RTF to read non-ASCII characters:
better parsing of font table, when using a font, switch to its character set, correct parsing of
escaped characters and Unicode character command word support for unicode characters greater than 32767
- no crash resolving recipients after reconnecting LDAP connection
- avoid creation of phantom contacts in SOGo from distribution list synced from Outlook.
- accepted & updated event names are now shown correctly in Outlook
- provide safe guards in mail and calendar to avoid exceptions while syncing
2.3.4 (2015-12-15)
------------------
New features
- initial support for EAS calendar exceptions
Enhancements
- limit the maximum width of toolbar buttons (#3381)
- updated CKEditor to version 4.5.6
Bug fixes
- JavaScript exception when printing events from calendars with no assigned color (#3203)
- EAS fix for wrong charset being used (#3392)
- EAS fix on qp-encoded subjects (#3390)
- correctly handle all-day event exceptions when the master event changes
- prevent characters in calendar component UID causing issues during import process
- avoid duplicating attendees when accepting event using a different identity over CalDAV
2.3.3a (2015-11-18)
-------------------
Bug fixes
- expanded mail folders list is not saved (#3386)
- cleanup translations
2.3.3 (2015-11-11)
------------------
New features
- initial S/MIME support for EAS (#3327)
- now possible to choose which folders to sync over EAS
Enhancements
- we no longer always entirely rewrite messages for Outlook 2013 when using EAS
- support for ghosted elements on contacts over EAS
- added Macedonian (mk_MK) translation - thanks to Miroslav Jovanovic
- added Portuguese (pt) translation - thanks to Eduardo Crispim
Bug fixes
- numerous EAS fixes when connections are dropped before the EAS client receives the response (#3058, #2849)
- correctly handle the References header over EAS (#3365)
- make sure English is always used when generating Date headers using EAS (#3356)
- don't escape quoted strings during versit generation
- we now return all cards when we receive an empty addressbook-query REPORT
- avoid crash when replying to a mail with no recipients (#3359)
- inline images sent from SOGo webmail are not displayed in Mozilla Thunderbird (#3271)
- prevent postal address showing on single line over EAS (#2614)
- display missing events when printing working hours only
- fix corner case making server crash when syncing hard deleted messages when clear offline items was set up (Zentyal)
- avoid infinite Outlook client loops trying to set read flag when it is already set (Zentyal)
- avoid crashing when calendar metadata is missing in the cache (Zentyal)
- fix recurrence pattern event corner case created by Mozilla Thunderbird which made server crash (Zentyal)
- fix corner case that removes attachments on sending messages from Outlook (Zentyal)
- freebusy on web interface works again in multidomain environments (Zentyal)
- fix double creation of folders in Outlook when the folder name starts with a digit (Zentyal)
- avoid crashing Outlook after setting a custom view in a calendar folder (Zentyal)
- handle emails having an attachment as their content
- fixed JavaScript syntax error in attendees editor
- fixed wrong comparison of meta vs. META tag in HTML mails
- fixed popup menu position when moved to the left (#3381)
- fixed dialog position when at the bottom of the window (#2646, #3378)
2.3.2 (2015-09-16)
------------------
Enhancements
- improved EAS speed and memory usage, avoiding many IMAP LIST commands (#3294)
- improved EAS speed during initial syncing of large mailboxes (#3293)
- updated CKEditor to version 4.5.3
Bug fixes
- fixed display of whitelisted attendees in Preferences window on Firefox (#3285)
- non-latin subfolder names are displayed correctly on Outlook (Zentyal)
- fixed several sync issues on environments with multiple users (Zentyal)
- folders from other users will no longer appear on your Outlook (Zentyal)
- use right auth in multidomain environments in contacts and calendar from Outlook (Zentyal)
- session fix when SOGoEnableDomainBasedUID is enabled but logins are domain-less
- less sync issues when setting read flag (Zentyal)
- attachments with non-latin filenames sent by Outlook are now received (Zentyal)
- support attachments from more mail clients (Zentyal)
- avoid conflicting message on saving a draft mail (Zentyal)
- less conflicting messages in Outlook while moving messages between folders (Zentyal)
- start/end shifting by 1 hour due to timezone change on last Sunday of October 2015 (#3344)
- fixed localization of calendar categories with empty profile (#3295)
- fixed options availability in contextual menu of Contacts module (#3342)
- Non-latin subfolder names are displayed correctly on Outlook (Zentyal)
- Fixed several sync issues on environments with multiple users (Zentyal)
- Folders from other users will no longer appear on your Outlook (Zentyal)
- Use right auth in multidomain environments in contacts and calendar from Outlook (Zentyal)
2.3.1 (2015-07-23)
------------------
@@ -202,7 +19,6 @@ Enhancements
- added create-folder subcommand to sogo-tool to create contact and calendar folders
- group mail addresses can be used as recipient in Outlook
- added 'ActiveSync' module constraints
- updated CKEditor to version 4.5.1
- added Slovenian translation - thanks to Jens Riecken
- added Chinese (Taiwan) translation
+1 -2
View File
@@ -145,8 +145,7 @@ $(DBMSGREADER_TOOL)_LIB_DIRS += \
-L../SoObjects/SOGo/SOGo.framework/sogo -lSOGo \
-L../SOPE/GDLContentStore/obj/ -lGDLContentStore \
-L../SOPE/NGCards/obj/ -lNGCards \
-lNGObjWeb \
$(LIBMAPI_LIBS)
-lNGObjWeb
TEST_TOOL_NAME += $(PLREADER_TOOL) $(DBMSGREADER_TOOL)
+3 -2
View File
@@ -24,7 +24,6 @@
#define MAPISTORECALENDARWRAPPER_H
#import <NGCards/iCalPerson.h>
#import <NGCards/iCalTimeZone.h>
#import <Appointments/iCalEntityObject+SOGo.h>
#import "MAPIStoreObjectProxy.h"
@@ -43,7 +42,7 @@
iCalCalendar *calendar;
iCalEvent *firstEvent;
iCalEvent *event;
iCalTimeZone *timeZone;
NSTimeZone *timeZone;
SOGoUser *user;
NSString *senderEmail;
NSData *globalObjectId;
@@ -58,10 +57,12 @@
+ (id) wrapperWithICalEvent: (iCalEvent *) newEvent
andUser: (SOGoUser *) newUser
andSenderEmail: (NSString *) newSenderEmail
inTimeZone: (NSTimeZone *) newTimeZone
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo;
- (id) initWithICalEvent: (iCalEvent *) newEvent
andUser: (SOGoUser *) newUser
andSenderEmail: (NSString *) newSenderEmail
inTimeZone: (NSTimeZone *) newTimeZone
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo;
/* getters */
+106 -49
View File
@@ -37,9 +37,7 @@
#import <NGCards/iCalEventChanges.h>
#import <NGCards/iCalPerson.h>
#import <NGCards/iCalTrigger.h>
#import <NGCards/iCalTimeZonePeriod.h>
#import <NGCards/NSString+NGCards.h>
#import <SOGo/SOGoDomainDefaults.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserManager.h>
@@ -82,6 +80,7 @@ static NSCharacterSet *hexCharacterSet = nil;
+ (id) wrapperWithICalEvent: (iCalEvent *) newEvent
andUser: (SOGoUser *) newUser
andSenderEmail: (NSString *) newSenderEmail
inTimeZone: (NSTimeZone *) newTimeZone
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo
{
MAPIStoreAppointmentWrapper *wrapper;
@@ -89,6 +88,7 @@ static NSCharacterSet *hexCharacterSet = nil;
wrapper = [[self alloc] initWithICalEvent: newEvent
andUser: newUser
andSenderEmail: newSenderEmail
inTimeZone: newTimeZone
withConnectionInfo: newConnInfo];
[wrapper autorelease];
@@ -182,10 +182,10 @@ static NSCharacterSet *hexCharacterSet = nil;
- (id) initWithICalEvent: (iCalEvent *) newEvent
andUser: (SOGoUser *) newUser
andSenderEmail: (NSString *) newSenderEmail
inTimeZone: (NSTimeZone *) newTimeZone
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo
{
NSArray *events;
iCalTimeZone *tz;
if ((self = [self init]))
{
@@ -194,20 +194,9 @@ static NSCharacterSet *hexCharacterSet = nil;
event = newEvent;
events = [calendar events];
firstEvent = [events objectAtIndex: 0];
ASSIGN (timeZone, newTimeZone);
ASSIGN (user, newUser);
ASSIGN (senderEmail, newSenderEmail);
/* If newEvent comes from the client, we set its time zone in
updateFromMAPIProperties. If it is not present, we use the
time zone of the user */
tz = (iCalTimeZone *) [calendar firstChildWithTag: @"vtimezone"];
if (!tz)
{
tz = [iCalTimeZone timeZoneForName: [[[user userDefaults] timeZone] name]];
if (!tz)
[self logWithFormat: @"no time zone could be set"];
}
ASSIGN (timeZone, tz);
[self _setupITIPContext];
}
@@ -277,7 +266,7 @@ static NSCharacterSet *hexCharacterSet = nil;
{
username = [contactInfos objectForKey: @"sAMAccountName"];
recipient->username = [username asUnicodeInMemCtx: msgData];
entryId = MAPIStoreInternalEntryId (connInfo, username);
entryId = MAPIStoreInternalEntryId (connInfo->sam_ctx, username);
}
else
{
@@ -378,7 +367,7 @@ static NSCharacterSet *hexCharacterSet = nil;
{
username = [contactInfos objectForKey: @"sAMAccountName"];
recipient->username = [username asUnicodeInMemCtx: msgData];
entryId = MAPIStoreInternalEntryId (connInfo, username);
entryId = MAPIStoreInternalEntryId (connInfo->sam_ctx, username);
}
else
{
@@ -732,15 +721,22 @@ static NSCharacterSet *hexCharacterSet = nil;
inMemCtx: (TALLOC_CTX *) memCtx
{
NSCalendarDate *dateValue;
NSInteger offset;
// if ([event isRecurrent])
// dateValue = [event firstRecurrenceStartDate];
// else
dateValue = [event startDate];
if ([event isAllDay])
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
{
offset = -[timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
}
[dateValue setTimeZone: utcTZ];
*data = [dateValue asFileTimeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
@@ -753,14 +749,22 @@ static NSCharacterSet *hexCharacterSet = nil;
exceptions, where it is the normal start date for the day of the
exception. */
NSCalendarDate *dateValue;
NSInteger offset;
dateValue = [event recurrenceId];
if (!dateValue)
dateValue = [event startDate];
[dateValue setTimeZone: timeZone];
if ([event isAllDay])
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
{
offset = -[timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
}
[dateValue setTimeZone: utcTZ];
*data = [dateValue asFileTimeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
@@ -768,12 +772,19 @@ static NSCharacterSet *hexCharacterSet = nil;
inMemCtx: (TALLOC_CTX *) memCtx
{
NSCalendarDate *dateValue;
NSInteger offset;
dateValue = [firstEvent startDate];
if ([firstEvent isAllDay])
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
{
offset = -[timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
}
[dateValue setTimeZone: utcTZ];
*data = [dateValue asFileTimeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
@@ -793,8 +804,8 @@ static NSCharacterSet *hexCharacterSet = nil;
month: [start monthOfYear]
day: [start dayOfMonth]
hour: 0 minute: 0 second: 0
timeZone: utcTZ];
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
timeZone: timeZone];
[dateValue setTimeZone: utcTZ];
*data = [dateValue asFileTimeInMemCtx: memCtx];
rc = MAPISTORE_SUCCESS;
}
@@ -818,7 +829,7 @@ static NSCharacterSet *hexCharacterSet = nil;
dateValue = [event startDate];
offset = [event durationAsTimeInterval];
if ([event isAllDay])
offset -= [[timeZone periodForDate: dateValue] secondsOffsetFromGMT];
offset -= [timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
@@ -836,14 +847,15 @@ static NSCharacterSet *hexCharacterSet = nil;
dateValue = [event recurrenceId];
if (!dateValue)
dateValue = [event startDate];
[dateValue setTimeZone: timeZone];
offset = [firstEvent durationAsTimeInterval];
if ([firstEvent isAllDay])
offset -= [[timeZone periodForDate: dateValue] secondsOffsetFromGMT];
offset -= [timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
*data = [dateValue asFileTimeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
@@ -859,7 +871,7 @@ static NSCharacterSet *hexCharacterSet = nil;
dateValue = [firstEvent startDate];
offset = [firstEvent durationAsTimeInterval];
if ([event isAllDay])
offset -= [[timeZone periodForDate: dateValue] secondsOffsetFromGMT];
offset -= [timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
@@ -873,14 +885,23 @@ static NSCharacterSet *hexCharacterSet = nil;
{
enum mapistore_error rc;
NSCalendarDate *dateValue;
NSInteger offset;
iCalRecurrenceRule *rrule;
if ([event isRecurrent])
{
rrule = [[event recurrenceRules] objectAtIndex: 0];
dateValue = [rrule untilDate];
if (dateValue && [event isAllDay])
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
if (dateValue)
{
if ([event isAllDay])
offset = -[timeZone secondsFromGMTForDate: dateValue];
else
offset = 0;
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
}
else
dateValue = [NSCalendarDate dateWithYear: 4500 month: 8 day: 31
hour: 23 minute: 59 second: 00
@@ -911,7 +932,7 @@ static NSCharacterSet *hexCharacterSet = nil;
if (contactInfos)
{
username = [contactInfos objectForKey: @"sAMAccountName"];
entryId = MAPIStoreInternalEntryId (connInfo, username);
entryId = MAPIStoreInternalEntryId (connInfo->sam_ctx, username);
}
else
entryId = MAPIStoreExternalEntryId (cn, email);
@@ -1317,14 +1338,21 @@ static NSCharacterSet *hexCharacterSet = nil;
{
enum mapistore_error rc;
NSCalendarDate *dateValue;
NSInteger offset;
dateValue = [event recurrenceId];
if (dateValue)
{
rc = MAPISTORE_SUCCESS;
if ([event isAllDay])
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
{
offset = -[timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
}
[dateValue setTimeZone: utcTZ];
*data = [dateValue asFileTimeInMemCtx: memCtx];
}
else
@@ -1349,6 +1377,7 @@ static NSCharacterSet *hexCharacterSet = nil;
iCalEventChanges *changes;
NSArray *changedProperties;
NSCalendarDate *dateValue;
NSInteger offset;
changes = [iCalEventChanges changesFromEvent: event toEvent: exceptionEvent];
@@ -1356,17 +1385,28 @@ static NSCharacterSet *hexCharacterSet = nil;
memset (extendedException, 0, sizeof (struct ExtendedException));
extendedException->ChangeHighlight.Size = sizeof (uint32_t);
dateValue = [timeZone computedDateForDate: [exceptionEvent startDate]];
dateValue = [exceptionEvent startDate];
offset = [timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
exceptionInfo->StartDateTime = [dateValue asMinutesSince1601];
extendedException->ChangeHighlight.Value = BIT_CH_START;
extendedException->StartDateTime = exceptionInfo->StartDateTime;
dateValue = [timeZone computedDateForDate: [exceptionEvent endDate]];
dateValue = [exceptionEvent endDate];
offset = [timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
exceptionInfo->EndDateTime = [dateValue asMinutesSince1601];
extendedException->ChangeHighlight.Value |= BIT_CH_END;
extendedException->EndDateTime = exceptionInfo->EndDateTime;
dateValue = [timeZone computedDateForDate: [exceptionEvent recurrenceId]];
dateValue = [[exceptionEvent recurrenceId]
dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
exceptionInfo->OriginalStartDate = [dateValue asMinutesSince1601];
extendedException->OriginalStartDate = exceptionInfo->OriginalStartDate;
@@ -1424,6 +1464,7 @@ static NSCharacterSet *hexCharacterSet = nil;
arp = talloc_zero (NULL, struct AppointmentRecurrencePattern);
[rule fillRecurrencePattern: &arp->RecurrencePattern
withEvent: event
inTimeZone: timeZone
inMemCtx: arp];
arp->ReaderVersion2 = 0x00003006;
arp->WriterVersion2 = 0x00003008; /* 0x3008 for compatibility with
@@ -1434,7 +1475,7 @@ static NSCharacterSet *hexCharacterSet = nil;
fields are relative to midnight of those days ([MS-OXOCAL] 2.2.1.44.5),
so no time zone adjustment is needed */
if (![event isAllDay])
firstStartDate = [timeZone computedDateForDate: firstStartDate];
[firstStartDate setTimeZone: timeZone];
startMinutes = ([firstStartDate hourOfDay] * 60
+ [firstStartDate minuteOfHour]);
arp->StartTimeOffset = startMinutes;
@@ -1660,16 +1701,15 @@ ReservedBlockEE2Size: 00 00 00 00
fromDate: (NSCalendarDate *) instanceDate;
{
uint16_t year;
NSCalendarDate *dateValue;
if (instanceDate)
{
dateValue = [timeZone computedDateForDate: instanceDate];
year = [dateValue yearOfCommonEra];
[instanceDate setTimeZone: timeZone];
year = [instanceDate yearOfCommonEra];
newGlobalId->YH = year >> 8;
newGlobalId->YL = year & 0xff;
newGlobalId->Month = [dateValue monthOfYear];
newGlobalId->D = [dateValue dayOfMonth];
newGlobalId->Month = [instanceDate monthOfYear];
newGlobalId->D = [instanceDate dayOfMonth];
}
}
@@ -1934,6 +1974,7 @@ ReservedBlockEE2Size: 00 00 00 00
if (alarm)
{
alarmDate = [alarm nextAlarmDate];
[alarmDate setTimeZone: utcTZ];
*data = [alarmDate asFileTimeInMemCtx: memCtx];
}
else
@@ -1995,7 +2036,8 @@ ReservedBlockEE2Size: 00 00 00 00
enum mapistore_error rc;
NSString *tzid;
tzid = [timeZone tzId];
tzid = [(iCalDateTime *) [event firstChildWithTag: @"dtstart"]
value: 0 ofAttribute: @"tzid"];
if ([tzid length] > 0)
{
*data = [tzid asUnicodeInMemCtx: memCtx];
@@ -2011,9 +2053,16 @@ ReservedBlockEE2Size: 00 00 00 00
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
iCalTimeZone *icalTZ;
*data = [timeZone asTimeZoneStructInMemCtx: memCtx];
rc = MAPISTORE_SUCCESS;
icalTZ = [(iCalDateTime *) [event firstChildWithTag: @"dtstart"] timeZone];
if (icalTZ)
{
*data = [icalTZ asTimeZoneStructInMemCtx: memCtx];
rc = MAPISTORE_SUCCESS;
}
else
rc = MAPISTORE_ERR_NOT_FOUND;
return rc;
}
@@ -2022,16 +2071,24 @@ ReservedBlockEE2Size: 00 00 00 00
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
iCalTimeZone *icalTZ;
/* [MS-OXOCAL] 3.1.5.5.1: This property is used in floating (all-day) events,
specified in floating time, to convert the start date from UTC to the user's
time zone */
if ([event isAllDay] | [event isRecurrent])
if ([event isAllDay])
icalTZ = [iCalTimeZone timeZoneForName: [timeZone timeZoneName]];
else if ([event isRecurrent])
icalTZ = [(iCalDateTime *) [event firstChildWithTag: @"dtstart"] timeZone];
else
icalTZ = nil;
if (icalTZ)
{
/* [MS-OXOCAL] 2.2.1.42: This property can only have the E flag set in the
TimeZoneDefinition struct */
*data = [timeZone asZoneTimeDefinitionWithFlags: TZRULE_FLAG_EFFECTIVE_TZREG
inMemCtx: memCtx];
*data = [icalTZ asZoneTimeDefinitionWithFlags: TZRULE_FLAG_EFFECTIVE_TZREG
inMemCtx: memCtx];
rc = MAPISTORE_SUCCESS;
}
else
-3
View File
@@ -46,9 +46,6 @@
forURL: (NSURL *) server
forceRenew: (BOOL) renew;
- (NSString *) passwordInContext: (WOContext *) context;
@end
#endif /* MAPISTOREAUTHENTICATOR_H */
-4
View File
@@ -72,8 +72,4 @@
return imapPassword;
}
- (NSString *) passwordInContext: (WOContext *) context
{
return password;
}
@end
@@ -58,6 +58,7 @@
wrapperWithICalEvent: [newContainer event]
andUser: [userContext sogoUser]
andSenderEmail: nil
inTimeZone: [userContext timeZone]
withConnectionInfo: [context connectionInfo]];
[self addProxy: appointmentWrapper];
}
+3 -14
View File
@@ -77,17 +77,6 @@
- (NSArray *) rolesForExchangeRights: (uint32_t) rights
{
/* Limitations
Following rights are not supported by SOGo specifically:
- DeleteOwned : Delete only own objects
- EditOwned : Edit only own objects
- CreateSubfolders: No calendar subfolders
- FolderOwner: No sharing folder ownership?
- FolderContact: No support to store this information
- FolderVisible: It is inferred by other rights when extracting
*/
NSMutableArray *roles;
roles = [NSMutableArray arrayWithCapacity: 6];
@@ -128,11 +117,11 @@
if ([roles containsObject: SOGoRole_ObjectCreator])
rights |= RightsCreateItems;
if ([roles containsObject: SOGoRole_ObjectEraser])
rights |= RightsDeleteAll | RightsDeleteOwn;
rights |= RightsDeleteAll;
if ([roles containsObject: SOGoCalendarRole_PublicModifier]
&& [roles containsObject: SOGoCalendarRole_PrivateModifier]
&& [roles containsObject: SOGoCalendarRole_ConfidentialModifier])
rights |= RightsReadItems | RightsEditAll | RightsEditOwn | RightsFreeBusySimple | RightsFreeBusyDetailed;
rights |= RightsReadItems | RightsEditAll;
else if ([roles containsObject: SOGoCalendarRole_PublicViewer]
&& [roles containsObject: SOGoCalendarRole_PrivateViewer]
&& [roles containsObject: SOGoCalendarRole_ConfidentialViewer])
@@ -146,7 +135,7 @@
if ([roles containsObject: SOGoCalendarRole_ConfidentialDAndTViewer])
rights |= RightsFreeBusyDetailed;
if ((rights & RightsReadItems) != 0 || (rights & RightsCreateItems) != 0 || (rights & RightsDeleteAll) != 0)
if (rights != 0)
rights |= RoleNone; /* actually "folder visible" */
// [self logWithFormat: @"rights for roles (%@) = %.8x", roles, rights];
+2 -1
View File
@@ -197,6 +197,7 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
= [MAPIStoreAppointmentWrapper wrapperWithICalEvent: masterEvent
andUser: [userContext sogoUser]
andSenderEmail: nil
inTimeZone: [userContext timeZone]
withConnectionInfo: [context connectionInfo]];
[self addProxy: appointmentWrapper];
}
@@ -670,7 +671,7 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
return newAttachment;
}
- (enum mapistore_error) setReadFlag: (uint8_t) flag
- (int) setReadFlag: (uint8_t) flag
{
return MAPISTORE_SUCCESS;
}
+2 -2
View File
@@ -96,9 +96,9 @@
if ([roles containsObject: SOGoRole_ObjectCreator])
rights |= RightsCreateItems;
if ([roles containsObject: SOGoRole_ObjectEraser])
rights |= RightsDeleteAll | RightsDeleteOwn;
rights |= RightsDeleteAll;
if ([roles containsObject: SOGoRole_ObjectEditor])
rights |= RightsEditAll | RightsEditOwn;
rights |= RightsEditAll;
if ([roles containsObject: SOGoRole_ObjectViewer])
rights |= RightsReadItems;
if (rights != 0)
File diff suppressed because it is too large. Load diff
+3 -3
View File
@@ -102,7 +102,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
{
value = get_SPropValue_SRow (aRow, PidTagDisplayName_string8);
if (value)
folderName = [NSString stringWithUTF8String: (const char *) value->value.lpszA];
folderName = [NSString stringWithUTF8String: value->value.lpszA];
else
folderName = nil;
}
@@ -321,9 +321,9 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
if ([roles containsObject: MAPIStoreRightDeleteOwn])
rights |= RightsDeleteOwn;
if ([roles containsObject: MAPIStoreRightEditAll])
rights |= RightsEditAll | RightsEditOwn;
rights |= RightsEditAll;
if ([roles containsObject: MAPIStoreRightDeleteAll])
rights |= RightsDeleteAll | RightsDeleteOwn;
rights |= RightsDeleteAll;
if ([roles containsObject: MAPIStoreRightCreateSubfolders])
rights |= RightsCreateSubfolders;
if ([roles containsObject: MAPIStoreRightFolderOwner])
+14 -227
View File
@@ -22,7 +22,6 @@
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
@@ -35,7 +34,6 @@
#import "MAPIStoreDBFolder.h"
#import "MAPIStoreDBMessage.h"
#import "MAPIStoreTypes.h"
#import "NSData+MAPIStore.h"
#import "NSObject+MAPIStore.h"
#import "NSString+MAPIStore.h"
@@ -45,28 +43,16 @@
@implementation MAPIStoreDBMessage
+ (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP
inMemCtx: (TALLOC_CTX *) memCtx
+ (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
inMemCtx: (TALLOC_CTX *) memCtx
{
struct SPropTagArray *properties;
NSUInteger count;
enum MAPITAGS faiProperties[] = {
0x68330048, /* PR_VIEW_CLSID */
0x68350102, /* PR_VIEW_STATE */
0x683c0102,
0x683d0040,
0x683e0102,
0x683f0102, /* PR_VIEW_VIEWTYPE_KEY */
0x68410003,
0x68420102,
0x68450102,
0x68460003,
0x7006001F, /* PR_VD_NAME_W */
0x70030003, /* PR_VD_FLAGS */
0x70070003 /* PR_VD_VERSION */
};
enum MAPITAGS faiProperties[] = { 0x68350102, 0x683c0102, 0x683e0102,
0x683f0102, 0x68410003, 0x68420102,
0x68450102, 0x68460003,
// PR_VD_NAME_W, PR_VD_FLAGS, PR_VD_VERSION, PR_VIEW_CLSID
0x7006001F, 0x70030003, 0x70070003, 0x68330048 };
size_t faiSize = sizeof(faiProperties) / sizeof(enum MAPITAGS);
properties = talloc_zero (memCtx, struct SPropTagArray);
@@ -88,13 +74,6 @@
return MAPISTORE_SUCCESS;
}
- (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP
inMemCtx: (TALLOC_CTX *) memCtx
{
return [[self class] getAvailableProperties: propertiesP
inMemCtx: memCtx];
}
- (id) initWithSOGoObject: (id) newSOGoObject
inContainer: (MAPIStoreObject *) newContainer
{
@@ -109,173 +88,22 @@
return self;
}
- (NSString *) description
{
id key, value;
NSEnumerator *propEnumerator;
NSMutableString *description;
description = [NSMutableString stringWithFormat: @"%@ %@. Properties: {", NSStringFromClass ([self class]),
[self url]];
propEnumerator = [properties keyEnumerator];
while ((key = [propEnumerator nextObject]))
{
uint32_t proptag = 0;
if ([key isKindOfClass: [NSString class]] && [(NSString *)key intValue] > 0)
proptag = [(NSString *)key intValue];
else if ([key isKindOfClass: [NSNumber class]])
proptag = [key unsignedLongValue];
if (proptag > 0)
{
const char *propTagName = get_proptag_name ([key unsignedLongValue]);
NSString *propName;
if (propTagName)
propName = [NSString stringWithCString: propTagName
encoding: NSUTF8StringEncoding];
else
propName = [NSString stringWithFormat: @"0x%.4x", [key unsignedLongValue]];
[description appendFormat: @"'%@': ", propName];
}
else
[description appendFormat: @"'%@': ", key];
value = [properties objectForKey: key];
[description appendFormat: @"%@ (%@), ", value, NSStringFromClass ([value class])];
}
[description appendString: @"}\n"];
return description;
}
- (uint64_t) objectVersion
{
/* Return the global counter from CN structure.
See [MS-OXCFXICS] Section 2.2.2.1 */
NSNumber *versionNbr, *cn;
NSNumber *versionNbr;
uint64_t objectVersion;
[(SOGoMAPIDBMessage *) sogoObject reloadIfNeeded];
versionNbr = [properties objectForKey: @"version_number"];
versionNbr = [properties objectForKey: @"version"];
if (versionNbr)
objectVersion = exchange_globcnt ([versionNbr unsignedLongLongValue]);
objectVersion = (([versionNbr unsignedLongLongValue] >> 16)
& 0x0000ffffffffffffLL);
else
{
/* Old version which stored the CN structure not useful for searching */
cn = [properties objectForKey: @"version"];
if (cn)
objectVersion = (([cn unsignedLongLongValue] >> 16)
& 0x0000ffffffffffffLL);
else
objectVersion = ULLONG_MAX;
}
objectVersion = ULLONG_MAX;
return objectVersion;
}
- (void) _updatePredecessorChangeList
{
BOOL updated;
enum mapistore_error rc;
NSData *currentChangeList, *changeKey;
NSMutableArray *changeKeys;
NSMutableData *newChangeList;
NSUInteger count, len;
struct SizedXid *changes;
struct SPropValue property;
struct SRow aRow;
struct XID *currentChangeKey;
TALLOC_CTX *localMemCtx;
uint32_t nChanges;
localMemCtx = talloc_new (NULL);
if (!localMemCtx)
{
[self errorWithFormat: @"No more memory"];
return;
}
changeKey = [self getReplicaKeyFromGlobCnt: [self objectVersion]];
currentChangeList = [properties objectForKey: MAPIPropertyKey (PidTagPredecessorChangeList)];
if (!currentChangeList)
{
/* Create a new PredecessorChangeList */
len = [changeKey length];
newChangeList = [NSMutableData dataWithCapacity: len + 1];
[newChangeList appendUInt8: len];
[newChangeList appendData: changeKey];
}
else
{
/* Update current predecessor change list with new change key */
changes = [currentChangeList asSizedXidArrayInMemCtx: localMemCtx
with: &nChanges];
updated = NO;
currentChangeKey = [changeKey asXIDInMemCtx: localMemCtx];
for (count = 0; count < nChanges && !updated; count++)
{
if (GUID_equal(&changes[count].XID.NameSpaceGuid, &currentChangeKey->NameSpaceGuid))
{
NSData *globCnt, *oldGlobCnt;
oldGlobCnt = [NSData dataWithBytes: changes[count].XID.LocalId.data length: changes[count].XID.LocalId.length];
globCnt = [NSData dataWithBytes: currentChangeKey->LocalId.data length: currentChangeKey->LocalId.length];
if ([globCnt compare: oldGlobCnt] == NSOrderedDescending)
{
if ([globCnt length] != [oldGlobCnt length])
{
[self errorWithFormat: @"Cannot compare globcnt with different length: %@ and %@", globCnt, oldGlobCnt];
abort();
}
memcpy (changes[count].XID.LocalId.data, currentChangeKey->LocalId.data, currentChangeKey->LocalId.length);
updated = YES;
}
}
}
/* Serialise it */
changeKeys = [NSMutableArray array];
if (!updated)
[changeKeys addObject: changeKey];
for (count = 0; count < nChanges; count++)
{
changeKey = [NSData dataWithXID: &changes[count].XID];
[changeKeys addObject: changeKey];
}
[changeKeys sortUsingFunction: MAPIChangeKeyGUIDCompare context: localMemCtx];
newChangeList = [NSMutableData data];
len = [changeKeys count];
for (count = 0; count < len; count++)
{
changeKey = [changeKeys objectAtIndex: count];
[newChangeList appendUInt8: [changeKey length]];
[newChangeList appendData: changeKey];
}
}
if ([newChangeList length] > 0)
{
property.ulPropTag = PidTagPredecessorChangeList;
property.value.bin = *[newChangeList asBinaryInMemCtx: localMemCtx];
aRow.cValues = 1;
aRow.lpProps = &property;
rc = [self addPropertiesFromRow: &aRow];
if (rc != MAPISTORE_SUCCESS)
[self errorWithFormat: @"Impossible to add a new predecessor change list: %d", rc];
}
talloc_free (localMemCtx);
}
//
// FIXME: how this can happen?
//
@@ -335,19 +163,10 @@
[properties setObject: attachmentParts forKey: @"attachments"];
newVersion = [[self context] getNewChangeNumber];
newVersion = exchange_globcnt ((newVersion >> 16) & 0x0000ffffffffffffLL);
[properties setObject: [NSNumber numberWithUnsignedLongLong: newVersion]
forKey: @"version_number"];
forKey: @"version"];
/* Remove old version */
[properties removeObjectForKey: @"version"];
/* Update PredecessorChangeList accordingly */
[self _updatePredecessorChangeList];
// [self logWithFormat: @"Saving %@", [self description]];
// [self logWithFormat: @"%d props in dict", [properties count]];
[self logWithFormat: @"%d props in dict", [properties count]];
[sogoObject save];
}
@@ -390,36 +209,4 @@
return [sogoObject lastModified];
}
- (enum mapistore_error) setReadFlag: (uint8_t) flag
{
/* Modify PidTagMessageFlags from SetMessageReadFlag and
SyncImportReadStateChanges ROPs */
NSNumber *flags;
uint32_t newFlag;
flags = [properties objectForKey: MAPIPropertyKey (PR_MESSAGE_FLAGS)];
if (flags)
{
newFlag = [flags unsignedLongValue];
if (flag & SUPPRESS_RECEIPT)
newFlag |= MSGFLAG_READ;
if (flag & CLEAR_RN_PENDING)
newFlag &= ~MSGFLAG_RN_PENDING;
if (flag & CLEAR_READ_FLAG)
newFlag &= ~MSGFLAG_READ;
if (flag & CLEAR_NRN_PENDING)
newFlag &= ~MSGFLAG_NRN_PENDING;
}
else
{
newFlag = MSGFLAG_READ;
if (flag & CLEAR_READ_FLAG)
newFlag = 0x0;
}
[properties setObject: [NSNumber numberWithUnsignedLong: newFlag]
forKey: MAPIPropertyKey (PR_MESSAGE_FLAGS)];
return MAPISTORE_SUCCESS;
}
@end
+4 -5
View File
@@ -61,15 +61,14 @@ static Class MAPIStoreDBMessageK = Nil;
if ((uint32_t) res->ulPropTag == PidTagChangeNumber)
{
SEL operator;
value = NSObjectFromMAPISPropValue (&res->lpProp);
cVersion = exchange_globcnt (([value unsignedLongLongValue] >> 16)
& 0x0000ffffffffffffLL);
version = [NSNumber numberWithUnsignedLongLong: cVersion];
operator = [self operatorFromRestrictionOperator: res->relop];
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"version_number"
operatorSelector: operator
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
[self logWithFormat: @" version: %.16lx", cVersion];
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"version"
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
value: version];
[*qualifier autorelease];
rc = MAPIRestrictionStateNeedsEval;
-1
View File
@@ -121,7 +121,6 @@
fromFolder: (MAPIStoreFolder *) sourceFolder
withMIDs: (uint64_t *) targetMids
andChangeKeys: (struct Binary_r **) targetChangeKeys
andPredecessorChangeLists: (struct Binary_r **) targetPredecessorChangeLists
wantCopy: (uint8_t) want_copy
inMemCtx: (TALLOC_CTX *) memCtx;
+11 -22
View File
@@ -642,7 +642,6 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
fromFolder: (MAPIStoreFolder *) sourceFolder
withMID: (uint64_t) targetMid
andChangeKey: (struct Binary_r *) targetChangeKey
andPredecessorChangeList: (struct Binary_r *) targetPredecessorChangeList
wantCopy: (uint8_t) wantCopy
inMemCtx: (TALLOC_CTX *) memCtx
{
@@ -670,18 +669,15 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
[sourceMsg copyToMessage: destMsg inMemCtx: memCtx];
if (targetPredecessorChangeList)
if (targetChangeKey)
{
property.ulPropTag = PidTagPredecessorChangeList;
property.value.bin = *targetPredecessorChangeList;
property.ulPropTag = PidTagChangeKey;
property.value.bin = *targetChangeKey;
aRow.cValues = 1;
aRow.lpProps = &property;
rc = [destMsg addPropertiesFromRow: &aRow];
if (rc != MAPISTORE_SUCCESS)
{
[self errorWithFormat: @"Cannot add PredecessorChangeList on move"];
goto end;
}
goto end;
}
[destMsg save: memCtx];
if (!wantCopy)
@@ -700,7 +696,6 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
fromFolder: (MAPIStoreFolder *) sourceFolder
withMIDs: (uint64_t *) targetMids
andChangeKeys: (struct Binary_r **) targetChangeKeys
andPredecessorChangeLists: (struct Binary_r **) targetPredecessorChangeLists
wantCopy: (uint8_t) wantCopy
inMemCtx: (TALLOC_CTX *) memCtx
{
@@ -710,7 +705,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
NSString *oldMessageURL;
MAPIStoreMapping *mapping;
SOGoUser *ownerUser;
struct Binary_r *targetChangeKey, *targetPredecessorChangeList;
struct Binary_r *targetChangeKey;
//TALLOC_CTX *memCtx;
//memCtx = talloc_zero (NULL, TALLOC_CTX);
@@ -731,21 +726,14 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
if (oldMessageURL)
{
[oldMessageURLs addObject: oldMessageURL];
if (targetChangeKeys && targetPredecessorChangeList)
{
targetChangeKey = targetChangeKeys[count];
targetPredecessorChangeList = targetPredecessorChangeLists[count];
}
if (targetChangeKeys)
targetChangeKey = targetChangeKeys[count];
else
{
targetChangeKey = NULL;
targetPredecessorChangeList = NULL;
}
targetChangeKey = NULL;
rc = [self _moveCopyMessageWithMID: srcMids[count]
fromFolder: sourceFolder
withMID: targetMids[count]
andChangeKey: targetChangeKey
andPredecessorChangeList: targetPredecessorChangeList
wantCopy: wantCopy
inMemCtx: memCtx];
}
@@ -1549,6 +1537,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
struct Binary_r bin32;
struct AddressBookEntryId *entryId;
NSString *username;
struct ldb_context *samCtx;
if (bin && bin->cb)
{
@@ -1558,8 +1547,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
entryId = get_AddressBookEntryId (NULL, &bin32);
if (entryId)
{
username = MAPIStoreSamDBUserAttribute ([[self context] connectionInfo],
@"legacyExchangeDN",
samCtx = [[self context] connectionInfo]->sam_ctx;
username = MAPIStoreSamDBUserAttribute (samCtx, @"legacyExchangeDN",
[NSString stringWithUTF8String: entryId->X500DN],
@"sAMAccountName");
}
+1 -3
View File
@@ -41,10 +41,8 @@
/* synchronisation */
- (BOOL) synchroniseCache;
- (BOOL) synchroniseCacheFor: (NSString *) nameInContainer;
- (void) updateVersionsForMessageWithKey: (NSString *) messageKey
withChangeKey: (NSData *) oldChangeKey
andPredecessorChangeList: (NSData *) pcl;
withChangeKey: (NSData *) newChangeKey;
- (NSNumber *) lastModifiedFromMessageChangeNumber: (NSString *) changeNumber;
- (NSString *) changeNumberForMessageWithKey: (NSString *) messageKey;
- (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey;
+21 -197
View File
@@ -75,7 +75,6 @@ static Class NSNumberK;
[SOGoMAPIDBMessage objectWithName: @"versions.plist"
inContainer: dbFolder]);
[versionsMessage setObjectType: MAPIInternalCacheObject];
[versionsMessage reloadIfNeeded];
}
- (void) dealloc
@@ -262,6 +261,7 @@ static Class NSNumberK;
*/
- (void) _setChangeKey: (NSData *) changeKey
forMessageEntry: (NSMutableDictionary *) messageEntry
inChangeListOnly: (BOOL) inChangeListOnly
{
struct XID *xid;
NSString *guid;
@@ -270,15 +270,19 @@ static Class NSNumberK;
NSMutableDictionary *changeList;
xid = [changeKey asXIDInMemCtx: NULL];
guid = [NSString stringWithGUID: &xid->NameSpaceGuid];
globCnt = [NSData dataWithBytes: xid->LocalId.data length: xid->LocalId.length];
guid = [NSString stringWithGUID: &xid->GUID];
globCnt = [NSData dataWithBytes: xid->Data length: xid->Size];
talloc_free (xid);
/* 1. set change key association */
changeKeyDict = [NSDictionary dictionaryWithObjectsAndKeys: guid, @"GUID",
globCnt, @"LocalId",
nil];
[messageEntry setObject: changeKeyDict forKey: @"ChangeKey"];
if (!inChangeListOnly)
{
/* 1. set change key association */
changeKeyDict = [NSDictionary dictionaryWithObjectsAndKeys:
guid, @"GUID",
globCnt, @"LocalId",
nil];
[messageEntry setObject: changeKeyDict forKey: @"ChangeKey"];
}
/* 2. append/update predecessor change list */
changeList = [messageEntry objectForKey: @"PredecessorChangeList"];
@@ -292,77 +296,6 @@ static Class NSNumberK;
[changeList setObject: globCnt forKey: guid];
}
- (void) _updatePredecessorChangeList: (NSData *) predecessorChangeList
forMessageEntry: (NSMutableDictionary *) messageEntry
withOldChangeKey: (NSData *) oldChangeKey
{
NSData *globCnt, *oldGlobCnt;
NSDictionary *changeKeyDict;
NSString *guid;
NSMutableDictionary *changeList;
struct SizedXid *sizedXIDList;
struct XID xid, *givenChangeKey;
TALLOC_CTX *localMemCtx;
uint32_t i, length;
localMemCtx = talloc_new (NULL);
if (!localMemCtx)
{
[self errorWithFormat: @"No more memory"];
return;
}
if (predecessorChangeList)
{
sizedXIDList = [predecessorChangeList asSizedXidArrayInMemCtx: localMemCtx with: &length];
changeList = [messageEntry objectForKey: @"PredecessorChangeList"];
if (!changeList)
{
changeList = [NSMutableDictionary new];
[messageEntry setObject: changeList
forKey: @"PredecessorChangeList"];
[changeList release];
}
if (sizedXIDList) {
for (i = 0; i < length; i++)
{
xid = sizedXIDList[i].XID;
guid = [NSString stringWithGUID: &xid.NameSpaceGuid];
globCnt = [NSData dataWithBytes: xid.LocalId.data length: xid.LocalId.length];
oldGlobCnt = [changeList objectForKey: guid];
if (!oldGlobCnt || ([globCnt compare: oldGlobCnt] == NSOrderedDescending))
[changeList setObject: globCnt forKey: guid];
}
}
}
if (oldChangeKey)
{
givenChangeKey = [oldChangeKey asXIDInMemCtx: localMemCtx];
if (givenChangeKey) {
guid = [NSString stringWithGUID: &givenChangeKey->NameSpaceGuid];
globCnt = [NSData dataWithBytes: givenChangeKey->LocalId.data length: givenChangeKey->LocalId.length];
changeKeyDict = [messageEntry objectForKey: @"ChangeKey"];
if (!changeKeyDict ||
([guid isEqualToString: [changeKeyDict objectForKey: @"GUID"]]
&& ([globCnt compare: [changeKeyDict objectForKey: @"LocalId"]] == NSOrderedDescending)))
{
/* The given change key is greater than current one stored in
metadata or it does not exist */
[messageEntry setObject: [NSDictionary dictionaryWithObjectsAndKeys: guid, @"GUID",
globCnt, @"LocalId",
nil]
forKey: @"ChangeKey"];
}
}
}
talloc_free (localMemCtx);
}
- (EOQualifier *) componentQualifier
{
if (!componentQualifier)
@@ -532,7 +465,8 @@ static Class NSNumberK;
// 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];
[self _setChangeKey: changeKey forMessageEntry: messageEntry
inChangeListOnly: NO];
}
now = [NSCalendarDate date];
@@ -548,123 +482,13 @@ static Class NSNumberK;
return rc;
}
- (BOOL) synchroniseCacheFor: (NSString *) nameInContainer
{
/* Try to synchronise old messages in versions.plist cache using an
specific c_name. It returns a boolean indicating if the
synchronisation was carried out succesfully.
It should be used as last resort, keeping synchroniseCache as the
main sync entry point. */
uint64_t changeNumber;
NSString *changeNumberStr;
NSData *changeKey;
NSNumber *cLastModified, *cDeleted, *cVersion;
EOFetchSpecification *fs;
EOQualifier *searchQualifier, *fetchQualifier;
NSArray *fetchResults;
NSDictionary *result;
NSMutableDictionary *currentProperties, *messages, *mapping, *messageEntry;
GCSFolder *ocsFolder;
static NSArray *fields;
[versionsMessage reloadIfNeeded];
currentProperties = [versionsMessage properties];
messages = [currentProperties objectForKey: @"Messages"];
if (!messages)
{
messages = [NSMutableDictionary new];
[currentProperties setObject: messages forKey: @"Messages"];
[messages release];
}
messageEntry = [messages objectForKey: nameInContainer];
if (!messageEntry)
{
/* Fetch the message by its name */
if (!fields)
fields = [[NSArray alloc]
initWithObjects: @"c_name", @"c_version", @"c_lastmodified",
@"c_deleted", nil];
searchQualifier = [[EOKeyValueQualifier alloc] initWithKey: @"c_name"
operatorSelector: EOQualifierOperatorEqual
value: nameInContainer];
fetchQualifier = [[EOAndQualifier alloc]
initWithQualifiers: searchQualifier,
[self contentComponentQualifier],
nil];
[fetchQualifier autorelease];
[searchQualifier release];
ocsFolder = [sogoObject ocsFolder];
fs = [EOFetchSpecification
fetchSpecificationWithEntityName: [ocsFolder folderName]
qualifier: fetchQualifier
sortOrderings: nil];
fetchResults = [ocsFolder fetchFields: fields
fetchSpecification: fs
ignoreDeleted: NO];
if ([fetchResults count] == 1)
{
result = [fetchResults objectAtIndex: 0];
cLastModified = [result objectForKey: @"c_lastmodified"];
cDeleted = [result objectForKey: @"c_deleted"];
if ([cDeleted isKindOfClass: NSNumberK] && [cDeleted intValue])
cVersion = [NSNumber numberWithInt: -1];
else
cVersion = [result objectForKey: @"c_version"];
changeNumber = [[self context] getNewChangeNumber];
changeNumberStr = [NSString stringWithUnsignedLongLong: changeNumber];
/* Create new message entry in Messages dict */
messageEntry = [NSMutableDictionary new];
[messages setObject: messageEntry forKey: nameInContainer];
[messageEntry release];
/* Store cLastModified, cVersion and the change number */
[messageEntry setObject: cLastModified forKey: @"c_lastmodified"];
[messageEntry setObject: cVersion forKey: @"c_version"];
[messageEntry setObject: changeNumberStr forKey: @"version"];
/* Store the change key */
changeKey = [self getReplicaKeyFromGlobCnt: changeNumber >> 16];
[self _setChangeKey: changeKey forMessageEntry: messageEntry];
/* Store the changeNumber -> cLastModified mapping */
mapping = [currentProperties objectForKey: @"VersionMapping"];
if (!mapping)
{
mapping = [NSMutableDictionary new];
[currentProperties setObject: mapping forKey: @"VersionMapping"];
[mapping release];
}
[mapping setObject: cLastModified forKey: changeNumberStr];
/* Save the message */
[versionsMessage save];
return YES;
}
else
return NO;
}
/* If message entry exists, then synchroniseCache did its job */
return YES;
}
- (void) updateVersionsForMessageWithKey: (NSString *) messageKey
withChangeKey: (NSData *) oldChangeKey
andPredecessorChangeList: (NSData *) pcl
withChangeKey: (NSData *) newChangeKey
{
NSMutableDictionary *messages, *messageEntry;
[self synchroniseCache];
if (oldChangeKey || pcl)
if (newChangeKey)
{
messages = [[versionsMessage properties] objectForKey: @"Messages"];
messageEntry = [messages objectForKey: messageKey];
@@ -672,8 +496,8 @@ static Class NSNumberK;
[NSException raise: @"MAPIStoreIOException"
format: @"no version record found for message '%@'",
messageKey];
[self _updatePredecessorChangeList: pcl forMessageEntry: messageEntry
withOldChangeKey: oldChangeKey];
[self _setChangeKey: newChangeKey forMessageEntry: messageEntry
inChangeListOnly: YES];
[versionsMessage save];
}
}
@@ -681,12 +505,12 @@ static Class NSNumberK;
- (NSNumber *) lastModifiedFromMessageChangeNumber: (NSString *) changeNumber
{
NSDictionary *mapping;
NSNumber *lastModified;
NSNumber *modseq;
mapping = [[versionsMessage properties] objectForKey: @"VersionMapping"];
lastModified = [mapping objectForKey: changeNumber];
modseq = [mapping objectForKey: changeNumber];
return lastModified;
return modseq;
}
- (NSString *) changeNumberForMessageWithKey: (NSString *) messageKey
+16 -39
View File
@@ -140,16 +140,9 @@
[parentFolder synchroniseCache];
changeKey = [parentFolder changeKeyForMessageWithKey: nameInContainer];
}
if (changeKey)
*data = [changeKey asBinaryInMemCtx: memCtx];
else
{
[self warnWithFormat: @"No change key for %@ in folder %@",
nameInContainer,
[parentFolder url]
];
rc = MAPISTORE_ERR_NOT_FOUND;
}
if (!changeKey)
abort ();
*data = [changeKey asBinaryInMemCtx: memCtx];
}
return rc;
@@ -187,8 +180,7 @@
{
uint64_t version = ULLONG_MAX;
NSString *changeNumber;
BOOL synced;
if (!isNew)
{
changeNumber = [(MAPIStoreGCSFolder *) container
@@ -197,28 +189,16 @@
{
[self warnWithFormat: @"attempting to get change number"
@" by synchronising folder..."];
synced = [(MAPIStoreGCSFolder *) container synchroniseCache];
if (synced)
[(MAPIStoreGCSFolder *) container synchroniseCache];
changeNumber = [(MAPIStoreGCSFolder *) container
changeNumberForMessageWithKey: [self nameInContainer]];
if (changeNumber)
[self logWithFormat: @"got one"];
else
{
changeNumber = [(MAPIStoreGCSFolder *) container
changeNumberForMessageWithKey: [self nameInContainer]];
}
if (!changeNumber)
{
[self warnWithFormat: @"attempting to get change number"
@" by synchronising this specific message..."];
synced = [(MAPIStoreGCSFolder *) container
synchroniseCacheFor: [self nameInContainer]];
if (synced)
{
changeNumber = [(MAPIStoreGCSFolder *) container
changeNumberForMessageWithKey: [self nameInContainer]];
}
if (!changeNumber)
{
[self errorWithFormat: @"still nothing. We crash!"];
abort();
}
[self errorWithFormat: @"still nothing. We crash!"];
abort();
}
}
version = [changeNumber unsignedLongLongValue] >> 16;
@@ -229,16 +209,13 @@
- (void) updateVersions
{
/* Update ChangeKey and PredecessorChangeList on message's save */
NSData *newChangeKey, *predecessorChangeList;
NSData *newChangeKey;
newChangeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)];
predecessorChangeList = [properties objectForKey: MAPIPropertyKey (PR_PREDECESSOR_CHANGE_LIST)];
[(MAPIStoreGCSFolder *) container
updateVersionsForMessageWithKey: [self nameInContainer]
withChangeKey: newChangeKey
andPredecessorChangeList: predecessorChangeList];
updateVersionsForMessageWithKey: [self nameInContainer]
withChangeKey: newChangeKey];
}
@end
+4 -14
View File
@@ -27,7 +27,6 @@
#import <Foundation/NSString.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSObject+Values.h>
#import <EOControl/EOFetchSpecification.h>
#import <EOControl/EOQualifier.h>
@@ -39,6 +38,7 @@
#import "MAPIStoreTypes.h"
#import "MAPIStoreGCSFolder.h"
#import "MAPIStoreGCSMessageTable.h"
#undef DEBUG
@@ -89,31 +89,21 @@
if (res->ulPropTag == PidTagChangeNumber)
{
NSString *changeNumber;
value = NSObjectFromMAPISPropValue (&res->lpProp);
changeNumber = [NSString stringWithUnsignedLongLong: [(NSNumber *)value unsignedLongLongValue]];
lastModified = [(MAPIStoreGCSFolder *)
container lastModifiedFromMessageChangeNumber: changeNumber];
container lastModifiedFromMessageChangeNumber: value];
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
//[self logWithFormat: @" c_lastmodified: %@", lastModified];
if (lastModified)
{
SEL operator;
operator = [self operatorFromRestrictionOperator: res->relop];
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"c_lastmodified"
operatorSelector: operator
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
value: lastModified];
[*qualifier autorelease];
rc = MAPIRestrictionStateNeedsEval;
}
else
{
[self logWithFormat: @"No last modified found for: 0x%.16"PRIx64". Then no restriction applied",
[value unsignedLongLongValue]];
rc = MAPIRestrictionStateAlwaysTrue;
}
rc = MAPIRestrictionStateAlwaysTrue;
}
else
{
+15 -4
View File
@@ -30,7 +30,6 @@
#import <SOGo/NSArray+Utilities.h>
#import <Mailer/SOGoMailBodyPart.h>
#import <Mailer/SOGoMailObject.h>
#import <Mailer/NSDictionary+Mail.h>
#import "MAPIStoreTypes.h"
#import "MAPIStoreMailMessage.h"
@@ -109,7 +108,7 @@
static char recordBytes[] = {0xd9, 0xd8, 0x11, 0xa3, 0xe2, 0x90, 0x18, 0x41,
0x9e, 0x04, 0x58, 0x46, 0x9d, 0x6d, 0x1b,
0x68};
*data = [[NSData dataWithBytes: recordBytes length: 16]
asBinaryInMemCtx: memCtx];
@@ -118,7 +117,19 @@
- (NSString *) _fileName
{
return [bodyInfo filename];
NSString *fileName;
NSDictionary *parameters;
fileName = [[bodyInfo objectForKey: @"parameterList"]
objectForKey: @"name"];
if (!fileName)
{
parameters = [[bodyInfo objectForKey: @"disposition"]
objectForKey: @"parameterList"];
fileName = [parameters objectForKey: @"filename"];
}
return fileName;
}
- (int) getPidTagAttachLongFilename: (void **) data
@@ -167,7 +178,7 @@
- (int) getPidTagAttachContentId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
{
*data = [[bodyInfo objectForKey: @"bodyId"]
asUnicodeInMemCtx: memCtx];
+11 -13
View File
@@ -160,25 +160,23 @@ MakeDisplayFolderName (NSString *folderName)
for (count = 0; count < max; count++)
{
context = talloc_zero (memCtx, struct mapistore_contexts_list);
// secondaryFolders has the names (1) Imap4Encoded ,(2) asCSSIdentifier and (3) "folder"-prefixed
// e.g.: folderProbl&AOg-mes_SP_de_SP_synchronisation
// secondaryFolders has the names (1) Imap4Encoded and (2) asCSSIdentifier
// e.g.: Probl&AOg-mes_SP_de_SP_synchronisation
currentName = [secondaryFolders objectAtIndex: count];
// To get the real name we have to revert that (applying the decode functions
// in reverse order)
// To get the real name we have to revert that (applying the decode functions)
// in reverse order
// e.g.: Problèmes de synchronisation
realName = [[[currentName substringFromIndex: 6]
fromCSSIdentifier]
stringByDecodingImap4FolderName];
realName = [[currentName fromCSSIdentifier]
stringByDecodingImap4FolderName];
// And finally to represent that as URI we have to (1) asCSSIdentifier,
// (2) Imap4Encode (3) AddPercentEscapes and (4) add the "folder" prefix
// e.g.: folderProbl&AOg-mes_SP_de_SP_synchronisation
// (2) Imap4Encode and (3) AddPercentEscapes
// e.g.: Probl&AOg-mes_SP_de_SP_synchronisation
// In the example there are no percent escapes added because is already ok
stringData = [[[realName asCSSIdentifier]
stringByEncodingImap4FolderName]
stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
stringData = [NSString stringWithFormat: @"folder%@", stringData];
context->url = [[NSString stringWithFormat: @"%@%@", urlBase, stringData] asUnicodeInMemCtx: context];
context->name = [realName asUnicodeInMemCtx: context];
context->name = [[realName substringFromIndex: 6] asUnicodeInMemCtx: context];
context->main_folder = false;
context->role = MAPISTORE_MAIL_ROLE;
context->tag = "tag";
@@ -202,7 +200,7 @@ MakeDisplayFolderName (NSString *folderName)
andTDBIndexing: NULL];
accountFolder = [[userContext rootFolders] objectForKey: @"mail"];
folderName = [NSString stringWithFormat: @"folder%@",
[[newFolderName stringByEncodingImap4FolderName] asCSSIdentifier]];
[newFolderName asCSSIdentifier]];
newFolder = [SOGoMailFolder objectWithName: folderName
inContainer: accountFolder];
if ([newFolder create])
@@ -211,7 +209,7 @@ MakeDisplayFolderName (NSString *folderName)
withString: @"%40"],
[userName stringByReplacingOccurrencesOfString: @"@"
withString: @"%40"],
[folderName stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
[[folderName stringByEncodingImap4FolderName] stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
else
mapistoreURI = nil;
-2
View File
@@ -52,8 +52,6 @@
- (NSString *) changeNumberForMessageUID: (NSString *) messageUid;
- (void) setChangeKey: (NSData *) changeKey
forMessageWithKey: (NSString *) messageKey;
- (BOOL) updatePredecessorChangeListWith: (NSData *) changeKey
forMessageWithKey: (NSString *) messageKey;
- (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey;
- (NSData *) predecessorChangeListForMessageWithKey: (NSString *) messageKey;
+45 -198
View File
@@ -68,13 +68,10 @@
static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
#include <gen_ndr/exchange.h>
#undef DEBUG
#include <util/attr.h>
#include <libmapi/libmapi.h>
#include <libmapiproxy.h>
#include <limits.h>
#include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h>
@@ -112,7 +109,6 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
[SOGoMAPIDBMessage objectWithName: @"versions.plist"
inContainer: dbFolder]);
[versionsMessage setObjectType: MAPIInternalCacheObject];
[versionsMessage reloadIfNeeded];
}
- (BOOL) ensureFolderExists
@@ -182,7 +178,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME_UNICODE)
folderName = [NSString stringWithUTF8String: aRow->lpProps[i].value.lpszW];
else if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME)
folderName = [NSString stringWithUTF8String: (const char *) aRow->lpProps[i].value.lpszA];
folderName = [NSString stringWithUTF8String: aRow->lpProps[i].value.lpszA];
}
if (folderName)
@@ -258,67 +254,6 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
return MAPISTORE_SUCCESS;
}
- (EOQualifier *) simplifyQualifier: (EOQualifier *) qualifier
{
/* Hack: Reduce the number of MODSEQ constraints to a single one as
we assume the difference among MODSEQs will be small enough to
return a small number of UIDs.
This is the only case we do simplify:
MODSEQ >= x | MODSEQ >= y | MODSEQ >= z => MODSEQ >= min(x,y,z)
*/
if (qualifier && [qualifier isKindOfClass: [EOOrQualifier class]])
{
EOQualifier *simplifiedQualifier;
NSArray *quals;
NSNumber *minModseq;
NSUInteger i, count;
quals = [(EOOrQualifier *)qualifier qualifiers];
count = [quals count];
if (count < 2)
return qualifier;
minModseq = [NSNumber numberWithUnsignedLongLong: ULLONG_MAX];
for (i = 0; i < count; i++)
{
EOQualifier *subQualifier;
subQualifier = [quals objectAtIndex: i];
if ([subQualifier isKindOfClass: [EOAndQualifier class]]
&& [[(EOAndQualifier *)subQualifier qualifiers] count] == 1)
subQualifier = [[(EOAndQualifier *)subQualifier qualifiers] objectAtIndex: 0];
if ([subQualifier isKindOfClass: [EOKeyValueQualifier class]]
&& [[(EOKeyValueQualifier *)subQualifier key] isEqualToString: @"MODSEQ"])
{
NSNumber *value;
value = (NSNumber *)[(EOKeyValueQualifier *)subQualifier value];
if ([minModseq compare: value] == NSOrderedDescending
&& [value unsignedLongLongValue] > 0)
minModseq = (NSNumber *)[(EOKeyValueQualifier *)subQualifier value];
}
else
return qualifier;
}
if ([minModseq unsignedLongLongValue] > 0 && [minModseq unsignedLongLongValue] < ULLONG_MAX)
{
simplifiedQualifier = [[EOKeyValueQualifier alloc]
initWithKey: @"MODSEQ"
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
value: minModseq];
[simplifiedQualifier autorelease];
return simplifiedQualifier;
}
}
return qualifier;
}
- (EOQualifier *) nonDeletedQualifier
{
static EOQualifier *nonDeletedQualifier = nil;
@@ -343,7 +278,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
andSortOrderings: (NSArray *) sortOrderings
{
NSArray *uidKeys;
EOQualifier *fetchQualifier, *simplifiedQualifier;
EOQualifier *fetchQualifier;
if ([self ensureFolderExists])
{
@@ -352,10 +287,9 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
if (qualifier)
{
simplifiedQualifier = [self simplifyQualifier: qualifier];
fetchQualifier
= [[EOAndQualifier alloc] initWithQualifiers:
[self nonDeletedQualifier], simplifiedQualifier,
[self nonDeletedQualifier], qualifier,
nil];
[fetchQualifier autorelease];
}
@@ -582,44 +516,6 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
return [modseq1 compare: modseq2];
}
- (void) _updatePredecessorChangeListWith: (NSData *) predecessorChangeList
forMessageEntry: (NSMutableDictionary *) messageEntry
{
NSData *globCnt, *oldGlobCnt;
NSMutableDictionary *changeList;
NSString *guid;
struct SizedXid *sizedXIDList;
struct XID xid;
uint32_t i, length;
sizedXIDList = [predecessorChangeList asSizedXidArrayInMemCtx: NULL with: &length];
changeList = [messageEntry objectForKey: @"PredecessorChangeList"];
if (!changeList)
{
changeList = [NSMutableDictionary new];
[messageEntry setObject: changeList
forKey: @"PredecessorChangeList"];
[changeList release];
}
if (sizedXIDList) {
for (i = 0; i < length; i++)
{
xid = sizedXIDList[i].XID;
guid = [NSString stringWithGUID: &xid.NameSpaceGuid];
globCnt = [NSData dataWithBytes: xid.LocalId.data length: xid.LocalId.length];
oldGlobCnt = [changeList objectForKey: guid];
if (!oldGlobCnt || ([globCnt compare: oldGlobCnt] == NSOrderedDescending))
[changeList setObject: globCnt forKey: guid];
}
talloc_free (sizedXIDList);
}
[versionsMessage save];
}
- (void) _setChangeKey: (NSData *) changeKey
forMessageEntry: (NSMutableDictionary *) messageEntry
{
@@ -630,8 +526,8 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
NSMutableDictionary *changeList;
xid = [changeKey asXIDInMemCtx: NULL];
guid = [NSString stringWithGUID: &xid->NameSpaceGuid];
globCnt = [NSData dataWithBytes: xid->LocalId.data length: xid->LocalId.length];
guid = [NSString stringWithGUID: &xid->GUID];
globCnt = [NSData dataWithBytes: xid->Data length: xid->Size];
talloc_free (xid);
/* 1. set change key association */
@@ -657,12 +553,13 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
{
BOOL rc = YES;
uint64_t newChangeNum;
NSNumber *ti, *modseq, *lastModseq, *nextModseq;
NSNumber *ti, *modseq, *initialLastModseq, *lastModseq,
*nextModseq;
NSString *changeNumber, *uid, *messageKey;
uint64_t lastModseqNbr;
EOQualifier *searchQualifier;
NSArray *uids, *changeNumbers;
NSUInteger count, max, nFetched;
NSUInteger count, max;
NSArray *fetchResults;
NSDictionary *result;
NSData *changeKey;
@@ -696,6 +593,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
}
lastModseq = [currentProperties objectForKey: @"SyncLastModseq"];
initialLastModseq = lastModseq;
if (lastModseq)
{
lastModseqNbr = [lastModseq unsignedLongLongValue];
@@ -741,13 +639,6 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
= [fetchResults sortedArrayUsingFunction: _compareFetchResultsByMODSEQ
context: NULL];
nFetched = [fetchResults count];
if (nFetched != max) {
[self errorWithFormat: @"Error fetching UIDs. Asked: %d Received: %d."
@"Check the IMAP conversation for details", max, nFetched];
return NO;
}
for (count = 0; count < max; count++)
{
result = [fetchResults objectAtIndex: count];
@@ -786,37 +677,40 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
}
/* 2. we synchronise expunged UIDs */
fetchResults = [(SOGoMailFolder *) sogoObject
fetchUIDsOfVanishedItems: lastModseqNbr];
max = [fetchResults count];
changeNumber = nil;
for (count = 0; count < max; count++)
if (initialLastModseq)
{
uid = [[fetchResults objectAtIndex: count] stringValue];
if ([messages objectForKey: uid])
fetchResults = [(SOGoMailFolder *) sogoObject
fetchUIDsOfVanishedItems: lastModseqNbr];
max = [fetchResults count];
changeNumber = nil;
for (count = 0; count < max; count++)
{
if (!changeNumber)
uid = [[fetchResults objectAtIndex: count] stringValue];
if ([messages objectForKey: uid])
{
newChangeNum = [[self context] getNewChangeNumber];
changeNumber = [NSString stringWithUnsignedLongLong: newChangeNum];
if (!changeNumber)
{
newChangeNum = [[self context] getNewChangeNumber];
changeNumber = [NSString stringWithUnsignedLongLong: newChangeNum];
}
[messages removeObjectForKey: uid];
[self logWithFormat: @"Removed message entry for UID %@", uid];
}
else
{
[self logWithFormat:@"Message entry not found for UID %@", uid];
}
[messages removeObjectForKey: uid];
[self logWithFormat: @"Removed message entry for UID %@", uid];
}
else
if (changeNumber)
{
[self logWithFormat:@"Message entry not found for UID %@", uid];
[currentProperties setObject: changeNumber
forKey: @"SyncLastDeleteChangeNumber"];
[mapping setObject: lastModseq forKey: changeNumber];
foundChange = YES;
}
}
if (changeNumber)
{
[currentProperties setObject: changeNumber
forKey: @"SyncLastDeleteChangeNumber"];
[mapping setObject: lastModseq forKey: changeNumber];
foundChange = YES;
}
if (foundChange)
{
@@ -1030,7 +924,8 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
return changeNumber;
}
- (NSMutableDictionary *) _messageEntryFromMessageKey: (NSString *) messageKey
- (void) setChangeKey: (NSData *) changeKey
forMessageWithKey: (NSString *) messageKey
{
NSMutableDictionary *messages, *messageEntry;
NSString *messageUid;
@@ -1041,7 +936,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
messageEntry = [messages objectForKey: messageUid];
if (!messageEntry)
{
[self warnWithFormat: @"attempting to synchronise to get the message entry for "
[self warnWithFormat: @"attempting to synchronise to set the change key for "
@"this message %@", messageKey];
synced = [self synchroniseCacheForUID: messageUid];
if (synced)
@@ -1052,57 +947,11 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
abort ();
}
}
return messageEntry;
}
- (void) setChangeKey: (NSData *) changeKey
forMessageWithKey: (NSString *) messageKey
{
[self _setChangeKey: changeKey
forMessageEntry: [self _messageEntryFromMessageKey: messageKey]];
[self _setChangeKey: changeKey forMessageEntry: messageEntry];
[versionsMessage save];
}
- (BOOL) updatePredecessorChangeListWith: (NSData *) changeKey
forMessageWithKey: (NSString *) messageKey
{
/* Update predecessor change list property given the change key. It
returns if the change key has been added to the list or not */
BOOL added = NO;
NSData *globCnt, *oldGlobCnt;
NSDictionary *messageEntry;
NSMutableDictionary *changeList;
NSString *guid;
struct XID *xid;
xid = [changeKey asXIDInMemCtx: NULL];
guid = [NSString stringWithGUID: &xid->NameSpaceGuid];
globCnt = [NSData dataWithBytes: xid->LocalId.data length: xid->LocalId.length];
talloc_free (xid);
messageEntry = [self _messageEntryFromMessageKey: messageKey];
if (messageEntry)
{
changeList = [messageEntry objectForKey: @"PredecessorChangeList"];
if (changeList)
{
oldGlobCnt = [changeList objectForKey: guid];
if (!oldGlobCnt || ([globCnt compare: oldGlobCnt] == NSOrderedDescending))
{
[changeList setObject: globCnt forKey: guid];
[versionsMessage save];
added = YES;
}
}
else
[self errorWithFormat: @"Missing predecessor change list to update"];
}
return added;
}
- (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey
{
NSDictionary *messages, *changeKeyDict;
@@ -1368,7 +1217,6 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
fromFolder: (MAPIStoreFolder *) sourceFolder
withMIDs: (uint64_t *) targetMids
andChangeKeys: (struct Binary_r **) targetChangeKeys
andPredecessorChangeLists: (struct Binary_r **) targetPredecessorChangeLists
wantCopy: (uint8_t) wantCopy
inMemCtx: (TALLOC_CTX *) memCtx
@@ -1383,13 +1231,12 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
NSDictionary *result;
NSUInteger count;
NSArray *a;
NSData *changeList;
NSData *changeKey;
if (![sourceFolder isKindOfClass: [MAPIStoreMailFolder class]])
return [super moveCopyMessagesWithMIDs: srcMids andCount: midCount
fromFolder: sourceFolder withMIDs: targetMids
andChangeKeys: targetChangeKeys
andPredecessorChangeLists: targetPredecessorChangeLists
wantCopy: wantCopy
inMemCtx: memCtx];
@@ -1478,11 +1325,11 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
[self synchroniseCache];
for (count = 0; count < midCount; count++)
{
changeList = [NSData dataWithBinary: targetPredecessorChangeLists[count]];
changeKey = [NSData dataWithBinary: targetChangeKeys[count]];
messageKey = [NSString stringWithFormat: @"%@.eml",
[destUIDs objectAtIndex: count]];
[self _updatePredecessorChangeListWith: changeList
forMessageEntry: [self _messageEntryFromMessageKey: messageKey]];
[self setChangeKey: changeKey
forMessageWithKey: messageKey];
}
}
@@ -1711,10 +1558,10 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
rights |= RightsCreateItems;
if ([roles containsObject: SOGoRole_ObjectEraser]
&& [roles containsObject: SOGoRole_FolderEraser])
rights |= RightsDeleteAll | RightsDeleteOwn;
rights |= RightsDeleteAll;
if ([roles containsObject: SOGoRole_ObjectEditor])
rights |= RightsEditAll | RightsEditOwn;
rights |= RightsEditAll;
if ([roles containsObject: SOGoRole_ObjectViewer])
rights |= RightsReadItems;
if ([roles containsObject: SOGoRole_FolderCreator])
+43 -95
View File
@@ -40,7 +40,6 @@
#import <Mailer/NSData+Mail.h>
#import <Mailer/SOGoMailBodyPart.h>
#import <Mailer/SOGoMailObject.h>
#import <Mailer/NSDictionary+Mail.h>
#import "Codepages.h"
#import "NSData+MAPIStore.h"
@@ -197,7 +196,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
count1 = [keys indexOfObject: data1];
data2 = [entry2 objectForKey: @"mimeType"];
count2 = [keys indexOfObject: data2];
if (count1 == count2)
{
data1 = [entry1 objectForKey: @"key"];
@@ -340,6 +339,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
wrapperWithICalEvent: event
andUser: [context activeUser]
andSenderEmail: senderEmail
inTimeZone: [[self userContext] timeZone]
withConnectionInfo: [context connectionInfo]];
[appointmentWrapper retain];
}
@@ -521,9 +521,6 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
NSUInteger colIdx;
NSString *stringValue;
/* As specified in [MS-OXCMAIL] 2.2.3.2.6.1, if there are three
or less characters followed by a colon at the beginning of
the subject, we can assume that's the subject prefix */
subject = [self subject];
colIdx = [subject rangeOfString: @":"].location;
if (colIdx != NSNotFound && colIdx < 4)
@@ -532,52 +529,24 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
else
stringValue = @"";
*data = [stringValue asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidTagNormalizedSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSString *stringValue, *subject;
NSUInteger quoteStartIdx, quoteEndIdx, colIdx;
NSRange quoteRange;
if (!headerSetup)
[self _fetchHeaderData];
NSString *subject;
NSUInteger colIdx;
NSString *stringValue;
subject = [self subject];
if (mailIsMeetingRequest)
{
/* SOGo "spices up" the invitation/update mail's subject, but
the client uses it to name the attendee's event, so we keep
only what's inside the quotes */
quoteStartIdx = [subject rangeOfString: @"\""].location;
quoteEndIdx = [subject rangeOfString: @"\""
options: NSBackwardsSearch].location;
if (quoteStartIdx != NSNotFound
&& quoteEndIdx != NSNotFound
&& quoteStartIdx != quoteEndIdx)
{
quoteRange = NSMakeRange(quoteStartIdx + 1, quoteEndIdx - quoteStartIdx - 1);
stringValue = [subject substringWithRange: quoteRange];
}
else stringValue = subject;
}
colIdx = [subject rangeOfString: @":"].location;
if (colIdx != NSNotFound && colIdx < 4)
stringValue = [[subject substringFromIndex: colIdx + 1]
stringByTrimmingLeadSpaces];
else
{
/* As specified in [MS-OXCMAIL] 2.2.3.2.6.1, if there are three
or less characters followed by a colon at the beginning of
the subject, we can assume that's the subject prefix */
colIdx = [subject rangeOfString: @":"].location;
if (colIdx != NSNotFound && colIdx < 4)
stringValue = [[subject substringFromIndex: colIdx + 1]
stringByTrimmingLeadSpaces];
else
stringValue = subject;
}
stringValue = subject;
if (!stringValue)
stringValue = @"";
*data = [stringValue asUnicodeInMemCtx: memCtx];
@@ -655,7 +624,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
NSDictionary *coreInfos;
NSArray *flags;
unsigned int v = 0;
coreInfos = [sogoObject fetchCoreInfos];
flags = [coreInfos objectForKey: @"flags"];
@@ -667,7 +636,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
if ([[self attachmentKeys]
count] > 0)
v |= MSGFLAG_HASATTACH;
*data = MAPILongValue (memCtx, v);
return MAPISTORE_SUCCESS;
@@ -687,7 +656,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
v = 2;
else
v = 0;
*data = MAPILongValue (memCtx, v);
return MAPISTORE_SUCCESS;
@@ -699,15 +668,15 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
NSDictionary *coreInfos;
NSArray *flags;
unsigned int v;
coreInfos = [sogoObject fetchCoreInfos];
flags = [coreInfos objectForKey: @"flags"];
if ([flags containsObject: @"flagged"])
v = 6;
else
v = 0;
*data = MAPILongValue (memCtx, v);
return MAPISTORE_SUCCESS;
@@ -786,7 +755,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
if ([ngAddress isKindOfClass: [NGMailAddress class]])
{
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.
@@ -810,6 +779,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
NSDictionary *contactInfos;
NGMailAddress *ngAddress;
NSData *entryId;
struct ldb_context *samCtx;
int rc;
if (fullMail)
@@ -832,13 +802,14 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
if (contactInfos)
{
username = [contactInfos objectForKey: @"sAMAccountName"];
entryId = MAPIStoreInternalEntryId([[self context] connectionInfo], username);
samCtx = [[self context] connectionInfo]->sam_ctx;
entryId = MAPIStoreInternalEntryId (samCtx, username);
}
else
entryId = MAPIStoreExternalEntryId (cn, email);
*data = [entryId asBinaryInMemCtx: memCtx];
rc = MAPISTORE_SUCCESS;
}
else
@@ -995,15 +966,15 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
{
uint32_t v;
NSString *s;
s = [[sogoObject mailHeaders] objectForKey: @"x-priority"];
v = 0x1;
if ([s hasPrefix: @"1"]) v = 0x2;
else if ([s hasPrefix: @"2"]) v = 0x2;
else if ([s hasPrefix: @"4"]) v = 0x0;
else if ([s hasPrefix: @"5"]) v = 0x0;
*data = MAPILongValue (memCtx, v);
return MAPISTORE_SUCCESS;
@@ -1192,14 +1163,14 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
if (!headerSetup)
[self _fetchHeaderData];
if ([headerMimeType isEqualToString: @"text/plain"])
format = EDITOR_FORMAT_PLAINTEXT;
else if ([headerMimeType isEqualToString: @"text/html"])
format = EDITOR_FORMAT_HTML;
else
format = 0; /* EDITOR_FORMAT_DONTKNOW */
*data = MAPILongValue (memCtx, format);
return MAPISTORE_SUCCESS;
@@ -1475,9 +1446,11 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
NSData *entryId;
NSDictionary *contactInfos;
SOGoUserManager *mgr;
struct ldb_context *samCtx;
struct mapistore_message *msgData;
struct mapistore_message_recipient *recipient;
samCtx = [[self context] connectionInfo]->sam_ctx;
[super getMessageData: &msgData inMemCtx: memCtx];
if (!headerSetup)
@@ -1531,7 +1504,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
{
username = [contactInfos objectForKey: @"sAMAccountName"];
recipient->username = [username asUnicodeInMemCtx: msgData];
entryId = MAPIStoreInternalEntryId ([[self context] connectionInfo], username);
entryId = MAPIStoreInternalEntryId (samCtx, username);
}
else
{
@@ -1544,7 +1517,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
p = 0;
recipient->data = talloc_array (msgData, void *, msgData->columns->cValues);
memset (recipient->data, 0, msgData->columns->cValues * sizeof (void *));
// PR_OBJECT_TYPE = MAPI_MAILUSER (see MAPI_OBJTYPE)
recipient->data[p] = MAPILongValue (msgData, MAPI_MAILUSER);
p++;
@@ -1552,7 +1525,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
// PR_DISPLAY_TYPE = DT_MAILUSER (see MS-NSPI)
recipient->data[p] = MAPILongValue (msgData, 0);
p++;
// PR_7BIT_DISPLAY_NAME_UNICODE
recipient->data[p] = [cn asUnicodeInMemCtx: msgData];
p++;
@@ -1560,7 +1533,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
// PR_SMTP_ADDRESS_UNICODE
recipient->data[p] = [email asUnicodeInMemCtx: msgData];
p++;
// PR_SEND_INTERNET_ENCODING = 0x00060000 (plain text, see OXCMAIL)
recipient->data[p] = MAPILongValue (msgData, 0x00060000);
p++;
@@ -1593,9 +1566,12 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
withPrefix: (NSString *) keyPrefix
{
NSArray *parts;
NSDictionary *parameters;
NSUInteger count, max;
if ([[bodyInfo filename] length] > 0)
parameters = [[bodyInfo objectForKey: @"disposition"]
objectForKey: @"parameterList"];
if ([[parameters objectForKey: @"filename"] length] > 0)
{
if ([keyPrefix length] == 0)
keyPrefix = @"0";
@@ -1669,13 +1645,15 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
return attachment;
}
- (enum mapistore_error) setReadFlag: (uint8_t) flag
- (int) setReadFlag: (uint8_t) flag
{
NSString *imapFlag = @"\\Seen";
/* TODO: notifications should probably be emitted from here */
if (flag & CLEAR_READ_FLAG)
[properties setObject: [NSNumber numberWithBool: NO] forKey: @"read_flag_set"];
[sogoObject removeFlags: imapFlag];
else
[properties setObject: [NSNumber numberWithBool: YES] forKey: @"read_flag_set"];
[sogoObject addFlags: imapFlag];
return MAPISTORE_SUCCESS;
}
@@ -1716,12 +1694,9 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
return nil;
}
- (void) save: (TALLOC_CTX *) memCtx
- (void) save: (TALLOC_CTX *) memCtx
{
BOOL modified = NO;
BOOL seen, storedSeenFlag;
NSNumber *value;
NSString *imapFlag = @"\\Seen";
value = [properties objectForKey: MAPIPropertyKey (PR_FLAG_STATUS)];
if (value)
@@ -1731,35 +1706,8 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
[sogoObject addFlags: @"\\Flagged"];
else /* 0: unflagged, 1: follow up complete */
[sogoObject removeFlags: @"\\Flagged"];
modified = YES;
}
/* Manage seen flag on save */
value = [properties objectForKey: @"read_flag_set"];
if (value)
{
seen = [value boolValue];
storedSeenFlag = [[[sogoObject fetchCoreInfos] objectForKey: @"flags"] containsObject: @"seen"];
/* We modify the flags anyway to generate a new change number */
if (seen)
{
if (storedSeenFlag)
[sogoObject removeFlags: imapFlag];
[sogoObject addFlags: imapFlag];
}
else
{
if (!storedSeenFlag)
[sogoObject addFlags: imapFlag];
[sogoObject removeFlags: imapFlag];
}
modified = YES;
}
if (modified)
[(MAPIStoreMailFolder *)[self container] synchroniseCache];
if (mailIsSharingObject)
[[self _sharingObject] saveWithMessage: self
andSOGoObject: sogoObject];
+7 -22
View File
@@ -161,30 +161,15 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
//[self logWithFormat: @" modseq: %.16lx", [modseq unsignedLongLongValue]];
if (modseq)
{
if (res->relop == RELOP_GT)
modseq = [NSNumber numberWithUnsignedLongLong:
[modseq unsignedLongLongValue] + 1];
}
modseq = [NSNumber numberWithUnsignedLongLong:
[modseq unsignedLongLongValue] + 1];
else
modseq = [NSNumber numberWithUnsignedLongLong: 0];
if (res->relop == RELOP_GT || res->relop == RELOP_GE)
{
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"MODSEQ"
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
value: modseq];
[*qualifier autorelease];
rc = MAPIRestrictionStateNeedsEval;
}
else
{
/* Ignore other operations as IMAP only support MODSEQ >= X */
[self warnWithFormat: @"Ignoring '%@' as only supported operators are > and >=",
NSStringFromSelector ([self operatorFromRestrictionOperator: res->relop])];
rc = MAPIRestrictionStateAlwaysTrue;
}
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"MODSEQ"
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
value: modseq];
[*qualifier autorelease];
rc = MAPIRestrictionStateNeedsEval;
}
break;
+27 -50
View File
@@ -34,7 +34,6 @@
#import <NGExtensions/NGBase64Coding.h>
#import <NGExtensions/NGHashMap.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSObject+Values.h>
#import <NGExtensions/NSString+Encoding.h>
#import <NGMime/NGMimeBodyPart.h>
#import <NGMime/NGMimeMultipartBody.h>
@@ -167,9 +166,9 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
- (BOOL) hasContentId
{
NSString *contentId = [properties
objectForKey: MAPIPropertyKey (PR_ATTACH_CONTENT_ID_UNICODE)];
return contentId && [contentId length] > 0;
return ([properties
objectForKey: MAPIPropertyKey (PR_ATTACH_CONTENT_ID_UNICODE)]
!= nil);
}
- (NGMimeBodyPart *) asMIMEBodyPart
@@ -233,7 +232,7 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
[map addObject: contentDisposition forKey: @"content-disposition"];
contentId = [properties
objectForKey: MAPIPropertyKey (PR_ATTACH_CONTENT_ID_UNICODE)];
if (contentId && [contentId length] > 0)
if (contentId)
[map setObject: [NSString stringWithFormat: @"<%@>", contentId]
forKey: @"content-id"];
bodyPart = [NGMimeBodyPart bodyPartWithHeader: map];
@@ -286,7 +285,7 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
version = [properties objectForKey: @"version"];
return (version
? [version unsignedLongLongValue]
? exchange_globcnt ([version unsignedLongLongValue])
: ULLONG_MAX);
}
@@ -338,10 +337,13 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
NSData *entryId;
NSDictionary *allRecipients, *dict, *contactInfos;
SOGoUserManager *mgr;
struct ldb_context *samCtx;
struct mapistore_message *msgData;
struct mapistore_message_recipient *recipient;
enum ulRecipClass type;
samCtx = [[self context] connectionInfo]->sam_ctx;
// [super getMessageData: &msgData inMemCtx: memCtx];
msgData = talloc_zero (memCtx, struct mapistore_message);
@@ -386,7 +388,7 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
{
username = [contactInfos objectForKey: @"sAMAccountName"];
recipient->username = [username asUnicodeInMemCtx: msgData];
entryId = MAPIStoreInternalEntryId ([[self context] connectionInfo], username);
entryId = MAPIStoreInternalEntryId (samCtx, username);
}
else
{
@@ -679,14 +681,6 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
if (!fromResolved)
{
TALLOC_CTX *local_mem_ctx;
local_mem_ctx = talloc_new(NULL);
if (!local_mem_ctx)
{
NSLog (@"%s: Out of memory", __PRETTY_FUNCTION__);
return;
}
NSLog (@"Message without an orig from, try to guess it from PidTagSenderEntryId");
senderEntryId = [mailProperties objectForKey: MAPIPropertyKey (PR_SENDER_ENTRYID)];
if (senderEntryId)
@@ -700,12 +694,12 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
bin32.cb = [senderEntryId length];
bin32.lpb = (uint8_t *) [senderEntryId bytes];
addrBookEntryId = get_AddressBookEntryId (local_mem_ctx, &bin32);
addrBookEntryId = get_AddressBookEntryId (connInfo->sam_ctx, &bin32);
if (addrBookEntryId && [[NSString stringWithGUID: &addrBookEntryId->ProviderUID]
hasSuffix: @"08002b2fe182"])
{
/* TODO: better way to distinguish local and other ones */
username = MAPIStoreSamDBUserAttribute (connInfo, @"legacyExchangeDN",
username = MAPIStoreSamDBUserAttribute (connInfo->sam_ctx, @"legacyExchangeDN",
[NSString stringWithUTF8String: addrBookEntryId->X500DN], @"sAMAccountName");
if (username)
{
@@ -726,7 +720,7 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
/* Try with One-Off EntryId */
struct OneOffEntryId *oneOffEntryId;
oneOffEntryId = get_OneOffEntryId (local_mem_ctx, &bin32);
oneOffEntryId = get_OneOffEntryId (connInfo->sam_ctx, &bin32);
if (oneOffEntryId && [[NSString stringWithGUID: &oneOffEntryId->ProviderUID]
hasSuffix: @"00dd010f5402"])
{
@@ -735,7 +729,9 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
[fromRecipient setObject: [NSString stringWithUTF8String: oneOffEntryId->EmailAddress.lpszW]
forKey: @"email"];
}
talloc_free (oneOffEntryId);
}
talloc_free (addrBookEntryId);
if ([[fromRecipient allKeys] count] > 0)
{
@@ -745,8 +741,6 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
}
}
/* Free entryId */
talloc_free(local_mem_ctx);
}
if (!recipients)
@@ -1013,7 +1007,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
- (NGMimeMessage *) _generateMessageWithBcc: (BOOL) withBcc
{
NSString *contentType;
NGMimeMessage *message;
NGMimeMessage *message;
NGMutableHashMap *headers;
id messageBody;
@@ -1053,7 +1047,6 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
- (int) submitWithFlags: (enum SubmitFlags) flags
{
enum mapistore_error rc = MAPISTORE_SUCCESS;
NSDictionary *recipients;
NSData *messageData;
NSMutableArray *recipientEmails;
@@ -1100,10 +1093,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
withAuthenticator: authenticator
inContext: woContext];
if (error)
{
[self errorWithFormat: @"an error occurred: '%@'", error];
rc = MAPISTORE_ERR_MSG_SEND;
}
[self logWithFormat: @"an error occurred: '%@'", error];
// mapping = [self mapping];
// [mapping unregisterURLWithID: [self objectId]];
@@ -1115,13 +1105,12 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
[self logWithFormat: @"skipping submit of message with class '%@'",
msgClass];
return rc;
return MAPISTORE_SUCCESS;
}
- (void) save: (TALLOC_CTX *) memCtx
{
BOOL updatedMetadata;
NSString *folderName, *flag, *newIdString, *messageKey, *changeNumber;
NSString *folderName, *flag, *newIdString, *messageKey;
NSData *changeKey, *messageData;
NGImap4Connection *connection;
NGImap4Client *client;
@@ -1157,33 +1146,21 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
[sogoObject setNameInContainer: messageKey];
[mapping registerURL: [self url] withID: mid];
/* synchronise the cache and update the predecessor change list
with the change key provided 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 */
/* synchronise the cache and update the change key with the one provided
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)
{
updatedMetadata = [(MAPIStoreMailFolder *) container updatePredecessorChangeListWith: changeKey
forMessageWithKey: messageKey];
if (!updatedMetadata)
[self warnWithFormat: @"Predecessor change list not updated with client data"];
}
/* Update version property (PR_CHANGE_KEY indeed) as it is
requested once it is saved */
changeNumber = [(MAPIStoreMailFolder *) container changeNumberForMessageUID: newIdString];
if (changeNumber)
[properties setObject: [NSNumber numberWithUnsignedLongLong: [changeNumber unsignedLongLongValue] >> 16]
forKey: @"version"];
[(MAPIStoreMailFolder *) container
setChangeKey: changeKey
forMessageWithKey: messageKey];
}
}
+1 -1
View File
@@ -63,7 +63,7 @@
withAID: (uint32_t) aid;
- (int) getAttachmentTable: (MAPIStoreAttachmentTable **) tablePtr
andRowCount: (uint32_t *) countPtr;
- (enum mapistore_error) setReadFlag: (uint8_t) flag;
- (int) setReadFlag: (uint8_t) flag;
- (enum mapistore_error) saveMessage: (TALLOC_CTX *) memCtx;
- (NSArray *) activeContainerMessageTables;
+2 -3
View File
@@ -549,12 +549,11 @@ rtf2html (NSData *compressedRTF)
}
[self save: memCtx];
/* We make sure that any change-related properties are removed from the
/* 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. */
[properties removeObjectForKey: MAPIPropertyKey (PidTagChangeKey)];
[properties removeObjectForKey: MAPIPropertyKey (PidTagChangeNumber)];
[properties removeObjectForKey: MAPIPropertyKey (PidTagPredecessorChangeList)];
if ([container isKindOfClass: MAPIStoreFolderK])
{
@@ -919,7 +918,7 @@ rtf2html (NSData *compressedRTF)
return [self getNo: data inMemCtx: memCtx];;
}
- (enum mapistore_error) setReadFlag: (uint8_t) flag
- (int) setReadFlag: (uint8_t) flag
{
// [self subclassResponsibility: _cmd];
+1 -1
View File
@@ -103,7 +103,7 @@
else
{
connInfo = [(MAPIStoreContext *) [container context] connectionInfo];
entryId = MAPIStoreInternalEntryId (connInfo, userId);
entryId = MAPIStoreInternalEntryId (connInfo->sam_ctx, userId);
}
*data = [entryId asBinaryInMemCtx: memCtx];
+6 -2
View File
@@ -25,9 +25,12 @@
#include <talloc.h>
#import <Foundation/NSTimeZone.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalRecurrenceRule.h>
#import <NGCards/iCalTimeZone.h>
@class NSTimeZone;
@class iCalEvent;
@class iCalRepeatableEntityObject;
@@ -43,7 +46,7 @@
fromRecurrencePattern: (struct RecurrencePattern *) rp
withExceptions: (struct ExceptionInfo *) exInfos
andExceptionCount: (uint16_t) exInfoCount
inTimeZone: (iCalTimeZone *) tz;
inTimeZone: (NSTimeZone *) tz;
@end
@@ -51,6 +54,7 @@
- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp
withEvent: (iCalEvent *) event
inTimeZone: (NSTimeZone *) timeZone
inMemCtx: (TALLOC_CTX *) memCtx;
@end
+8 -6
View File
@@ -24,6 +24,7 @@
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSSet.h>
#import <Foundation/NSString.h>
#import <Foundation/NSTimeZone.h>
#import <NGExtensions/NSCalendarDate+misc.h>
#import <NGExtensions/NSObject+Logs.h>
@@ -34,7 +35,6 @@
#import <NGCards/iCalRepeatableEntityObject.h>
#import <NGCards/iCalRecurrenceRule.h>
#import <NGCards/iCalTimeZone.h>
#import <NGCards/iCalTimeZonePeriod.h>
#import "NSDate+MAPIStore.h"
#import "MAPIStoreRecurrenceUtils.h"
@@ -51,7 +51,7 @@
fromRecurrencePattern: (struct RecurrencePattern *) rp
withExceptions: (struct ExceptionInfo *) exInfos
andExceptionCount: (uint16_t) exInfoCount
inTimeZone: (iCalTimeZone *) tz
inTimeZone: (NSTimeZone *) tz
{
NSCalendarDate *startDate, *olEndDate, *untilDate, *exDate;
@@ -63,7 +63,7 @@
iCalWeekOccurrence weekOccurrence;
iCalWeekOccurrences dayMaskDays;
NSUInteger count, max;
NSInteger bySetPos, tzOffset;
NSInteger bySetPos;
unsigned char maskValue;
[entity removeAllRecurrenceRules];
@@ -242,10 +242,9 @@
{
/* The OriginalStartDate is in local time */
exDate = [NSDate dateFromMinutesSince1601: exInfos[count].OriginalStartDate];
tzOffset = -[[tz periodForDate: exDate] secondsOffsetFromGMT];
exDate = [exDate dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: tzOffset];
seconds: - [tz secondsFromGMT]];
[exceptionDates removeObject: exDate];
}
}
@@ -264,6 +263,7 @@
- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp
withEvent: (iCalEvent *) event
inTimeZone: (NSTimeZone *) timeZone
inMemCtx: (TALLOC_CTX *) memCtx
{
iCalRecurrenceFrequency freq;
@@ -279,8 +279,10 @@
NSMutableArray *deletedDates, *modifiedDates;
startDate = [event firstRecurrenceStartDate];
[startDate setTimeZone: timeZone];
endDate = [event lastPossibleRecurrenceStartDate];
[endDate setTimeZone: timeZone];
rp->ReaderVersion = 0x3004;
rp->WriterVersion = 0x3004;
+44 -46
View File
@@ -64,11 +64,11 @@ static BOOL initialization_done = NO;
} \
OC_DEBUG(5, "[SOGo] --->");
#define NS_CURRENT_THREAD_TRY_UNREGISTER(rc) \
#define NS_CURRENT_THREAD_TRY_UNREGISTER() \
if (__nsrct_thread_registered) { \
GSUnregisterCurrentThread(); \
} \
OC_DEBUG(6, "[SOGo] <--- [%s]", mapistore_errstr (rc));
OC_DEBUG(6, "[SOGo] <---");
#define TRYCATCH_START @try {
#define TRYCATCH_END(pool) \
@@ -76,7 +76,7 @@ static BOOL initialization_done = NO;
enum mapistore_error ret = sogo_backend_handle_objc_exception(e, __PRETTY_FUNCTION__, __LINE__); \
mapiapp_cleanup(); \
[pool release]; \
NS_CURRENT_THREAD_TRY_UNREGISTER(ret); \
NS_CURRENT_THREAD_TRY_UNREGISTER(); \
return ret; \
} \
mapiapp_cleanup();
@@ -253,7 +253,7 @@ sogo_backend_create_context(TALLOC_CTX *mem_ctx,
rc = MAPISTORE_ERROR;
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
return rc;
}
@@ -291,7 +291,7 @@ sogo_backend_create_root_folder (const char *username,
rc = MAPISTORE_ERROR;
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
return rc;
}
@@ -322,7 +322,7 @@ sogo_backend_list_contexts(const char *username, struct indexing_context *indexi
rc = MAPISTORE_ERROR;
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
return rc;
}
@@ -363,7 +363,7 @@ sogo_context_get_path(void *backend_object, TALLOC_CTX *mem_ctx,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -397,7 +397,7 @@ sogo_context_get_root_folder(void *backend_object, TALLOC_CTX *mem_ctx,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -439,7 +439,7 @@ sogo_folder_open_folder(void *folder_object, TALLOC_CTX *mem_ctx, uint64_t fid,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -480,7 +480,7 @@ sogo_folder_create_folder(void *folder_object, TALLOC_CTX *mem_ctx,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -519,7 +519,7 @@ sogo_folder_delete(void *folder_object)
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -549,7 +549,7 @@ sogo_folder_get_child_count(void *folder_object, enum mapistore_table_type table
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -588,7 +588,7 @@ sogo_folder_open_message(void *folder_object,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -627,7 +627,7 @@ sogo_folder_create_message(void *folder_object,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -657,7 +657,7 @@ sogo_folder_delete_message(void *folder_object, uint64_t mid, uint8_t flags)
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -674,7 +674,6 @@ sogo_folder_move_copy_messages(void *folder_object,
uint32_t mid_count,
uint64_t *src_mids, uint64_t *t_mids,
struct Binary_r **target_change_keys,
struct Binary_r **target_predecessor_change_lists,
uint8_t want_copy)
{
MAPIStoreFolder *sourceFolder, *targetFolder;
@@ -699,13 +698,12 @@ sogo_folder_move_copy_messages(void *folder_object,
fromFolder: sourceFolder
withMIDs: t_mids
andChangeKeys: target_change_keys
andPredecessorChangeLists: target_predecessor_change_lists
wantCopy: want_copy
inMemCtx: mem_ctx];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -753,7 +751,7 @@ sogo_folder_move_folder(void *folder_object, void *target_folder_object,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -795,7 +793,7 @@ sogo_folder_copy_folder(void *folder_object, void *target_folder_object, TALLOC_
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -831,7 +829,7 @@ sogo_folder_get_deleted_fmids(void *folder_object, TALLOC_CTX *mem_ctx,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -869,7 +867,7 @@ sogo_folder_open_table(void *folder_object, TALLOC_CTX *mem_ctx,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -903,7 +901,7 @@ sogo_folder_modify_permissions(void *folder_object, uint8_t flags,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -934,7 +932,7 @@ sogo_folder_preload_message_bodies(void *folder_object, enum mapistore_table_typ
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -967,8 +965,8 @@ sogo_message_get_message_data(void *message_object,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
rc = MAPISTORE_SUCCESS;
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
}
else
{
@@ -1001,7 +999,7 @@ sogo_message_create_attachment (void *message_object, TALLOC_CTX *mem_ctx, void
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1035,7 +1033,7 @@ sogo_message_open_attachment (void *message_object, TALLOC_CTX *mem_ctx,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1069,7 +1067,7 @@ sogo_message_get_attachment_table (void *message_object, TALLOC_CTX *mem_ctx, vo
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1104,7 +1102,7 @@ sogo_message_modify_recipients (void *message_object,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1120,7 +1118,7 @@ sogo_message_set_read_flag (void *message_object, uint8_t flag)
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreMessage *message;
enum mapistore_error rc;
int rc;
if (message_object)
{
@@ -1134,7 +1132,7 @@ sogo_message_set_read_flag (void *message_object, uint8_t flag)
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1164,7 +1162,7 @@ sogo_message_save (void *message_object, TALLOC_CTX *mem_ctx)
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1194,7 +1192,7 @@ sogo_message_submit (void *message_object, enum SubmitFlags flags)
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1234,7 +1232,7 @@ sogo_message_attachment_open_embedded_message (void *attachment_object,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1272,7 +1270,7 @@ sogo_message_attachment_create_embedded_message (void *attachment_object,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1302,7 +1300,7 @@ static enum mapistore_error sogo_table_get_available_properties(void *table_obje
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1333,7 +1331,7 @@ sogo_table_set_columns (void *table_object, uint16_t count, enum MAPITAGS *prope
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1366,7 +1364,7 @@ sogo_table_set_restrictions (void *table_object, struct mapi_SRestriction *restr
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1399,7 +1397,7 @@ sogo_table_set_sort_order (void *table_object, struct SSortOrderSet *sort_order,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1432,7 +1430,7 @@ sogo_table_get_row (void *table_object, TALLOC_CTX *mem_ctx,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1465,7 +1463,7 @@ sogo_table_get_row_count (void *table_object,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1495,8 +1493,8 @@ sogo_table_handle_destructor (void *table_object, uint32_t handle_id)
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
rc = MAPISTORE_SUCCESS;
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
}
else
{
@@ -1527,7 +1525,7 @@ static enum mapistore_error sogo_properties_get_available_properties(void *objec
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1562,7 +1560,7 @@ sogo_properties_get_properties (void *object,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1592,7 +1590,7 @@ sogo_properties_set_properties (void *object, struct SRow *aRow)
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
@@ -1646,7 +1644,7 @@ sogo_manager_generate_uri (TALLOC_CTX *mem_ctx,
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER(MAPISTORE_SUCCESS);
NS_CURRENT_THREAD_TRY_UNREGISTER();
return MAPISTORE_SUCCESS;
}
+1 -3
View File
@@ -197,7 +197,6 @@ static Class MAPIStoreFolderK;
inMemCtx: (TALLOC_CTX *) memCtx
{
int rc;
struct mapistore_connection_info *connInfo;
uint64_t obVersion;
obVersion = [self objectVersion];
@@ -205,9 +204,8 @@ static Class MAPIStoreFolderK;
rc = MAPISTORE_ERR_NOT_FOUND;
else
{
connInfo = [[self context] connectionInfo];
*data = MAPILongLongValue (memCtx, ((obVersion << 16)
| connInfo->repl_id));
| 0x0001));
rc = MAPISTORE_SUCCESS;
}
+3 -3
View File
@@ -25,13 +25,13 @@
@class NSString;
#include <mapistore/mapistore.h>
struct ldb_context;
NSString *MAPIStoreSamDBUserAttribute (struct mapistore_connection_info *connInfo,
NSString *MAPIStoreSamDBUserAttribute (struct ldb_context *samCtx,
NSString *userKey,
NSString *value,
NSString *attributeName);
NSData *MAPIStoreInternalEntryId (struct mapistore_connection_info *connInfo, NSString *username);
NSData *MAPIStoreInternalEntryId (struct ldb_context *, NSString *username);
NSData *MAPIStoreExternalEntryId (NSString *cn, NSString *email);
#endif /* MAPISTORESAMDBUTILS_H */
+4 -19
View File
@@ -24,18 +24,13 @@
#import <Foundation/NSString.h>
#include <talloc.h>
#include <ldb.h>
#include <libmapiproxy.h>
#include <samba/version.h>
#import "NSData+MAPIStore.h"
#import "MAPIStoreSamDBUtils.h"
NSString *
MAPIStoreSamDBUserAttribute (struct mapistore_connection_info *connInfo,
MAPIStoreSamDBUserAttribute (struct ldb_context *samCtx,
NSString *userKey,
NSString *value,
NSString *attributeName)
@@ -53,20 +48,10 @@ MAPIStoreSamDBUserAttribute (struct mapistore_connection_info *connInfo,
attrs[0] = [attributeName UTF8String];
searchFormat
= [NSString stringWithFormat: @"(&(objectClass=user)(%@=%%s))", userKey];
#if SAMBA_VERSION_MAJOR <= 4 && SAMBA_VERSION_MINOR < 3
ret = ldb_search (connInfo->sam_ctx, memCtx, &res,
ldb_get_default_basedn(connInfo->sam_ctx),
ret = ldb_search (samCtx, memCtx, &res, ldb_get_default_basedn(samCtx),
LDB_SCOPE_SUBTREE, attrs,
[searchFormat UTF8String],
[value UTF8String]);
#else
ret = safe_ldb_search (&connInfo->sam_ctx, memCtx, &res,
ldb_get_default_basedn(connInfo->sam_ctx),
LDB_SCOPE_SUBTREE, attrs,
[searchFormat UTF8String],
[value UTF8String]);
#endif
if (ret == LDB_SUCCESS && res->count == 1)
{
result = ldb_msg_find_attr_as_string (res->msgs[0], attrs[0], NULL);
@@ -80,7 +65,7 @@ MAPIStoreSamDBUserAttribute (struct mapistore_connection_info *connInfo,
}
NSData *
MAPIStoreInternalEntryId (struct mapistore_connection_info *connInfo, NSString *username)
MAPIStoreInternalEntryId (struct ldb_context *samCtx, NSString *username)
{
static const uint8_t const providerUid[] = { 0xdc, 0xa7, 0x40, 0xc8,
0xc0, 0x42, 0x10, 0x1a,
@@ -97,7 +82,7 @@ MAPIStoreInternalEntryId (struct mapistore_connection_info *connInfo, NSString *
type: 32
X500DN: variable */
legacyDN = MAPIStoreSamDBUserAttribute (connInfo, @"sAMAccountName", username,
legacyDN = MAPIStoreSamDBUserAttribute (samCtx, @"sAMAccountName", username,
@"legacyExchangeDN");
if (legacyDN)
{
+2 -2
View File
@@ -107,11 +107,11 @@
if ([roles containsObject: SOGoRole_ObjectCreator])
rights |= RightsCreateItems;
if ([roles containsObject: SOGoRole_ObjectEraser])
rights |= RightsDeleteAll | RightsDeleteOwn;
rights |= RightsDeleteAll;
if ([roles containsObject: SOGoCalendarRole_PublicModifier]
&& [roles containsObject: SOGoCalendarRole_PrivateModifier]
&& [roles containsObject: SOGoCalendarRole_ConfidentialModifier])
rights |= RightsReadItems | RightsEditAll | RightsEditOwn;
rights |= RightsReadItems | RightsEditAll;
else if ([roles containsObject: SOGoCalendarRole_PublicViewer]
&& [roles containsObject: SOGoCalendarRole_PrivateViewer]
&& [roles containsObject: SOGoCalendarRole_ConfidentialViewer])
+1 -1
View File
@@ -531,7 +531,7 @@
}
[vToDo setTimeStampAsDate: now];
[sogoObject saveCalendar: vCalendar];
[sogoObject saveComponent: vCalendar];
[self updateVersions];
}
+1 -1
View File
@@ -198,7 +198,7 @@ NSObjectFromSPropValue (const struct SPropValue *value)
break;
case PT_STRING8:
result = (value->value.lpszA
? [NSString stringWithUTF8String: (const char *) value->value.lpszA]
? [NSString stringWithUTF8String: value->value.lpszA]
: (id) @"");
break;
case PT_SYSTIME:
-2
View File
@@ -73,8 +73,6 @@ static NSMapTable *contextsTable = nil;
[userContext autorelease];
[contextsTable setObject: userContext forKey: username];
}
else
[userContext activate];
return userContext;
}
+1 -1
View File
@@ -228,7 +228,7 @@
mvResult = [NSMutableArray arrayWithCapacity: mvString->cValues];
for (count = 0; count < mvString->cValues; count++)
{
subObject = [NSString stringWithUTF8String: (const char *) mvString->lppszA[count]];
subObject = [NSString stringWithUTF8String: mvString->lppszA[count]];
[mvResult addObject: subObject];
}
-2
View File
@@ -41,8 +41,6 @@
+ (id) dataWithXID: (const struct XID *) xid;
- (struct XID *) asXIDInMemCtx: (void *) memCtx;
- (struct SizedXid *) asSizedXidArrayInMemCtx: (void *) memCtx
with: (uint32_t *) length;
+ (id) dataWithChangeKeyGUID: (NSString *) guidString
andCnt: (NSData *) globCnt;
+6 -40
View File
@@ -22,7 +22,6 @@
#import <NGExtensions/NSObject+Logs.h>
#import "MAPIStoreTypes.h"
#import "NSObject+MAPIStore.h"
#import "NSString+MAPIStore.h"
@@ -30,7 +29,6 @@
#undef DEBUG
#include <stdbool.h>
#include <libmapi/libmapi.h>
#include <talloc.h>
#include <util/time.h>
#include <gen_ndr/exchange.h>
@@ -138,11 +136,11 @@ static void _fillFlatUIDWithGUID (struct FlatUID_r *flatUID, const struct GUID *
NSMutableData *xidData;
struct FlatUID_r flatUID;
_fillFlatUIDWithGUID (&flatUID, &xid->NameSpaceGuid);
_fillFlatUIDWithGUID (&flatUID, &xid->GUID);
xidData = [NSMutableData dataWithCapacity: 16 + xid->LocalId.length];
xidData = [NSMutableData dataWithCapacity: 16 + xid->Size];
[xidData appendBytes: flatUID.ab length: 16];
[xidData appendBytes: xid->LocalId.data length: xid->LocalId.length];
[xidData appendBytes: xid->Data length: xid->Size];
return xidData;
}
@@ -158,12 +156,12 @@ static void _fillFlatUIDWithGUID (struct FlatUID_r *flatUID, const struct GUID *
{
xid = talloc_zero (memCtx, struct XID);
[self _extractGUID: &xid->NameSpaceGuid];
[self _extractGUID: &xid->GUID];
xid->LocalId.length = max - 16;
xid->Size = max - 16;
bytes = (uint8_t *) [self bytes];
xid->LocalId.data = talloc_memdup (xid, (bytes+16), xid->LocalId.length);
xid->Data = talloc_memdup (xid, (bytes+16), xid->Size);
}
else
{
@@ -174,38 +172,6 @@ static void _fillFlatUIDWithGUID (struct FlatUID_r *flatUID, const struct GUID *
return xid;
}
- (struct SizedXid *) asSizedXidArrayInMemCtx: (void *) memCtx
with: (uint32_t *) length
{
struct Binary_r bin;
struct SizedXid *sizedXIDArray;
bin.cb = [self length];
bin.lpb = (uint8_t *)[self bytes];
sizedXIDArray = get_SizedXidArray(memCtx, &bin, length);
if (!sizedXIDArray)
{
NSLog (@"Impossible to parse SizedXID array");
return NULL;
}
return sizedXIDArray;
}
- (NSComparisonResult) compare: (NSData *) otherGlobCnt
{
uint64_t globCnt = 0, oGlobCnt = 0;
if ([self length] > 0)
globCnt = *(uint64_t *) [self bytes];
if ([otherGlobCnt length] > 0)
oGlobCnt = *(uint64_t *) [otherGlobCnt bytes];
return MAPICNCompare (globCnt, oGlobCnt, NULL);
}
+ (id) dataWithChangeKeyGUID: (NSString *) guidString
andCnt: (NSData *) globCnt;
{
-2
View File
@@ -37,8 +37,6 @@
- (BOOL) isNever; /* occurs on 4500-12-31 */
+ (NSCalendarDate *) dateFromSystemTime: (struct SYSTEMTIME) date
andRuleYear: (uint16_t) rYear;
@end
NSComparisonResult NSDateCompare (id date1, id date2, void *);
+1 -60
View File
@@ -24,7 +24,6 @@
#import <Foundation/NSString.h>
#import <Foundation/NSTimeZone.h>
#import "MAPIStoreTypes.h"
#import "NSDate+MAPIStore.h"
#undef DEBUG
@@ -49,7 +48,7 @@ _setupRefDate ()
refDate = [[NSCalendarDate alloc]
initWithYear: 1601 month: 1 day: 1
hour: 0 minute: 0 second: 0
timeZone: utcTZ];
timeZone: [NSTimeZone timeZoneWithName: @"UTC"]];
}
+ (NSCalendarDate *) dateFromMinutesSince1601: (uint32_t) minutes
@@ -129,64 +128,6 @@ _setupRefDate ()
return [calDate yearOfCommonEra] == 4500;
}
+ (NSCalendarDate *) dateFromSystemTime: (struct SYSTEMTIME) date
andRuleYear: (uint16_t) rYear
{
NSCalendarDate *result;
NSInteger daysToDate;
NSUInteger firstDayOfWeek, year;
/* ([MS-OXOCAL] 2.2.1.41.1) When we're provided an absolute date (i.e., it
happens once), the SYSTEMTIME structure is enough to fill the date.
When we're parsing a SYSTEMTIME field from a time zone rule, however, a
relative date can be provided for the peroidicity of its periods. In this
scenario, the wYear field is empty and we have to use the wYear field in
the parent rule */
if (date.wYear != 0)
year = date.wYear;
else
year = rYear;
/* The wDay field indicates the occurrence of the wDayOfWeek within the month.
The 5th occurrence means the last one, even if it is the 4th. */
if (date.wDay < 5)
{
result = [[NSCalendarDate alloc] initWithYear: year month: date.wMonth day: 1
hour: date.wHour minute: date.wMinute second: date.wSecond
timeZone: utcTZ];
[result autorelease];
firstDayOfWeek = [result dayOfWeek];
daysToDate = 7 * (date.wDay - 1) + date.wDayOfWeek - firstDayOfWeek;
if (date.wDayOfWeek < firstDayOfWeek)
daysToDate += 7;
result = [result dateByAddingYears: 0 months: 0 days: daysToDate
hours: 0 minutes: 0
seconds: 0];
}
else
{
result = [[NSCalendarDate alloc] initWithYear: year month: date.wMonth + 1 day: 1
hour: date.wHour minute: date.wMinute second: date.wSecond
timeZone: utcTZ];
[result autorelease];
firstDayOfWeek = [result dayOfWeek];
daysToDate = date.wDayOfWeek - firstDayOfWeek;
if (date.wDayOfWeek >= firstDayOfWeek)
daysToDate -= 7;
result = [result dateByAddingYears: 0 months: 0 days: daysToDate
hours: 0 minutes: 0
seconds: 0];
}
return result;
}
@end
NSComparisonResult
+2 -11
View File
@@ -28,8 +28,6 @@
//
//
//
@class RTFFontTable;
@interface RTFHandler : NSObject
{
NSMapTable *_charsets;
@@ -43,11 +41,6 @@
- (id) initWithData: (NSData *) theData;
- (NSMutableData *) parse;
- (RTFFontTable *) parseFontTable;
- (void) mangleInternalStateWithBytesPtr: (const char*) newBytes
andCurrentPos: (int) newCurrentPos;
@end
//
@@ -74,7 +67,6 @@
int font_index;
int color_index;
int start_pos;
const unsigned short *charset;
}
@end
@@ -85,13 +77,12 @@
{
@public
NSString *family;
unsigned char charset;
NSString *charset;
NSString *name;
unsigned int pitch;
unsigned int index;
}
- (NSString *) description;
@end
//
@@ -105,8 +96,8 @@
- (void) addFontInfo: (RTFFontInfo *) theFontInfo
atIndex: (unsigned int ) theIndex;
- (RTFFontInfo *) fontInfoAtIndex: (unsigned int ) theIndex;
- (NSString *) description;
@end
+299 -732
View File
File diff suppressed because it is too large. Load diff
+5 -42
View File
@@ -1,8 +1,8 @@
/* dbmsgreader.m - this file is part of SOGo
*
* Copyright (C) 2011-2012 Inverse inc
* 2015 Enrique J. Hernandez
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,58 +33,21 @@
#import <SOGo/SOGoProductLoader.h>
#import <SOGo/SOGoSystemDefaults.h>
#import <libmapi/libmapi.h>
#import "MAPIStoreUserContext.h"
#import <SOGo/SOGoCacheGCSObject.h>
#import <SOGo/BSONCodec.h>
#import "NSObject+PropertyList.h"
Class MAPIStoreUserContextK, SOGoCacheGCSObjectK, NSStringK;
Class MAPIStoreUserContextK, SOGoCacheGCSObjectK;
static void
DumpBSONData(NSData *data)
{
id key, value;
NSEnumerator *dictEnum;
NSDictionary *dvalue;
NSMutableString *outStr;
NSUInteger max;
dvalue = [data BSONValue];
max = [dvalue count];
dictEnum = [dvalue keyEnumerator];
NSStringK = [NSString class];
outStr = [NSMutableString stringWithFormat: @"{ %d items\n", max];
while ((key = [dictEnum nextObject]))
{
uint32_t proptag = 0;
if ([key isKindOfClass: NSStringK] && [(NSString *)key intValue] > 0)
proptag = [(NSString *)key intValue];
if (proptag > 0)
{
const char *propTagName = get_proptag_name (proptag);
NSString *propName;
if (propTagName)
propName = [NSString stringWithCString: propTagName
encoding: NSUTF8StringEncoding];
else
propName = [NSString stringWithFormat: @"0x%.4x", [key unsignedLongValue]];
[outStr appendFormat: @" %@ = ", propName];
}
else
[outStr appendFormat: @" %@ = ", key];
value = [dvalue objectForKey: key];
[outStr appendFormat: @"(%@) %@,\n", NSStringFromClass ([value class]), value];
}
[outStr appendFormat: @"}\n"];
printf ("%s\n", [outStr UTF8String]);
[dvalue displayWithIndentation:0];
printf("\n");
}
static void
@@ -104,7 +67,7 @@ DbDumpObject (NSString *username, NSString *path)
{
printf("record found: %p\n", record);
content = [[record objectForKey: @"c_content"] dataByDecodingBase64];
DumpBSONData (content);
DumpBSONData(content);
}
else
NSLog (@"record not found");
+32 -33
View File
@@ -36,7 +36,6 @@
#import <NGCards/iCalDateTime.h>
#import <NGCards/iCalPerson.h>
#import <NGCards/iCalTimeZone.h>
#import <NGCards/iCalTimeZonePeriod.h>
#import <NGCards/iCalTrigger.h>
#import <SOGo/SOGoPermissions.h>
#import <SOGo/SOGoUser.h>
@@ -71,12 +70,11 @@
#include <mapistore/mapistore_nameid.h>
#import "iCalEvent+MAPIStore.h"
#import "iCalTimeZone+MAPIStore.h"
@implementation iCalEvent (MAPIStoreProperties)
- (void) _setupEventRecurrence: (NSData *) mapiRecurrenceData
inTimeZone: (iCalTimeZone *) tz
inTimeZone: (NSTimeZone *) tz
inMemCtx: (TALLOC_CTX *) memCtx
{
struct Binary_r *blob;
@@ -252,8 +250,10 @@
BOOL isAllDay;
iCalDateTime *start, *end;
iCalTimeZone *tz;
NSString *priority, *class = nil, *tzDescription = nil;
NSTimeZone *userTimeZone;
NSString *priority, *class = nil;
NSUInteger responseStatus = 0;
NSInteger tzOffset;
SOGoUser *ownerUser;
id value;
@@ -274,31 +274,7 @@
[self setAccessClass: @"PUBLIC"];
}
/* Time zone = PidLidAppointmentTimeZoneDefinitionRecur
or PidLidAppointmentTimeZoneDefinition[Start|End]Display */
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentTimeZoneDefinitionStartDisplay)];
if (!value)
{
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentTimeZoneDefinitionEndDisplay)];
if (!value)
{
/* If PidLidtimeZoneStruct, TZID SHOULD come from PidLidTimeZoneDescription,
if PidLidAppointmentTimeZoneDefinition[Start|End]Display it MUST be derived from KeyName
(MS-OXCICAL] 2.1.3.1.1.19.1) */
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentTimeZoneDefinitionRecur)];
tzDescription = [properties objectForKey: MAPIPropertyKey (PidLidTimeZoneDescription)];
}
}
if (value)
{
tz = [[iCalTimeZone alloc] iCalTimeZoneFromDefinition: value
withDescription: tzDescription
inMemCtx: memCtx];
}
else
/* The client is more likely to have the webmail's time zone than any other */
tz = [iCalTimeZone timeZoneForName: [[userContext timeZone] name]];
[(iCalCalendar *) parent addTimeZone: tz];
userTimeZone = [userContext timeZone];
/* CREATED */
value = [properties objectForKey: MAPIPropertyKey (PidTagCreationTime)];
@@ -330,13 +306,20 @@
objectForKey: MAPIPropertyKey (PidLidAppointmentSubType)];
if (value)
isAllDay = [value boolValue];
if (!isAllDay)
{
tz = [iCalTimeZone timeZoneForName: [userTimeZone name]];
[(iCalCalendar *) parent addTimeZone: tz];
}
else
tz = nil;
// recurrence-id
value
= [properties objectForKey: MAPIPropertyKey (PidLidExceptionReplaceTime)];
if (value)
[self setRecurrenceId: value];
// start
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentStartWhole)];
if (!value)
@@ -347,7 +330,15 @@
[start setTimeZone: tz];
if (isAllDay)
{
/* All-day events are set in floating time ([MS-OXCICAL] 2.1.3.1.1.20.8) */
/* when user TZ is positive (East) all-day events were not
shown properly in SOGo UI. This day delay fixes it */
tzOffset = [userTimeZone secondsFromGMTForDate: value];
if (tzOffset > 0)
{
value = [value dateByAddingYears: 0 months: 0 days: 1
hours: 0 minutes: 0
seconds: 0];
}
[start setDate: value];
[start setTimeZone: nil];
}
@@ -365,7 +356,15 @@
[end setTimeZone: tz];
if (isAllDay)
{
/* All-day events are set in floating time ([MS-OXCICAL] 2.1.3.1.1.20.8) */
/* when user TZ is positive (East) all-day events were not
shown properly in SOGo UI. This day delay fixes it */
tzOffset = [userTimeZone secondsFromGMTForDate: value];
if (tzOffset > 0)
{
value = [value dateByAddingYears: 0 months: 0 days: 1
hours: 0 minutes: 0
seconds: 0];
}
[end setDate: value];
[end setTimeZone: nil];
}
@@ -468,7 +467,7 @@
value = [properties
objectForKey: MAPIPropertyKey (PidLidAppointmentRecur)];
if (value)
[self _setupEventRecurrence: value inTimeZone: tz inMemCtx: memCtx];
[self _setupEventRecurrence: value inTimeZone: userTimeZone inMemCtx: memCtx];
/* alarm */
[self _setupEventAlarmFromProperties: properties];
-5
View File
@@ -30,11 +30,6 @@
- (struct Binary_r *) asTimeZoneStructInMemCtx: (TALLOC_CTX *) memCtx;
- (struct Binary_r *) asZoneTimeDefinitionWithFlags: (enum TZRuleFlag) flags
inMemCtx: (TALLOC_CTX *) memCtx;
- (iCalTimeZone *) iCalTimeZoneFromDefinition: (NSData *) value
withDescription: (NSString *) description
inMemCtx: (TALLOC_CTX *) memCtx;
- (NSCalendarDate *) shiftedCalendarDateForDate: (NSCalendarDate *) date;
@end
+5 -212
View File
@@ -23,15 +23,11 @@
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSString.h>
#import <Foundation/NSTimeZone.h>
#import <NGCards/iCalByDayMask.h>
#import <NGCards/iCalDateTime.h>
#import <NGCards/iCalTimeZonePeriod.h>
#import <NGCards/iCalRecurrenceRule.h>
#import "NSString+MAPIStore.h"
#import "NSData+MAPIStore.h"
#import "NSDate+MAPIStore.h"
#include <stdbool.h>
#include <stdint.h>
@@ -40,7 +36,6 @@
#include <libmapi/libmapi.h>
#import "iCalTimeZone+MAPIStore.h"
#import "MAPIStoreTypes.h"
@interface iCalTimeZonePeriod (MAPIStorePropertiesPrivate)
@@ -108,18 +103,18 @@
{
iCalTimeZonePeriod *period;
struct TimeZoneStruct tz;
int32_t lBias, dlBias;
int lBias, dlBias;
memset (&tz, 0, sizeof (struct TimeZoneStruct));
period = [self _mostRecentPeriodWithName: @"STANDARD"];
lBias = -[period secondsOffsetFromGMT] / 60;
tz.lBias = lBias;
tz.lBias = (uint32_t) lBias;
[period _fillTZDate: &tz.stStandardDate];
period = [self _mostRecentPeriodWithName: @"DAYLIGHT"];
if (!period)
tz.stStandardDate.wMonth = 0;
dlBias = -([period secondsOffsetFromGMT] / 60) - lBias;
tz.lDaylightBias = dlBias;
tz.lDaylightBias = (uint32_t) (dlBias);
[period _fillTZDate: &tz.stDaylightDate];
tz.wStandardYear = tz.stStandardDate.wYear;
tz.wDaylightYear = tz.stDaylightDate.wYear;
@@ -158,220 +153,18 @@
period = [self _mostRecentPeriodWithName: @"STANDARD"];
rule.wYear = [[period startDate] yearOfCommonEra];
lBias = -[period secondsOffsetFromGMT] / 60;
rule.lBias = lBias;
rule.lBias = (uint32_t) lBias;
[period _fillTZDate: &rule.stStandardDate];
period = [self _mostRecentPeriodWithName: @"DAYLIGHT"];
if (!period)
rule.stStandardDate.wMonth = 0;
dlBias = -([period secondsOffsetFromGMT] / 60) - lBias;
rule.lDaylightBias = dlBias;
rule.lDaylightBias = (uint32_t) (dlBias);
[period _fillTZDate: &rule.stDaylightDate];
return set_TimeZoneDefinition (memCtx, &definition);
}
- (NSString *) _offsetStringFromOffset: (NSInteger) offset
{
NSInteger offsetHours, offsetMins;
NSString *offsetSign;
/* The offset format is, eg, "+0200" for 2 hours 0 minutes ahead */
if (offset < 0)
offsetSign = @"-";
else
offsetSign = @"+";
offsetHours = abs (offset) / 60;
offsetMins = abs (offset) % 60;
return [NSString stringWithFormat: @"%@%d%d%d%d",
offsetSign, offsetHours / 10, offsetHours % 10,
offsetMins / 10, offsetMins % 10];
}
- (NSString *) _rRuleStringFromSystemTime: (struct SYSTEMTIME) date
{
NSString *result, *byDay;
/* The conversion tables between the SYSTEMTIME fields and the RRULE ones
can be found at [MS-OXCICAL] 2.1.3.2.1 */
if (date.wDay == 5)
byDay = @"-1";
else
byDay = [NSString stringWithFormat: @"%d", date.wDay];
switch (date.wDayOfWeek)
{
case iCalWeekDaySunday:
byDay = [byDay stringByAppendingString: @"SU"];
break;
case iCalWeekDayMonday:
byDay = [byDay stringByAppendingString: @"MO"];
break;
case iCalWeekDayTuesday:
byDay = [byDay stringByAppendingString: @"TU"];
break;
case iCalWeekDayWednesday:
byDay = [byDay stringByAppendingString: @"WE"];
break;
case iCalWeekDayThursday:
byDay = [byDay stringByAppendingString: @"TH"];
break;
case iCalWeekDayFriday:
byDay = [byDay stringByAppendingString: @"FR"];
break;
case iCalWeekDaySaturday:
byDay = [byDay stringByAppendingString: @"SA"];
break;
}
result = [NSString stringWithFormat: @"FREQ=YEARLY;BYDAY=%@;BYMONTH=%d", byDay, date.wMonth];
return result;
}
- (iCalTimeZone *) iCalTimeZoneFromDefinition: (NSData *) value
withDescription: (NSString *) description
inMemCtx: (TALLOC_CTX *) memCtx
{
BOOL daylightDefined = NO, ruleFound = NO;
iCalDateTime *daylightStart, *standardStart;
iCalRecurrenceRule *daylightRRule, *standardRRule;
iCalTimeZone *tz = nil;
iCalTimeZonePeriod *daylight, *standard;
NSCalendarDate *dlStartValue, *stStartValue;
NSString *strOffsetFrom, *strOffsetTo, *tzID;
char *keyName;
struct Binary_r *binValue;
struct SYSTEMTIME initDate;
struct TimeZoneDefinition *definition;
struct TZRule rule;
uint16_t count;
binValue = [value asBinaryInMemCtx: memCtx];
definition = get_TimeZoneDefinition (memCtx, binValue);
if (!definition)
return nil;
if (!definition->cRules)
goto end;
for (count = 0; count < definition->cRules; count++)
{
/* ([MS-OXCICAL] 2.1.3.1.1.19) The TZRule with the
TZRULE_FLAG_EFFECTIVE_TZREG bit set in the TZRule flags field
is the one that MUST be exported */
if (definition->TZRules[count].flags & TZRULE_FLAG_EFFECTIVE_TZREG)
{
rule = definition->TZRules[count];
ruleFound = YES;
break;
}
}
if (!ruleFound)
goto end;
if (!description)
{
/* The cbHeader field contains the size, in bytes of the Reserved (2b),
cchKeyName (2b) keyName (variable Unicode string) and cRules (2b)
([MS-OXOCAL] 2.2.1.41). The keyName field is a non-NULL-terminated
char array. */
keyName = talloc_strndup (memCtx, definition->keyName, (definition->cbHeader - 6) / 2);
tzID = [NSString stringWithCString: keyName
encoding: [NSString defaultCStringEncoding]];
talloc_free (keyName);
}
else
tzID = [NSString stringWithString: description];
tz = [iCalTimeZone groupWithTag: @"vtimezone"];
[tz addChild: [CardElement simpleElementWithTag: @"tzid"
value: tzID]];
if (rule.stStandardDate.wMonth != 0)
daylightDefined = YES;
/* STANDARD TIME ([MS-OXCICAL] 2.1.3.1.1.19.2) */
standard = [iCalTimeZonePeriod groupWithTag: @"standard"];
/* TZOFFSETFROM = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lDaylightBias) */
strOffsetFrom = [self _offsetStringFromOffset: -1 * (rule.lBias + rule.lDaylightBias)];
[standard addChild: [CardElement simpleElementWithTag: @"tzoffsetfrom"
value: strOffsetFrom]];
/* TZOFFSETTO = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lStandardBias) */
strOffsetTo = [self _offsetStringFromOffset: -1 * (rule.lBias + rule.lStandardBias)];
[standard addChild: [CardElement simpleElementWithTag: @"tzoffsetto"
value: strOffsetTo]];
/* DTSTART & RRULE are derived from the stStandardDate and wYear properties */
standardStart = [iCalDateTime elementWithTag: @"dtstart"];
initDate = rule.stStandardDate;
stStartValue = [NSCalendarDate dateFromSystemTime: initDate
andRuleYear: rule.wYear];
[standardStart setDateTime: stStartValue];
[standard addChild: standardStart];
if (daylightDefined)
{
standardRRule = [[iCalRecurrenceRule alloc] initWithString: [self _rRuleStringFromSystemTime: initDate]];
[standard addChild: standardRRule];
/* DAYLIGHT SAVING TIME ([MS-OXCICAL] 2.1.3.1.1.19.3) */
daylight = [iCalTimeZonePeriod groupWithTag: @"daylight"];
/* TZOFFSETFROM = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lStandardBias) */
[daylight addChild: [CardElement simpleElementWithTag: @"tzoffsetfrom"
value: strOffsetTo]];
/* TZOFFSETTO = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lDaylightBias) */
[daylight addChild: [CardElement simpleElementWithTag: @"tzoffsetto"
value: strOffsetFrom]];
/* DTSTART & RRULE are derived from the stDaylightDate and wYear properties */
daylightStart = [iCalDateTime elementWithTag: @"dtstart"];
initDate = rule.stDaylightDate;
dlStartValue = [NSCalendarDate dateFromSystemTime: initDate
andRuleYear: rule.wYear];
[daylightStart setDateTime: dlStartValue];
[daylight addChild: daylightStart];
daylightRRule = [[iCalRecurrenceRule alloc] initWithString: [self _rRuleStringFromSystemTime: initDate]];
[daylight addChild: daylightRRule];
[tz addChild: daylight];
}
[tz addChild: standard];
end:
talloc_free (definition);
return tz;
}
/**
* Adjust a date in this vTimeZone to its representation in UTC
* Example: Timezone is +0001, the date is 2015-12-15 00:00:00 +0000
* it returns 2015-12-14 23:00:00 +0000
* @param date the date to adjust to the timezone.
* @return a new GMT date adjusted with the offset of the timezone.
*/
- (NSCalendarDate *) shiftedCalendarDateForDate: (NSCalendarDate *) date
{
NSCalendarDate *tmpDate;
tmpDate = [date copy];
[tmpDate autorelease];
[tmpDate setTimeZone: utcTZ];
return [tmpDate addYear: 0 month: 0 day: 0
hour: 0 minute: 0
second: -[[self periodForDate: tmpDate] secondsOffsetFromGMT]];
}
@end
+27
View File
@@ -0,0 +1,27 @@
[![SOGo Logo](http://www.sogo.nu/fileadmin/sogo/logos/sogo.logo.png)](http://www.sogo.nu/)
Share your calendars, address books and mails in your community with a completely free and open source solution.
Let your Mozilla Thunderbird/Lightning, Microsoft Outlook, Apple iCal/iPhone, Android and BlackBerry users collaborate using a modern platform.
## What is SOGo?
SOGo is [fully supported](http://www.sogo.nu/support/commercial_support.html) and [trusted](http://www.sogo.nu/tour/testimonials.html) groupware server with a focus on scalability and open standards. SOGo is released under the GNU GPL/LGPL v2 and above.
SOGo provides a rich AJAX-based Web interface and supports multiple native clients through the use of standard protocols such as CalDAV, CardDAV and GroupDAV.
SOGo is the missing component of your infrastructure; it sits in the middle of your servers to offer your users an uniform and complete interface to access their information. It has been deployed in production environments where thousands of users are involved.
[![Sogo diagram](http://www.sogo.nu/uploads/pics/sogo.png)](http://www.sogo.nu/)
[Learn more...](http://www.sogo.nu/about/overview.html)
## Microsoft Outlook Compatible
SOGo offers native Microsoft Outlook compatibility using the [OpenChange](http://www.openchange.org/) backend developed by [Inverse](http://www.inverse.ca/). This means Microsoft Outlook 2003, 2007, 2010 and 2013 can talk directly to SOGo &ndash; just like if it was a Microsoft Exchange server. **No plugins are required in Outlook to make this work**.
The following screencast shows Outlook 2010 connected to SOGo as if it was an Exchange server, along the Web interface of SOGo.
[![SOGo Screencast](http://img.youtube.com/vi/1hcBSB4Kxww/0.jpg)](http://www.youtube.com/watch?v=1hcBSB4Kxww)
[![SOGo on GitHub](http://www.sogo.nu/fileadmin/images/icon.github.png)](https://github.com/inverse-inc/sogo/) [![SOGo Ohloh](http://www.sogo.nu/fileadmin/images/icon.ohloh.png)](https://www.ohloh.net/p/sogo) [![SOGo on Twitter](http://www.sogo.nu/fileadmin/images/icon.twitter.png)](http://twitter.com/scalableogo) [![SOGo on SourceForge](http://www.sogo.nu/fileadmin/images/icon.sourceforge.png)](http://sourceforge.net/projects/sogo-zeg) [![SOGo on free code](http://www.sogo.nu/fileadmin/images/icon.freecode.png)](https://freecode.com/projects/sogo-inverse) [![SOGo on LinkedIn](http://www.sogo.nu/fileadmin/images/icon.linkedin.png)](http://www.linkedin.com/groups/SOGo-Groupware-4164805)
+1 -1
View File
@@ -500,7 +500,7 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
ms = [NSMutableString stringWithCapacity: 256];
[ms appendFormat: @"<0x%p[%@]: ", self, NSStringFromClass ([self class])];
[ms appendFormat: @" #adaptors=%d", (int)[urlToAdaptor count]];
[ms appendFormat: @" #adaptors=%d", [urlToAdaptor count]];
[ms appendString: @">"];
return ms;
+1 -1
View File
@@ -414,7 +414,7 @@
if (group)
[str appendFormat: @"%@ (group: %@)\n", tag, group];
else
[str appendFormat: @"%@\n", tag];
[str appendFormat: @"%@\n", tag, group];
[str appendString: [self versitString]];
+1 -1
View File
@@ -409,7 +409,7 @@ static NGCardsSaxHandler *sax = nil;
max = [children count];
if (max > 0)
{
[str appendFormat: @"\n %d children: {\n", (int)[children count]];
[str appendFormat: @"\n %d children: {\n", [children count]];
for (count = 0; count < max; count++)
[str appendFormat: @" %@\n",
[[children objectAtIndex: count] description]];
+5 -5
View File
@@ -32,16 +32,16 @@
- (NSString *) iCalFormattedDateTimeString
{
return [NSString stringWithFormat: @"%.4d%.2d%.2dT%.2d%.2d%.2d",
(int)[self yearOfCommonEra], (int)[self monthOfYear],
(int)[self dayOfMonth], (int)[self hourOfDay],
(int)[self minuteOfHour], (int)[self secondOfMinute]];
[self yearOfCommonEra], [self monthOfYear],
[self dayOfMonth], [self hourOfDay],
[self minuteOfHour], [self secondOfMinute]];
}
- (NSString *) iCalFormattedDateString
{
return [NSString stringWithFormat: @"%.4d%.2d%.2d",
(int)[self yearOfCommonEra], (int)[self monthOfYear],
(int)[self dayOfMonth]];
[self yearOfCommonEra], [self monthOfYear],
[self dayOfMonth]];
}
@end
+2 -2
View File
@@ -53,10 +53,10 @@
[aString appendString: @","];
subValue = [self objectAtIndex: count];
/* We MUST quote attribute values that have a ":" or "," in them
/* We MUST quote attribute values that have a ":" in them
and that not already quoted */
if (asAttributes && [subValue length] > 2
&& ([subValue rangeOfString: @":"].length || [subValue rangeOfString: @","].length)
&& [subValue rangeOfString: @":"].length
&& [subValue characterAtIndex: 0] != '"'
&& ![subValue hasSuffix: @"\""])
subValue = [NSString stringWithFormat: @"\"%@\"", subValue];
-15
View File
@@ -158,31 +158,16 @@
NSMutableString *string;
unsigned int len, i;
unichar c;
BOOL isQuoted;
len = [self length];
string = [NSMutableString stringWithCapacity: len * 1.5];
isQuoted = NO;
for (i = 0; i < len; i++)
{
c = [self characterAtIndex: i];
if (isQuoted)
{
if (c == '"')
isQuoted = NO;
[string appendFormat: @"%C", c];
continue;
}
switch (c)
{
case '"':
isQuoted = YES;
[string appendFormat: @"%C", c];
break;
case '\\':
[string appendString: @"\\\\"];
break;
+4 -3
View File
@@ -1,8 +1,6 @@
/* iCalByDayMask.h - this file is part of SOPE
*
* Copyright (C) 2010 Wolfgang Sourdeau
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2010-2015 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
@@ -55,6 +53,8 @@ typedef iCalWeekOccurrence iCalWeekOccurrences[7];
- (id) initWithDays: (iCalWeekOccurrences) theDays;
+ (id) byDayMaskWithRuleString: (NSString *) byDayRule;
- (id) initWithRuleString: (NSString *) byDayRule;
+ (id) byDayMaskWithDaysAndOccurrences: (NSArray *) values;
- (id) initWithDaysAndOccurrences: (NSArray *) values;
- (BOOL) occursOnDay: (iCalWeekDay) weekDay;
- (BOOL) occursOnDay: (iCalWeekDay) weekDay
@@ -71,6 +71,7 @@ typedef iCalWeekOccurrence iCalWeekOccurrences[7];
- (NSString *) asRuleString;
- (NSString *) asRuleStringWithIntegers;
- (NSArray *) asRuleArray;
@end
+159 -20
View File
@@ -1,8 +1,6 @@
/* iCalByDayMask.m - this file is part of SOPE
*
* Copyright (C) 2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2010-2015 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
@@ -21,7 +19,9 @@
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#import "iCalByDayMask.h"
@@ -39,10 +39,10 @@
+ (id) byDayMaskWithDays: (iCalWeekOccurrences) theDays
{
id o;
o = [[self alloc] initWithDays: theDays];
AUTORELEASE(o);
return o;
}
@@ -62,7 +62,7 @@
{
id o;
iCalWeekOccurrences d;
d[iCalWeekDaySunday] = 0;
d[iCalWeekDayMonday] = iCalWeekOccurrenceAll;
d[iCalWeekDayTuesday] = iCalWeekOccurrenceAll;
@@ -72,7 +72,7 @@
d[iCalWeekDaySaturday] = 0;
o = [[self alloc] initWithDays: d];
AUTORELEASE(o);
return o;
}
@@ -102,7 +102,7 @@
if (self)
{
memset(days, 0, 7 * sizeof(iCalWeekOccurrence));
if ([byDayRule length] > 0)
{
values = [byDayRule componentsSeparatedByString: @","];
@@ -120,7 +120,7 @@
[value getCharacters: chars
range: NSMakeRange(valueLength - 2, 2)];
switch (chars[0])
{
case 'M': day = iCalWeekDayMonday;
@@ -142,7 +142,7 @@
day = iCalWeekDaySunday;
break;
}
if (day != iCalWeekDayUnknown)
{
c = [value characterAtIndex: 0];
@@ -157,15 +157,15 @@
digitStart = 1;
c = [value characterAtIndex: 1];
}
i = digitStart;
while (i < valueLength && isdigit(c))
{
i++;
c = [value characterAtIndex: i];
}
if (i != digitStart)
order = [[value substringWithRange: NSMakeRange(digitStart, (i - digitStart))] intValue];
@@ -186,7 +186,123 @@
}
}
}
return self;
}
+ (id) byDayMaskWithDaysAndOccurrences: (NSArray *) values
{
id o;
o = [[self alloc] initWithDaysAndOccurrences: values];
AUTORELEASE(o);
return o;
}
- (id) initWithDaysAndOccurrences: (NSArray *) values
{
unsigned int count, max;
NSString *value;
unichar c, chars[2];
unsigned int valueLength, i, digitStart, order;
iCalWeekDay day;
id mask;
BOOL reverse;
self = [super init];
if (self)
{
memset(days, 0, 7 * sizeof(iCalWeekOccurrence));
max = [values count];
for (count = 0; count < max; count++)
{
mask = [values objectAtIndex: count];
if (![mask isKindOfClass: [NSDictionary class]])
continue;
value = [[mask objectForKey: @"day"] uppercaseString];
valueLength = [value length];
if (valueLength > 1)
{
day = iCalWeekDayUnknown;
reverse = NO;
digitStart = 0;
order = 0;
[value getCharacters: chars
range: NSMakeRange(0, valueLength)];
switch (chars[0])
{
case 'M': day = iCalWeekDayMonday;
break;
case 'W': day = iCalWeekDayWednesday;
break;
case 'F': day = iCalWeekDayFriday;
break;
case 'T':
if (chars[1] == 'U')
day = iCalWeekDayTuesday;
else if (chars[1] == 'H')
day = iCalWeekDayThursday;
break;
case 'S':
if (chars[1] == 'A')
day = iCalWeekDaySaturday;
else if (chars[1] == 'U')
day = iCalWeekDaySunday;
break;
}
if (day != iCalWeekDayUnknown)
{
value = [mask objectForKey: @"occurrence"];
valueLength = [value length];
if (valueLength > 0)
{
c = [value characterAtIndex: 0];
if (c == '-')
{
digitStart = 1;
reverse = YES;
}
else if (c == '+')
{
digitStart = 1;
}
i = digitStart;
while (i < valueLength)
{
c = [value characterAtIndex: i];
i++;
if (!isdigit(c))
break;
}
if (i != digitStart)
order = [[value substringWithRange: NSMakeRange(digitStart, (i - digitStart))] intValue];
}
if (order > 0 && order < 6)
{
order = pow (2, order - 1);
if (reverse)
order = order << 5;
days[day] |= order;
//NSLog(@"*** iCalByDayMask [%i] %@ : day = %i, order = %i, result = %i", count, byDayRule, day, order, days[day]);
}
else
{
days[day] = iCalWeekOccurrenceAll;
}
}
}
}
}
return self;
}
@@ -214,7 +330,7 @@
withWeekNumber: (int) week
{
unsigned int absWeek, order;
absWeek = abs (week);
order = 0;
if (absWeek > 0 && absWeek < 6)
@@ -223,7 +339,7 @@
if (week < 0)
order = order << 5;
}
return ((days[weekDay] & order) > 0);
}
@@ -249,7 +365,7 @@
if (days[i])
day = i;
}
return day;
}
@@ -260,10 +376,10 @@
occurrence = 0;
day = [self firstDay];
if (day > -1 && days[day] != iCalWeekOccurrenceAll)
occurrence = [self _iCalWeekOccurrenceIntValue: days[day]];
return occurrence;
}
@@ -323,7 +439,7 @@
[rules addObject: rule];
}
}
return [rules componentsJoinedByString: @","];
}
@@ -344,4 +460,27 @@
return s;
}
- (NSArray *) asRuleArray
{
NSMutableArray *rules;
NSMutableDictionary *rule;
int i;
rules = [NSMutableArray array];
for (i = 0; i < 7; i++)
{
if (days[i])
{
rule = [NSMutableDictionary dictionary];
if (days[i] != iCalWeekOccurrenceAll)
[rule setObject: [NSNumber numberWithInt: [self _iCalWeekOccurrenceIntValue: days[i]]]
forKey: @"occurrence"];
[rule setObject: iCalWeekDayString[i]
forKey: @"day"];
[rules addObject: rule];
}
}
return rules;
}
@end /* iCalByDayMask */
+2 -2
View File
@@ -94,8 +94,8 @@ typedef enum
- (void) increaseSequence;
/* url can either be set as NSString or NSURL */
- (void) setAttach: (id) _value;
- (NSURL *) attach;
- (void) setAttach: (NSArray *) _value;
- (NSArray *) attach;
- (void) setUrl: (id) _value;
- (NSURL *) url;
+33 -20
View File
@@ -27,7 +27,6 @@
#import "NSCalendarDate+NGCards.h"
#import "iCalAlarm.h"
#import "iCalCalendar.h"
#import "iCalDateTime.h"
#import "iCalEntityObject.h"
#import "iCalEvent.h"
@@ -269,12 +268,9 @@
- (void) setRecurrenceId: (NSCalendarDate *) newRecId
{
iCalDateTime* recurrenceId;
BOOL isMasterAllDay;
isMasterAllDay = [[[[self parent] events] objectAtIndex: 0] isAllDay];
recurrenceId = (iCalDateTime *) [self uniqueChildWithTag: @"recurrence-id"];
if ([self isKindOfClass: [iCalEvent class]] && isMasterAllDay)
if ([self isKindOfClass: [iCalEvent class]] && [(iCalEvent *)self isAllDay])
[recurrenceId setDate: newRecId];
else
[recurrenceId setDateTime: newRecId];
@@ -404,32 +400,49 @@
return [self childrenWithTag: @"valarm"];
}
- (void) setAttach: (id) _value
- (void) setAttach: (NSArray *) _value
{
NSString *aString;
id anObject;
int count, max;
if ([_value isKindOfClass: [NSString class]])
aString = _value;
else if ([_value isKindOfClass: [NSURL class]])
aString = [_value absoluteString];
else
aString = @"";
[[self uniqueChildWithTag: @"attach"] setSingleValue: aString forKey: @""];
max = [_value count];
for (count = 0; count < max; count++)
{
anObject = [_value objectAtIndex: count];
if ([anObject isKindOfClass: [NSURL class]])
{
aString = [anObject absoluteString];
}
else
aString = anObject;
[self addChild: [CardElement simpleElementWithTag: @"attach" value: aString]];
}
}
- (NSURL *) attach
- (NSArray *) attach
{
NSArray *elements;
NSMutableArray *attachUrls;
NSString *stringAttach;
NSURL *url;
int count, max;
stringAttach = [[self uniqueChildWithTag: @"attach"] flattenedValuesForKey: @""];
url = [NSURL URLWithString: stringAttach];
elements = [self childrenWithTag: @"attach"];
max = [elements count];
attachUrls = [NSMutableArray arrayWithCapacity: max];
for (count = 0; count < max; count++)
{
stringAttach = [[elements objectAtIndex: count] flattenedValuesForKey: @""];
url = [NSURL URLWithString: stringAttach];
if (!url && [stringAttach length] > 0)
url = [NSURL URLWithString: [NSString stringWithFormat: @"http://%@", stringAttach]];
if (!url && [stringAttach length] > 0)
url = [NSURL URLWithString: [NSString stringWithFormat: @"http://%@", stringAttach]];
[attachUrls addObject: [url absoluteString]];
}
return url;
return attachUrls;
}
- (void) setUrl: (id) _value
@@ -348,7 +348,7 @@ static inline unsigned iCalDoWForNSDoW (int dow)
if ([byDayMask occursOnDay: currentWeekDay])
{
if ([bySetPos containsObject:
[NSString stringWithFormat: @"%d", (int)currentPos]])
[NSString stringWithFormat: @"%d", currentPos]])
monthDays[monthDay+1] = YES;
currentPos++;
}
@@ -362,7 +362,7 @@ static inline unsigned iCalDoWForNSDoW (int dow)
if ([byDayMask occursOnDay: currentWeekDay])
{
if ([bySetPos containsObject:
[NSString stringWithFormat: @"%d", (int)currentPos]])
[NSString stringWithFormat: @"%d", currentPos]])
monthDays[monthDay] = YES;
currentPos--;
}
+2
View File
@@ -44,6 +44,8 @@ typedef enum {
@interface iCalPerson : CardElement
+ (NSString *) descriptionForParticipationStatus: (iCalPersonPartStat) _status;
/* accessors */
- (void)setCn:(NSString *)_s;
+46 -35
View File
@@ -25,6 +25,48 @@
@implementation iCalPerson
+ (NSString *) descriptionForParticipationStatus: (iCalPersonPartStat) _status
{
NSString *stat;
switch (_status) {
case iCalPersonPartStatUndefined:
stat = @"";
break;
case iCalPersonPartStatAccepted:
stat = @"ACCEPTED";
break;
case iCalPersonPartStatDeclined:
stat = @"DECLINED";
break;
case iCalPersonPartStatTentative:
stat = @"TENTATIVE";
break;
case iCalPersonPartStatDelegated:
stat = @"DELEGATED";
break;
case iCalPersonPartStatCompleted:
stat = @"COMPLETED";
break;
case iCalPersonPartStatInProcess:
stat = @"IN-PROCESS";
break;
case iCalPersonPartStatExperimental:
case iCalPersonPartStatOther:
// [NSException raise:NSInternalInconsistencyException
// format:@"Attempt to set meaningless "
// @"participationStatus (%d)!", _status];
stat = nil; /* keep compiler happy */
break;
default:
stat = @"NEEDS-ACTION";
break;
}
return stat;
}
/* accessors */
- (void) setCn: (NSString *) _s
@@ -132,44 +174,13 @@
{
NSString *stat;
switch (_status) {
case iCalPersonPartStatUndefined:
stat = @"";
break;
case iCalPersonPartStatAccepted:
stat = @"ACCEPTED";
break;
case iCalPersonPartStatDeclined:
stat = @"DECLINED";
break;
case iCalPersonPartStatTentative:
stat = @"TENTATIVE";
break;
case iCalPersonPartStatDelegated:
stat = @"DELEGATED";
break;
case iCalPersonPartStatCompleted:
stat = @"COMPLETED";
break;
case iCalPersonPartStatInProcess:
stat = @"IN-PROCESS";
break;
case iCalPersonPartStatExperimental:
case iCalPersonPartStatOther:
// [NSException raise:NSInternalInconsistencyException
// format:@"Attempt to set meaningless "
// @"participationStatus (%d)!", _status];
stat = nil; /* keep compiler happy */
break;
default:
stat = @"NEEDS-ACTION";
break;
}
stat = [iCalPerson descriptionForParticipationStatus: _status];
if (stat)
[self setPartStat:stat];
}
- (iCalPersonPartStat)participationStatus {
- (iCalPersonPartStat) participationStatus {
NSString *stat;
stat = [[self partStat] uppercaseString];
@@ -256,7 +267,7 @@
- (BOOL)isEqual:(id)_other {
if(_other == nil)
return NO;
if([_other class] != object_getClass(self))
if([_other class] != self->isa)
return NO;
if([_other hash] != [self hash])
return NO;
+1
View File
@@ -75,6 +75,7 @@ extern NSString *iCalWeekDayString[];
- (void) setFrequency: (iCalRecurrenceFrequency) _frequency;
- (iCalRecurrenceFrequency) frequency;
- (iCalRecurrenceFrequency) valueForFrequency: (NSString *) value;
- (NSString *) frequencyForValue: (iCalRecurrenceFrequency) freq;
- (void) setRepeatInterval: (int) _repeatInterval;
- (int) repeatInterval;
+2 -2
View File
@@ -309,10 +309,10 @@ NSString *iCalWeekDayString[] = { @"SU", @"MO", @"TU", @"WE", @"TH", @"FR",
else if ([frequency isEqualToString:@"SECONDLY"])
freq = iCalRecurrenceFrequenceSecondly;
else
freq = (iCalRecurrenceFrequency)NSNotFound;
freq = NSNotFound;
}
else
freq = (iCalRecurrenceFrequency)NSNotFound;
freq = NSNotFound;
return freq;
}
+3 -2
View File
@@ -1,6 +1,6 @@
/* iCalTimeZone.m - this file is part of SOPE
*
* Copyright (C) 2006-2014 Inverse inc.
* Copyright (C) 2006-2015 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
@@ -147,7 +147,8 @@ static NSArray *knownTimeZones;
if (ext.location != NSNotFound)
{
zone = [zone substringToIndex: ext.location];
[timeZoneNames addObject: zone];
if (![timeZoneNames containsObject: zone])
[timeZoneNames addObject: zone];
}
}
}
+4 -36
View File
@@ -161,11 +161,8 @@
minute: [tzStart minuteOfHour] second: 0
timeZone: [NSTimeZone timeZoneWithName: @"GMT"]];
tmpDate = [tmpDate addYear: 0
month: ((pos > 0) ? 0 : 1)
day: 0
hour: 0
minute: 0
tmpDate = [tmpDate addYear: 0 month: ((pos > 0) ? 0 : 1)
day: 0 hour: 0 minute: 0
second: 0];
/* If the day of the time change is "-XSU", we need to determine whether the
@@ -200,41 +197,12 @@
END:STANDARD
END:VTIMEZONE
The time changes occur on a Sunday, but in March, the 1st is a Sunday itself and in November
The time changes occure on a Sunday, but in March, the 1st is a Sunday itself and in November
the 1st is also a Sunday. If we don't decrement "pos" by one, tmpDate (which is set to March or November 1st
because of "day: 1" will have 14 more days added for March and 7 more days added for November - which will
effectively shift the time change by a whole week.
In Europe/Berlin, we have a different use-case for November. In 2015, November 1st is a Sunday.
The time change in November must occur on October 25th but since tmpDate will be November 1st,
so a Sunday, dateDayOfWeek will be 0 and dayOfWeek will also be 0 we would decrement tmpDate by 14 days,
which is incorrect because it would shift the timezone change one week earlier. We take care about this
one with check if pos is greater or equal than 0 and if so, we don't decrement it.
BEGIN:VCALENDAR
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:Europe/Berlin
X-LIC-LOCATION:Europe/Berlin
BEGIN:DAYLIGHT
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
TZNAME:CEST
DTSTART:19700329T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
TZNAME:CET
DTSTART:19701025T030000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
END:STANDARD
END:VTIMEZONE
END:VCALENDAR
*/
if (dayOfWeek == dateDayOfWeek && pos >= 0)
if (dayOfWeek == dateDayOfWeek)
pos--;
offset = (dayOfWeek - dateDayOfWeek) + (pos * 7);
+1
View File
@@ -39,6 +39,7 @@
- (NSString *) percentComplete;
- (void) setDue: (NSCalendarDate *) _date;
- (void) setAllDayDue: (NSCalendarDate *) _date;
- (NSCalendarDate *) due;
- (void) setCompleted: (NSCalendarDate *) _date;
+6
View File
@@ -65,6 +65,12 @@
setDateTime: newDueDate];
}
- (void) setAllDayDue: (NSCalendarDate *) newDueDate
{
[(iCalDateTime *) [self uniqueChildWithTag: @"due"]
setDate: newDueDate];
}
- (NSCalendarDate *) due
{
return [(iCalDateTime *) [self uniqueChildWithTag: @"due"]
Loaded 100 of 1583 files, more files were not shown because too many files have changed in this diff. Show more