diff --git a/ActiveSync/SOGoActiveSyncDispatcher.m b/ActiveSync/SOGoActiveSyncDispatcher.m
index 82c1868fc..0d5287a8a 100644
--- a/ActiveSync/SOGoActiveSyncDispatcher.m
+++ b/ActiveSync/SOGoActiveSyncDispatcher.m
@@ -457,13 +457,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
NSData *d;
//
- // We mark the cache object as deleted
+ // We destroy the cache object
//
key = [NSString stringWithFormat: @"%@+%@", [context objectForKey: @"DeviceId"], [folderToDelete nameInContainer]];
o = [SOGoCacheGCSObject objectWithName: key inContainer: nil];
[o setTableUrl: [self folderTableURL]];
- [o reloadIfNeeded];
- [o delete];
+ [o destroy];
//
// We update the FolderSync's synckey
@@ -697,7 +696,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if (![imapGUIDs allKeysForObject: cKey])
{
- // Delete folders cache content to avoid stale data if a new folder gets created with the same name
+ // Destroy folders cache content to avoid stale data if a new folder gets created with the same name
key = [NSString stringWithFormat: @"%@+folder%@", [context objectForKey: @"DeviceId"], [cachedGUIDs objectForKey: cKey]];
o = [SOGoCacheGCSObject objectWithName: key inContainer: nil];
[o setObjectType: ActiveSyncFolderCacheObject];
@@ -711,8 +710,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
command_count++;
}
- [[o properties] removeAllObjects];
- [o save];
+ [o destroy];
}
}
diff --git a/ActiveSync/common.make b/ActiveSync/common.make
index d53fcef8e..505f53f88 100644
--- a/ActiveSync/common.make
+++ b/ActiveSync/common.make
@@ -18,7 +18,6 @@ ADDITIONAL_INCLUDE_DIRS += \
ADDITIONAL_LIB_DIRS += \
-L../SoObjects/SOGo/SOGo.framework/ \
-L../SoObjects/SOGo/$(GNUSTEP_OBJ_DIR)/ \
- -L../OGoContentStore/$(GNUSTEP_OBJ_DIR)/ \
-L../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ \
-L/usr/local/lib
diff --git a/Apache/SOGo-apple-ab.conf b/Apache/SOGo-apple-ab.conf
index 9c42bf1cd..936fb98cc 100644
--- a/Apache/SOGo-apple-ab.conf
+++ b/Apache/SOGo-apple-ab.conf
@@ -28,8 +28,13 @@
ProxyPass /SOGo http://127.0.0.1:20000/SOGo interpolate
ProxyPass / http://127.0.0.1:20000/SOGo/dav/ interpolate
- Order allow,deny
- Allow from all
+
+ Order deny,allow
+ Allow from all
+
+ = 2.4>
+ Require all granted
+
diff --git a/Apache/SOGo.conf b/Apache/SOGo.conf
index f36fbbe8f..bfe7560ba 100644
--- a/Apache/SOGo.conf
+++ b/Apache/SOGo.conf
@@ -5,8 +5,14 @@ Alias /SOGo/WebServerResources/ \
AllowOverride None
- Order deny,allow
- Allow from all
+
+
+ Order deny,allow
+ Allow from all
+
+ = 2.4>
+ Require all granted
+
# Explicitly allow caching of static content to avoid browser specific behavior.
# A resource's URL MUST change in order to have the client load the new version.
diff --git a/ChangeLog b/ChangeLog
index 7c75ed5a7..ebfb6b9e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,1499 @@
+commit 69c8aa074364395a8bdf3705d74ee6a93c11d54a
+Author: Alexandre Cloutier
+Date: Wed Sep 10 13:22:36 2014 -0400
+
+ quickfix for IE for searchInbox
+
+M UI/WebServerResources/UIxMailSearch.js
+
+commit 36b833ccb58353d36085a9fc8ca087f9684b7efb
+Author: Alexandre Cloutier
+Date: Wed Sep 10 13:02:13 2014 -0400
+
+ bugFix InboxSearch IMAP query keywords
+
+M UI/WebServerResources/UIxMailSearch.js
+
+commit 9d6bcb00bcbae81d55fa2d5c27d3e6458d5a2bb9
+Author: Francis Lachapelle
+Date: Wed Sep 10 11:58:47 2014 -0400
+
+ Fix compilation warning
+
+M UI/MailerUI/UIxMailEditor.m
+
+commit 1dd3dbacb50a03a6e59508d3f504754ded0e1e5b
+Author: Francis Lachapelle
+Date: Wed Sep 10 11:37:52 2014 -0400
+
+ Various fixes and improvements to the Mail module
+
+M UI/MailerUI/English.lproj/Localizable.strings
+M UI/MailerUI/French.lproj/Localizable.strings
+M UI/MailerUI/Toolbars/SOGoMailFolder.toolbar
+M UI/Templates/MailerUI/UIxMailSearch.wox
+M UI/WebServerResources/MailerUI.js
+M UI/WebServerResources/UIxMailSearch.css
+M UI/WebServerResources/UIxMailSearch.js
+M UI/WebServerResources/generic.css
+
+commit c441fa5b802a7920315c927479621de92937846c
+Author: Francis Lachapelle
+Date: Wed Sep 10 10:47:18 2014 -0400
+
+ Various fix and improvements to Scheduler module
+
+M UI/Scheduler/French.lproj/Localizable.strings
+M UI/Templates/SchedulerUI/UIxCalViewPrint.wox
+M UI/WebServerResources/SchedulerUI.js
+
+commit 7e297ad56c76d3c3477d66dcf0407889d1b40479
+Author: Francis Lachapelle
+Date: Wed Sep 10 10:58:46 2014 -0400
+
+ Remove spaces
+
+M UI/WebServerResources/SchedulerUI.js
+
+commit 8eb4212f5ddc8b97c8a1cee7b5b08e2652f2b04f
+Author: Francis Lachapelle
+Date: Wed Sep 10 10:49:54 2014 -0400
+
+ Various fix and improvements to Mail module
+
+M UI/WebServerResources/MailerUI.js
+M UI/WebServerResources/UIxMailSearch.css
+M UI/WebServerResources/UIxMailSearch.js
+M UI/WebServerResources/generic.css
+
+commit 3ad9327d171dc48f100eb490029999e3704068ac
+Author: Luc Charland
+Date: Wed Sep 10 10:25:42 2014 -0400
+
+ putting test-prevent-invitations back in
+
+M Tests/Integration/config.py.in
+D Tests/Integration/dont-test-prevent-invitations.py
+A Tests/Integration/test-prevent-invitations.py
+
+commit 0483794f451bf07ec6fc9b32db18b82eb962219b
+Author: Ludovic Marcotte
+Date: Wed Sep 10 09:20:47 2014 -0400
+
+ Updated the documentation for the release
+
+M Documentation/SOGo Installation Guide.odt
+M Documentation/SOGo Mozilla Thunderbird Configuration.odt
+M Documentation/SOGo Native Microsoft Outlook Configuration.odt
+M NEWS
+M Version
+
+commit 3c1d6d7d898a663f826cb0a32b013f01e02656d0
+Author: Alexandre Cloutier
+Date: Tue Sep 9 16:03:44 2014 -0400
+
+ bugfix; UserSettings was not refresh properly after toggling threads
+
+M UI/WebServerResources/MailerUI.js
+
+commit 1dcf631ad6e78174a43b076c804b6026b45e532a
+Author: Francis Lachapelle
+Date: Tue Sep 9 15:49:16 2014 -0400
+
+ Update translations
+
+M NEWS
+M SoObjects/Appointments/Catalan.lproj/Localizable.strings
+M SoObjects/Appointments/Czech.lproj/Localizable.strings
+M SoObjects/Appointments/Dutch.lproj/Localizable.strings
+M SoObjects/Appointments/Hungarian.lproj/Localizable.strings
+M SoObjects/Appointments/NorwegianBokmal.lproj/Localizable.strings
+M SoObjects/Appointments/Polish.lproj/Localizable.strings
+M SoObjects/Contacts/Catalan.lproj/Localizable.strings
+M SoObjects/Contacts/NorwegianBokmal.lproj/Localizable.strings
+M SoObjects/Mailer/Catalan.lproj/Localizable.strings
+M SoObjects/Mailer/NorwegianBokmal.lproj/Localizable.strings
+M UI/Common/Catalan.lproj/Localizable.strings
+M UI/Common/Czech.lproj/Localizable.strings
+M UI/Common/Dutch.lproj/Localizable.strings
+M UI/Common/Finnish.lproj/Localizable.strings
+M UI/Common/NorwegianBokmal.lproj/Localizable.strings
+M UI/Common/Polish.lproj/Localizable.strings
+M UI/Common/SpanishSpain.lproj/Localizable.strings
+M UI/Contacts/Catalan.lproj/Localizable.strings
+M UI/Contacts/NorwegianBokmal.lproj/Localizable.strings
+M UI/MailPartViewers/Catalan.lproj/Localizable.strings
+M UI/MailPartViewers/NorwegianBokmal.lproj/Localizable.strings
+M UI/MailerUI/Catalan.lproj/Localizable.strings
+M UI/MailerUI/NorwegianBokmal.lproj/Localizable.strings
+M UI/PreferencesUI/Catalan.lproj/Localizable.strings
+M UI/PreferencesUI/Czech.lproj/Localizable.strings
+M UI/PreferencesUI/Dutch.lproj/Localizable.strings
+M UI/PreferencesUI/French.lproj/Localizable.strings
+M UI/PreferencesUI/Hungarian.lproj/Localizable.strings
+M UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings
+M UI/PreferencesUI/Polish.lproj/Localizable.strings
+M UI/Scheduler/Catalan.lproj/Localizable.strings
+M UI/Scheduler/Czech.lproj/Localizable.strings
+M UI/Scheduler/Dutch.lproj/Localizable.strings
+M UI/Scheduler/Hungarian.lproj/Localizable.strings
+M UI/Scheduler/NorwegianBokmal.lproj/Localizable.strings
+M UI/Scheduler/Polish.lproj/Localizable.strings
+
+commit cbc53b3a52f435f0e1ca49c532baf9954b2da82d
+Author: Ludovic Marcotte
+Date: Tue Sep 9 15:38:15 2014 -0400
+
+ Updated NEWS file
+
+M NEWS
+
+commit 574c2457580c24482cfd560512602b901971e53e
+Author: Alexandre Cloutier
+Date: Tue Sep 9 15:34:04 2014 -0400
+
+ bugfix PreventInvitation; fix object parsing on a blank user
+
+M UI/WebServerResources/UIxPreferences.js
+
+commit f3ca4ea7fca3e2f2d8434914fba0dc9e397d7e1f
+Author: Alexandre Cloutier
+Date: Tue Sep 9 15:29:08 2014 -0400
+
+ bugfix foldingThread; Renaming a foldername with a space was not correctly handled
+
+M UI/MailerUI/UIxMailFolderActions.m
+
+commit e542ff56465a22767751ff3a4259ce0c5d3f2bb8
+Author: Ludovic Marcotte
+Date: Tue Sep 9 15:15:56 2014 -0400
+
+ Fix for bug #1240
+
+M NEWS
+M UI/MainUI/SOGoUserHomePage.m
+
+commit 9daab5a9a1de1c49b79deca6bda9cc667edd78bd
+Author: Alexandre Cloutier
+Date: Mon Sep 8 14:58:21 2014 -0400
+
+ update NEWS file
+
+M NEWS
+
+commit 1fb3198dbc379566e504d0423dd69f4968626564
+Author: Alexandre Cloutier
+Date: Thu Sep 4 11:42:46 2014 -0400
+
+ applied comments
+
+M SoObjects/SOGo/SOGoUserDefaults.m
+
+commit d62c50476342d50bde7536ebcc2f1bd7ed83faed
+Author: Alexandre Cloutier
+Date: Fri Aug 29 13:16:30 2014 -0400
+
+ Changed the configurable variable SOGoMailMessageCheck to a general refresh associated to the current view
+
+M SoObjects/SOGo/SOGoDefaults.plist
+M SoObjects/SOGo/SOGoDomainDefaults.h
+M SoObjects/SOGo/SOGoDomainDefaults.m
+M SoObjects/SOGo/SOGoUserDefaults.h
+M SoObjects/SOGo/SOGoUserDefaults.m
+M UI/PreferencesUI/Arabic.lproj/Localizable.strings
+M UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings
+M UI/PreferencesUI/Catalan.lproj/Localizable.strings
+M UI/PreferencesUI/Czech.lproj/Localizable.strings
+M UI/PreferencesUI/Danish.lproj/Localizable.strings
+M UI/PreferencesUI/Dutch.lproj/Localizable.strings
+M UI/PreferencesUI/English.lproj/Localizable.strings
+M UI/PreferencesUI/Finnish.lproj/Localizable.strings
+M UI/PreferencesUI/French.lproj/Localizable.strings
+M UI/PreferencesUI/German.lproj/Localizable.strings
+M UI/PreferencesUI/Hungarian.lproj/Localizable.strings
+M UI/PreferencesUI/Icelandic.lproj/Localizable.strings
+M UI/PreferencesUI/Italian.lproj/Localizable.strings
+M UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings
+M UI/PreferencesUI/NorwegianNynorsk.lproj/Localizable.strings
+M UI/PreferencesUI/Polish.lproj/Localizable.strings
+M UI/PreferencesUI/Russian.lproj/Localizable.strings
+M UI/PreferencesUI/Slovak.lproj/Localizable.strings
+M UI/PreferencesUI/SpanishArgentina.lproj/Localizable.strings
+M UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings
+M UI/PreferencesUI/Swedish.lproj/Localizable.strings
+M UI/PreferencesUI/UIxPreferences.m
+M UI/PreferencesUI/Ukrainian.lproj/Localizable.strings
+M UI/PreferencesUI/Welsh.lproj/Localizable.strings
+M UI/Templates/ContactsUI/UIxContactEditor.wox
+M UI/Templates/MailerUI/UIxMailMainFrame.wox
+M UI/Templates/PreferencesUI/UIxPreferences.wox
+M UI/Templates/SchedulerUI/UIxCalMainView.wox
+M UI/WebServerResources/ContactsUI.js
+M UI/WebServerResources/MailerUI.js
+M UI/WebServerResources/SchedulerUI.js
+M UI/WebServerResources/UIxPreferences.js
+
+commit 7db526a5d968e0f0c7ad0782f8449220df722359
+Author: Alexandre Cloutier
+Date: Tue Sep 9 13:50:42 2014 -0400
+
+ bugfix for new user without userSettings.mail
+
+M UI/MailerUI/UIxMailActions.m
+M UI/WebServerResources/MailerUI.js
+
+commit 06f81a032cafe6017e328f8c8b4215119cc502a0
+Author: Alexandre Cloutier
+Date: Tue Sep 9 12:44:23 2014 -0400
+
+ applied comments
+
+M UI/WebServerResources/MailerUI.js
+
+commit df42c31618611f41856bc5a2427e7b59cc899bda
+Author: Alexandre Cloutier
+Date: Mon Sep 8 12:43:29 2014 -0400
+
+ Update NEWS file
+
+M NEWS
+
+commit e6002c9b2a419dd12f543990fed588a07b0a88df
+Author: Alexandre Cloutier
+Date: Mon Sep 8 12:39:55 2014 -0400
+
+ applied comments
+
+M UI/MailerUI/UIxMailActions.m
+M UI/MailerUI/UIxMailFolderActions.m
+M UI/WebServerResources/MailerUI.js
+
+commit 0c88edc61b788c5a33de2ab85fda9680deb80bc2
+Author: Alexandre Cloutier
+Date: Thu Sep 4 11:09:04 2014 -0400
+
+ bugfix where an exception was raised if threadsCollapsed is undefined
+
+M UI/WebServerResources/SOGoMailDataSource.js
+
+commit 267a689683dd435fde53dc7f442a9e9853b91305
+Author: Alexandre Cloutier
+Date: Fri Aug 29 09:30:40 2014 -0400
+
+ Applied comments
+
+M UI/MailerUI/UIxMailFolderActions.m
+
+commit c9d1294a8aca4e66c8ef59595035e9f8b3dd35ac
+Author: Alexandre Cloutier
+Date: Thu Aug 28 17:55:35 2014 -0400
+
+ Manage the collapse UIDs save in the user settings
+
+M UI/MailerUI/UIxMailActions.m
+M UI/MailerUI/UIxMailFolderActions.m
+
+commit 59023da7f00010c44ff026019d93009ff908d13e
+Author: Alexandre Cloutier
+Date: Wed Aug 13 18:39:33 2014 -0400
+
+ applied comments and fix bug where the folded threads were saved only after refreshing the entire page
+
+M UI/MailerUI/UIxMailActions.m
+M UI/WebServerResources/MailerUI.js
+
+commit c5f9dd086b78319d5e8170b62ae854a8e9d625c0
+Author: Alexandre Cloutier
+Date: Tue Aug 12 17:43:01 2014 -0400
+
+ Possibility to collapsed threads with persistance
+
+M UI/MailerUI/UIxMailActions.m
+M UI/MailerUI/product.plist
+M UI/WebServerResources/MailerUI.js
+M UI/WebServerResources/SOGoDataTable.js
+M UI/WebServerResources/SOGoMailDataSource.js
+
+commit 0bfaceb398e701379efa4be935d5c8d6ebd69313
+Author: Alexandre Cloutier
+Date: Tue Sep 9 12:51:59 2014 -0400
+
+ applied comments
+
+M UI/MailerUI/UIxMailFolderActions.m
+
+commit 9a380f711c0b2bb9e7a15c561d8661a5aa975c2d
+Author: Alexandre Cloutier
+Date: Tue Sep 9 10:28:59 2014 -0400
+
+ bugfix PreventInvitation
+
+M SoObjects/Appointments/SOGoAppointmentObject.m
+M UI/PreferencesUI/UIxPreferences.m
+M UI/WebServerResources/UIxPreferences.js
+
+commit 8c8e7d24a76d82cf37b19d02983e140fff177540
+Author: Ludovic Marcotte
+Date: Mon Sep 8 15:25:21 2014 -0400
+
+ Modified Apache's config file to handle Apache > 2.3
+
+M Apache/SOGo-apple-ab.conf
+M Apache/SOGo.conf
+M NEWS
+
+commit 77c50e523250ccdceafa3fe1b1a3439e630a407e
+Author: Alexandre Cloutier
+Date: Mon Sep 8 14:11:42 2014 -0400
+
+ applied comments; fix errors from merge and update NEWS file
+
+M NEWS
+M UI/WebServerResources/MailerUI.js
+
+commit b639c2d251c48a5ab6498a81e8a40fb3f153ef84
+Author: Francis Lachapelle
+Date: Fri Sep 5 16:04:29 2014 -0400
+
+ Fixes for IE
+
+M UI/Templates/MailerUI/UIxMailSearch.wox
+M UI/WebServerResources/UIxMailSearch.css
+M UI/WebServerResources/UIxMailSearch.js
+
+commit 984e208dd938911cdb091514e8da2a3f328bedce
+Author: Alexandre Cloutier
+Date: Fri Sep 5 11:01:57 2014 -0400
+
+ IE bugfixes
+
+M UI/Templates/MailerUI/UIxMailSearch.wox
+M UI/WebServerResources/UIxMailSearch.css
+M UI/WebServerResources/UIxMailSearch.js
+M UI/WebServerResources/generic.css
+M UI/WebServerResources/iefixes.css
+
+commit 606ee9780e8f8edaecfbf0f245ee114a2c31874e
+Author: Luc Charland
+Date: Thu Sep 4 22:36:02 2014 -0400
+
+ dont test prevent invitations
+
+A Tests/Integration/dont-test-prevent-invitations.py
+D Tests/Integration/test-prevent-invitations.py
+
+commit c6f82dac01545789528c524d91ac532ba04d5290
+Author: Luc Charland
+Date: Thu Sep 4 22:24:32 2014 -0400
+
+ catch specific exception
+
+M Tests/Integration/webdavlib.py
+
+commit e37a603632e532d3f36588b3212575e02939a702
+Author: Luc Charland
+Date: Thu Sep 4 21:59:36 2014 -0400
+
+ should help some builds that might timeout
+
+M Tests/Integration/webdavlib.py
+
+commit ca8351d1f9097793ed816c099683c3b97e87a13d
+Author: Alexandre Cloutier
+Date: Thu Sep 4 10:50:03 2014 -0400
+
+ fix IE7, IE8, IE9, IE10, IE11 GUI
+
+M UI/MailerUI/English.lproj/Localizable.strings
+M UI/Templates/MailerUI/UIxMailSearch.wox
+M UI/WebServerResources/MailerUI.js
+M UI/WebServerResources/UIxMailSearch.css
+M UI/WebServerResources/UIxMailSearch.js
+M UI/WebServerResources/generic.css
+M UI/WebServerResources/iefixes.css
+
+commit 031e4c9409abd0ce46a634d5e05db417e785faa7
+Author: Luc Charland
+Date: Wed Sep 3 22:43:49 2014 -0400
+
+ more of the same
+
+M Tests/Integration/test-preferences.py
+M Tests/Integration/test-sieve.py
+
+commit c621bbcd563a8b4306cbf59d9390f12a9a260e7c
+Author: Luc Charland
+Date: Wed Sep 3 22:32:46 2014 -0400
+
+ Those need the same adjustments
+
+M Tests/Integration/test-preferences.py
+M Tests/Integration/test-sieve.py
+
+commit 4b94a183be2887ef958931bb4848dec51ad41cbb
+Author: Luc Charland
+Date: Wed Sep 3 13:50:13 2014 -0400
+
+ urllib.quote needs a string
+
+M Tests/Integration/test-prevent-invitations.py
+
+commit 32476b16cc79f113be494f6bc755d47b89a2ab85
+Author: Alexandre Cloutier
+Date: Tue Sep 2 14:31:46 2014 -0400
+
+ applied comments and fix bug when tagging msgs already tagged
+
+M UI/MailerUI/UIxMailFolderActions.m
+M UI/WebServerResources/MailerUI.js
+
+commit 3b65eaea0b177374abe7389a42935ccd08629910
+Author: Alexandre Cloutier
+Date: Tue Sep 2 13:42:04 2014 -0400
+
+ Tagging labels with 1 AJAX request
+
+M UI/MailerUI/UIxMailFolderActions.m
+M UI/MailerUI/product.plist
+M UI/WebServerResources/MailerUI.js
+
+commit 7e26d80c77316c0869470b045a29786efccfdeb2
+Author: Alexandre Cloutier
+Date: Tue Sep 2 10:11:27 2014 -0400
+
+ merge conflicts
+
+M UI/MailerUI/UIxMailActions.m
+M UI/MailerUI/UIxMailFolderActions.m
+M UI/MailerUI/product.plist
+M UI/WebServerResources/MailerUI.js
+
+commit 1af52e6d6b93bc68dc7c038ce740851fb56c88b3
+Author: Francis Lachapelle
+Date: Fri Aug 29 15:33:56 2014 -0400
+
+ Fix message labels handling
+
+ Selecting "none" from the label submenu on a multiple selection of
+ messages is now working. When changing the label of multiple messages,
+ the display is now properly updated.
+
+ Fixes #2902
+
+M NEWS
+M UI/WebServerResources/MailerUI.js
+
+commit eaf815eae62c8c7311158a34eb0b67bda2d3f9e6
+Author: Alexandre Cloutier
+Date: Fri Aug 29 14:55:21 2014 -0400
+
+ update NEWS file
+
+M NEWS
+
+commit 9bd09cc55d08ed34745f4fa51413dc760c7114d1
+Author: Alexandre Cloutier
+Date: Thu Aug 28 13:20:43 2014 -0400
+
+ add the location column
+
+M UI/Templates/MailerUI/UIxMailSearch.wox
+M UI/WebServerResources/UIxMailSearch.js
+
+commit ced09628940cde92c3bb70ce96e31dd5cc973b08
+Author: Luc Charland
+Date: Thu Aug 28 10:43:32 2014 -0400
+
+ Added white_listed_attendee to the config file
+
+M Tests/Integration/config.py.in
+
+commit dadad3df2a755ffcd73198d633a8eb368412b2b3
+Author: Francis Lachapelle
+Date: Thu Aug 28 09:37:49 2014 -0400
+
+ Fix some compilation warnings
+
+M UI/Scheduler/UIxAppointmentActions.m
+M UI/Scheduler/UIxCalMainView.m
+
+commit da184f8459a43bbe0c7f740e366cdf60baedb0ef
+Author: Alexandre Cloutier
+Date: Wed Aug 27 16:50:45 2014 -0400
+
+ bugfix#2864
+
+M UI/WebServerResources/SchedulerUI.js
+
+commit 03152ea3d4cbf39ef8a5340e865d038bc899877f
+Author: Alexandre Cloutier
+Date: Wed Aug 27 16:01:35 2014 -0400
+
+ bugfix with DND from calendar view to calendar list
+
+M UI/WebServerResources/SchedulerUIDnD.js
+
+commit 84a08659ecc263f1962aa138bb025308aaf41870
+Author: Alexandre Cloutier
+Date: Wed Aug 27 13:50:56 2014 -0400
+
+ bugfix where it is not possible to delete msg when mailbox is full
+
+M UI/WebServerResources/MailerUI.js
+
+commit d749d5c2fb9a41697732eaef3f17e27e807fff55
+Author: Luc Charland
+Date: Wed Aug 27 13:31:49 2014 -0400
+
+ Added tests for prevent invitation and whitelist
+
+M Tests/Integration/preferences.py
+M Tests/Integration/test-preferences.py
+A Tests/Integration/test-prevent-invitations.py
+
+commit 07a138e0d62ebaaea722dc91ae0be162385d74ed
+Author: Alexandre Cloutier
+Date: Wed Aug 27 12:30:33 2014 -0400
+
+ applied comments and add the possibility to resize the search inbox window
+
+M UI/Templates/MailerUI/UIxMailSearch.wox
+M UI/WebServerResources/MailerUI.js
+M UI/WebServerResources/UIxMailSearch.css
+M UI/WebServerResources/UIxMailSearch.js
+M UI/WebServerResources/generic.css
+
+commit 76c9b45fd077759c888cde2941e710a9e5925577
+Author: Alexandre Cloutier
+Date: Tue Aug 26 14:25:27 2014 -0400
+
+ update Localizable.strings
+
+ Update the print window options strings
+
+M UI/Scheduler/English.lproj/Localizable.strings
+
+commit 38a3b7bb4f29aa676c7af0dccde3d87973b1007e
+Author: Alexandre Cloutier
+Date: Tue Aug 26 13:36:42 2014 -0400
+
+ print calendars events&Tasks with colors - either borders or backgrounds
+
+M UI/Scheduler/UIxCalListingActions.m
+M UI/Scheduler/UIxCalViewPrint.h
+M UI/Scheduler/UIxCalViewPrint.m
+M UI/Templates/SchedulerUI/UIxCalViewPrint.wox
+M UI/WebServerResources/SchedulerUI.js
+M UI/WebServerResources/UIxCalViewPrint.css
+M UI/WebServerResources/UIxCalViewPrint.js
+
+commit b2b77c65d3d35d7c96986eb0f01c53783e0c6b05
+Author: Francis Lachapelle
+Date: Tue Aug 26 09:00:13 2014 -0400
+
+ Fix folders paths of "sogo-tool restore -l"
+
+M NEWS
+M Tools/SOGoToolRestore.m
+
+commit 6aecccf6ca26231342af1f8542dfbe28347778fc
+Author: Alexandre Cloutier
+Date: Mon Aug 25 13:46:35 2014 -0400
+
+ indentations
+
+M UI/WebServerResources/UIxCalViewPrint.js
+
+commit e4a84d49202b2aa42251910dcbc1ffb8de6b498f
+Author: Francis Lachapelle
+Date: Mon Aug 25 12:15:05 2014 -0400
+
+ Fix usage of SOGoSubscriptionFolderFormat default
+
+M NEWS
+M SoObjects/SOGo/SOGoGCSFolder.h
+M SoObjects/SOGo/SOGoGCSFolder.m
+
+commit 28f26ec08e7994b857c0b51551b1d5625df822b3
+Author: Francis Lachapelle
+Date: Mon Aug 25 10:16:10 2014 -0400
+
+ Fix display of users with no possible subscription
+
+M NEWS
+M UI/WebServerResources/UIxContactsUserFolders.js
+
+commit 74bd96e5a635cefd963315db2fef5199eeba14c4
+Author: Francis Lachapelle
+Date: Mon Aug 25 10:12:09 2014 -0400
+
+ Fix encoding of new calendars + new subscriptions
+
+M NEWS
+M UI/WebServerResources/SchedulerUI.js
+
+commit e044476772b304e307f7853906996282f9b0eb93
+Author: Alexandre Cloutier
+Date: Fri Aug 15 13:41:30 2014 -0400
+
+ bugFix #2827
+
+M UI/WebServerResources/ContactsUI.js
+
+commit c76cb3646122e43e6b1cb2dfa6e64a88da85d605
+Author: Alexandre Cloutier
+Date: Fri Aug 15 13:06:46 2014 -0400
+
+ Disable the search button on toolbar once it is opened
+
+M UI/WebServerResources/MailerUI.js
+M UI/WebServerResources/UIxMailSearch.js
+
+commit 73fcdc230615da8ac22281397f4ba692a4a7cdc8
+Author: Alexandre Cloutier
+Date: Fri Aug 15 11:41:37 2014 -0400
+
+ adjust css for other browser, fix display bug
+
+M UI/Templates/MailerUI/UIxMailSearch.wox
+M UI/WebServerResources/UIxMailSearch.css
+M UI/WebServerResources/UIxMailSearch.js
+M UI/WebServerResources/tablekit.js
+
+commit b9dd1ddc5ae215b1b1c888ee9538b8036fbf9208
+Author: Ludovic Marcotte
+Date: Fri Aug 15 09:57:19 2014 -0400
+
+ Fix for bug #2892
+
+M NEWS
+M UI/Common/UIxFolderActions.m
+
+commit 8783f09a4acca298fc3a9f533feb2dda5590db36
+Author: Alexandre Cloutier
+Date: Thu Aug 14 15:01:40 2014 -0400
+
+ fix leak
+
+M UI/MailerUI/UIxMailSearch.m
+
+commit 52476251b82ed0c172bc143a0642ae223d306b6e
+Author: Alexandre Cloutier
+Date: Thu Aug 14 14:49:44 2014 -0400
+
+ applied comments, fix bug and add sortable results
+
+M UI/MailerUI/UIxMailListActions.m
+M UI/Templates/MailerUI/UIxMailSearch.wox
+M UI/WebServerResources/UIxMailSearch.css
+M UI/WebServerResources/UIxMailSearch.js
+
+commit f6c7ca33797bfd0e00a6b1f4e85f6b7de1ae9889
+Author: Alexandre Cloutier
+Date: Wed Aug 13 17:41:58 2014 -0400
+
+ applied comments
+
+M UI/MailerUI/English.lproj/Localizable.strings
+M UI/MailerUI/UIxMailListActions.m
+M UI/MailerUI/UIxMailSearch.m
+M UI/WebServerResources/UIxMailSearch.js
+
+commit c3e46e4bafd6e26ec417927f10cf0c88180b7786
+Author: Alexandre Cloutier
+Date: Mon Aug 11 09:25:09 2014 -0400
+
+ code refactoring and GUI improvement
+
+M UI/MailerUI/UIxMailListActions.m
+M UI/Templates/MailerUI/UIxMailSearch.wox
+M UI/WebServerResources/UIxMailSearch.css
+M UI/WebServerResources/UIxMailSearch.js
+M UI/WebServerResources/generic.css
+
+commit 7794d716b983992251492f26bcf3ff07edbd3b5a
+Author: Alexandre Cloutier
+Date: Wed Aug 6 14:49:36 2014 -0400
+
+ version 1 of the inbox search
+
+M UI/MailerUI/GNUmakefile
+M UI/MailerUI/Toolbars/SOGoMailFolder.toolbar
+M UI/MailerUI/UIxMailListActions.m
+M UI/MailerUI/UIxMailMainFrame.m
+A UI/MailerUI/UIxMailSearch.h
+A UI/MailerUI/UIxMailSearch.m
+M UI/MailerUI/product.plist
+M UI/Templates/MailerUI/UIxMailMainFrame.wox
+A UI/Templates/MailerUI/UIxMailSearch.wox
+M UI/WebServerResources/MailerUI.js
+M UI/WebServerResources/SOGoDataTable.js
+M UI/WebServerResources/SOGoMailDataSource.js
+A UI/WebServerResources/UIxMailSearch.css
+A UI/WebServerResources/UIxMailSearch.js
+M UI/WebServerResources/generic.css
+M UI/WebServerResources/generic.js
+
+commit 5b886e5c4dab6bdf486f937df8bb234c4902f50c
+Author: Francis Lachapelle
+Date: Fri Aug 1 12:26:53 2014 -0400
+
+ Fix issue with DnD of tasks with FireFox
+
+M UI/WebServerResources/SchedulerUI.js
+
+commit cde1db93245c8bdfbf8e69ed8efe8a0f6a03027c
+Author: Ludovic Marcotte
+Date: Fri Aug 1 09:40:45 2014 -0400
+
+ Refactored GCSFolder: -writeContent and fixed sogo-tool restore
+
+M SOPE/GDLContentStore/GCSFolder.h
+M SOPE/GDLContentStore/GCSFolder.m
+M SoObjects/Contacts/SOGoContactGCSFolder.h
+M SoObjects/SOGo/SOGoContentObject.m
+M Tools/SOGoToolRestore.m
+
+commit f43341c1005d3d5813c23133071c253c753bb3e9
+Author: Ludovic Marcotte
+Date: Thu Jul 31 16:19:49 2014 -0400
+
+ Fixed JSON'ification of the admin module
+
+M UI/WebServerResources/AdministrationUI.js
+
+commit b05fcc7d82395fe2d988567c36d213aa1c6cfeae
+Author: Ludovic Marcotte
+Date: Wed Jul 30 14:51:00 2014 -0400
+
+ Fat commit to refactor the quick record generation
+
+M ActiveSync/common.make
+M GNUmakefile
+M Main/GNUmakefile.preamble
+M NEWS
+D OGoContentStore/COPYING
+D OGoContentStore/GNUmakefile
+D OGoContentStore/GNUmakefile.postamble
+D OGoContentStore/GNUmakefile.preamble
+D OGoContentStore/OCSContactFieldExtractor.m
+D OGoContentStore/OCSiCalFieldExtractor.h
+D OGoContentStore/OCSiCalFieldExtractor.m
+D OGoContentStore/README
+D OGoContentStore/Version
+D OGoContentStore/appointment-oracle.ocs
+D OGoContentStore/appointment.ocs
+D OGoContentStore/contact-oracle.ocs
+D OGoContentStore/contact.ocs
+D OGoContentStore/iCalRepeatableEntityObject+OCS.h
+D OGoContentStore/iCalRepeatableEntityObject+OCS.m
+D OGoContentStore/misc/iNetOrgPerson.txt
+D OGoContentStore/misc/icaltest.ical
+D OGoContentStore/misc/test1/GNUmakefile
+D OGoContentStore/misc/test1/common.h
+D OGoContentStore/misc/test1/test1.m
+M OpenChange/GNUmakefile
+M OpenChange/MAPIStoreContactsMessage.m
+M OpenChange/MAPIStoreTasksMessage.m
+D SOPE/GDLContentStore/GCSFieldExtractor.h
+D SOPE/GDLContentStore/GCSFieldExtractor.m
+M SOPE/GDLContentStore/GCSFolder.h
+M SOPE/GDLContentStore/GCSFolder.m
+M SOPE/GDLContentStore/GCSFolderManager.m
+M SOPE/GDLContentStore/GCSFolderType.h
+M SOPE/GDLContentStore/GCSFolderType.m
+M SOPE/GDLContentStore/GNUmakefile
+A SOPE/GDLContentStore/GNUmakefile.postamble
+A SOPE/GDLContentStore/appointment-oracle.ocs
+A SOPE/GDLContentStore/appointment.ocs
+A SOPE/GDLContentStore/contact-oracle.ocs
+A SOPE/GDLContentStore/contact.ocs
+M SoObjects/Appointments/SOGoAppointmentFolder.m
+M SoObjects/Appointments/SOGoAppointmentObject.h
+M SoObjects/Appointments/SOGoAppointmentObject.m
+M SoObjects/Appointments/SOGoCalendarComponent.h
+M SoObjects/Appointments/SOGoCalendarComponent.m
+M SoObjects/Appointments/SOGoComponentOccurence.m
+M SoObjects/Appointments/SOGoTaskObject.h
+M SoObjects/Appointments/SOGoTaskObject.m
+M SoObjects/Appointments/SOGoWebAppointmentFolder.h
+M SoObjects/Appointments/SOGoWebAppointmentFolder.m
+M SoObjects/Appointments/iCalCalendar+SOGo.m
+M SoObjects/Appointments/iCalEntityObject+SOGo.h
+M SoObjects/Appointments/iCalEntityObject+SOGo.m
+M SoObjects/Appointments/iCalEvent+SOGo.h
+M SoObjects/Appointments/iCalEvent+SOGo.m
+M SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.h
+M SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m
+M SoObjects/Appointments/iCalToDo+SOGo.h
+M SoObjects/Appointments/iCalToDo+SOGo.m
+M SoObjects/Contacts/NGVCard+SOGo.m
+M SoObjects/Contacts/NGVList+SOGo.h
+M SoObjects/Contacts/NGVList+SOGo.m
+M SoObjects/Contacts/SOGoContactGCSEntry.m
+M SoObjects/Contacts/SOGoContactGCSList.m
+M SoObjects/Contacts/SOGoContactLDIFEntry.m
+M SoObjects/Mailer/SOGoDraftObject.m
+M SoObjects/SOGo/GNUmakefile.preamble
+M SoObjects/SOGo/SOGoContentObject.h
+M SoObjects/SOGo/SOGoContentObject.m
+M SoObjects/common.make
+M Tests/Integration/GNUmakefile.preamble
+M Tests/Unit/GNUmakefile
+M Tools/GNUmakefile.preamble
+M Tools/SOGoToolRestore.m
+M UI/Contacts/UIxContactFolderActions.m
+M UI/Contacts/UIxListEditor.m
+M UI/MailPartViewers/UIxMailPartICalActions.m
+M UI/Scheduler/UIxComponentEditor.m
+M UI/Scheduler/UIxTaskEditor.m
+M UI/common.make
+M packaging/debian-multiarch/sogo.overrides
+M packaging/debian/sogo.overrides
+M packaging/rhel/sogo.spec
+
+commit 07324e56a0ab257334d4d4a67ed52ce8f1a844d9
+Author: Francis Lachapelle
+Date: Wed Jul 30 11:16:35 2014 -0400
+
+ Update ChangeLog
+
+M ChangeLog
+
+commit 397a36cc89f0160bc84ba19b2f7adc2b96a6a5c1
+Author: Francis Lachapelle
+Date: Wed Jul 30 11:16:10 2014 -0400
+
+ Preparation for release 2.2.7
+
+M Documentation/SOGo Installation Guide.odt
+M Documentation/SOGo Mozilla Thunderbird Configuration.odt
+M Documentation/SOGo Native Microsoft Outlook Configuration.odt
+M Version
+
+commit c240931c54873943349d0c65c1fb9b1dadcbd9c1
+Author: Francis Lachapelle
+Date: Wed Jul 30 11:15:05 2014 -0400
+
+ Update CKEditor to version 4.4.3
+
+M NEWS
+M UI/WebServerResources/ckeditor/build-config.js
+M UI/WebServerResources/ckeditor/ckeditor.js
+M UI/WebServerResources/ckeditor/lang/ar.js
+M UI/WebServerResources/ckeditor/lang/ca.js
+M UI/WebServerResources/ckeditor/lang/cs.js
+M UI/WebServerResources/ckeditor/lang/cy.js
+M UI/WebServerResources/ckeditor/lang/da.js
+M UI/WebServerResources/ckeditor/lang/de.js
+M UI/WebServerResources/ckeditor/lang/en.js
+M UI/WebServerResources/ckeditor/lang/es.js
+M UI/WebServerResources/ckeditor/lang/fi.js
+M UI/WebServerResources/ckeditor/lang/fr.js
+M UI/WebServerResources/ckeditor/lang/hu.js
+M UI/WebServerResources/ckeditor/lang/is.js
+M UI/WebServerResources/ckeditor/lang/it.js
+M UI/WebServerResources/ckeditor/lang/nb.js
+M UI/WebServerResources/ckeditor/lang/nl.js
+M UI/WebServerResources/ckeditor/lang/no.js
+M UI/WebServerResources/ckeditor/lang/pl.js
+M UI/WebServerResources/ckeditor/lang/pt-br.js
+M UI/WebServerResources/ckeditor/lang/ru.js
+M UI/WebServerResources/ckeditor/lang/sk.js
+M UI/WebServerResources/ckeditor/lang/sv.js
+M UI/WebServerResources/ckeditor/lang/uk.js
+M UI/WebServerResources/ckeditor/plugins/colordialog/dialogs/colordialog.js
+M UI/WebServerResources/ckeditor/plugins/image/dialogs/image.js
+M UI/WebServerResources/ckeditor/plugins/tabletools/dialogs/tableCell.js
+M UI/WebServerResources/ckeditor/skins/moono/dialog.css
+M UI/WebServerResources/ckeditor/skins/moono/dialog_ie.css
+M UI/WebServerResources/ckeditor/skins/moono/dialog_ie7.css
+M UI/WebServerResources/ckeditor/skins/moono/dialog_ie8.css
+M UI/WebServerResources/ckeditor/skins/moono/dialog_iequirks.css
+M UI/WebServerResources/ckeditor/skins/moono/editor.css
+M UI/WebServerResources/ckeditor/skins/moono/editor_gecko.css
+M UI/WebServerResources/ckeditor/skins/moono/editor_ie.css
+M UI/WebServerResources/ckeditor/skins/moono/editor_ie7.css
+M UI/WebServerResources/ckeditor/skins/moono/editor_ie8.css
+M UI/WebServerResources/ckeditor/skins/moono/editor_iequirks.css
+
+commit ef2432e10f396886f09134ff39c9b90cac5e8c2b
+Author: Francis Lachapelle
+Date: Wed Jul 30 10:36:31 2014 -0400
+
+ Update NEWS file
+
+M NEWS
+
+commit 571322958a875e53dc0c689caf3f24a1debdea54
+Author: Francis Lachapelle
+Date: Wed Jul 30 10:33:15 2014 -0400
+
+ Update fi, fr, de, and es_ES translations
+
+M SoObjects/Appointments/Finnish.lproj/Localizable.strings
+M SoObjects/Appointments/French.lproj/Localizable.strings
+M SoObjects/Appointments/German.lproj/Localizable.strings
+M SoObjects/Appointments/SpanishSpain.lproj/Localizable.strings
+M UI/Common/German.lproj/Localizable.strings
+M UI/PreferencesUI/Finnish.lproj/Localizable.strings
+M UI/PreferencesUI/French.lproj/Localizable.strings
+M UI/PreferencesUI/German.lproj/Localizable.strings
+M UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings
+M UI/Scheduler/Finnish.lproj/Localizable.strings
+M UI/Scheduler/French.lproj/Localizable.strings
+M UI/Scheduler/German.lproj/Localizable.strings
+M UI/Scheduler/SpanishSpain.lproj/Localizable.strings
+
+commit bd5c05cca2aa9166198c9c6ea6e9c583da9359bd
+Author: Francis Lachapelle
+Date: Wed Jul 30 10:31:25 2014 -0400
+
+ Indentation in JavaScript files
+
+M UI/WebServerResources/AdministrationUI.js
+M UI/WebServerResources/ContactsUI.js
+M UI/WebServerResources/MailerUI.js
+M UI/WebServerResources/SchedulerUI.js
+M UI/WebServerResources/UIxPreferences.js
+M UI/WebServerResources/generic.js
+
+commit ea44308aa3d95d150b6d6565cdf4dbdc79e5c64e
+Author: Francis Lachapelle
+Date: Tue Jul 29 16:05:46 2014 -0400
+
+ Fix all-day events display in IE
+
+ It also fixes the display of the event categories for all-day events in
+ IE.
+
+M NEWS
+M UI/WebServerResources/SchedulerUI.css
+M UI/WebServerResources/SchedulerUI.js
+
+commit 94f3246658c151b55ca86404c607fe29de7b94b1
+Author: Ludovic Marcotte
+Date: Tue Jul 29 10:36:20 2014 -0400
+
+ Improved error message when you cannot invite users
+
+M SoObjects/Appointments/English.lproj/Localizable.strings
+M SoObjects/Appointments/SOGoAppointmentObject.m
+
+commit 1df7e989e012fbbb3a93293ed944b2c80f48299f
+Author: Ludovic Marcotte
+Date: Fri Jul 25 14:48:25 2014 -0400
+
+ Removed worthless declaration
+
+M UI/Scheduler/UIxCalListingActions.m
+
+commit d9ca1051b31f7efd35083dc87bd59b143cb3e593
+Author: Francis Lachapelle
+Date: Fri Jul 25 11:34:33 2014 -0400
+
+ Improve headers of multicolumns view
+
+M UI/Templates/SchedulerUI/UIxCalDayTable.wox
+M UI/Templates/SchedulerUI/UIxCalendarSelector.wox
+M UI/WebServerResources/SchedulerUI.css
+
+commit 4eefa4c2697d4da8ba72674a81f74492e01a11dd
+Author: Ludovic Marcotte
+Date: Fri Jul 25 08:12:12 2014 -0400
+
+ Fixed test since we now return a 200 instead of a 204
+
+M Tests/Integration/utilities.py
+
+commit 4c21a050d91e5969921db8f9971752863a7edd48
+Author: Ludovic Marcotte
+Date: Thu Jul 24 14:00:57 2014 -0400
+
+ JSON interface to folder subscriptions
+
+M NEWS
+M UI/MainUI/SOGoUserHomePage.m
+M UI/WebServerResources/UIxContactsUserFolders.js
+
+commit b52289904f607121627a5cf3298f7124a5042d22
+Author: Alexandre Cloutier
+Date: Thu Jul 24 13:48:41 2014 -0400
+
+ task.png for DnD taskList
+
+A UI/WebServerResources/task.png
+
+commit c389630d76b4d72e10552be32f8482b4807c1558
+Author: Alexandre Cloutier
+Date: Thu Jul 24 13:35:14 2014 -0400
+
+ DnD tasksList
+
+M UI/WebServerResources/SchedulerUI.css
+M UI/WebServerResources/SchedulerUI.js
+
+commit f6ef94a6314e3fe7d5b863d20a0df4580e8ca7bb
+Author: Ludovic Marcotte
+Date: Thu Jul 24 12:48:03 2014 -0400
+
+ improved handling of SOGoSubscriptionFolderFormat
+
+M NEWS
+M SoObjects/Appointments/SOGoAppointmentFolders.m
+M SoObjects/SOGo/SOGoGCSFolder.m
+M SoObjects/SOGo/SOGoUserFolder.m
+M UI/Common/UIxAclEditor.m
+M UI/Common/UIxFolderActions.m
+M UI/MainUI/SOGoUserHomePage.m
+M UI/WebServerResources/UIxContactsUserFolders.js
+
+commit 5de51e8aa1facd6ddaf1162f31f9e42ca810d125
+Author: Francis Lachapelle
+Date: Thu Jul 24 09:30:19 2014 -0400
+
+ Fix missing argument with new DnD controller
+
+M UI/WebServerResources/SchedulerUIDnD.js
+
+commit 006727a74b42ee0fe5fcb479a9ab8080db14602b
+Author: Ludovic Marcotte
+Date: Thu Jul 24 08:39:41 2014 -0400
+
+ Properly destroy cache objects of vanished folders
+
+M ActiveSync/SOGoActiveSyncDispatcher.m
+M NEWS
+M SoObjects/SOGo/SOGoCacheGCSObject.m
+M SoObjects/SOGo/SOGoCacheObject.h
+
+commit 6619840f80dab04eacac6a7fe66436443796bfd8
+Author: Jeroen Dekkers
+Date: Tue Jul 22 19:54:18 2014 +0200
+
+ Add Mailer and Appointments to product.list requires of MailPartViewers
+
+M UI/MailPartViewers/product.plist
+
+commit 08fd2fcfaa8488a8460c0b555b45f4950f1010a2
+Author: Francis Lachapelle
+Date: Tue Jul 22 13:26:28 2014 -0400
+
+ Fix JavaScript after bad merge
+
+M UI/WebServerResources/SchedulerUI.js
+
+commit a43dd97fc939692f74f38dfcd2064147e8cafbdc
+Author: Alexandre Cloutier
+Date: Tue Jul 22 11:37:45 2014 -0400
+
+ Fix bug with DnD; leftPanelController.stopEvent()
+
+M UI/WebServerResources/SchedulerUIDnD.js
+
+commit 192659fdd9d64ddd63f8dcd014a14a3b4e7fad15
+Author: Francis Lachapelle
+Date: Mon Jul 21 16:12:27 2014 -0400
+
+ Add missing localizable string
+
+M UI/PreferencesUI/English.lproj/Localizable.strings
+
+commit 06fe36fd75aaedd05ff7e92cad1320f4dff63160
+Author: Francis Lachapelle
+Date: Mon Jul 21 16:07:13 2014 -0400
+
+ Add missing localizable strings
+
+M UI/PreferencesUI/English.lproj/Localizable.strings
+M UI/Templates/PreferencesUI/UIxPreferences.wox
+
+commit 24f9d83ff7e8503118aabd02598f3300a07a646b
+Author: Francis Lachapelle
+Date: Mon Jul 21 16:06:24 2014 -0400
+
+ Fix JavaScript from merge leftover
+
+M UI/WebServerResources/SchedulerUI.js
+
+commit 8dd967d0a87a7ee560b854f667fb55c296b89245
+Author: Ludovic Marcotte
+Date: Mon Jul 21 15:38:23 2014 -0400
+
+ Updated NEWS file for two merged pull requests
+
+M NEWS
+
+commit 08cd080d47f4ef0d0d262021e173b5d6c6519276
+Author: Ludovic Marcotte
+Date: Mon Jul 21 15:34:56 2014 -0400
+
+ Fixed charset substitution in meta tags
+
+M NEWS
+M UI/MailPartViewers/UIxMailPartHTMLViewer.m
+
+commit 28e6bb8b9d521dad8801206655c30d57ef3f9ff6
+Author: Alexandre Cloutier
+Date: Fri Jul 18 15:03:28 2014 -0400
+
+ Applied comments
+
+M UI/Scheduler/English.lproj/Localizable.strings
+M UI/Templates/SchedulerUI/UIxCalMainView.wox
+M UI/WebServerResources/SchedulerUI.css
+M UI/WebServerResources/SchedulerUI.js
+M UI/WebServerResources/SchedulerUIDnD.js
+
+commit b892b3f7946e4466a51af901fb4b77da75872d40
+Author: Alexandre Cloutier
+Date: Fri Jul 18 10:14:38 2014 -0400
+
+ Add RegEx
+
+M UI/Scheduler/English.lproj/Localizable.strings
+M UI/WebServerResources/SchedulerUI.js
+
+commit cdf4cc1acb98f451bec00ab7d6e3858937c293a8
+Author: Alexandre Cloutier
+Date: Fri Jul 18 09:46:31 2014 -0400
+
+ fix DnD from eventList to calendarList for repeated event
+
+M UI/WebServerResources/SchedulerUI.js
+
+commit 3cac794de5dbda0f005901cbb081b2ee5fa01e7f
+Author: Alexandre Cloutier
+Date: Fri Jul 18 09:33:51 2014 -0400
+
+ move line
+
+M UI/WebServerResources/SchedulerUIDnD.js
+
+commit 8f9b24a23f593eb2041cfaaca3e4fb611ddd7060
+Author: Alexandre Cloutier
+Date: Fri Jul 18 09:23:07 2014 -0400
+
+ visual helper while dragging from calendar view to calendarList
+
+M UI/Templates/SchedulerUI/UIxCalMainView.wox
+M UI/WebServerResources/SchedulerUI.css
+M UI/WebServerResources/SchedulerUIDnD.js
+
+commit a2a7014140ce8abf97ce9b04b9eb7467deda192b
+Author: Alexandre Cloutier
+Date: Thu Jul 17 09:42:32 2014 -0400
+
+ fix dnd repeated event bug + applied comments
+
+M UI/Scheduler/UIxAppointmentActions.m
+M UI/WebServerResources/SchedulerUI.js
+M UI/WebServerResources/SchedulerUIDnD.js
+
+commit a5ecb2063f449505ab671e3952497f4484b12bec
+Author: Alexandre Cloutier
+Date: Wed Jul 16 10:30:48 2014 -0400
+
+ added event7.png and adjust javascript indentation
+
+M UI/WebServerResources/SchedulerUI.js
+M UI/WebServerResources/SchedulerUIDnD.js
+A UI/WebServerResources/event7.png
+
+commit 9bd7aeebfb5ea41c078c7e9691fe0c0e9513eb12
+Author: Alexandre Cloutier
+Date: Tue Jul 15 17:29:39 2014 -0400
+
+ DnD from calendarView to CalendarList
+
+M UI/WebServerResources/SchedulerUIDnD.js
+
+commit 01af72cfe95e1970fa84405732690355ed72dcd8
+Author: Alexandre Cloutier
+Date: Tue Jul 15 09:49:48 2014 -0400
+
+ DnD from eventList to the calendarList
+
+M UI/WebServerResources/SchedulerUI.css
+M UI/WebServerResources/SchedulerUI.js
+
+commit 6dddb5c98ce402268205eaa4fc7eec3068380f9f
+Author: Alexandre Cloutier
+Date: Fri Jul 11 17:04:06 2014 -0400
+
+ dragNdrop from the events table to the calendars list
+
+M UI/Templates/SchedulerUI/UIxCalMainView.wox
+M UI/WebServerResources/SchedulerUI.js
+M UI/WebServerResources/UIxOccurenceDialog.js
+
+commit ccf181bcf95a8bebf6c4ab9bdb66c151548cc00d
+Author: Alexandre Cloutier
+Date: Thu Jul 10 13:34:47 2014 -0400
+
+ applied comments and fix repeated events dragNdrop between calendars
+
+M UI/Scheduler/UIxAppointmentActions.m
+M UI/WebServerResources/SchedulerUI.js
+
+commit e478b29c2e40963041abf63c678a7e36d287ad2f
+Author: Alexandre Cloutier
+Date: Wed Jul 9 16:47:13 2014 -0400
+
+ creating and dragNDrop between calendars in multicolumndayview
+
+M UI/Scheduler/UIxAppointmentActions.m
+M UI/Scheduler/UIxCalDayTable.m
+M UI/Templates/SchedulerUI/UIxCalDayTable.wox
+M UI/WebServerResources/SchedulerUI.js
+M UI/WebServerResources/SchedulerUIDnD.js
+
+commit c2027f072d0b59944882ca39fc97f573a2157fd7
+Author: Alexandre Cloutier
+Date: Fri Jul 18 13:57:18 2014 -0400
+
+ indentation
+
+M SoObjects/Appointments/SOGoAppointmentObject.m
+
+commit ce6a31dd38aa50736eae48eb073deb991b87173a
+Author: Alexandre Cloutier
+Date: Fri Jul 18 09:26:02 2014 -0400
+
+ Adjust line of code to make it easier to read
+
+M SoObjects/Appointments/SOGoAppointmentObject.m
+
+commit a71013eebf8e7dd088a55cd18554d4de9c69369b
+Author: Alexandre Cloutier
+Date: Wed Jul 16 14:26:30 2014 -0400
+
+ javascript indentation
+
+M UI/WebServerResources/UIxPreferences.js
+
+commit eaec5a614d713d397b032f58f6d56ac3034165c6
+Author: Alexandre Cloutier
+Date: Wed Jul 16 14:08:39 2014 -0400
+
+ Change exception 403 to 409 and fix indentation in the javascript
+
+M SoObjects/Appointments/SOGoAppointmentObject.m
+M UI/WebServerResources/UIxPreferences.js
+
+commit 5217bed5ae3e298adc48a4c2e8c94ca1ab0e4891
+Author: Alexandre Cloutier
+Date: Wed Jul 16 14:01:50 2014 -0400
+
+ Organized the categories and appointments invitations inside a tabContainer
+
+M UI/Templates/PreferencesUI/UIxPreferences.wox
+M UI/WebServerResources/UIxPreferences.css
+M UI/WebServerResources/UIxPreferences.js
+M UI/WebServerResources/generic.css
+
+commit 17319cc8dd39c46a3f0c7c48e1ef9d182d06a663
+Author: Alexandre Cloutier
+Date: Wed Jul 16 10:37:27 2014 -0400
+
+ reverted UIxListEditor.wox
+
+M UI/Templates/ContactsUI/UIxListEditor.wox
+
+commit 89d116363ca6a27b08b3b3e6812669ebbbd69ea0
+Author: Alexandre Cloutier
+Date: Wed Jul 16 10:03:13 2014 -0400
+
+ replace ampersands with commas
+
+M SoObjects/Appointments/SOGoAppointmentObject.m
+
+commit 7c3e85f517a56ca66f540a8468b75010a5943f5f
+Author: Alexandre Cloutier
+Date: Tue Jul 15 17:34:49 2014 -0400
+
+ applied comments
+
+M SoObjects/Appointments/SOGoAppointmentObject.m
+
+commit 05fb7ae0c88a1f9b47d636caabaab96bea426309
+Author: Alexandre Cloutier
+Date: Thu Jul 10 11:13:07 2014 -0400
+
+ applied comments
+
+M SoObjects/Appointments/SOGoAppointmentObject.m
+M UI/PreferencesUI/UIxPreferences.m
+M UI/Templates/PreferencesUI/UIxPreferences.wox
+M UI/WebServerResources/UIxPreferences.js
+
+commit ef20108e3297b5d644044307ba84fd2a6c6fbdbc
+Author: Alexandre Cloutier
+Date: Wed Jul 9 17:26:41 2014 -0400
+
+ fix bug where the user could enter any names in the whitelist
+
+M UI/WebServerResources/UIxPreferences.js
+
+commit b5c0363400a48610f782c06dd0fdba21cc7cc478
+Author: Alexandre Cloutier
+Date: Mon Jul 7 17:42:43 2014 -0400
+
+ applied comment and refactor code
+
+M SoObjects/Appointments/SOGoAppointmentObject.m
+M UI/PreferencesUI/UIxPreferences.h
+M UI/PreferencesUI/UIxPreferences.m
+M UI/WebServerResources/UIxPreferences.js
+
+commit f0b8eb8dfb6d19fdc82fe92a796c9e2b9a9c2aa3
+Author: Alexandre Cloutier
+Date: Mon Jul 7 13:38:37 2014 -0400
+
+ server side code to integrate the whitelist
+
+M SoObjects/Appointments/English.lproj/Localizable.strings
+M SoObjects/Appointments/SOGoAppointmentObject.m
+M UI/PreferencesUI/UIxPreferences.m
+M UI/WebServerResources/UIxPreferences.js
+
+commit 16d02455bdcb5e8d2e2c5b4dc160b294895da82c
+Author: Alexandre Cloutier
+Date: Mon Jul 7 10:00:16 2014 -0400
+
+ Serialization of the whiteList
+
+M UI/PreferencesUI/UIxPreferences.m
+M UI/Templates/PreferencesUI/UIxPreferences.wox
+M UI/WebServerResources/UIxPreferences.js
+
+commit 8ded5a8aaff1e7b4025b6ffe35e3e36d64ebd687
+Author: Alexandre Cloutier
+Date: Fri Jul 4 09:51:41 2014 -0400
+
+ Prevent Invitations and whitelist GUI
+
+M SoObjects/Appointments/SOGoAppointmentObject.m
+M UI/PreferencesUI/UIxPreferences.h
+M UI/PreferencesUI/UIxPreferences.m
+M UI/Templates/ContactsUI/UIxListEditor.wox
+M UI/Templates/PreferencesUI/UIxPreferences.wox
+M UI/WebServerResources/SOGoAutoCompletion.js
+M UI/WebServerResources/UIxPreferences.css
+M UI/WebServerResources/UIxPreferences.js
+
+commit 1cc93c700a0925f84262896ae6d28f90395a8b51
+Author: Ludovic Marcotte
+Date: Wed Jul 9 14:08:31 2014 -0400
+
+ Updated NEWS file for changes occurred right after v2.2.6 was released
+
+M NEWS
+
+commit 44d0cb5c0d57de6548148ea204f49a5d697e8358
+Author: Francis Lachapelle
+Date: Wed Jul 9 11:17:36 2014 -0400
+
+ Fix refresh of list when forwarding a message
+
+ Fixes #2818
+
+M NEWS
+M SoObjects/Mailer/SOGoDraftObject.h
+M SoObjects/Mailer/SOGoDraftObject.m
+M UI/MailerUI/UIxMailEditor.m
+M UI/WebServerResources/MailerUI.js
+M UI/WebServerResources/UIxMailEditor.js
+
+commit dbdb7d90513aa54c2aa314013f236c434eeb0082
+Author: Ludovic Marcotte
+Date: Wed Jul 9 10:04:44 2014 -0400
+
+ Fix sending of METHOD:REPLY for DAV clients
+
+M NEWS
+M SoObjects/Appointments/SOGoAppointmentObject.m
+
+commit e343ed240b8de3b06da82a8777fe5d639cbf6a1c
+Author: Francis Lachapelle
+Date: Tue Jul 8 22:00:06 2014 -0400
+
+ Fix regression of word breaking
+
+ Fixes #2845
+
+M UI/WebServerResources/UIxCalViewPrint.css
+M UI/WebServerResources/generic.css
+
+commit 45553be122c5dd12b0373e3e6fdc4bd2f1aeef4b
+Author: Francis Lachapelle
+Date: Tue Jul 8 17:19:55 2014 -0400
+
+ Fix rename of calendars, improve tasks count badge
+
+M NEWS
+M UI/Scheduler/UIxCalendarSelector.m
+M UI/Templates/ContactsUI/UIxContactFoldersView.wox
+M UI/Templates/SchedulerUI/UIxCalendarSelector.wox
+M UI/WebServerResources/ContactsUI.js
+M UI/WebServerResources/SchedulerUI.css
+M UI/WebServerResources/SchedulerUI.js
+M UI/WebServerResources/UIxContactFolderProperties.js
+M UI/WebServerResources/generic.css
+M UI/WebServerResources/generic.js
+
+commit 1cf4841477dea27261c5654717cabab1ea6ac43e
+Author: Alexandre Cloutier
+Date: Fri Jul 4 11:23:59 2014 -0400
+
+ fix display glitch
+
+M UI/WebServerResources/SchedulerUI.js
+
+commit 017a85b7f2c91827615ab1adfbaab6dc4fef9707
+Author: Alexandre Cloutier
+Date: Fri Jul 4 10:46:49 2014 -0400
+
+ fix month events categories display
+
+M UI/WebServerResources/SchedulerUI.js
+
+commit 8c8e47daf632ce5146df347c407cbdc5ba858681
+Author: Alexandre Cloutier
+Date: Fri Jul 4 10:37:35 2014 -0400
+
+ fix spacing between events and categorie display
+
+M UI/WebServerResources/SchedulerUI.js
+
+commit 8a172467253db8e129a0926d949b86410e50d811
+Author: Ludovic Marcotte
+Date: Fri Jul 4 10:18:56 2014 -0400
+
+ Cleaned up code and fixed the translation of the weekdays in the datepicker
+
+M UI/Scheduler/UIxDatePicker.h
+M UI/Scheduler/UIxDatePicker.m
+M UI/WebServerResources/datepicker.js
+
+commit 4843c6b6d7f05e32047a27e1c6cd28a1912e615d
+Author: Ludovic Marcotte
+Date: Fri Jul 4 08:55:35 2014 -0400
+
+ Renamed Multi-Column to Multicolumn and refactored some code
+
+M UI/Scheduler/English.lproj/Localizable.strings
+M UI/Scheduler/Toolbars/SOGoAppointmentFolders.toolbar
+M UI/Scheduler/UIxCalViewPrint.m
+
+commit 6e13f1547719c5f3bfc6149d9a038de90c284cb2
+Author: Ludovic Marcotte
+Date: Wed Jul 2 11:32:18 2014 -0400
+
+ Update ChangeLog
+
+M ChangeLog
+
commit 5dd2088d42388b397e8cc3fde35455b2455f7f3e
Author: Ludovic Marcotte
Date: Wed Jul 2 11:32:06 2014 -0400
diff --git a/Documentation/SOGo Installation Guide.odt b/Documentation/SOGo Installation Guide.odt
index 81fbe0883..64513c61f 100644
Binary files a/Documentation/SOGo Installation Guide.odt and b/Documentation/SOGo Installation Guide.odt differ
diff --git a/Documentation/SOGo Mozilla Thunderbird Configuration.odt b/Documentation/SOGo Mozilla Thunderbird Configuration.odt
index 97588c202..01702b8e5 100644
Binary files a/Documentation/SOGo Mozilla Thunderbird Configuration.odt and b/Documentation/SOGo Mozilla Thunderbird Configuration.odt differ
diff --git a/Documentation/SOGo Native Microsoft Outlook Configuration.odt b/Documentation/SOGo Native Microsoft Outlook Configuration.odt
index 7651f52ed..ed89ec8c0 100644
Binary files a/Documentation/SOGo Native Microsoft Outlook Configuration.odt and b/Documentation/SOGo Native Microsoft Outlook Configuration.odt differ
diff --git a/GNUmakefile b/GNUmakefile
index 957160740..fdff4d793 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -6,7 +6,6 @@ include $(GNUSTEP_MAKEFILES)/common.make
SUBPROJECTS = \
SOPE/NGCards \
SOPE/GDLContentStore \
- OGoContentStore \
SoObjects \
Main \
UI \
diff --git a/Main/GNUmakefile.preamble b/Main/GNUmakefile.preamble
index 675b5916c..022e3d1e2 100644
--- a/Main/GNUmakefile.preamble
+++ b/Main/GNUmakefile.preamble
@@ -10,14 +10,12 @@ ADDITIONAL_INCLUDE_DIRS += \
ADDITIONAL_LIB_DIRS += \
-L../SoObjects/SOGo/SOGo.framework \
- -L../OGoContentStore/$(GNUSTEP_OBJ_DIR)/ \
-L../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/
SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib
$(SOGOD)_TOOL_LIBS += \
-lSOGo \
- -lOGoContentStore \
-lGDLContentStore \
-lGDLAccess \
-lWEExtensions \
diff --git a/NEWS b/NEWS
index 4b233c364..88c22f938 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,59 @@
+2.2.8 (2014-09-10)
+------------------
+
+New features
+ - new user settings for threads collapsing
+ - IMAP global search support (#2670)
+
+Enchancements
+ - major refactoring of the GCS component saving code (dropped OGoContentStore)
+ - printing calendars in colors is now possible in all views; list, daily, weekly and multicolumns
+ - new option to print calendars events and tasks with a background color or with a border color
+ - labels tagging only make one AJAX call for all the selected messages instead of one AJAX call per message
+ - new option to print calendars events and tasks with a background color or with a border color
+ - all modules can now be automatically refreshed
+ - new configurable user defaults variables; SOGoRefreshViewCheck & SOGoRefreshViewIntervals. SOGoMailMessageCheck has
+ been replaced by SOGoRefreshViewCheck and SOGoMailPollingIntervals has been replaced by SOGoRefreshViewIntervals
+ - updated Catalan, Czech, Dutch, Finnish, French, Hungarian, Norwegian, and Polish translations
+
+Bug fixes
+ - fixed crasher when subscribing users to resources (#2892)
+ - fixed encoding of new calendars and new subscriptions (JavaScript only)
+ - fixed display of users with no possible subscription
+ - fixed usage of SOGoSubscriptionFolderFormat domain default when the folder's name hasn't been changed
+ - fixed "sogo-tool restore -l" that was returning incorrect folder IDs
+ - fixed Can not delete mail when over quota (#2812)
+ - fixed Events and tasks cannot be moved to other calendars using drag&drop (#2759)
+ - fixed In "Multicolumn Day View" mouse position is not honored when creating an event (#2864)
+ - fixed handling of messages labels (#2902)
+ - fixed Apache > 2.3 configuration
+ - fixed freebusy retrieval during timezone changes (#1240)
+
+2.2.7 (2014-07-30)
+------------------
+
+New features
+ - new user preference to prevent event invitations
+
+Enhancements
+ - improved badges of active tasks count
+ - refresh draft folder after sending a message
+ - now possible to DnD events in the calendar list
+ - improved handling of SOGoSubscriptionFolderFormat
+ - JSON'ified folder subscription interface
+ - updated Finnish, French, German, and Spanish (Spain) translations
+ - updated CKEditor to version 4.4.3
+
+Bug fixes
+ - fixed weekdays translation in the datepicker
+ - fixed event categories display
+ - fixed all-day events display in IE
+ - fixed rename of calendars
+ - we now correctly add the "METHOD:REPLY" when sending out ITIP messages from DAV clients
+ - fixed refresh of message headers when forwarding a message (#2818)
+ - we now correctly escape all charset= in tags, not only in the
+ - we now destroy cache objects of vanished folders
+
2.2.6 (2014-07-02)
------------------
@@ -9,7 +65,7 @@ Enhancements
- implemented the GetAttachment ActiveSync command (#2808)
- implemented the Ping ActiveSync command
- added "soft deletes" support for ActiveSync (#2734)
- - now display the active tasks next to calendar names (#2760)
+ - now display the active tasks count next to calendar names (#2760)
Bug fixes
- better handling of empty "Flag" messages over ActiveSync (#2806)
diff --git a/OGoContentStore/COPYING b/OGoContentStore/COPYING
deleted file mode 100644
index 161a3d1d4..000000000
--- a/OGoContentStore/COPYING
+++ /dev/null
@@ -1,482 +0,0 @@
- GNU LIBRARY GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the library GPL. It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it. You can use it for
-your libraries, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
- Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library. If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software. To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
- Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs. This
-license, the GNU Library General Public License, applies to certain
-designated libraries. This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
- The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it. Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program. However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
- Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries. We
-concluded that weaker conditions might promote sharing better.
-
- However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves. This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them. (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.) The hope is that this
-will lead to faster development of free libraries.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, while the latter only
-works together with the library.
-
- Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-
- GNU LIBRARY GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License"). Each licensee is
-addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- c) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- d) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- Appendix: How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- , 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
diff --git a/OGoContentStore/GNUmakefile b/OGoContentStore/GNUmakefile
deleted file mode 100644
index 3b7a48a62..000000000
--- a/OGoContentStore/GNUmakefile
+++ /dev/null
@@ -1,34 +0,0 @@
-# GNUstep makefile
-
-include ../config.make
-include $(GNUSTEP_MAKEFILES)/common.make
-include ./Version
-
-LIBRARY_NAME = libOGoContentStore
-
-TYPEMODELS_DIR = $(SOGO_TYPEMODELS)
-
-libOGoContentStore_HEADER_FILES_DIR = .
-libOGoContentStore_HEADER_FILES_INSTALL_DIR = /OGoContentStore
-libOGoContentStore_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION)
-
-ADDITIONAL_INCLUDE_DIRS += -I../SOPE
-ADDITIONAL_LIB_DIRS += -L../SOPE/GDLContentStore/obj
-
-libOGoContentStore_OBJC_FILES += \
- OCSiCalFieldExtractor.m \
- OCSContactFieldExtractor.m \
-
-libOGoContentStore_TYPEMODELS += \
- appointment.ocs \
- contact.ocs \
- appointment-oracle.ocs \
- contact-oracle.ocs
-
--include GNUmakefile.preamble
-ifneq ($(FHS_INSTALL_ROOT),)
-GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include
-endif
-include $(GNUSTEP_MAKEFILES)/library.make
-include $(GNUSTEP_MAKEFILES)/tool.make
--include GNUmakefile.postamble
diff --git a/OGoContentStore/GNUmakefile.preamble b/OGoContentStore/GNUmakefile.preamble
deleted file mode 100644
index 3a458580d..000000000
--- a/OGoContentStore/GNUmakefile.preamble
+++ /dev/null
@@ -1,32 +0,0 @@
-# compilation settings
-
-libOGoContentStore_LIBRARIES_DEPEND_UPON += \
- -lGDLContentStore \
- -lGDLAccess \
- -lNGCards \
- -lNGExtensions \
- -lEOControl \
- -lSaxObjC \
- $(BASE_LIBS)
-
-ADDITIONAL_INCLUDE_DIRS += -I. -I.. -I../SOPE -I../SoObjects
-
-ADDITIONAL_LIB_DIRS += -L./$(GNUSTEP_OBJ_DIR) -L../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ -L../SoObjects/SOGo/SOGo.framework/
-
-SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib
-
-ifeq ($(FOUNDATION_LIB),apple)
-libOGoContentStore_PREBIND_ADDR="0xC7700000"
-libOGoContentStore_LDFLAGS += -seg1addr $(libOGoContentStore_PREBIND_ADDR)
-endif
-
-test_quick_extract_TOOL_LIBS += \
- -lEOControl \
- -lSaxObjC \
- -lDOM \
- -lNGExtensions \
- -lNGCards \
- -lGDLContentStore \
- -lGDLAccess \
- -lOGoContentStore \
- $(BASE_LIBS)
diff --git a/OGoContentStore/OCSContactFieldExtractor.m b/OGoContentStore/OCSContactFieldExtractor.m
deleted file mode 100644
index 8b1445316..000000000
--- a/OGoContentStore/OCSContactFieldExtractor.m
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- Copyright (C) 2004-2005 SKYRIX Software AG
-
- This file is part of OpenGroupware.org.
-
- OGo is free software; you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- OGo is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with OGo; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-*/
-
-#import
-#import
-#import
-#import
-
-#import
-#import
-#import
-
-#import
-
-@interface OCSContactFieldExtractor : GCSFieldExtractor
-@end
-
-@implementation OCSContactFieldExtractor
-
-- (NSMutableDictionary *) extractQuickFieldsFromVCard: (NGVCard *) vCard
-{
- NSMutableDictionary *fields;
- NSArray *values;
- CardElement *element;
- NSString *value;
-
- fields = [NSMutableDictionary dictionaryWithCapacity: 16];
-
- value = [vCard fn];
- if (value)
- [fields setObject: value forKey: @"c_cn"];
- element = [vCard n];
- [fields setObject: [element flattenedValueAtIndex: 0 forKey: @""]
- forKey: @"c_sn"];
- [fields setObject: [element flattenedValueAtIndex: 1 forKey: @""]
- forKey: @"c_givenName"];
- value = [vCard preferredTel];
- if (value)
- [fields setObject: value forKey: @"c_telephonenumber"];
- value = [vCard preferredEMail];
- if (![value isNotNull])
- value = @"";
- [fields setObject: value forKey: @"c_mail"];
- element = [vCard org];
- [fields setObject: [element flattenedValueAtIndex: 0 forKey: @""]
- forKey: @"c_o"];
- [fields setObject: [element flattenedValueAtIndex: 1 forKey: @""]
- forKey: @"c_ou"];
- element = [vCard preferredAdr];
- if (element && ![element isVoid])
- [fields setObject: [element flattenedValueAtIndex: 3
- forKey: @""]
- forKey: @"c_l"];
- value = [[vCard uniqueChildWithTag: @"X-AIM"] flattenedValuesForKey: @""];
- [fields setObject: value forKey: @"c_screenname"];
- values = [[vCard categories] trimmedComponents];
- if ([values count] > 0)
- [fields setObject: [values componentsJoinedByString: @","]
- forKey: @"c_categories"];
- else
- [fields setObject: [NSNull null] forKey: @"c_categories"];
- [fields setObject: @"vcard" forKey: @"c_component"];
-
- return fields;
-}
-
-- (NSMutableDictionary *) extractQuickFieldsFromVList: (NGVList *) vList
-{
- NSMutableDictionary *fields;
- NSString *value;
-
- fields = [NSMutableDictionary dictionaryWithCapacity: 1];
-
- value = [vList fn];
- if (value)
- [fields setObject: value forKey: @"c_cn"];
- [fields setObject: @"vlist" forKey: @"c_component"];
-
- return fields;
-}
-
-- (NSMutableDictionary *) extractQuickFieldsFromContent: (NSString *) content
-{
- NSMutableDictionary *fields;
- NGVCard *vCard;
- NGVList *vList;
- NSString *upperContent;
-
- fields = nil;
- if ([content length] > 0)
- {
- upperContent = [content uppercaseString];
- if ([upperContent hasPrefix: @"BEGIN:VCARD"])
- {
- vCard = [NGVCard parseSingleFromSource: content];
- if (vCard)
- fields = [self extractQuickFieldsFromVCard: vCard];
- else
- [self errorWithFormat: @"Could not parse VCARD content."];
- }
- else if ([upperContent hasPrefix: @"BEGIN:VLIST"])
- {
- vList = [NGVList parseSingleFromSource: content];
- if (vList)
- fields = [self extractQuickFieldsFromVList: vList];
- else
- [self errorWithFormat: @"Could not parse VLIST content."];
- }
- else
- [self errorWithFormat: @"Content is unknown."];
- }
- else
- [self errorWithFormat: @"Content is empty."];
-
- return fields;
-}
-
-@end /* OCSContactFieldExtractor */
diff --git a/OGoContentStore/OCSiCalFieldExtractor.h b/OGoContentStore/OCSiCalFieldExtractor.h
deleted file mode 100644
index 504d2842c..000000000
--- a/OGoContentStore/OCSiCalFieldExtractor.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- Copyright (C) 2004-2005 SKYRIX Software AG
-
- This file is part of OpenGroupware.org.
-
- OGo is free software; you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- OGo is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with OGo; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-*/
-
-#ifndef __OGoContentStore_OCSiCalFieldExtractor_H__
-#define __OGoContentStore_OCSiCalFieldExtractor_H__
-
-#include
-
-@interface OCSiCalFieldExtractor : GCSFieldExtractor
-{
-}
-
-+ (id)sharedICalFieldExtractor;
-
-@end
-
-#endif /* __OGoContentStore_OCSiCalFieldExtractor_H__ */
diff --git a/OGoContentStore/OCSiCalFieldExtractor.m b/OGoContentStore/OCSiCalFieldExtractor.m
deleted file mode 100644
index 3bd604720..000000000
--- a/OGoContentStore/OCSiCalFieldExtractor.m
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- Copyright (C) 2004 SKYRIX Software AG
-
- This file is part of OpenGroupware.org.
-
- OGo is free software; you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- OGo is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with SOGo; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-*/
-
-#import
-#import
-#import
-#import
-
-#import
-#import
-#import
-
-#import
-
-#import "OCSiCalFieldExtractor.h"
-
-@implementation OCSiCalFieldExtractor
-
-+ (id) sharedICalFieldExtractor
-{
- static OCSiCalFieldExtractor *extractor = nil;
-
- if (!extractor)
- extractor = [self new];
-
- return extractor;
-}
-
-/* operations */
-
-- (CardGroup *) firstElementFromCalendar: (iCalCalendar *) ical
-{
- NSArray *elements;
- CardGroup *element;
- unsigned int count;
-
- elements = [ical allObjects];
- count = [elements count];
- if (count)
- element = [elements objectAtIndex: 0];
- else
- {
- [self logWithFormat: @"ERROR: given calendar contains no elements: %@", ical];
- element = nil;
- }
-
- return element;
-}
-
-- (NSMutableDictionary *) extractQuickFieldsFromContent: (NSString *) _content
-{
- NSMutableDictionary *fields;
- id cal;
-
- fields = nil;
-
- if ([_content length])
- {
- cal = [iCalCalendar parseSingleFromSource: _content];
- if (cal)
- {
- if ([cal isKindOfClass: [iCalCalendar class]])
- cal = [self firstElementFromCalendar: cal];
-
- if ([cal isKindOfClass: [iCalRepeatableEntityObject class]])
- fields = [cal quickRecord];
- else if ([cal isNotNull])
- [self logWithFormat: @"ERROR: unexpected iCalendar parse result: %@",
- cal];
- }
- else
- [self logWithFormat: @"ERROR: parsing source didn't return anything"];
- }
-
- return fields;
-}
-
-@end /* OCSiCalFieldExtractor */
diff --git a/OGoContentStore/README b/OGoContentStore/README
deleted file mode 100644
index 4c2b1d3b6..000000000
--- a/OGoContentStore/README
+++ /dev/null
@@ -1,144 +0,0 @@
-Storage Backend
-===============
-
-The storage backend implements the "low level" folder abstraction, which is
-basically an arbitary "BLOB" containing some document. The feature is that
-we extract "quick access" / "searchable" attributes from the document content.
-
-Further it contains the "folder management" API, as named folders can be stored
-in different databases.
-Note: we need a way to tell where "new" folders should be created
-Note: to sync with LDAP we need to periodically delete or archive old folders
-
-Folders have associated a type (like 'calendar') which defines the query
-attributes and serialization format.
-
-TODO
-====
-- hierarchies deeper than 4 (properly filter on path in OCS)
-
-Open Questions
-==============
-
-System-meta-data in the blob-table or in the quick-table?
-- master data belongs into the blob table
-- could be regular 'NSxxx' keys to differentiate meta data from
-
-Class Hierarchy
-===============
-
- [NSObject]
- OCSContext - tracking context
- OCSFolder - represents a single folder
- OCSFolderManager - manages folders
- OCSFolderType - the mapping info for a specific folder-type
- OCSFieldInfo - mapping info for one 'quick field'
- OCSChannelManager - maintains EOAdaptorChannel objects
-
- TBD:
- - field 'extractor'
- - field 'value' (eg array values for participants?)
- - BLOB archiver/unarchiver
-
-Defaults
-========
-
- OCSFolderInfoURL - the DB URL where the folder-info table is located
- eg: http://OGo:OGo@localhost/test/folder_info
-
- OCSFolderManagerDebugEnabled - enable folder-manager debug logs
- OCSFolderManagerSQLDebugEnabled - enable folder-manager SQL gen debug logs
-
- OCSChannelManagerDebugEnabled - enable channel debug pooling logs
- OCSChannelManagerPoolDebugEnabled - debug pool handle allocation
-
- OCSChannelExpireAge - if that age in seconds is exceeded, a channel
- will be removed from the pool
- OCSChannelCollectionTimer - time in seconds. each n-seconds the pool will be
- checked for channels too old
-
- [PGDebugEnabled] - enable PostgreSQL adaptor debugging
-
-URLs
-====
-
- "Database URLs"
-
- We use the schema:
- postgresql://[user]:[password]@[host]:[port]/[dbname]/[tablename]
-
-BLOB Formats
-============
-
-- TBD
-- iCal, XML
-- problem with iCal is that a complete and valid iCal file is different from
- just the vevent. so we basically need to parse those files in any case.
-- XML: the iCal SaxDriver reports XML events, so we can easily store that as
- XML
-- we need to parse the BLOB for different clients anyway (iCal != iCal ...)
-- XML: we could use some XML query extension to PG in the future?
-
-Update: we now have OCSiCalFieldExtractor
- - it parses the BLOB as an iCalendar file and extracts a set of fixed
- keys:
- - title - plain copy of "summary"
- - uid - plain copy
- - startdate - date as utime
- - enddate - date as utime
- - participants - CNs of attendees separated by comma ", "
- - location
- - partmails
- - sequence
- - TBD: iscyclic
- - TBD: isallday
- - TBD: cycles - I guess the client should fetch the BLOB to resolve
- - the field extractor is accessed by OCSFolder using the folderinfo:
- extractor = [self->folderInfo quickExtractor];
- quickRow = [extractor extractQuickFieldsFromContent:_content];
-
-Support Tools
-=============
-
-- tools we need:
- - one to recreate a quick table based on the blob table
-
-Notes
-=====
-
-- need to use http:// URLs for connect info, until generic URLs in
- libFoundation are fixed (the parses breaks on the login/password parts)
-
-QA
-==
-
-Q: Why do we use two tables, we could store the quick columns in the blob?
-==
-They could be in the same table. I considered using separate tables since the
-quick table is likely to be recreated now and then if BLOB indexing
-requirements change.
-Actually one could even use different _quick tables which share a common BLOB
-table.
-(a quick table is nothing more than a database index and like with DB indexes
- multiple ones for different requirements can make sense).
-
-Further it might improve caching behaviour for row based caches (the quick
-table is going to be queried much more often) - not sure whether this is
-relevant with PostgreSQL, probably not?
-
-Q: Can we use a VARCHAR primary key?
-==
-I asked in the postgres IRC channel and apparently the performance penalty of
-string primary keys isn't big.
-We could also use an 'internal' int sequence in addition (might be useful for
-supporting ZideLook)
-Motivation: the 'iCalendar' ID is a string and usually looks like a GUID.
-
-Q: Why using VARCHAR instead of TEXT in the BLOB?
-==
-To quote PostgreSQL documentation:
-"There are no performance differences between these three types, apart from
- the increased storage size when using the blank-padded type."
-So varchar(xx) is just a large TEXT. Since we intend to store mostly small
-snippets of data (tiny XML fragments), I considered VARCHAR the more
-appropriate type.
diff --git a/OGoContentStore/Version b/OGoContentStore/Version
deleted file mode 100644
index 0d15a8243..000000000
--- a/OGoContentStore/Version
+++ /dev/null
@@ -1,14 +0,0 @@
-# Version file
-
-MAJOR_VERSION=0
-MINOR_VERSION=9
-SUBMINOR_VERSION:=33
-
-# v0.9.30 requires libNGiCal v4.5.48
-# v0.9.26 requires libGDLContentStore v4.5.26
-# v0.9.19 requires libNGiCal v4.5.40
-# v0.9.18 requires libNGiCal v4.5.38
-# v0.9.17 requires libNGiCal v4.5.37
-# v0.9.11 requires libFoundation v1.0.63
-# v0.9.11 requires libNGExtensions v4.3.125
-# v0.9.7 requires libGDLAccess v1.1.35
diff --git a/OGoContentStore/iCalRepeatableEntityObject+OCS.h b/OGoContentStore/iCalRepeatableEntityObject+OCS.h
deleted file mode 100644
index 36371ede4..000000000
--- a/OGoContentStore/iCalRepeatableEntityObject+OCS.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- Copyright (C) 2004-2005 SKYRIX Software AG
-
- This file is part of OpenGroupware.org.
-
- OGo is free software; you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- OGo is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with OGo; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-*/
-// $Id: iCalRepeatableEntityObject+OCS.h 617 2005-03-01 17:08:11Z znek $
-
-
-#ifndef __OGoContentStore_iCalRepeatableEntityObject_OCS_H_
-#define __OGoContentStore_iCalRepeatableEntityObject_OCS_H_
-
-#include
-
-@interface iCalRepeatableEntityObject (OCS)
-
-- (NSString *)cycleInfo;
-
-@end
-
-#endif /* __OGoContentStore_iCalRepeatableEntityObject_OCS_H_ */
diff --git a/OGoContentStore/iCalRepeatableEntityObject+OCS.m b/OGoContentStore/iCalRepeatableEntityObject+OCS.m
deleted file mode 100644
index 6e31876dc..000000000
--- a/OGoContentStore/iCalRepeatableEntityObject+OCS.m
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- Copyright (C) 2004-2005 SKYRIX Software AG
-
- This file is part of OpenGroupware.org.
-
- OGo is free software; you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- OGo is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with OGo; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-*/
-
-#import
-#import
-
-#import "iCalRepeatableEntityObject+OCS.h"
-
-@implementation iCalRepeatableEntityObject (OCS)
-
-@end
diff --git a/OGoContentStore/misc/iNetOrgPerson.txt b/OGoContentStore/misc/iNetOrgPerson.txt
deleted file mode 100644
index eff00af8b..000000000
--- a/OGoContentStore/misc/iNetOrgPerson.txt
+++ /dev/null
@@ -1,108 +0,0 @@
-http://www.faqs.org/rfcs/rfc2798.html
-
-Class
- NAME 'inetOrgPerson'
- SUP organizationalPerson
- STRUCTURAL
- MAY (
- audio $ businessCategory $ carLicense $ departmentNumber $
- displayName $ employeeNumber $ employeeType $ givenName $
- homePhone $ homePostalAddress $ initials $ jpegPhoto $
- labeledURI $ mail $ manager $ mobile $ o $ pager $
- photo $ roomNumber $ secretary $ uid $ userCertificate $
- x500uniqueIdentifier $ preferredLanguage $
- userSMIMECertificate $ userPKCS12
- )
- MUST (
- cn $ objectClass $ sn
- )
- MAY (
- description $ destinationIndicator $ facsimileTelephoneNumber $
- internationaliSDNNumber $ l $ ou $ physicalDeliveryOfficeName $
- postalAddress $ postalCode $ postOfficeBox $
- preferredDeliveryMethod $ registeredAddress $ seeAlso $
- st $ street $ telephoneNumber $ teletexTerminalIdentifier $
- telexNumber $ title $ userPassword $ x121Address
- )
-
-Properties (inetOrgPerson + organizationalPerson)
- businessCategory
- carLicense
- departmentNumber
- destinationIndicator
- employeeNumber
- employeeType
- facsimileTelephoneNumber
- givenName
- homePostalAddress
- initials
- jpegPhoto
- l
- mail
- manager
- mobile
- o
- objectClass
- ou
- pager
- physicalDeliveryOfficeName
- postOfficeBox
- postalCode
- preferredLanguage
- registeredAddress
- roomNumber
- secretary
- seeAlso
- sn
- street
- telephoneNumber
- teletexTerminalIdentifier
- title
- uid
- userCertificate
- userPKCS12
- userPassword
- x121Address
- audio
- cn
- description
- displayName
- homePhone
- internationaliSDNNumber
- labeledURI
- photo
- postalAddress
- preferredDeliveryMethod
- st
- telexNumber
- userSMIMECertificate
- x500uniqueIdentifier
-
-Sample:
- version: 1
- dn: cn=Barbara Jensen,ou=Product Development,dc=siroe,dc=com
- objectClass: top
- objectClass: person
- objectClass: organizationalPerson
- objectClass: inetOrgPerson
- cn: Barbara Jensen
- cn: Babs Jensen
- displayName: Babs Jensen
- sn: Jensen
- givenName: Barbara
- initials: BJJ
- title: manager, product development
- uid: bjensen
- mail: bjensen@siroe.com
- telephoneNumber: +1 408 555 1862
- facsimileTelephoneNumber: +1 408 555 1992
- mobile: +1 408 555 1941
- roomNumber: 0209
- carLicense: 6ABC246
- o: Siroe
- ou: Product Development
- departmentNumber: 2604
- employeeNumber: 42
- employeeType: full time
- preferredLanguage: fr, en-gb;q=0.8, en;q=0.7
- labeledURI: http://www.siroe.com/users/bjensen My Home Page
diff --git a/OGoContentStore/misc/icaltest.ical b/OGoContentStore/misc/icaltest.ical
deleted file mode 100644
index d048821f7..000000000
--- a/OGoContentStore/misc/icaltest.ical
+++ /dev/null
@@ -1,30 +0,0 @@
-BEGIN:VEVENT
-DURATION:PT1H
-ATTENDEE;CN="Elke Bethke";DIR="addressbook://B156F3F0-9CFD-11D8-8561-000
- D93C1A604:ABPerson":mailto:E.Bethke@Sachsen-Anhalt-Lotto.de
-ATTENDEE;CN="Erik Doernenburg";DIR="addressbook://B15FCB0F-9CFD-11D8-8561
- -000D93C1A604:ABPerson":mailto:erik@x101.net
-ATTENDEE;CN="Christian Schnelle";DIR="addressbook://B1418D4E-9CFD-11D8-8
- 561-000D93C1A604:ABPerson":mailto:cs@enervation.de
-ATTENDEE;CN="Chris Herrenberger";DIR="addressbook://B14A390C-9CFD-11D8-8
- 561-000D93C1A604:ABPerson":invalid:nomail
-ATTENDEE;CN="Horst Parplies";DIR="addressbook://B19B47E5-9CFD-11D8-8561-
- 000D93C1A604:ABPerson":mailto:horst.parplies@freenet.de
-ATTENDEE;CN="Imdat Solak";DIR="addressbook://B19EDB62-9CFD-11D8-8561-000
- D93C1A604:ABPerson":mailto:imdat@solak.de
-ATTENDEE;CN="Jens Enders";DIR="addressbook://B1B6819F-9CFD-11D8-8561-000
- D93C1A604:ABPerson":mailto:jens.enders@skyrix.com
-ATTENDEE;CN="Jens Muenster";DIR="addressbook://B1BBA42E-9CFD-11D8-8561-00
- 0D93C1A604:ABPerson":mailto:jens.muenster@skyrix.com
-ATTENDEE;CN="Laurent Pierre";DIR="addressbook://9337C270-A825-11D8-B930-
- 000D93C1A604:ABPerson":mailto:laurent.pierre@linagora.com
-ATTENDEE;CN="Marcel Weiher";DIR="addressbook://B1F9BB12-9CFD-11D8-8561-0
- 00D93C1A604:ABPerson":mailto:marcel@metaobject.co
-DTSTAMP:20040520T140002Z
-UID:BD91C454-AA65-11D8-84CA-000D93C1A604
-SEQUENCE:3
-STATUS:CONFIRMED
-DTSTART;TZID=Europe/Berlin:20040618T160000
-SUMMARY:SIZE EVENT
-X-WR-ITIPSTATUSML:UNCLEAN
-END:VEVENT
diff --git a/OGoContentStore/misc/test1/GNUmakefile b/OGoContentStore/misc/test1/GNUmakefile
deleted file mode 100644
index d92ce9b29..000000000
--- a/OGoContentStore/misc/test1/GNUmakefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# $Id$
-
-include $(GNUSTEP_MAKEFILES)/common.make
-
-TOOL_NAME = test
-
-test_OBJC_FILES += test1.m
-
-ADDITIONAL_TOOL_LIBS += -lOGoContentStore
-
-ADDITIONAL_LIB_DIRS += -L../../$(GNUSTEP_OBJ_DIR)
-
--include GNUmakefile.preamble
-include $(GNUSTEP_MAKEFILES)/tool.make
--include GNUmakefile.postamble
diff --git a/OGoContentStore/misc/test1/common.h b/OGoContentStore/misc/test1/common.h
deleted file mode 100644
index f771957e7..000000000
--- a/OGoContentStore/misc/test1/common.h
+++ /dev/null
@@ -1,3 +0,0 @@
-// $Id$
-
-#import
diff --git a/OGoContentStore/misc/test1/test1.m b/OGoContentStore/misc/test1/test1.m
deleted file mode 100644
index 7724b19d1..000000000
--- a/OGoContentStore/misc/test1/test1.m
+++ /dev/null
@@ -1,31 +0,0 @@
-// $Id$
-
-#include "common.h"
-
-static void testurl(NSString *s) {
- NSURL *url;
-
- url = [NSURL URLWithString:s];
- NSLog(@"url: %@", url);
- NSLog(@" login: %@", [url user]);
- NSLog(@" pwd: %@", [url password]);
-}
-
-static void test(void) {
- testurl(@"http://OGoUser:OGoPwd@localhost/OGo");
- testurl(@"postgresql://OGoUser:OGoPwd@localhost/OGo");
-}
-
-int main(int argc, char **argv, char **env) {
- NSAutoreleasePool *pool;
-
- pool = [[NSAutoreleasePool alloc] init];
-#if LIB_FOUNDATION_LIBRARY
- [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
-#endif
-
- test();
-
- [pool release];
- return 0;
-}
diff --git a/OpenChange/GNUmakefile b/OpenChange/GNUmakefile
index 2a7bac557..3e323a300 100644
--- a/OpenChange/GNUmakefile
+++ b/OpenChange/GNUmakefile
@@ -137,7 +137,6 @@ $(DBMSGREADER_TOOL)_OBJC_FILES += \
$(DBMSGREADER_TOOL)_LIB_DIRS += \
-L../SoObjects/SOGo/SOGo.framework/ -lSOGo \
- -L../OGoContentStore/obj/ -lOGoContentStore \
-L../SOPE/GDLContentStore/obj/ -lGDLContentStore \
-L../SOPE/NGCards/obj/ -lNGCards \
-lNGObjWeb
@@ -166,7 +165,6 @@ $(MAPISTORESOGO)_LIB_DIRS += \
$(LIBMAPISTORE_LIBS)
$(SOGOBACKEND)_LIB_DIRS += \
- -L../OGoContentStore/$(GNUSTEP_OBJ_DIR)/ -lOGoContentStore \
-L../SoObjects/SOGo/SOGo.framework/ -lSOGo \
$(LIBMAPI_LIBS) \
$(LIBMAPISTORE_LIBS)
diff --git a/OpenChange/MAPIStoreContactsMessage.m b/OpenChange/MAPIStoreContactsMessage.m
index b2a5ce660..3b35f9c34 100644
--- a/OpenChange/MAPIStoreContactsMessage.m
+++ b/OpenChange/MAPIStoreContactsMessage.m
@@ -1200,7 +1200,7 @@ fromProperties: (NSDictionary *) attachmentProps
//
// we save the new/modified card
//
- [sogoObject saveContentString: [newCard versitString]];
+ [sogoObject saveComponent: newCard];
[self updateVersions];
}
diff --git a/OpenChange/MAPIStoreTasksMessage.m b/OpenChange/MAPIStoreTasksMessage.m
index 2a7958f19..9215bc409 100644
--- a/OpenChange/MAPIStoreTasksMessage.m
+++ b/OpenChange/MAPIStoreTasksMessage.m
@@ -513,7 +513,7 @@
}
[vToDo setTimeStampAsDate: now];
- [sogoObject saveContentString: [vCalendar versitString]];
+ [sogoObject saveComponent: vCalendar];
[self updateVersions];
}
diff --git a/SOPE/GDLContentStore/GCSFieldExtractor.h b/SOPE/GDLContentStore/GCSFieldExtractor.h
deleted file mode 100644
index 1b1e64af4..000000000
--- a/SOPE/GDLContentStore/GCSFieldExtractor.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- Copyright (C) 2004-2005 SKYRIX Software AG
-
- This file is part of OpenGroupware.org.
-
- OGo is free software; you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- OGo is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with OGo; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-*/
-
-#ifndef __GDLContentStore_GCSFieldExtractor_H__
-#define __GDLContentStore_GCSFieldExtractor_H__
-
-#import
-
-@class NSString, NSMutableDictionary;
-
-@interface GCSFieldExtractor : NSObject
-{
-}
-
-- (NSMutableDictionary *)extractQuickFieldsFromContent:(NSString *)_content;
-
-@end
-
-#endif /* __GDLContentStore_GCSFieldExtractor_H__ */
diff --git a/SOPE/GDLContentStore/GCSFieldExtractor.m b/SOPE/GDLContentStore/GCSFieldExtractor.m
deleted file mode 100644
index 134a40343..000000000
--- a/SOPE/GDLContentStore/GCSFieldExtractor.m
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- Copyright (C) 2004-2005 SKYRIX Software AG
-
- This file is part of OpenGroupware.org.
-
- OGo is free software; you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- OGo is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with OGo; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-*/
-
-#import "GCSFieldExtractor.h"
-
-@implementation GCSFieldExtractor
-
-- (NSMutableDictionary *)extractQuickFieldsFromContent:(NSString *)_content {
- return nil;
-}
-
-@end /* GCSFieldExtractor */
diff --git a/SOPE/GDLContentStore/GCSFolder.h b/SOPE/GDLContentStore/GCSFolder.h
index ff940fd40..296933b2c 100644
--- a/SOPE/GDLContentStore/GCSFolder.h
+++ b/SOPE/GDLContentStore/GCSFolder.h
@@ -117,10 +117,11 @@
- (NSDictionary *) recordOfEntryWithName: (NSString *) name;
- (NSException *) writeContent: (NSString *) _content
+ fromComponent: (id) theComponent
+ container: (id) theContainer
toName: (NSString *) _name
baseVersion: (unsigned int *) _baseVersion;
-- (NSException *) writeContent: (NSString *) _content
- toName: (NSString *) _name;
+
- (NSException *) deleteContentWithName: (NSString *) _name;
- (NSException *) deleteAllContent;
diff --git a/SOPE/GDLContentStore/GCSFolder.m b/SOPE/GDLContentStore/GCSFolder.m
index ac5efa58e..2b05ef67e 100644
--- a/SOPE/GDLContentStore/GCSFolder.m
+++ b/SOPE/GDLContentStore/GCSFolder.m
@@ -1,22 +1,22 @@
/*
Copyright (C) 2004-2007 SKYRIX Software AG
Copyright (C) 2007 Helge Hess
- Copyright (c) 2008-2011 Inverse inc.
+ Copyright (c) 2008-2014 Inverse inc.
- This file is part of OpenGroupware.org.
+ This file is part of SOGo.
- OGo is free software; you can redistribute it and/or modify it under
+ SOGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
- OGo is distributed in the hope that it will be useful, but WITHOUT ANY
+ SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with OGo; see the file COPYING. If not, write to the
+ License along with SOGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
@@ -38,7 +38,6 @@
#import "GCSFolderManager.h"
#import "GCSFolderType.h"
#import "GCSChannelManager.h"
-#import "GCSFieldExtractor.h"
#import "NSURL+GCS.h"
#import "EOAdaptorChannel+GCS.h"
#import "EOQualifier+GCS.h"
@@ -882,13 +881,14 @@ andAttribute: (EOAttribute *)_attribute
}
- (NSException *) writeContent: (NSString *) _content
- toName: (NSString *) _name
+ fromComponent: (id) theComponent
+ container: (id) theContainer
+ toName: (NSString *) _name
baseVersion: (unsigned int *) _baseVersion
{
EOAdaptorChannel *storeChannel, *quickChannel;
NSMutableDictionary *quickRow, *contentRow;
NSDictionary *currentRow;
- GCSFieldExtractor *extractor;
NSNumber *storedVersion;
BOOL isNewRecord, hasInsertDelegate, hasUpdateDelegate;
NSCalendarDate *nowDate;
@@ -944,8 +944,7 @@ andAttribute: (EOAttribute *)_attribute
|| *_baseVersion == [storedVersion unsignedIntValue])
{
/* extract quick info */
- extractor = [folderInfo quickExtractor];
- quickRow = [extractor extractQuickFieldsFromContent:_content];
+ quickRow = [theComponent performSelector: @selector(quickRecordForContainer:) withObject: theContainer];
if (quickRow)
{
[quickRow setObject:_name forKey:@"c_name"];
@@ -1080,8 +1079,8 @@ andAttribute: (EOAttribute *)_attribute
__PRETTY_FUNCTION__];
}
else
- error = [self errorExtractorReturnedNoQuickRow:extractor
- forContent:_content];
+ [self errorWithFormat:@"%s: could not extract quick row information",
+ __PRETTY_FUNCTION__];
}
else /* version mismatch (concurrent update) */
error = [self errorVersionMismatchBetweenStoredVersion:
@@ -1101,13 +1100,6 @@ andAttribute: (EOAttribute *)_attribute
return error;
}
-
-- (NSException *)writeContent:(NSString *)_content toName:(NSString *)_name {
- /* this method does not check for concurrent writes */
- unsigned int v = 0;
- return [self writeContent:_content toName:_name baseVersion:&v];
-}
-
- (NSException *)deleteContentWithName:(NSString *)_name {
EOAdaptorChannel *storeChannel, *quickChannel;
EOAdaptorContext *adaptorCtx;
diff --git a/SOPE/GDLContentStore/GCSFolderManager.m b/SOPE/GDLContentStore/GCSFolderManager.m
index f333c9951..91c59c268 100644
--- a/SOPE/GDLContentStore/GCSFolderManager.m
+++ b/SOPE/GDLContentStore/GCSFolderManager.m
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2006-2011 Inverse inc.
+ Copyright (C) 2006-2014 Inverse inc.
Copyright (C) 2004-2007 SKYRIX Software AG
This file is part of SOGo.
diff --git a/SOPE/GDLContentStore/GCSFolderType.h b/SOPE/GDLContentStore/GCSFolderType.h
index 8a2e843ce..5784780bd 100644
--- a/SOPE/GDLContentStore/GCSFolderType.h
+++ b/SOPE/GDLContentStore/GCSFolderType.h
@@ -41,7 +41,7 @@
@class NSString, NSArray, NSDictionary;
@class EOQualifier;
@class NGResourceLocator;
-@class GCSFolder, GCSFieldExtractor;
+@class GCSFolder;
@interface GCSFolderType : NSObject
{
@@ -50,7 +50,6 @@
NSArray *fields, *quickFields; // GCSFieldInfo objects
EOQualifier *folderQualifier; // to further limit the table set
NSString *extractorClassName;
- GCSFieldExtractor *extractor;
}
+ (id)folderTypeWithName:(NSString *)_type;
@@ -67,10 +66,6 @@
- (NSString *)sqlQuickCreateWithTableName:(NSString *)_tabName;
-/* quick support */
-
-- (GCSFieldExtractor *)quickExtractor;
-
/* locator used to find .ocs files */
+ (NGResourceLocator *)resourceLocator;
diff --git a/SOPE/GDLContentStore/GCSFolderType.m b/SOPE/GDLContentStore/GCSFolderType.m
index da051c7a3..bb99051e6 100644
--- a/SOPE/GDLContentStore/GCSFolderType.m
+++ b/SOPE/GDLContentStore/GCSFolderType.m
@@ -1,20 +1,20 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
- This file is part of OpenGroupware.org.
+ This file is part of SOGo.
- OGo is free software; you can redistribute it and/or modify it under
+ SOGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
- OGo is distributed in the hope that it will be useful, but WITHOUT ANY
+ SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with OGo; see the file COPYING. If not, write to the
+ License along with SOGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
@@ -35,7 +35,6 @@
#import "GCSFolderType.h"
#import "GCSFolder.h"
#import "GCSFieldInfo.h"
-#import "GCSFieldExtractor.h"
@implementation GCSFolderType
@@ -116,7 +115,6 @@
- (void) dealloc
{
- [extractor release];
[extractorClassName release];
[blobTablePattern release];
[quickTablePattern release];
@@ -173,36 +171,6 @@
return sql;
}
-/* quick support */
-
-- (GCSFieldExtractor *) quickExtractor
-{
- Class clazz;
- GCSFieldExtractor *quickExtractor;
-
- if (!extractor)
- {
- clazz = (extractorClassName
- ? NSClassFromString (extractorClassName)
- : [GCSFieldExtractor class]);
- if (clazz)
- {
- extractor = [clazz new];
- if (!extractor)
- [self logWithFormat:@"ERROR: could not create field extractor of class %@",
- clazz];
- }
- else
- [self logWithFormat:@"ERROR: did not find field extractor class (%@)", extractorClassName];
- }
- if ([extractor isNotNull])
- quickExtractor = extractor;
- else
- quickExtractor = nil;
-
- return quickExtractor;
-}
-
- (NSArray *) quickFields
{
return quickFields;
diff --git a/SOPE/GDLContentStore/GNUmakefile b/SOPE/GDLContentStore/GNUmakefile
index e0e50cab2..84f24d0c0 100644
--- a/SOPE/GDLContentStore/GNUmakefile
+++ b/SOPE/GDLContentStore/GNUmakefile
@@ -31,7 +31,6 @@ libGDLContentStore_HEADER_FILES += \
GCSFolderManager.h \
GCSFolderType.h \
GCSChannelManager.h \
- GCSFieldExtractor.h \
GCSSessionsFolder.h \
GCSSpecialQueries.h \
GCSStringFormatter.h \
@@ -48,7 +47,6 @@ libGDLContentStore_OBJC_FILES += \
GCSFolderManager.m \
GCSFolderType.m \
GCSChannelManager.m \
- GCSFieldExtractor.m \
GCSSessionsFolder.m \
GCSSpecialQueries.m \
GCSStringFormatter.m \
@@ -60,6 +58,14 @@ GDLContentStore_HEADER_FILES = $(libGDLContentStore_HEADER_FILES)
GDLContentStore_OBJC_FILES = $(libGDLContentStore_OBJC_FILES)
GDLContentStore_SUBPROJECTS = $(libGDLContentStore_SUBPROJECTS)
+# Type models
+TYPEMODELS_DIR = $(SOGO_TYPEMODELS)
+
+libGDLContentStore_TYPEMODELS += \
+ appointment.ocs \
+ contact.ocs \
+ appointment-oracle.ocs \
+ contact-oracle.ocs
# building
diff --git a/OGoContentStore/GNUmakefile.postamble b/SOPE/GDLContentStore/GNUmakefile.postamble
similarity index 55%
rename from OGoContentStore/GNUmakefile.postamble
rename to SOPE/GDLContentStore/GNUmakefile.postamble
index 834af222e..2de398a10 100644
--- a/OGoContentStore/GNUmakefile.postamble
+++ b/SOPE/GDLContentStore/GNUmakefile.postamble
@@ -3,10 +3,10 @@
$(TYPEMODELS_DIR) :
$(MKDIRS) $(TYPEMODELS_DIR)
-ocs-typemodels : $(TYPEMODELS_DIR) $(libOGoContentStore_TYPEMODELS)
- @(if [ "$(libOGoContentStore_TYPEMODELS)" != "" ]; then \
+ocs-typemodels : $(TYPEMODELS_DIR) $(libGDLContentStore_TYPEMODELS)
+ @(if [ "$(libGDLContentStore_TYPEMODELS)" != "" ]; then \
echo "Copying type models into install path ..."; \
- for ff in $(libOGoContentStore_TYPEMODELS); do \
+ for ff in $(libGDLContentStore_TYPEMODELS); do \
cp $$ff $(TYPEMODELS_DIR)/$$ff; \
done; \
fi)
diff --git a/OGoContentStore/appointment-oracle.ocs b/SOPE/GDLContentStore/appointment-oracle.ocs
similarity index 100%
rename from OGoContentStore/appointment-oracle.ocs
rename to SOPE/GDLContentStore/appointment-oracle.ocs
diff --git a/OGoContentStore/appointment.ocs b/SOPE/GDLContentStore/appointment.ocs
similarity index 100%
rename from OGoContentStore/appointment.ocs
rename to SOPE/GDLContentStore/appointment.ocs
diff --git a/OGoContentStore/contact-oracle.ocs b/SOPE/GDLContentStore/contact-oracle.ocs
similarity index 100%
rename from OGoContentStore/contact-oracle.ocs
rename to SOPE/GDLContentStore/contact-oracle.ocs
diff --git a/OGoContentStore/contact.ocs b/SOPE/GDLContentStore/contact.ocs
similarity index 100%
rename from OGoContentStore/contact.ocs
rename to SOPE/GDLContentStore/contact.ocs
diff --git a/SoObjects/Appointments/Catalan.lproj/Localizable.strings b/SoObjects/Appointments/Catalan.lproj/Localizable.strings
index 8d89ffe89..33861d079 100644
--- a/SoObjects/Appointments/Catalan.lproj/Localizable.strings
+++ b/SoObjects/Appointments/Catalan.lproj/Localizable.strings
@@ -1,3 +1,4 @@
+"Inviting the following persons is prohibited:" = "Està prohibit Convidar a les següents persones:";
"Personal Calendar" = "Calendari personal";
vevent_class0 = "(Esdeveniment públic)";
vevent_class1 = "(Esdeveniment privat)";
diff --git a/SoObjects/Appointments/Czech.lproj/Localizable.strings b/SoObjects/Appointments/Czech.lproj/Localizable.strings
index 33667b7f7..fde0f1775 100644
--- a/SoObjects/Appointments/Czech.lproj/Localizable.strings
+++ b/SoObjects/Appointments/Czech.lproj/Localizable.strings
@@ -1,3 +1,4 @@
+"Inviting the following persons is prohibited:" = "Pozvání následujících osob je zakázáno:";
"Personal Calendar" = "Osobní kalendář";
vevent_class0 = "(Veřejná událost)";
vevent_class1 = "(Soukromá událost)";
diff --git a/SoObjects/Appointments/Dutch.lproj/Localizable.strings b/SoObjects/Appointments/Dutch.lproj/Localizable.strings
index 857875a0e..f554e976e 100644
--- a/SoObjects/Appointments/Dutch.lproj/Localizable.strings
+++ b/SoObjects/Appointments/Dutch.lproj/Localizable.strings
@@ -1,3 +1,4 @@
+"Inviting the following persons is prohibited:" = "De volgende personen uitnodigen is niet toegestaan:";
"Personal Calendar" = "Persoonlijke agenda";
vevent_class0 = "(Publieke afspraak)";
vevent_class1 = "(Privé-afspraak)";
diff --git a/SoObjects/Appointments/English.lproj/Localizable.strings b/SoObjects/Appointments/English.lproj/Localizable.strings
index ba3b942f1..45a038dfa 100644
--- a/SoObjects/Appointments/English.lproj/Localizable.strings
+++ b/SoObjects/Appointments/English.lproj/Localizable.strings
@@ -1,3 +1,4 @@
+"Inviting the following persons is prohibited:" = "Inviting the following persons is prohibited:";
"Personal Calendar" = "Personal Calendar";
vevent_class0 = "(Public event)";
vevent_class1 = "(Private event)";
diff --git a/SoObjects/Appointments/Finnish.lproj/Localizable.strings b/SoObjects/Appointments/Finnish.lproj/Localizable.strings
index f184ddab3..2574c7110 100644
--- a/SoObjects/Appointments/Finnish.lproj/Localizable.strings
+++ b/SoObjects/Appointments/Finnish.lproj/Localizable.strings
@@ -1,3 +1,4 @@
+"Inviting the following persons is prohibited:" = "Seuraavien henkilöiden kutsuminen on estetty:";
"Personal Calendar" = "Henkilökohtainen kalenteri";
vevent_class0 = "(Julkinen tapahtuma)";
vevent_class1 = "(Yksityinen tapahtuma)";
diff --git a/SoObjects/Appointments/French.lproj/Localizable.strings b/SoObjects/Appointments/French.lproj/Localizable.strings
index 7b39d0cf1..690738b77 100644
--- a/SoObjects/Appointments/French.lproj/Localizable.strings
+++ b/SoObjects/Appointments/French.lproj/Localizable.strings
@@ -1,3 +1,4 @@
+"Inviting the following persons is prohibited:" = "L'invitation des personnes suivantes est interdite :";
"Personal Calendar" = "Agenda personnel";
vevent_class0 = "(Événement public)";
vevent_class1 = "(Événement privé)";
diff --git a/SoObjects/Appointments/German.lproj/Localizable.strings b/SoObjects/Appointments/German.lproj/Localizable.strings
index 4cd49d8c5..a9e975288 100644
--- a/SoObjects/Appointments/German.lproj/Localizable.strings
+++ b/SoObjects/Appointments/German.lproj/Localizable.strings
@@ -1,3 +1,4 @@
+"Inviting the following persons is prohibited:" = "Das Einladen von folgenden Personen ist verboten:";
"Personal Calendar" = "Persönlicher Kalender";
vevent_class0 = "(Öffentlicher Termin)";
vevent_class1 = "(Privater Termin)";
diff --git a/SoObjects/Appointments/Hungarian.lproj/Localizable.strings b/SoObjects/Appointments/Hungarian.lproj/Localizable.strings
index 0a53c00ca..ab163b121 100644
--- a/SoObjects/Appointments/Hungarian.lproj/Localizable.strings
+++ b/SoObjects/Appointments/Hungarian.lproj/Localizable.strings
@@ -1,3 +1,4 @@
+"Inviting the following persons is prohibited:" = "A következő személyek meghívása tilos:";
"Personal Calendar" = "Személyes naptár";
vevent_class0 = "(Nyilvános esemény)";
vevent_class1 = "(Magán esemény)";
diff --git a/SoObjects/Appointments/NorwegianBokmal.lproj/Localizable.strings b/SoObjects/Appointments/NorwegianBokmal.lproj/Localizable.strings
index 3a5b2227e..cbabb272b 100644
--- a/SoObjects/Appointments/NorwegianBokmal.lproj/Localizable.strings
+++ b/SoObjects/Appointments/NorwegianBokmal.lproj/Localizable.strings
@@ -1,3 +1,4 @@
+"Inviting the following persons is prohibited:" = "Invitering av følgende personer er forbudt.";
"Personal Calendar" = "Personlig kalender";
vevent_class0 = "(Offentlig hendelse)";
vevent_class1 = "(Privat hendelse)";
diff --git a/SoObjects/Appointments/Polish.lproj/Localizable.strings b/SoObjects/Appointments/Polish.lproj/Localizable.strings
index 409dd5916..092525208 100644
--- a/SoObjects/Appointments/Polish.lproj/Localizable.strings
+++ b/SoObjects/Appointments/Polish.lproj/Localizable.strings
@@ -1,3 +1,4 @@
+"Inviting the following persons is prohibited:" = "Zapraszanie następujących osób jest zakazane:";
"Personal Calendar" = "Kalendarz osobisty";
vevent_class0 = "(Wydarzenie publiczne)";
vevent_class1 = "(Wydarzenie prywatne)";
diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m
index 96a14d536..6845a3d23 100644
--- a/SoObjects/Appointments/SOGoAppointmentFolder.m
+++ b/SoObjects/Appointments/SOGoAppointmentFolder.m
@@ -983,7 +983,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
{
if ([dateRange containsDate: [component startDate]])
{
- newRecord = [self fixupRecord: [component quickRecord]];
+ newRecord = [self fixupRecord: [component quickRecordForContainer: self]];
[ma replaceObjectAtIndex: recordIndex withObject: newRecord];
}
else
@@ -999,7 +999,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
{
// The recurrence id of the exception is outside the date range;
// simply add the exception to the records array
- newRecord = [self fixupRecord: [component quickRecord]];
+ newRecord = [self fixupRecord: [component quickRecordForContainer: self]];
newRecordRange = [NGCalendarDateRange
calendarDateRangeWithStartDate: [newRecord objectForKey: @"startDate"]
endDate: [newRecord objectForKey: @"endDate"]];
@@ -3034,7 +3034,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
[content appendFormat: @"%@\n", [timezone versitString]];
[content appendFormat: @"%@\nEND:VCALENDAR", [event versitString]];
- return ([object saveContentString: content] == nil) ? uid : nil;
+ return ([object saveCalendar: [iCalCalendar parseSingleFromSource: content]] == nil) ? uid : nil;
}
/**
@@ -3047,7 +3047,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
NSArray *vtimezones;
NSMutableArray *components;
NSMutableDictionary *timezones, *uids;
- NSString *tzId, *uid, *originalUid, *content;
+ NSString *tzId, *uid, *originalUid;
iCalEntityObject *element;
iCalDateTime *startDate;
iCalTimeZone *timezone;
@@ -3175,8 +3175,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
[masterCalendar addToEvents: event];
if (timezone)
[masterCalendar addTimeZone: timezone];
- content = [masterCalendar versitString];
- [master saveContentString: content];
+ [master saveCalendar: masterCalendar];
continue;
}
}
diff --git a/SoObjects/Appointments/SOGoAppointmentFolders.m b/SoObjects/Appointments/SOGoAppointmentFolders.m
index 99b73a636..f5ae1b23c 100644
--- a/SoObjects/Appointments/SOGoAppointmentFolders.m
+++ b/SoObjects/Appointments/SOGoAppointmentFolders.m
@@ -750,7 +750,8 @@ static SoSecurityManager *sm = nil;
for (userCount = 0; userCount < userMax; userCount++)
[currentFolder
subscribeUserOrGroup: [proxySubscribers objectAtIndex: userCount]
- reallyDo: YES];
+ reallyDo: YES
+ response: nil];
}
}
}
@@ -775,7 +776,8 @@ static SoSecurityManager *sm = nil;
for (userCount = 0; userCount < userMax; userCount++)
[currentFolder
subscribeUserOrGroup: [proxySubscribers objectAtIndex: userCount]
- reallyDo: NO];
+ reallyDo: NO
+ response: nil];
}
}
}
diff --git a/SoObjects/Appointments/SOGoAppointmentObject.h b/SoObjects/Appointments/SOGoAppointmentObject.h
index 6c0aebd01..6abfb6c0d 100644
--- a/SoObjects/Appointments/SOGoAppointmentObject.h
+++ b/SoObjects/Appointments/SOGoAppointmentObject.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2007-2011 Inverse inc.
+ Copyright (C) 2007-2014 Inverse inc.
This file is part of SOGo
diff --git a/SoObjects/Appointments/SOGoAppointmentObject.m b/SoObjects/Appointments/SOGoAppointmentObject.m
index 0e397928f..986978878 100644
--- a/SoObjects/Appointments/SOGoAppointmentObject.m
+++ b/SoObjects/Appointments/SOGoAppointmentObject.m
@@ -25,6 +25,7 @@
#import
#import
#import
+#import
#import
#import
@@ -52,6 +53,7 @@
#import
#import
#import
+#import
#import
#import
#import
@@ -126,13 +128,12 @@
}
- (iCalRepeatableEntityObject *) lookupOccurrence: (NSString *) recID
-
{
return [[self calendar: NO secure: NO] eventWithRecurrenceID: recID];
}
- (SOGoAppointmentObject *) _lookupEvent: (NSString *) eventUID
- forUID: (NSString *) uid
+ forUID: (NSString *) uid
{
SOGoAppointmentFolder *folder;
SOGoAppointmentObject *object;
@@ -146,30 +147,30 @@
while ( object == nil && (folder = [e nextObject]) )
{
object = [folder lookupName: nameInContainer
- inContext: context
- acquire: NO];
+ inContext: context
+ acquire: NO];
if ([object isKindOfClass: [NSException class]] || [object isNew])
- {
- possibleName = [folder resourceNameForEventUID: eventUID];
- if (possibleName)
- {
- object = [folder lookupName: possibleName
- inContext: context acquire: NO];
- if ([object isKindOfClass: [NSException class]] || [object isNew])
- object = nil;
- }
- else
- object = nil;
- }
+ {
+ possibleName = [folder resourceNameForEventUID: eventUID];
+ if (possibleName)
+ {
+ object = [folder lookupName: possibleName
+ inContext: context acquire: NO];
+ if ([object isKindOfClass: [NSException class]] || [object isNew])
+ object = nil;
+ }
+ else
+ object = nil;
+ }
}
-
+
if (!object)
{
// Create the event in the user's personal calendar.
folder = [[SOGoUser userWithLogin: uid]
personalCalendarFolderInContext: context];
object = [SOGoAppointmentObject objectWithName: nameInContainer
- inContainer: folder];
+ inContainer: folder];
[object setIsNew: YES];
}
@@ -180,60 +181,60 @@
//
//
- (void) _addOrUpdateEvent: (iCalEvent *) theEvent
- forUID: (NSString *) theUID
- owner: (NSString *) theOwner
+ forUID: (NSString *) theUID
+ owner: (NSString *) theOwner
{
if (![theUID isEqualToString: theOwner])
{
SOGoAppointmentObject *attendeeObject;
- NSString *iCalString;
-
- iCalString = nil;
+ iCalCalendar *iCalendarToSave;
+
+ iCalendarToSave = nil;
attendeeObject = [self _lookupEvent: [theEvent uid] forUID: theUID];
// We must add an occurence to a non-existing event. We have
// to handle this with care, as in the postCalDAVEventRequestTo:from:
if ([attendeeObject isNew] && [theEvent recurrenceId])
- {
- iCalEvent *ownerEvent;
- iCalPerson *person;
- SOGoUser *user;
-
- // We check if the attendee that was added to a single occurence is
- // present in the master component. If not, we add it with a participation
- // status set to "DECLINED".
- ownerEvent = [[[theEvent parent] events] objectAtIndex: 0];
- user = [SOGoUser userWithLogin: theUID];
- if (![ownerEvent userAsAttendee: user])
- {
- // Update the master event in the owner's calendar with the
- // status of the new attendee set as "DECLINED".
+ {
+ iCalEvent *ownerEvent;
+ iCalPerson *person;
+ SOGoUser *user;
+
+ // We check if the attendee that was added to a single occurence is
+ // present in the master component. If not, we add it with a participation
+ // status set to "DECLINED".
+ ownerEvent = [[[theEvent parent] events] objectAtIndex: 0];
+ user = [SOGoUser userWithLogin: theUID];
+ if (![ownerEvent userAsAttendee: user])
+ {
+ // Update the master event in the owner's calendar with the
+ // status of the new attendee set as "DECLINED".
person = [iCalPerson elementWithTag: @"attendee"];
[person setCn: [user cn]];
[person setEmail: [[user allEmails] objectAtIndex: 0]];
[person setParticipationStatus: iCalPersonPartStatDeclined];
[person setRsvp: @"TRUE"];
[person setRole: @"REQ-PARTICIPANT"];
- [ownerEvent addToAttendees: person];
-
- iCalString = [[ownerEvent parent] versitString];
- }
- }
+ [ownerEvent addToAttendees: person];
+
+ iCalendarToSave = [ownerEvent parent];
+ }
+ }
else
- {
- // TODO : if [theEvent recurrenceId], only update this occurrence
- // in attendee's calendar
-
- // TODO : when updating the master event, handle exception dates
- // in attendee's calendar (add exception dates and remove matching
- // occurrences) -- see _updateRecurrenceIDsWithEvent:
-
- iCalString = [[theEvent parent] versitString];
- }
+ {
+ // TODO : if [theEvent recurrenceId], only update this occurrence
+ // in attendee's calendar
+
+ // TODO : when updating the master event, handle exception dates
+ // in attendee's calendar (add exception dates and remove matching
+ // occurrences) -- see _updateRecurrenceIDsWithEvent:
+
+ iCalendarToSave = [theEvent parent];
+ }
// Save the event in the attendee's calendar
- if (iCalString)
- [attendeeObject saveContentString: iCalString];
+ if (iCalendarToSave)
+ [attendeeObject saveCalendar: iCalendarToSave];
}
}
@@ -242,7 +243,7 @@
//
- (void) _removeEventFromUID: (NSString *) theUID
owner: (NSString *) theOwner
- withRecurrenceId: (NSCalendarDate *) recurrenceId
+ withRecurrenceId: (NSCalendarDate *) recurrenceId
{
if (![theUID isEqualToString: theOwner])
{
@@ -252,53 +253,50 @@
iCalRepeatableEntityObject *event;
iCalCalendar *calendar;
NSCalendarDate *currentId;
- NSString *calendarContent;
NSArray *occurences;
int max, count;
// Invitations are always written to the personal folder; it's not necessay
// to look into all folders of the user
folder = [[SOGoUser userWithLogin: theUID]
- personalCalendarFolderInContext: context];
+ personalCalendarFolderInContext: context];
object = [folder lookupName: nameInContainer
inContext: context acquire: NO];
if (![object isKindOfClass: [NSException class]])
- {
- if (recurrenceId == nil)
- [object delete];
- else
- {
- calendar = [object calendar: NO secure: NO];
-
- // If recurrenceId is defined, remove the occurence from
- // the repeating event.
- occurences = [calendar events];
- max = [occurences count];
- count = 1;
- while (count < max)
- {
- currentOccurence = [occurences objectAtIndex: count];
- currentId = [currentOccurence recurrenceId];
- if ([currentId compare: recurrenceId] == NSOrderedSame)
- {
- [[calendar children] removeObject: currentOccurence];
- break;
- }
- count++;
- }
-
- // Add an date exception.
- event = (iCalRepeatableEntityObject*)[calendar firstChildWithTag: [object componentTag]];
- [event addToExceptionDates: recurrenceId];
-
- [event increaseSequence];
-
- // We generate the updated iCalendar file and we save it
- // in the database.
- calendarContent = [calendar versitString];
- [object saveContentString: calendarContent];
- }
- }
+ {
+ if (recurrenceId == nil)
+ [object delete];
+ else
+ {
+ calendar = [object calendar: NO secure: NO];
+
+ // If recurrenceId is defined, remove the occurence from
+ // the repeating event.
+ occurences = [calendar events];
+ max = [occurences count];
+ count = 1;
+ while (count < max)
+ {
+ currentOccurence = [occurences objectAtIndex: count];
+ currentId = [currentOccurence recurrenceId];
+ if ([currentId compare: recurrenceId] == NSOrderedSame)
+ {
+ [[calendar children] removeObject: currentOccurence];
+ break;
+ }
+ count++;
+ }
+
+ // Add an date exception.
+ event = (iCalRepeatableEntityObject*)[calendar firstChildWithTag: [object componentTag]];
+ [event addToExceptionDates: recurrenceId];
+
+ [event increaseSequence];
+
+ // We save the updated iCalendar in the database.
+ [object saveCalendar: calendar];
+ }
+ }
}
}
@@ -317,8 +315,8 @@
{
currentUID = [currentAttendee uid];
if (currentUID)
- [self _removeEventFromUID: currentUID
- owner: owner
+ [self _removeEventFromUID: currentUID
+ owner: owner
withRecurrenceId: recurrenceId];
}
}
@@ -343,9 +341,7 @@
[event removeFromAttendees: delegate];
}
else
- [self errorWithFormat:
- @"broken chain: delegate with email '%@' was not found",
- mailTo];
+ [self errorWithFormat:@"broken chain: delegate with email '%@' was not found", mailTo];
}
}
@@ -400,9 +396,9 @@
{
currentUID = [currentAttendee uid];
if (currentUID)
- [self _addOrUpdateEvent: newEvent
- forUID: currentUID
- owner: owner];
+ [self _addOrUpdateEvent: newEvent
+ forUID: currentUID
+ owner: owner];
}
[self sendEMailUsingTemplateNamed: @"Update"
@@ -412,6 +408,70 @@
withType: @"calendar:invitation-update"];
}
+// This method scans the list of attendees.
+- (NSException *) _handleAttendeeAvailability: (NSArray *) theAttendees
+ forEvent: (iCalEvent *) theEvent
+{
+ iCalPerson *currentAttendee;
+ SOGoUser *user;
+ SOGoUserSettings *us;
+ NSMutableArray *unavailableAttendees;
+ NSEnumerator *enumerator;
+ NSString *currentUID, *ownerUID, *whiteListString;
+ NSMutableString *reason;
+ NSDictionary *values;
+ NSMutableDictionary *value, *moduleSettings, *whiteList;
+ int i, count;
+ i = count = 0;
+
+ // Build list of the attendees uids without ressources
+ unavailableAttendees = [[NSMutableArray alloc] init];
+ enumerator = [theAttendees objectEnumerator];
+ ownerUID = [[[self context] activeUser] login];
+
+ while ((currentAttendee = [enumerator nextObject]))
+ {
+ currentUID = [currentAttendee uid];
+ if (currentUID)
+ {
+ user = [SOGoUser userWithLogin: currentUID];
+ us = [user userSettings];
+ moduleSettings = [us objectForKey:@"Calendar"];
+ // Check if the user prevented his account from beeing invited to events
+ if (![user isResource] && [[moduleSettings objectForKey:@"PreventInvitations"] boolValue])
+ {
+ // Check if the user have a whiteList
+ whiteListString = [moduleSettings objectForKey:@"PreventInvitationsWhitelist"];
+ whiteList = [whiteListString objectFromJSONString];
+ // If the filter have a hit, do not add the currentUID to the unavailableAttendees array
+ if (![whiteList objectForKey:ownerUID])
+ {
+ values = [NSDictionary dictionaryWithObject:[user cn] forKey:@"Cn"];
+ [unavailableAttendees addObject:values];
+ }
+ }
+ }
+ }
+
+ count = [unavailableAttendees count];
+ if (count > 0)
+ {
+ reason = [NSMutableString stringWithString:[self labelForKey: @"Inviting the following persons is prohibited:"]];
+ // Add all the unavailable users in the warning message
+ for (i = 0; i < count; i++)
+ {
+ value = [unavailableAttendees objectAtIndex:i];
+ [reason appendString:[value keysWithFormat: @"\n %{Cn}"]];
+ if (i < count-2)
+ [reason appendString:@", "];
+ }
+ [unavailableAttendees release];
+ return [NSException exceptionWithHTTPStatus:409 reason: reason];
+ }
+ [unavailableAttendees release];
+ return nil;
+}
+
//
// This methods scans the list of attendees. If they are
// considered as resource, it checks for conflicting
@@ -434,8 +494,8 @@
NSMutableArray *attendees;
NSEnumerator *enumerator;
NSString *currentUID;
- SOGoUser *user, *currentUser, *ownerUser;
-
+ SOGoUser *user, *currentUser;
+
// Build a list of the attendees uids
attendees = [NSMutableArray arrayWithCapacity: [theAttendees count]];
enumerator = [theAttendees objectEnumerator];
@@ -447,7 +507,7 @@
[attendees addObject: currentUID];
}
}
-
+
// If the active user is not the owner of the calendar, check possible conflict when
// the owner is a resource
currentUser = [context activeUser];
@@ -455,152 +515,152 @@
{
[attendees addObject: owner];
}
-
+
enumerator = [attendees objectEnumerator];
while ((currentUID = [enumerator nextObject]))
{
- user = [SOGoUser userWithLogin: currentUID];
-
- if ([user isResource])
- {
- SOGoAppointmentFolder *folder;
- NSCalendarDate *start, *end;
- NGCalendarDateRange *range;
- NSMutableArray *fbInfo;
- NSArray *allOccurences;
-
- BOOL must_delete;
- int i, j;
-
- // We get the start/end date for our conflict range. If the event to be added is recurring, we
- // check for at least a year to start with.
- start = [[theEvent startDate] dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: 1];
- end = [[theEvent endDate] dateByAddingYears: ([theEvent isRecurrent] ? 1 : 0) months: 0 days: 0 hours: 0 minutes: 0 seconds: -1];
-
- folder = [user personalCalendarFolderInContext: context];
-
- // Deny access to the resource if the ACLs don't allow the user
- if (![folder aclSQLListingFilter])
- {
- NSDictionary *values;
- NSString *reason;
-
- values = [NSDictionary dictionaryWithObjectsAndKeys:
- [user cn], @"Cn",
- [user systemEmail], @"SystemEmail"];
- reason = [values keysWithFormat: [self labelForKey: @"Cannot access resource: \"%{Cn} %{SystemEmail}\""]];
- return [NSException exceptionWithHTTPStatus:403 reason: reason];
- }
-
- fbInfo = [NSMutableArray arrayWithArray: [folder fetchFreeBusyInfosFrom: start
- to: end]];
-
- // We first remove any occurences in the freebusy that corresponds to the
- // current event. We do this to avoid raising a conflict if we move a 1 hour
- // meeting from 12:00-13:00 to 12:15-13:15. We would overlap on ourself otherwise.
- //
- // We must also check here for repetitive events that don't overlap our event.
- // We remove all events that don't overlap. The events here are already
- // decomposed.
- //
- if ([theEvent isRecurrent])
- allOccurences = [theEvent recurrenceRangesWithinCalendarDateRange: [NGCalendarDateRange calendarDateRangeWithStartDate: start
- endDate: end]
- firstInstanceCalendarDateRange: [NGCalendarDateRange calendarDateRangeWithStartDate: [theEvent startDate]
- endDate: [theEvent endDate]]];
- else
- allOccurences = nil;
-
- for (i = [fbInfo count]-1; i >= 0; i--)
- {
- range = [NGCalendarDateRange calendarDateRangeWithStartDate: [[fbInfo objectAtIndex: i] objectForKey: @"startDate"]
- endDate: [[fbInfo objectAtIndex: i] objectForKey: @"endDate"]];
-
- if ([[[fbInfo objectAtIndex: i] objectForKey: @"c_uid"] compare: [theEvent uid]] == NSOrderedSame)
- {
- [fbInfo removeObjectAtIndex: i];
- continue;
- }
-
- // No need to check if the event isn't recurrent here as it's handled correctly
- // when we compute the "end" date.
- if ([allOccurences count])
- {
- must_delete = YES;
-
- for (j = 0; j < [allOccurences count]; j++)
- {
- if ([range doesIntersectWithDateRange: [allOccurences objectAtIndex: j]])
- {
- must_delete = NO;
- break;
- }
- }
-
- if (must_delete)
- [fbInfo removeObjectAtIndex: i];
- }
- }
-
- // Find the attendee associated to the current UID
- for (i = 0; i < [theAttendees count]; i++)
+ user = [SOGoUser userWithLogin: currentUID];
+
+ if ([user isResource])
+ {
+ SOGoAppointmentFolder *folder;
+ NSCalendarDate *start, *end;
+ NGCalendarDateRange *range;
+ NSMutableArray *fbInfo;
+ NSArray *allOccurences;
+
+ BOOL must_delete;
+ int i, j;
+
+ // We get the start/end date for our conflict range. If the event to be added is recurring, we
+ // check for at least a year to start with.
+ start = [[theEvent startDate] dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: 1];
+ end = [[theEvent endDate] dateByAddingYears: ([theEvent isRecurrent] ? 1 : 0) months: 0 days: 0 hours: 0 minutes: 0 seconds: -1];
+
+ folder = [user personalCalendarFolderInContext: context];
+
+ // Deny access to the resource if the ACLs don't allow the user
+ if (![folder aclSQLListingFilter])
+ {
+ NSDictionary *values;
+ NSString *reason;
+
+ values = [NSDictionary dictionaryWithObjectsAndKeys:
+ [user cn], @"Cn",
+ [user systemEmail], @"SystemEmail"];
+ reason = [values keysWithFormat: [self labelForKey: @"Cannot access resource: \"%{Cn} %{SystemEmail}\""]];
+ return [NSException exceptionWithHTTPStatus:403 reason: reason];
+ }
+
+ fbInfo = [NSMutableArray arrayWithArray: [folder fetchFreeBusyInfosFrom: start
+ to: end]];
+
+ // We first remove any occurences in the freebusy that corresponds to the
+ // current event. We do this to avoid raising a conflict if we move a 1 hour
+ // meeting from 12:00-13:00 to 12:15-13:15. We would overlap on ourself otherwise.
+ //
+ // We must also check here for repetitive events that don't overlap our event.
+ // We remove all events that don't overlap. The events here are already
+ // decomposed.
+ //
+ if ([theEvent isRecurrent])
+ allOccurences = [theEvent recurrenceRangesWithinCalendarDateRange: [NGCalendarDateRange calendarDateRangeWithStartDate: start
+ endDate: end]
+ firstInstanceCalendarDateRange: [NGCalendarDateRange calendarDateRangeWithStartDate: [theEvent startDate]
+ endDate: [theEvent endDate]]];
+ else
+ allOccurences = nil;
+
+ for (i = [fbInfo count]-1; i >= 0; i--)
+ {
+ range = [NGCalendarDateRange calendarDateRangeWithStartDate: [[fbInfo objectAtIndex: i] objectForKey: @"startDate"]
+ endDate: [[fbInfo objectAtIndex: i] objectForKey: @"endDate"]];
+
+ if ([[[fbInfo objectAtIndex: i] objectForKey: @"c_uid"] compare: [theEvent uid]] == NSOrderedSame)
{
- currentAttendee = [theAttendees objectAtIndex: i];
- if ([[currentAttendee uid] isEqualToString: currentUID])
- break;
- else
- currentAttendee = nil;
+ [fbInfo removeObjectAtIndex: i];
+ continue;
}
-
- if ([fbInfo count])
+
+ // No need to check if the event isn't recurrent here as it's handled correctly
+ // when we compute the "end" date.
+ if ([allOccurences count])
{
- // If we always force the auto-accept if numberOfSimultaneousBookings == 0 (ie., no limit
- // is imposed) or if numberOfSimultaneousBookings is greater than the number of
- // overlapping events
- if ([user numberOfSimultaneousBookings] == 0 ||
- [user numberOfSimultaneousBookings] > [fbInfo count])
+ must_delete = YES;
+
+ for (j = 0; j < [allOccurences count]; j++)
{
- if (currentAttendee)
+ if ([range doesIntersectWithDateRange: [allOccurences objectAtIndex: j]])
{
- [[currentAttendee attributes] removeObjectForKey: @"RSVP"];
- [currentAttendee setParticipationStatus: iCalPersonPartStatAccepted];
+ must_delete = NO;
+ break;
}
}
- else
- {
- iCalCalendar *calendar;
- NSDictionary *values;
- NSString *reason;
- iCalEvent *event;
-
- calendar = [iCalCalendar parseSingleFromSource: [[fbInfo objectAtIndex: 0] objectForKey: @"c_content"]];
- event = [[calendar events] lastObject];
-
- values = [NSDictionary dictionaryWithObjectsAndKeys:
- [NSString stringWithFormat: @"%d", [user numberOfSimultaneousBookings]], @"NumberOfSimultaneousBookings",
- [user cn], @"Cn",
- [user systemEmail], @"SystemEmail",
- ([event summary] ? [event summary] : @""), @"EventTitle",
- [[fbInfo objectAtIndex: 0] objectForKey: @"startDate"], @"StartDate",
- nil];
-
- reason = [values keysWithFormat: [self labelForKey: @"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}."]];
-
- return [NSException exceptionWithHTTPStatus: 403
- reason: reason];
- }
- }
- else if (currentAttendee)
- {
- // No conflict, we auto-accept. We do this for resources automatically if no
- // double-booking is observed. If it's not the desired behavior, just don't
- // set the resource as one!
- [[currentAttendee attributes] removeObjectForKey: @"RSVP"];
- [currentAttendee setParticipationStatus: iCalPersonPartStatAccepted];
+
+ if (must_delete)
+ [fbInfo removeObjectAtIndex: i];
}
}
+
+ // Find the attendee associated to the current UID
+ for (i = 0; i < [theAttendees count]; i++)
+ {
+ currentAttendee = [theAttendees objectAtIndex: i];
+ if ([[currentAttendee uid] isEqualToString: currentUID])
+ break;
+ else
+ currentAttendee = nil;
+ }
+
+ if ([fbInfo count])
+ {
+ // If we always force the auto-accept if numberOfSimultaneousBookings == 0 (ie., no limit
+ // is imposed) or if numberOfSimultaneousBookings is greater than the number of
+ // overlapping events
+ if ([user numberOfSimultaneousBookings] == 0 ||
+ [user numberOfSimultaneousBookings] > [fbInfo count])
+ {
+ if (currentAttendee)
+ {
+ [[currentAttendee attributes] removeObjectForKey: @"RSVP"];
+ [currentAttendee setParticipationStatus: iCalPersonPartStatAccepted];
+ }
+ }
+ else
+ {
+ iCalCalendar *calendar;
+ NSDictionary *values;
+ NSString *reason;
+ iCalEvent *event;
+
+ calendar = [iCalCalendar parseSingleFromSource: [[fbInfo objectAtIndex: 0] objectForKey: @"c_content"]];
+ event = [[calendar events] lastObject];
+
+ values = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSString stringWithFormat: @"%d", [user numberOfSimultaneousBookings]], @"NumberOfSimultaneousBookings",
+ [user cn], @"Cn",
+ [user systemEmail], @"SystemEmail",
+ ([event summary] ? [event summary] : @""), @"EventTitle",
+ [[fbInfo objectAtIndex: 0] objectForKey: @"startDate"], @"StartDate",
+ nil];
+
+ reason = [values keysWithFormat: [self labelForKey: @"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}."]];
+
+ return [NSException exceptionWithHTTPStatus: 403
+ reason: reason];
+ }
+ }
+ else if (currentAttendee)
+ {
+ // No conflict, we auto-accept. We do this for resources automatically if no
+ // double-booking is observed. If it's not the desired behavior, just don't
+ // set the resource as one!
+ [[currentAttendee attributes] removeObjectForKey: @"RSVP"];
+ [currentAttendee setParticipationStatus: iCalPersonPartStatAccepted];
+ }
+ }
}
-
+
return nil;
}
@@ -608,27 +668,29 @@
//
//
- (NSException *) _handleAddedUsers: (NSArray *) attendees
- fromEvent: (iCalEvent *) newEvent
+ fromEvent: (iCalEvent *) newEvent
{
iCalPerson *currentAttendee;
NSEnumerator *enumerator;
NSString *currentUID;
NSException *e;
-
+
// We check for conflicts
if ((e = [self _handleResourcesConflicts: attendees forEvent: newEvent]))
return e;
-
+ if ((e = [self _handleAttendeeAvailability: attendees forEvent: newEvent]))
+ return e;
+
enumerator = [attendees objectEnumerator];
while ((currentAttendee = [enumerator nextObject]))
{
currentUID = [currentAttendee uid];
if (currentUID)
- [self _addOrUpdateEvent: newEvent
- forUID: currentUID
- owner: owner];
+ [self _addOrUpdateEvent: newEvent
+ forUID: currentUID
+ owner: owner];
}
-
+
return nil;
}
@@ -656,12 +718,11 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
{
e = [events objectAtIndex: i];
if ([e recurrenceId])
- for (j = 0; j < [theAttendees count]; j++)
- if (shouldAdd)
- [e addToAttendees: [theAttendees objectAtIndex: j]];
- else
- [e removeFromAttendees: [theAttendees objectAtIndex: j]];
-
+ for (j = 0; j < [theAttendees count]; j++)
+ if (shouldAdd)
+ [e addToAttendees: [theAttendees objectAtIndex: j]];
+ else
+ [e removeFromAttendees: [theAttendees objectAtIndex: j]];
}
}
@@ -709,8 +770,9 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
withType: @"calendar:cancellation"];
}
- if ((ex = [self _handleResourcesConflicts: [newEvent attendees]
- forEvent: newEvent]))
+ if ((ex = [self _handleResourcesConflicts: [newEvent attendees] forEvent: newEvent]))
+ return ex;
+ if ((ex = [self _handleAttendeeAvailability: [newEvent attendees] forEvent: newEvent]))
return ex;
addedAttendees = [changes insertedAttendees];
@@ -719,7 +781,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
// the attendees were added to the master event.
[self _addOrDeleteAttendees: addedAttendees
inRecurrenceExceptionsForEvent: newEvent
- add: YES];
+ add: YES];
if ([changes sequenceShouldBeIncreased])
{
@@ -735,29 +797,29 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
// If other attributes have changed, update the event
// in each attendee's calendar
if ([[changes updatedProperties] count])
- {
- NSEnumerator *enumerator;
- iCalPerson *currentAttendee;
- NSString *currentUID;
-
+ {
+ NSEnumerator *enumerator;
+ iCalPerson *currentAttendee;
+ NSString *currentUID;
+
updatedAttendees = [newEvent attendees];
- enumerator = [updatedAttendees objectEnumerator];
- while ((currentAttendee = [enumerator nextObject]))
- {
- currentUID = [currentAttendee uid];
- if (currentUID)
- [self _addOrUpdateEvent: newEvent
- forUID: currentUID
- owner: owner];
- }
- }
+ enumerator = [updatedAttendees objectEnumerator];
+ while ((currentAttendee = [enumerator nextObject]))
+ {
+ currentUID = [currentAttendee uid];
+ if (currentUID)
+ [self _addOrUpdateEvent: newEvent
+ forUID: currentUID
+ owner: owner];
+ }
+ }
}
if ([addedAttendees count])
{
// Send an invitation to new attendees
if ((ex = [self _handleAddedUsers: addedAttendees fromEvent: newEvent]))
- return ex;
+ return ex;
[self sendEMailUsingTemplateNamed: @"Invitation"
forObject: [newEvent itipEntryWithMethod: @"request"]
@@ -765,12 +827,12 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
toAttendees: addedAttendees
withType: @"calendar:invitation"];
}
-
- [self sendReceiptEmailForObject: newEvent
- addedAttendees: addedAttendees
- deletedAttendees: deletedAttendees
- updatedAttendees: updatedAttendees
- operation: EventUpdated];
+
+ [self sendReceiptEmailForObject: newEvent
+ addedAttendees: addedAttendees
+ deletedAttendees: deletedAttendees
+ updatedAttendees: updatedAttendees
+ operation: EventUpdated];
return nil;
}
@@ -783,7 +845,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
// +------------> _handleUpdatedEvent:fromOldEvent: ---> _addOrUpdateEvent:forUID:owner: <-----------+
// | | ^ |
// v v | |
-// _handleRemovedUsers:withRecurrenceId: _handleSequenceUpdateInEvent:ignoringAttendees:fromOldEvent: |
+// _handleRemovedUsers:withRecurrenceId: _handleSequenceUpdateInEvent:ignoringAttendees:fromOldEvent: |
// | |
// | [DELETEAction:] |
// | | {_handleAdded/Updated...}<--+ |
@@ -822,57 +884,56 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
{
// New event -- send invitation to all attendees
attendees = [newEvent attendeesWithoutUser: ownerUser];
-
+
// We catch conflicts and abort the save process immediately
// in case of one with resources
if ((ex = [self _handleAddedUsers: attendees fromEvent: newEvent]))
return ex;
-
+
if ([attendees count])
- {
- [self sendEMailUsingTemplateNamed: @"Invitation"
- forObject: [newEvent itipEntryWithMethod: @"request"]
- previousObject: nil
- toAttendees: attendees
+ {
+ [self sendEMailUsingTemplateNamed: @"Invitation"
+ forObject: [newEvent itipEntryWithMethod: @"request"]
+ previousObject: nil
+ toAttendees: attendees
withType: @"calendar:invitation"];
- }
-
+ }
+
[self sendReceiptEmailForObject: newEvent
- addedAttendees: attendees
- deletedAttendees: nil
- updatedAttendees: nil
- operation: EventCreated];
+ addedAttendees: attendees
+ deletedAttendees: nil
+ updatedAttendees: nil
+ operation: EventCreated];
}
- else
+ else
{
BOOL hasOrganizer;
-
+
// Event is modified -- sent update status to all attendees
// and modify their calendars.
recurrenceId = [newEvent recurrenceId];
if (recurrenceId == nil)
- oldEvent = [self component: NO secure: NO];
+ oldEvent = [self component: NO secure: NO];
else
- {
- // If recurrenceId is defined, find the specified occurence
- // within the repeating vEvent.
- recurrenceTime = [NSString stringWithFormat: @"%f", [recurrenceId timeIntervalSince1970]];
- oldEvent = (iCalEvent*)[self lookupOccurrence: recurrenceTime];
- if (oldEvent == nil)
- // If no occurence found, create one
- oldEvent = (iCalEvent *)[self newOccurenceWithID: recurrenceTime];
- }
-
+ {
+ // If recurrenceId is defined, find the specified occurence
+ // within the repeating vEvent.
+ recurrenceTime = [NSString stringWithFormat: @"%f", [recurrenceId timeIntervalSince1970]];
+ oldEvent = (iCalEvent*)[self lookupOccurrence: recurrenceTime];
+ if (oldEvent == nil) // If no occurence found, create one
+ oldEvent = (iCalEvent *)[self newOccurenceWithID: recurrenceTime];
+ }
+
oldMasterEvent = (iCalEvent *)[[oldEvent parent] firstChildWithTag: [self componentTag]];
hasOrganizer = [[[oldMasterEvent organizer] email] length];
-
+
if (!hasOrganizer || [oldMasterEvent userIsOrganizer: ownerUser])
- // The owner is the organizer of the event; handle the modifications. We aslo
- // catch conflicts just like when the events are created
- if ((ex = [self _handleUpdatedEvent: newEvent fromOldEvent: oldEvent]))
- return ex;
+ // The owner is the organizer of the event; handle the modifications. We aslo
+ // catch conflicts just like when the events are created
+ if ((ex = [self _handleUpdatedEvent: newEvent fromOldEvent: oldEvent]))
+ return ex;
}
-
+
[super saveComponent: newEvent];
[self flush];
@@ -894,17 +955,17 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
- (NSException *) _updateAttendee: (iCalPerson *) attendee
withDelegate: (iCalPerson *) delegate
ownerUser: (SOGoUser *) theOwnerUser
- forEventUID: (NSString *) eventUID
- withRecurrenceId: (NSCalendarDate *) recurrenceId
- withSequence: (NSNumber *) sequence
- forUID: (NSString *) uid
- shouldAddSentBy: (BOOL) b
+ forEventUID: (NSString *) eventUID
+ withRecurrenceId: (NSCalendarDate *) recurrenceId
+ withSequence: (NSNumber *) sequence
+ forUID: (NSString *) uid
+ shouldAddSentBy: (BOOL) b
{
SOGoAppointmentObject *eventObject;
iCalCalendar *calendar;
iCalEntityObject *event;
iCalPerson *otherAttendee, *otherDelegate;
- NSString *iCalString, *recurrenceTime, *delegateEmail;
+ NSString *recurrenceTime, *delegateEmail;
NSException *error;
BOOL addDelegate, removeDelegate;
@@ -914,30 +975,30 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
if (![eventObject isNew])
{
if (recurrenceId == nil)
- {
- // We must update main event and all its occurences (if any).
- calendar = [eventObject calendar: NO secure: NO];
- event = (iCalEntityObject*)[calendar firstChildWithTag: [self componentTag]];
- }
+ {
+ // We must update main event and all its occurences (if any).
+ calendar = [eventObject calendar: NO secure: NO];
+ event = (iCalEntityObject*)[calendar firstChildWithTag: [self componentTag]];
+ }
else
- {
- // If recurrenceId is defined, find the specified occurence
- // within the repeating vEvent.
- recurrenceTime = [NSString stringWithFormat: @"%f", [recurrenceId timeIntervalSince1970]];
- event = [eventObject lookupOccurrence: recurrenceTime];
-
- if (event == nil)
- // If no occurence found, create one
- event = [eventObject newOccurenceWithID: recurrenceTime];
- }
+ {
+ // If recurrenceId is defined, find the specified occurence
+ // within the repeating vEvent.
+ recurrenceTime = [NSString stringWithFormat: @"%f", [recurrenceId timeIntervalSince1970]];
+ event = [eventObject lookupOccurrence: recurrenceTime];
+
+ if (event == nil)
+ // If no occurence found, create one
+ event = [eventObject newOccurenceWithID: recurrenceTime];
+ }
if ([[event sequence] intValue] <= [sequence intValue])
- {
- SOGoUser *currentUser;
-
- currentUser = [context activeUser];
- otherAttendee = [event userAsAttendee: theOwnerUser];
-
+ {
+ SOGoUser *currentUser;
+
+ currentUser = [context activeUser];
+ otherAttendee = [event userAsAttendee: theOwnerUser];
+
delegateEmail = [otherAttendee delegatedTo];
if ([delegateEmail length])
delegateEmail = [delegateEmail rfc822Email];
@@ -945,7 +1006,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
otherDelegate = [event findAttendeeWithEmail: delegateEmail];
else
otherDelegate = NO;
-
+
/* we handle the addition/deletion of delegate users */
addDelegate = NO;
removeDelegate = NO;
@@ -960,68 +1021,65 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
}
}
else
- addDelegate = YES;
+ addDelegate = YES;
}
else
{
if (otherDelegate)
- removeDelegate = YES;
+ removeDelegate = YES;
}
-
+
if (removeDelegate)
- {
- while (otherDelegate)
- {
- [event removeFromAttendees: otherDelegate];
-
- // Verify if the delegate was already delegate
- delegateEmail = [otherDelegate delegatedTo];
- if ([delegateEmail length])
- delegateEmail = [delegateEmail rfc822Email];
-
- if ([delegateEmail length])
- otherDelegate = [event findAttendeeWithEmail: delegateEmail];
- else
- otherDelegate = NO;
- }
- }
+ {
+ while (otherDelegate)
+ {
+ [event removeFromAttendees: otherDelegate];
+
+ // Verify if the delegate was already delegate
+ delegateEmail = [otherDelegate delegatedTo];
+ if ([delegateEmail length])
+ delegateEmail = [delegateEmail rfc822Email];
+
+ if ([delegateEmail length])
+ otherDelegate = [event findAttendeeWithEmail: delegateEmail];
+ else
+ otherDelegate = NO;
+ }
+ }
if (addDelegate)
[event addToAttendees: delegate];
-
- [otherAttendee setPartStat: [attendee partStat]];
+
+ [otherAttendee setPartStat: [attendee partStat]];
[otherAttendee setDelegatedTo: [attendee delegatedTo]];
[otherAttendee setDelegatedFrom: [attendee delegatedFrom]];
-
+
// Remove the RSVP attribute, as an action from the attendee
// was actually performed, and this confuses iCal (bug #1850)
[[otherAttendee attributes] removeObjectForKey: @"RSVP"];
-
- // If one has accepted / declined an invitation on behalf of
- // the attendee, we add the user to the SENT-BY attribute.
- if (b && ![[currentUser login] isEqualToString: [theOwnerUser login]])
- {
- NSString *currentEmail, *quotedEmail;
- currentEmail = [[currentUser allEmails] objectAtIndex: 0];
- quotedEmail = [NSString stringWithFormat: @"\"MAILTO:%@\"",
- currentEmail];
- [otherAttendee setValue: 0 ofAttribute: @"SENT-BY"
+
+ // If one has accepted / declined an invitation on behalf of
+ // the attendee, we add the user to the SENT-BY attribute.
+ if (b && ![[currentUser login] isEqualToString: [theOwnerUser login]])
+ {
+ NSString *currentEmail, *quotedEmail;
+ currentEmail = [[currentUser allEmails] objectAtIndex: 0];
+ quotedEmail = [NSString stringWithFormat: @"\"MAILTO:%@\"", currentEmail];
+ [otherAttendee setValue: 0 ofAttribute: @"SENT-BY"
to: quotedEmail];
- }
- else
- {
- // We must REMOVE any SENT-BY here. This is important since if A accepted
- // the event for B and then, B changes by himself his participation status,
- // we don't want to keep the previous SENT-BY attribute there.
- [(NSMutableDictionary *)[otherAttendee attributes] removeObjectForKey: @"SENT-BY"];
- }
- }
+ }
+ else
+ {
+ // We must REMOVE any SENT-BY here. This is important since if A accepted
+ // the event for B and then, B changes by himself his participation status,
+ // we don't want to keep the previous SENT-BY attribute there.
+ [(NSMutableDictionary *)[otherAttendee attributes] removeObjectForKey: @"SENT-BY"];
+ }
+ }
- // We generate the updated iCalendar file and we save it
- // in the database.
- iCalString = [[event parent] versitString];
- error = [eventObject saveContentString: iCalString];
+ // We save the updated iCalendar in the database.
+ error = [eventObject saveCalendar: [event parent]];
}
-
+
return error;
}
@@ -1035,8 +1093,8 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
- (NSException *) _handleAttendee: (iCalPerson *) attendee
withDelegate: (iCalPerson *) delegate
ownerUser: (SOGoUser *) theOwnerUser
- statusChange: (NSString *) newStatus
- inEvent: (iCalEvent *) event
+ statusChange: (NSString *) newStatus
+ inEvent: (iCalEvent *) event
{
NSString *currentStatus, *organizerUID;
SOGoUser *ownerUser, *currentUser;
@@ -1067,29 +1125,28 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
if (delegate)
{
if (otherDelegate)
- {
- // There was already a delegate
- if (![delegate hasSameEmailAddress: otherDelegate])
- {
- // The delegate has changed
- removeDelegate = YES;
- addDelegate = YES;
- }
- }
+ {
+ // There was already a delegate
+ if (![delegate hasSameEmailAddress: otherDelegate])
+ {
+ // The delegate has changed
+ removeDelegate = YES;
+ addDelegate = YES;
+ }
+ }
else
- // There was no previous delegate
- addDelegate = YES;
+ // There was no previous delegate
+ addDelegate = YES;
}
else
{
if (otherDelegate)
- // The user has removed the delegate
- removeDelegate = YES;
+ // The user has removed the delegate
+ removeDelegate = YES;
}
if (addDelegate || removeDelegate
- || [currentStatus caseInsensitiveCompare: newStatus]
- != NSOrderedSame)
+ || [currentStatus caseInsensitiveCompare: newStatus] != NSOrderedSame)
{
NSMutableArray *delegates;
NSString *delegatedUID;
@@ -1101,106 +1158,105 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
// the attendee, we add the user to the SENT-BY attribute.
currentUser = [context activeUser];
if (![[currentUser login] isEqualToString: [theOwnerUser login]])
- {
+ {
NSString *currentEmail, *quotedEmail;
currentEmail = [[currentUser allEmails] objectAtIndex: 0];
- quotedEmail = [NSString stringWithFormat: @"\"MAILTO:%@\"",
- currentEmail];
+ quotedEmail = [NSString stringWithFormat: @"\"MAILTO:%@\"", currentEmail];
[attendee setValue: 0 ofAttribute: @"SENT-BY"
to: quotedEmail];
- }
+ }
else
- {
- // We must REMOVE any SENT-BY here. This is important since if A accepted
- // the event for B and then, B changes by himself his participation status,
- // we don't want to keep the previous SENT-BY attribute there.
- [(NSMutableDictionary *)[attendee attributes] removeObjectForKey: @"SENT-BY"];
- }
-
+ {
+ // We must REMOVE any SENT-BY here. This is important since if A accepted
+ // the event for B and then, B changes by himself his participation status,
+ // we don't want to keep the previous SENT-BY attribute there.
+ [(NSMutableDictionary *)[attendee attributes] removeObjectForKey: @"SENT-BY"];
+ }
+
[attendee setDelegatedTo: [delegate email]];
-
+
if (removeDelegate)
- {
- delegates = [NSMutableArray array];
-
- while (otherDelegate)
- {
- [delegates addObject: otherDelegate];
-
- delegatedUID = [otherDelegate uid];
- if (delegatedUID)
- // Delegate attendee is a local user; remove event from his calendar
- [self _removeEventFromUID: delegatedUID
- owner: [theOwnerUser login]
- withRecurrenceId: [event recurrenceId]];
-
- [event removeFromAttendees: otherDelegate];
-
- // Verify if the delegate was already delegated
- delegateEmail = [otherDelegate delegatedTo];
- if ([delegateEmail length])
- delegateEmail = [delegateEmail rfc822Email];
-
- if ([delegateEmail length])
- otherDelegate = [event findAttendeeWithEmail: delegateEmail];
- else
- otherDelegate = NO;
- }
-
- [self sendEMailUsingTemplateNamed: @"Deletion"
- forObject: [event itipEntryWithMethod: @"cancel"]
- previousObject: nil
- toAttendees: delegates
+ {
+ delegates = [NSMutableArray array];
+
+ while (otherDelegate)
+ {
+ [delegates addObject: otherDelegate];
+
+ delegatedUID = [otherDelegate uid];
+ if (delegatedUID)
+ // Delegate attendee is a local user; remove event from his calendar
+ [self _removeEventFromUID: delegatedUID
+ owner: [theOwnerUser login]
+ withRecurrenceId: [event recurrenceId]];
+
+ [event removeFromAttendees: otherDelegate];
+
+ // Verify if the delegate was already delegated
+ delegateEmail = [otherDelegate delegatedTo];
+ if ([delegateEmail length])
+ delegateEmail = [delegateEmail rfc822Email];
+
+ if ([delegateEmail length])
+ otherDelegate = [event findAttendeeWithEmail: delegateEmail];
+ else
+ otherDelegate = NO;
+ }
+
+ [self sendEMailUsingTemplateNamed: @"Deletion"
+ forObject: [event itipEntryWithMethod: @"cancel"]
+ previousObject: nil
+ toAttendees: delegates
withType: @"calendar:cancellation"];
- } // if (removeDelegate)
-
+ } // if (removeDelegate)
+
if (addDelegate)
- {
- delegatedUID = [delegate uid];
- delegates = [NSArray arrayWithObject: delegate];
- [event addToAttendees: delegate];
-
- if (delegatedUID)
- // Delegate attendee is a local user; add event to his calendar
- [self _addOrUpdateEvent: event
- forUID: delegatedUID
- owner: [theOwnerUser login]];
-
- [self sendEMailUsingTemplateNamed: @"Invitation"
- forObject: [event itipEntryWithMethod: @"request"]
- previousObject: nil
- toAttendees: delegates
+ {
+ delegatedUID = [delegate uid];
+ delegates = [NSArray arrayWithObject: delegate];
+ [event addToAttendees: delegate];
+
+ if (delegatedUID)
+ // Delegate attendee is a local user; add event to his calendar
+ [self _addOrUpdateEvent: event
+ forUID: delegatedUID
+ owner: [theOwnerUser login]];
+
+ [self sendEMailUsingTemplateNamed: @"Invitation"
+ forObject: [event itipEntryWithMethod: @"request"]
+ previousObject: nil
+ toAttendees: delegates
withType: @"calendar:invitation"];
- } // if (addDelegate)
+ } // if (addDelegate)
// If the current user isn't the organizer of the event
// that has just been updated, we update the event and
// send a notification
ownerUser = [SOGoUser userWithLogin: owner];
if (!(ex || [event userIsOrganizer: ownerUser]))
- {
- if ([event isStillRelevant])
- [self sendResponseToOrganizer: event
+ {
+ if ([event isStillRelevant])
+ [self sendResponseToOrganizer: event
from: ownerUser];
-
- organizerUID = [[event organizer] uid];
-
- // Event is an exception to a recurring event; retrieve organizer from master event
- if (!organizerUID)
- organizerUID = [[(iCalEntityObject*)[[event parent] firstChildWithTag: [self componentTag]] organizer] uid];
-
- if (organizerUID)
- // Update the attendee in organizer's calendar.
- ex = [self _updateAttendee: attendee
+
+ organizerUID = [[event organizer] uid];
+
+ // Event is an exception to a recurring event; retrieve organizer from master event
+ if (!organizerUID)
+ organizerUID = [[(iCalEntityObject*)[[event parent] firstChildWithTag: [self componentTag]] organizer] uid];
+
+ if (organizerUID)
+ // Update the attendee in organizer's calendar.
+ ex = [self _updateAttendee: attendee
withDelegate: delegate
ownerUser: theOwnerUser
forEventUID: [event uid]
withRecurrenceId: [event recurrenceId]
withSequence: [event sequence]
forUID: organizerUID
- shouldAddSentBy: YES];
- }
-
+ shouldAddSentBy: YES];
+ }
+
// We update the calendar of all attendees that are
// local to the system. This is useful in case user A accepts
// invitation from organizer B and users C, D, E who are also
@@ -1209,15 +1265,13 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
iCalPerson *att;
NSString *uid;
int i;
-
+
attendees = [event attendees];
for (i = 0; i < [attendees count]; i++)
- {
- att = [attendees objectAtIndex: i];
- uid = [att uid];
- if (uid
- && att != attendee
- && ![uid isEqualToString: delegatedUID])
+ {
+ att = [attendees objectAtIndex: i];
+ uid = [att uid];
+ if (uid && att != attendee && ![uid isEqualToString: delegatedUID])
[self _updateAttendee: attendee
withDelegate: delegate
ownerUser: theOwnerUser
@@ -1226,9 +1280,9 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
withSequence: [event sequence]
forUID: uid
shouldAddSentBy: YES];
- }
+ }
}
-
+
return ex;
}
@@ -1238,13 +1292,9 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
NSDictionary *code;
element = [NSMutableArray array];
- [element addObject: davElementWithContent (@"recipient", XMLNS_CALDAV,
- recipient)];
- [element addObject: davElementWithContent (@"request-status",
- XMLNS_CALDAV,
- @"2.0;Success")];
- code = davElementWithContent (@"response", XMLNS_CALDAV,
- element);
+ [element addObject: davElementWithContent (@"recipient", XMLNS_CALDAV, recipient)];
+ [element addObject: davElementWithContent (@"request-status", XMLNS_CALDAV, @"2.0;Success")];
+ code = davElementWithContent (@"response", XMLNS_CALDAV, element);
return code;
}
@@ -1254,7 +1304,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
// advertise for its support but we do everything within the calendar-auto-scheduling code
//
- (NSArray *) postCalDAVEventRequestTo: (NSArray *) recipients
- from: (NSString *) originator
+ from: (NSString *) originator
{
NSEnumerator *recipientsEnum;
NSMutableArray *elements;
@@ -1267,14 +1317,14 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
while ((recipient = [recipientsEnum nextObject]))
if ([[recipient lowercaseString] hasPrefix: @"mailto:"])
{
- [elements addObject: [self _caldavSuccessCodeWithRecipient: recipient]];
+ [elements addObject: [self _caldavSuccessCodeWithRecipient: recipient]];
}
return elements;
}
- (NSArray *) postCalDAVEventCancelTo: (NSArray *) recipients
- from: (NSString *) originator
+ from: (NSString *) originator
{
NSEnumerator *recipientsEnum;
NSMutableArray *elements;
@@ -1288,14 +1338,14 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
while ((recipient = [recipientsEnum nextObject]))
if ([[recipient lowercaseString] hasPrefix: @"mailto:"])
{
- [elements addObject: [self _caldavSuccessCodeWithRecipient: recipient]];
+ [elements addObject: [self _caldavSuccessCodeWithRecipient: recipient]];
}
return elements;
}
- (NSArray *) postCalDAVEventReplyTo: (NSArray *) recipients
- from: (NSString *) originator
+ from: (NSString *) originator
{
NSEnumerator *recipientsEnum;
NSMutableArray *elements;
@@ -1307,7 +1357,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
while ((recipient = [recipientsEnum nextObject]))
if ([[recipient lowercaseString] hasPrefix: @"mailto:"])
{
- [elements addObject: [self _caldavSuccessCodeWithRecipient: recipient]];
+ [elements addObject: [self _caldavSuccessCodeWithRecipient: recipient]];
}
return elements;
@@ -1320,7 +1370,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
withDelegate: (iCalPerson *) delegate
{
return [self changeParticipationStatus: status
- withDelegate: delegate
+ withDelegate: delegate
forRecurrenceId: nil];
}
@@ -1371,15 +1421,14 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
attendee = [event userAsAttendee: ownerUser];
if (attendee)
{
- if (delegate
- && ![[delegate email] isEqualToString: [attendee delegatedTo]])
+ if (delegate && ![[delegate email] isEqualToString: [attendee delegatedTo]])
{
delegatedUid = [delegate uid];
if (delegatedUid)
delegatedUser = [SOGoUser userWithLogin: delegatedUid];
if (delegatedUser != nil && [event userIsOrganizer: delegatedUser])
ex = [NSException exceptionWithHTTPStatus: 403
- reason: @"delegate is organizer"];
+ reason: @"delegate is organizer"];
if ([event isAttendee: [[delegate email] rfc822Email]])
ex = [NSException exceptionWithHTTPStatus: 403
reason: @"delegate is a participant"];
@@ -1405,19 +1454,18 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
// the database. We do this ONLY when using SOGo from the
// Web interface or over ActiveSync.
// Over DAV, it'll be handled directly in PUTAction:
- if (![context request]
- || [[context request] handledByDefaultHandler]
- || [[[context request] requestHandlerKey] isEqualToString: @"Microsoft-Server-ActiveSync"])
- ex = [self saveContentString: [[event parent] versitString]];
+ if (![context request] || [[context request] handledByDefaultHandler]
+ || [[[context request] requestHandlerKey] isEqualToString: @"Microsoft-Server-ActiveSync"])
+ ex = [self saveCalendar: [event parent]];
}
}
else
ex = [NSException exceptionWithHTTPStatus: 404 // Not Found
reason: @"user does not participate in this calendar event"];
}
- else
- ex = [NSException exceptionWithHTTPStatus: 500 // Server Error
- reason: @"unable to parse event record"];
+ else
+ ex = [NSException exceptionWithHTTPStatus: 500 // Server Error
+ reason: @"unable to parse event record"];
return ex;
}
@@ -1438,20 +1486,20 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
if (theOrganizer && (v = [theOrganizer value: 0 ofAttribute: @"SCHEDULE-AGENT"]))
{
if ([v caseInsensitiveCompare: @"NONE"] == NSOrderedSame ||
- [v caseInsensitiveCompare: @"CLIENT"] == NSOrderedSame)
- b = NO;
+ [v caseInsensitiveCompare: @"CLIENT"] == NSOrderedSame)
+ b = NO;
}
-
- //
- // If we have to deal with Thunderbird/Lightning, we always send invitation
- // reponses, as Lightning v2.6 (at least this version) sets SCHEDULE-AGENT
- // to NONE/CLIENT when responding to an external invitation received by
- // SOGo - so no invitation responses are ever sent by Lightning. See
- // https://bugzilla.mozilla.org/show_bug.cgi?id=865726 and
- // https://bugzilla.mozilla.org/show_bug.cgi?id=997784
- //
- userAgents = [[context request] headersForKey: @"User-Agent"];
-
+
+ //
+ // If we have to deal with Thunderbird/Lightning, we always send invitation
+ // reponses, as Lightning v2.6 (at least this version) sets SCHEDULE-AGENT
+ // to NONE/CLIENT when responding to an external invitation received by
+ // SOGo - so no invitation responses are ever sent by Lightning. See
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=865726 and
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=997784
+ //
+ userAgents = [[context request] headersForKey: @"User-Agent"];
+
for (i = 0; i < [userAgents count]; i++)
{
if ([[userAgents objectAtIndex: i] rangeOfString: @"Thunderbird"].location != NSNotFound &&
@@ -1504,36 +1552,36 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
#warning Make sure this is correct ..
if (![attendees count] && event != occurence)
- attendees = [event attendeesWithoutUser: currentUser];
+ attendees = [event attendeesWithoutUser: currentUser];
if ([attendees count])
- {
- // Remove the event from all attendees calendars
- // and send them an email.
- [self _handleRemovedUsers: attendees
- withRecurrenceId: recurrenceId];
- [self sendEMailUsingTemplateNamed: @"Deletion"
+ {
+ // Remove the event from all attendees calendars
+ // and send them an email.
+ [self _handleRemovedUsers: attendees
+ withRecurrenceId: recurrenceId];
+ [self sendEMailUsingTemplateNamed: @"Deletion"
forObject: [occurence itipEntryWithMethod: @"cancel"]
previousObject: nil
toAttendees: attendees
withType: @"calendar:cancellation"];
- }
+ }
}
else if ([occurence userIsAttendee: ownerUser])
{
// The current user deletes the occurence; let the organizer know that
// the user has declined this occurence.
[self changeParticipationStatus: @"DECLINED" withDelegate: nil
- forRecurrenceId: recurrenceId];
+ forRecurrenceId: recurrenceId];
send_receipt = NO;
}
-
- if (send_receipt)
- [self sendReceiptEmailForObject: event
- addedAttendees: nil
- deletedAttendees: nil
- updatedAttendees: nil
- operation: EventDeleted];
+
+ if (send_receipt)
+ [self sendReceiptEmailForObject: event
+ addedAttendees: nil
+ deletedAttendees: nil
+ updatedAttendees: nil
+ operation: EventDeleted];
}
- (NSException *) prepareDelete
@@ -1616,9 +1664,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
{
event = [allEvents objectAtIndex: i];
if ([event isAllDay] && [event isOpaque])
- {
- [event setTransparency: @"TRANSPARENT"];
- }
+ [event setTransparency: @"TRANSPARENT"];
}
}
@@ -1690,10 +1736,10 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
event = [allEvents objectAtIndex: i];
if ([event recurrenceId] && !theRecurrenceId)
- return event;
-
+ return event;
+
if ([event recurrenceId] && [[event recurrenceId] compare: theRecurrenceId] == NSOrderedSame)
- return event;
+ return event;
}
return nil;
@@ -1744,12 +1790,9 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
NSArray *roles;
SOGoUser *ownerUser;
- if (calendar == fullCalendar
- || calendar == safeCalendar
- || calendar == originalCalendar)
- [NSException raise: NSInvalidArgumentException
- format: @"the 'calendar' argument must be a distinct instance"
- @" from the original object"];
+ if (calendar == fullCalendar || calendar == safeCalendar
+ || calendar == originalCalendar)
+ [NSException raise: NSInvalidArgumentException format: @"the 'calendar' argument must be a distinct instance" @" from the original object"];
ownerUser = [SOGoUser userWithLogin: owner];
@@ -1760,24 +1803,21 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
// responding to one of our invitation. In this case, _setupResponseCalendarInRequest
// will only take the new attendee status and actually discard any other modifications.
//
- if ([roles containsObject: @"ComponentResponder"]
- && ![roles containsObject: @"ComponentModifier"])
+ if ([roles containsObject: @"ComponentResponder"] && ![roles containsObject: @"ComponentModifier"])
calendar = [self _setupResponseInRequestCalendar: calendar];
else
{
- if (![[rq headersForKey: @"X-SOGo"]
- containsObject: @"NoGroupsDecomposition"])
+ if (![[rq headersForKey: @"X-SOGo"] containsObject: @"NoGroupsDecomposition"])
[self _decomposeGroupsInRequestCalendar: calendar];
-
- if ([[ownerUser domainDefaults] iPhoneForceAllDayTransparency]
- && [rq isIPhone])
- {
- [self _adjustTransparencyInRequestCalendar: calendar];
- }
-
+
+ if ([[ownerUser domainDefaults] iPhoneForceAllDayTransparency] && [rq isIPhone])
+ {
+ [self _adjustTransparencyInRequestCalendar: calendar];
+ }
+
[self _adjustEventsInRequestCalendar: calendar];
}
-
+
//
// We first check if it's a new event
//
@@ -1798,47 +1838,46 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
// TODO: send out a no-uid-conflict (DAV:href) xml element (rfc4791 section 5.3.2.1)
if ([container resourceNameForEventUID: eventUID])
{
- return [NSException exceptionWithHTTPStatus: 403
- reason: [NSString stringWithFormat: @"Event UID already in use. (%s)", eventUID]];
+ return [NSException exceptionWithHTTPStatus: 403
+ reason: [NSString stringWithFormat: @"Event UID already in use. (%s)", eventUID]];
}
//
// New event and we're the organizer -- send invitation to all attendees
//
if (scheduling && [event userIsOrganizer: ownerUser])
- {
- attendees = [event attendeesWithoutUser: ownerUser];
- if ([attendees count])
- {
- if ((ex = [self _handleAddedUsers: attendees fromEvent: event]))
- return ex;
- else
- {
- // We might have auto-accepted resources here. If that's the
- // case, let's regenerate the versitstring and replace the
- // one from the request.
- [rq setContent: [[[event parent] versitString] dataUsingEncoding: [rq contentEncoding]]];
- }
-
- [self sendEMailUsingTemplateNamed: @"Invitation"
- forObject: [event itipEntryWithMethod: @"request"]
- previousObject: nil
- toAttendees: attendees
- withType: @"calendar:invitation"];
- }
- }
+ {
+ attendees = [event attendeesWithoutUser: ownerUser];
+ if ([attendees count])
+ {
+ if ((ex = [self _handleAddedUsers: attendees fromEvent: event]))
+ return ex;
+ else
+ {
+ // We might have auto-accepted resources here. If that's the
+ // case, let's regenerate the versitstring and replace the
+ // one from the request.
+ [rq setContent: [[[event parent] versitString] dataUsingEncoding: [rq contentEncoding]]];
+ }
+
+ [self sendEMailUsingTemplateNamed: @"Invitation"
+ forObject: [event itipEntryWithMethod: @"request"]
+ previousObject: nil
+ toAttendees: attendees
+ withType: @"calendar:invitation"];
+ }
+ }
//
// We aren't the organizer but we're an attendee. That can happen when
// we receive an external invitation (IMIP/ITIP) and we accept it
// from a CUA - it gets added to a specific CalDAV calendar using a PUT
//
else if (scheduling && [event userIsAttendee: ownerUser])
- {
- [self sendIMIPReplyForEvent: event
- from: ownerUser
- to: [event organizer]];
- }
-
+ {
+ [self sendIMIPReplyForEvent: event
+ from: ownerUser
+ to: [event organizer]];
+ }
[self sendReceiptEmailForObject: event
addedAttendees: attendees
@@ -1865,198 +1904,197 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
recurrenceId = nil;
for (i = [newEvents count]-1; i >= 0; i--)
- {
- newEvent = [newEvents objectAtIndex: i];
-
- if ([newEvent recurrenceId])
- {
- // Find the corresponding RECURRENCE-ID in the old calendar
- // If not present, we assume it was created before the PUT
- oldEvent = [self _eventFromRecurrenceId: [newEvent recurrenceId]
- events: oldEvents];
-
- if (oldEvent == nil)
- {
- NSString *recurrenceTime;
- recurrenceTime = [NSString stringWithFormat: @"%f", [[newEvent recurrenceId] timeIntervalSince1970]];
- oldEvent = (iCalEvent *)[self newOccurenceWithID: recurrenceTime];
- }
-
- // If present, we look for changes
- changes = [iCalEventChanges changesFromEvent: oldEvent toEvent: newEvent];
-
- if ([changes sequenceShouldBeIncreased] | [changes hasAttendeeChanges])
- {
- // We found a RECURRENCE-ID with changes, we consider it
- recurrenceId = [newEvent recurrenceId];
- break;
- }
- else
- {
+ {
+ newEvent = [newEvents objectAtIndex: i];
+
+ if ([newEvent recurrenceId])
+ {
+ // Find the corresponding RECURRENCE-ID in the old calendar
+ // If not present, we assume it was created before the PUT
+ oldEvent = [self _eventFromRecurrenceId: [newEvent recurrenceId]
+ events: oldEvents];
+
+ if (oldEvent == nil)
+ {
+ NSString *recurrenceTime;
+ recurrenceTime = [NSString stringWithFormat: @"%f", [[newEvent recurrenceId] timeIntervalSince1970]];
+ oldEvent = (iCalEvent *)[self newOccurenceWithID: recurrenceTime];
+ }
+
+ // If present, we look for changes
+ changes = [iCalEventChanges changesFromEvent: oldEvent toEvent: newEvent];
+
+ if ([changes sequenceShouldBeIncreased] | [changes hasAttendeeChanges])
+ {
+ // We found a RECURRENCE-ID with changes, we consider it
+ recurrenceId = [newEvent recurrenceId];
+ break;
+ }
+ else
+ {
[newEvents removeObject: newEvent];
[oldEvents removeObject: oldEvent];
- }
- }
-
- oldEvent = nil;
- newEvent = nil;
- }
+ }
+ }
+
+ oldEvent = nil;
+ newEvent = nil;
+ }
// If no changes were observed, let's see if we have any left overs
// in the oldEvents or in the newEvents array
if (!oldEvent && !newEvent)
- {
- // We check if we only have to deal with the MASTER event
- if ([newEvents count] == [oldEvents count])
- {
- oldEvent = [oldEvents objectAtIndex: 0];
- newEvent = [newEvents objectAtIndex: 0];
- }
- // A RECURRENCE-ID was added
- else if ([newEvents count] > [oldEvents count])
- {
- oldEvent = nil;
- newEvent = [self _eventFromRecurrenceId: nil events: newEvents];
- recurrenceId = [newEvent recurrenceId];
- }
- // A RECURRENCE-ID was removed
- else
- {
- oldEvent = [self _eventFromRecurrenceId: nil events: oldEvents];
- newEvent = nil;
- recurrenceId = [oldEvent recurrenceId];
- }
- }
-
+ {
+ // We check if we only have to deal with the MASTER event
+ if ([newEvents count] == [oldEvents count])
+ {
+ oldEvent = [oldEvents objectAtIndex: 0];
+ newEvent = [newEvents objectAtIndex: 0];
+ }
+ // A RECURRENCE-ID was added
+ else if ([newEvents count] > [oldEvents count])
+ {
+ oldEvent = nil;
+ newEvent = [self _eventFromRecurrenceId: nil events: newEvents];
+ recurrenceId = [newEvent recurrenceId];
+ }
+ // A RECURRENCE-ID was removed
+ else
+ {
+ oldEvent = [self _eventFromRecurrenceId: nil events: oldEvents];
+ newEvent = nil;
+ recurrenceId = [oldEvent recurrenceId];
+ }
+ }
+
// We check if the PUT call is actually an PART-STATE change
// from one of the attendees - here's the logic :
//
- // if owner == organizer
+ // if owner == organizer
//
// if [context activeUser] == organizer
// [send the invitation update]
// else
// [react on SENT-BY as someone else is acting for the organizer]
- //
- //
+ //
+ //
if ([[newEvent attendees] count] || [[oldEvent attendees] count])
- {
- NSString *uid;
+ {
+ NSString *uid;
// newEvent might be nil here, if we're deleting a RECURRENCE-ID with attendees
// If that's the case, we use the oldEvent for now just to obtain the organizer
// and we'll swap it back to nil once we're done.
if (!newEvent)
newEvent = oldEvent;
-
- // We fetch the organizer's uid. Sometimes, the recurrence-id will
- // have it, sometimes not. If it doesn't, we fetch it from the master event.
- uid = [[newEvent organizer] uid];
-
- if (!uid && !recurrenceId)
- uid = [[[[[newEvent parent] events] objectAtIndex: 0] organizer] uid];
-
- // With Thunderbird 10, if you create a recurring event with an exception
- // occurence, and invite someone, the PUT will have the organizer in the
- // recurrence-id and not in the master event. We must fix this, otherwise
- // SOGo will break.
- if (!recurrenceId && ![[[[[newEvent parent] events] objectAtIndex: 0] organizer] uid])
- [[[[newEvent parent] events] objectAtIndex: 0]
- setOrganizer: [newEvent organizer]];
-
+
+ // We fetch the organizer's uid. Sometimes, the recurrence-id will
+ // have it, sometimes not. If it doesn't, we fetch it from the master event.
+ uid = [[newEvent organizer] uid];
+
+ if (!uid && !recurrenceId)
+ uid = [[[[[newEvent parent] events] objectAtIndex: 0] organizer] uid];
+
+ // With Thunderbird 10, if you create a recurring event with an exception
+ // occurence, and invite someone, the PUT will have the organizer in the
+ // recurrence-id and not in the master event. We must fix this, otherwise
+ // SOGo will break.
+ if (!recurrenceId && ![[[[[newEvent parent] events] objectAtIndex: 0] organizer] uid])
+ [[[[newEvent parent] events] objectAtIndex: 0] setOrganizer: [newEvent organizer]];
+
if (newEvent == oldEvent)
newEvent = nil;
-
- if (uid && [uid caseInsensitiveCompare: owner] == NSOrderedSame)
- {
+
+ if (uid && [uid caseInsensitiveCompare: owner] == NSOrderedSame)
+ {
// A RECCURENCE-ID was removed
if (!newEvent && oldEvent)
[self prepareDeleteOccurence: oldEvent];
// The master event was changed, A RECCURENCE-ID was added or modified
else if ((ex = [self _handleUpdatedEvent: newEvent fromOldEvent: oldEvent]))
- return ex;
- }
- //
- // else => attendee is responding
- //
- // if [context activeUser] == attendee
- // [we change the PART-STATE]
- // else
- // [react on SENT-BY as someone else is acting for the attendee]
- else
- {
- iCalPerson *attendee, *delegate;
- NSString *delegateEmail;
-
- attendee = [newEvent userAsAttendee: [SOGoUser userWithLogin: owner]];
-
- // We first check of the sequences are alright. We don't accept attendees
- // accepting "old" invitations. If that's the case, we return a 403
+ return ex;
+ }
+ //
+ // else => attendee is responding
+ //
+ // if [context activeUser] == attendee
+ // [we change the PART-STATE]
+ // else
+ // [react on SENT-BY as someone else is acting for the attendee]
+ else
+ {
+ iCalPerson *attendee, *delegate;
+ NSString *delegateEmail;
+
+ attendee = [newEvent userAsAttendee: [SOGoUser userWithLogin: owner]];
+
+ // We first check of the sequences are alright. We don't accept attendees
+ // accepting "old" invitations. If that's the case, we return a 403
if ([[newEvent sequence] intValue] < [[oldEvent sequence] intValue])
- return [NSException exceptionWithHTTPStatus:403
- reason: @"sequences don't match"];
-
+ return [NSException exceptionWithHTTPStatus:403
+ reason: @"sequences don't match"];
+
// Remove the RSVP attribute, as an action from the attendee
// was actually performed, and this confuses iCal (bug #1850)
- [[attendee attributes] removeObjectForKey: @"RSVP"];
-
- delegate = nil;
- delegateEmail = [attendee delegatedTo];
-
- if ([delegateEmail length])
- {
- delegateEmail = [delegateEmail substringFromIndex: 7];
- if ([delegateEmail length])
- delegate = [newEvent findAttendeeWithEmail: delegateEmail];
- }
-
- changes = [iCalEventChanges changesFromEvent: oldEvent toEvent: newEvent];
-
- // The current user deletes the occurence; let the organizer know that
- // the user has declined this occurence.
- if ([[changes updatedProperties] containsObject: @"exdate"])
- {
- [self changeParticipationStatus: @"DECLINED"
- withDelegate: nil // FIXME (specify delegate?)
- forRecurrenceId: [self _addedExDate: oldEvent newEvent: newEvent]];
- }
- else if (attendee)
- {
- [self changeParticipationStatus: [attendee partStat]
- withDelegate: delegate
- forRecurrenceId: recurrenceId];
- }
- // All attendees and the organizer field were removed. Apple iCal does
- // that when we remove the last attendee of an event.
- //
- // We must update previous's attendees' calendars to actually
- // remove the event in each of them.
- else
- {
- [self _handleRemovedUsers: [changes deletedAttendees]
- withRecurrenceId: recurrenceId];
- }
- }
- } // if ([[newEvent attendees] count] || [[oldEvent attendees] count])
+ [[attendee attributes] removeObjectForKey: @"RSVP"];
+
+ delegate = nil;
+ delegateEmail = [attendee delegatedTo];
+
+ if ([delegateEmail length])
+ {
+ delegateEmail = [delegateEmail substringFromIndex: 7];
+ if ([delegateEmail length])
+ delegate = [newEvent findAttendeeWithEmail: delegateEmail];
+ }
+
+ changes = [iCalEventChanges changesFromEvent: oldEvent toEvent: newEvent];
+
+ // The current user deletes the occurence; let the organizer know that
+ // the user has declined this occurence.
+ if ([[changes updatedProperties] containsObject: @"exdate"])
+ {
+ [self changeParticipationStatus: @"DECLINED"
+ withDelegate: nil // FIXME (specify delegate?)
+ forRecurrenceId: [self _addedExDate: oldEvent newEvent: newEvent]];
+ }
+ else if (attendee)
+ {
+ [self changeParticipationStatus: [attendee partStat]
+ withDelegate: delegate
+ forRecurrenceId: recurrenceId];
+ }
+ // All attendees and the organizer field were removed. Apple iCal does
+ // that when we remove the last attendee of an event.
+ //
+ // We must update previous's attendees' calendars to actually
+ // remove the event in each of them.
+ else
+ {
+ [self _handleRemovedUsers: [changes deletedAttendees]
+ withRecurrenceId: recurrenceId];
+ }
+ }
+ } // if ([[newEvent attendees] count] || [[oldEvent attendees] count])
else
- {
- [self sendReceiptEmailForObject: newEvent
- addedAttendees: nil
- deletedAttendees: nil
- updatedAttendees: nil
- operation: EventUpdated];
- }
+ {
+ [self sendReceiptEmailForObject: newEvent
+ addedAttendees: nil
+ deletedAttendees: nil
+ updatedAttendees: nil
+ operation: EventUpdated];
+ }
} // else of if (isNew) ...
-
+
unsigned int baseVersion;
// We must NOT invoke [super PUTAction:] here as it'll resave
// the content string and we could have etag mismatches.
baseVersion = (isNew ? 0 : version);
-
- ex = [self saveContentString: [calendar versitString]
- baseVersion: baseVersion];
-
- return ex;
+
+ ex = [self saveComponent: calendar
+ baseVersion: baseVersion];
+
+ return ex;
}
//
@@ -2086,24 +2124,24 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
//
ex = [self matchesRequestConditionInContext: context];
if (ex)
- return ex;
+ return ex;
}
-
- ex = [self updateContentWithCalendar: rqCalendar fromRequest: rq];
- if (ex)
- response = (WOResponse *) ex;
+
+ ex = [self updateContentWithCalendar: rqCalendar fromRequest: rq];
+ if (ex)
+ response = (WOResponse *) ex;
else
{
response = [_ctx response];
if (isNew)
- [response setStatus: 201 /* Created */];
+ [response setStatus: 201 /* Created */];
else
- [response setStatus: 204 /* No Content */];
+ [response setStatus: 204 /* No Content */];
etag = [self davEntityTag];
if (etag)
- [response setHeader: etag forKey: @"etag"];
+ [response setHeader: etag forKey: @"etag"];
}
-
+
return response;
}
diff --git a/SoObjects/Appointments/SOGoCalendarComponent.h b/SoObjects/Appointments/SOGoCalendarComponent.h
index 61aca5c3d..e1e2bc7bd 100644
--- a/SoObjects/Appointments/SOGoCalendarComponent.h
+++ b/SoObjects/Appointments/SOGoCalendarComponent.h
@@ -1,6 +1,6 @@
/* SOGoCalendarComponent.h - this file is part of SOGo
*
- * Copyright (C) 2006-2013 Inverse inc.
+ * Copyright (C) 2006-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/SoObjects/Appointments/SOGoCalendarComponent.m b/SoObjects/Appointments/SOGoCalendarComponent.m
index d595bdba0..f8822c061 100644
--- a/SoObjects/Appointments/SOGoCalendarComponent.m
+++ b/SoObjects/Appointments/SOGoCalendarComponent.m
@@ -169,6 +169,11 @@
DESTROY(originalCalendar);
}
+- (Class *) parsingClass
+{
+ return [iCalCalendar class];
+}
+
- (NSString *) davContentType
{
return @"text/calendar";
@@ -662,7 +667,7 @@
- (NSException *) saveCalendar: (iCalCalendar *) newCalendar
{
- [self saveContentString: [newCalendar versitString]];
+ [super saveComponent: newCalendar];
return nil;
}
@@ -1193,7 +1198,19 @@
[NSString stringWithFormat: @"%@.ics", newUID]
inContainer: newFolder];
- return [newComponent saveContentString: [calendar versitString]];
+ return [newComponent saveCalendar: calendar];
+}
+
+- (NSException *) moveToFolder: (SOGoGCSFolder *) newFolder
+{
+ NSException *ex;
+
+ ex = [self copyToFolder: newFolder];
+
+ if (!ex)
+ ex = [self delete];
+
+ return ex;
}
#warning Should we not remove the concept of Organizer and Participant roles?
diff --git a/SoObjects/Appointments/SOGoComponentOccurence.m b/SoObjects/Appointments/SOGoComponentOccurence.m
index 97c9b1138..0609720b3 100644
--- a/SoObjects/Appointments/SOGoComponentOccurence.m
+++ b/SoObjects/Appointments/SOGoComponentOccurence.m
@@ -1,9 +1,6 @@
/* SOGoComponentOccurence.m - this file is part of SOGo
*
- * Copyright (C) 2008-2011 Inverse inc.
- *
- * Author: Wolfgang Sourdeau
- * Francis Lachapelle
+ * Copyright (C) 2008-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -152,7 +149,6 @@
NSArray *occurences;
NSCalendarDate *recurrenceId, *currentId;
NSException *error;
- NSString *newContent;
NSTimeZone *timeZone;
iCalCalendar *calendar;
iCalEntityObject *currentOccurence;
@@ -197,10 +193,8 @@
[master addToExceptionDates: recurrenceId];
[master increaseSequence];
- // We generate the updated iCalendar file and we save it
- // in the database.
- newContent = [calendar versitString];
- error = [container saveContentString: newContent];
+ // We save the updated iCalendar in the database.
+ error = [container saveComponent: calendar];
}
return error;
diff --git a/SoObjects/Appointments/SOGoTaskObject.h b/SoObjects/Appointments/SOGoTaskObject.h
index 6b5d27d60..5d15c856a 100644
--- a/SoObjects/Appointments/SOGoTaskObject.h
+++ b/SoObjects/Appointments/SOGoTaskObject.h
@@ -1,6 +1,6 @@
/*
- Copyright (C) 2006-2013 Inverse inc.
+ Copyright (C) 2006-2014 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of SOGo.
diff --git a/SoObjects/Appointments/SOGoTaskObject.m b/SoObjects/Appointments/SOGoTaskObject.m
index 5d70dabd0..a94ca3a38 100644
--- a/SoObjects/Appointments/SOGoTaskObject.m
+++ b/SoObjects/Appointments/SOGoTaskObject.m
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2006-2012 Inverse inc.
+ Copyright (C) 2006-2014 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of SOGo.
@@ -65,12 +65,12 @@
#warning this code should be put in SOGoCalendarComponent once the UID hack\
in SOGoAppointmentObject is resolved
-- (NSException *) saveContentString: (NSString *) newContent
- baseVersion: (unsigned int) newVersion
+- (NSException *) saveComponent: (id) theComponent
+ baseVersion: (unsigned int) newVersion
{
NSException *ex;
- ex = [super saveContentString: newContent baseVersion: newVersion];
+ ex = [super saveComponent: theComponent baseVersion: newVersion];
[fullCalendar release];
fullCalendar = nil;
[safeCalendar release];
diff --git a/SoObjects/Appointments/SOGoWebAppointmentFolder.h b/SoObjects/Appointments/SOGoWebAppointmentFolder.h
index 45e5da636..736a6b461 100644
--- a/SoObjects/Appointments/SOGoWebAppointmentFolder.h
+++ b/SoObjects/Appointments/SOGoWebAppointmentFolder.h
@@ -1,9 +1,6 @@
/* SOGoWebAppointmentFolder.h - this file is part of SOGo
*
- * Copyright (C) 2009-2012 Inverse inc.
- *
- * Author: Cyril Robert
- * Ludovic Marcotte
+ * Copyright (C) 2009-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/SoObjects/Appointments/SOGoWebAppointmentFolder.m b/SoObjects/Appointments/SOGoWebAppointmentFolder.m
index f5c004c84..3bd6c4206 100644
--- a/SoObjects/Appointments/SOGoWebAppointmentFolder.m
+++ b/SoObjects/Appointments/SOGoWebAppointmentFolder.m
@@ -1,9 +1,6 @@
/* SOGoWebAppointmentFolder.m - this file is part of SOGo
*
- * Copyright (C) 2009-2013 Inverse inc.
- *
- * Author: Cyril Robert
- * Ludovic Marcotte
+ * Copyright (C) 2009-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/SoObjects/Appointments/SpanishSpain.lproj/Localizable.strings b/SoObjects/Appointments/SpanishSpain.lproj/Localizable.strings
index c855a96bf..5add824eb 100644
--- a/SoObjects/Appointments/SpanishSpain.lproj/Localizable.strings
+++ b/SoObjects/Appointments/SpanishSpain.lproj/Localizable.strings
@@ -1,3 +1,4 @@
+"Inviting the following persons is prohibited:" = "Esta prohibido invitar las siguientes personas:";
"Personal Calendar" = "Calendario personal";
vevent_class0 = "(Evento público)";
vevent_class1 = "(Evento privado)";
diff --git a/SoObjects/Appointments/iCalCalendar+SOGo.m b/SoObjects/Appointments/iCalCalendar+SOGo.m
index 466c47291..e3af84d15 100644
--- a/SoObjects/Appointments/iCalCalendar+SOGo.m
+++ b/SoObjects/Appointments/iCalCalendar+SOGo.m
@@ -1,8 +1,6 @@
/* iCalCalendar+SOGo.m - this file is part of SOGo
*
- * Copyright (C) 2012 Inverse inc
- *
- * Author: Wolfgang Sourdeau
+ * Copyright (C) 2012-2014 Inverse inc
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -80,4 +78,24 @@
return [self _occurrence: recID inArray: [self todos]];
}
+- (NSMutableDictionary *) quickRecordForContainer: (id) theContainer
+{
+ CardGroup *element;
+ NSArray *elements;
+
+ unsigned int count;
+
+ elements = [self allObjects];
+ count = [elements count];
+ if (count)
+ element = [elements objectAtIndex: 0];
+ else
+ {
+ [self logWithFormat: @"ERROR: given calendar contains no elements: %@", self];
+ element = nil;
+ }
+
+ return [element quickRecordForContainer: theContainer];
+}
+
@end
diff --git a/SoObjects/Appointments/iCalEntityObject+SOGo.h b/SoObjects/Appointments/iCalEntityObject+SOGo.h
index dee22f353..a37c727d5 100644
--- a/SoObjects/Appointments/iCalEntityObject+SOGo.h
+++ b/SoObjects/Appointments/iCalEntityObject+SOGo.h
@@ -43,7 +43,7 @@ extern NSNumber *iCalDistantFutureNumber;
- (id) itipEntryWithMethod: (NSString *) method;
- (NSArray *) attendeesWithoutUser: (SOGoUser *) user;
-- (NSMutableDictionary *) quickRecord;
+- (NSMutableDictionary *) quickRecordForContainer: (id) theContainer;
- (int) priorityNumber;
- (NSString *) createdBy;
diff --git a/SoObjects/Appointments/iCalEntityObject+SOGo.m b/SoObjects/Appointments/iCalEntityObject+SOGo.m
index 97f9ce336..cdb32a582 100644
--- a/SoObjects/Appointments/iCalEntityObject+SOGo.m
+++ b/SoObjects/Appointments/iCalEntityObject+SOGo.m
@@ -213,7 +213,7 @@ NSNumber *iCalDistantFutureNumber = nil;
return dateNumber;
}
-- (NSMutableDictionary *) quickRecord
+- (NSMutableDictionary *) quickRecordForContainer: (id) theContainer
{
[self subclassResponsibility: _cmd];
diff --git a/SoObjects/Appointments/iCalEvent+SOGo.h b/SoObjects/Appointments/iCalEvent+SOGo.h
index 9d2ee9dd4..fd4869132 100644
--- a/SoObjects/Appointments/iCalEvent+SOGo.h
+++ b/SoObjects/Appointments/iCalEvent+SOGo.h
@@ -1,9 +1,6 @@
/* iCalEvent+SOGo.h - this file is part of SOGo
*
- * Copyright (C) 2007-2011 Inverse inc.
- *
- * Author: Wolfgang Sourdeau
- * Francis Lachapelle
+ * Copyright (C) 2007-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,7 +29,7 @@
- (BOOL) isStillRelevant;
- (unsigned int) occurenceInterval;
-- (NSMutableDictionary *) quickRecord;
+- (NSMutableDictionary *) quickRecordForContainer: (id) theContainer;
- (void) updateRecurrenceRulesUntilDate: (NSCalendarDate *) previousEndDate;
@end
diff --git a/SoObjects/Appointments/iCalEvent+SOGo.m b/SoObjects/Appointments/iCalEvent+SOGo.m
index 6856d89fb..f811ceeca 100644
--- a/SoObjects/Appointments/iCalEvent+SOGo.m
+++ b/SoObjects/Appointments/iCalEvent+SOGo.m
@@ -1,9 +1,6 @@
/* iCalEvent+SOGo.m - this file is part of SOGo
*
- * Copyright (C) 2007-2013 Inverse inc.
- *
- * Author: Wolfgang Sourdeau
- * Francis Lachapelle
+ * Copyright (C) 2007-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -67,7 +64,7 @@
//
//
//
-- (NSMutableDictionary *) quickRecord
+- (NSMutableDictionary *) quickRecordForContainer: (id) theContainer
{
NSMutableDictionary *row;
NSCalendarDate *startDate, *endDate, *nextAlarmDate;
diff --git a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.h b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.h
index 2d5233666..845167967 100644
--- a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.h
+++ b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.h
@@ -1,24 +1,22 @@
/* iCalRepeatableEntityObject+SOGo.h - this file is part of SOGo
- Copyright (C) 2004-2005 SKYRIX Software AG
- Copyright (C) 2008-2013 Inverse inc.
-
- This file is part of OpenGroupware.org.
-
- OGo is free software; you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- OGo is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with OGo; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-*/
+ *
+ * Copyright (C) 2007-2014 Inverse inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
#import
diff --git a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m
index 4bbc30e25..128249e88 100644
--- a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m
+++ b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m
@@ -1,24 +1,22 @@
-/*
- Copyright (C) 2008-2013 Inverse inc.
- Copyright (C) 2004-2005 SKYRIX Software AG
-
- This file is part of OpenGroupware.org.
-
- OGo is free software; you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- OGo is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with OGo; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-*/
+/* iCalRepeatableEntityObject+SOGo.m - this file is part of SOGo
+ *
+ * Copyright (C) 2007-2014 Inverse inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
#import
#import
diff --git a/SoObjects/Appointments/iCalToDo+SOGo.h b/SoObjects/Appointments/iCalToDo+SOGo.h
index 81c16f80d..8da587395 100644
--- a/SoObjects/Appointments/iCalToDo+SOGo.h
+++ b/SoObjects/Appointments/iCalToDo+SOGo.h
@@ -1,8 +1,6 @@
/* iCalToDo+SOGo.h - this file is part of SOGo
*
- * Copyright (C) 2007 Inverse inc.
- *
- * Author: Wolfgang Sourdeau
+ * Copyright (C) 2007-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,7 +27,7 @@
@interface iCalToDo (SOGoExtensions)
-- (NSMutableDictionary *) quickRecord;
+- (NSMutableDictionary *) quickRecordForContainer: (id) theContainer;
@end
diff --git a/SoObjects/Appointments/iCalToDo+SOGo.m b/SoObjects/Appointments/iCalToDo+SOGo.m
index fd3487198..f46f05ba5 100644
--- a/SoObjects/Appointments/iCalToDo+SOGo.m
+++ b/SoObjects/Appointments/iCalToDo+SOGo.m
@@ -1,9 +1,6 @@
-/* iCalEvent+SOGo.m - this file is part of SOGo
+/* iCalToDot+SOGo.m - this file is part of SOGo
*
- * Copyright (C) 2008 Inverse inc.
- * Copyright (C) 2004-2005 SKYRIX Software AG
- *
- * Author: Wolfgang Sourdeau
+ * Copyright (C) 2008-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -41,7 +38,7 @@
@implementation iCalToDo (SOGoExtensions)
-- (NSMutableDictionary *) quickRecord
+- (NSMutableDictionary *) quickRecordForContainer: (id) theContainer
{
NSMutableDictionary *row;
NSCalendarDate *startDate, *dueDate, *nextAlarmDate;
diff --git a/SoObjects/Contacts/Catalan.lproj/Localizable.strings b/SoObjects/Contacts/Catalan.lproj/Localizable.strings
index 4be5199c9..368f3b89b 100644
--- a/SoObjects/Contacts/Catalan.lproj/Localizable.strings
+++ b/SoObjects/Contacts/Catalan.lproj/Localizable.strings
@@ -1 +1,2 @@
"Personal Address Book" = "Llibreta personal d'adreces";
+"Collected Address Book" = "Llibreta d'adreces recopilades";
diff --git a/SoObjects/Contacts/NGVCard+SOGo.m b/SoObjects/Contacts/NGVCard+SOGo.m
index e13cbfffe..5f94a8a87 100644
--- a/SoObjects/Contacts/NGVCard+SOGo.m
+++ b/SoObjects/Contacts/NGVCard+SOGo.m
@@ -24,9 +24,12 @@
#import
#import
+#import
+
#import
#import
+#import
#import
#import "NSDictionary+LDIF.h"
@@ -788,4 +791,51 @@ convention:
return date;
}
+- (NSMutableDictionary *) quickRecordForContainer: (id) theContainer
+{
+ NSMutableDictionary *fields;
+ CardElement *element;
+ NSString *value;
+ NSArray *v;
+
+ fields = [NSMutableDictionary dictionaryWithCapacity: 16];
+
+ value = [self fn];
+ if (value)
+ [fields setObject: value forKey: @"c_cn"];
+ element = [self n];
+ [fields setObject: [element flattenedValueAtIndex: 0 forKey: @""]
+ forKey: @"c_sn"];
+ [fields setObject: [element flattenedValueAtIndex: 1 forKey: @""]
+ forKey: @"c_givenName"];
+ value = [self preferredTel];
+ if (value)
+ [fields setObject: value forKey: @"c_telephonenumber"];
+ value = [self preferredEMail];
+ if (![value isNotNull])
+ value = @"";
+ [fields setObject: value forKey: @"c_mail"];
+ element = [self org];
+ [fields setObject: [element flattenedValueAtIndex: 0 forKey: @""]
+ forKey: @"c_o"];
+ [fields setObject: [element flattenedValueAtIndex: 1 forKey: @""]
+ forKey: @"c_ou"];
+ element = [self preferredAdr];
+ if (element && ![element isVoid])
+ [fields setObject: [element flattenedValueAtIndex: 3
+ forKey: @""]
+ forKey: @"c_l"];
+ value = [[self uniqueChildWithTag: @"X-AIM"] flattenedValuesForKey: @""];
+ [fields setObject: value forKey: @"c_screenname"];
+ v = [[self categories] trimmedComponents];
+ if ([v count] > 0)
+ [fields setObject: [v componentsJoinedByString: @","]
+ forKey: @"c_categories"];
+ else
+ [fields setObject: [NSNull null] forKey: @"c_categories"];
+ [fields setObject: @"vcard" forKey: @"c_component"];
+
+ return fields;
+}
+
@end /* NGVCard */
diff --git a/SoObjects/Contacts/NGVList+SOGo.h b/SoObjects/Contacts/NGVList+SOGo.h
index 04601ae1c..286a65faa 100644
--- a/SoObjects/Contacts/NGVList+SOGo.h
+++ b/SoObjects/Contacts/NGVList+SOGo.h
@@ -1,8 +1,6 @@
/* NGVCard+SOGo.h - this file is part of SOGo
*
- * Copyright (C) 2009 Inverse inc.
- *
- * Author: Cyril Robert
+ * Copyright (C) 2009-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/SoObjects/Contacts/NGVList+SOGo.m b/SoObjects/Contacts/NGVList+SOGo.m
index 4e6fd7c78..7c7bebbe7 100644
--- a/SoObjects/Contacts/NGVList+SOGo.m
+++ b/SoObjects/Contacts/NGVList+SOGo.m
@@ -1,8 +1,6 @@
/* NGVCard+SOGo.m - this file is part of SOGo
*
- * Copyright (C) 2009 Inverse inc.
- *
- * Author: Cyril Robert
+ * Copyright (C) 2009-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -71,4 +69,19 @@
return rc;
}
+- (NSMutableDictionary *) quickRecordForContainer: (id) theContainer
+{
+ NSMutableDictionary *fields;
+ NSString *value;
+
+ fields = [NSMutableDictionary dictionaryWithCapacity: 1];
+
+ value = [self fn];
+ if (value)
+ [fields setObject: value forKey: @"c_cn"];
+ [fields setObject: @"vlist" forKey: @"c_component"];
+
+ return fields;
+}
+
@end /* NGVList */
diff --git a/SoObjects/Contacts/NorwegianBokmal.lproj/Localizable.strings b/SoObjects/Contacts/NorwegianBokmal.lproj/Localizable.strings
index ab6ee40e1..85fade2b6 100644
--- a/SoObjects/Contacts/NorwegianBokmal.lproj/Localizable.strings
+++ b/SoObjects/Contacts/NorwegianBokmal.lproj/Localizable.strings
@@ -1 +1,2 @@
"Personal Address Book" = "Personlig adressebok";
+"Collected Address Book" = "Samlet addressebok";
diff --git a/SoObjects/Contacts/SOGoContactGCSEntry.m b/SoObjects/Contacts/SOGoContactGCSEntry.m
index 6e3365d4e..4b5d5bd21 100644
--- a/SoObjects/Contacts/SOGoContactGCSEntry.m
+++ b/SoObjects/Contacts/SOGoContactGCSEntry.m
@@ -48,6 +48,11 @@
[super dealloc];
}
+- (Class *) parsingClass
+{
+ return [NGVCard class];
+}
+
/* content */
- (NGVCard *) vCard
@@ -121,11 +126,25 @@
newContact = [[self class] objectWithName:
[NSString stringWithFormat: @"%@.vcf", newUID]
- inContainer: newFolder];
+ inContainer: newFolder];
- return [newContact saveContentString: [newCard versitString]];
+ return [newContact saveComponent: newCard];
}
+
+- (NSException *) moveToFolder: (SOGoGCSFolder *) newFolder
+{
+ NSException *ex;
+
+ ex = [self copyToFolder: newFolder];
+
+ if (!ex)
+ ex = [self delete];
+
+ return ex;
+}
+
+
- (NSString *) displayName
{
return [[self vCard] fn];
@@ -150,7 +169,7 @@
NSException *result;
if (card)
- result = [self saveContentString: [card versitString]];
+ result = [super saveComponent: card];
else
result = nil; /* TODO: we should probably return an exception instead */
@@ -160,15 +179,15 @@
- (NSException *) saveComponent: (NGVCard *) newCard
{
ASSIGN(card, newCard);
- return [self save];
+ return [super saveComponent: newCard];
}
-- (NSException *) saveContentString: (NSString *) newContent
- baseVersion: (unsigned int) newVersion
+- (NSException *) saveComponent: (NGVCard *) newCard
+ baseVersion: (unsigned int) newVersion
{
NSException *ex;
- ex = [super saveContentString: newContent baseVersion: newVersion];
+ ex = [super saveComponent: newCard baseVersion: newVersion];
[card release];
card = nil;
diff --git a/SoObjects/Contacts/SOGoContactGCSFolder.h b/SoObjects/Contacts/SOGoContactGCSFolder.h
index 643491278..15c823542 100644
--- a/SoObjects/Contacts/SOGoContactGCSFolder.h
+++ b/SoObjects/Contacts/SOGoContactGCSFolder.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2006-2011 Inverse inc.
+ Copyright (C) 2006-2014 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of SOGo.
diff --git a/SoObjects/Contacts/SOGoContactGCSList.m b/SoObjects/Contacts/SOGoContactGCSList.m
index 11d75a752..61e68bf85 100644
--- a/SoObjects/Contacts/SOGoContactGCSList.m
+++ b/SoObjects/Contacts/SOGoContactGCSList.m
@@ -1,8 +1,6 @@
/* SOGoContactGCSList.m - this file is part of SOGo
*
- * Copyright (C) 2008-2009 Inverse inc.
- *
- * Author: Wolfgang Sourdeau
+ * Copyright (C) 2008-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -45,6 +43,12 @@
[super dealloc];
}
+- (Class *) parsingClass
+{
+ return [NGVList class];
+}
+
+
/* content */
- (NGVList *) vList
@@ -77,7 +81,19 @@
[NSString stringWithFormat: @"%@.vlf", newUID]
inContainer: newFolder];
- return [newGList saveContentString: [newList versitString]];
+ return [newGList saveComponent: newList];
+}
+
+- (NSException *) moveToFolder: (SOGoGCSFolder *) newFolder
+{
+ NSException *ex;
+
+ ex = [self copyToFolder: newFolder];
+
+ if (!ex)
+ ex = [self delete];
+
+ return ex;
}
/* DAV */
@@ -100,7 +116,7 @@
vlist = [self vList];
- [self saveContentString: [vlist versitString]];
+ [self saveComponent: vlist];
}
@end
diff --git a/SoObjects/Contacts/SOGoContactLDIFEntry.m b/SoObjects/Contacts/SOGoContactLDIFEntry.m
index dc8ec3431..4e456cbed 100644
--- a/SoObjects/Contacts/SOGoContactLDIFEntry.m
+++ b/SoObjects/Contacts/SOGoContactLDIFEntry.m
@@ -1,9 +1,6 @@
/* SOGoContactLDIFEntry.m - this file is part of SOGo
*
- * Copyright (C) 2006-2012 Inverse inc.
- *
- * Author: Wolfgang Sourdeau
- * Ludovic Marcotte
+ * Copyright (C) 2006-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -231,7 +228,7 @@
[NSString stringWithFormat: @"%@.vcf", newUID]
inContainer: newFolder];
- return [newContact saveContentString: [newCard versitString]];
+ return [newContact saveComponent: newCard];
}
@end
diff --git a/SoObjects/Mailer/Catalan.lproj/Localizable.strings b/SoObjects/Mailer/Catalan.lproj/Localizable.strings
index b58d9f585..e2cedc99a 100644
--- a/SoObjects/Mailer/Catalan.lproj/Localizable.strings
+++ b/SoObjects/Mailer/Catalan.lproj/Localizable.strings
@@ -1,2 +1,2 @@
-"SieveFolderName" = "Filtres";
"OtherUsersFolderName" = "Altres usuaris";
+"SharedFoldersName" = "Carpetes compartides";
diff --git a/SoObjects/Mailer/NorwegianBokmal.lproj/Localizable.strings b/SoObjects/Mailer/NorwegianBokmal.lproj/Localizable.strings
index 37a85656e..bcd8b0460 100644
--- a/SoObjects/Mailer/NorwegianBokmal.lproj/Localizable.strings
+++ b/SoObjects/Mailer/NorwegianBokmal.lproj/Localizable.strings
@@ -1,2 +1,2 @@
-"SieveFolderName" = "Filter";
"OtherUsersFolderName" = "Andre brukere";
+"SharedFoldersName" = "Delte mapper";
diff --git a/SoObjects/Mailer/SOGoDraftObject.h b/SoObjects/Mailer/SOGoDraftObject.h
index 0405a8ebe..cf4e06d27 100644
--- a/SoObjects/Mailer/SOGoDraftObject.h
+++ b/SoObjects/Mailer/SOGoDraftObject.h
@@ -53,6 +53,7 @@
{
NSString *path;
int IMAP4ID;
+ int sourceIMAP4ID;
NSMutableDictionary *headers;
NSString *inReplyTo;
NSString *text;
@@ -87,6 +88,9 @@
- (void) setSourceFolder: (NSString *) newSourceFolder;
- (NSString *) sourceFolder;
+- (void) setSourceIMAP4ID: (int) newSourceIMAPID;
+- (int) sourceIMAP4ID;
+
- (void) setIMAP4ID: (int) newIMAPID;
- (int) IMAP4ID;
diff --git a/SoObjects/Mailer/SOGoDraftObject.m b/SoObjects/Mailer/SOGoDraftObject.m
index 4d0f9aa38..b1cb2a2cc 100644
--- a/SoObjects/Mailer/SOGoDraftObject.m
+++ b/SoObjects/Mailer/SOGoDraftObject.m
@@ -197,6 +197,7 @@ static NSString *userAgent = nil;
{
if ((self = [super init]))
{
+ sourceIMAP4ID = -1;
IMAP4ID = -1;
headers = [NSMutableDictionary new];
text = @"";
@@ -234,8 +235,7 @@ static NSString *userAgent = nil;
{
if (!path)
{
- path = [[self userSpoolFolderPath] stringByAppendingPathComponent:
- nameInContainer];
+ path = [[self userSpoolFolderPath] stringByAppendingPathComponent: nameInContainer];
[path retain];
}
@@ -466,6 +466,9 @@ static NSString *userAgent = nil;
forKey: @"isHTML"];
if (inReplyTo)
[infos setObject: inReplyTo forKey: @"inReplyTo"];
+ if (sourceIMAP4ID > -1)
+ [infos setObject: [NSString stringWithFormat: @"%i", sourceIMAP4ID]
+ forKey: @"sourceIMAP4ID"];
if (IMAP4ID > -1)
[infos setObject: [NSString stringWithFormat: @"%i", IMAP4ID]
forKey: @"IMAP4ID"];
@@ -513,6 +516,10 @@ static NSString *userAgent = nil;
[self setText: value];
isHTML = [[infoDict objectForKey: @"isHTML"] boolValue];
+ value = [infoDict objectForKey: @"sourceIMAP4ID"];
+ if (value)
+ [self setSourceIMAP4ID: [value intValue]];
+
value = [infoDict objectForKey: @"IMAP4ID"];
if (value)
[self setIMAP4ID: [value intValue]];
@@ -564,6 +571,22 @@ static NSString *userAgent = nil;
[self debugWithFormat: @"Note: info object does not yet exist: %@", p];
}
+//
+//
+//
+- (void) setSourceIMAP4ID: (int) newSourceIMAP4ID
+{
+ sourceIMAP4ID = newSourceIMAP4ID;
+}
+
+//
+//
+//
+- (int) sourceIMAP4ID
+{
+ return sourceIMAP4ID;
+}
+
//
//
//
@@ -610,7 +633,7 @@ static NSString *userAgent = nil;
{
if (IMAP4ID > -1)
error = [imap4 markURLDeleted: [self imap4URL]];
- IMAP4ID = [self IMAP4IDFromAppendResult: result];
+ [self setIMAP4ID: [self IMAP4IDFromAppendResult: result]];
if (imap4URL)
{
// Invalidate the IMAP message URL since the message ID has changed
@@ -902,9 +925,7 @@ static NSString *userAgent = nil;
[self setHeaders: info];
[self setText: [sourceMail contentForEditing]];
- [self setSourceURL: [sourceMail imap4URLString]];
[self setIMAP4ID: [[sourceMail nameInContainer] intValue]];
- [self setSourceFolderWithMailObject: sourceMail];
[self storeInfo];
}
@@ -934,7 +955,7 @@ static NSString *userAgent = nil;
[self setHeaders: info];
[self setSourceURL: [sourceMail imap4URLString]];
[self setSourceFlag: @"Answered"];
- [self setIMAP4ID: [[sourceMail nameInContainer] intValue]];
+ [self setSourceIMAP4ID: [[sourceMail nameInContainer] intValue]];
[self setSourceFolderWithMailObject: sourceMail];
[self storeInfo];
@@ -957,7 +978,7 @@ static NSString *userAgent = nil;
[self setSourceURL: [sourceMail imap4URLString]];
[self setSourceFlag: @"$Forwarded"];
- [self setIMAP4ID: [[sourceMail nameInContainer] intValue]];
+ [self setSourceIMAP4ID: [[sourceMail nameInContainer] intValue]];
[self setSourceFolderWithMailObject: sourceMail];
/* attach message */
@@ -1812,7 +1833,7 @@ static NSString *userAgent = nil;
newContact = [contactGCSEntry objectWithName: uid
inContainer: folder];
[newContact setIsNew: YES];
- [newContact saveContentString: [card versitString]];
+ [newContact saveComponent: card];
}
}
}
diff --git a/SoObjects/SOGo/GNUmakefile.preamble b/SoObjects/SOGo/GNUmakefile.preamble
index 925df35a0..a03047c38 100644
--- a/SoObjects/SOGo/GNUmakefile.preamble
+++ b/SoObjects/SOGo/GNUmakefile.preamble
@@ -15,7 +15,6 @@ ADDITIONAL_CPPFLAGS += \
SOGo_LIBRARIES_DEPEND_UPON += \
-Wl,--no-as-needed \
- -L../../OGoContentStore/$(GNUSTEP_OBJ_DIR)/ -lOGoContentStore \
-L../../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ \
-lmemcached \
-lGDLAccess \
diff --git a/SoObjects/SOGo/SOGoCacheGCSObject.m b/SoObjects/SOGo/SOGoCacheGCSObject.m
index 03269d9d7..0b3ba25e8 100644
--- a/SoObjects/SOGo/SOGoCacheGCSObject.m
+++ b/SoObjects/SOGo/SOGoCacheGCSObject.m
@@ -456,6 +456,40 @@ static EOAttribute *textColumn = nil;
return nil;
}
+- (NSException *) destroy
+{
+ NSString *tableName, *pathValue, *sql;
+ EOAdaptorChannel *channel;
+ GCSChannelManager *cm;
+ NSException *result;
+ EOAdaptor *adaptor;
+
+ cm = [GCSChannelManager defaultChannelManager];
+ channel = [cm acquireOpenChannelForURL: [self tableUrl]];
+ tableName = [self tableName];
+
+ adaptor = [[channel adaptorContext] adaptor];
+ pathValue = [adaptor formatValue: [self path]
+ forAttribute: textColumn];
+ result = nil;
+
+ sql = [NSString stringWithFormat:
+ (@"DELETE FROM %@"
+ @" WHERE c_path = %@"),
+ tableName,
+ pathValue];
+
+ result = [channel evaluateExpressionX: sql];
+
+ if (result)
+ [self errorWithFormat: @"could not delete record %@"
+ @" in %@: %@", pathValue, tableName, result];
+
+ [cm releaseChannel: channel];
+
+ return result;
+}
+
- (void) save
{
NSString *sql;
diff --git a/SoObjects/SOGo/SOGoCacheObject.h b/SoObjects/SOGo/SOGoCacheObject.h
index 0d0a78492..d8b01c468 100644
--- a/SoObjects/SOGo/SOGoCacheObject.h
+++ b/SoObjects/SOGo/SOGoCacheObject.h
@@ -42,6 +42,8 @@
- (NSCalendarDate *) creationDate;
- (NSCalendarDate *) lastModified;
+- (NSException *) destroy;
+
@end
#endif /* SOGOCACHEOBJECT_H */
diff --git a/SoObjects/SOGo/SOGoContentObject.h b/SoObjects/SOGo/SOGoContentObject.h
index 866e2dfb2..fbd0e7365 100644
--- a/SoObjects/SOGo/SOGoContentObject.h
+++ b/SoObjects/SOGo/SOGoContentObject.h
@@ -1,20 +1,21 @@
/*
Copyright (C) 2004 SKYRIX Software AG
+ Copyright (C) 2005-2014 Inverse inc.
- This file is part of OpenGroupware.org.
+ This file is part of SOGo.
- OGo is free software; you can redistribute it and/or modify it under
+ SOGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
- OGo is distributed in the hope that it will be useful, but WITHOUT ANY
+ SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with OGo; see the file COPYING. If not, write to the
+ License along with SOGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
@@ -50,6 +51,7 @@
- (id) initWithName: (NSString *) newName
andContent: (NSString *) newContent
inContainer: (SOGoGCSFolder *) newContainer;
+- (Class *) parsingClass;
/* content */
@@ -62,9 +64,9 @@
- (NSCalendarDate *) lastModified;
- (NSString *) contentAsString;
-- (NSException *) saveContentString: (NSString *) _str
- baseVersion: (unsigned int) _baseVersion;
-- (NSException *) saveContentString: (NSString *)_str;
+- (NSException *) saveComponent: (id) theComponent
+ baseVersion: (unsigned int) _baseVersion;
+- (NSException *) saveComponent: (id) theComponent;
- (id) PUTAction: (WOContext *) _ctx;
diff --git a/SoObjects/SOGo/SOGoContentObject.m b/SoObjects/SOGo/SOGoContentObject.m
index b1afaa699..088fe522e 100644
--- a/SoObjects/SOGo/SOGoContentObject.m
+++ b/SoObjects/SOGo/SOGoContentObject.m
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2006-2013 Inverse inc.
+ Copyright (C) 2006-2014 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of SOGo.
@@ -32,6 +32,9 @@
#import
#import
+#import
+#import
+
#import "NSCalendarDate+SOGo.h"
#import "SOGoCache.h"
#import "SOGoGCSFolder.h"
@@ -87,6 +90,13 @@
return self;
}
+- (Class *) parsingClass
+{
+ [self subclassResponsibility: _cmd];
+
+ return nil;
+}
+
- (void) _setRecord: (NSDictionary *) objectRecord
{
id data;
@@ -187,16 +197,18 @@
return content;
}
-- (NSException *) saveContentString: (NSString *) newContent
- baseVersion: (unsigned int) newVersion
+- (NSException *) saveComponent: (id) theComponent
+ baseVersion: (unsigned int) newVersion
{
/* Note: "iCal multifolder saves" are implemented in the apt subclass! */
GCSFolder *folder;
NSException *ex;
NSCalendarDate *now;
+ NSString *newContent;
ex = nil;
-
+
+ newContent = [theComponent versitString];
now = [NSCalendarDate calendarDate];
if (!content)
ASSIGN (creationDate, now);
@@ -208,8 +220,10 @@
if (folder)
{
ex = [folder writeContent: newContent
- toName: nameInContainer
- baseVersion: &version];
+ fromComponent: theComponent
+ container: container
+ toName: nameInContainer
+ baseVersion: &version];
if (ex)
[self errorWithFormat:@"write failed: %@", ex];
}
@@ -223,9 +237,9 @@
return ex;
}
-- (NSException *) saveContentString: (NSString *) newContent
+- (NSException *) saveComponent: (id) theComponent
{
- return [self saveContentString: newContent baseVersion: version];
+ return [self saveComponent: theComponent baseVersion: version];
}
/* actions */
@@ -239,17 +253,7 @@
- (NSException *) moveToFolder: (SOGoGCSFolder *) newFolder
{
- SOGoContentObject *newObject;
- NSException *ex;
-
- newObject = [[self class] objectWithName: nameInContainer
- inContainer: newFolder];
- [newObject setIsNew: YES];
- ex = [newObject saveContentString: content];
- if (!ex)
- ex = [self delete];
-
- return ex;
+ [self subclassResponsibility: _cmd];
}
- (NSException *) delete
@@ -341,8 +345,8 @@
/* attempt a save */
- error = [self saveContentString: [rq contentAsString]
- baseVersion: baseVersion];
+ error = [self saveComponent: [[self parsingClass] parseSingleFromSource: [rq contentAsString]]
+ baseVersion: baseVersion];
if (error)
response = (WOResponse *) error;
else
diff --git a/SoObjects/SOGo/SOGoDefaults.plist b/SoObjects/SOGo/SOGoDefaults.plist
index d23fa971a..17388f261 100644
--- a/SoObjects/SOGo/SOGoDefaults.plist
+++ b/SoObjects/SOGo/SOGoDefaults.plist
@@ -55,11 +55,11 @@
SOGoIMAPServer = "localhost";
SOGoMailDomain = "localhost";
SOGoSelectedAddressBook = "collected";
- SOGoMailMessageCheck = "manually";
+ SOGoRefreshViewCheck = "manually";
SOGoMailMessageForwarding = "inline";
SOGoMailReplyPlacement = "below";
SOGoMailSignaturePlacement = "below";
- SOGoMailPollingIntervals = ( 1, 2, 5, 10, 20, 30, 60 );
+ SOGoRefreshViewIntervals = ( 1, 2, 5, 10, 20, 30, 60 );
SOGoMailComposeMessageType = "text";
SOGoMailListViewColumnsOrder = ( "Thread", "Flagged", "Attachment", "Subject",
"From", "Unread", "Date", "Priority",
diff --git a/SoObjects/SOGo/SOGoDomainDefaults.h b/SoObjects/SOGo/SOGoDomainDefaults.h
index a55bb572c..00a79cfe9 100644
--- a/SoObjects/SOGo/SOGoDomainDefaults.h
+++ b/SoObjects/SOGo/SOGoDomainDefaults.h
@@ -66,7 +66,7 @@
- (BOOL) foldersSendEMailNotifications;
- (NSArray *) calendarDefaultRoles;
- (NSArray *) contactsDefaultRoles;
-- (NSArray *) mailPollingIntervals;
+- (NSArray *) refreshViewIntervals;
- (NSString *) subscriptionFolderFormat;
- (NSString *) calendarDefaultCategoryColor;
diff --git a/SoObjects/SOGo/SOGoDomainDefaults.m b/SoObjects/SOGo/SOGoDomainDefaults.m
index b602e8a9a..1a577c3f6 100644
--- a/SoObjects/SOGo/SOGoDomainDefaults.m
+++ b/SoObjects/SOGo/SOGoDomainDefaults.m
@@ -225,9 +225,9 @@
return [mailingMechanism lowercaseString];
}
-- (NSArray *) mailPollingIntervals
+- (NSArray *) refreshViewIntervals
{
- return [self arrayForKey: @"SOGoMailPollingIntervals"];
+ return [self arrayForKey: @"SOGoRefreshViewIntervals"];
}
- (NSString *) smtpServer
diff --git a/SoObjects/SOGo/SOGoGCSFolder.h b/SoObjects/SOGo/SOGoGCSFolder.h
index 794ebc9ac..806be9105 100644
--- a/SoObjects/SOGo/SOGoGCSFolder.h
+++ b/SoObjects/SOGo/SOGoGCSFolder.h
@@ -1,6 +1,6 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
- Copyright (C) 2006-2013 Inverse inc.
+ Copyright (C) 2006-2014 Inverse inc.
This file is part of SOGo.
@@ -53,7 +53,6 @@
NSString *ocsPath;
GCSFolder *ocsFolder;
NSMutableDictionary *childRecords;
- NSMutableDictionary *folderSubscriptionValues;
BOOL userCanAccessAllObjects; /* i.e. user obtains 'Access Object' on
subobjects */
}
@@ -102,7 +101,8 @@
withReference: (NSString *) reference;
- (BOOL) subscribeUserOrGroup: (NSString *) theIdentifier
- reallyDo: (BOOL) reallyDo;
+ reallyDo: (BOOL) reallyDo
+ response: (WOResponse *) theResponse;
- (BOOL) userIsSubscriber: (NSString *) subscribingUser;
- (void) initializeQuickTablesAclsInContext: (WOContext *) localContext;
diff --git a/SoObjects/SOGo/SOGoGCSFolder.m b/SoObjects/SOGo/SOGoGCSFolder.m
index b0110f58d..e128f7424 100644
--- a/SoObjects/SOGo/SOGoGCSFolder.m
+++ b/SoObjects/SOGo/SOGoGCSFolder.m
@@ -196,7 +196,6 @@ static NSArray *childRecordFields = nil;
ocsPath = nil;
ocsFolder = nil;
childRecords = [NSMutableDictionary new];
- folderSubscriptionValues = nil;
userCanAccessAllObjects = NO;
}
@@ -208,7 +207,6 @@ static NSArray *childRecordFields = nil;
[ocsFolder release];
[ocsPath release];
[childRecords release];
- [folderSubscriptionValues release];
[super dealloc];
}
@@ -216,18 +214,17 @@ static NSArray *childRecordFields = nil;
- (void) setFolderPropertyValue: (id) theValue
inCategory: (NSString *) theKey
+ settings: (SOGoUserSettings *) theSettings
{
- SOGoUserSettings *settings;
NSMutableDictionary *folderSettings, *values;
NSString *module;
- settings = [[context activeUser] userSettings];
module = [container nameInContainer];
- folderSettings = [settings objectForKey: module];
+ folderSettings = [theSettings objectForKey: module];
if (!folderSettings)
{
folderSettings = [NSMutableDictionary dictionary];
- [settings setObject: folderSettings forKey: module];
+ [theSettings setObject: folderSettings forKey: module];
}
values = [folderSettings objectForKey: theKey];
if (theValue)
@@ -249,7 +246,19 @@ static NSArray *childRecordFields = nil;
[folderSettings removeObjectForKey: theKey];
}
- [settings synchronize];
+ [theSettings synchronize];
+}
+
+- (void) setFolderPropertyValue: (id) theValue
+ inCategory: (NSString *) theKey
+{
+ SOGoUserSettings *settings;
+
+ settings = [[context activeUser] userSettings];
+
+ [self setFolderPropertyValue: theValue
+ inCategory: theKey
+ settings: settings];
}
- (id) folderPropertyValueInCategory: (NSString *) theKey
@@ -276,39 +285,21 @@ static NSArray *childRecordFields = nil;
- (void) _setDisplayNameFromRow: (NSDictionary *) row
{
NSString *primaryDN;
- NSDictionary *ownerIdentity;
- NSString *subjectFormat;
- SOGoDomainDefaults *dd;
primaryDN = [row objectForKey: @"c_foldername"];
+
if ([primaryDN length])
- {
- displayName = [NSMutableString new];
- if ([primaryDN isEqualToString: [container defaultFolderName]])
- [displayName appendString: [self labelForKey: primaryDN
- inContext: context]];
- else
- [displayName appendString: primaryDN];
-
- if (!activeUserIsOwner)
{
- // We MUST NOT use SOGoUser instances here (by calling -primaryIdentity)
- // as it'll load user defaults and user settings which is _very costly_
- // since it involves JSON parsing and database requests
- ownerIdentity = [[SOGoUserManager sharedUserManager]
- contactInfosForUserWithUIDorEmail: owner];
-
- folderSubscriptionValues = [[NSMutableDictionary alloc] initWithObjectsAndKeys: displayName, @"FolderName",
- [ownerIdentity objectForKey: @"cn"], @"UserName",
- [ownerIdentity objectForKey: @"c_email"], @"Email", nil];
+ DESTROY(displayName);
- dd = [[context activeUser] domainDefaults];
- subjectFormat = [dd subscriptionFolderFormat];
+ if ([primaryDN isEqualToString: [container defaultFolderName]])
+ displayName = [self labelForKey: primaryDN
+ inContext: context];
+ else
+ displayName = primaryDN;
- displayName = [folderSubscriptionValues keysWithFormat: subjectFormat];
- [displayName retain];
+ RETAIN(displayName);
}
- }
}
/* This method fetches the display name defined by the owner, but is also the
@@ -352,7 +343,31 @@ static NSArray *childRecordFields = nil;
- (void) _fetchDisplayNameFromSubscriber
{
+ NSDictionary *ownerIdentity, *folderSubscriptionValues;
+ NSString *displayNameFormat;
+ SOGoDomainDefaults *dd;
+
displayName = [self folderPropertyValueInCategory: @"FolderDisplayNames"];
+ if (!displayName)
+ {
+ [self _fetchDisplayNameFromOwner];
+
+ // We MUST NOT use SOGoUser instances here (by calling -primaryIdentity)
+ // as it'll load user defaults and user settings which is _very costly_
+ // since it involves JSON parsing and database requests
+ ownerIdentity = [[SOGoUserManager sharedUserManager]
+ contactInfosForUserWithUIDorEmail: owner];
+
+ folderSubscriptionValues = [[NSDictionary alloc] initWithObjectsAndKeys: displayName, @"FolderName",
+ [ownerIdentity objectForKey: @"cn"], @"UserName",
+ [ownerIdentity objectForKey: @"c_email"], @"Email", nil];
+
+ dd = [[context activeUser] domainDefaults];
+ displayNameFormat = [dd subscriptionFolderFormat];
+
+ displayName = [folderSubscriptionValues keysWithFormat: displayNameFormat];
+ }
+
[displayName retain];
}
@@ -365,6 +380,7 @@ static NSArray *childRecordFields = nil;
else
{
[self _fetchDisplayNameFromSubscriber];
+
if (!displayName)
[self _fetchDisplayNameFromOwner];
}
@@ -856,6 +872,7 @@ static NSArray *childRecordFields = nil;
- (BOOL) subscribeUserOrGroup: (NSString *) theIdentifier
reallyDo: (BOOL) reallyDo
+ response: (WOResponse *) theResponse
{
NSMutableDictionary *moduleSettings, *folderShowAlarms;
NSMutableArray *folderSubscription;
@@ -868,7 +885,7 @@ static NSArray *childRecordFields = nil;
int i;
dict = [[SOGoUserManager sharedUserManager] contactInfosForUserWithUIDorEmail: theIdentifier];
-
+
if ([[dict objectForKey: @"isGroup"] boolValue])
{
SOGoGroup *aGroup;
@@ -890,9 +907,13 @@ static NSArray *childRecordFields = nil;
else
allUsers = [NSArray array];
}
-
+
rc = NO;
+ // This is consumed by SOGo Integrator during folder subscription since v24.0.6
+ if (theResponse)
+ [theResponse appendContentString: [self displayName]];
+
for (i = 0; i < [allUsers count]; i++)
{
sogoUser = [allUsers objectAtIndex: i];
@@ -905,8 +926,7 @@ static NSArray *childRecordFields = nil;
[us setObject: moduleSettings forKey: [container nameInContainer]];
}
- folderSubscription
- = [moduleSettings objectForKey: @"SubscribedFolders"];
+ folderSubscription = [moduleSettings objectForKey: @"SubscribedFolders"];
subscriptionPointer = [self folderReference];
folderShowAlarms = [moduleSettings objectForKey: @"FolderShowAlarms"];
@@ -929,6 +949,10 @@ static NSArray *childRecordFields = nil;
forKey: @"FolderShowAlarms"];
}
+ [self setFolderPropertyValue: [self displayName]
+ inCategory: @"FolderDisplayNames"
+ settings: us];
+
[folderSubscription addObjectUniquely: subscriptionPointer];
// By default, we disable alarms on subscribed calendars
@@ -987,7 +1011,7 @@ static NSArray *childRecordFields = nil;
response = [context response];
[response setHeader: @"text/plain; charset=utf-8"
forKey: @"Content-Type"];
- [response setStatus: 204];
+ [response setStatus: 200];
currentUser = [context activeUser];
delegatedUsers = [self _parseDAVDelegatedUsers];
@@ -1002,7 +1026,8 @@ static NSArray *childRecordFields = nil;
create contention on GDNC. */
for (count = 0; count < max; count++)
[self subscribeUserOrGroup: [delegatedUsers objectAtIndex: count]
- reallyDo: reallyDo];
+ reallyDo: reallyDo
+ response: response];
}
else
{
@@ -1021,7 +1046,9 @@ static NSArray *childRecordFields = nil;
@"You cannot (un)subscribe to a folder that you own!"];
}
else
- [self subscribeUserOrGroup: userLogin reallyDo: reallyDo];
+ [self subscribeUserOrGroup: userLogin
+ reallyDo: reallyDo
+ response: response];
}
return response;
diff --git a/SoObjects/SOGo/SOGoUserDefaults.h b/SoObjects/SOGo/SOGoUserDefaults.h
index b8df5621b..4cb893b8d 100644
--- a/SoObjects/SOGo/SOGoUserDefaults.h
+++ b/SoObjects/SOGo/SOGoUserDefaults.h
@@ -117,8 +117,8 @@ extern NSString *SOGoWeekStartFirstFullWeek;
- (void) setSelectedAddressBook: (NSString *) newValue;
- (NSString *) selectedAddressBook;
-- (void) setMailMessageCheck: (NSString *) newValue;
-- (NSString *) mailMessageCheck;
+- (void) setRefreshViewCheck: (NSString *) newValue;
+- (NSString *) refreshViewCheck;
- (void) setMailComposeMessageType: (NSString *) newValue;
- (NSString *) mailComposeMessageType;
diff --git a/SoObjects/SOGo/SOGoUserDefaults.m b/SoObjects/SOGo/SOGoUserDefaults.m
index d6d1c3999..031a3283a 100644
--- a/SoObjects/SOGo/SOGoUserDefaults.m
+++ b/SoObjects/SOGo/SOGoUserDefaults.m
@@ -198,7 +198,7 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
@"SOGoLanguage", @"Language",
@"SOGoMailComposeMessageType", @"ComposeMessagesType",
@"SOGoSelectedAddressBook", @"SelectedAddressBook",
- @"SOGoMailMessageCheck", @"MessageCheck",
+ @"SOGoRefreshViewCheck", @"RefreshViewCheck",
@"SOGoMailMessageForwarding", @"MessageForwarding",
@"SOGoMailSignature", @"MailSignature",
@"SOGoMailSignaturePlacement", @"SignaturePlacement",
@@ -488,14 +488,14 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
return [self stringForKey: @"SOGoSelectedAddressBook"];
}
-- (void) setMailMessageCheck: (NSString *) newValue
+- (void) setRefreshViewCheck: (NSString *) newValue
{
- [self setObject: newValue forKey: @"SOGoMailMessageCheck"];
+ [self setObject: newValue forKey: @"SOGoRefreshViewCheck"];
}
-- (NSString *) mailMessageCheck
+- (NSString *) refreshViewCheck
{
- return [self stringForKey: @"SOGoMailMessageCheck"];
+ return [self stringForKey: @"SOGoRefreshViewCheck"];
}
- (void) setMailComposeMessageType: (NSString *) newValue
diff --git a/SoObjects/SOGo/SOGoUserFolder.m b/SoObjects/SOGo/SOGoUserFolder.m
index c450dc0cf..9292f9ffa 100644
--- a/SoObjects/SOGo/SOGoUserFolder.m
+++ b/SoObjects/SOGo/SOGoUserFolder.m
@@ -153,13 +153,15 @@
- (NSArray *) _subFoldersFromFolder: (SOGoParentFolder *) parentFolder
{
- NSMutableArray *folders;
- NSEnumerator *subfolders;
- SOGoFolder *currentFolder;
- NSString *folderName, *folderOwner;
- Class subfolderClass;
+ NSDictionary *folderSubscriptionValues, *ownerIdentity;
+ NSString *folderName, *folderOwner, *formattedName;
NSMutableDictionary *currentDictionary;
SoSecurityManager *securityManager;
+ SOGoFolder *currentFolder;
+ NSEnumerator *subfolders;
+ NSMutableArray *folders;
+ SOGoDomainDefaults *dd;
+ Class subfolderClass;
folders = [NSMutableArray array];
@@ -190,6 +192,18 @@
forKey: @"owner"];
[currentDictionary setObject: [currentFolder folderType]
forKey: @"type"];
+
+ dd = [[context activeUser] domainDefaults];
+ ownerIdentity = [[SOGoUserManager sharedUserManager]
+ contactInfosForUserWithUIDorEmail: owner];
+ folderSubscriptionValues = [[NSDictionary alloc] initWithObjectsAndKeys: [currentFolder displayName], @"FolderName",
+ [ownerIdentity objectForKey: @"cn"], @"UserName",
+ [ownerIdentity objectForKey: @"c_email"], @"Email", nil];
+
+ formattedName = [folderSubscriptionValues keysWithFormat: [dd subscriptionFolderFormat]];
+ [currentDictionary setObject: formattedName
+ forKey: @"formattedName"];
+
[folders addObject: currentDictionary];
}
}
diff --git a/SoObjects/common.make b/SoObjects/common.make
index 8dc2d8c28..31f10e1ac 100644
--- a/SoObjects/common.make
+++ b/SoObjects/common.make
@@ -20,7 +20,6 @@ ADDITIONAL_INCLUDE_DIRS += \
ADDITIONAL_LIB_DIRS += \
-L../SOGo/SOGo.framework/ \
-L../../SOGo/$(GNUSTEP_OBJ_DIR)/ \
- -L../../OGoContentStore/$(GNUSTEP_OBJ_DIR)/ \
-L../../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ \
-L/usr/local/lib
diff --git a/Tests/Integration/GNUmakefile.preamble b/Tests/Integration/GNUmakefile.preamble
index 90cc86a41..cd29c8e19 100644
--- a/Tests/Integration/GNUmakefile.preamble
+++ b/Tests/Integration/GNUmakefile.preamble
@@ -11,7 +11,6 @@ ADDITIONAL_INCLUDE_DIRS += \
ADDITIONAL_LIB_DIRS += \
-L../../SoObjects/SOGo/SOGo.framework -lSOGo \
- -L../../OGoContentStore/$(GNUSTEP_OBJ_DIR)/ -lOGoContentStore \
-L../../SOPE/GDLContentStore/$(GNUSTEP_OBJ_DIR)/ -lGDLContentStore \
-L../../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ -lNGCards \
-L/usr/local/lib -L/usr/lib -lEOControl -lNGStreams -lNGMime -lNGExtensions
diff --git a/Tests/Integration/config.py.in b/Tests/Integration/config.py.in
index 3a7d79a55..7e5c1ca78 100644
--- a/Tests/Integration/config.py.in
+++ b/Tests/Integration/config.py.in
@@ -23,6 +23,8 @@ attendee1_delegate_password = "sogo"
resource_no_overbook = "res"
resource_can_overbook = "res-nolimit"
+white_listed_attendee = '{"sogo1":"John Doe "}'
+
mailserver = "imaphost"
testput_nbrdays = 30
diff --git a/Tests/Integration/preferences.py b/Tests/Integration/preferences.py
index f66ac0dea..ab12f7894 100644
--- a/Tests/Integration/preferences.py
+++ b/Tests/Integration/preferences.py
@@ -46,7 +46,7 @@ class preferences:
self.client = webdavlib.WebDAVClient(hostname, port)
- authCookie = sogoLogin.getAuthCookie(hostname, port, username, password)
+ authCookie = sogoLogin.getAuthCookie(hostname, port, self.login, self.passw)
self.cookie = authCookie
# map between preferences/jsonDefaults and the webUI names
@@ -56,17 +56,22 @@ class preferences:
"SOGoTimeZone": "timezone",
"SOGoSieveFilters": "sieveFilters",
- # Vacation stuff
- "Vacation": "enableVacation", # to disable, don't specify it
- "autoReplyText": "autoReplyText", # string
- "autoReplyEmailAddresses": "autoReplyEmailAddresses", # LIST
- "daysBetweenResponse": "daysBetweenResponsesList",
- "ignoreLists": "ignoreLists", #bool
+ # Vacation stuff
+ "Vacation": "enableVacation", # to disable, don't specify it
+ "autoReplyText": "autoReplyText", # string
+ "autoReplyEmailAddresses": "autoReplyEmailAddresses", # LIST
+ "daysBetweenResponse": "daysBetweenResponsesList",
+ "ignoreLists": "ignoreLists", #bool
- # forward stuff
- "Forward": "enableForward", # to disable, don't specify it
- "forwardAddress": "forwardAddress",
- "keepCopy": "forwardKeepCopy",
+ # forward stuff
+ "Forward": "enableForward", # to disable, don't specify it
+ "forwardAddress": "forwardAddress",
+ "keepCopy": "forwardKeepCopy",
+
+ # Calendar stuff
+ "enablePreventInvitations": "preventInvitations",
+ "PreventInvitations": "PreventInvitations",
+ "whiteList": "whiteList",
}
def set(self, preference, value=None):
@@ -74,11 +79,11 @@ class preferences:
content=""
if isinstance(preference, dict):
for k,v in preference.items():
- content+="%s=%s&" % (self.preferencesMap[k], v)
+ content+="%s=%s&" % (self.preferencesMap[k], urllib.quote(v))
else:
# assume it is a str
formKey = self.preferencesMap[preference]
- content = "%s=%s&hasChanged=1" % (formKey, value)
+ content = "%s=%s&hasChanged=1" % (formKey, urllib.quote(value))
url = "/SOGo/so/%s/preferences" % self.login
@@ -94,7 +99,7 @@ class preferences:
raise Exception ("failure setting prefs, (code = %d)" \
% post.response["status"])
- def get(self, preference):
+ def get(self, preference=None):
url = "/SOGo/so/%s/preferences/jsonDefaults" % self.login
get = HTTPPreferencesGET (url)
get.cookie = self.cookie
@@ -102,7 +107,26 @@ class preferences:
content = simplejson.loads(get.response['body'])
result = None
try:
- result = content[preference]
+ if preference:
+ result = content[preference]
+ else:
+ result = content
+ except:
+ pass
+ return result
+
+ def get_settings(self, preference=None):
+ url = "/SOGo/so/%s/preferences/jsonSettings" % self.login
+ get = HTTPPreferencesGET (url)
+ get.cookie = self.cookie
+ self.client.execute (get)
+ content = simplejson.loads(get.response['body'])
+ result = None
+ try:
+ if preference:
+ result = content[preference]
+ else:
+ result = content
except:
pass
return result
diff --git a/Tests/Integration/test-preferences.py b/Tests/Integration/test-preferences.py
index cd1866d39..e49e82dd2 100644
--- a/Tests/Integration/test-preferences.py
+++ b/Tests/Integration/test-preferences.py
@@ -1,5 +1,5 @@
#!/usr/bin/python
-from config import hostname, port, username, password
+from config import hostname, port, username, password, white_listed_attendee
import preferences
import simplejson
@@ -35,5 +35,22 @@ class preferencesTest(unittest.TestCase):
prefText = "weird data \ ' \"; ^"
self._setTextPref(prefText)
+ def testSetPreventInvitation(self):
+ """ Set/get the PreventInvitation pref"""
+ self.prefs.set('PreventInvitations', '0')
+ notset = self.prefs.get_settings('')['Calendar']['PreventInvitations']
+ self.assertEqual(notset, 0)
+ self.prefs.set('enablePreventInvitations', '0')
+ isset = self.prefs.get_settings('')['Calendar']['PreventInvitations']
+ self.assertEqual(isset, 1)
+
+ def testPreventInvitationsWhiteList(self):
+ """Add to the PreventInvitations Whitelist"""
+ self.prefs.set("whiteList", white_listed_attendee)
+ whitelist = self.prefs.get_settings('Calendar')['PreventInvitationsWhitelist']
+ self.assertEqual(whitelist, white_listed_attendee)
+
+
+
if __name__ == "__main__":
sogotests.runTests()
diff --git a/Tests/Integration/test-prevent-invitations.py b/Tests/Integration/test-prevent-invitations.py
new file mode 100755
index 000000000..a1ec81b1f
--- /dev/null
+++ b/Tests/Integration/test-prevent-invitations.py
@@ -0,0 +1,209 @@
+#!/usr/bin/python
+from config import hostname, port, username, password, \
+ superuser, superuser_password, \
+ attendee1, attendee1_username, \
+ attendee1_password, \
+ attendee1_delegate, attendee1_delegate_username, \
+ attendee1_delegate_password, \
+ resource_no_overbook, resource_can_overbook, \
+ white_listed_attendee
+
+import preferences
+import simplejson
+import sogotests
+import unittest
+import utilities
+import datetime
+import dateutil.tz
+import vobject
+import vobject.base
+import vobject.icalendar
+import webdavlib
+import StringIO
+
+
+class preventInvitationsTest(unittest.TestCase):
+ def setUp(self):
+ self.prefs = preferences.preferences(attendee1, attendee1_password)
+ self.caldav = CalDAVSchedulingTest(self)
+
+ def tearDown(self):
+ self.prefs.set("autoReplyText", "")
+ self.prefs.set('PreventInvitations', '0')
+ self.prefs.set("whiteList", "")
+ #- Manual Cleanup, not called because classs is not derived from unittest
+ self.caldav.tearDown()
+
+ def testDontPreventInvitation(self):
+ """ Set/get the PreventInvitation pref"""
+ #- First accept the invitation
+ self.prefs.set('PreventInvitations', '0')
+ notset = self.prefs.get_settings('')['Calendar']['PreventInvitations']
+ self.assertEqual(notset, 0)
+ self.caldav.AddAttendee()
+ self.caldav.VerifyEvent()
+
+ def testPreventInvitation(self):
+ """ Set PreventInvitation and don't accept the Invitation"""
+ #- Second, enable PreventInviation and refuse it
+ self.prefs.set('enablePreventInvitations', '0')
+ isset = self.prefs.get_settings('')['Calendar']['PreventInvitations']
+ self.assertEqual(isset, 1)
+ self.caldav.AddAttendee(409)
+ self.caldav.VerifyEvent(404)
+
+ def testPreventInvitationWhiteList(self):
+ """ Set PreventInvitation add to WhiteList and accept the Invitation"""
+ #- First, add the Organiser to the Attendee's whitelist
+ self.prefs.set('enablePreventInvitations', '0')
+ self.prefs.set("whiteList", white_listed_attendee)
+ whitelist = self.prefs.get_settings('Calendar')['PreventInvitationsWhitelist']
+ self.assertEqual(whitelist, white_listed_attendee)
+
+ #- Second, try again to invite, it should work
+ self.prefs.set('enablePreventInvitations', '0')
+ isset = self.prefs.get_settings('')['Calendar']['PreventInvitations']
+ self.assertEqual(isset, 1)
+ self.caldav.AddAttendee()
+ self.caldav.VerifyEvent()
+
+
+class CalDAVSchedulingTest(object):
+ def __init__(self, parent_self):
+ self.test = parent_self # used for utilities
+ self.setUp()
+
+ def setUp(self):
+ self.superuser_client = webdavlib.WebDAVClient(hostname, port,
+ superuser, superuser_password)
+ self.client = webdavlib.WebDAVClient(hostname, port,
+ username, password)
+ self.attendee1_client = webdavlib.WebDAVClient(hostname, port,
+ attendee1_username, attendee1_password)
+ self.attendee1_delegate_client = webdavlib.WebDAVClient(hostname, port,
+ attendee1_delegate_username, attendee1_delegate_password)
+
+ utility = utilities.TestUtility(self.test, self.client)
+ (self.user_name, self.user_email) = utility.fetchUserInfo(username)
+ (self.attendee1_name, self.attendee1_email) = utility.fetchUserInfo(attendee1)
+ (self.attendee1_delegate_name, self.attendee1_delegate_email) = utility.fetchUserInfo(attendee1_delegate)
+
+ self.user_calendar = "/SOGo/dav/%s/Calendar/personal/" % username
+ self.attendee1_calendar = "/SOGo/dav/%s/Calendar/personal/" % attendee1
+ self.attendee1_delegate_calendar = "/SOGo/dav/%s/Calendar/personal/" % attendee1_delegate
+
+ # fetch non existing event to let sogo create the calendars in the db
+ self._getEvent(self.client, "%snonexistent" % self.user_calendar, exp_status=404)
+ self._getEvent(self.attendee1_client, "%snonexistent" % self.attendee1_calendar, exp_status=404)
+ self._getEvent(self.attendee1_delegate_client, "%snonexistent" %
+ self.attendee1_delegate_calendar, exp_status=404)
+
+ # list of ics used by the test.
+ # tearDown will loop over this and wipe them in all users' calendar
+ self.ics_list = []
+
+
+ def tearDown(self):
+ # delete all created events from all users' calendar
+ for ics in self.ics_list:
+ self._deleteEvent(self.superuser_client,
+ "%s%s" % (self.user_calendar, ics), None)
+ self._deleteEvent(self.superuser_client,
+ "%s%s" % (self.attendee1_calendar, ics), None)
+ self._deleteEvent(self.superuser_client,
+ "%s%s" % (self.attendee1_delegate_calendar, ics), None)
+
+ def _newEvent(self, summary="test event", uid="test", transp=0):
+ transparency = ("OPAQUE", "TRANSPARENT")
+
+ newCal = vobject.iCalendar()
+ vevent = newCal.add('vevent')
+ vevent.add('summary').value = summary
+ vevent.add('transp').value = transparency[transp]
+
+ now = datetime.datetime.now(dateutil.tz.gettz("America/Montreal"))
+ startdate = vevent.add('dtstart')
+ startdate.value = now
+ enddate = vevent.add('dtend')
+ enddate.value = now + datetime.timedelta(0, 3600)
+ vevent.add('uid').value = uid
+ vevent.add('dtstamp').value = now
+ vevent.add('last-modified').value = now
+ vevent.add('created').value = now
+ vevent.add('class').value = "PUBLIC"
+ vevent.add('sequence').value = "0"
+
+ return newCal
+
+ def _putEvent(self, client, filename, event, exp_status = 201):
+ put = webdavlib.HTTPPUT(filename, event.serialize())
+ put.content_type = "text/calendar; charset=utf-8"
+ client.execute(put)
+ if exp_status is not None:
+ self.test.assertEquals(put.response["status"], exp_status)
+
+ def _getEvent(self, client, filename, exp_status = 200):
+ get = webdavlib.HTTPGET(filename)
+ client.execute(get)
+
+ if exp_status is not None:
+ self.test.assertEquals(get.response["status"], exp_status)
+
+ if get.response["headers"]["content-type"].startswith("text/calendar"):
+ stream = StringIO.StringIO(get.response["body"])
+ event = vobject.base.readComponents(stream).next()
+ else:
+ event = None
+
+ return event
+
+ def _deleteEvent(self, client, filename, exp_status = 204):
+ delete = webdavlib.WebDAVDELETE(filename)
+ client.execute(delete)
+ if exp_status is not None:
+ self.test.assertEquals(delete.response["status"], exp_status)
+
+ def AddAttendee(self, exp_status=204):
+ """ add attendee after event creation """
+
+ # make sure the event doesn't exist
+ ics_name = "test-add-attendee.ics"
+ self.ics_list += [ics_name]
+
+ self._deleteEvent(self.client,
+ "%s%s" % (self.user_calendar,ics_name), None)
+ self._deleteEvent(self.attendee1_client,
+ "%s%s" % (self.attendee1_calendar,ics_name), None)
+
+ # 1. create an event in the organiser's calendar
+ event = self._newEvent(summary="Test add attendee", uid="Test add attendee")
+ organizer = event.vevent.add('organizer')
+ organizer.cn_param = self.user_name
+ organizer.value = self.user_email
+ self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), event)
+
+ # 2. add an attendee
+ event.add("method").value = "REQUEST"
+ attendee = event.vevent.add('attendee')
+ attendee.cn_param = self.attendee1_name
+ attendee.rsvp_param = "TRUE"
+ attendee.partstat_param = "NEEDS-ACTION"
+ attendee.value = self.attendee1_email
+ self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), event,
+ exp_status=exp_status)
+
+ #- save event for VerifyEvent
+ self.event = event
+ self.ics_name = ics_name
+
+ def VerifyEvent(self, exp_status=200):
+ # 1. verify that the attendee has the event
+ attendee_event = self._getEvent(self.attendee1_client, "%s%s" % (self.attendee1_calendar, self.ics_name), exp_status)
+
+ # 2. make sure the received event match the original one
+ if attendee_event:
+ self.test.assertEquals(self.event.vevent.uid, attendee_event.vevent.uid)
+
+
+if __name__ == "__main__":
+ sogotests.runTests()
diff --git a/Tests/Integration/test-sieve.py b/Tests/Integration/test-sieve.py
index 54620a339..55a85a4c5 100644
--- a/Tests/Integration/test-sieve.py
+++ b/Tests/Integration/test-sieve.py
@@ -73,9 +73,9 @@ class sieveTest(unittest.TestCase):
"days": preferences.daysBetweenResponseList[daysSelect],
}
- filterAdd = {"Vacation":1,
+ filterAdd = {"Vacation":"1",
"autoReplyText": vacation_msg,
- "daysBetweenResponse": daysSelect,
+ "daysBetweenResponse": "%d" % daysSelect,
"autoReplyEmailAddresses": self.user_email,
}
@@ -94,11 +94,11 @@ class sieveTest(unittest.TestCase):
"days": preferences.daysBetweenResponseList[daysSelect],
}
- filterAdd = {"Vacation":1,
+ filterAdd = {"Vacation":"1",
"autoReplyText": vacation_msg,
- "daysBetweenResponse": daysSelect,
+ "daysBetweenResponse": "%d" % daysSelect,
"autoReplyEmailAddresses": self.user_email,
- "ignoreLists": 1,
+ "ignoreLists": "1",
}
self.prefs.set(filterAdd)
@@ -112,7 +112,7 @@ class sieveTest(unittest.TestCase):
sieveScript = sieve_simple_forward % { "redirect_mailaddr": redirect_mailaddr }
- filterAdd = { "Forward": 1,
+ filterAdd = { "Forward": "1",
"forwardAddress": redirect_mailaddr,
}
@@ -126,9 +126,9 @@ class sieveTest(unittest.TestCase):
sieveScript = sieve_forward_keep % { "redirect_mailaddr": redirect_mailaddr }
- filterAdd = { "Forward": 1,
+ filterAdd = { "Forward": "1",
"forwardAddress": redirect_mailaddr,
- "keepCopy": 1,
+ "keepCopy": "1",
}
self.prefs.set(filterAdd)
diff --git a/Tests/Integration/utilities.py b/Tests/Integration/utilities.py
index 3b7f31441..850cb07a8 100644
--- a/Tests/Integration/utilities.py
+++ b/Tests/Integration/utilities.py
@@ -101,7 +101,7 @@ class TestACLUtility(TestUtility):
post = webdavlib.HTTPPOST(self.resource, subscribeQuery)
post.content_type = "application/xml; charset=\"utf-8\""
self.client.execute(post)
- self.test.assertEquals(post.response["status"], 204,
+ self.test.assertEquals(post.response["status"], 200,
"subscribtion failure to '%s' for '%s' (status: %d)"
% (self.resource, "', '".join(subscribers),
post.response["status"]))
diff --git a/Tests/Integration/webdavlib.py b/Tests/Integration/webdavlib.py
index 0e0f7c384..4d3d8311d 100644
--- a/Tests/Integration/webdavlib.py
+++ b/Tests/Integration/webdavlib.py
@@ -106,7 +106,12 @@ class WebDAVClient:
query.start = time.time()
self.conn.request(query.method, query.url,
body, self.prepare_headers(query, body))
- query.set_response(self.conn.getresponse());
+ try:
+ query.set_response(self.conn.getresponse());
+ except httplib.BadStatusLine, e:
+ print e
+ time.sleep(3)
+ query.set_response(self.conn.getresponse());
query.duration = time.time() - query.start
class HTTPSimpleQuery:
diff --git a/Tests/Unit/GNUmakefile b/Tests/Unit/GNUmakefile
index 316e5cf4e..6b99e05a5 100644
--- a/Tests/Unit/GNUmakefile
+++ b/Tests/Unit/GNUmakefile
@@ -35,7 +35,7 @@ $(TEST_TOOL)_CPPFLAGS += \
ADDITIONAL_LIB_DIRS += \
-L../../SoObjects/SOGo/SOGo.framework/Versions/Current -L../../SOPE/NGCards/obj -L../../SOPE/GDLContentStore/obj -lSOGo -lNGMime -lNGCards -lGDLContentStore -lNGExtensions -lSBJson -lobjc \
-L/usr/local/lib -lSaxObjC \
- -Wl,-rpath,../../SoObjects/SOGo/SOGo.framework/Versions/Current -Wl,-rpath,../../SOPE/NGCards/obj -Wl,-rpath,../../SOPE/GDLContentStore/obj -Wl,-rpath,../../OGoContentStore/obj
+ -Wl,-rpath,../../SoObjects/SOGo/SOGo.framework/Versions/Current -Wl,-rpath,../../SOPE/NGCards/obj -Wl,-rpath,../../SOPE/GDLContentStore/obj
ADDITIONAL_LDFLAGS += -Wl,--no-as-needed
-include GNUmakefile.preamble
diff --git a/Tools/GNUmakefile.preamble b/Tools/GNUmakefile.preamble
index 3c0700276..fc78b8b0a 100644
--- a/Tools/GNUmakefile.preamble
+++ b/Tools/GNUmakefile.preamble
@@ -11,7 +11,6 @@ ADDITIONAL_INCLUDE_DIRS += \
ADDITIONAL_LIB_DIRS += \
-L../SoObjects/SOGo/SOGo.framework -lSOGo \
- -L../OGoContentStore/$(GNUSTEP_OBJ_DIR)/ -lOGoContentStore \
-L../SOPE/GDLContentStore/$(GNUSTEP_OBJ_DIR)/ -lGDLContentStore \
-L../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ -lNGCards \
-L/usr/local/lib -L/usr/lib -lEOControl -lNGStreams -lNGMime -lNGExtensions -lNGObjWeb
diff --git a/Tools/SOGoToolRestore.m b/Tools/SOGoToolRestore.m
index 0cdda3b29..d3fb601f9 100644
--- a/Tools/SOGoToolRestore.m
+++ b/Tools/SOGoToolRestore.m
@@ -1,8 +1,6 @@
/* SOGoToolRestore.m - this file is part of SOGo
*
- * Copyright (C) 2009-2012 Inverse inc.
- *
- * Author: Wolfgang Sourdeau
+ * Copyright (C) 2009-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -43,6 +41,10 @@
#import
#import
+#import
+#import
+#import
+
#import "SOGoTool.h"
/* TODO:
@@ -116,6 +118,29 @@ typedef enum SOGoToolRestoreMode {
" sogo-tool restore -p /tmp/foo bob\n");
}
+- (Class) parsingClassForContent: (NSString *) theContent
+{
+ CardGroup *cardEntry;
+ NSString *firstTag;
+ Class objectClass;
+
+ objectClass = Nil;
+
+ cardEntry = [CardGroup parseSingleFromSource: theContent];
+ if (cardEntry)
+ {
+ firstTag = [[cardEntry tag] uppercaseString];
+ if ([firstTag isEqualToString: @"VCARD"])
+ objectClass = [NGVCard class];
+ else if ([firstTag isEqualToString: @"VLIST"])
+ objectClass = [NGVList class];
+ else
+ objectClass = [iCalCalendar class];
+ }
+
+ return objectClass;
+}
+
- (BOOL) checkDirectory
{
NSFileManager *fm;
@@ -347,11 +372,12 @@ typedef enum SOGoToolRestoreMode {
- (BOOL) restoreRecords: (NSArray *) records
ofFolder: (GCSFolder *) gcsFolder
{
- NSAutoreleasePool *pool;
NSDictionary *existingRecords, *currentRecord;
NSString *cName, *cContent;
- int count, max;
+ NSAutoreleasePool *pool;
+
unsigned int version;
+ int count, max;
BOOL rc;
if (records)
@@ -374,7 +400,10 @@ typedef enum SOGoToolRestoreMode {
{
NSLog (@"restoring record '%@'", cName);
cContent = [currentRecord objectForKey: @"c_content"];
- [gcsFolder writeContent: cContent toName: cName
+ [gcsFolder writeContent: cContent
+ fromComponent: [[self parsingClassForContent: cContent] parseSingleFromSource: cContent]
+ container: nil
+ toName: cName
baseVersion: &version];
}
}
@@ -529,14 +558,14 @@ typedef enum SOGoToolRestoreMode {
if (tables)
{
NSLog (@"Restorable folders:");
- folderPrefixLen = 1 + [userID length];
- tableKeys = [[tables allKeys] objectEnumerator];
+ folderPrefixLen = 8 + [userID length]; // tables keys start with /Users/
+ tableKeys = [[[tables allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] objectEnumerator];
while ((key = [tableKeys nextObject]))
{
currentFolder = [tables objectForKey: key];
folderKey = [key substringFromIndex: folderPrefixLen];
- NSLog (@" '%@': %@",
- [currentFolder objectForKey: @"displayname"], folderKey);
+ NSLog (@" %@ (%@)",
+ folderKey, [currentFolder objectForKey: @"displayname"]);
}
}
else
diff --git a/UI/Common/Catalan.lproj/Localizable.strings b/UI/Common/Catalan.lproj/Localizable.strings
index a29d35ddd..750183367 100644
--- a/UI/Common/Catalan.lproj/Localizable.strings
+++ b/UI/Common/Catalan.lproj/Localizable.strings
@@ -69,6 +69,7 @@
"You cannot create a list in a shared address book."
= "No podeu crear una llista en una agenda compartida.";
"Warning" = "Atenció";
+"Can't contact server" = "Ha ocorregut un error en contactar amb el servidor. Per favor, intenti-ho més tarda.";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "No teniu permís per a accedir a aquest mòdul o sistema. Contacteu amb l'administrador.";
@@ -101,10 +102,9 @@
"Due Date:" = "Data límit:";
"Location:" = "Lloc:";
-/* Mail labels */
+/* mail labels */
"Important" = "Important";
"Work" = "Feina";
-"Work" = "Feina";
"Personal" = "Personal";
"To Do" = "Per fer";
"Later" = "Més tard";
diff --git a/UI/Common/Czech.lproj/Localizable.strings b/UI/Common/Czech.lproj/Localizable.strings
index 011219d31..ef60019d4 100644
--- a/UI/Common/Czech.lproj/Localizable.strings
+++ b/UI/Common/Czech.lproj/Localizable.strings
@@ -69,6 +69,7 @@
"You cannot create a list in a shared address book."
= "Nemůžete vytvořit seznam ve sdíleném adresáři.";
"Warning" = "Upozornění";
+"Can't contact server" = "Při připojení k serveru došlo k chybě. Prosím zkuste to později.";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "Nemáte oprávnění pro přístup k tomuto modulu nebo systému. Kontaktujte prosím svého systémového administrátora.";
@@ -101,10 +102,9 @@
"Due Date:" = "Do dne:";
"Location:" = "Místo:";
-/* Mail labels */
+/* mail labels */
"Important" = "Důležitý";
"Work" = "Pracovní";
-"Work" = "Pracovní";
"Personal" = "Osobní";
"To Do" = "Třeba udělat";
"Later" = "Později";
diff --git a/UI/Common/Dutch.lproj/Localizable.strings b/UI/Common/Dutch.lproj/Localizable.strings
index 7b69510c0..b01954529 100644
--- a/UI/Common/Dutch.lproj/Localizable.strings
+++ b/UI/Common/Dutch.lproj/Localizable.strings
@@ -69,6 +69,7 @@
"You cannot create a list in a shared address book."
= "U kunt geen lijst maken in een gedeeld adresboek.";
"Warning" = "Waarschuwing";
+"Can't contact server" = "Bij het verbinden met de server is een fout opgetreden, probeer het alter opnieuw.";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "U heeft geen toegang tot deze module of dit systeem. Neem contact op met uw systeembeheerder.";
@@ -101,10 +102,9 @@
"Due Date:" = "Verloopdatum:";
"Location:" = "Plaats:";
-/* Mail labels */
+/* mail labels */
"Important" = "Belangrijk";
"Work" = "Werk";
-"Work" = "Werk";
"Personal" = "Persoonlijk";
"To Do" = "Te doen";
"Later" = "Later";
diff --git a/UI/Common/Finnish.lproj/Localizable.strings b/UI/Common/Finnish.lproj/Localizable.strings
index dccd332d8..b4d89b9f4 100644
--- a/UI/Common/Finnish.lproj/Localizable.strings
+++ b/UI/Common/Finnish.lproj/Localizable.strings
@@ -69,6 +69,7 @@
"You cannot create a list in a shared address book."
= "Et voi luoda listaa jaettuun osoitekirjaan.";
"Warning" = "Varoitus";
+"Can't contact server" = "Virhe palvelinyhteydessä. Yritä myöhemmin uudelleen.";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "Sinulla ei ole pääsyoikeuksia tähän moduliin tai järjestelmään. Ole hyvä ja ota yhteyttä järjestelmänvalvojaan. ";
@@ -102,10 +103,8 @@
"Location:" = "Sijainti:";
/* mail labels */
-/* Mail labels */
"Important" = "Tärkeä";
"Work" = "Työ";
-"Work" = "Työ";
"Personal" = "Henkilökohtainen";
"To Do" = "Tehtävä";
"Later" = "Myöhemmin";
diff --git a/UI/Common/German.lproj/Localizable.strings b/UI/Common/German.lproj/Localizable.strings
index a9f5e1458..85d47b658 100644
--- a/UI/Common/German.lproj/Localizable.strings
+++ b/UI/Common/German.lproj/Localizable.strings
@@ -13,7 +13,7 @@
"Administration" = "Administration";
"Disconnect" = "Beenden";
"Right Administration" = "Rechteadministration";
-"Log Console (dev.)" = "Journal (dev.)";
+"Log Console (dev.)" = "Journal (Entwickler)";
"User" = "Benutzer";
"Vacation message is enabled" = "Abwesenheitsmeldung ist eingeschaltet";
diff --git a/UI/Common/NorwegianBokmal.lproj/Localizable.strings b/UI/Common/NorwegianBokmal.lproj/Localizable.strings
index d73850120..3789e7797 100644
--- a/UI/Common/NorwegianBokmal.lproj/Localizable.strings
+++ b/UI/Common/NorwegianBokmal.lproj/Localizable.strings
@@ -69,6 +69,7 @@
"You cannot create a list in a shared address book."
= "Du kan ikke opprette en liste i en delt adressebok.";
"Warning" = "Advarsel";
+"Can't contact server" = "Det oppstod en feil ved opprettelse av kontakt med serveren. Vennligst prøv igjen senere.";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "Du har ikke rettigheter til modulen eller systemet. Kontakt din systemadministrator.";
@@ -101,10 +102,9 @@
"Due Date:" = "Forfallsdato:";
"Location:" = "Lokasjon:";
-/* Mail labels */
+/* mail labels */
"Important" = "Viktig";
"Work" = "Arbeid";
-"Work" = "Arbeid";
"Personal" = "Personlig";
"To Do" = "Gjøremål";
"Later" = "Senere";
diff --git a/UI/Common/Polish.lproj/Localizable.strings b/UI/Common/Polish.lproj/Localizable.strings
index a041733e5..23df39b8e 100644
--- a/UI/Common/Polish.lproj/Localizable.strings
+++ b/UI/Common/Polish.lproj/Localizable.strings
@@ -103,10 +103,8 @@
"Location:" = "Miejsce:";
/* mail labels */
-/* Mail labels */
"Important" = "Ważne";
"Work" = "Praca";
-"Work" = "Praca";
"Personal" = "Osobiste";
"To Do" = "Do zrobienia";
"Later" = "Później";
diff --git a/UI/Common/SpanishSpain.lproj/Localizable.strings b/UI/Common/SpanishSpain.lproj/Localizable.strings
index 1be575659..8bf18963b 100644
--- a/UI/Common/SpanishSpain.lproj/Localizable.strings
+++ b/UI/Common/SpanishSpain.lproj/Localizable.strings
@@ -69,6 +69,7 @@
"You cannot create a list in a shared address book."
= "No es posible crear una lista en una libreta de direcciones compartida.";
"Warning" = "Aviso";
+"Can't contact server" = "Ha ocurrido un error al contactar al servidor. Prueba otra vez mas tarde.";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "No esta permitido el acceso a este módulo o éste sistema. Por favor contacte con su administrador de sistemas.";
@@ -101,10 +102,9 @@
"Due Date:" = "Vencimiento:";
"Location:" = "Lugar:";
-/* Mail labels */
+/* mail labels */
"Important" = "Importante";
"Work" = "Trabajo";
-"Work" = "Trabajo";
"Personal" = "Personal";
"To Do" = "Por hacer";
"Later" = "Más tarde";
diff --git a/UI/Common/UIxAclEditor.m b/UI/Common/UIxAclEditor.m
index a50e0ff07..8c39a7ebd 100644
--- a/UI/Common/UIxAclEditor.m
+++ b/UI/Common/UIxAclEditor.m
@@ -1,8 +1,6 @@
/* UIxAclEditor.m - this file is part of SOGo
*
- * Copyright (C) 2006-2010 Inverse inc.
- *
- * Author: Wolfgang Sourdeau
+ * Copyright (C) 2006-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -138,7 +136,7 @@
- (BOOL) canSubscribeUsers
{
return [[self clientObject]
- respondsToSelector: @selector (subscribeUserOrGroup:reallyDo:)];
+ respondsToSelector: @selector (subscribeUserOrGroup:reallyDo:response:)];
}
- (BOOL) currentUserIsSubscribed
diff --git a/UI/Common/UIxFolderActions.m b/UI/Common/UIxFolderActions.m
index fb0a95eeb..374be4be8 100644
--- a/UI/Common/UIxFolderActions.m
+++ b/UI/Common/UIxFolderActions.m
@@ -89,7 +89,10 @@
}
else
{
- [clientObject subscribeUserOrGroup: login reallyDo: reallyDo];
+ [clientObject subscribeUserOrGroup: login
+ reallyDo: reallyDo
+ response: response];
+
if (isMailInvitation)
{
mailInvitationURL
@@ -373,7 +376,8 @@
max = [userIDs count];
for (count = 0; count < max; count++)
[folder subscribeUserOrGroup: [userIDs objectAtIndex: count]
- reallyDo: YES];
+ reallyDo: YES
+ response: nil];
ex = nil;
}
else
diff --git a/UI/Contacts/Catalan.lproj/Localizable.strings b/UI/Contacts/Catalan.lproj/Localizable.strings
index 2249ab989..0371cfe93 100644
--- a/UI/Contacts/Catalan.lproj/Localizable.strings
+++ b/UI/Contacts/Catalan.lproj/Localizable.strings
@@ -36,7 +36,6 @@
"delete" = "esborrar";
"edit" = "modificar";
"invalidemailwarn" = "Adreça de correu no vàlida.";
-"invaliddatewarn" = "Data no vàlida.";
"new" = "nou";
"Preferred Phone" = "Telèfon preferit";
@@ -64,6 +63,7 @@
"New Card" = "Afegir contacte";
"New List" = "Crear llista";
+"Edit" = "Modificar";
"Properties" = "Propietats";
"Sharing..." = "Compartir...";
"Write" = "Escriure";
@@ -147,7 +147,7 @@
"You cannot delete the card of \"%{0}\"."
= "No podeu esborrar el contacte \"%{0}\".";
-"Address Book Name" = "Nom de la llibreta";
+
"You cannot subscribe to a folder that you own!"
= "No us podeu subscriure a una carpeta que és vostra.";
@@ -206,3 +206,10 @@
"A total of %{0} cards were imported in the addressbook." = "S'han importat a la llibreta %{0} contactes.";
"Reload" = "Actualitzar";
+
+/* Properties window */
+"Address Book Name:" = "Nom de la llibreta d'adreces";
+"Links to this Address Book" = "Enllaços a aquesta llibreta d'adreces";
+"Authenticated User Access" = "Accés autenticat";
+"CardDAV URL: " = "URL CardDAV:";
+
diff --git a/UI/Contacts/NorwegianBokmal.lproj/Localizable.strings b/UI/Contacts/NorwegianBokmal.lproj/Localizable.strings
index c4eb8bf81..c8405b9aa 100644
--- a/UI/Contacts/NorwegianBokmal.lproj/Localizable.strings
+++ b/UI/Contacts/NorwegianBokmal.lproj/Localizable.strings
@@ -36,7 +36,6 @@
"delete" = "slett";
"edit" = "endre";
"invalidemailwarn" = "Den spesifiserte e-posten er ikke gyldig";
-"invaliddatewarn" = "Den spesifiserte datoen er ikke gyldig.";
"new" = "ny";
"Preferred Phone" = "Foretrukket telefon";
@@ -64,6 +63,7 @@
"New Card" = "Nytt adressekort";
"New List" = "Ny mailingliste";
+"Edit" = "Endre";
"Properties" = "Egenskaper";
"Sharing..." = "Deling...";
"Write" = "Skriv";
@@ -147,7 +147,7 @@
"You cannot delete the card of \"%{0}\"."
= "Du kan ikke slette adressekortet \"%{0}\".";
-"Address Book Name" = "Navn på adressebok";
+
"You cannot subscribe to a folder that you own!"
= "Du kan ikke abonnere på en mappe som du selv eier.";
@@ -206,3 +206,10 @@
"A total of %{0} cards were imported in the addressbook." = "Totalt %{0} av adressekortene ble importert til adresseboken.";
"Reload" = "Last på nytt";
+
+/* Properties window */
+"Address Book Name:" = "Addressebok navn:";
+"Links to this Address Book" = "Lenker til denne addresseboken";
+"Authenticated User Access" = "Autentisert brukertilgang";
+"CardDAV URL: " = "CardDAV URL:";
+
diff --git a/UI/Contacts/UIxContactFolderActions.m b/UI/Contacts/UIxContactFolderActions.m
index 887ce3b7b..974e7d5d0 100644
--- a/UI/Contacts/UIxContactFolderActions.m
+++ b/UI/Contacts/UIxContactFolderActions.m
@@ -1,6 +1,6 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
- Copyright (C) 2006-2013 Inverse inc.
+ Copyright (C) 2006-2014 Inverse inc.
This file is part of SOGo
@@ -280,7 +280,7 @@
inContainer: folder];
[contact setIsNew: YES];
- [contact saveContentString: [card versitString]];
+ [contact saveComponent: card];
rc = YES;
}
diff --git a/UI/Contacts/UIxListEditor.m b/UI/Contacts/UIxListEditor.m
index d9478b9cc..69d63bd21 100644
--- a/UI/Contacts/UIxListEditor.m
+++ b/UI/Contacts/UIxListEditor.m
@@ -1,9 +1,6 @@
/* UIxListEditor.m - this file is part of SOGo
*
- * Copyright (C) 2008-2012 Inverse inc.
- *
- * Author: Wolfgang Sourdeau
- * Francis Lachapelle
+ * Copyright (C) 2008-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -190,7 +187,7 @@
// Add vCard to current folder
newContact = [SOGoContactGCSEntry objectWithName: newUID
inContainer: folder];
- [newContact saveContentString: [newCard versitString]];
+ [newContact saveComponent: newCard];
// Create card reference for the list
cardReference = [NGVCardReference elementWithTag: @"card"];
diff --git a/UI/MailPartViewers/Catalan.lproj/Localizable.strings b/UI/MailPartViewers/Catalan.lproj/Localizable.strings
index c55d613ec..350a38191 100644
--- a/UI/MailPartViewers/Catalan.lproj/Localizable.strings
+++ b/UI/MailPartViewers/Catalan.lproj/Localizable.strings
@@ -12,6 +12,8 @@ publish_info_text = "El remitent us informa de l'esdeveniment adjunt.";
cancel_info_text = "La vostra invitació o l'esdeveniment han estat \ncancel·lats.";
request_info_no_attendee = "Heu proposat un esdeveniment. Rebeu aquest correu com a notificació, però no hi figureu com a participant.";
Appointment = "Cita";
+"Status Update" = "Canvi d'estat";
+was = "era";
Organizer = "Organitzador";
Time = "Hora";
diff --git a/UI/MailPartViewers/NorwegianBokmal.lproj/Localizable.strings b/UI/MailPartViewers/NorwegianBokmal.lproj/Localizable.strings
index 2088ec87d..23ee2f68e 100644
--- a/UI/MailPartViewers/NorwegianBokmal.lproj/Localizable.strings
+++ b/UI/MailPartViewers/NorwegianBokmal.lproj/Localizable.strings
@@ -12,6 +12,8 @@ publish_info_text = "Avsenderen informerer deg om vedlagte arrangement.";
cancel_info_text = "Din invitasjon eller hele arrangementet er avlyst.";
request_info_no_attendee = "foreslår et møte til deltakerne. Du har fått informasjon, men er ikke planlagt som en deltaker.";
Appointment = "Møte";
+"Status Update" = "Status oppdatering";
+was = "var";
Organizer = "Arrangør";
Time = "Tid";
diff --git a/UI/MailPartViewers/UIxMailPartHTMLViewer.m b/UI/MailPartViewers/UIxMailPartHTMLViewer.m
index 7160f6ba2..09d48ae5a 100644
--- a/UI/MailPartViewers/UIxMailPartHTMLViewer.m
+++ b/UI/MailPartViewers/UIxMailPartHTMLViewer.m
@@ -146,34 +146,34 @@ static NSData* _sanitizeContent(NSData *theData)
const char *bytes;
char *buf;
int i, j, len;
- BOOL found_delimiter;
+ BOOL found_delimiter, in_meta;
d = [NSMutableData dataWithData: theData];
bytes = [d bytes];
len = [d length];
i = 0;
+ in_meta = NO;
+
while (i < len)
{
- // We check if we see in which case, we don't do any kind
- // of substitution there after.
- if (i < len-6)
+ // We check if we see in which case, we substitute de charset= stuff.
+ if (i < len-5)
{
if ((*bytes == '<') &&
- (*(bytes+1) == '/') &&
- (*(bytes+2) == 'h' || *(bytes+2) == 'H') &&
- (*(bytes+3) == 'e' || *(bytes+3) == 'E') &&
- (*(bytes+4) == 'a' || *(bytes+4) == 'A') &&
- (*(bytes+5) == 'd' || *(bytes+5) == 'D') &&
- (*(bytes+6) == '>'))
- break;
+ (*(bytes+1) == 'm' || *(bytes+2) == 'M') &&
+ (*(bytes+2) == 'e' || *(bytes+3) == 'E') &&
+ (*(bytes+3) == 't' || *(bytes+4) == 'T') &&
+ (*(bytes+4) == 'a' || *(bytes+5) == 'A') &&
+ (*(bytes+5) == ' '))
+ in_meta = YES;
}
// We search for something like :
//
//
//
- if (i < len-9)
+ if (in_meta && i < len-9)
{
if ((*bytes == 'c' || *bytes == 'C') &&
(*(bytes+1) == 'h' || *(bytes+1) == 'H') &&
@@ -195,16 +195,18 @@ static NSData* _sanitizeContent(NSData *theData)
// We haven't found anything, let's return the data untouched
if ((i+j) >= len)
{
- found_delimiter = NO;
+ in_meta = found_delimiter = NO;
break;
}
}
if (found_delimiter)
- [d replaceBytesInRange: NSMakeRange(i, j)
- withBytes: NULL
- length: 0];
- break;
+ {
+ [d replaceBytesInRange: NSMakeRange(i, j)
+ withBytes: NULL
+ length: 0];
+ in_meta = found_delimiter = NO;
+ }
}
}
diff --git a/UI/MailPartViewers/UIxMailPartICalActions.m b/UI/MailPartViewers/UIxMailPartICalActions.m
index 281ee4bdc..be8c47e73 100644
--- a/UI/MailPartViewers/UIxMailPartICalActions.m
+++ b/UI/MailPartViewers/UIxMailPartICalActions.m
@@ -1,8 +1,6 @@
/* UIxMailPartICalActions.m - this file is part of SOGo
*
- * Copyright (C) 2007-2011 Inverse inc.
- *
- * Author: Wolfgang Sourdeau
+ * Copyright (C) 2007-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -179,7 +177,7 @@
if ([*eventObject isNew])
{
chosenEvent = emailEvent;
- [*eventObject saveContentString: [[emailEvent parent] versitString]];
+ [*eventObject saveCalendar: [emailEvent parent]];
}
else
{
@@ -209,7 +207,7 @@
parent = [calendarEvent parent];
[parent removeChild: calendarEvent];
[parent addChild: emailEvent];
- [*eventObject saveContentString: [parent versitString]];
+ [*eventObject saveCalendar: parent];
[*eventObject flush];
chosenEvent = emailEvent;
}
@@ -332,7 +330,6 @@
{
iCalEvent *emailEvent;
SOGoAppointmentObject *eventObject;
- NSString *iCalString;
WOResponse *response;
emailEvent = [self _emailEvent];
@@ -341,8 +338,7 @@
eventObject = [self _eventObjectWithUID: [emailEvent uid]];
if ([eventObject isNew])
{
- iCalString = [[emailEvent parent] versitString];
- [eventObject saveContentString: iCalString];
+ [eventObject saveCalendar: [emailEvent parent]];
response = [self responseWith204];
}
else
diff --git a/UI/MailPartViewers/product.plist b/UI/MailPartViewers/product.plist
index dd749362d..225c9e7f0 100644
--- a/UI/MailPartViewers/product.plist
+++ b/UI/MailPartViewers/product.plist
@@ -1,5 +1,5 @@
{ /* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- requires = ( MAIN );
+ requires = ( MAIN, Mailer, Appointments );
publicResources = (
);
diff --git a/UI/MailerUI/Catalan.lproj/Localizable.strings b/UI/MailerUI/Catalan.lproj/Localizable.strings
index c5c6f293c..c76770b66 100644
--- a/UI/MailerUI/Catalan.lproj/Localizable.strings
+++ b/UI/MailerUI/Catalan.lproj/Localizable.strings
@@ -79,7 +79,7 @@
"Remove this folder" = "Esborrar aquesta carpeta";
"Erase mails from this folder" = "Esborrar els correus d'aquesta carpeta";
"Expunge this folder" = "Compactar aquesta carpeta";
-"Archive This Folder" = "Arxivar aquesta carpeta";
+"Export This Folder" = "Exportar Aquesta Carpeta";
"Modify the acl of this folder" = "Modificar la llista de permisos d'aquesta carpeta";
"Saved Messages.zip" = "missatgesdesats.zip";
@@ -97,11 +97,12 @@
"Reply-To" = "Respondre a";
"Add address" = "Afegir adreça";
-"Attachments:" = "Adjunts:";
"Open" = "Obrir";
"Select All" = "Seleccionar tots";
"Attach Web Page..." = "Adjuntar pàgina Web...";
-"Attach File(s)..." = "Adjuntar fitxers...";
+"file" = "Fitxer";
+"files" = "Fitxers";
+"Save all" = "Desar Tot";
"to" = "per a";
"cc" = "cc";
@@ -252,7 +253,6 @@
"Please select only one message to print." = "Per imprimir, seleccioneu només un missatge.";
"The message you have selected doesn't exist anymore." = "El missatge seleccionat ja no existeix.";
-
"The folder with name \"%{0}\" could not be created."
= "La carpeta de nom \"%{0}\" no es pot crear.";
"This folder could not be renamed to \"%{0}\"."
@@ -279,11 +279,15 @@
"error_missingsubject" = "No heu indicat l'assumpte";
"error_missingrecipients" = "No heu indicat els destinataris";
"Send Anyway" = "Enviar igualment";
+"Error while saving the draft:" = "Error en guardar l'esborrany:";
+"Error while uploading the file \"%{0}\":" = "Error en carregar el fitxer \"%{0}\":";
+"There is an active file upload. Closing the window will interrupt it." = "Hi ha una càrrega de fitxer activa. S'interromprà si es tanca la finestra.";
/* Message sending */
"cannot send message: (smtp) all recipients discarded" = "No s'ha pogut enviar el missatge: tots els destinataris són incorrectes.";
"cannot send message (smtp) - recipients discarded:" = "No s'ha pogut enviar el missatge. Les següents adreces són incorrectes:";
"cannot send message: (smtp) error when connecting" = "No s'ha pogut enviar el missatge. Error al connectar amb el servidor SMTP.";
-"Name" = "Nom";
+/* Contacts list in mail editor */
"Email" = "Correu electrònic";
+"Name" = "Nom";
diff --git a/UI/MailerUI/English.lproj/Localizable.strings b/UI/MailerUI/English.lproj/Localizable.strings
index 345d4c09b..02466f5b5 100644
--- a/UI/MailerUI/English.lproj/Localizable.strings
+++ b/UI/MailerUI/English.lproj/Localizable.strings
@@ -13,6 +13,7 @@
"Print" = "Print";
"Stop" = "Stop";
"Write" = "Write";
+"Search" = "Search";
"Send" = "Send";
"Contacts" = "Contacts";
@@ -41,6 +42,7 @@
"Attachment" = "Attachment";
"Unread" = "Unread";
"Flagged" = "Flagged";
+"Search multiple mailboxes" = "Search multiple mailboxes";
/* Main Frame */
@@ -94,8 +96,9 @@
"To" = "To";
"Cc" = "Cc";
"Bcc" = "Bcc";
-"Reply-To" = "Reply-To";
+"Reply-To" = "Reply-To";
"Add address" = "Add address";
+"Body" = "Body";
"Open" = "Open";
"Select All" = "Select All";
@@ -237,6 +240,18 @@
"As Not Junk" = "As Not Junk";
"Run Junk Mail Controls" = "Run Junk Mail Controls";
+"Search messages in:" = "Search messages in:";
+"Search" = "Search";
+"Search subfolders" = "Search subfolders";
+"Match any of the following" = "Match any of the following";
+"Match all of the following" = "Match all of the following";
+"contains" = "contains";
+"does not contain" = "does not contain";
+"No matches found" = "No matches found";
+"results found" = "results found";
+"result found" = "result found";
+"Please specify at least one filter" = "Please specify at least one filter";
+
/* Folder operations */
"Name :" = "Name :";
"Enter the new name of your folder :"
diff --git a/UI/MailerUI/French.lproj/Localizable.strings b/UI/MailerUI/French.lproj/Localizable.strings
index d0e64a0db..b136c0a99 100644
--- a/UI/MailerUI/French.lproj/Localizable.strings
+++ b/UI/MailerUI/French.lproj/Localizable.strings
@@ -13,6 +13,7 @@
"Print" = "Imprimer";
"Stop" = "Arrêter";
"Write" = "Écrire";
+"Search" = "Recherche";
"Send" = "Envoyer";
"Contacts" = "Contacts";
@@ -41,6 +42,7 @@
"Attachment" = "Documents joints";
"Unread" = "Non lus";
"Flagged" = "Marqués";
+"Search multiple mailboxes" = "Rechercher dans plusieurs boîtes";
/* Main Frame */
@@ -94,8 +96,9 @@
"To" = "Destinataire";
"Cc" = "Copie à";
"Bcc" = "Copie cachée à";
-"Reply-To" = "Répondre à";
+"Reply-To" = "Répondre à";
"Add address" = "Ajouter Adresse";
+"Body" = "Contenu";
"Open" = "Ouvrir";
"Select All" = "Tout sélectionner";
@@ -237,6 +240,18 @@
"As Not Junk" = "Comme acceptable";
"Run Junk Mail Controls" = "Lancer le contrôle des indésirables";
+"Search messages in:" = "Rechercher dans :";
+"Search" = "Recherche";
+"Search subfolders" = "Rechercher dans les sous-dossiers";
+"Match any of the following" = "Répondant à un des critères suivants";
+"Match all of the following" = "Répondant à tous les critères suivants";
+"contains" = "contient";
+"does not contain" = "ne contient pas";
+"No matches found" = "Aucun résultat";
+"results found" = "messages trouvés";
+"result found" = "message trouvé";
+"Please specify at least one filter" = "Veuillez définir au moins un critère.";
+
/* Folder operations */
"Name :" = "Nom:";
"Enter the new name of your folder :"
diff --git a/UI/MailerUI/GNUmakefile b/UI/MailerUI/GNUmakefile
index e354d983f..851eb9abf 100644
--- a/UI/MailerUI/GNUmakefile
+++ b/UI/MailerUI/GNUmakefile
@@ -23,6 +23,7 @@ MailerUI_OBJC_FILES += \
UIxMailPopupView.m \
UIxMailMoveToPopUp.m \
UIxMailFilterPanel.m \
+ UIxMailSearch.m \
\
UIxMailAccountActions.m \
UIxMailFolderActions.m \
diff --git a/UI/MailerUI/NorwegianBokmal.lproj/Localizable.strings b/UI/MailerUI/NorwegianBokmal.lproj/Localizable.strings
index 7904d6acc..b1632f685 100644
--- a/UI/MailerUI/NorwegianBokmal.lproj/Localizable.strings
+++ b/UI/MailerUI/NorwegianBokmal.lproj/Localizable.strings
@@ -79,7 +79,7 @@
"Remove this folder" = "Fjern mappen";
"Erase mails from this folder" = "Slett meldinger fra mappen";
"Expunge this folder" = "Fjern mappen";
-"Archive This Folder" = "Arkiver denne mappen";
+"Export This Folder" = "Eksporter denne mappen";
"Modify the acl of this folder" = "Endre adgangsrettigheter til mappen";
"Saved Messages.zip" = "Lagrede Meldinger.zip";
@@ -97,11 +97,12 @@
"Reply-To" = "Svar-til";
"Add address" = "Legg til adresse";
-"Attachments:" = "Vedlegg:";
"Open" = "Åpne";
"Select All" = "Velg alle";
"Attach Web Page..." = "Legg til url...";
-"Attach File(s)..." = "Legg til fil(er)...";
+"file" = "fil";
+"files" = "filer";
+"Save all" = "Lagre alle";
"to" = "Til";
"cc" = "Kopi";
@@ -278,6 +279,9 @@
"error_missingsubject" = "Emnefelt mangler. Vil du likevel sende meldingen?";
"error_missingrecipients" = "Ingen mottakere er angitt";
"Send Anyway" = "Send likevel";
+"Error while saving the draft:" = "Problem ved lagring av utkast:";
+"Error while uploading the file \"%{0}\":" = "Problem ved opplasting av fil \"%{0}\":";
+"There is an active file upload. Closing the window will interrupt it." = "Det er en aktiv fil opplasting. Lukk vinduet for å avbryte den.";
/* Message sending */
"cannot send message: (smtp) all recipients discarded" = "Kan ikke sende melding: alle mottakeradresser er ugyldige.";
diff --git a/UI/MailerUI/Toolbars/SOGoMailFolder.toolbar b/UI/MailerUI/Toolbars/SOGoMailFolder.toolbar
index 1c9d1968d..119b2ac9b 100644
--- a/UI/MailerUI/Toolbars/SOGoMailFolder.toolbar
+++ b/UI/MailerUI/Toolbars/SOGoMailFolder.toolbar
@@ -63,5 +63,12 @@
image = "tb-mail-print-flat-24x24.png";
label = "Print";
tooltip = "Print this message"; },
+
+ { link = "#";
+ onclick = "return onSearchMail(event);";
+ cssClass = "";
+ image = "search-messages.png";
+ label = "Search";
+ tooltip = "Search multiple mailboxes"; }
)
)
diff --git a/UI/MailerUI/UIxMailActions.m b/UI/MailerUI/UIxMailActions.m
index b21cd160f..691a75f26 100644
--- a/UI/MailerUI/UIxMailActions.m
+++ b/UI/MailerUI/UIxMailActions.m
@@ -34,6 +34,7 @@
#import
#import
#import
+#import
#import
#import "../Common/WODirectAction+SOGo.h"
@@ -145,6 +146,80 @@
return response;
}
+- (void) collapseAction: (BOOL) isCollapsing
+{
+ SOGoMailObject *co;
+ NSMutableDictionary *moduleSettings, *threadsCollapsed;
+ NSMutableArray *mailboxThreadsCollapsed;
+ NSString *msguid, *currentMailbox, *currentAccount, *keyForMsgUIDs;
+ SOGoUserSettings *us;
+
+ co = [self clientObject];
+ us = [[context activeUser] userSettings];
+ if (!(moduleSettings = [us objectForKey: @"Mail"]))
+ [us setObject:[NSMutableDictionary dictionnary] forKey: @"Mail"];
+ msguid = [co nameInContainer];
+ currentMailbox = [[co container] nameInContainer];
+ currentAccount = [[[co container] container] nameInContainer];
+ keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox];
+
+ if (isCollapsing)
+ {
+ // Check if the module threadsCollapsed is created in the userSettings
+ if ((threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"]))
+ {
+ // Check if the currentMailbox already have other threads saved and add the new collapsed thread
+ if ((mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]))
+ {
+ if (![mailboxThreadsCollapsed containsObject:msguid])
+ [mailboxThreadsCollapsed addObject:msguid];
+ }
+ else
+ {
+ mailboxThreadsCollapsed = [NSMutableArray arrayWithObject:msguid];
+ [threadsCollapsed setObject:mailboxThreadsCollapsed forKey:keyForMsgUIDs];
+ }
+ }
+ else
+ {
+ // Created the module threadsCollapsed and add the new collapsed thread
+ mailboxThreadsCollapsed = [NSMutableArray arrayWithObject:msguid];
+ threadsCollapsed = [NSMutableDictionary dictionaryWithObject:mailboxThreadsCollapsed forKey:keyForMsgUIDs];
+ [moduleSettings setObject:threadsCollapsed forKey: @"threadsCollapsed"];
+ }
+ }
+ else
+ {
+ // Check if the module threadsCollapsed is created in the userSettings
+ if ((threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"]))
+ {
+ // Check if the currentMailbox already have other threads saved and remove the uncollapsed thread
+ if ((mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]))
+ {
+ [mailboxThreadsCollapsed removeObject:msguid];
+ if ([mailboxThreadsCollapsed count] == 0)
+ [threadsCollapsed removeObjectForKey:keyForMsgUIDs];
+ }
+ }
+ // TODO : Manage errors
+ }
+ [us synchronize];
+}
+
+- (id) markMessageCollapseAction
+{
+ [self collapseAction: YES];
+
+ return [self responseWith204];
+}
+
+- (id) markMessageUncollapseAction
+{
+ [self collapseAction: NO];
+
+ return [self responseWith204];
+}
+
/* SOGoDraftObject */
- (WOResponse *) editAction
{
@@ -203,74 +278,4 @@
return response;
}
-- (WOResponse *) addLabelAction
-{
- WOResponse *response;
- SOGoMailObject *co;
- NSException *error;
- NSArray *flags;
- NSString *flag;
-
- flag = [[[self->context request] formValueForKey: @"flag"] fromCSSIdentifier];
- co = [self clientObject];
- flags = [NSArray arrayWithObject: flag];
-
- error = [co addFlags: flags];
- if (error)
- response = (WOResponse *) error;
- else
- response = [self responseWith204];
-
- return response;
-}
-
-- (WOResponse *) removeLabelAction
-{
- WOResponse *response;
- SOGoMailObject *co;
- NSException *error;
- NSArray *flags;
- NSString *flag;
-
- flag = [[[self->context request] formValueForKey: @"flag"] fromCSSIdentifier];
- co = [self clientObject];
- flags = [NSArray arrayWithObject: flag];
-
- error = [co removeFlags: flags];
- if (error)
- response = (WOResponse *) error;
- else
- response = [self responseWith204];
-
- return response;
-}
-
-- (WOResponse *) removeAllLabelsAction
-{
- NSMutableArray *flags;
- WOResponse *response;
- SOGoMailObject *co;
- NSException *error;
- NSDictionary *v;
-
-
- co = [self clientObject];
-
- v = [[[context activeUser] userDefaults] mailLabelsColors];
-
- // We always unconditionally remove the Mozilla tags
- flags = [NSMutableArray arrayWithObjects: @"$Label1", @"$Label2", @"$Label3",
- @"$Label4", @"$Label5", nil];
-
- [flags addObjectsFromArray: [v allKeys]];
-
- error = [co removeFlags: flags];
- if (error)
- response = (WOResponse *) error;
- else
- response = [self responseWith204];
-
- return response;
-}
-
@end
diff --git a/UI/MailerUI/UIxMailEditor.m b/UI/MailerUI/UIxMailEditor.m
index f78843b53..5c0a7a661 100644
--- a/UI/MailerUI/UIxMailEditor.m
+++ b/UI/MailerUI/UIxMailEditor.m
@@ -1,6 +1,6 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
- Copyright (C) 2008-2011 Inverse inc.
+ Copyright (C) 2008-2014 Inverse inc.
This file is part of SOGo.
@@ -15,11 +15,12 @@
License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with OGo; see the file COPYING. If not, write to the
+ License along with SOGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
+#import
#import
#import
#import
@@ -808,7 +809,7 @@ static NSArray *infoKeys = nil;
jsonResponse = [NSDictionary dictionaryWithObjectsAndKeys:
@"success", @"status",
[co sourceFolder], @"sourceFolder",
- [NSNumber numberWithInt: [co IMAP4ID]], @"messageID",
+ [NSNumber numberWithInt: [co sourceIMAP4ID]], @"sourceMessageID",
nil];
recipients_count += [[co allRecipients] count];
diff --git a/UI/MailerUI/UIxMailFolderActions.m b/UI/MailerUI/UIxMailFolderActions.m
index 0e1ca9123..e04bf50bc 100644
--- a/UI/MailerUI/UIxMailFolderActions.m
+++ b/UI/MailerUI/UIxMailFolderActions.m
@@ -89,22 +89,45 @@
- (WOResponse *) renameFolderAction
{
SOGoMailFolder *co;
+ SOGoUserSettings *us;
WOResponse *response;
NSException *error;
- NSString *folderName;
+ NSString *newFolderName, *currentMailbox, *currentAccount, *keyForMsgUIDs, *newKeyForMsgUIDs;
+ NSMutableDictionary *moduleSettings, *threadsCollapsed;
+ NSArray *values;
co = [self clientObject];
+ //Prepare the variables need to verify if the current folder have any collapsed threads saved in userSettings
+ us = [[context activeUser] userSettings];
+ moduleSettings = [us objectForKey: @"Mail"];
+ threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"];
+ currentMailbox = [co nameInContainer];
+ currentAccount = [[co container] nameInContainer];
+ keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox];
- folderName = [[context request] formValueForKey: @"name"];
- error = [co renameTo: folderName];
+ newFolderName = [[context request] formValueForKey: @"name"];
+ newKeyForMsgUIDs = [[NSString stringWithFormat:@"/%@/folder%@", currentAccount, newFolderName] asCSSIdentifier];
+ error = [co renameTo: newFolderName];
if (error)
{
response = [self responseWithStatus: 500];
[response appendContentString: @"Unable to rename folder."];
}
else
- response = [self responseWith204];
-
+ {
+ // Verify if the current folder have any collapsed threads save under it old name and adjust the folderName
+ if (threadsCollapsed)
+ {
+ if ([threadsCollapsed objectForKey:keyForMsgUIDs])
+ {
+ values = [NSArray arrayWithArray:[threadsCollapsed objectForKey:keyForMsgUIDs]];
+ [threadsCollapsed setObject:values forKey:newKeyForMsgUIDs];
+ [threadsCollapsed removeObjectForKey:keyForMsgUIDs];
+ [us synchronize];
+ }
+ }
+ response = [self responseWith204];
+ }
return response;
}
@@ -149,10 +172,13 @@
- (WOResponse *) deleteAction
{
SOGoMailFolder *co, *inbox;
+ SOGoUserSettings *us;
WOResponse *response;
NGImap4Connection *connection;
NSException *error;
NSURL *srcURL, *destURL;
+ NSMutableDictionary *moduleSettings, *threadsCollapsed;
+ NSString *currentMailbox, *currentAccount, *keyForMsgUIDs;
co = [self clientObject];
if ([co ensureTrashFolder])
@@ -174,7 +200,23 @@
// We unsubscribe to the old one, and subscribe back to the new one
[[connection client] subscribe: [destURL path]];
[[connection client] unsubscribe: [srcURL path]];
-
+
+ // Verify if the current folder have any collapsed threads save under it name and erase it
+ us = [[context activeUser] userSettings];
+ moduleSettings = [us objectForKey: @"Mail"];
+ threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"];
+ currentMailbox = [co nameInContainer];
+ currentAccount = [[co container] nameInContainer];
+ keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox];
+
+ if (threadsCollapsed)
+ {
+ if ([threadsCollapsed objectForKey:keyForMsgUIDs])
+ {
+ [threadsCollapsed removeObjectForKey:keyForMsgUIDs];
+ [us synchronize];
+ }
+ }
response = [self responseWith204];
}
}
@@ -191,11 +233,16 @@
{
SOGoMailFolder *co;
SOGoMailAccount *account;
+ SOGoUserSettings *us;
WOResponse *response;
NSArray *uids;
NSString *value;
NSDictionary *data;
BOOL withTrash;
+ NSMutableDictionary *moduleSettings, *threadsCollapsed;
+ NSString *currentMailbox, *currentAccount, *keyForMsgUIDs;
+ NSMutableArray *mailboxThreadsCollapsed;
+ int i;
co = [self clientObject];
value = [[context request] formValueForKey: @"uid"];
@@ -217,7 +264,26 @@
andString: [data jsonRepresentation]];
}
else
- response = [self responseWith204];
+ {
+ // Verify if the message beeing delete is saved as the root of a collapsed thread
+ us = [[context activeUser] userSettings];
+ moduleSettings = [us objectForKey: @"Mail"];
+ threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"];
+ currentMailbox = [co nameInContainer];
+ currentAccount = [[co container] nameInContainer];
+ keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox];
+
+ if (threadsCollapsed)
+ {
+ if ((mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]))
+ {
+ for (i = 0; i < [uids count]; i++)
+ [mailboxThreadsCollapsed removeObject:[uids objectAtIndex:i]];
+ [us synchronize];
+ }
+ }
+ response = [self responseWith204];
+ }
}
}
else
@@ -317,9 +383,14 @@
- (WOResponse *) moveMessagesAction
{
SOGoMailFolder *co;
+ SOGoUserSettings *us;
WOResponse *response;
NSArray *uids;
NSString *value, *destinationFolder;
+ NSMutableDictionary *moduleSettings, *threadsCollapsed;
+ NSString *currentMailbox, *currentAccount, *keyForMsgUIDs;
+ NSMutableArray *mailboxThreadsCollapsed;
+ int i;
co = [self clientObject];
value = [[context request] formValueForKey: @"uid"];
@@ -331,6 +402,23 @@
uids = [value componentsSeparatedByString: @","];
response = [co moveUIDs: uids toFolder: destinationFolder inContext: context];
if (!response)
+ // Verify if the message beeing delete is saved as the root of a collapsed thread
+ us = [[context activeUser] userSettings];
+ moduleSettings = [us objectForKey: @"Mail"];
+ threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"];
+ currentMailbox = [co nameInContainer];
+ currentAccount = [[co container] nameInContainer];
+ keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox];
+
+ if (threadsCollapsed)
+ {
+ if ((mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]))
+ {
+ for (i = 0; i < [uids count]; i++)
+ [mailboxThreadsCollapsed removeObject:[uids objectAtIndex:i]];
+ [us synchronize];
+ }
+ }
response = [self responseWith204];
}
else
@@ -618,4 +706,70 @@
return response;
}
+- (WOResponse *) addOrRemoveLabelAction
+{
+ WOResponse *response;
+ WORequest *request;
+ SOGoMailFolder *co;
+ NSException *error;
+ NSArray *msgUIDs, *flags;
+ NSString *operation;
+ NSDictionary *content, *result;
+ BOOL addOrRemove;
+ NGImap4Client *client;
+
+ request = [context request];
+ content = [[request contentAsString] objectFromJSONString];
+ flags = [NSArray arrayWithObject:[content objectForKey:@"flags"]];
+ msgUIDs = [NSArray arrayWithArray:[content objectForKey:@"msgUIDs"]];
+ operation = [content objectForKey:@"operation"];
+ addOrRemove = ([operation isEqualToString:@"add"]? YES: NO);
+
+ co = [self clientObject];
+ client = [[co imap4Connection] client];
+ [[co imap4Connection] selectFolder: [co imap4URL]];
+ result = [client storeFlags:flags forUIDs:msgUIDs addOrRemove:addOrRemove];
+ if ([[result valueForKey: @"result"] boolValue])
+ response = [self responseWith204];
+ else
+ response = [self responseWithStatus:500 andJSONRepresentation:result];
+
+ return response;
+}
+
+- (WOResponse *) removeAllLabelsAction
+{
+ WOResponse *response;
+ WORequest *request;
+ SOGoMailFolder *co;
+ NGImap4Client *client;
+ NSArray *msgUIDs;
+ NSMutableArray *flags;
+ NSDictionary *v, *content, *result;
+
+ request = [context request];
+ content = [[request contentAsString] objectFromJSONString];
+ msgUIDs = [NSArray arrayWithArray:[content objectForKey:@"msgUIDs"]];
+
+ // We always unconditionally remove the Mozilla tags
+ flags = [NSMutableArray arrayWithObjects: @"$Label1", @"$Label2", @"$Label3",
+ @"$Label4", @"$Label5", nil];
+
+ co = [self clientObject];
+ v = [[[context activeUser] userDefaults] mailLabelsColors];
+ [flags addObjectsFromArray: [v allKeys]];
+
+ client = [[co imap4Connection] client];
+ [[co imap4Connection] selectFolder: [co imap4URL]];
+ result = [client storeFlags:flags forUIDs:msgUIDs addOrRemove:NO];
+
+ if ([[result valueForKey: @"result"] boolValue])
+ response = [self responseWith204];
+ else
+ response = [self responseWithStatus:500 andJSONRepresentation:result];
+
+ return response;
+}
+
+
@end
diff --git a/UI/MailerUI/UIxMailListActions.m b/UI/MailerUI/UIxMailListActions.m
index 33585e932..163ead021 100644
--- a/UI/MailerUI/UIxMailListActions.m
+++ b/UI/MailerUI/UIxMailListActions.m
@@ -54,6 +54,7 @@
#import
#import
#import
+#import
#import
#import
#import
@@ -322,27 +323,21 @@
return @"ARRIVAL";
}
-- (NSString *) imap4SortKey
-{
- NSString *sort;
-
- sort = [[context request] formValueForKey: @"sort"];
-
- return [sort uppercaseString];
-}
-
- (NSString *) imap4SortOrdering
{
- NSString *sort, *ascending;
- NSString *module;
+ WORequest *request;
+ NSString *sort, *module;
NSMutableDictionary *moduleSettings;
- BOOL asc;
+ NSDictionary *urlParams, *sortingAttributes;
SOGoUser *activeUser;
SOGoUserSettings *us;
+ BOOL asc;
- sort = [self imap4SortKey];
- ascending = [[context request] formValueForKey: @"asc"];
- asc = [ascending boolValue];
+ request = [context request];
+ urlParams = [[request contentAsString] objectFromJSONString];
+ sortingAttributes = [urlParams objectForKey:@"sortingAttributes"];
+ sort = [[sortingAttributes objectForKey:@"sort"] uppercaseString];
+ asc = [[sortingAttributes objectForKey:@"asc"] boolValue];
activeUser = [context activeUser];
module = @"Mail";
@@ -393,37 +388,47 @@
- (EOQualifier *) searchQualifier
{
- NSString *criteria, *value;
- EOQualifier *qualifier;
- WORequest *request;
-
- request = [context request];
- criteria = [request formValueForKey: @"search"];
- value = [request formValueForKey: @"value"];
- qualifier = nil;
- if ([value length])
- {
- if ([criteria isEqualToString: @"subject"])
- qualifier = [EOQualifier qualifierWithQualifierFormat:
- @"(subject doesContain: %@)", value];
- else if ([criteria isEqualToString: @"sender"])
- qualifier = [EOQualifier qualifierWithQualifierFormat:
- @"(from doesContain: %@)", value];
- else if ([criteria isEqualToString: @"subject_or_sender"])
- qualifier = [EOQualifier qualifierWithQualifierFormat:
- @"((subject doesContain: %@)"
- @" OR (from doesContain: %@))",
- value, value];
- else if ([criteria isEqualToString: @"to_or_cc"])
- qualifier = [EOQualifier qualifierWithQualifierFormat:
- @"((to doesContain: %@)"
- @" OR (cc doesContain: %@))",
- value, value];
- else if ([criteria isEqualToString: @"entire_message"])
- qualifier = [EOQualifier qualifierWithQualifierFormat:
- @"(body doesContain: %@)", value];
- }
+ EOQualifier *qualifier, *searchQualifier;
+ WORequest *request;
+ NSDictionary *sortingAttributes, *content;
+ NSArray *filters;
+ NSString *searchBy, *searchArgument, *searchInput, *searchString, *match;
+ NSMutableArray *searchArray;
+ int nbFilters = 0, i;
+ request = [context request];
+ content = [[request contentAsString] objectFromJSONString];
+ qualifier = nil;
+ searchString = nil;
+
+ if ([content objectForKey:@"filters"])
+ {
+ filters = [content objectForKey:@"filters"];
+ sortingAttributes = [content objectForKey:@"sortingAttributes"];
+ nbFilters = [filters count];
+ match = [NSString stringWithString:[sortingAttributes objectForKey:@"match"]]; // AND, OR
+
+ searchArray = [NSMutableArray arrayWithCapacity:nbFilters];
+ for (i = 0; i < nbFilters; i++)
+ {
+ searchBy = [NSString stringWithString:[[filters objectAtIndex:i] objectForKey:@"searchBy"]];
+ searchArgument = [NSString stringWithString:[[filters objectAtIndex:i] objectForKey:@"searchArgument"]];
+ searchInput = [NSString stringWithString:[[filters objectAtIndex:i] objectForKey:@"searchInput"]];
+
+ if ([[[filters objectAtIndex:i] objectForKey:@"negative"] boolValue])
+ searchString = [NSString stringWithFormat:@"(not (%@ %@: '%@'))", searchBy, searchArgument, searchInput];
+ else
+ searchString = [NSString stringWithFormat:@"(%@ %@: '%@')", searchBy, searchArgument, searchInput];
+
+ searchQualifier = [EOQualifier qualifierWithQualifierFormat:searchString];
+ [searchArray addObject:searchQualifier];
+ }
+ if ([match isEqualToString:@"OR"])
+ qualifier = [[EOOrQualifier alloc] initWithQualifierArray: searchArray];
+ else
+ qualifier = [[EOAndQualifier alloc] initWithQualifierArray: searchArray];
+ }
+
return qualifier;
}
@@ -433,25 +438,20 @@
if (!sortedUIDs)
{
- notDeleted = [EOQualifier qualifierWithQualifierFormat:
- @"(not (flags = %@))",
- @"deleted"];
+ notDeleted = [EOQualifier qualifierWithQualifierFormat: @"(not (flags = %@))", @"deleted"];
qualifier = [self searchQualifier];
if (qualifier)
- {
- fetchQualifier = [[EOAndQualifier alloc] initWithQualifiers:
- notDeleted, qualifier,
- nil];
- [fetchQualifier autorelease];
- }
+ {
+ fetchQualifier = [[EOAndQualifier alloc] initWithQualifiers: notDeleted, qualifier, nil];
+ [fetchQualifier autorelease];
+ }
else
- fetchQualifier = notDeleted;
-
- sortedUIDs
- = [mailFolder fetchUIDsMatchingQualifier: fetchQualifier
- sortOrdering: [self imap4SortOrdering]
- threaded: sortByThread];
-
+ fetchQualifier = notDeleted;
+
+ sortedUIDs = [mailFolder fetchUIDsMatchingQualifier: fetchQualifier
+ sortOrdering: [self imap4SortOrdering]
+ threaded: sortByThread];
+
[sortedUIDs retain];
}
@@ -459,7 +459,8 @@
}
/**
- * Returns a flatten representation of the messages threads as triples of
+ * Returns a
+ of the messages threads as triples of
* metadata, including the message UID, thread level and root position.
* @param _sortedUIDs the interleaved arrays representation of the messages UIDs
* @return an flatten array representation of the messages UIDs
@@ -632,11 +633,14 @@
// Retrieve messages UIDs using form parameters "sort" and "asc"
uids = [self getSortedUIDsInFolder: folder];
+
+ // Get rid of the extra parenthesis
+ // uids = [[[[uids stringValue] stringByReplacingOccurrencesOfString:@"(" withString:@""] stringByReplacingOccurrencesOfString:@")" withString:@""] componentsSeparatedByString:@","];
if (includeHeaders)
{
// Also retrieve the first headers, up to 'headersPrefetchMaxSize'
- count = [uids count];
+ count = [[uids flattenedArray] count];
if (count > headersPrefetchMaxSize) count = headersPrefetchMaxSize;
r = NSMakeRange(0, count);
headers = [self getHeadersForUIDs: [[uids flattenedArray] subarrayWithRange: r]
@@ -671,7 +675,7 @@
- (id ) getUIDsAction
{
- NSDictionary *data;
+ NSDictionary *data, *requestContent;
NSString *noHeaders;
SOGoMailFolder *folder;
WORequest *request;
@@ -679,11 +683,14 @@
request = [context request];
response = [context response];
+ requestContent = [[request contentAsString] objectFromJSONString];
+
[response setHeader: @"text/plain; charset=utf-8"
- forKey: @"content-type"];
+ forKey: @"content-type"];
+
folder = [self clientObject];
- noHeaders = [request formValueForKey: @"no_headers"];
+ noHeaders = [[requestContent objectForKey: @"sortingAttributes"] objectForKey:@"no_headers"];
data = [self getUIDsInFolder: folder
withHeaders: ([noHeaders length] == 0)];
diff --git a/UI/MailerUI/UIxMailMainFrame.m b/UI/MailerUI/UIxMailMainFrame.m
index d87fa20af..d94f90aae 100644
--- a/UI/MailerUI/UIxMailMainFrame.m
+++ b/UI/MailerUI/UIxMailMainFrame.m
@@ -119,6 +119,17 @@
return [names jsonRepresentation];
}
+- (NSString *) userNames
+{
+ NSArray *accounts, *userNames;
+
+ accounts = [[self clientObject] mailAccounts];
+ userNames = [accounts objectsForKey: @"userName" notFoundMarker: nil];
+
+ return [userNames jsonRepresentation];
+
+}
+
- (NSString *) pageFormURL
{
NSString *u;
diff --git a/UI/MailerUI/UIxMailSearch.h b/UI/MailerUI/UIxMailSearch.h
new file mode 100644
index 000000000..8eb7b03ba
--- /dev/null
+++ b/UI/MailerUI/UIxMailSearch.h
@@ -0,0 +1,29 @@
+/* UIxMailSearch.h - this file is part of SOGo
+ *
+ * Copyright (C) 2006-2014 Inverse inc.
+ *
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include
+
+@interface UIxMailSearch : UIxComponent
+{
+ id item;
+
+}
+@end
\ No newline at end of file
diff --git a/UI/MailerUI/UIxMailSearch.m b/UI/MailerUI/UIxMailSearch.m
new file mode 100644
index 000000000..a89467df2
--- /dev/null
+++ b/UI/MailerUI/UIxMailSearch.m
@@ -0,0 +1,91 @@
+/* UIxMailSearch.m - this file is part of SOGo
+ *
+ * Copyright (C) 2006-2014 Inverse inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import
+#import
+#import
+
+#import
+#import
+#import
+
+#import
+
+@implementation UIxMailSearch
+
+- (id) init
+{
+ item = nil;
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [item release];
+}
+
+- (void) setItem: (NSString *) newItem
+{
+ ASSIGN(item, newItem);
+}
+
+- (NSString *) item
+{
+ return item;
+}
+
+- (NSArray *) mailAccountsList
+{
+ SOGoMailAccount *mAccount;
+ SOGoMailAccounts *mAccounts;
+ NSString *userName, *option, *aString;
+ NSArray *accountFolders;
+ NSMutableArray *mailboxes;
+ NSDictionary *accountName;
+ int nbMailboxes, nbMailAccounts, i, j;
+
+ // Number of accounts linked with the current user
+ mAccounts = [self clientObject];
+ nbMailAccounts = [[mAccounts mailAccounts] count];
+
+ mailboxes = [NSMutableArray array];
+ for (i = 0; i < nbMailAccounts; i++)
+ {
+ accountName = [[[mAccounts mailAccounts] objectAtIndex:i] objectForKey:@"name"]; // Keys on this account = (name, port, encryption, mailboxes, serverName, identities, userName)
+ userName = [[[mAccounts mailAccounts] objectAtIndex:i] objectForKey:@"userName"];
+
+ aString = [NSString stringWithFormat:@"%i", i];
+ mAccount = [mAccounts lookupName:aString inContext: context acquire: NO];
+ accountFolders = [mAccount allFoldersMetadata];
+
+ // Number of mailboxes inside the current account
+ nbMailboxes = [accountFolders count];
+ [mailboxes addObject:accountName];
+ for (j = 0; j < nbMailboxes; j++)
+ {
+ option = [NSString stringWithFormat:@"%@%@", userName, [[accountFolders objectAtIndex:j] objectForKey:@"displayName"]];
+ [mailboxes addObject:option];
+ }
+ }
+ return mailboxes;
+}
+
+@end
\ No newline at end of file
diff --git a/UI/MailerUI/product.plist b/UI/MailerUI/product.plist
index 8b9ed30cb..4ef063eca 100644
--- a/UI/MailerUI/product.plist
+++ b/UI/MailerUI/product.plist
@@ -181,6 +181,16 @@
pageName = "UIxMailUserRightsEditor";
actionName = "saveUserRights";
};
+ addOrRemoveLabel = {
+ protectedBy = "View";
+ actionClass = "UIxMailFolderActions";
+ actionName = "addOrRemoveLabel";
+ };
+ removeAllLabels = {
+ protectedBy = "View";
+ actionClass = "UIxMailFolderActions";
+ actionName = "removeAllLabels";
+ };
};
};
@@ -252,6 +262,16 @@
actionClass = "UIxMailActions";
actionName = "forward";
};
+ markMessageUncollapse = {
+ protectedBy = "View";
+ actionClass = "UIxMailActions";
+ actionName = "markMessageUncollapse";
+ };
+ markMessageCollapse = {
+ protectedBy = "View";
+ actionClass = "UIxMailActions";
+ actionName = "markMessageCollapse";
+ };
markMessageUnflagged = {
protectedBy = "View";
actionClass = "UIxMailActions";
@@ -272,21 +292,6 @@
actionClass = "UIxMailActions";
actionName = "markMessageRead";
};
- addLabel = {
- protectedBy = "View";
- actionClass = "UIxMailActions";
- actionName = "addLabel";
- };
- removeLabel = {
- protectedBy = "View";
- actionClass = "UIxMailActions";
- actionName = "removeLabel";
- };
- removeAllLabels = {
- protectedBy = "View";
- actionClass = "UIxMailActions";
- actionName = "removeAllLabels";
- };
};
};
@@ -327,6 +332,10 @@
pageName = "UIxMailMainFrame";
actionName = "saveColumnsState";
};
+ search = {
+ protectedBy = "View";
+ pageName = "UIxMailSearch";
+ };
};
};
diff --git a/UI/MainUI/SOGoUserHomePage.m b/UI/MainUI/SOGoUserHomePage.m
index 95d7a72de..39d96ec26 100644
--- a/UI/MainUI/SOGoUserHomePage.m
+++ b/UI/MainUI/SOGoUserHomePage.m
@@ -1,8 +1,6 @@
/* SOGoUserHomePage.m - this file is part of SOGo
*
- * Copyright (C) 2007-2010 Inverse inc.
- *
- * Author: Wolfgang Sourdeau
+ * Copyright (C) 2007-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -47,6 +45,8 @@
#import
#import
+#import
+
#define intervalSeconds 900 /* 15 minutes */
@interface SOGoUserHomePage : UIxComponent
@@ -91,7 +91,7 @@
NSDictionary *record;
SOGoUser *user;
- int recordCount, recordMax, count, startInterval, endInterval, i, type, maxBookings, isResource;
+ int recordCount, recordMax, count, startInterval, endInterval, i, type, maxBookings, isResource, delta;
recordMax = [records count];
user = [SOGoUser userWithLogin: [[self clientObject] ownerInContext: context] roles: nil];
@@ -148,12 +148,18 @@
startInterval = ([currentDate timeIntervalSinceDate: startDate]
/ intervalSeconds);
+ delta = [[currentDate timeZoneDetail] timeZoneSecondsFromGMT] - [[startDate timeZoneDetail] timeZoneSecondsFromGMT];
+ startInterval += (delta/60/15);
+
currentDate = [record objectForKey: @"endDate"];
if ([currentDate earlierDate: endDate] == endDate)
endInterval = itemCount - 1;
else
endInterval = ([currentDate timeIntervalSinceDate: startDate]
/ intervalSeconds);
+
+ delta = [[currentDate timeZoneDetail] timeZoneSecondsFromGMT] - [[startDate timeZoneDetail] timeZoneSecondsFromGMT];
+ endInterval += (delta/60/15);
// Update bit string representation
// If the user is a resource, keep the sum of overlapping events
@@ -183,11 +189,31 @@
forFreeBusy: (SOGoFreeBusyObject *) fb
andContact: (NSString *) uid
{
+ NSCalendarDate *start, *end;
NSMutableArray *freeBusy;
unsigned int *freeBusyItems;
NSTimeInterval interval;
unsigned int count, intervals;
+ // We "copy" the start/end date because -fetchFreeBusyInfosFrom will mess
+ // with the timezone and we don't want that to properly calculate the delta
+ // DO NOT USE -copy HERE - it'll simply return [self retain].
+ start = [NSCalendarDate dateWithYear: [startDate yearOfCommonEra]
+ month: [startDate monthOfYear]
+ day: [startDate dayOfMonth]
+ hour: [startDate hourOfDay]
+ minute: [startDate minuteOfHour]
+ second: [startDate secondOfMinute]
+ timeZone: [startDate timeZone]];
+
+ end = [NSCalendarDate dateWithYear: [endDate yearOfCommonEra]
+ month: [endDate monthOfYear]
+ day: [endDate dayOfMonth]
+ hour: [endDate hourOfDay]
+ minute: [endDate minuteOfHour]
+ second: [endDate secondOfMinute]
+ timeZone: [endDate timeZone]];
+
interval = [endDate timeIntervalSinceDate: startDate] + 60;
intervals = interval / intervalSeconds; /* slices of 15 minutes */
@@ -195,7 +221,7 @@
freeBusyItems = NSZoneCalloc (NULL, intervals, sizeof (int));
[self _fillFreeBusyItems: freeBusyItems
count: intervals
- withRecords: [fb fetchFreeBusyInfosFrom: startDate to: endDate forContact: uid]
+ withRecords: [fb fetchFreeBusyInfosFrom: start to: end forContact: uid]
fromStartDate: startDate
toEndDate: endDate];
@@ -437,17 +463,13 @@
- (WOResponse *) _foldersResponseForResults: (NSArray *) folders
{
WOResponse *response;
- NSEnumerator *foldersEnum;
- NSDictionary *currentFolder;
response = [context response];
[response setStatus: 200];
[response setHeader: @"text/plain; charset=utf-8"
forKey: @"Content-Type"];
- foldersEnum = [folders objectEnumerator];
- while ((currentFolder = [foldersEnum nextObject]))
- [response appendContentString:
- [currentFolder keysWithFormat: @";%{displayName}:%{name}:%{type}"]];
+
+ [response appendContentString: [folders JSONRepresentation]];
return response;
}
diff --git a/UI/PreferencesUI/Arabic.lproj/Localizable.strings b/UI/PreferencesUI/Arabic.lproj/Localizable.strings
index 3b526b597..855e12075 100644
--- a/UI/PreferencesUI/Arabic.lproj/Localizable.strings
+++ b/UI/PreferencesUI/Arabic.lproj/Localizable.strings
@@ -127,14 +127,14 @@
"Show subscribed mailboxes only" = "عرض صناديق البريد المشترك بها فقط";
"Sort messages by threads" = "رتب الرسائل حسب المواضيع";
"Check for new mail:" = "تحقق من وجود بريد جديد:";
-"messagecheck_manually" = "يدوي";
-"messagecheck_every_minute" = "كل دقيقة";
-"messagecheck_every_2_minutes" = "كل 2 دقيقة";
-"messagecheck_every_5_minutes" = "كل 5 دقائق";
-"messagecheck_every_10_minutes" = "كل 10 دقائق";
-"messagecheck_every_20_minutes" = "كل 20 دقيقة";
-"messagecheck_every_30_minutes" = "كل 30 دقيقة";
-"messagecheck_once_per_hour" = "مرة كل ساعة";
+"refreshview_manually" = "يدوي";
+"refreshview_every_minute" = "كل دقيقة";
+"refreshview_every_2_minutes" = "كل 2 دقيقة";
+"refreshview_every_5_minutes" = "كل 5 دقائق";
+"refreshview_every_10_minutes" = "كل 10 دقائق";
+"refreshview_every_20_minutes" = "كل 20 دقيقة";
+"refreshview_every_30_minutes" = "كل 30 دقيقة";
+"refreshview_once_per_hour" = "مرة كل ساعة";
"Forward messages:" = "أعد توجيه الرسائل:";
"messageforward_inline" = "مضمنة";
@@ -199,7 +199,7 @@
"Contacts" = "دفتر العناوين";
"Mail" = "بريد";
"Last" = "أخر إستخدام";
-"Default module :" = "وحدة نمطية افتراضية :";
+"Default Module :" = "وحدة نمطية افتراضية :";
"Language :" = "اللغة:";
"choose" = "اختيار ...";
diff --git a/UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings b/UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings
index 933d6250f..eae77b19b 100644
--- a/UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings
+++ b/UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings
@@ -127,14 +127,14 @@
"Show subscribed mailboxes only" = "Exibir somente caixas de correio inscritas";
"Sort messages by threads" = "Ordenar mensagens por tópicos";
"Check for new mail:" = "Checar novos emails:";
-"messagecheck_manually" = "Manualmente";
-"messagecheck_every_minute" = "A cada minuto";
-"messagecheck_every_2_minutes" = "A cada 2 minutos";
-"messagecheck_every_5_minutes" = "A cada 5 minutos";
-"messagecheck_every_10_minutes" = "A cada 10 minutos";
-"messagecheck_every_20_minutes" = "A cada 20 minutos";
-"messagecheck_every_30_minutes" = "A cada 30 minutos";
-"messagecheck_once_per_hour" = "Uma vez por hora";
+"refreshview_manually" = "Manualmente";
+"refreshview_every_minute" = "A cada minuto";
+"refreshview_every_2_minutes" = "A cada 2 minutos";
+"refreshview_every_5_minutes" = "A cada 5 minutos";
+"refreshview_every_10_minutes" = "A cada 10 minutos";
+"refreshview_every_20_minutes" = "A cada 20 minutos";
+"refreshview_every_30_minutes" = "A cada 30 minutos";
+"refreshview_once_per_hour" = "Uma vez por hora";
"Forward messages:" = "Encaminhar mensagens:";
"messageforward_inline" = "No corpo da mensagem";
@@ -199,7 +199,7 @@
"Contacts" = "Catálogo";
"Mail" = "Correio";
"Last" = "Último usado";
-"Default module :" = "Módulo Padrão:";
+"Default Module :" = "Módulo Padrão:";
"Language :" = "Idioma :";
"choose" = "Escolha ...";
diff --git a/UI/PreferencesUI/Catalan.lproj/Localizable.strings b/UI/PreferencesUI/Catalan.lproj/Localizable.strings
index 2668c029b..459878dda 100644
--- a/UI/PreferencesUI/Catalan.lproj/Localizable.strings
+++ b/UI/PreferencesUI/Catalan.lproj/Localizable.strings
@@ -97,44 +97,52 @@
"Show time as busy outside working hours" = "Mostra el temps com ocupat fora de les hores de treball";
"First week of year :" = "Primera setmana de l'any: ";
"Enable reminders for Calendar items" = "Habilitar recordatoris per a ítems del calendari";
-"Play a sound when a reminder comes due"
-= "Usar senyal acústic per als recordatoris";
+"Play a sound when a reminder comes due" = "Usar senyal acústic per als recordatoris";
"Default reminder :" = "Recordatori per omissió: ";
"firstWeekOfYear_January1" = "Comença l'1 de gener";
"firstWeekOfYear_First4DayWeek" = "Primera setmana de 4 dies";
"firstWeekOfYear_FirstFullWeek" = "Primera setmana completa";
+"Prevent from being invited to appointments" = "Impedeix ser convidat a cites";
+"White list for appointment invitations:" = "Llista blanca per a invitacions a cites:";
+"Contacts Names" = "Nom dels Contactes";
+
/* Default Calendar */
"Default calendar :" = "Calendari per defecte";
"selectedCalendar" = "Calendari seleccionat";
"personalCalendar" = "Calendari personal";
"firstCalendar" = "Primer calendari habilitat";
+"reminder_NONE" = "Cap Recordatori";
"reminder_5_MINUTES_BEFORE" = "5 minuts";
"reminder_10_MINUTES_BEFORE" = "10 minuts";
"reminder_15_MINUTES_BEFORE" = "15 minuts";
"reminder_30_MINUTES_BEFORE" = "30 minuts";
+"reminder_45_MINUTES_BEFORE" = "45 minuts abans";
"reminder_1_HOUR_BEFORE" = "1 hora";
"reminder_2_HOURS_BEFORE" = "2 hores";
-"reminder_5_HOURS_BEFORE"= "5 hores";
-"reminder_15_HOURS_BEFORE"= "15 hores";
+"reminder_5_HOURS_BEFORE" = "5 hores";
+"reminder_15_HOURS_BEFORE" = "15 hores";
"reminder_1_DAY_BEFORE" = "1 dia";
"reminder_2_DAYS_BEFORE" = "2 dies";
+"reminder_1_WEEK_BEFORE" = "1 setmana abans";
/* Mailer */
+"Labels" = "Etiquetes";
"Label" = "Etiquetar";
"Show subscribed mailboxes only" = "Mostrar només les bústies subscrites";
"Sort messages by threads" = "Ordenar els missatges per temes";
+"When sending mail, add unknown recipients to my" = "En enviar un missatge, afegeix els destinataris desconeguts al meu";
"Check for new mail:" = "Comprovar nou correu: ";
-"messagecheck_manually" = "Manualment";
-"messagecheck_every_minute" = "Cada minut";
-"messagecheck_every_2_minutes" = "Cada 2 minuts";
-"messagecheck_every_5_minutes" = "Cada 5 minuts";
-"messagecheck_every_10_minutes" = "Cada 10 minuts";
-"messagecheck_every_20_minutes" = "Cada 20 minuts";
-"messagecheck_every_30_minutes" = "Cada 30 minuts";
-"messagecheck_once_per_hour" = "Cada hora";
+"refreshview_manually" = "Manualment";
+"refreshview_every_minute" = "Cada minut";
+"refreshview_every_2_minutes" = "Cada 2 minuts";
+"refreshview_every_5_minutes" = "Cada 5 minuts";
+"refreshview_every_10_minutes" = "Cada 10 minuts";
+"refreshview_every_20_minutes" = "Cada 20 minuts";
+"refreshview_every_30_minutes" = "Cada 30 minuts";
+"refreshview_once_per_hour" = "Cada hora";
"Forward messages:" = "Reenviar missatges:";
"messageforward_inline" = "Incorporats";
@@ -153,6 +161,10 @@
"displayremoteinlineimages_never" = "Mai";
"displayremoteinlineimages_always" = "Sempre";
+/* Contact */
+"Personal Address Book" = "Llibreta personal d'adreces";
+"Collected Address Book" = "Llibreta d'adreces recopilades";
+
/* IMAP Accounts */
"New Mail Account" = "Compte de correu nou";
@@ -199,7 +211,8 @@
"Contacts" = "Llibreta d'adreces";
"Mail" = "Correu";
"Last" = "Últim usat";
-"Default module :" = "Pàgina per defecte :";
+"Default Module :" = "Pàgina per defecte :";
+"SOGo Version :" = "Versió del SOGo:";
"Language :" = "Language :";
"choose" = "Choose ...";
@@ -244,6 +257,8 @@
"Active" = "Actiu";
"Move Up" = "Pujar";
"Move Down" = "Baixar";
+"Connection error" = "Error de connexió";
+"Service temporarily unavailable" = "Servei temporalment no disponible";
/* Filters - UIxFilterEditor */
"Filter name:" = "Nom del filtre:";
@@ -261,6 +276,7 @@
"To or Cc" = "A o Cc";
"Size (Kb)" = "Mida (Kb)";
"Header" = "Capçalera";
+"Body" = "Cos";
"Flag the message with:" = "Marca el missatge amb:";
"Discard the message" = "Descarta el missatge";
"File the message in:" = "Arxiva el missatge en:";
@@ -287,12 +303,8 @@
"Flagged" = "Marcat";
"Junk" = "Brossa";
"Not Junk" = "No brossa";
-"Label 1" = "Etiqueta 1";
-"Label 2" = "Etiqueta 2";
-"Label 3" = "Etiqueta 3";
-"Label 4" = "Etiqueta 4";
-"Label 5" = "Etiqueta 5";
+/* Password policy */
"The password was changed successfully." = "La contrasenya s'ha canviat correctament";
"Password must not be empty." = "La contrasenya no ha d'estar buida.";
"The passwords do not match. Please try again." = "Les contrasenyes no coincideixen. Intenta-ho de nou.";
diff --git a/UI/PreferencesUI/Czech.lproj/Localizable.strings b/UI/PreferencesUI/Czech.lproj/Localizable.strings
index bcf32ab2c..47750fbb8 100644
--- a/UI/PreferencesUI/Czech.lproj/Localizable.strings
+++ b/UI/PreferencesUI/Czech.lproj/Localizable.strings
@@ -27,7 +27,7 @@
"Add default email addresses" = "Přidat základní emailové adresy";
"Days between responses :" = "Počet dnů mezi odpověďmi :";
"Do not send responses to mailing lists" = "Neposílat odpovědi do konferencí";
-"Disable auto reply on" = "Zakázat automatické odpovědi na";
+"Disable auto reply on" = "Automatické odpovědi vypnout dne";
"Please specify your message and your email addresses for which you want to enable auto reply."
= "Prosím zadejte text zprávy a své emailové adresy, pro které chcete zasílání v nepřítomnosti použít.";
"Your vacation message must not end with a single dot on a line." = "Vaše zpráva v nepřítomnosti nesmí končit samotnou tečkou na řádce.";
@@ -104,6 +104,10 @@
"firstWeekOfYear_First4DayWeek" = "První 4-denní týden";
"firstWeekOfYear_FirstFullWeek" = "První celý týden";
+"Prevent from being invited to appointments" = "Blokovat budoucí pozvání na schůzky";
+"White list for appointment invitations:" = "Seznam povolených pro pozvání na schůzky:";
+"Contacts Names" = "Jména kontaktů";
+
/* Default Calendar */
"Default calendar :" = "Výchozí kalendář :";
"selectedCalendar" = "Zvolený kalendář";
@@ -131,14 +135,14 @@
"Sort messages by threads" = "Třídit zprávy podle souvislostí";
"When sending mail, add unknown recipients to my" = "Automaticky přidávat odchozí e-mailovou adresu do složky:";
"Check for new mail:" = "Zkontrolovat novou poštu:";
-"messagecheck_manually" = "Manuálně";
-"messagecheck_every_minute" = "Každou minutu";
-"messagecheck_every_2_minutes" = "Každé 2 minuty";
-"messagecheck_every_5_minutes" = "Každých 5 minut";
-"messagecheck_every_10_minutes" = "Každých 10 minut";
-"messagecheck_every_20_minutes" = "Každých 20 minut";
-"messagecheck_every_30_minutes" = "Každých 30 minut";
-"messagecheck_once_per_hour" = "Jednou za hodinu";
+"refreshview_manually" = "Manuálně";
+"refreshview_every_minute" = "Každou minutu";
+"refreshview_every_2_minutes" = "Každé 2 minuty";
+"refreshview_every_5_minutes" = "Každých 5 minut";
+"refreshview_every_10_minutes" = "Každých 10 minut";
+"refreshview_every_20_minutes" = "Každých 20 minut";
+"refreshview_every_30_minutes" = "Každých 30 minut";
+"refreshview_once_per_hour" = "Jednou za hodinu";
"Forward messages:" = "Přeposlat zprávy:";
"messageforward_inline" = "Do řady";
@@ -207,8 +211,8 @@
"Contacts" = "Adresář";
"Mail" = "Pošta";
"Last" = "Naposledy použitý";
-"Default module :" = "Výchozí modul :";
-"SOGo version:" = "SOGo verze:";
+"Default Module :" = "Výchozí modul :";
+"SOGo Version :" = "SOGo verze:";
"Language :" = "Jazyk :";
"choose" = "Vybrat ...";
diff --git a/UI/PreferencesUI/Danish.lproj/Localizable.strings b/UI/PreferencesUI/Danish.lproj/Localizable.strings
index ad2b8b98c..903abf10d 100644
--- a/UI/PreferencesUI/Danish.lproj/Localizable.strings
+++ b/UI/PreferencesUI/Danish.lproj/Localizable.strings
@@ -127,14 +127,14 @@
"Show subscribed mailboxes only" = "Vis kun abonnerede postkasser";
"Sort messages by threads" = "Sortér beskeder efter tråd";
"Check for new mail:" = "Tjek for ny post:";
-"messagecheck_manually" = "Manuelt";
-"messagecheck_every_minute" = "Hvert minut";
-"messagecheck_every_2_minutes" = "Hvert 2. minut";
-"messagecheck_every_5_minutes" = "Hvert 5. minut";
-"messagecheck_every_10_minutes" = "Hvert 10. minut";
-"messagecheck_every_20_minutes" = "Hvert 20. minut";
-"messagecheck_every_30_minutes" = "Hvert 30. minut";
-"messagecheck_once_per_hour" = "Én gang i timen";
+"refreshview_manually" = "Manuelt";
+"refreshview_every_minute" = "Hvert minut";
+"refreshview_every_2_minutes" = "Hvert 2. minut";
+"refreshview_every_5_minutes" = "Hvert 5. minut";
+"refreshview_every_10_minutes" = "Hvert 10. minut";
+"refreshview_every_20_minutes" = "Hvert 20. minut";
+"refreshview_every_30_minutes" = "Hvert 30. minut";
+"refreshview_once_per_hour" = "Én gang i timen";
"Forward messages:" = "Videresend beskeder:";
"messageforward_inline" = "På linie";
@@ -199,7 +199,7 @@
"Contacts" = "Adressebog";
"Mail" = "Mail";
"Last" = "Sidst anvendt";
-"Default module :" = "Standard modul:";
+"Default Module :" = "Standard modul:";
"Language :" = "Sprog:";
"choose" = "Vælg ...";
diff --git a/UI/PreferencesUI/Dutch.lproj/Localizable.strings b/UI/PreferencesUI/Dutch.lproj/Localizable.strings
index 5135fe739..12b996c4d 100644
--- a/UI/PreferencesUI/Dutch.lproj/Localizable.strings
+++ b/UI/PreferencesUI/Dutch.lproj/Localizable.strings
@@ -104,6 +104,10 @@
"firstWeekOfYear_First4DayWeek" = "Eerste week met 4 dagen";
"firstWeekOfYear_FirstFullWeek" = "Eerste volledige week";
+"Prevent from being invited to appointments" = "Voorkom uitgenodigingen voor gebeurtenissen";
+"White list for appointment invitations:" = "Whitelist voor uitnodigingen:";
+"Contacts Names" = "Contactnamen";
+
/* Default Calendar */
"Default calendar :" = "Standaardagenda:";
"selectedCalendar" = "Geselecteerde agenda";
@@ -131,14 +135,14 @@
"Sort messages by threads" = "Berichten sorteren op threads";
"When sending mail, add unknown recipients to my" = "Bij het versturen van mail, voeg onbekende ontvangers toe aan mijn";
"Check for new mail:" = "Controleren op nieuwe mail:";
-"messagecheck_manually" = "Handmatig";
-"messagecheck_every_minute" = "Iedere minuut";
-"messagecheck_every_2_minutes" = "Iedere 2 minuten";
-"messagecheck_every_5_minutes" = "Iedere 5 minuten";
-"messagecheck_every_10_minutes" = "Iedere 10 minuten";
-"messagecheck_every_20_minutes" = "Iedere 20 minuten";
-"messagecheck_every_30_minutes" = "Iedere 30 minuten";
-"messagecheck_once_per_hour" = "Ieder uur";
+"refreshview_manually" = "Handmatig";
+"refreshview_every_minute" = "Iedere minuut";
+"refreshview_every_2_minutes" = "Iedere 2 minuten";
+"refreshview_every_5_minutes" = "Iedere 5 minuten";
+"refreshview_every_10_minutes" = "Iedere 10 minuten";
+"refreshview_every_20_minutes" = "Iedere 20 minuten";
+"refreshview_every_30_minutes" = "Iedere 30 minuten";
+"refreshview_once_per_hour" = "Ieder uur";
"Forward messages:" = "Berichten doorsturen:";
"messageforward_inline" = "In het bericht";
@@ -207,8 +211,8 @@
"Contacts" = "Adresboek";
"Mail" = "Mail";
"Last" = "Laatst gebruikt";
-"Default module :" = "Standaardmodule:";
-"SOGo version:" = "SOGo versie:";
+"Default Module :" = "Standaardmodule:";
+"SOGo Version :" = "SOGo versie:";
"Language :" = "Taal:";
"choose" = "Kies...";
diff --git a/UI/PreferencesUI/English.lproj/Localizable.strings b/UI/PreferencesUI/English.lproj/Localizable.strings
index 66f8729e0..65219eec9 100644
--- a/UI/PreferencesUI/English.lproj/Localizable.strings
+++ b/UI/PreferencesUI/English.lproj/Localizable.strings
@@ -104,6 +104,10 @@
"firstWeekOfYear_First4DayWeek" = "First 4-day week";
"firstWeekOfYear_FirstFullWeek" = "First full week";
+"Prevent from being invited to appointments" = "Prevent from being invited to appointments";
+"White list for appointment invitations:" = "White list for appointment invitations:";
+"Contacts Names" = "Contacts Names";
+
/* Default Calendar */
"Default calendar :" = "Default calendar:";
"selectedCalendar" = "Selected calendar";
@@ -130,15 +134,6 @@
"Show subscribed mailboxes only" = "Show subscribed mailboxes only";
"Sort messages by threads" = "Sort messages by threads";
"When sending mail, add unknown recipients to my" = "When sending mail, add unknown recipients to my";
-"Check for new mail:" = "Check for new mail:";
-"messagecheck_manually" = "Manually";
-"messagecheck_every_minute" = "Every minute";
-"messagecheck_every_2_minutes" = "Every 2 minutes";
-"messagecheck_every_5_minutes" = "Every 5 minutes";
-"messagecheck_every_10_minutes" = "Every 10 minutes";
-"messagecheck_every_20_minutes" = "Every 20 minutes";
-"messagecheck_every_30_minutes" = "Every 30 minutes";
-"messagecheck_once_per_hour" = "Once per hour";
"Forward messages:" = "Forward messages:";
"messageforward_inline" = "Inline";
@@ -207,8 +202,8 @@
"Contacts" = "Address Book";
"Mail" = "Mail";
"Last" = "Last used";
-"Default module :" = "Default module:";
-"SOGo version:" = "SOGo version:";
+"Default Module :" = "Default Module:";
+"SOGo Version :" = "SOGo Version:";
"Language :" = "Language:";
"choose" = "Choose ...";
@@ -236,6 +231,16 @@
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
+"Refresh View :" = "Refresh View:";
+"refreshview_manually" = "Manually";
+"refreshview_every_minute" = "Every minute";
+"refreshview_every_2_minutes" = "Every 2 minutes";
+"refreshview_every_5_minutes" = "Every 5 minutes";
+"refreshview_every_10_minutes" = "Every 10 minutes";
+"refreshview_every_20_minutes" = "Every 20 minutes";
+"refreshview_every_30_minutes" = "Every 30 minutes";
+"refreshview_once_per_hour" = "Once per hour";
+
/* Return receipts */
"When I receive a request for a return receipt:" = "When I receive a request for a return receipt:";
"Never send a return receipt" = "Never send a return receipt";
diff --git a/UI/PreferencesUI/Finnish.lproj/Localizable.strings b/UI/PreferencesUI/Finnish.lproj/Localizable.strings
index 08a58f9d5..4769f69e0 100644
--- a/UI/PreferencesUI/Finnish.lproj/Localizable.strings
+++ b/UI/PreferencesUI/Finnish.lproj/Localizable.strings
@@ -104,6 +104,10 @@
"firstWeekOfYear_First4DayWeek" = "Ensimmäinen nelipäiväinen viikko";
"firstWeekOfYear_FirstFullWeek" = "Ensimmäinen täysi viikko";
+"Prevent from being invited to appointments" = "Estä tapaamiskutsut";
+"White list for appointment invitations:" = "Valkoinen lista kalenterikutsuille:";
+"Contacts Names" = "Yhteystietojen Nimet";
+
/* Default Calendar */
"Default calendar :" = "Oletuskalenteri";
"selectedCalendar" = "Valittu kalenteri";
@@ -131,14 +135,14 @@
"Sort messages by threads" = "Järjestä viestit ketjuiksi";
"When sending mail, add unknown recipients to my" = "Postia lähettäessä lisää tuntemattomat vastaanottajat";
"Check for new mail:" = "Hae uudet sähköpostit";
-"messagecheck_manually" = "Manuaalisesti";
-"messagecheck_every_minute" = "Joka minuutti";
-"messagecheck_every_2_minutes" = "Joka toinen minuutti";
-"messagecheck_every_5_minutes" = "Viiden minuutin välein";
-"messagecheck_every_10_minutes" = "10 minuutin välein";
-"messagecheck_every_20_minutes" = "20 minuutin välein";
-"messagecheck_every_30_minutes" = "Puolen tunnin välein";
-"messagecheck_once_per_hour" = "Kerran tunnissa ";
+"refreshview_manually" = "Manuaalisesti";
+"refreshview_every_minute" = "Joka minuutti";
+"refreshview_every_2_minutes" = "Joka toinen minuutti";
+"refreshview_every_5_minutes" = "Viiden minuutin välein";
+"refreshview_every_10_minutes" = "10 minuutin välein";
+"refreshview_every_20_minutes" = "20 minuutin välein";
+"refreshview_every_30_minutes" = "Puolen tunnin välein";
+"refreshview_once_per_hour" = "Kerran tunnissa ";
"Forward messages:" = "Edelleenlähetä viestit:";
"messageforward_inline" = "Tekstisisällössä";
@@ -207,8 +211,8 @@
"Contacts" = "Osoitekirja";
"Mail" = "Sähköposti";
"Last" = "Viimeksi käytetty";
-"Default module :" = "Oletusmoduli:";
-"SOGo version:" = "SOGo versio:";
+"Default Module :" = "Oletusmoduli:";
+"SOGo Version :" = "SOGo versio:";
"Language :" = "Kieli:";
"choose" = "Valitse...";
diff --git a/UI/PreferencesUI/French.lproj/Localizable.strings b/UI/PreferencesUI/French.lproj/Localizable.strings
index b4d291e61..58218f0e6 100644
--- a/UI/PreferencesUI/French.lproj/Localizable.strings
+++ b/UI/PreferencesUI/French.lproj/Localizable.strings
@@ -104,6 +104,10 @@
"firstWeekOfYear_First4DayWeek" = "Première semaine de 4 jours";
"firstWeekOfYear_FirstFullWeek" = "Première semaine entière";
+"Prevent from being invited to appointments" = "Interdire de m'inviter à des rendez-vous";
+"White list for appointment invitations:" = "Liste blanche pour les invitations";
+"Contacts Names" = "Noms des contacts";
+
/* Default Calendar */
"Default calendar :" = "Calendrier par défaut :";
"selectedCalendar" = "le calendrier sélectionné";
@@ -130,15 +134,6 @@
"Show subscribed mailboxes only" = "Afficher seulement les abonnements";
"Sort messages by threads" = "Grouper les discussions";
"When sending mail, add unknown recipients to my" = "Lors de l'envoi d'un message, ajouter les destinataires inconnus au carnet";
-"Check for new mail:" = "Vérifier l'arrivée de messages :";
-"messagecheck_manually" = "Manuellement";
-"messagecheck_every_minute" = "Chaque minute";
-"messagecheck_every_2_minutes" = "Toutes les 2 minutes";
-"messagecheck_every_5_minutes" = "Toutes les 5 minutes";
-"messagecheck_every_10_minutes" = "Toutes les 10 minutes";
-"messagecheck_every_20_minutes" = "Toutes les 20 minutes";
-"messagecheck_every_30_minutes" = "Toutes les 30 minutes";
-"messagecheck_once_per_hour" = "Une fois par heure";
"Forward messages:" = "Transférer les messages :";
"messageforward_inline" = "intégrés";
@@ -207,8 +202,8 @@
"Contacts" = "Carnet d'adresses";
"Mail" = "Courrier";
"Last" = "Dernier utilisé";
-"Default module :" = "Module par défaut :";
-"SOGo version:" = "Version :";
+"Default Module :" = "Module par défaut :";
+"SOGo Version :" = "Version :";
"Language :" = "Langue :";
"choose" = "Choisir ...";
@@ -236,6 +231,16 @@
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
+"Refresh View :" = "Actualisation :";
+"refreshview_manually" = "Manuellement";
+"refreshview_every_minute" = "Chaque minute";
+"refreshview_every_2_minutes" = "Toutes les 2 minutes";
+"refreshview_every_5_minutes" = "Toutes les 5 minutes";
+"refreshview_every_10_minutes" = "Toutes les 10 minutes";
+"refreshview_every_20_minutes" = "Toutes les 20 minutes";
+"refreshview_every_30_minutes" = "Toutes les 30 minutes";
+"refreshview_once_per_hour" = "Une fois par heure";
+
/* Return receipts */
"When I receive a request for a return receipt:" = "Lors de la réception d'une demande d'accusé de réception :";
"Never send a return receipt" = "Ne jamais envoyer d'accusé de réception";
diff --git a/UI/PreferencesUI/German.lproj/Localizable.strings b/UI/PreferencesUI/German.lproj/Localizable.strings
index 41abe64a3..baca7235c 100644
--- a/UI/PreferencesUI/German.lproj/Localizable.strings
+++ b/UI/PreferencesUI/German.lproj/Localizable.strings
@@ -22,7 +22,7 @@
/* vacation (auto-reply) */
"Enable vacation auto reply" = "Automatische Abwesenheitsnachricht aktivieren";
-"Auto reply message :" = "Folgende Nachricht wird automatisch an jeden Absender gesendet:";
+"Auto reply message :" = "Mit folgender Nachricht auf jede eingehende E-Mail antworten:";
"Email addresses (separated by commas) :" = "E-Mail-Adressen (getrennt durch Kommata):";
"Add default email addresses" = "Standardadresse hinzufügen";
"Days between responses :" = "Tage zwischen automatischen Abwesenheitsnachrichten:";
@@ -104,6 +104,10 @@
"firstWeekOfYear_First4DayWeek" = "Erste 4 Tage Woche";
"firstWeekOfYear_FirstFullWeek" = "Erste ganze Woche";
+"Prevent from being invited to appointments" = "Verhindere, dass ich zu Terminen eingeladen werde";
+"White list for appointment invitations:" = "White-Liste für Termineinladungen:";
+"Contacts Names" = "Kontaktnamen";
+
/* Default Calendar */
"Default calendar :" = "Standardkalender";
"selectedCalendar" = "Gewählter Kalender";
@@ -129,16 +133,16 @@
"Label" = "Schlagwort";
"Show subscribed mailboxes only" = "Nur abonnierte Ordner anzeigen";
"Sort messages by threads" = "Nachrichten nach Thema sortieren";
-"When sending mail, add unknown recipients to my" = "Wenn ich E-Mails sende, füge die unbekannten Empfänger zu meinem";
+"When sending mail, add unknown recipients to my" = "Unbekannte Empfänger meiner E-Mails hinzufügen zu";
"Check for new mail:" = "Auf neue Nachrichten prüfen:";
-"messagecheck_manually" = "Manuell";
-"messagecheck_every_minute" = "Minütlich";
-"messagecheck_every_2_minutes" = "Alle 2 Minuten";
-"messagecheck_every_5_minutes" = "Alle 5 Minuten";
-"messagecheck_every_10_minutes" = "Alle 10 Minuten";
-"messagecheck_every_20_minutes" = "Alle 20 Minuten";
-"messagecheck_every_30_minutes" = "Alle 30 Minuten";
-"messagecheck_once_per_hour" = "Stündlich";
+"refreshview_manually" = "Manuell";
+"refreshview_every_minute" = "Minütlich";
+"refreshview_every_2_minutes" = "Alle 2 Minuten";
+"refreshview_every_5_minutes" = "Alle 5 Minuten";
+"refreshview_every_10_minutes" = "Alle 10 Minuten";
+"refreshview_every_20_minutes" = "Alle 20 Minuten";
+"refreshview_every_30_minutes" = "Alle 30 Minuten";
+"refreshview_once_per_hour" = "Stündlich";
"Forward messages:" = "Nachrichten weiterleiten:";
"messageforward_inline" = "Eingebunden";
@@ -207,8 +211,8 @@
"Contacts" = "Adressbuch";
"Mail" = "E-Mail";
"Last" = "Zuletzt benutztes";
-"Default module :" = "Standard Modul:";
-"SOGo version:" = "SOGo Version:";
+"Default Module :" = "Standard Modul:";
+"SOGo Version :" = "SOGo Version:";
"Language :" = "Sprache:";
"choose" = "Auswählen ...";
@@ -310,7 +314,7 @@
"Password change failed - Password is too short" = "Passwortänderung fehlgeschlagen - Passwort ist zu kurz";
"Password change failed - Password is too young" = "Passwortänderung fehlgeschlagen - zu frühe Passwortänderung";
"Password change failed - Password is in history" = "Passwortänderung fehlgeschlagen - Passwort wurde zuvor verwendet";
-"Unhandled policy error: %{0}" = "Unbearbeiteter Vorgabenfehler: %{0}";
-"Unhandled error response" = "Unbearbeitete Fehlerantwort";
+"Unhandled policy error: %{0}" = "Unerwarteter Fehler bei Passwortänderung: %{0}";
+"Unhandled error response" = "Unerwarteter Fehler";
"Password change is not supported." = "Passwortänderung wird nicht unterstützt.";
-"Unhandled HTTP error code: %{0}" = "Unbearbeiteter HTTP-Fehlercode: %{0}";
+"Unhandled HTTP error code: %{0}" = "Unerwarteter HTTP-Fehlercode: %{0}";
diff --git a/UI/PreferencesUI/Hungarian.lproj/Localizable.strings b/UI/PreferencesUI/Hungarian.lproj/Localizable.strings
index d4be47a0c..2e3908993 100644
--- a/UI/PreferencesUI/Hungarian.lproj/Localizable.strings
+++ b/UI/PreferencesUI/Hungarian.lproj/Localizable.strings
@@ -104,6 +104,10 @@
"firstWeekOfYear_First4DayWeek" = "Első 4 napos héttől";
"firstWeekOfYear_FirstFullWeek" = "Első teljes héttől";
+"Prevent from being invited to appointments" = "Megakadályozza a meghívást találkozókra";
+"White list for appointment invitations:" = "Engedélyezési lista a találkozók meghívásaihoz:";
+"Contacts Names" = "Kapcsolatok nevei";
+
/* Default Calendar */
"Default calendar :" = "Alapértelmezett naptár";
"selectedCalendar" = "Kiválasztott naptár";
@@ -131,14 +135,14 @@
"Sort messages by threads" = "Üzenetek beszélgetések szerinti rendezése ";
"When sending mail, add unknown recipients to my" = "Levél küldésekor az ismeretlen címeket adja hozzá a következőhöz";
"Check for new mail:" = "Új üzenetek letöltése:";
-"messagecheck_manually" = "Kézi";
-"messagecheck_every_minute" = "Percenként";
-"messagecheck_every_2_minutes" = "Kétpercenként";
-"messagecheck_every_5_minutes" = "Ötpercenként";
-"messagecheck_every_10_minutes" = "Tízpercenként";
-"messagecheck_every_20_minutes" = "Húszpercenként";
-"messagecheck_every_30_minutes" = "Harminc percenként";
-"messagecheck_once_per_hour" = "Óránként";
+"refreshview_manually" = "Kézi";
+"refreshview_every_minute" = "Percenként";
+"refreshview_every_2_minutes" = "Kétpercenként";
+"refreshview_every_5_minutes" = "Ötpercenként";
+"refreshview_every_10_minutes" = "Tízpercenként";
+"refreshview_every_20_minutes" = "Húszpercenként";
+"refreshview_every_30_minutes" = "Harminc percenként";
+"refreshview_once_per_hour" = "Óránként";
"Forward messages:" = "Üzenetek továbbítása:";
"messageforward_inline" = "Levélként";
@@ -207,8 +211,8 @@
"Contacts" = "Címjegyzék";
"Mail" = "Levél";
"Last" = "Utoljára használt";
-"Default module :" = "Alapértelmezett modul";
-"SOGo version:" = "SOGo verzió:";
+"Default Module :" = "Alapértelmezett modul";
+"SOGo Version :" = "SOGo verzió:";
"Language :" = "Nyelv :";
"choose" = "Válasszon ...";
diff --git a/UI/PreferencesUI/Icelandic.lproj/Localizable.strings b/UI/PreferencesUI/Icelandic.lproj/Localizable.strings
index c4b496ecd..264172a04 100644
--- a/UI/PreferencesUI/Icelandic.lproj/Localizable.strings
+++ b/UI/PreferencesUI/Icelandic.lproj/Localizable.strings
@@ -107,14 +107,14 @@
"Label" = "Merki";
"Show subscribed mailboxes only" = "Sýna aðeins pósthólf sem eru í áskrift";
"Check for new mail:" = "Sækja nýjan póst:";
-"messagecheck_manually" = "Handvirkt";
-"messagecheck_every_minute" = "Hverjar mínútu";
-"messagecheck_every_2_minutes" = "Hverjar 2 mínútur";
-"messagecheck_every_5_minutes" = "Hverjar 5 mínútur";
-"messagecheck_every_10_minutes" = "Hverjar 10 mínútur";
-"messagecheck_every_20_minutes" = "Hverjar 20 mínútur";
-"messagecheck_every_30_minutes" = "Hverjar 30 mínútur";
-"messagecheck_once_per_hour" = "Á klukkustundar fresti";
+"refreshview_manually" = "Handvirkt";
+"refreshview_every_minute" = "Hverjar mínútu";
+"refreshview_every_2_minutes" = "Hverjar 2 mínútur";
+"refreshview_every_5_minutes" = "Hverjar 5 mínútur";
+"refreshview_every_10_minutes" = "Hverjar 10 mínútur";
+"refreshview_every_20_minutes" = "Hverjar 20 mínútur";
+"refreshview_every_30_minutes" = "Hverjar 30 mínútur";
+"refreshview_once_per_hour" = "Á klukkustundar fresti";
"Forward messages:" = "Áframsenda póst:";
"messageforward_inline" = "Innfellt";
@@ -169,7 +169,7 @@
"Contacts" = "Nafnaskrá";
"Mail" = "Póstur";
"Last" = "Síðast notað";
-"Default module :" = "Sjálfgefið viðmót :";
+"Default Module :" = "Sjálfgefið viðmót :";
"Language :" = "Tungumál :";
"choose" = "Velja...";
diff --git a/UI/PreferencesUI/Italian.lproj/Localizable.strings b/UI/PreferencesUI/Italian.lproj/Localizable.strings
index 546109f36..dda3400af 100644
--- a/UI/PreferencesUI/Italian.lproj/Localizable.strings
+++ b/UI/PreferencesUI/Italian.lproj/Localizable.strings
@@ -127,14 +127,14 @@
"Show subscribed mailboxes only" = "Mostra solo le cartelle sottoscritte";
"Sort messages by threads" = "Ordina i messaggi per conversazione";
"Check for new mail:" = "Controlla la posta in arrivo:";
-"messagecheck_manually" = "Manualmente";
-"messagecheck_every_minute" = "Ogni minuto";
-"messagecheck_every_2_minutes" = "Ogni 2 minuti";
-"messagecheck_every_5_minutes" = "Ogni 5 minuti";
-"messagecheck_every_10_minutes" = "Ogni 10 minuti";
-"messagecheck_every_20_minutes" = "Ogni 20 minuti";
-"messagecheck_every_30_minutes" = "Ogni 30 minuti";
-"messagecheck_once_per_hour" = "Ogni ora";
+"refreshview_manually" = "Manualmente";
+"refreshview_every_minute" = "Ogni minuto";
+"refreshview_every_2_minutes" = "Ogni 2 minuti";
+"refreshview_every_5_minutes" = "Ogni 5 minuti";
+"refreshview_every_10_minutes" = "Ogni 10 minuti";
+"refreshview_every_20_minutes" = "Ogni 20 minuti";
+"refreshview_every_30_minutes" = "Ogni 30 minuti";
+"refreshview_once_per_hour" = "Ogni ora";
"Forward messages:" = "Inoltra messaggi come:";
"messageforward_inline" = "Parte del messaggio";
@@ -190,7 +190,7 @@
"Contacts" = "Rubrica";
"Mail" = "Posta";
"Last" = "Ultimo usato";
-"Default module :" = "Modulo di default :";
+"Default Module :" = "Modulo di default :";
"Language :" = "Lingua :";
"choose" = "Scegli...";
diff --git a/UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings b/UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings
index 221db266c..dcac7f017 100644
--- a/UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings
+++ b/UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings
@@ -97,44 +97,52 @@
"Show time as busy outside working hours" = "Vis tid som opptatt utenfor arbeidstid";
"First week of year :" = "Første uken i året:";
"Enable reminders for Calendar items" = "Aktivere påminnelser for kalenderelementer";
-"Play a sound when a reminder comes due"
-= "Avspill lyd ved en påminnelse";
+"Play a sound when a reminder comes due" = "Avspill lyd ved en påminnelse";
"Default reminder :" = "Standardpåminnelse:";
"firstWeekOfYear_January1" = "Begynner den 1. januar";
"firstWeekOfYear_First4DayWeek" = "Første firedagersuken i året";
"firstWeekOfYear_FirstFullWeek" = "Første hele uken i året";
+"Prevent from being invited to appointments" = "Hindre fra å bli invitert til avtaler";
+"White list for appointment invitations:" = "Hviteliste for avtale invitasjoner:";
+"Contacts Names" = "Kontakters navn";
+
/* Default Calendar */
"Default calendar :" = "Standard kalender:";
"selectedCalendar" = "Valgte kalender";
"personalCalendar" = "Personlig kalender";
"firstCalendar" = "Første aktiverte kalender";
+"reminder_NONE" = "Ingen påminnelse";
"reminder_5_MINUTES_BEFORE" = "5 minutter";
"reminder_10_MINUTES_BEFORE" = "10 minutter";
"reminder_15_MINUTES_BEFORE" = "15 minutter";
"reminder_30_MINUTES_BEFORE" = "30 minutter";
+"reminder_45_MINUTES_BEFORE" = "45 minutter før";
"reminder_1_HOUR_BEFORE" = "1 time";
"reminder_2_HOURS_BEFORE" = "2 timer";
-"reminder_5_HOURS_BEFORE"= "5 timer";
-"reminder_15_HOURS_BEFORE"= "15 timer";
+"reminder_5_HOURS_BEFORE" = "5 timer";
+"reminder_15_HOURS_BEFORE" = "15 timer";
"reminder_1_DAY_BEFORE" = "1 dag";
"reminder_2_DAYS_BEFORE" = "2 dager";
+"reminder_1_WEEK_BEFORE" = "1 uke før";
/* Mailer */
+"Labels" = "Merkelapper";
"Label" = "Etikett";
"Show subscribed mailboxes only" = "Vis bare abonnerte postbokser";
"Sort messages by threads" = "Sorter meldinger etter tråder";
+"When sending mail, add unknown recipients to my" = "Ved sending av mail, legg til ukjente mottakere til min";
"Check for new mail:" = "Hent ny post:";
-"messagecheck_manually" = "Manuelt";
-"messagecheck_every_minute" = "Hvert minutt";
-"messagecheck_every_2_minutes" = "Hvert 2. minutt";
-"messagecheck_every_5_minutes" = "Hvert 5. minutt";
-"messagecheck_every_10_minutes" = "Hvert 10. minutt";
-"messagecheck_every_20_minutes" = "Hvert 20. minutt";
-"messagecheck_every_30_minutes" = "Hvert 30. minutt";
-"messagecheck_once_per_hour" = "Hver time";
+"refreshview_manually" = "Manuelt";
+"refreshview_every_minute" = "Hvert minutt";
+"refreshview_every_2_minutes" = "Hvert 2. minutt";
+"refreshview_every_5_minutes" = "Hvert 5. minutt";
+"refreshview_every_10_minutes" = "Hvert 10. minutt";
+"refreshview_every_20_minutes" = "Hvert 20. minutt";
+"refreshview_every_30_minutes" = "Hvert 30. minutt";
+"refreshview_once_per_hour" = "Hver time";
"Forward messages:" = "Videresend meldinger:";
"messageforward_inline" = "Innsatt";
@@ -153,6 +161,10 @@
"displayremoteinlineimages_never" = "Aldri";
"displayremoteinlineimages_always" = "Alltid";
+/* Contact */
+"Personal Address Book" = "Personlig addressebok";
+"Collected Address Book" = "Samlet addressebok";
+
/* IMAP Accounts */
"New Mail Account" = "Ny e-postkonto";
@@ -199,7 +211,8 @@
"Contacts" = "Adressebok";
"Mail" = "E-post";
"Last" = "Sist besøkt";
-"Default module :" = "Standardmodul:";
+"Default Module :" = "Standardmodul:";
+"SOGo Version :" = "SOGo versjon:";
"Language :" = "Språk:";
"choose" = "Velg ...";
@@ -244,6 +257,8 @@
"Active" = "Aktiv";
"Move Up" = "Flytt opp";
"Move Down" = "Flytt ned";
+"Connection error" = "Koblingsfeil";
+"Service temporarily unavailable" = "Tjeneste midlertidig utilgjengelig";
/* Filters - UIxFilterEditor */
"Filter name:" = "Filternavn:";
@@ -261,6 +276,7 @@
"To or Cc" = "Til eller Kopi";
"Size (Kb)" = "Størrelse (Kb)";
"Header" = "Tittel";
+"Body" = "Kropp";
"Flag the message with:" = "Flagg meldingen med:";
"Discard the message" = "Forkast meldingen";
"File the message in:" = "Fil meldingen i:";
@@ -287,12 +303,8 @@
"Flagged" = "Flagget";
"Junk" = "Søppel";
"Not Junk" = "Ikke søppel";
-"Label 1" = "Etikett 1";
-"Label 2" = "Etikett 2";
-"Label 3" = "Etikett 3";
-"Label 4" = "Etikett 4";
-"Label 5" = "Etikett 5";
+/* Password policy */
"The password was changed successfully." = "Passordet ble endret.";
"Password must not be empty." = "Passord kan ikke være tomme.";
"The passwords do not match. Please try again." = "Passordene er ikke like. Prøv igjen.";
diff --git a/UI/PreferencesUI/NorwegianNynorsk.lproj/Localizable.strings b/UI/PreferencesUI/NorwegianNynorsk.lproj/Localizable.strings
index 718b758bc..3c8f23b64 100644
--- a/UI/PreferencesUI/NorwegianNynorsk.lproj/Localizable.strings
+++ b/UI/PreferencesUI/NorwegianNynorsk.lproj/Localizable.strings
@@ -114,14 +114,14 @@
"Show subscribed mailboxes only" = "Vis bare abonnerte postbokser";
"Sort messages by threads" = "Sort messages by threads";
"Check for new mail:" = "Hent ny post:";
-"messagecheck_manually" = "Manuelt";
-"messagecheck_every_minute" = "Hvert minutt";
-"messagecheck_every_2_minutes" = "Hvert 2 minutt";
-"messagecheck_every_5_minutes" = "Hvert 5 minutt";
-"messagecheck_every_10_minutes" = "Hvert 10 minutt";
-"messagecheck_every_20_minutes" = "Hvert 20 minutt";
-"messagecheck_every_30_minutes" = "Hvert 30 minutt";
-"messagecheck_once_per_hour" = "Hver time";
+"refreshview_manually" = "Manuelt";
+"refreshview_every_minute" = "Hvert minutt";
+"refreshview_every_2_minutes" = "Hvert 2 minutt";
+"refreshview_every_5_minutes" = "Hvert 5 minutt";
+"refreshview_every_10_minutes" = "Hvert 10 minutt";
+"refreshview_every_20_minutes" = "Hvert 20 minutt";
+"refreshview_every_30_minutes" = "Hvert 30 minutt";
+"refreshview_once_per_hour" = "Hver time";
"Forward messages:" = "Videresend melding:";
"messageforward_inline" = "Innsatt";
@@ -176,7 +176,7 @@
"Contacts" = "Adressebok";
"Mail" = "E-post";
"Last" = "Sist besøkt";
-"Default module :" = "Standardmodul:";
+"Default Module :" = "Standardmodul:";
"Language :" = "Språk:";
"choose" = "Velg ...";
diff --git a/UI/PreferencesUI/Polish.lproj/Localizable.strings b/UI/PreferencesUI/Polish.lproj/Localizable.strings
index 1144a3740..6606ec007 100644
--- a/UI/PreferencesUI/Polish.lproj/Localizable.strings
+++ b/UI/PreferencesUI/Polish.lproj/Localizable.strings
@@ -104,6 +104,10 @@
"firstWeekOfYear_First4DayWeek" = "pierwszy 4-dniowy tydzień";
"firstWeekOfYear_FirstFullWeek" = "pierwszy pełny tydzień";
+"Prevent from being invited to appointments" = "Zablokuj możliwość zapraszania cię na wydarzenia";
+"White list for appointment invitations:" = "Osoby, którym pozwalasz się zapraszać:";
+"Contacts Names" = "Nazwy kontaktów";
+
/* Default Calendar */
"Default calendar :" = "Domyślny kalendarz:";
"selectedCalendar" = "Wybrany kalendarz";
@@ -131,14 +135,14 @@
"Sort messages by threads" = "Sortuj wiadomości według wątków";
"When sending mail, add unknown recipients to my" = "Gdy wysyłam e-mail, dodaj adresy nowych odbiorców do";
"Check for new mail:" = "Sprawdzaj nowe wiadomości:";
-"messagecheck_manually" = "ręcznie";
-"messagecheck_every_minute" = "co minutę";
-"messagecheck_every_2_minutes" = "co 2 minuty";
-"messagecheck_every_5_minutes" = "co 5 minut";
-"messagecheck_every_10_minutes" = "co 10 minut";
-"messagecheck_every_20_minutes" = "co 20 minut";
-"messagecheck_every_30_minutes" = "co 30 minut";
-"messagecheck_once_per_hour" = "raz na godzinę";
+"refreshview_manually" = "ręcznie";
+"refreshview_every_minute" = "co minutę";
+"refreshview_every_2_minutes" = "co 2 minuty";
+"refreshview_every_5_minutes" = "co 5 minut";
+"refreshview_every_10_minutes" = "co 10 minut";
+"refreshview_every_20_minutes" = "co 20 minut";
+"refreshview_every_30_minutes" = "co 30 minut";
+"refreshview_once_per_hour" = "raz na godzinę";
"Forward messages:" = "Przekaż wiadomości:";
"messageforward_inline" = "w treści";
@@ -207,8 +211,8 @@
"Contacts" = "Książka adresowa";
"Mail" = "Poczta";
"Last" = "Ostatnio używane";
-"Default module :" = "Tryb domyślny:";
-"SOGo version:" = "Wersja SOGo:";
+"Default Module :" = "Tryb domyślny:";
+"SOGo Version :" = "Wersja SOGo:";
"Language :" = "Język:";
"choose" = "Wybierz";
diff --git a/UI/PreferencesUI/Russian.lproj/Localizable.strings b/UI/PreferencesUI/Russian.lproj/Localizable.strings
index b9fcba4d9..59876e6e7 100644
--- a/UI/PreferencesUI/Russian.lproj/Localizable.strings
+++ b/UI/PreferencesUI/Russian.lproj/Localizable.strings
@@ -131,14 +131,14 @@
"Sort messages by threads" = "Сортировать сообщения по нитям";
"When sending mail, add unknown recipients to my" = "При отправке писем добавлять неизвестных получателей в мою";
"Check for new mail:" = "Проверять новую почту:";
-"messagecheck_manually" = "Вручную";
-"messagecheck_every_minute" = "Каждую минуту";
-"messagecheck_every_2_minutes" = "Каждые 2 минуты";
-"messagecheck_every_5_minutes" = "Каждые 5 минут";
-"messagecheck_every_10_minutes" = "Каждые 10 минут";
-"messagecheck_every_20_minutes" = "Каждые 20 минут";
-"messagecheck_every_30_minutes" = "Каждые 30 минут";
-"messagecheck_once_per_hour" = "Раз в час";
+"refreshview_manually" = "Вручную";
+"refreshview_every_minute" = "Каждую минуту";
+"refreshview_every_2_minutes" = "Каждые 2 минуты";
+"refreshview_every_5_minutes" = "Каждые 5 минут";
+"refreshview_every_10_minutes" = "Каждые 10 минут";
+"refreshview_every_20_minutes" = "Каждые 20 минут";
+"refreshview_every_30_minutes" = "Каждые 30 минут";
+"refreshview_once_per_hour" = "Раз в час";
"Forward messages:" = "Пересылать сообщения:";
"messageforward_inline" = "В теле письма";
@@ -207,8 +207,8 @@
"Contacts" = "Адресная книга";
"Mail" = "Почта";
"Last" = "Последнее использование";
-"Default module :" = "Модуль по умолчанию :";
-"SOGo version:" = "Версия SOGo:";
+"Default Module :" = "Модуль по умолчанию :";
+"SOGo Version :" = "Версия SOGo:";
"Language :" = "Язык :";
"choose" = "Выбрать ...";
diff --git a/UI/PreferencesUI/Slovak.lproj/Localizable.strings b/UI/PreferencesUI/Slovak.lproj/Localizable.strings
index dc8208fa2..e564e8c50 100644
--- a/UI/PreferencesUI/Slovak.lproj/Localizable.strings
+++ b/UI/PreferencesUI/Slovak.lproj/Localizable.strings
@@ -131,14 +131,14 @@
"Sort messages by threads" = "Zoraď správy do konverzácií";
"When sending mail, add unknown recipients to my" = "Pri odosielaní emailu, pridaj neznámych príjemcov do môjho";
"Check for new mail:" = "Kontrola nových mailov:";
-"messagecheck_manually" = "Ručne";
-"messagecheck_every_minute" = "Každú minútu";
-"messagecheck_every_2_minutes" = "Každé 2 minúty";
-"messagecheck_every_5_minutes" = "Každých 5 minút";
-"messagecheck_every_10_minutes" = "Každých 10 minút";
-"messagecheck_every_20_minutes" = "Každých 20 minút";
-"messagecheck_every_30_minutes" = "Každých 30 minút";
-"messagecheck_once_per_hour" = "Raz za hodinu";
+"refreshview_manually" = "Ručne";
+"refreshview_every_minute" = "Každú minútu";
+"refreshview_every_2_minutes" = "Každé 2 minúty";
+"refreshview_every_5_minutes" = "Každých 5 minút";
+"refreshview_every_10_minutes" = "Každých 10 minút";
+"refreshview_every_20_minutes" = "Každých 20 minút";
+"refreshview_every_30_minutes" = "Každých 30 minút";
+"refreshview_once_per_hour" = "Raz za hodinu";
"Forward messages:" = "Preposielaj správy:";
"messageforward_inline" = "Vrade";
@@ -207,8 +207,8 @@
"Contacts" = "Adresár";
"Mail" = "Pošta";
"Last" = "Naposledy použité";
-"Default module :" = "Predvolený modul:";
-"SOGo version:" = "Verzia SOGo:";
+"Default Module :" = "Predvolený modul:";
+"SOGo Version :" = "Verzia SOGo:";
"Language :" = "Jazyk:";
"choose" = "Vyber...";
diff --git a/UI/PreferencesUI/SpanishArgentina.lproj/Localizable.strings b/UI/PreferencesUI/SpanishArgentina.lproj/Localizable.strings
index c2b003477..98f09d019 100644
--- a/UI/PreferencesUI/SpanishArgentina.lproj/Localizable.strings
+++ b/UI/PreferencesUI/SpanishArgentina.lproj/Localizable.strings
@@ -131,14 +131,14 @@
"Sort messages by threads" = "Ordenar mensajes por conversaciones";
"When sending mail, add unknown recipients to my" = "Al enviar correos, agregar destinatarios desconocidos a mi";
"Check for new mail:" = "Comprobar si hay nuevos correos: ";
-"messagecheck_manually" = "Manualmente";
-"messagecheck_every_minute" = "Cada minuto";
-"messagecheck_every_2_minutes" = "Cada 2 minutos";
-"messagecheck_every_5_minutes" = "Cada 5 minutos";
-"messagecheck_every_10_minutes" = "Cada 10 minutos";
-"messagecheck_every_20_minutes" = "Cada 20 minutos";
-"messagecheck_every_30_minutes" = "Cada 30 minutos";
-"messagecheck_once_per_hour" = "Cada hora";
+"refreshview_manually" = "Manualmente";
+"refreshview_every_minute" = "Cada minuto";
+"refreshview_every_2_minutes" = "Cada 2 minutos";
+"refreshview_every_5_minutes" = "Cada 5 minutos";
+"refreshview_every_10_minutes" = "Cada 10 minutos";
+"refreshview_every_20_minutes" = "Cada 20 minutos";
+"refreshview_every_30_minutes" = "Cada 30 minutos";
+"refreshview_once_per_hour" = "Cada hora";
"Forward messages:" = "Reenviar mensajes:";
"messageforward_inline" = "Incorporado";
@@ -207,8 +207,8 @@
"Contacts" = "Libreta de direcciones";
"Mail" = "Correo";
"Last" = "Ultimo usado";
-"Default module :" = "Módulo por defecto :";
-"SOGo version:" = "Versión de SOGo:";
+"Default Module :" = "Módulo por defecto :";
+"SOGo Version :" = "Versión de SOGo:";
"Language :" = "Idioma :";
"choose" = "Elija ...";
diff --git a/UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings b/UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings
index a0abeb7aa..3cc800f6f 100644
--- a/UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings
+++ b/UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings
@@ -104,6 +104,10 @@
"firstWeekOfYear_First4DayWeek" = "Primera semana del año de 4 días";
"firstWeekOfYear_FirstFullWeek" = "Primera semana del año completa";
+"Prevent from being invited to appointments" = "Evitar invitaciones a eventos";
+"White list for appointment invitations:" = "Lista blanca de invitaciones a eventos:";
+"Contacts Names" = "Nombres de Contacto";
+
/* Default Calendar */
"Default calendar :" = "Calendario por defecto";
"selectedCalendar" = "Calendario seleccionado";
@@ -131,14 +135,14 @@
"Sort messages by threads" = "Ordenar mensajes por temas";
"When sending mail, add unknown recipients to my" = "Cuando se envía correo, añade destinatarios desconocidos a mi";
"Check for new mail:" = "Comprobar correo nuevo: ";
-"messagecheck_manually" = "Manualmente";
-"messagecheck_every_minute" = "Cada minuto";
-"messagecheck_every_2_minutes" = "Cada 2 minutos";
-"messagecheck_every_5_minutes" = "Cada 5 minutos";
-"messagecheck_every_10_minutes" = "Cada 10 minutos";
-"messagecheck_every_20_minutes" = "Cada 20 minutos";
-"messagecheck_every_30_minutes" = "Cada 30 minutos";
-"messagecheck_once_per_hour" = "Cada hora";
+"refreshview_manually" = "Manualmente";
+"refreshview_every_minute" = "Cada minuto";
+"refreshview_every_2_minutes" = "Cada 2 minutos";
+"refreshview_every_5_minutes" = "Cada 5 minutos";
+"refreshview_every_10_minutes" = "Cada 10 minutos";
+"refreshview_every_20_minutes" = "Cada 20 minutos";
+"refreshview_every_30_minutes" = "Cada 30 minutos";
+"refreshview_once_per_hour" = "Cada hora";
"Forward messages:" = "Reenviar mensajes:";
"messageforward_inline" = "Incorporado";
@@ -207,8 +211,8 @@
"Contacts" = "Libreta de direcciones";
"Mail" = "Correo";
"Last" = "Ultimo usado";
-"Default module :" = "Módulo por defecto :";
-"SOGo version:" = "Versión de SOGo:";
+"Default Module :" = "Módulo por defecto :";
+"SOGo Version :" = "Versión de SOGo:";
"Language :" = "Idioma :";
"choose" = "Elija ...";
diff --git a/UI/PreferencesUI/Swedish.lproj/Localizable.strings b/UI/PreferencesUI/Swedish.lproj/Localizable.strings
index 73e4b0282..915b3d324 100644
--- a/UI/PreferencesUI/Swedish.lproj/Localizable.strings
+++ b/UI/PreferencesUI/Swedish.lproj/Localizable.strings
@@ -114,14 +114,14 @@
"Show subscribed mailboxes only" = "Visa endast prenumrerade postlådor";
"Sort messages by threads" = "Sort messages by threads";
"Check for new mail:" = "Hämta ny post:";
-"messagecheck_manually" = "Manuellt";
-"messagecheck_every_minute" = "Varje minut";
-"messagecheck_every_2_minutes" = "Varje 2 minuter";
-"messagecheck_every_5_minutes" = "Varje 5 minuter";
-"messagecheck_every_10_minutes" = "Varje 10 minuter";
-"messagecheck_every_20_minutes" = "Varje 20 minuter";
-"messagecheck_every_30_minutes" = "Varje 30 minuter";
-"messagecheck_once_per_hour" = "Varje timme";
+"refreshview_manually" = "Manuellt";
+"refreshview_every_minute" = "Varje minut";
+"refreshview_every_2_minutes" = "Varje 2 minuter";
+"refreshview_every_5_minutes" = "Varje 5 minuter";
+"refreshview_every_10_minutes" = "Varje 10 minuter";
+"refreshview_every_20_minutes" = "Varje 20 minuter";
+"refreshview_every_30_minutes" = "Varje 30 minuter";
+"refreshview_once_per_hour" = "Varje timme";
"Forward messages:" = "Vidarebefordra meddelanden:";
"messageforward_inline" = "Infogade";
@@ -178,7 +178,7 @@ Servernamn:";
"Contacts" = "Adressbok";
"Mail" = "E-post";
"Last" = "Senast använd";
-"Default module :" = "Standardmodul:";
+"Default Module :" = "Standardmodul:";
"Language :" = "Språk:";
"choose" = "Välj ...";
diff --git a/UI/PreferencesUI/UIxPreferences.m b/UI/PreferencesUI/UIxPreferences.m
index 0900c4d3a..5017a4bec 100644
--- a/UI/PreferencesUI/UIxPreferences.m
+++ b/UI/PreferencesUI/UIxPreferences.m
@@ -19,6 +19,7 @@
*/
#import
+#import
#import
#import
#import
@@ -41,6 +42,7 @@
#import