diff --git a/.tx/config b/.tx/config index b6a16ff1d..e8337eb38 100644 --- a/.tx/config +++ b/.tx/config @@ -21,6 +21,7 @@ trans.nn_NO = UI/MailerUI/NorwegianNynorsk.lproj/Localizable.strings trans.pl = UI/MailerUI/Polish.lproj/Localizable.strings trans.pt_BR = UI/MailerUI/BrazilianPortuguese.lproj/Localizable.strings trans.ru = UI/MailerUI/Russian.lproj/Localizable.strings +trans.sk = UI/MailerUI/Slovak.lproj/Localizable.strings trans.sv = UI/MailerUI/Swedish.lproj/Localizable.strings trans.uk = UI/MailerUI/Ukrainian.lproj/Localizable.strings @@ -44,6 +45,7 @@ trans.nn_NO = UI/PreferencesUI/NorwegianNynorsk.lproj/Localizable.strings trans.pl = UI/PreferencesUI/Polish.lproj/Localizable.strings trans.pt_BR = UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings trans.ru = UI/PreferencesUI/Russian.lproj/Localizable.strings +trans.sk = UI/PreferencesUI/Slovak.lproj/Localizable.strings trans.sv = UI/PreferencesUI/Swedish.lproj/Localizable.strings trans.uk = UI/PreferencesUI/Ukrainian.lproj/Localizable.strings @@ -67,6 +69,7 @@ trans.nn_NO = UI/Scheduler/NorwegianNynorsk.lproj/Localizable.strings trans.pl = UI/Scheduler/Polish.lproj/Localizable.strings trans.pt_BR = UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings trans.ru = UI/Scheduler/Russian.lproj/Localizable.strings +trans.sk = UI/Scheduler/Slovak.lproj/Localizable.strings trans.sv = UI/Scheduler/Swedish.lproj/Localizable.strings trans.uk = UI/Scheduler/Ukrainian.lproj/Localizable.strings @@ -90,6 +93,7 @@ trans.nn_NO = UI/Contacts/NorwegianNynorsk.lproj/Localizable.strings trans.pl = UI/Contacts/Polish.lproj/Localizable.strings trans.pt_BR = UI/Contacts/BrazilianPortuguese.lproj/Localizable.strings trans.ru = UI/Contacts/Russian.lproj/Localizable.strings +trans.sk = UI/Contacts/Slovak.lproj/Localizable.strings trans.sv = UI/Contacts/Swedish.lproj/Localizable.strings trans.uk = UI/Contacts/Ukrainian.lproj/Localizable.strings @@ -113,6 +117,7 @@ trans.nn_NO = UI/MainUI/NorwegianNynorsk.lproj/Localizable.strings trans.pl = UI/MainUI/Polish.lproj/Localizable.strings trans.pt_BR = UI/MainUI/BrazilianPortuguese.lproj/Localizable.strings trans.ru = UI/MainUI/Russian.lproj/Localizable.strings +trans.sk = UI/MainUI/Slovak.lproj/Localizable.strings trans.sv = UI/MainUI/Swedish.lproj/Localizable.strings trans.uk = UI/MainUI/Ukrainian.lproj/Localizable.strings @@ -136,6 +141,7 @@ trans.nn_NO = UI/Common/NorwegianNynorsk.lproj/Localizable.strings trans.pl = UI/Common/Polish.lproj/Localizable.strings trans.pt_BR = UI/Common/BrazilianPortuguese.lproj/Localizable.strings trans.ru = UI/Common/Russian.lproj/Localizable.strings +trans.sk = UI/Common/Slovak.lproj/Localizable.strings trans.sv = UI/Common/Swedish.lproj/Localizable.strings trans.uk = UI/Common/Ukrainian.lproj/Localizable.strings @@ -159,6 +165,7 @@ trans.nn_NO = UI/AdministrationUI/NorwegianNynorsk.lproj/Localizable.strings trans.pl = UI/AdministrationUI/Polish.lproj/Localizable.strings trans.pt_BR = UI/AdministrationUI/BrazilianPortuguese.lproj/Localizable.strings trans.ru = UI/AdministrationUI/Russian.lproj/Localizable.strings +trans.sk = UI/AdministrationUI/Slovak.lproj/Localizable.strings trans.sv = UI/AdministrationUI/Swedish.lproj/Localizable.strings trans.uk = UI/AdministrationUI/Ukrainian.lproj/Localizable.strings @@ -182,6 +189,7 @@ trans.nn_NO = SoObjects/Appointments/NorwegianNynorsk.lproj/Localizable.strings trans.pl = SoObjects/Appointments/Polish.lproj/Localizable.strings trans.pt_BR = SoObjects/Appointments/BrazilianPortuguese.lproj/Localizable.strings trans.ru = SoObjects/Appointments/Russian.lproj/Localizable.strings +trans.sk = SoObjects/Appointments/Slovak.lproj/Localizable.strings trans.sv = SoObjects/Appointments/Swedish.lproj/Localizable.strings trans.uk = SoObjects/Appointments/Ukrainian.lproj/Localizable.strings @@ -205,6 +213,7 @@ trans.nn_NO = SoObjects/Contacts/NorwegianNynorsk.lproj/Localizable.strings trans.pl = SoObjects/Contacts/Polish.lproj/Localizable.strings trans.pt_BR = SoObjects/Contacts/BrazilianPortuguese.lproj/Localizable.strings trans.ru = SoObjects/Contacts/Russian.lproj/Localizable.strings +trans.sk = SoObjects/Contacts/Slovak.lproj/Localizable.strings trans.sv = SoObjects/Contacts/Swedish.lproj/Localizable.strings trans.uk = SoObjects/Contacts/Ukrainian.lproj/Localizable.strings @@ -228,5 +237,6 @@ trans.nn_NO = UI/MailPartViewers/NorwegianNynorsk.lproj/Localizable.strings trans.pl = UI/MailPartViewers/Polish.lproj/Localizable.strings trans.pt_BR = UI/MailPartViewers/BrazilianPortuguese.lproj/Localizable.strings trans.ru = UI/MailPartViewers/Russian.lproj/Localizable.strings +trans.sk = UI/MailPartViewers/Slovak.lproj/Localizable.strings trans.sv = UI/MailPartViewers/Swedish.lproj/Localizable.strings trans.uk = UI/MailPartViewers/Ukrainian.lproj/Localizable.strings diff --git a/ChangeLog b/ChangeLog index 13a41e89d..aba47c924 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,1094 @@ +commit 2a5e0aeaa96920752ba88be91f31eab4a92dafe9 +Author: Francis Lachapelle +Date: Thu Dec 6 10:32:31 2012 -0500 + + Disable autocompletion of reply-to address + +M UI/Templates/PreferencesUI/UIxPreferences.wox + +commit 026ffd888865467961384c1defffa3062928c375 +Author: Francis Lachapelle +Date: Thu Dec 6 10:31:15 2012 -0500 + + Update translations + +M SoObjects/Appointments/BrazilianPortuguese.lproj/Localizable.strings +M SoObjects/Appointments/Polish.lproj/Localizable.strings +M UI/Common/Polish.lproj/Localizable.strings +M UI/Common/Slovak.lproj/Localizable.strings +M UI/Contacts/BrazilianPortuguese.lproj/Localizable.strings +M UI/Contacts/Polish.lproj/Localizable.strings +M UI/MailPartViewers/Polish.lproj/Localizable.strings +M UI/MailerUI/BrazilianPortuguese.lproj/Localizable.strings +M UI/MailerUI/Dutch.lproj/Localizable.strings +M UI/MailerUI/Polish.lproj/Localizable.strings +M UI/MailerUI/Slovak.lproj/Localizable.strings +M UI/MainUI/Slovak.lproj/Localizable.strings +M UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings +M UI/PreferencesUI/Dutch.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/Polish.lproj/Localizable.strings +M UI/PreferencesUI/Slovak.lproj/Localizable.strings +M UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings +M UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings +M UI/Scheduler/Dutch.lproj/Localizable.strings +M UI/Scheduler/French.lproj/Localizable.strings +M UI/Scheduler/German.lproj/Localizable.strings +M UI/Scheduler/Hungarian.lproj/Localizable.strings +M UI/Scheduler/Polish.lproj/Localizable.strings +M UI/Scheduler/Slovak.lproj/Localizable.strings +M UI/Scheduler/SpanishSpain.lproj/Localizable.strings + +commit 4926855f48e78b30fc9b2a4ce2c2aa7ce002a744 +Author: Francis Lachapelle +Date: Thu Dec 6 09:39:07 2012 -0500 + + Bump version to 2.0.3 + +M Documentation/SOGo Mozilla Thunderbird Configuration.odt +M Scripts/updates.php +M Version + +commit 881a725f1232089aae17a3389d94349073e76065 +Author: Francis Lachapelle +Date: Thu Dec 6 09:06:55 2012 -0500 + + Update NEWS file + +M NEWS + +commit a7722755b7019f357acb23f500662a915fa5e908 +Author: Ludovic Marcotte +Date: Thu Dec 6 09:03:17 2012 -0500 + + Fixed length call. + +M SoObjects/SOGo/SOGoSieveManager.m + +commit 5e7d2325bb8e8b558833c75393e80b27ae4b2142 +Author: Francis Lachapelle +Date: Wed Dec 5 22:16:47 2012 -0500 + + Update documentation guides + +M Documentation/SOGo Installation Guide.odt +M Documentation/SOGo Mobile Devices Configuration.odt +M Documentation/SOGo Mozilla Thunderbird Configuration.odt +M Documentation/SOGo Native Microsoft Outlook Configuration.odt + +commit 347434dbff705f438f2b19d6655fc727ef3cab26 +Author: Ludovic Marcotte +Date: Wed Dec 5 15:52:50 2012 -0500 + + We now fallback properly on the IMAP server if the Sieve server is undefined. + +M SoObjects/SOGo/SOGoSieveManager.m + +commit ca1a3ac06b3e770ec296f3eaa585644a50c0cd77 +Author: Ludovic Marcotte +Date: Wed Dec 5 14:56:29 2012 -0500 + + Fixed the ordering of the memory context. + +M OpenChange/MAPIStoreSOGo.m + +commit 8ca79d9a17c9ce76f860ad5b304413fe97bf4f04 +Author: Francis Lachapelle +Date: Wed Dec 5 14:47:28 2012 -0500 + + Search field for tasks + + Fixes #2103 + +M UI/Scheduler/UIxCalListingActions.m +M UI/Templates/AdministrationUI/UIxAdministrationFilterPanel.wox +M UI/Templates/ContactsUI/UIxContactsFilterPanel.wox +M UI/Templates/MailerUI/UIxMailFilterPanel.wox +M UI/Templates/SchedulerUI/UIxCalFilterPanel.wox +M UI/Templates/SchedulerUI/UIxCalMainView.wox +M UI/WebServerResources/AdministrationUI.js +M UI/WebServerResources/ContactsUI.js +M UI/WebServerResources/MailerUI.js +M UI/WebServerResources/SchedulerUI.css +M UI/WebServerResources/SchedulerUI.js +M UI/WebServerResources/generic.css +M UI/WebServerResources/generic.js + +commit 3606601c3922eecc60e8e3f0f21deafc25a994c3 +Author: Ludovic Marcotte +Date: Wed Dec 5 08:51:55 2012 -0500 + + Fix for bug #2130 + +M packaging/debian-multiarch/sogo.cron.daily +M packaging/debian/sogo.cron.daily + +commit 988e91a63833dc7e2d96dedb560e5487ae67ec6c +Author: Ludovic Marcotte +Date: Wed Dec 5 08:31:35 2012 -0500 + + We also remove the RSVP in the user's calendar during a PUT. + +M SoObjects/Appointments/SOGoAppointmentObject.m + +commit f6b5fdacb989a3e2a9b952a5c53d81ee464e2e60 +Author: Ludovic Marcotte +Date: Mon Dec 3 16:49:20 2012 -0500 + + Remaining patches for bug #1866. + +M SoObjects/SOGo/SOGoSieveManager.m +M SoObjects/SOGo/SOGoUser.m + +commit aa7aa6a9736d8717424aa1f303c749ab89d0b768 +Author: Ludovic Marcotte +Date: Mon Dec 3 16:42:56 2012 -0500 + + Initial patch from #1866 to fix c_sievehostname. + +M SoObjects/SOGo/SOGoUserManager.m + +commit d64fd65ea8b3ee1b0fc3ade039c46e0459b79816 +Author: Ludovic Marcotte +Date: Mon Dec 3 16:33:14 2012 -0500 + + Lowercase some value to avoid broken comparaisons. + +M SoObjects/SOGo/SOGoDomainDefaults.m + +commit ef7c69eda7abc8f142935da134662e55c6210975 +Author: Ludovic Marcotte +Date: Mon Dec 3 14:56:11 2012 -0500 + + Now consider "utf8" crap as "utf-8", coming from bad mailers. + +M UI/MailPartViewers/UIxMailPartHTMLViewer.m + +commit 2017536bebed404688af06d9b5cdcdcffa7eb7f7 +Author: Ludovic Marcotte +Date: Mon Dec 3 09:18:17 2012 -0500 + + move_copy_messages now uses the openchange's memory context. + + This fixes strange crashes when dealing with invitations and + other stuff. More work will need to be done in this regard. Also + kept the old code just in case for now. Will be cleaned up shortly + after more people test it. + +M OpenChange/MAPIStoreAttachment.h +M OpenChange/MAPIStoreAttachment.m +M OpenChange/MAPIStoreCalendarFolder.m +M OpenChange/MAPIStoreFolder.h +M OpenChange/MAPIStoreFolder.m +M OpenChange/MAPIStoreMailFolder.m +M OpenChange/MAPIStoreMessage.h +M OpenChange/MAPIStoreMessage.m +M OpenChange/MAPIStoreObject.h +M OpenChange/MAPIStoreObject.m +M OpenChange/MAPIStoreSOGo.m +M OpenChange/NSObject+MAPIStore.m + +commit 5500f99312988721524c4ba003a66eb3a968afda +Author: Francis Lachapelle +Date: Fri Nov 30 15:11:03 2012 -0500 + + Remove conditions on RSVP + + Fixes #1850 + +M SoObjects/Appointments/SOGoAppointmentObject.m +M UI/Scheduler/UIxComponentEditor.m + +commit eed17fd95abdbe421f870dc112abac71d67971d7 +Author: Ludovic Marcotte +Date: Fri Nov 30 13:57:55 2012 -0500 + + Fix for bug #1850 and removed dead code/comments. + +M SoObjects/Appointments/SOGoAppointmentObject.m + +commit 0e02334fda980dccf623d76bebbab997d22de837 +Author: Ludovic Marcotte +Date: Fri Nov 30 10:31:58 2012 -0500 + + Updated the doc in preparation for the release and to fix #2101. + +M Documentation/SOGo Mozilla Thunderbird Configuration.odt + +commit 47a9a22bc02ac4dbfbcb9d30eae2643773e9a6fa +Author: Ludovic Marcotte +Date: Fri Nov 30 10:11:05 2012 -0500 + + Fix for bug #2082. + +M SoObjects/SOGo/SOGoSieveManager.m + +commit b1d3aba1e19188beec0d2c9c8b52aa64a2b9e4c0 +Author: Francis Lachapelle +Date: Thu Nov 29 16:09:53 2012 -0500 + + Add missing localizable strings in prefs module + +M UI/PreferencesUI/English.lproj/Localizable.strings + +commit 73ff981d4fe5a77c3859de8ecaef43dfb52c463c +Author: Ludovic Marcotte +Date: Thu Nov 29 15:49:32 2012 -0500 + + Fixed the method that returns the current-user-principal. + +M SoObjects/Appointments/SOGoUserFolder+Appointments.h +M SoObjects/SOGo/SOGoObject.m + +commit 88550c0d0d8c98c7f559fcf264974936d03a40ed +Author: Francis Lachapelle +Date: Thu Nov 29 14:56:33 2012 -0500 + + Update NEWS file + +M NEWS + +commit 440523747df12ec6ba08075d20d4da198f4bc4f6 +Author: Francis Lachapelle +Date: Thu Nov 29 14:54:15 2012 -0500 + + Rollback selection of language on login page + + See dfcf0ca and ticket #1798 + +M UI/Templates/MainUI/SOGoRootPage.wox + +commit 93f77c0dd5daff09d82fbc5a8398e133c44ef4c7 +Author: Francis Lachapelle +Date: Thu Nov 29 14:46:39 2012 -0500 + + Add missing localizable string in calendar module + +M UI/Scheduler/English.lproj/Localizable.strings + +commit ce36e80d6b5155987a7074ce3351a2d6cdd9b412 +Author: Francis Lachapelle +Date: Thu Nov 29 14:40:46 2012 -0500 + + Initial Slovak translation + +M .tx/config +M SoObjects/Appointments/GNUmakefile +A SoObjects/Appointments/Slovak.lproj/Localizable.strings +M SoObjects/Contacts/GNUmakefile +A SoObjects/Contacts/Slovak.lproj/Localizable.strings +A SoObjects/Mailer/SOGoMailSlovakForward.wo/SOGoMailSlovakForward.html +A SoObjects/Mailer/SOGoMailSlovakForward.wo/SOGoMailSlovakForward.wod +A SoObjects/Mailer/SOGoMailSlovakReply.wo/SOGoMailSlovakReply.html +A SoObjects/Mailer/SOGoMailSlovakReply.wo/SOGoMailSlovakReply.wod +M SoObjects/SOGo/SOGoDefaults.plist +M Tests/Integration/preferences.py +M UI/AdministrationUI/GNUmakefile +A UI/AdministrationUI/Slovak.lproj/Localizable.strings +M UI/Common/GNUmakefile +A UI/Common/Slovak.lproj/Localizable.strings +M UI/Contacts/GNUmakefile +A UI/Contacts/Slovak.lproj/Localizable.strings +M UI/MailPartViewers/GNUmakefile +A UI/MailPartViewers/Slovak.lproj/Localizable.strings +M UI/MailerUI/GNUmakefile +A UI/MailerUI/Slovak.lproj/Localizable.strings +M UI/MainUI/BrazilianPortuguese.lproj/Localizable.strings +M UI/MainUI/Catalan.lproj/Localizable.strings +M UI/MainUI/Czech.lproj/Localizable.strings +M UI/MainUI/Danish.lproj/Localizable.strings +M UI/MainUI/Dutch.lproj/Localizable.strings +M UI/MainUI/English.lproj/Localizable.strings +M UI/MainUI/French.lproj/Localizable.strings +M UI/MainUI/GNUmakefile +M UI/MainUI/German.lproj/Localizable.strings +M UI/MainUI/Hungarian.lproj/Localizable.strings +M UI/MainUI/Icelandic.lproj/Localizable.strings +M UI/MainUI/Italian.lproj/Localizable.strings +M UI/MainUI/NorwegianBokmal.lproj/Localizable.strings +M UI/MainUI/NorwegianNynorsk.lproj/Localizable.strings +M UI/MainUI/Polish.lproj/Localizable.strings +M UI/MainUI/Russian.lproj/Localizable.strings +A UI/MainUI/Slovak.lproj/Locale +A UI/MainUI/Slovak.lproj/Localizable.strings +M UI/MainUI/SpanishArgentina.lproj/Localizable.strings +M UI/MainUI/SpanishSpain.lproj/Localizable.strings +M UI/MainUI/Swedish.lproj/Localizable.strings +M UI/MainUI/Ukrainian.lproj/Localizable.strings +M UI/MainUI/Welsh.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/French.lproj/Localizable.strings +M UI/PreferencesUI/GNUmakefile +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 +A 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/Ukrainian.lproj/Localizable.strings +M UI/PreferencesUI/Welsh.lproj/Localizable.strings +M UI/Scheduler/GNUmakefile +A UI/Scheduler/Slovak.lproj/Localizable.strings +A UI/Templates/SOGoACLSlovakAdditionAdvisory.wox +A UI/Templates/SOGoACLSlovakModificationAdvisory.wox +A UI/Templates/SOGoACLSlovakRemovalAdvisory.wox +A UI/Templates/SOGoFolderSlovakAdditionAdvisory.wox +A UI/Templates/SOGoFolderSlovakRemovalAdvisory.wox + +commit 96f023d108c3304393f30436f93ac81b321cc968 +Author: Francis Lachapelle +Date: Thu Nov 29 14:00:10 2012 -0500 + + Mail: Improve iCal viewer + +M UI/Templates/MailPartViewers/UIxMailPartICalViewer.wox +M UI/WebServerResources/MailerUI.css + +commit f2da438a2b7b57a4ce026edf56625d7b409a862f +Author: extrafu +Date: Tue Nov 27 21:07:11 2012 -0500 + + Fixed typo + +M NEWS + +commit e1411e7120d8464c84abca45bdf25ee9947ad09a +Author: Francis Lachapelle +Date: Tue Nov 27 16:43:26 2012 -0500 + + Update NEWS file + +M NEWS + +commit cbfb6eb9ffa7e08b919a51e0c1b19e2e7abe1d66 +Author: Francis Lachapelle +Date: Tue Nov 27 16:37:55 2012 -0500 + + Update NEWS file + +M NEWS + +commit 14630ce222b4c4c43cf5ed04999dd02f5bf5edaf +Author: Francis Lachapelle +Date: Tue Nov 27 15:53:39 2012 -0500 + + Improve memory usage of "sogo-tool restore" + + Used an autorelease pool. + +M Tools/SOGoToolRestore.m + +commit e523926ef561e29064953a9db000733894df27d6 +Author: Francis Lachapelle +Date: Tue Nov 27 15:14:30 2012 -0500 + + iCalTrigger: fix initialization of variable + +M SOPE/NGCards/iCalTrigger.m + +commit 57e4116d7c08854069b5041ecbf1bf587b0972ce +Author: Francis Lachapelle +Date: Tue Nov 27 10:44:43 2012 -0500 + + Cleanup + +M UI/WebServerResources/generic.js + +commit 1d0eb6678170580180864d385bc58308b721d170 +Author: Francis Lachapelle +Date: Tue Nov 27 10:37:14 2012 -0500 + + Place caret at proper position in HTML replies + + Removed constraint in preferences module that would limit the reply + placement of HTML mail to be before the quote. We now properly place the + caret at the bottom, before the signature, when the user has chosen to + start her reply bellow the quote in HTML mode. + +M UI/WebServerResources/UIxMailEditor.js +M UI/WebServerResources/UIxPreferences.js + +commit d75b04c59fc6a0ed944a73cfc134b43ec88e5d23 +Author: Francis Lachapelle +Date: Tue Nov 27 10:33:06 2012 -0500 + + Fix JS syntax for IE7 + +M UI/WebServerResources/ContactsUI.js + +commit 3e8f7cb29ea5034554669dd87d9f210903440b3d +Author: Francis Lachapelle +Date: Mon Nov 26 15:07:33 2012 -0500 + + Fix all-day event display in day/week view + + Fixes #2098 + +M UI/Scheduler/UIxCalListingActions.m + +commit 7c250fad8fbee5c51dd655af23058c20a710db82 +Author: Ludovic Marcotte +Date: Mon Nov 26 13:13:06 2012 -0500 + + Fix for bug #1061. + +M Documentation/SOGo Installation Guide.odt +M SoObjects/SOGo/LDAPSource.h +M SoObjects/SOGo/LDAPSource.m +M SoObjects/SOGo/SOGoSieveManager.m +M SoObjects/SOGo/SOGoUser.m +M SoObjects/SOGo/SQLSource.h +M SoObjects/SOGo/SQLSource.m + +commit 6d61e064a567c153239c216d13cad400961dbf6b +Author: Jean Raby +Date: Fri Nov 23 10:26:43 2012 -0500 + + Fix typos + +M Scripts/openchange_cleanup.py + +commit a5948b420bde1f01d4066a3c6449d8002aad9a8d +Author: Francis Lachapelle +Date: Thu Nov 22 10:57:21 2012 -0500 + + Simplify JS regexp to handle issue with FireFox + +M UI/WebServerResources/generic.js + +commit 1bf2509d1e821bdc2e1afc5998d3a1fc74ead9a4 +Author: Ludovic Marcotte +Date: Wed Nov 21 11:56:24 2012 -0500 + + Fix for bug #2115. + +M SoObjects/Appointments/SOGoCalendarComponent.m + +commit 249bf16e8a7f08910a958adfb469e50272967903 +Author: Francis Lachapelle +Date: Wed Nov 21 11:13:17 2012 -0500 + + Add missing localized string in preferences module + +M UI/PreferencesUI/English.lproj/Localizable.strings + +commit 7b65c29b1eb532de628188498cb51f86b6722cd4 +Author: Ludovic Marcotte +Date: Wed Nov 21 08:54:32 2012 -0500 + + Fixed \n /
when composing mails and improved preferences UI. + +M UI/MailerUI/UIxMailAccountActions.m +M UI/PreferencesUI/English.lproj/Localizable.strings +M UI/Templates/PreferencesUI/UIxPreferences.wox + +commit 28f66c6fd9407fa69a99511bfe6b7839de368f3f +Author: Ludovic Marcotte +Date: Tue Nov 20 20:29:27 2012 -0500 + + We correctly use
instead of \n when handling the signature. + + This happens when using HTML composition, instead of plain/text. + +M SoObjects/Mailer/SOGoDraftObject.m +M SoObjects/Mailer/SOGoMailForward.m + +commit cc98664d130d08d9c65c0dde332f334bda6e51e2 +Author: Ludovic Marcotte +Date: Tue Nov 20 15:21:49 2012 -0500 + + Fix for bug #2024. + +M OpenChange/MAPIStoreMailVolatileMessage.m + +commit 1fdcf843f30df64472d005729eedbea83a609616 +Author: Ludovic Marcotte +Date: Tue Nov 20 08:30:41 2012 -0500 + + Slightly improved previous commit to avoid losing X- elements. + +M SOPE/NGCards/CardVersitRenderer.m +M SOPE/NGCards/iCalCalendar.m + +commit a1d092cab0b0c02b437c640ee7446a5aa5272bee +Author: Ludovic Marcotte +Date: Mon Nov 19 14:20:13 2012 -0500 + + Fix for #2093. + +M SOPE/NGCards/iCalCalendar.m +M SoObjects/Appointments/SOGoAppointmentFolderICS.m + +commit 2606787dd7f6a8f00901dd3e3abc2e345ed27935 +Author: Ludovic Marcotte +Date: Mon Nov 19 09:45:48 2012 -0500 + + Make sure we handle arrays, and not single-value string objects. + +M SoObjects/SOGo/SOGoGroup.m + +commit eec99de5d0eb18c819bb10995cdb03205a5b32a7 +Author: Francis Lachapelle +Date: Fri Nov 16 19:11:13 2012 -0500 + + Indentation + +M UI/Templates/Appointments/SOGoAptMailReceipt.wox + +commit 5bf71059827cb9b5af49bfc543a72c730a663046 +Author: Ludovic Marcotte +Date: Sun Nov 18 10:48:58 2012 -0500 + + Fix for bug #1783. + +M UI/Scheduler/UIxAppointmentActions.m +M UI/Scheduler/UIxAppointmentEditor.h +M UI/Scheduler/UIxComponentEditor.h +M UI/Scheduler/UIxComponentEditor.m + +commit 0979bd13aef99a578fcfac3c52b6c86c0745aae6 +Author: Ludovic Marcotte +Date: Sat Nov 17 17:16:00 2012 -0500 + + Fix for bug #2006. + +M SoObjects/Contacts/SOGoContactGCSFolder.m +M UI/Contacts/UIxContactsFilterPanel.m +M UI/Contacts/UIxContactsListActions.m +M UI/Templates/ContactsUI/UIxContactsFilterPanel.wox +M UI/WebServerResources/ContactsUI.js + +commit 40d6ce66d01e0c5f7d258fde94d9c531edbbe919 +Author: Ludovic Marcotte +Date: Sat Nov 17 16:43:49 2012 -0500 + + Small fix over previous commit. + +M SoObjects/Contacts/NGVCard+SOGo.m + +commit 8fd0966a236e568c8a61e28b614693601bc5ce53 +Author: Ludovic Marcotte +Date: Sat Nov 17 16:12:23 2012 -0500 + + Correctly loop among calendars. This fixes #2070. + +M UI/Scheduler/UIxCalFolderActions.m + +commit 3f8d374d638f9259254deefe0d856e58e73368a2 +Author: Ludovic Marcotte +Date: Sat Nov 17 15:38:29 2012 -0500 + + Fix for bug #2035 + +M SoObjects/Appointments/SOGoAppointmentFolder.m + +commit 77e4b3307fa9bd89afc4c20ff664f59f1ca02e47 +Author: Ludovic Marcotte +Date: Sat Nov 17 15:33:07 2012 -0500 + + Fix for bug #2106 + +M SOPE/NGCards/CardElement.m +M SoObjects/Contacts/NGVCard+SOGo.m +M SoObjects/Contacts/NSDictionary+LDIF.m +M SoObjects/Contacts/SOGoContactLDIFEntry.m +M UI/Contacts/UIxContactFolderActions.m + +commit 378eef408236051f5bcb44011f20a51ed1fe3fe8 +Author: Jean Raby +Date: Tue Nov 13 17:20:18 2012 -0500 + + Use GCSSpecialQueries in sogo-tool rename-user + + Fixes #1924 + The SQL syntax used by the former query would only work + with postgresql and Oracle. + +M SOPE/GDLContentStore/GCSSpecialQueries.m +M Tools/SOGoToolRenameUser.m + +commit 8c96f717c07c125b6c4b838bcaefd77bc899b6ef +Author: Francis Lachapelle +Date: Tue Nov 13 16:25:20 2012 -0500 + + Update Prototype JS to version 1.7.1 + + .. and fixed namespace conflict in dtree.js (Node => dtreeNode) + +M UI/WebServerResources/AdministrationUI.js +M UI/WebServerResources/HTMLElement.js +M UI/WebServerResources/MailerUI.js +M UI/WebServerResources/SOGoResizableTable.js +M UI/WebServerResources/UIxContactsUserFolders.js +M UI/WebServerResources/dtree.js +M UI/WebServerResources/prototype.js + +commit 33bd07a53d76317f2eeac6c518c3a0495126369d +Author: Francis Lachapelle +Date: Tue Nov 13 16:22:27 2012 -0500 + + Fix user rights editor in calendar module + +M UI/WebServerResources/UIxCalUserRightsEditor.css + +commit fb4b266b3bfff65f69a98984433293905ddee975 +Author: Francis Lachapelle +Date: Tue Nov 13 16:13:56 2012 -0500 + + Improve user rights editor in calendar module + +M UI/WebServerResources/UIxCalUserRightsEditor.css + +commit d82ba7cbb96e55950da133bcfced87d0af131539 +Author: Jean Raby +Date: Tue Nov 13 15:01:30 2012 -0500 + + Reorder VCALENDAR template elements + + It must match [iCalCalendar orderOfElements] + +M Tests/Integration/test-davacl.py + +commit 51192dd5338f43570382d3dc942b083933430dda +Author: Ludovic Marcotte +Date: Tue Nov 13 13:58:05 2012 -0500 + + We now order correctly CardGroups - especially for calendars. + + This is to avoid a bug in BlackBerry devices where the METHOD + must be placed BEFORE any vevent/vtimezone objects, otherwise + the invitation objects are never recognized, and rather shown + as a "application/x-rimdevicecalendar" attachment. + +M SOPE/NGCards/CardElement.h +M SOPE/NGCards/CardElement.m +M SOPE/NGCards/CardGroup.h +M SOPE/NGCards/CardGroup.m +M SOPE/NGCards/CardVersitRenderer.m +M SOPE/NGCards/iCalCalendar.h +M SOPE/NGCards/iCalCalendar.m +M SoObjects/Appointments/SOGoAppointmentObject.m + +commit b088f6f97f897520d469e860b3ff740c5bc2a4ba +Author: Francis Lachapelle +Date: Mon Nov 12 16:36:30 2012 -0500 + + Fix scrolling for calendars/addressbooks lists + +M UI/WebServerResources/ContactsUI.css +M UI/WebServerResources/SchedulerUI.css +M UI/WebServerResources/SchedulerUI.js + +commit e037ca0a4914785c4f34a50613292fa0ddc08775 +Author: Francis Lachapelle +Date: Mon Nov 12 15:32:03 2012 -0500 + + Fix bug with reply-to header in messages + +M SoObjects/Mailer/SOGoDraftObject.m + +commit 48b6cbcf0cc25e993f5730b640d3f654356a24be +Author: Jean Raby +Date: Mon Nov 12 09:36:38 2012 -0500 + + Add missing dependency on lasso and lasso-devel + +M packaging/rhel/sogo.spec + +commit 3b0a497f2d715a470c2041065b09ab5425c1565f +Author: Wolfgang Sourdeau +Date: Fri Nov 9 14:50:56 2012 -0500 + + (hack) allow subcribers to read messages from "Freebusy Data" root folder + +M OpenChange/MAPIStoreDBFolder.m + +commit 58d6a3c5eac67066ed5d8380664391e1d0627c07 +Author: Wolfgang Sourdeau +Date: Thu Nov 8 19:40:44 2012 -0500 + + Style + +M Scripts/openchange_cleanup.py + +commit c3c5e464a9cdd59feb808eab814afd711e3fa67f +Author: Wolfgang Sourdeau +Date: Thu Nov 8 19:36:32 2012 -0500 + + Restored cleanup of IMAP folders created by Outlook + +M Scripts/openchange_cleanup.py + +commit 303eaa38207a563c6f07d2420751be9d5f29cf72 +Author: Wolfgang Sourdeau +Date: Thu Nov 8 19:31:23 2012 -0500 + + Enable the reading of system-wide user defaults + +M Scripts/openchange_cleanup.py + +commit d797868d71099bcb8ae09ea5eec6fad5adddae97 +Author: Wolfgang Sourdeau +Date: Thu Nov 8 19:15:00 2012 -0500 + + asCSSIdentifier: made conversion faster by using a list + +M Scripts/openchange_cleanup.py + +commit 0ab36d4ec5b0079c72b42fd8717fda17744d0666 +Author: Francis Lachapelle +Date: Wed Nov 7 11:06:12 2012 -0500 + + Fix title display of cards with a photo + +M UI/WebServerResources/ContactsUI.css + +commit 3f58b6bfd135cd1b2a4f8dae897a436e38b49d76 +Author: Wolfgang Sourdeau +Date: Wed Nov 7 09:50:32 2012 -0500 + + Use the output of "gnustep-config --base-libs" to determine which libs our libraries must be linked against + +M OGoContentStore/GNUmakefile.preamble +M SOPE/GDLContentStore/GNUmakefile.preamble +M SOPE/NGCards/GNUmakefile.preamble +M SoObjects/SOGo/GNUmakefile.preamble +M UI/SOGoUI/GNUmakefile.preamble +M UI/common.make +M configure + +commit 160aa42b88234c5b484bb6628d78befe2a905d53 +Author: Wolfgang Sourdeau +Date: Wed Nov 7 09:49:46 2012 -0500 + + set the "check" target as a non-default target + +M Tests/Unit/GNUmakefile + +commit 0884a0f23ed063a5f5e2890fc4bf37d5a45b702f +Author: Luc Charland +Date: Tue Nov 6 15:39:14 2012 -0500 + + Modified CSS to move mail preference filter down + +M UI/WebServerResources/UIxPreferences.css + +commit 63024c30f07aca6710ccc0242228591dbf26f24d +Author: Wolfgang Sourdeau +Date: Tue Nov 6 13:50:26 2012 -0500 + + Make use of the new -[NSData compress] method and remove \n chars from base64 data + +M SoObjects/SOGo/SOGoWebAuthenticator.m + +commit 4b8a14e41eaf7ba43259eb4dce9e1c20c23e7603 +Author: Wolfgang Sourdeau +Date: Tue Nov 6 10:46:40 2012 -0500 + + Make use of SAML2 assertion as IMAP password + +M SoObjects/SOGo/SOGoWebAuthenticator.m + +commit ba67c57629241b54d2852c165fbf2296955582cf +Author: Wolfgang Sourdeau +Date: Tue Nov 6 10:46:11 2012 -0500 + + Save SAML2 assertion + +M SoObjects/SOGo/SOGoSAML2Session.h +M SoObjects/SOGo/SOGoSAML2Session.m + +commit 0f0b4926a9a2e41d81b9423bae35e2ba6952287a +Author: Wolfgang Sourdeau +Date: Tue Nov 6 10:45:53 2012 -0500 + + updated NEWS + +M NEWS + +commit 6ad59a8481972be77b1af56b93ec24dd6482aaf6 +Author: Ludovic Marcotte +Date: Tue Nov 6 09:04:18 2012 -0500 + + Apply patches for bug #2060 + +M SoObjects/SOGo/LDAPSource.m +M SoObjects/SOGo/NSString+Crypto.h +M SoObjects/SOGo/NSString+Crypto.m +M SoObjects/SOGo/SQLSource.m + +commit fe09a7969d5fe57468bd7540318da75111b767ab +Author: Ludovic Marcotte +Date: Tue Nov 6 08:05:23 2012 -0500 + + Automatically disable alarms for newly subsribed calendars. + + This fixes bug #2074. + +M SoObjects/SOGo/SOGoGCSFolder.m + +commit ca568ec5b548587f1ee3174d5be155ab9a215af2 +Author: Jean Raby +Date: Mon Nov 5 15:31:48 2012 -0500 + + Disable SAML2 on RHEL5 - its glib2 is prehistoric + +M packaging/rhel/sogo.spec + +commit 0a4809e2be49b89c0515d1ac63a3e0c89ac57455 +Author: Jean Raby +Date: Mon Nov 5 13:12:25 2012 -0500 + + Fix 'Show Raw Source' for tasks + +M UI/WebServerResources/SchedulerUI.js + +commit 627ebbaea904abdc51ebeda4729397a254837933 +Author: Wolfgang Sourdeau +Date: Mon Nov 5 10:34:46 2012 -0500 + + Updated documentation for NGImap4AuthMechanism + +M Documentation/SOGo Installation Guide.odt + +commit 48c41e6c62cd4cafd36f0fc19c5ad4c7f5428c42 +Author: Wolfgang Sourdeau +Date: Fri Nov 2 15:48:46 2012 -0400 + + Updated for SAML2 authentication + +M Documentation/SOGo Installation Guide.odt + +commit 9096f0b279c2b633057f1506290b2793437c793b +Author: Wolfgang Sourdeau +Date: Fri Nov 2 15:35:19 2012 -0400 + + Updates news + +M NEWS + +commit aeabd85c90e657b8b55831bd4c318bd8a9d421cf +Author: Wolfgang Sourdeau +Date: Fri Nov 2 15:31:49 2012 -0400 + + Finalized support for SAML2 logon + +M SoObjects/SOGo/SOGoSAML2Session.h +M SoObjects/SOGo/SOGoSAML2Session.m +M SoObjects/SOGo/SOGoSession.h +M SoObjects/SOGo/SOGoSession.m +M SoObjects/SOGo/SOGoWebAuthenticator.h +M SoObjects/SOGo/SOGoWebAuthenticator.m +M UI/Common/UIxPageFrame.m +M UI/MainUI/GNUmakefile.preamble +M UI/MainUI/SOGoRootPage.m +M UI/MainUI/SOGoSAML2Actions.m +M UI/MainUI/product.plist + +commit 695fc5fff9ec0fb5f0d4ffd1d5d07342d565e9fe +Author: Wolfgang Sourdeau +Date: Fri Nov 2 15:30:13 2012 -0400 + + added methods for supporting SAML2 configuration + +M SoObjects/SOGo/SOGoSystemDefaults.h +M SoObjects/SOGo/SOGoSystemDefaults.m + +commit 6840fbb96c25dee846aa8280e8e79e4e4cd4210a +Author: Wolfgang Sourdeau +Date: Fri Nov 2 15:29:02 2012 -0400 + + added methods for supporting SAML2 persistence + +M SoObjects/SOGo/SOGoCache.h +M SoObjects/SOGo/SOGoCache.m + +commit b905f42f470f4341b269453b2a49bde4969481fe +Author: Jean Raby +Date: Fri Nov 2 14:25:26 2012 -0400 + + Encode username when deleting socfs table contents + + Using the same encoding as NSString+Utilities asCSSIdentifier + +M Scripts/openchange_cleanup.py + +commit e02221d7163cace26e0dc3b0bd357964c0436e51 +Author: Wolfgang Sourdeau +Date: Fri Nov 2 13:54:52 2012 -0400 + + Auto-generate the SOGoSAML2Exceptions helper module + +M SoObjects/SOGo/GNUmakefile +A SoObjects/SOGo/gen-saml2-exceptions.py + +commit 9edab5ee4a765045eb18bdf5053e80b7923072ae +Author: Jean Raby +Date: Fri Nov 2 11:24:55 2012 -0400 + + Enable saml2 in rpms + +M packaging/rhel/sogo.spec + +commit bc2b003676fc0ca8479c57729be0366062adea14 +Author: Wolfgang Sourdeau +Date: Thu Nov 1 16:06:26 2012 -0400 + + Make use of pkg-config to retrieve gcc and ld options for liblasso + +M SoObjects/SOGo/GNUmakefile.preamble +M configure + +commit a9b521c8be61b5ffab3ab8c4279c1e7c7825157a +Author: Wolfgang Sourdeau +Date: Thu Nov 1 11:29:27 2012 -0400 + + Added SOGoSAML2Session + +A SoObjects/SOGo/SOGoSAML2Session.h +A SoObjects/SOGo/SOGoSAML2Session.m + +commit 157e66ad4f57cac2db87036f25ad03fdcdd494b0 +Author: Wolfgang Sourdeau +Date: Thu Nov 1 11:28:45 2012 -0400 + + added "--enable-saml2" configuration option and dependency on liblasso + +M SoObjects/SOGo/GNUmakefile +M SoObjects/SOGo/GNUmakefile.preamble +M UI/MainUI/GNUmakefile +M configure + +commit 39c2d43cef0f20950dc616aa48ce6f60b23d7e2e +Author: Wolfgang Sourdeau +Date: Thu Nov 1 10:48:10 2012 -0400 + + Implemented "saml2-metadata" web method to fetch the metadata corresponding to the current server + +M UI/MainUI/GNUmakefile +A UI/MainUI/SOGoSAML2Actions.m +M UI/MainUI/product.plist + +commit ac5f0bb95a3f8c7e1455525dc32ad54c3eb7de6e +Author: Wolfgang Sourdeau +Date: Thu Nov 1 10:46:51 2012 -0400 + + implemented +[SOGoSAML2Session metadata] + +M SoObjects/SOGo/GNUmakefile + +commit e31f8098493b75d8575d10dc6b8615d2f885a1c5 +Author: Wolfgang Sourdeau +Date: Thu Nov 1 10:27:27 2012 -0400 + + Use the system defaults when the user defaults are not availble + +M UI/SOGoUI/UIxComponent.m + +commit a916ac892703c45fc1c4d720e7baf73c747d45d7 +Author: Luc Charland +Date: Fri Oct 26 13:39:28 2012 -0400 + + Fixed bug #1105 Remote images display + + There now is a configurable default in mail preferences where + you can set remote images to display either Never or Always. + +M SoObjects/SOGo/SOGoUserDefaults.h +M SoObjects/SOGo/SOGoUserDefaults.m +M UI/PreferencesUI/English.lproj/Localizable.strings +M UI/PreferencesUI/UIxPreferences.m +M UI/Templates/MailerUI/UIxMailMainFrame.wox +M UI/Templates/PreferencesUI/UIxPreferences.wox +M UI/WebServerResources/MailerUI.js + +commit 21ee23e7dfb10510d83a7ac081050215d215dcf2 +Author: Wolfgang Sourdeau +Date: Tue Oct 30 16:59:22 2012 -0400 + + avoid comparisons that extend past the string length + +M SoObjects/SOGo/NSString+Utilities.m + +commit 1223a6c0ee91d3dc9a3189384424219034eaefbc +Author: Wolfgang Sourdeau +Date: Tue Oct 30 09:41:20 2012 -0400 + + make use of -[WOComponent componentBundle] + +M UI/Scheduler/UIxComponentEditor.m + +commit 806ea9fd13a307bf71762da938a49db0b1acd33f +Author: Wolfgang Sourdeau +Date: Tue Oct 30 08:49:51 2012 -0400 + + do not duplicate the result of method calls into a NSMutableString + +M SOPE/GDLContentStore/GCSFolder.m + +commit 40a1a51845d1476b0bd0bd4c8d0e4eaa56bba6b0 +Author: Wolfgang Sourdeau +Date: Tue Oct 30 08:49:02 2012 -0400 + + cache the "startDate" + +M SOPE/NGCards/iCalTimeZonePeriod.h +M SOPE/NGCards/iCalTimeZonePeriod.m + +commit 20cb769db1af72f878f0e19b13848e0c5630a32d +Author: Wolfgang Sourdeau +Date: Fri Oct 26 22:38:41 2012 -0400 + + style + +M SoObjects/SOGo/LDAPSource.m + +commit 2fdf4f55355377dffc8e696562fffaf1626be305 +Author: Francis Lachapelle +Date: Fri Oct 26 22:31:14 2012 -0400 + + Fix typos in Spanish (Spain) translation + +M SoObjects/Appointments/SpanishSpain.lproj/Localizable.strings + +commit 99296231194d352db4f9536035826b640a9f1a25 +Author: Wolfgang Sourdeau +Date: Thu Oct 25 21:58:34 2012 -0400 + + Accelerated basic page loading by caching the list of supported languages + +M SoObjects/SOGo/SOGoSystemDefaults.m + +commit cf0e0691f6edab754e911f7b5f50bf0c5e1180f1 +Author: Wolfgang Sourdeau +Date: Thu Oct 25 21:46:23 2012 -0400 + + Accelerated basic page loading by caching the user language + +M SoObjects/SOGo/SOGoUserDefaults.h +M SoObjects/SOGo/SOGoUserDefaults.m + +commit 1080bee3ba9749aad0dc28625081fc6a496f7280 +Author: Wolfgang Sourdeau +Date: Wed Oct 24 15:00:02 2012 -0400 + + style + +M ChangeLog + commit 389f4d4c19065341fd4a20fa8a72d8feebb90cbf Author: Wolfgang Sourdeau Date: Wed Oct 24 14:59:13 2012 -0400 diff --git a/Documentation/SOGo Installation Guide.odt b/Documentation/SOGo Installation Guide.odt index feb7c3526..88dd25ccf 100644 Binary files a/Documentation/SOGo Installation Guide.odt and b/Documentation/SOGo Installation Guide.odt differ diff --git a/Documentation/SOGo Mobile Devices Configuration.odt b/Documentation/SOGo Mobile Devices Configuration.odt index 4570bdaff..1732eaf05 100644 Binary files a/Documentation/SOGo Mobile Devices Configuration.odt and b/Documentation/SOGo Mobile Devices Configuration.odt differ diff --git a/Documentation/SOGo Mozilla Thunderbird Configuration.odt b/Documentation/SOGo Mozilla Thunderbird Configuration.odt index 303ccd7b2..87cc821f7 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 c8a3fcdb4..994b80d51 100644 Binary files a/Documentation/SOGo Native Microsoft Outlook Configuration.odt and b/Documentation/SOGo Native Microsoft Outlook Configuration.odt differ diff --git a/NEWS b/NEWS index b29bbd96b..a9d5b3f32 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,54 @@ +2.0.3 (2012-12-06) +------------------ + +New features + - support for SAML2 for single sign-on, with the help of the lasso library + - added support for the "AUTHENTICATE" command and SASL mechanisms + - added domain default SieveHostFieldName + - added a search field for tasks + +Enhancements + - search the contacts for the organization attribute + - in HTML mode, optionally place answer after the quoted text + - improved memory usage of "sogo-tool restore" + - fixed invitations status in OSX iCal.app/Calendar.app (cleanup RSVP attribute) + - now uses "imap4flags" instead of the deprecated "imapflags" + - added Slovak translation - thanks to Martin Pastor + - updated translations + +Bug fixes + - fixed LDIF import with categories + - imported events now keep their UID when possible + - fixed importation of multiple calendars + - fixed modification date when drag'n'droping events + - fixed missing 'from' header in Outlook + - fixed invitations in Outlook + - fixed JavaScript regexp for Firefox + - fixed JavaScript syntax for IE7 + - fixed all-day event display in day/week view + - fixed parsing of alarm + - fixed Sieve server URL fallback + - fixed Debian cronjob (spool directory cleanup) + +2.0.2a (2012-11-15) +------------------- + +Enhancements + - improved user rights editor in calendar module + - disable alarms for newly subsribed calendars + +Bug fixes + - fixed typos in Spanish (Spain) translation + - fixed display of raw source for tasks + - fixed title display of cards with a photo + - fixed null address in reply-to header of messages + - fixed scrolling for calendar/addressbooks lists + - fixed display of invitations on BlackBerry devices + - fixed sogo-tool rename-user for MySQL database + - fixed corrupted attachments in Webmail + - fixed parsing of URLs that can throw an exception + - fixed password encoding in user sources + 2.0.2 (2012-10-24) ------------------ diff --git a/OGoContentStore/GNUmakefile.preamble b/OGoContentStore/GNUmakefile.preamble index b2d9374e7..3a458580d 100644 --- a/OGoContentStore/GNUmakefile.preamble +++ b/OGoContentStore/GNUmakefile.preamble @@ -7,8 +7,7 @@ libOGoContentStore_LIBRARIES_DEPEND_UPON += \ -lNGExtensions \ -lEOControl \ -lSaxObjC \ - -lgnustep-base \ - -lobjc + $(BASE_LIBS) ADDITIONAL_INCLUDE_DIRS += -I. -I.. -I../SOPE -I../SoObjects @@ -29,4 +28,5 @@ test_quick_extract_TOOL_LIBS += \ -lNGCards \ -lGDLContentStore \ -lGDLAccess \ - -lOGoContentStore + -lOGoContentStore \ + $(BASE_LIBS) diff --git a/OpenChange/MAPIStoreAttachment.h b/OpenChange/MAPIStoreAttachment.h index c859e7c8a..bfa779b85 100644 --- a/OpenChange/MAPIStoreAttachment.h +++ b/OpenChange/MAPIStoreAttachment.h @@ -48,7 +48,7 @@ - (NSData *) mimeAttachTag; /* move & copy operations */ -- (void) copyToAttachment: (MAPIStoreAttachment *) newAttachment; +- (void) copyToAttachment: (MAPIStoreAttachment *) newAttachment inMemCtx: (TALLOC_CTX *) memCtx; /* subclasses */ - (MAPIStoreEmbeddedMessage *) openEmbeddedMessage; diff --git a/OpenChange/MAPIStoreAttachment.m b/OpenChange/MAPIStoreAttachment.m index 5e7c69180..cb85911e3 100644 --- a/OpenChange/MAPIStoreAttachment.m +++ b/OpenChange/MAPIStoreAttachment.m @@ -152,13 +152,13 @@ return ULLONG_MAX; } -- (void) copyToAttachment: (MAPIStoreAttachment *) newAttachment +- (void) copyToAttachment: (MAPIStoreAttachment *) newAttachment inMemCtx: (TALLOC_CTX *) memCtx { void *attachMethod; enum mapistore_error error; MAPIStoreEmbeddedMessage *embeddedMessage, *newEmbeddedMessage; - [self copyPropertiesToObject: newAttachment]; + [self copyPropertiesToObject: newAttachment inMemCtx: memCtx]; attachMethod = NULL; error = [self getProperty: &attachMethod @@ -170,7 +170,7 @@ { embeddedMessage = [self openEmbeddedMessage]; newEmbeddedMessage = [newAttachment createEmbeddedMessage]; - [embeddedMessage copyToMessage: newEmbeddedMessage]; + [embeddedMessage copyToMessage: newEmbeddedMessage inMemCtx: memCtx]; } talloc_free (attachMethod); } diff --git a/OpenChange/MAPIStoreCalendarFolder.m b/OpenChange/MAPIStoreCalendarFolder.m index eeb5bb81e..5cab28712 100644 --- a/OpenChange/MAPIStoreCalendarFolder.m +++ b/OpenChange/MAPIStoreCalendarFolder.m @@ -63,6 +63,8 @@ SOGoAppointmentObject *newEntry; NSString *name; + [self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__]; + name = [NSString stringWithFormat: @"%@.ics", [SOGoObject globallyUniqueObjectId]]; newEntry = [SOGoAppointmentObject objectWithName: name diff --git a/OpenChange/MAPIStoreDBFolder.m b/OpenChange/MAPIStoreDBFolder.m index cacbb2376..e7d90f5a7 100644 --- a/OpenChange/MAPIStoreDBFolder.m +++ b/OpenChange/MAPIStoreDBFolder.m @@ -337,7 +337,18 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact"; - (BOOL) subscriberCanReadMessages { - return [self _testRoleForActiveUser: MAPIStoreRightReadItems]; + NSString *displayName; + + /* when this folder is the "Freebusy Data" folder, we need to allow + subscribed to read an open contained messages in order to enable them to + find the "LocalFreebusy" message */ + [sogoObject reloadIfNeeded]; + + displayName = [[sogoObject properties] + objectForKey: MAPIPropertyKey (PidTagDisplayName)]; + + return ([displayName isEqualToString: @"Freebusy Data"] + || [self _testRoleForActiveUser: MAPIStoreRightReadItems]); } - (BOOL) subscriberCanDeleteMessages diff --git a/OpenChange/MAPIStoreFolder.h b/OpenChange/MAPIStoreFolder.h index c5a7bd72e..7b769ac5f 100644 --- a/OpenChange/MAPIStoreFolder.h +++ b/OpenChange/MAPIStoreFolder.h @@ -123,7 +123,8 @@ fromFolder: (MAPIStoreFolder *) sourceFolder withMIDs: (uint64_t *) targetMids andChangeKeys: (struct Binary_r **) targetChangeKeys - wantCopy: (uint8_t) want_copy; + wantCopy: (uint8_t) want_copy + inMemCtx: (TALLOC_CTX *) memCtx; - (enum mapistore_error) moveCopyToFolder: (MAPIStoreFolder *) targetFolder withNewName: (NSString *) newFolderName diff --git a/OpenChange/MAPIStoreFolder.m b/OpenChange/MAPIStoreFolder.m index e3ec06976..64a388fcb 100644 --- a/OpenChange/MAPIStoreFolder.m +++ b/OpenChange/MAPIStoreFolder.m @@ -180,6 +180,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe - (void) dealloc { + [self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__]; + // [messageKeys release]; // [faiMessageKeys release]; // [folderKeys release]; @@ -656,19 +658,23 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe return rc; } -- (int) moveCopyMessageWithMID: (uint64_t) srcMid - fromFolder: (MAPIStoreFolder *) sourceFolder - withMID: (uint64_t) targetMid - andChangeKey: (struct Binary_r *) targetChangeKey - wantCopy: (uint8_t) wantCopy +// private method +- (int) _moveCopyMessageWithMID: (uint64_t) srcMid + fromFolder: (MAPIStoreFolder *) sourceFolder + withMID: (uint64_t) targetMid + andChangeKey: (struct Binary_r *) targetChangeKey + wantCopy: (uint8_t) wantCopy + inMemCtx: (TALLOC_CTX *) memCtx { int rc; MAPIStoreMessage *sourceMsg, *destMsg; - TALLOC_CTX *memCtx; + //TALLOC_CTX *memCtx; struct SRow aRow; struct SPropValue property; - memCtx = talloc_zero (NULL, TALLOC_CTX); + [self logWithFormat: @"-moveCopyMessageWithMID: 0x%.16llx .. withMID: 0x%.16llx .. wantCopy: %d", srcMid, targetMid, wantCopy]; + + //memCtx = talloc_zero (NULL, TALLOC_CTX); rc = [sourceFolder openMessage: &sourceMsg withMID: srcMid forWriting: NO @@ -681,7 +687,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe if (rc != MAPISTORE_SUCCESS) goto end; - [sourceMsg copyToMessage: destMsg]; + [sourceMsg copyToMessage: destMsg inMemCtx: memCtx]; if (targetChangeKey) { @@ -698,7 +704,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe rc = [sourceFolder deleteMessageWithMID: srcMid andFlags: 0]; end: - talloc_free (memCtx); + //talloc_free (memCtx); return rc; } @@ -709,6 +715,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe withMIDs: (uint64_t *) targetMids andChangeKeys: (struct Binary_r **) targetChangeKeys wantCopy: (uint8_t) wantCopy + inMemCtx: (TALLOC_CTX *) memCtx { int rc = MAPISTORE_SUCCESS; NSUInteger count; @@ -717,6 +724,9 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe MAPIStoreMapping *mapping; SOGoUser *ownerUser; struct Binary_r *targetChangeKey; + //TALLOC_CTX *memCtx; + + //memCtx = talloc_zero (NULL, TALLOC_CTX); ownerUser = [[self userContext] sogoUser]; @@ -738,11 +748,12 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe targetChangeKey = targetChangeKeys[count]; else targetChangeKey = NULL; - rc = [self moveCopyMessageWithMID: srcMids[count] - fromFolder: sourceFolder - withMID: targetMids[count] - andChangeKey: targetChangeKey - wantCopy: wantCopy]; + rc = [self _moveCopyMessageWithMID: srcMids[count] + fromFolder: sourceFolder + withMID: targetMids[count] + andChangeKey: targetChangeKey + wantCopy: wantCopy + inMemCtx: memCtx]; } else rc = MAPISTORE_ERR_NOT_FOUND; @@ -765,7 +776,9 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe } else rc = MAPISTORE_ERR_DENIED; - + + //talloc_free (memCtx); + return rc; } @@ -785,6 +798,9 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe NSUInteger count, max; NSString *childKey; uint64_t fmid; + TALLOC_CTX *memCtx; + + memCtx = talloc_zero (NULL, TALLOC_CTX); /* TODO: one possible issue with this algorithm is that moved messages will lack a version number and will all be assigned a new one, even though @@ -807,7 +823,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe if (rc == MAPISTORE_SUCCESS) { newFolder = [targetFolder lookupFolder: childKey]; - [self copyPropertiesToObject: newFolder]; + [self copyPropertiesToObject: newFolder inMemCtx: memCtx]; pool = [NSAutoreleasePool new]; children = [self messageKeys]; @@ -818,7 +834,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe message = [self lookupMessage: childKey]; targetMessage = [newFolder createMessage: NO]; [targetMessage setIsNew: YES]; - [message copyToMessage: targetMessage]; + [message copyToMessage: targetMessage inMemCtx: memCtx]; if (isMove) { fmid = [mapping idFromURL: [message url]]; @@ -839,7 +855,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe message = [self lookupFAIMessage: childKey]; targetMessage = [newFolder createMessage: YES]; [targetMessage setIsNew: YES]; - [message copyToMessage: targetMessage]; + [message copyToMessage: targetMessage inMemCtx: memCtx]; if (isMove) { fmid = [mapping idFromURL: [message url]]; @@ -882,6 +898,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe else rc = MAPISTORE_ERR_DENIED; + talloc_free (memCtx); + return rc; } diff --git a/OpenChange/MAPIStoreMailFolder.m b/OpenChange/MAPIStoreMailFolder.m index 9271751a2..3a2d2bb2f 100644 --- a/OpenChange/MAPIStoreMailFolder.m +++ b/OpenChange/MAPIStoreMailFolder.m @@ -929,6 +929,8 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP) withMIDs: (uint64_t *) targetMids andChangeKeys: (struct Binary_r **) targetChangeKeys wantCopy: (uint8_t) wantCopy + inMemCtx: (TALLOC_CTX *) memCtx + { NGImap4Connection *connection; NGImap4Client *client; @@ -946,7 +948,8 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP) return [super moveCopyMessagesWithMIDs: srcMids andCount: midCount fromFolder: sourceFolder withMIDs: targetMids andChangeKeys: targetChangeKeys - wantCopy: wantCopy]; + wantCopy: wantCopy + inMemCtx: memCtx]; /* Conversion of mids to IMAP uids */ mapping = [self mapping]; diff --git a/OpenChange/MAPIStoreMailVolatileMessage.m b/OpenChange/MAPIStoreMailVolatileMessage.m index b72bfc27f..9193794dd 100644 --- a/OpenChange/MAPIStoreMailVolatileMessage.m +++ b/OpenChange/MAPIStoreMailVolatileMessage.m @@ -569,7 +569,7 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers, } list = MakeRecipientsList ([recipients objectForKey: @"orig"]); - if (list) + if ([list count]) [headers setObjects: list forKey: @"from"]; } else diff --git a/OpenChange/MAPIStoreMessage.h b/OpenChange/MAPIStoreMessage.h index c782cb0d6..06ca45436 100644 --- a/OpenChange/MAPIStoreMessage.h +++ b/OpenChange/MAPIStoreMessage.h @@ -71,7 +71,7 @@ - (NSArray *) activeUserRoles; /* move & copy internal ops */ -- (void) copyToMessage: (MAPIStoreMessage *) newMessage; +- (void) copyToMessage: (MAPIStoreMessage *) newMessage inMemCtx: (TALLOC_CTX *) memCtx; /* subclasses */ - (void) save; diff --git a/OpenChange/MAPIStoreMessage.m b/OpenChange/MAPIStoreMessage.m index c1445f6c2..0751c993d 100644 --- a/OpenChange/MAPIStoreMessage.m +++ b/OpenChange/MAPIStoreMessage.m @@ -139,6 +139,8 @@ rtf2html (NSData *compressedRTF) - (id) init { + [self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self]; + if ((self = [super init])) { attachmentParts = [NSMutableDictionary new]; @@ -151,6 +153,7 @@ rtf2html (NSData *compressedRTF) - (void) dealloc { + [self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self]; [activeUserRoles release]; [attachmentKeys release]; [attachmentParts release]; @@ -437,17 +440,19 @@ rtf2html (NSData *compressedRTF) andType: MAPISTORE_MESSAGE_TABLE]; } -- (void) copyToMessage: (MAPIStoreMessage *) newMessage +- (void) copyToMessage: (MAPIStoreMessage *) newMessage inMemCtx: (TALLOC_CTX *) memCtx; { - TALLOC_CTX *memCtx; + //TALLOC_CTX *memCtx; struct mapistore_message *messageData; NSArray *keys; NSUInteger count, max; NSString *key; MAPIStoreAttachment *attachment, *newAttachment; - memCtx = talloc_zero (NULL, TALLOC_CTX); + [self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self]; + + //memCtx = talloc_zero (NULL, TALLOC_CTX); /* message headers and recipients */ [self getMessageData: &messageData inMemCtx: memCtx]; @@ -456,7 +461,7 @@ rtf2html (NSData *compressedRTF) andColumns: messageData->columns]; /* properties */ - [self copyPropertiesToObject: newMessage]; + [self copyPropertiesToObject: newMessage inMemCtx: memCtx]; /* attachments */ keys = [self attachmentKeys]; @@ -466,10 +471,10 @@ rtf2html (NSData *compressedRTF) key = [keys objectAtIndex: count]; attachment = [self lookupAttachment: key]; newAttachment = [newMessage createAttachment]; - [attachment copyToAttachment: newAttachment]; + [attachment copyToAttachment: newAttachment inMemCtx: memCtx]; } - talloc_free (memCtx); + //talloc_free (memCtx); } - (enum mapistore_error) saveMessage @@ -485,6 +490,8 @@ rtf2html (NSData *compressedRTF) BOOL userIsOwner; MAPIStoreMessage *mainMessage; + [self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__]; + context = [self context]; ownerUser = [[self userContext] sogoUser]; userIsOwner = [[context activeUser] isEqual: ownerUser]; diff --git a/OpenChange/MAPIStoreObject.h b/OpenChange/MAPIStoreObject.h index d7aa989de..c5a466ac3 100644 --- a/OpenChange/MAPIStoreObject.h +++ b/OpenChange/MAPIStoreObject.h @@ -91,7 +91,7 @@ inMemCtx: (TALLOC_CTX *) memCtx; /* move and copy operations */ -- (void) copyPropertiesToObject: (MAPIStoreObject *) newObject; +- (void) copyPropertiesToObject: (MAPIStoreObject *) newObject inMemCtx: (TALLOC_CTX *) memCtx; /* subclasses */ - (NSString *) nameInContainer; diff --git a/OpenChange/MAPIStoreObject.m b/OpenChange/MAPIStoreObject.m index 24310a926..7d4bb3219 100644 --- a/OpenChange/MAPIStoreObject.m +++ b/OpenChange/MAPIStoreObject.m @@ -317,9 +317,9 @@ static Class NSExceptionK, MAPIStoreFolderK; } /* move and copy operations */ -- (void) copyPropertiesToObject: (MAPIStoreObject *) newObject +- (void) copyPropertiesToObject: (MAPIStoreObject *) newObject inMemCtx: (TALLOC_CTX *) memCtx { - TALLOC_CTX *memCtx; + //TALLOC_CTX *memCtx; struct SPropTagArray *availableProps; struct SRow row; enum MAPITAGS propTag; @@ -328,7 +328,7 @@ static Class NSExceptionK, MAPIStoreFolderK; enum mapistore_error error; void *data; - memCtx = talloc_zero (NULL, TALLOC_CTX); + //memCtx = talloc_zero (NULL, TALLOC_CTX); [self getAvailableProperties: &availableProps inMemCtx: memCtx]; @@ -369,8 +369,7 @@ static Class NSExceptionK, MAPIStoreFolderK; } [newObject addPropertiesFromRow: &row]; - talloc_free (memCtx); - + //talloc_free (memCtx); } /* subclasses */ diff --git a/OpenChange/MAPIStoreSOGo.m b/OpenChange/MAPIStoreSOGo.m index 7e219fe03..c88622e04 100644 --- a/OpenChange/MAPIStoreSOGo.m +++ b/OpenChange/MAPIStoreSOGo.m @@ -95,6 +95,7 @@ sogo_backend_init (void) defaults using the system encoding rather than honouring the encoding specified in the file. */ putenv ("GNUSTEP_STRING_ENCODING=NSUTF8StringEncoding"); + //putenv ("NSZombieEnabled=YES"); [NSProcessInfo initializeWithArguments: argv count: 1 @@ -567,6 +568,7 @@ sogo_folder_delete_message(void *folder_object, uint64_t mid, uint8_t flags) static enum mapistore_error sogo_folder_move_copy_messages(void *folder_object, void *source_folder_object, + TALLOC_CTX *mem_ctx, uint32_t mid_count, uint64_t *src_mids, uint64_t *t_mids, struct Binary_r **target_change_keys, @@ -594,7 +596,8 @@ sogo_folder_move_copy_messages(void *folder_object, fromFolder: sourceFolder withMIDs: t_mids andChangeKeys: target_change_keys - wantCopy: want_copy]; + wantCopy: want_copy + inMemCtx: mem_ctx]; [pool release]; GSUnregisterCurrentThread (); } diff --git a/OpenChange/NSObject+MAPIStore.m b/OpenChange/NSObject+MAPIStore.m index 930b13f11..958fb9208 100644 --- a/OpenChange/NSObject+MAPIStore.m +++ b/OpenChange/NSObject+MAPIStore.m @@ -50,7 +50,8 @@ MAPIStoreTallocWrapperDestroy (void *data) GSRegisterCurrentThread (); pool = [NSAutoreleasePool new]; wrapper = data; - // NSLog (@"destroying wrapped object (wrapper: %p; object: %p)...\n", wrapper, wrapper->MAPIStoreSOGoObject); + //NSLog (@"destroying wrapped object (wrapper: %p; object: %p)...\n", wrapper, wrapper->MAPIStoreSOGoObject); + NSLog (@"destroying wrapped object (wrapper: %p)", wrapper); [wrapper->instance release]; [pool release]; GSUnregisterCurrentThread (); @@ -66,7 +67,7 @@ MAPIStoreTallocWrapperDestroy (void *data) talloc_set_destructor ((void *) wrapper, MAPIStoreTallocWrapperDestroy); wrapper->instance = self; [self retain]; - // NSLog (@"returning wrapper: %p; object: %p", wrapper, self); + NSLog (@"returning wrapper: %p; object: %p", wrapper, self); return wrapper; } diff --git a/SOPE/GDLContentStore/GCSFolder.m b/SOPE/GDLContentStore/GCSFolder.m index ec9c0283a..af49f91ce 100644 --- a/SOPE/GDLContentStore/GCSFolder.m +++ b/SOPE/GDLContentStore/GCSFolder.m @@ -351,15 +351,12 @@ static GCSStringFormatter *stringFormatter = nil; - (NSString *) _selectedFields: (NSArray *) fields requirement: (GCSTableRequirement) requirement { - NSMutableString *selectedFields; - - selectedFields = [NSMutableString string]; + NSString *selectedFields; - if (requirement == bothTableRequired - && [fields containsObject: @"c_name"]) - [selectedFields appendString: [self _dottedFields: fields]]; + if (requirement == bothTableRequired && [fields containsObject: @"c_name"]) + selectedFields = [self _dottedFields: fields]; else - [selectedFields appendString: [fields componentsJoinedByString: @", "]]; + selectedFields = [fields componentsJoinedByString: @", "]; return selectedFields; } diff --git a/SOPE/GDLContentStore/GCSSpecialQueries.m b/SOPE/GDLContentStore/GCSSpecialQueries.m index e99afbaf5..95ab3f814 100644 --- a/SOPE/GDLContentStore/GCSSpecialQueries.m +++ b/SOPE/GDLContentStore/GCSSpecialQueries.m @@ -110,6 +110,14 @@ return nil; } +- (NSString *) updateCPathInFolderInfo: (NSString *) tableName + withCPath2: (NSString *) c_path2 +{ + [self subclassResponsibility: _cmd]; + + return nil; +} + @end @@ -205,6 +213,17 @@ return types; } +- (NSString *) updateCPathInFolderInfo: (NSString *) tableName + withCPath2: (NSString *) c_path2 +{ + static NSString *sqlFolderFormat + = (@"UPDATE %@" + @" SET c_path = '/'||c_path1||'/'||c_path2||'/'||c_path3||'/'||c_path4" + @" WHERE c_path2 = '%@'"); + + return [NSString stringWithFormat: sqlFolderFormat, tableName, c_path2]; +} + @end // @@ -299,6 +318,17 @@ return types; } +- (NSString *) updateCPathInFolderInfo: (NSString *) tableName + withCPath2: (NSString *) c_path2 +{ + static NSString *sqlFolderFormat + = (@"UPDATE %@" + @" SET c_path = CONCAT('/', c_path1, '/', c_path2, '/', c_path3, '/', c_path4)" + @" WHERE c_path2 = '%@'"); + + return [NSString stringWithFormat: sqlFolderFormat, tableName, c_path2]; +} + @end // @@ -392,4 +422,15 @@ return types; } +- (NSString *) updateCPathInFolderInfo: (NSString *) tableName + withCPath2: (NSString *) c_path2 +{ + static NSString *sqlFolderFormat + = (@"UPDATE %@" + @" SET c_path = '/'||c_path1||'/'||c_path2||'/'||c_path3||'/'||c_path4" + @" WHERE c_path2 = '%@'"); + + return [NSString stringWithFormat: sqlFolderFormat, tableName, c_path2]; +} + @end diff --git a/SOPE/GDLContentStore/GNUmakefile.preamble b/SOPE/GDLContentStore/GNUmakefile.preamble index 6c900d3a3..114432e71 100644 --- a/SOPE/GDLContentStore/GNUmakefile.preamble +++ b/SOPE/GDLContentStore/GNUmakefile.preamble @@ -8,11 +8,12 @@ ADDITIONAL_INCLUDE_DIRS += -I. -I.. # dependencies +BASE_LIBS := $(shell gnustep-config --base-libs) libGDLContentStore_LIBRARIES_DEPEND_UPON += \ -lGDLAccess \ -lNGExtensions -lEOControl \ - -lgnustep-base -lobjc + $(BASE_LIBS) GDLContentStore_LIBRARIES_DEPEND_UPON += \ -framework GDLAccess \ @@ -25,7 +26,7 @@ GCS_TOOL_LIBS += \ -lGDLContentStore -lGDLAccess \ -lNGExtensions -lEOControl \ -lDOM -lSaxObjC \ - -lgnustep-base + $(BASE_LIBS) else GCS_TOOL_LIBS += \ -framework GDLContentStore -framework GDLAccess \ diff --git a/SOPE/NGCards/CardElement.h b/SOPE/NGCards/CardElement.h index 7bccaa46f..21e6c4d1d 100644 --- a/SOPE/NGCards/CardElement.h +++ b/SOPE/NGCards/CardElement.h @@ -1,6 +1,6 @@ /* CardElement.h - this file is part of SOPE * - * Copyright (C) 2006 Inverse inc. + * Copyright (C) 2006-2012 Inverse inc. * * Author: Wolfgang Sourdeau * diff --git a/SOPE/NGCards/CardElement.m b/SOPE/NGCards/CardElement.m index 959c37f12..834caf671 100644 --- a/SOPE/NGCards/CardElement.m +++ b/SOPE/NGCards/CardElement.m @@ -1,6 +1,6 @@ /* CardElement.m - this file is part of SOPE * - * Copyright (C) 2006 Inverse inc. + * Copyright (C) 2006-2012 Inverse inc. * * Author: Wolfgang Sourdeau * @@ -424,16 +424,19 @@ } static inline BOOL -_subValuesAreVoid (NSArray *subValues) +_subValuesAreVoid (id subValues) { BOOL result = YES; NSUInteger count, max; result = YES; - max = [subValues count]; - for (count = 0; result && count < max; count++) - result = ([[subValues objectAtIndex: count] length] == 0); + if ([subValues isKindOfClass: [NSArray class]]) + { + max = [subValues count]; + for (count = 0; result && count < max; count++) + result = ([[subValues objectAtIndex: count] length] == 0); + } return result; } diff --git a/SOPE/NGCards/CardGroup.h b/SOPE/NGCards/CardGroup.h index 117d00c54..b70dc817e 100644 --- a/SOPE/NGCards/CardGroup.h +++ b/SOPE/NGCards/CardGroup.h @@ -75,6 +75,8 @@ - (void) replaceThisElement: (CardElement *) oldElement withThisOne: (CardElement *) newElement; +- (NSArray *) orderOfElements; + @end #endif /* CARDGROUP_H */ diff --git a/SOPE/NGCards/CardGroup.m b/SOPE/NGCards/CardGroup.m index 702257148..c9ecfb1f3 100644 --- a/SOPE/NGCards/CardGroup.m +++ b/SOPE/NGCards/CardGroup.m @@ -1,6 +1,6 @@ /* CardGroup.m - this file is part of SOPE * - * Copyright (C) 2006 Inverse inc. + * Copyright (C) 2006-2012 Inverse inc. * * Author: Wolfgang Sourdeau * @@ -454,4 +454,9 @@ static NGCardsSaxHandler *sax = nil; return new; } +- (NSArray *) orderOfElements +{ + return nil; +} + @end diff --git a/SOPE/NGCards/CardVersitRenderer.m b/SOPE/NGCards/CardVersitRenderer.m index 50894a831..db46bbd35 100644 --- a/SOPE/NGCards/CardVersitRenderer.m +++ b/SOPE/NGCards/CardVersitRenderer.m @@ -1,6 +1,6 @@ /* CardVersitRenderer.m - this file is part of SOPE * - * Copyright (C) 2006 Inverse inc. + * Copyright (C) 2006-2012 Inverse inc. * * Author: Wolfgang Sourdeau * @@ -107,6 +107,7 @@ CardElement *currentChild; NSMutableString *rendering; NSString *groupTag; + NSArray *order; rendering = [NSMutableString string]; @@ -120,7 +121,36 @@ groupTag = [groupTag uppercaseString]; [rendering appendFormat: @"BEGIN:%@\r\n", groupTag]; - children = [[aGroup children] objectEnumerator]; + + // We reorder the group elemments, if necessary + order = [aGroup orderOfElements]; + + if (order) + { + NSMutableArray *orderedElements, *originalElements; + NSArray *currentChildren; + int i, c; + + originalElements = [NSMutableArray arrayWithArray: [aGroup children]]; + orderedElements = [NSMutableArray array]; + c = [order count]; + + for (i = 0; i < c; i++) + { + currentChildren = [aGroup childrenWithTag: [order objectAtIndex: i]]; + [orderedElements addObjectsFromArray: currentChildren]; + [originalElements removeObjectsInArray: currentChildren]; + } + + // We add the remaining, unordered elements + [orderedElements addObjectsFromArray: originalElements]; + children = [orderedElements objectEnumerator]; + } + else + { + children = [[aGroup children] objectEnumerator]; + } + while ((currentChild = [children nextObject])) [rendering appendString: [self render: currentChild]]; [rendering appendFormat: @"END:%@\r\n", groupTag]; diff --git a/SOPE/NGCards/GNUmakefile.preamble b/SOPE/NGCards/GNUmakefile.preamble index 6fc0b523b..1652f8ac5 100644 --- a/SOPE/NGCards/GNUmakefile.preamble +++ b/SOPE/NGCards/GNUmakefile.preamble @@ -17,11 +17,13 @@ ADDITIONAL_INCLUDE_DIRS += \ # dependencies +BASE_LIBS := $(shell gnustep-config --base-libs) + libNGCards_LIBRARIES_DEPEND_UPON += \ -lNGExtensions \ -lEOControl \ -lSaxObjC \ - -lgnustep-base -lobjc -lm + $(BASE_LIBS) NGCards_LIBRARIES_DEPEND_UPON += \ -framework NGExtensions -framework EOControl \ diff --git a/SOPE/NGCards/iCalCalendar.h b/SOPE/NGCards/iCalCalendar.h index 7e95badb6..ec9f0b2d9 100644 --- a/SOPE/NGCards/iCalCalendar.h +++ b/SOPE/NGCards/iCalCalendar.h @@ -38,18 +38,6 @@ @class iCalTimeZone; @interface iCalCalendar : CardGroup -// { -// NSString *version; -// NSString *calscale; -// NSString *prodId; -// NSString *method; - -// NSMutableArray *todos; -// NSMutableArray *events; -// NSMutableArray *journals; -// NSMutableArray *freeBusys; -// NSMutableDictionary *timezones; -// } /* accessors */ diff --git a/SOPE/NGCards/iCalCalendar.m b/SOPE/NGCards/iCalCalendar.m index 7578d71a3..09f629cf1 100644 --- a/SOPE/NGCards/iCalCalendar.m +++ b/SOPE/NGCards/iCalCalendar.m @@ -210,6 +210,13 @@ return [super versitString]; } +- (NSArray *) orderOfElements +{ + return [NSArray arrayWithObjects: @"prodid", @"version", @"method", @"calscale", + @"vtimezone", @"vevent", @"vtodo", @"vjournal", @"vfreebusy", nil]; +} + + /* ical typing */ - (NSString *) entityName diff --git a/SOPE/NGCards/iCalTimeZonePeriod.h b/SOPE/NGCards/iCalTimeZonePeriod.h index ad56ab50a..f4d9af6ce 100644 --- a/SOPE/NGCards/iCalTimeZonePeriod.h +++ b/SOPE/NGCards/iCalTimeZonePeriod.h @@ -30,6 +30,9 @@ @class iCalRecurrenceRule; @interface iCalTimeZonePeriod : CardGroup +{ + NSCalendarDate *startDate; +} - (NSCalendarDate *) startDate; - (iCalRecurrenceRule *) recurrenceRule; diff --git a/SOPE/NGCards/iCalTimeZonePeriod.m b/SOPE/NGCards/iCalTimeZonePeriod.m index ac436f96d..a7e21879a 100644 --- a/SOPE/NGCards/iCalTimeZonePeriod.m +++ b/SOPE/NGCards/iCalTimeZonePeriod.m @@ -103,10 +103,21 @@ // return dayOfWeek; // } +- (void) dealloc +{ + [startDate release]; + [super dealloc]; +} + - (NSCalendarDate *) startDate { - return [(iCalDateTime *) [self uniqueChildWithTag: @"dtstart"] - dateTime]; + if (!startDate) + { + startDate = [(iCalDateTime *) [self uniqueChildWithTag: @"dtstart"] + dateTime]; + [startDate retain]; + } + return startDate; } - (iCalRecurrenceRule *) recurrenceRule diff --git a/SOPE/NGCards/iCalTrigger.m b/SOPE/NGCards/iCalTrigger.m index 19d8e3899..715bd1681 100644 --- a/SOPE/NGCards/iCalTrigger.m +++ b/SOPE/NGCards/iCalTrigger.m @@ -59,6 +59,7 @@ NSTimeInterval anInterval; id grandParent; + nextAlarmDate = nil; triggerValue = [[self valueType] uppercaseString]; if ([triggerValue length] == 0) triggerValue = @"DURATION"; @@ -88,8 +89,6 @@ } else if ([triggerValue isEqualToString: @"DATE-TIME"]) nextAlarmDate = [[self flattenedValuesForKey: @""] asCalendarDate]; - else - nextAlarmDate = nil; return nextAlarmDate; } diff --git a/Scripts/openchange_cleanup.py b/Scripts/openchange_cleanup.py index ba0ee777e..c646cff75 100755 --- a/Scripts/openchange_cleanup.py +++ b/Scripts/openchange_cleanup.py @@ -12,9 +12,11 @@ import sys imaphost = '127.0.0.1' imapport = 143 + sambaprivate = '/var/lib/samba/private' mapistorefolder = "%s/mapistore" % (sambaprivate) -sogoDefaultsFile = "/home/sogo/GNUstep/Defaults/.GNUstepDefaults" +sogoSysDefaultsFile = "/etc/sogo/sogo.conf" +sogoUserDefaultsFile = "/home/sogo/GNUstep/Defaults/.GNUstepDefaults" # - takes a username and optionally its password # - removes the entry in samba's ldap tree via ldbedit (NOTYET) @@ -23,7 +25,7 @@ sogoDefaultsFile = "/home/sogo/GNUstep/Defaults/.GNUstepDefaults" # - Delete the socfs_ table for the username. def usage(): - print """ + print """ %s [-i imaphost] ] [-p imapport] [-s sambaprivate] username [password] -i imaphost IMAP host to connect to [%s] -p imappost IMAP port to use [%d] @@ -31,60 +33,59 @@ def usage(): """ % (os.path.basename(sys.argv[0]), imaphost, imapport, sambaprivate) def main(): - global sambaprivate - global mapistorefolder - global imaphost - global imapport - try: - opts, args = getopt.getopt(sys.argv[1:], "i:p:s:") - except getopt.GetoptError, err: - print str(err) - usage() - sys.exit(2) + global sambaprivate + global mapistorefolder + global imaphost + global imapport + try: + opts, args = getopt.getopt(sys.argv[1:], "i:p:s:") + except getopt.GetoptError, err: + print str(err) + usage() + sys.exit(2) - for o, a in opts: - if o == "-i": - imaphost = a - elif o == "-p": - imapport = a - elif o == "-s": - sambaprivate = a - mapistorefolder = "%s/mapistore" % (sambaprivate) - else: - assert False, "unhandled option" + for o, a in opts: + if o == "-i": + imaphost = a + elif o == "-p": + imapport = a + elif o == "-s": + sambaprivate = a + mapistorefolder = "%s/mapistore" % (sambaprivate) + else: + assert False, "unhandled option" - argslen = len(args) - if (argslen == 2): - username = args[0] - userpass = args[1] - elif (argslen == 1): - username = args[0] - userpass = username - print "Using username as password" - else: - usage() - print "Specify a user (and optionally the password)" - sys.exit(2) + argslen = len(args) + if (argslen == 2): + username = args[0] + userpass = args[1] + elif (argslen == 1): + username = args[0] + userpass = username + print "Using username as password" + else: + usage() + print "Specify a user (and optionally the password)" + sys.exit(2) - # cleanup starts here - try: - imapCleanup(imaphost, imapport, username, userpass) - except Exception as e: - print "Error during imapCleanup, continuing: %s" % str(e) + # cleanup starts here + try: + imapCleanup(imaphost, imapport, username, userpass) + except Exception as e: + print "Error during imapCleanup, continuing: %s" % str(e) - try: - mapistoreCleanup(mapistorefolder, username) - except (shutil.Error, OSError) as e: - print "Error during mapistoreCleanup, continuing: %s" % str(e) + try: + mapistoreCleanup(mapistorefolder, username) + except (shutil.Error, OSError) as e: + print "Error during mapistoreCleanup, continuing: %s" % str(e) -# try: -# pass -# #ldbCleanup(sambaprivate, username) -# except ldb.LdbError as e: -# print "Error during ldbCleanup, continuing: %s" % str(e) - - sqlCleanup(username) + # try: + # pass + # #ldbCleanup(sambaprivate, username) + # except ldb.LdbError as e: + # print "Error during ldbCleanup, continuing: %s" % str(e) + sqlCleanup(username) def extractmb(si): inparen = False @@ -133,8 +134,7 @@ def cleanupmb(mb, client): else: print "mailbox '%s' coult NOT be deleted (code = '%s')" % (mb, code) -def imapCleanup(imaphost, imapport, username, userpass) : - +def imapCleanup(imaphost, imapport, username, userpass): client = imaplib.IMAP4(imaphost, imapport) (code, data) = client.login(username, userpass) if code != "OK": @@ -142,83 +142,113 @@ def imapCleanup(imaphost, imapport, username, userpass) : print "Logged in as '%s'" % username - for foldername in [ "Sync Issues", "Junk E-mail" ]: + for foldername in ("Sync Issues", "Junk E-mail"): (code, data) = client.list(foldername, "%") if code == "OK": for si in data: if si is not None: - print si - continue mb = extractmb(si) cleanupmb(mb, client) client.logout() def mapistoreCleanup(mapistorefolder, username): - # delete the user's folder under the mapistore and under mapistore/SOGo shutil.rmtree("%s/%s" % (mapistorefolder, username), ignore_errors=True) shutil.rmtree("%s/SOGo/%s" % (mapistorefolder, username), ignore_errors=True) -# NOTYET -#def ldbCleanup(sambaprivate, username): -# conn = ldb.Ldb("%s/openchange.ldb" % (sambaprivate)) -#### entries = conn.search(None, expression="(|(cn=%s)(MAPIStoreURI=sogo://%s:*)(MAPIStoreURI=sogo://%s@*))" % (username,username,username), -# entries = conn.search(None, expression="cn=%s" % (username), -# scope=ldb.SCOPE_SUBTREE) -# for entry in entries: -# print "Deleting %s" % (entry.dn) -# conn.delete(entry.dn) + # NOTYET + #def ldbCleanup(sambaprivate, username): + # conn = ldb.Ldb("%s/openchange.ldb" % (sambaprivate)) + #### entries = conn.search(None, expression="(|(cn=%s)(MAPIStoreURI=sogo://%s:*)(MAPIStoreURI=sogo://%s@*))" % (username,username,username), + # entries = conn.search(None, expression="cn=%s" % (username), + # scope=ldb.SCOPE_SUBTREE) + # for entry in entries: + # print "Deleting %s" % (entry.dn) + # conn.delete(entry.dn) def mysqlCleanup(dbhost, dbport, dbuser, dbpass, dbname, username): - import MySQLdb + import MySQLdb - conn= MySQLdb.connect(host=dbhost, port=int(dbport), user=dbuser, passwd=dbpass, db=dbname) - c=conn.cursor() - tablename="socfs_%s" % (username) - c.execute("TRUNCATE TABLE %s" % tablename) - print "Table %s emptied" + conn= MySQLdb.connect(host=dbhost, port=int(dbport), user=dbuser, passwd=dbpass, db=dbname) + c=conn.cursor() + tablename="socfs_%s" % (username) + c.execute("TRUNCATE TABLE %s" % tablename) + print "Table %s emptied" def postgresqlCleanup(dbhost, dbport, dbuser, dbpass, dbname, username): - import pg - conn = pg.connect(host=dbhost, port=int(dbport), user=dbuser, passwd=dbpass, dbname=dbname) - tablename = "socfs_%s" % username - conn.query("DELETE FROM %s" % tablename) - print "table '%s' emptied" % tablename + import pg + conn = pg.connect(host=dbhost, port=int(dbport), user=dbuser, passwd=dbpass, dbname=dbname) + tablename = "socfs_%s" % username + conn.query("DELETE FROM %s" % tablename) + print "table '%s' emptied" % tablename def getOCSFolderInfoURL(): - global sogoDefaultsFile - sogoDefaults = plistlib.readPlist(sogoDefaultsFile) - try: - OCSFolderInfoURL = sogoDefaults['sogod']['OCSFolderInfoURL'] - except KeyError: + global sogoSysDefaultsFile, sogoUserDefaultsFile + OCSFolderInfoURL = "" - return OCSFolderInfoURL + # read defaults from /etc/sogo/sogo.conf + if os.path.exists(sogoSysDefaultsFile): + sogoDefaults = plistlib.readPlist(sogoSysDefaultsFile) + if "OCSFolderInfoURL" in sogoDefaults: + OCSFolderInfoURL = sogoDefaults["OCSFolderInfoURL"] + + # defaults from user directory must have precedence + if os.path.exists(sogoUserDefaultsFile): + sogoDefaults = plistlib.readPlist(sogoUserDefaultsFile) + if "sogod" in sogoDefaults and "OCSFolderInfoURL" in sogoDefaults["sogod"]: + OCSFolderInfoURL = sogoDefaults['sogod']['OCSFolderInfoURL'] + + return OCSFolderInfoURL + +def asCSSIdentifier(inputString): + cssEscapingCharMap = {"_" : "_U_", + "." : "_D_", + "#" : "_H_", + "@" : "_A_", + "*" : "_S_", + ":" : "_C_", + "," : "_CO_", + " " : "_SP_", + "'" : "_SQ_", + "&" : "_AM_", + "+" : "_P_"} + + newChars = [] + + for c in inputString: + if c in cssEscapingCharMap: + newChars.append(cssEscapingCharMap[c]) + else: + newChars.append(c) + + return "".join(newChars) def sqlCleanup(username): - OCSFolderInfoURL = getOCSFolderInfoURL() - if (OCSFolderInfoURL is None): - raise Exception("Couldn't fetch OCSFolderInfoURL or it is not set. the socfs_%s table should be truncated manually" % (username)) + OCSFolderInfoURL = getOCSFolderInfoURL() + if OCSFolderInfoURL is None: + raise Exception("Couldn't fetch OCSFolderInfoURL or it is not set. the socfs_%s table should be truncated manually" % (username)) - # postgresql://sogo:sogo@127.0.0.1:5432/sogo/sogo_folder_info - m = re.search("(.+)://(.+):(.+)@(.+):(\d+)/(.+)/(.+)", OCSFolderInfoURL) + # postgresql://sogo:sogo@127.0.0.1:5432/sogo/sogo_folder_info + m = re.search("(.+)://(.+):(.+)@(.+):(\d+)/(.+)/(.+)", OCSFolderInfoURL) - proto = m.group(1) - dbuser = m.group(2) - dbpass = m.group(3) - dbhost = m.group(4) - dbport = m.group(5) - dbname = m.group(6) - # 7 is folderinfo table + proto = m.group(1) + dbuser = m.group(2) + dbpass = m.group(3) + dbhost = m.group(4) + dbport = m.group(5) + dbname = m.group(6) + # 7 is folderinfo table - if (proto == "postgresql"): - postgresqlCleanup(dbhost, dbport, dbuser, dbpass, dbname, username) - elif (proto == "mysql"): - mysqlCleanup(dbhost, dbport, dbuser, dbpass, dbname, username) - else: - raise Exception("Unknown sql proto: " % (proto)) + encodedUserName = asCSSIdentifier(username) + if (proto == "postgresql"): + postgresqlCleanup(dbhost, dbport, dbuser, dbpass, dbname, encodedUserName) + elif (proto == "mysql"): + mysqlCleanup(dbhost, dbport, dbuser, dbpass, dbname, encodedUserName) + else: + raise Exception("Unknown sql proto: " % (proto)) if __name__ == "__main__": - main() + main() diff --git a/Scripts/updates.php b/Scripts/updates.php index f17fc8d92..aec2cea87 100755 --- a/Scripts/updates.php +++ b/Scripts/updates.php @@ -28,22 +28,22 @@ $plugins = array( "sogo-connector@inverse.ca" => array( "application" => "thunderbird", - "version" => "10.0.3", - "filename" => "sogo-connector-10.0.3.xpi" ), + "version" => "17.0.2", + "filename" => "sogo-connector-17.0.2.xpi" ), "sogo-integrator@inverse.ca" => array( "application" => "thunderbird", - "version" => "10.0.3", - "filename" => "sogo-integrator-10.0.3.xpi" ), + "version" => "17.0.2", + "filename" => "sogo-integrator-17.0.2.xpi" ), "{e2fda1a4-762b-4020-b5ad-a41df1933103}" => array( "application" => "thunderbird", - "version" => "1.2.3", - "filename" => "lightning.xpi" ) + "version" => "1.9", + "filename" => "lightning-1.9.xpi" ) ); $applications = array( "thunderbird" => "{3550f703-e582-4d05-9a08-453d09bdfdc6} - 10.0 - 10.*" ); + 17.0 + 17.*" ); $pluginname = $_GET["plugin"]; $plugin =& $plugins[$pluginname]; diff --git a/SoObjects/Appointments/BrazilianPortuguese.lproj/Localizable.strings b/SoObjects/Appointments/BrazilianPortuguese.lproj/Localizable.strings index c1792439f..c9dcbb802 100644 --- a/SoObjects/Appointments/BrazilianPortuguese.lproj/Localizable.strings +++ b/SoObjects/Appointments/BrazilianPortuguese.lproj/Localizable.strings @@ -8,23 +8,15 @@ vtodo_class1 = "(Tarefa Privada)"; vtodo_class2 = "(Tarefa Confidencial)"; /* Receipts */ -"Title:" = "Título:"; -"Start:" = "Início:"; -"End:" = "Fim:"; - -"Receipt: users invited to a meeting" = "Recepção: usuários convidados para uma reunião"; -"You have invited the following attendees(s):" = "Você convidou o(s) seguinte(s) participante(s):"; -"... to attend the following event:" = ".. para participar do seguinte evento:"; - -"Receipt: invitation updated" = "Recepção: Convite atualizado"; -"The following attendees(s):" = "O(s) seguinte(s) participante(s):"; -"... have been notified of the changes to the following event:" = "... foi notificado das alterações do seguinte evento:"; - -"Receipt: attendees removed from an event" = "Recepção: participantes removidos de um evento"; -"You have removed the following attendees(s):" = "Você removeu o(s) seguinte(s) participante(s): "; -"... from the following event:" = "... do seguinte evento:"; +"The event \"%{Summary}\" was created" = "O evento \"%{Summary}\" foi criado"; +"The event \"%{Summary}\" was deleted" = "O evento \"%{Summary}\" foi removido"; +"The event \"%{Summary}\" was updated" = "O evento \"%{Summary}\" foi atualizado"; +"The following attendees(s) were notified:" = "Estes participantes foram notificados:"; +"The following attendees(s) were added:" = "Estes participantes foram adicionados:"; +"The following attendees(s) were removed:" = "Estes participantes foram removidos:"; /* IMIP messages */ +"calendar_label" = "Calendário:"; "startDate_label" = "Início:"; "endDate_label" = "Fim:"; "due_label" = "Data de Vencimento:"; @@ -35,14 +27,19 @@ vtodo_class2 = "(Tarefa Confidencial)"; /* Invitation */ "Event Invitation: \"%{Summary}\"" = "Convite do Evento: \"%{Summary}\""; "(sent by %{SentBy}) " = "(enviado por %{SentBy}) "; +"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" = "%{Organizer} %{SentByText}convidou você para %{Summary}.\n\nInicio: %{StartDate}\nFim: %{EndDate}\nDescrição: %{Description}"; "%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" = "%{Organizer} %{SentByText} convidou você para %{Summary}.\n\nInício: %{StartDate} as %{StartTime}\nFim: %{EndDate} as %{EndTime}\nDescrição: %{Description}"; /* Deletion */ "Event Cancelled: \"%{Summary}\"" = "Evento Cancelado: \"%{Summary}\""; +"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" += "%{Organizer} %{SentByText}cancelou este evento: %{Summary}.\n\nInicio: %{StartDate}\nFim: %{EndDate}\nDescrição: %{Description}"; "%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" = "%{Organizer} %{SentByText} cancelou este evento: %{Summary}.\n\nInício: %{StartDate} as %{StartTime}\nFim: %{EndDate} as %{EndTime}\nDescrição: %{Description}"; /* Update */ +"The appointment \"%{Summary}\" for the %{OldStartDate} has changed" += "O compromisso \"%{Summary}\" de %{OldStartDate} mudou"; "The appointment \"%{Summary}\" for the %{OldStartDate} at %{OldStartTime} has changed" = "O Compromisso \"%{Summary}\" de %{OldStartDate} as %{OldStartTime} mudou"; "The following parameters have changed in the \"%{Summary}\" meeting:" @@ -51,6 +48,10 @@ vtodo_class2 = "(Tarefa Confidencial)"; = "Por favor, aceitar ou recusar as alterações."; /* Reply */ +"Accepted invitation: \"%{Summary}\"" = "Convite aceito: \"%{Summary}\""; +"Declined invitation: \"%{Summary}\"" = "Convite recusado: \"%{Summary}\""; +"Delegated invitation: \"%{Summary}\"" = "Convite delegado: \"%{Summary}\""; +"Not yet decided on invitation: \"%{Summary}\"" = "Convite ainda não decidido: \"%{Summary}\""; "%{Attendee} %{SentByText}has accepted your event invitation." = "%{Attendee} %{SentByText}foi aceitado seu convite ao evento."; "%{Attendee} %{SentByText}has declined your event invitation." @@ -61,4 +62,5 @@ vtodo_class2 = "(Tarefa Confidencial)"; = "%{Attendee} %{SentByText}foi ainda não decidiu seu convite ao evento."; /* Resources */ -"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\"." = "Número máximo de reservas simultâneas (%{NumberOfSimultaneousBookings}) alcançadas para o recurso \"%{Cn} %{SystemEmail}\"."; +"Cannot access resource: \"%{Cn} %{SystemEmail}\"" = "Não foi possível acessar o recurso: \"%{Cn} %{SystemEmail}\""; +"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}." = "O número máximo de reservas simultaneas (%{NumberOfSimultaneousBookings}) acabou para o recurso \"%{Cn} %{SystemEmail}\". O evento conflitante é \"%{EventTitle}\", e inicia em %{StartDate}."; diff --git a/SoObjects/Appointments/GNUmakefile b/SoObjects/Appointments/GNUmakefile index b2aedc140..95a30972e 100644 --- a/SoObjects/Appointments/GNUmakefile +++ b/SoObjects/Appointments/GNUmakefile @@ -53,7 +53,7 @@ Appointments_RESOURCE_FILES += \ \ MSExchangeFreeBusySOAPRequest.wo -Appointments_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian SpanishSpain SpanishArgentina Swedish Ukrainian Welsh +Appointments_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh Appointments_LOCALIZED_RESOURCE_FILES = Localizable.strings diff --git a/SoObjects/Appointments/Polish.lproj/Localizable.strings b/SoObjects/Appointments/Polish.lproj/Localizable.strings index 51a70cff4..409dd5916 100644 --- a/SoObjects/Appointments/Polish.lproj/Localizable.strings +++ b/SoObjects/Appointments/Polish.lproj/Localizable.strings @@ -28,14 +28,14 @@ vtodo_class2 = "(Zadanie poufne)"; "Event Invitation: \"%{Summary}\"" = "Zaproszenie na wydarzenie: \"%{Summary}\""; "(sent by %{SentBy}) " = "(wysłane przez %{SentBy}) "; "%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" = "%{Organizer} %{SentByText}zaprosił Cię na %{Summary}.⏎ ⏎ Początek: %{StartDate}⏎ Koniec: %{EndDate}⏎ Opis: %{Description}"; -"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" = "%{Organizer} %{SentByText}zaprosił cię na %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}"; +"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" = "%{Organizer} %{SentByText}zaprosił cię na %{Summary}.\n\nPoczątek: %{StartDate} o %{StartTime}\nKoniec: %{EndDate} o %{EndTime}\nOpis: %{Description}"; /* Deletion */ "Event Cancelled: \"%{Summary}\"" = "Wydarzenie anulowane: \"%{Summary}\""; "%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" = "%{Organizer} %{SentByText} anulował(a) to wydarzenie: %{Summary}.⏎⏎ Początek: %{StartDate}⏎ Koniec: %{EndDate}⏎ Opis: %{Description}"; "%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" -= "%{Organizer} %{SentByText}anulował(a) to wydarzenie: %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}"; += "%{Organizer} %{SentByText}anulował(a) to wydarzenie: %{Summary}.\n\nPoczątek: %{StartDate} o %{StartTime}\nKoniec: %{EndDate} o %{EndTime}\nOpis: %{Description}"; /* Update */ "The appointment \"%{Summary}\" for the %{OldStartDate} has changed" diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index c4b761963..4f2946731 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -2885,11 +2885,26 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir timezone: (iCalTimeZone *) timezone { SOGoAppointmentObject *object; - NSString *uid; NSMutableString *content; + NSString *uid; uid = [self globallyUniqueObjectId]; [event setUid: uid]; + + // We first look if there's an event with the same UID in our calendar. If not, + // let's reuse what is in the event, otherwise generate a new GUID and use it. + uid = [event uid]; + + object = [self lookupName: uid + inContext: context + acquire: NO]; + + if (object && ![object isKindOfClass: [NSException class]]) + { + uid = [self globallyUniqueObjectId]; + [event setUid: uid]; + } + object = [SOGoAppointmentObject objectWithName: uid inContainer: self]; [object setIsNew: YES]; @@ -3024,7 +3039,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir acquire: NO]; if (master) { - // Associate the occurrence to the master event + // Associate the occurrence to the master event and skip the actual import process masterCalendar = [master calendar: NO secure: NO]; [masterCalendar addToEvents: event]; if (timezone) diff --git a/SoObjects/Appointments/SOGoAppointmentFolderICS.m b/SoObjects/Appointments/SOGoAppointmentFolderICS.m index 5289327ee..2f9fd46f8 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolderICS.m +++ b/SoObjects/Appointments/SOGoAppointmentFolderICS.m @@ -1,8 +1,6 @@ /* SOGoAppointmentFolderICS.m - this file is part of SOGo * - * Copyright (C) 2010 Inverse inc. - * - * Author: Wolfgang Sourdeau + * Copyright (C) 2010-2012 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 @@ -22,6 +20,7 @@ #import +#import #import #import "SOGoAppointmentFolderICS.h" @@ -30,7 +29,19 @@ - (NSString *) contentAsString { - return [[self contentCalendar] versitString]; + iCalCalendar *cal; + CardElement *e; + NSString *s; + + cal = [self contentCalendar]; + + e = [CardElement simpleElementWithTag: @"x-wr-calname" + value: [self displayName]]; + [cal addChild: e]; + s = [cal versitString]; + [cal removeChild: e]; + + return s; } - (NSString *) davContentType diff --git a/SoObjects/Appointments/SOGoAppointmentObject.m b/SoObjects/Appointments/SOGoAppointmentObject.m index 09eefec8a..3809eb6cb 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.m +++ b/SoObjects/Appointments/SOGoAppointmentObject.m @@ -410,14 +410,6 @@ previousObject: oldEvent toAttendees: updateAttendees withType: @"calendar:invitation-update"]; - -#if 0 - // DELETE CODE - [self sendReceiptEmailForObject: newEvent - addedAttendees: nil - deletedAttendees: nil - updatedAttendees: updateAttendees]; -#endif } // @@ -968,6 +960,10 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent [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]]) @@ -999,7 +995,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent // -// This method is invoked from the SOGo Web interface. +// This method is invoked from the SOGo Web interface or from the DAV interface. // // - theOwnerUser is owner of the calendar where the attendee // participation state has changed. @@ -1063,6 +1059,10 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent || [currentStatus caseInsensitiveCompare: newStatus] != NSOrderedSame) { + NSMutableArray *delegates; + NSString *delegatedUID; + + delegatedUID = nil; [attendee setPartStat: newStatus]; // If one has accepted / declined an invitation on behalf of @@ -1087,9 +1087,6 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent [attendee setDelegatedTo: [delegate email]]; - NSString *delegatedUID = nil; - NSMutableArray *delegates; - if (removeDelegate) { delegates = [NSMutableArray array]; @@ -1123,13 +1120,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent previousObject: nil toAttendees: delegates withType: @"calendar:cancellation"]; -#if 0 - // DELETE CODE - [self sendReceiptEmailUsingTemplateNamed: @"Deletion" - forObject: event - to: delegates]; -#endif - } + } // if (removeDelegate) if (addDelegate) { @@ -1148,12 +1139,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent previousObject: nil toAttendees: delegates withType: @"calendar:invitation"]; -#if 0 - // DELETE CODE - [self sendReceiptEmailUsingTemplateNamed: @"Invitation" - forObject: event to: delegates]; -#endif - } + } // if (addDelegate) // If the current user isn't the organizer of the event // that has just been updated, we update the event and @@ -1161,10 +1147,9 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent ownerUser = [SOGoUser userWithLogin: owner]; if (!(ex || [event userIsOrganizer: ownerUser])) { - if ([[attendee rsvp] isEqualToString: @"true"] - && [event isStillRelevant]) + if ([event isStillRelevant]) [self sendResponseToOrganizer: event - from: ownerUser]; + from: ownerUser]; organizerUID = [[event organizer] uid]; @@ -1372,22 +1357,22 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent reason: @"delegate is a group"]; } if (ex == nil) - ex = [self _handleAttendee: attendee - withDelegate: delegate - ownerUser: ownerUser - statusChange: _status - inEvent: event]; + { + // Remove the RSVP attribute, as an action from the attendee + // was actually performed, and this confuses iCal (bug #1850) + [[attendee attributes] removeObjectForKey: @"RSVP"]; + ex = [self _handleAttendee: attendee + withDelegate: delegate + ownerUser: ownerUser + statusChange: _status + inEvent: event]; + } if (ex == nil) { // We generate the updated iCalendar file and we save it in // the database. We do this ONLY when using SOGo from the // Web interface. Over DAV, it'll be handled directly in // PUTAction: - - /* FIXME: this is a hack caused by the fact that - updateContentWithCalendar:fromRequest: invokes - changeParticipationStatusblabla, while the latter was - actually designed to be invoked by web methods only */ if (![context request] || [[context request] handledByDefaultHandler]) ex = [self saveContentString: [calendar versitString]]; } @@ -1944,6 +1929,9 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent 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]; diff --git a/SoObjects/Appointments/SOGoCalendarComponent.m b/SoObjects/Appointments/SOGoCalendarComponent.m index e40bfd306..e49fe4af4 100644 --- a/SoObjects/Appointments/SOGoCalendarComponent.m +++ b/SoObjects/Appointments/SOGoCalendarComponent.m @@ -725,7 +725,8 @@ header = [NSString stringWithFormat: @"text/calendar; method=%@;" @" charset=\"%@\"", [(iCalCalendar *) [object parent] method], charset]; - headerMap = [NGMutableHashMap hashMapWithCapacity: 1]; + headerMap = [NGMutableHashMap hashMapWithCapacity: 3]; + [headerMap setObject: @"urn:content-classes:calendarmessage" forKey: @"Content-Class"]; [headerMap setObject: header forKey: @"content-type"]; [headerMap setObject: @"quoted-printable" forKey: @"content-transfer-encoding"]; diff --git a/SoObjects/Appointments/SOGoUserFolder+Appointments.h b/SoObjects/Appointments/SOGoUserFolder+Appointments.h index 89af6b687..9342de19a 100644 --- a/SoObjects/Appointments/SOGoUserFolder+Appointments.h +++ b/SoObjects/Appointments/SOGoUserFolder+Appointments.h @@ -32,6 +32,7 @@ - (NSArray *) davCalendarUserAddressSet; - (NSArray *) davCalendarHomeSet; +- (NSArray *) davCalendarScheduleInboxURL; - (NSArray *) davCalendarScheduleOutboxURL; @end diff --git a/SoObjects/Appointments/Slovak.lproj/Localizable.strings b/SoObjects/Appointments/Slovak.lproj/Localizable.strings new file mode 100644 index 000000000..37d697647 --- /dev/null +++ b/SoObjects/Appointments/Slovak.lproj/Localizable.strings @@ -0,0 +1,66 @@ +"Personal Calendar" = "Osobný kalendár"; +vevent_class0 = "(Verejná udalosť)"; +vevent_class1 = "(Súkromná udalosť)"; +vevent_class2 = "(Dôverná udalosť)"; + +vtodo_class0 = "(Verejná úloha)"; +vtodo_class1 = "(Súkromná úloha)"; +vtodo_class2 = "(Dôverná úloha)"; + +/* Receipts */ +"The event \"%{Summary}\" was created" = "Udalosť \"%{Summary}\" bola vytvorená"; +"The event \"%{Summary}\" was deleted" = "Udalosť \"%{Summary}\" bola vymazaná"; +"The event \"%{Summary}\" was updated" = "Udalosť \"%{Summary}\" bola aktualizovaná"; +"The following attendees(s) were notified:" = "Nasledujúci účastník(ci) bol upozornený:"; +"The following attendees(s) were added:" = "Nasledujúci účastník(ci) bol pridaný:"; +"The following attendees(s) were removed:" = "Nasledujúci účastník(ci) bol odstránený:"; + +/* IMIP messages */ +"calendar_label" = "Kalendár:"; +"startDate_label" = "Začiatok:"; +"endDate_label" = "Koniec:"; +"due_label" = "Platnosť:"; +"location_label" = "Miesto:"; +"summary_label" = "Zhrnutie:"; +"comment_label" = "Komentár:"; + +/* Invitation */ +"Event Invitation: \"%{Summary}\"" = "Pozvánka na udalosť: \"%{Summary}\""; +"(sent by %{SentBy}) " = "(odoslané %{SentBy})"; +"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" = "%{Organizer} %{SentByText}Vás pozval na %{Summary}.⏎ ⏎ Začiatok: %{StartDate}⏎ Koniec: %{EndDate}⏎ Podrobnosti: %{Description}"; +"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" = "%{Organizer} %{SentByText}has invited you to %{Summary}.⏎ ⏎ Start: %{StartDate} at %{StartTime}⏎ End: %{EndDate} at %{EndTime}⏎ Description: %{Description}"; + +/* Deletion */ +"Event Cancelled: \"%{Summary}\"" = "Udalosť zrušená: \"%{Summary}\""; +"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" += "%{Organizer} %{SentByText}zrušil túto udalosť: %{Summary}.⏎ ⏎ Začiatok: %{StartDate}⏎ Koniec: %{EndDate}⏎ Podrobnosti: %{Description}"; +"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" += "%{Organizer} %{SentByText}zrušil túto udalosť: %{Summary}.⏎ ⏎\nZačiatok: %{StartDate} o %{StartTime}⏎ Koniec: %{EndDate} o %{EndTime}⏎ \nPopis: %{Description}"; + +/* Update */ +"The appointment \"%{Summary}\" for the %{OldStartDate} has changed" += "Stretnutie \"%{Summary}\" z %{OldStartDate} bolo zmenené"; +"The appointment \"%{Summary}\" for the %{OldStartDate} at %{OldStartTime} has changed" += "Stretnutie \"%{Summary}\" z %{OldStartDate} o %{OldStartTime} bola zmenená"; +"The following parameters have changed in the \"%{Summary}\" meeting:" += "Nasledujúce parametre boli zmenené v \"%{Summary}\" stretnutie:"; +"Please accept or decline those changes." += "Prosím prijmite alebo odmietnite tieto zmeny."; + +/* Reply */ +"Accepted invitation: \"%{Summary}\"" = "Prijatá pozvánka: \"%{Summary}\""; +"Declined invitation: \"%{Summary}\"" = "Zamietnutá pozvánka: \"%{Summary}\""; +"Delegated invitation: \"%{Summary}\"" = "Delegovaná pozvánka: \"%{Summary}\""; +"Not yet decided on invitation: \"%{Summary}\"" = "Doteraz nerozhodnutá pozvánka: \"%{Summary}\""; +"%{Attendee} %{SentByText}has accepted your event invitation." += "%{Attendee} %{SentByText}prijal Vašu pozvánku."; +"%{Attendee} %{SentByText}has declined your event invitation." += "%{Attendee} %{SentByText}odmietol Vašu pozvánku."; +"%{Attendee} %{SentByText}has delegated the invitation to %{Delegate}." += "%{Attendee} %{SentByText}delegoval pozvánku na %{Delegate}."; +"%{Attendee} %{SentByText}has not yet decided upon your event invitation." += "%{Attendee} %{SentByText}zatiaľ nerozhodol o Vašej pozvánke."; + +/* Resources */ +"Cannot access resource: \"%{Cn} %{SystemEmail}\"" = "Zdroj nedostupný: \"%{Cn} %{SystemEmail}\""; +"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}." = "Maximálny počet súčasných rezervácií (%{NumberOfSimultaneousBookings}) prekročil zdroje \"%{Cn} %{SystemEmail}\". Konfliktná udalosť je \"%{EventTitle}\", začínajúca %{StartDate}."; diff --git a/SoObjects/Appointments/SpanishSpain.lproj/Localizable.strings b/SoObjects/Appointments/SpanishSpain.lproj/Localizable.strings index 08dd4d3a6..c855a96bf 100644 --- a/SoObjects/Appointments/SpanishSpain.lproj/Localizable.strings +++ b/SoObjects/Appointments/SpanishSpain.lproj/Localizable.strings @@ -25,13 +25,13 @@ vtodo_class2 = "(Tarea confidencial)"; "comment_label" = "Comentario:"; /* Invitation */ -"Event Invitation: \"%{Summary}\"" = "Invitación al evento: \"% {Summary}\""; +"Event Invitation: \"%{Summary}\"" = "Invitación al evento: \"%{Summary}\""; "(sent by %{SentBy}) " = "(enviado por %{SentBy}) "; "%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" = "%{Organizer} %{SentByText}le ha invitado a %{Summary}.\n\nInicio: %{StartDate}\nFin: %{EndDate}\nDescripción: %{Description}"; "%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" = "%{Organizer} %{SentByText}le ha invitado a %{Summary}.\n\nInicio: %{StartDate} a las %{StartTime}\nFin: %{EndDate} a las %{EndTime}\nDescripción: %{Description}"; /* Deletion */ -"Event Cancelled: \"%{Summary}\"" = "Evento Cancelado: \"% {Summary}\""; +"Event Cancelled: \"%{Summary}\"" = "Evento Cancelado: \"%{Summary}\""; "%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" = "%{Organizer} %{SentByText}ha cancelado este evento: %{Summary}.\n\nInicio: %{StartDate}\nFin: %{EndDate}\nDescripción: %{Description}"; "%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" diff --git a/SoObjects/Contacts/GNUmakefile b/SoObjects/Contacts/GNUmakefile index af5ed91f5..257c2842b 100644 --- a/SoObjects/Contacts/GNUmakefile +++ b/SoObjects/Contacts/GNUmakefile @@ -27,7 +27,7 @@ Contacts_OBJC_FILES = \ Contacts_RESOURCE_FILES += \ product.plist \ -Contacts_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian SpanishSpain SpanishArgentina Swedish Ukrainian Welsh +Contacts_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh Contacts_LOCALIZED_RESOURCE_FILES = Localizable.strings diff --git a/SoObjects/Contacts/NGVCard+SOGo.m b/SoObjects/Contacts/NGVCard+SOGo.m index b306e0170..1f26f81fd 100644 --- a/SoObjects/Contacts/NGVCard+SOGo.m +++ b/SoObjects/Contacts/NGVCard+SOGo.m @@ -216,18 +216,19 @@ convention: - (void) updateFromLDIFRecord: (NSDictionary *) ldifRecord { - CardElement *element; - NSArray *units; NSInteger year, yearOfToday, month, day; + CardElement *element; NSCalendarDate *now; + NSArray *units; NSString *ou; + id o; [self setNWithFamily: [ldifRecord objectForKey: @"sn"] given: [ldifRecord objectForKey: @"givenname"] additional: nil prefixes: nil suffixes: nil]; [self setNickname: [ldifRecord objectForKey: @"mozillanickname"]]; [self setFn: [ldifRecord objectForKey: @"displayname"]]; - [self setTitle: [ldifRecord objectForKey: @"title"]]; + [self setTitle: [ldifRecord objectForKey: @"title"]]; element = [self _elementWithTag: @"adr" ofType: @"home"]; [element setSingleValue: [ldifRecord objectForKey: @"mozillahomestreet2"] @@ -303,7 +304,15 @@ convention: forKey: @""]; [self setNote: [ldifRecord objectForKey: @"description"]]; - [self setCategories: [ldifRecord objectForKey: @"vcardcategories"]]; + + o = [ldifRecord objectForKey: @"vcardcategories"]; + + // We can either have an array (from SOGo's web gui) or a + // string (from a LDIF import) as the value here. + if ([o isKindOfClass: [NSArray class]]) + [self setCategories: o]; + else + [self setCategories: [o componentsSeparatedByString: @","]]; [self cleanupEmptyChildren]; } diff --git a/SoObjects/Contacts/NSDictionary+LDIF.m b/SoObjects/Contacts/NSDictionary+LDIF.m index f475c0fc5..dd7a6e539 100644 --- a/SoObjects/Contacts/NSDictionary+LDIF.m +++ b/SoObjects/Contacts/NSDictionary+LDIF.m @@ -1,6 +1,6 @@ /* NSDictionary+LDIF.m - this file is part of SOGo * - * Copyright (C) 2011 Inverse inc + * Copyright (C) 2011-2012 Inverse inc * * Author: Wolfgang Sourdeau * diff --git a/SoObjects/Contacts/SOGoContactGCSFolder.m b/SoObjects/Contacts/SOGoContactGCSFolder.m index 6b8b313dd..7b8bfdac4 100644 --- a/SoObjects/Contacts/SOGoContactGCSFolder.m +++ b/SoObjects/Contacts/SOGoContactGCSFolder.m @@ -191,6 +191,10 @@ static NSArray *folderListingFields = nil; qs = [NSString stringWithFormat: @"(c_categories isCaseInsensitiveLike: '%%%@%%')", filter]; + else if ([criteria isEqualToString: @"organization"]) + qs = [NSString stringWithFormat: + @"(c_o isCaseInsensitiveLike: '%%%@%%')", + filter]; else qs = @"(1 == 0)"; diff --git a/SoObjects/Contacts/SOGoContactLDIFEntry.m b/SoObjects/Contacts/SOGoContactLDIFEntry.m index 4472ae901..dc8ec3431 100644 --- a/SoObjects/Contacts/SOGoContactLDIFEntry.m +++ b/SoObjects/Contacts/SOGoContactLDIFEntry.m @@ -1,6 +1,6 @@ /* SOGoContactLDIFEntry.m - this file is part of SOGo * - * Copyright (C) 2006-2011 Inverse inc. + * Copyright (C) 2006-2012 Inverse inc. * * Author: Wolfgang Sourdeau * Ludovic Marcotte diff --git a/SoObjects/Contacts/Slovak.lproj/Localizable.strings b/SoObjects/Contacts/Slovak.lproj/Localizable.strings new file mode 100644 index 000000000..1e3853747 --- /dev/null +++ b/SoObjects/Contacts/Slovak.lproj/Localizable.strings @@ -0,0 +1 @@ +"Personal Address Book" = "Osobné kontakty"; diff --git a/SoObjects/Mailer/SOGoDraftObject.m b/SoObjects/Mailer/SOGoDraftObject.m index e335bf13e..21a31e4da 100644 --- a/SoObjects/Mailer/SOGoDraftObject.m +++ b/SoObjects/Mailer/SOGoDraftObject.m @@ -1,5 +1,5 @@ /* - Copyright (C) 2007-2010 Inverse inc. + Copyright (C) 2007-2012 Inverse inc. Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOGo. @@ -269,7 +269,7 @@ static NSString *userAgent = nil; { id headerValue; unsigned int count; - NSString *messageID, *priority, *pureSender,*replyTo; + NSString *messageID, *priority, *pureSender, *replyTo; for (count = 0; count < 8; count++) { @@ -314,8 +314,8 @@ static NSString *userAgent = nil; if ([replyTo length] > 0) { [headers setObject: replyTo forKey: @"reply-to"]; - [headers removeObjectForKey: @"replyTo"]; } + [headers removeObjectForKey: @"replyTo"]; if ([[newHeaders objectForKey: @"receipt"] isEqualToString: @"true"]) { @@ -804,8 +804,8 @@ static NSString *userAgent = nil; - (void) fetchMailForForwarding: (SOGoMailObject *) sourceMail { NSDictionary *info, *attachment; + NSString *signature, *nl; SOGoUserDefaults *ud; - NSString *signature; [sourceMail fetchCoreInfos]; @@ -831,11 +831,14 @@ static NSString *userAgent = nil; } else { - // TODO: use subject for filename? -// error = [newDraft saveAttachment:content withName:@"forward.eml"]; + // TODO: use subject for filename? + // error = [newDraft saveAttachment:content withName:@"forward.eml"]; signature = [[self mailAccountFolder] signature]; if ([signature length]) - [self setText: [NSString stringWithFormat: @"\n-- \n%@", signature]]; + { + nl = (isHTML ? @"
" : @"\n"); + [self setText: [NSString stringWithFormat: @"%@-- %@%@", nl, nl, signature]]; + } attachment = [NSDictionary dictionaryWithObjectsAndKeys: [sourceMail filenameForForward], @"filename", @"message/rfc822", @"mimetype", diff --git a/SoObjects/Mailer/SOGoMailForward.m b/SoObjects/Mailer/SOGoMailForward.m index c3fba3007..9beca2887 100644 --- a/SoObjects/Mailer/SOGoMailForward.m +++ b/SoObjects/Mailer/SOGoMailForward.m @@ -1,6 +1,6 @@ /* SOGoMailForward.m - this file is part of SOGo * - * Copyright (C) 2007 Inverse inc. + * Copyright (C) 2007-2012 Inverse inc. * * Author: Wolfgang Sourdeau * @@ -226,11 +226,15 @@ - (NSString *) signature { - NSString *signature, *mailSignature; - + NSString *signature, *mailSignature, *nl; + signature = [[sourceMail mailAccountFolder] signature]; + if ([signature length]) - mailSignature = [NSString stringWithFormat: @"-- \n%@", signature]; + { + nl = (htmlComposition ? @"
" : @"\n"); + mailSignature = [NSString stringWithFormat: @"-- %@%@", nl, signature]; + } else mailSignature = @""; diff --git a/SoObjects/Mailer/SOGoMailSlovakForward.wo/SOGoMailSlovakForward.html b/SoObjects/Mailer/SOGoMailSlovakForward.wo/SOGoMailSlovakForward.html new file mode 100644 index 000000000..6ae765bb6 --- /dev/null +++ b/SoObjects/Mailer/SOGoMailSlovakForward.wo/SOGoMailSlovakForward.html @@ -0,0 +1,10 @@ +-------- Pôvodná správa -------- +Predmet: <#subject/> +Dátum: <#date/> +Od: <#from/> +<#hasReplyTo>Odpoveď na: <#replyTo/><#hasOrganization>Organizácia: <#organization/>Komu: <#to/> +<#hasCc>Kópia: <#cc/><#hasNewsGroups>Diskusné skupiny: <#newsgroups/><#hasReferences>Odkazy: <#references/> + +<#messageBody/> + +<#signature/> diff --git a/SoObjects/Mailer/SOGoMailSlovakForward.wo/SOGoMailSlovakForward.wod b/SoObjects/Mailer/SOGoMailSlovakForward.wo/SOGoMailSlovakForward.wod new file mode 100644 index 000000000..7787fa18e --- /dev/null +++ b/SoObjects/Mailer/SOGoMailSlovakForward.wo/SOGoMailSlovakForward.wod @@ -0,0 +1,79 @@ +subject: WOString { + value = subject; + escapeHTML = NO; +} + +date: WOString { + value = date; + escapeHTML = NO; +} + +from: WOString { + value = from; + escapeHTML = NO; +} + +newLine: WOString { + value = newLine; + escapeHTML = NO; +} + +hasReplyTo: WOConditional { + condition = hasReplyTo; +} + +replyTo: WOString { + value = replyTo; + escapeHTML = NO; +} + +hasOrganization: WOConditional { + condition = hasOrganization; +} + +organization: WOString { + value = organization; + escapeHTML = NO; +} + +to: WOString { + value = to; + escapeHTML = NO; +} + +hasCc: WOConditional { + condition = hasCc; +} + +cc: WOString { + value = cc; + escapeHTML = NO; +} + +hasNewsGroups: WOConditional { + condition = hasNewsGroups; +} + +newsgroups: WOString { + value = newsgroups; + escapeHTML = NO; +} + +hasReferences: WOConditional { + condition = hasReferences; +} + +references: WOString { + value = references; + escapeHTML = NO; +} + +messageBody: WOString { + value = messageBody; + escapeHTML = NO; +} + +signature: WOString { + value = signature; + escapeHTML = NO; +} diff --git a/SoObjects/Mailer/SOGoMailSlovakReply.wo/SOGoMailSlovakReply.html b/SoObjects/Mailer/SOGoMailSlovakReply.wo/SOGoMailSlovakReply.html new file mode 100644 index 000000000..f2d3f1b0e --- /dev/null +++ b/SoObjects/Mailer/SOGoMailSlovakReply.wo/SOGoMailSlovakReply.html @@ -0,0 +1,17 @@ +<#signaturePlacementOnTop> + + +<#signature/> + +<#outlookMode>-------- Pôvodná správa -------- +Predmet: <#subject/> +Dátum: <#date/> +Od: <#from/> +<#hasReplyTo>Odpoveď pre: <#replyTo/><#hasOrganization>Organizácia: <#organization/>Komu: <#to/> +<#hasCc>Kópia: <#cc/><#hasNewsGroups>Diskusné skupiny: <#newsgroups/><#hasReferences>Odkazy: <#references/> +<#standardMode> <#date/>, <#from/> napísal: + +<#messageBody/> + + +<#signaturePlacementOnBottom><#signature/> diff --git a/SoObjects/Mailer/SOGoMailSlovakReply.wo/SOGoMailSlovakReply.wod b/SoObjects/Mailer/SOGoMailSlovakReply.wo/SOGoMailSlovakReply.wod new file mode 100644 index 000000000..3fbed6d61 --- /dev/null +++ b/SoObjects/Mailer/SOGoMailSlovakReply.wo/SOGoMailSlovakReply.wod @@ -0,0 +1,106 @@ +outlookMode: WOConditional { + condition = outlookMode; +} + +standardMode: WOConditional { + condition = outlookMode; + negate = YES; +} + +subject: WOString { + value = subject; + escapeHTML = NO; +} + +date: WOString { + value = date; + escapeHTML = NO; +} + +from: WOString { + value = from; + escapeHTML = NO; +} + +newLine: WOString { + value = newLine; + escapeHTML = NO; +} + +hasReplyTo: WOConditional { + condition = hasReplyTo; +} + +replyTo: WOString { + value = replyTo; + escapeHTML = NO; +} + +hasOrganization: WOConditional { + condition = hasOrganization; +} + +organization: WOString { + value = organization; + escapeHTML = NO; +} + +to: WOString { + value = to; + escapeHTML = NO; +} + +hasCc: WOConditional { + condition = hasCc; +} + +cc: WOString { + value = cc; + escapeHTML = NO; +} + +hasNewsGroups: WOConditional { + condition = hasNewsGroups; +} + +newsgroups: WOString { + value = newsgroups; + escapeHTML = NO; +} + +hasReferences: WOConditional { + condition = hasReferences; +} + +references: WOString { + value = references; + escapeHTML = NO; +} + +messageBody: WOString { + value = messageBody; + escapeHTML = NO; +} + +signature: WOString { + value = signature; + escapeHTML = NO; +} + +replyPlacementOnTop: WOConditional { + condition = replyPlacementOnTop; +} + +replyPlacementOnBottom: WOConditional { + condition = replyPlacementOnTop; + negate = YES; +} + +signaturePlacementOnTop: WOConditional { + condition = signaturePlacementOnTop; +} + +signaturePlacementOnBottom: WOConditional { + condition = signaturePlacementOnTop; + negate = YES; +} diff --git a/SoObjects/SOGo/GNUmakefile b/SoObjects/SOGo/GNUmakefile index da52efc75..b965a681f 100644 --- a/SoObjects/SOGo/GNUmakefile +++ b/SoObjects/SOGo/GNUmakefile @@ -142,6 +142,16 @@ SOGo_RESOURCE_FILES = \ SOGoDefaults.plist \ DAVReportMap.plist +ifeq ($(saml2_config), yes) + SOGo_HEADER_FILES += SOGoSAML2Session.h SOGoSAML2Exceptions.h + SOGo_OBJC_FILES += SOGoSAML2Session.m SOGoSAML2Exceptions.m + SOGo_RESOURCE_FILES += SOGoSAML2Metadata.xml + +SOGoSAML2Exceptions.h SOGoSAML2Exceptions.m: gen-saml2-exceptions.py + $(ECHO_CREATING) ./gen-saml2-exceptions.py $(LASSO_CFLAGS) $(END_ECHO) + +endif + ifeq ($(ldap_config),yes) LIBRARY_NAME += \ diff --git a/SoObjects/SOGo/GNUmakefile.preamble b/SoObjects/SOGo/GNUmakefile.preamble index 6e01a3b92..f9b0a1515 100644 --- a/SoObjects/SOGo/GNUmakefile.preamble +++ b/SoObjects/SOGo/GNUmakefile.preamble @@ -24,7 +24,8 @@ SOGo_LIBRARIES_DEPEND_UPON += \ -lNGStreams -lNGExtensions -lEOControl \ -lDOM -lSaxObjC \ -lNGLdap -lSBJson \ - -lGDLContentStore -lgnustep-base -lobjc -ldl + -lGDLContentStore \ + $(BASE_LIBS) ifeq ($(HAS_LIBRARY_gnutls),yes) ADDITIONAL_CPPFLAGS += -DHAVE_GNUTLS=1 @@ -36,6 +37,11 @@ SOGo_LIBRARIES_DEPEND_UPON += -lcrypto endif endif +ifeq ($(HAS_LIBRARY_lasso), yes) +ADDITIONAL_CPPFLAGS += $(LASSO_CFLAGS) +SOGo_LIBRARIES_DEPEND_UPON += $(LASSO_LIBS) +endif + ifeq ($(findstring openbsd, $(GNUSTEP_HOST_OS)), openbsd) SOGo_LIBRARIES_DEPEND_UPON += -lcrypto else diff --git a/SoObjects/SOGo/LDAPSource.h b/SoObjects/SOGo/LDAPSource.h index 6842dd220..13b37f876 100644 --- a/SoObjects/SOGo/LDAPSource.h +++ b/SoObjects/SOGo/LDAPSource.h @@ -62,8 +62,11 @@ NSString *IDField; // the first part of a user DN NSString *CNField; NSString *UIDField; - NSArray *mailFields, *searchFields; - NSString *IMAPHostField, *IMAPLoginField; + NSArray *mailFields; + NSArray *searchFields; + NSString *IMAPHostField; + NSString *IMAPLoginField; + NSString *SieveHostField; NSArray *bindFields; BOOL listRequiresDot; @@ -110,6 +113,7 @@ searchFields: (NSArray *) newSearchFields IMAPHostField: (NSString *) newIMAPHostField IMAPLoginField: (NSString *) newIMAPLoginField + SieveHostField: (NSString *) newSieveHostField bindFields: (id) newBindFields kindField: (NSString *) newKindField andMultipleBookingsField: (NSString *) newMultipleBookingsField; diff --git a/SoObjects/SOGo/LDAPSource.m b/SoObjects/SOGo/LDAPSource.m index 86381d3a2..8948e5f9e 100644 --- a/SoObjects/SOGo/LDAPSource.m +++ b/SoObjects/SOGo/LDAPSource.m @@ -107,10 +107,11 @@ static Class NSStringK; [searchFields retain]; IMAPHostField = nil; IMAPLoginField = nil; + SieveHostField = nil; bindFields = nil; _scope = @"sub"; _filter = nil; - _userPasswordAlgorithm = nil; + _userPasswordAlgorithm = nil; listRequiresDot = YES; searchAttributes = nil; @@ -149,6 +150,7 @@ static Class NSStringK; [searchFields release]; [IMAPHostField release]; [IMAPLoginField release]; + [SieveHostField release]; [bindFields release]; [_filter release]; [_userPasswordAlgorithm release]; @@ -194,6 +196,7 @@ static Class NSStringK; searchFields: [udSource objectForKey: @"SearchFieldNames"] IMAPHostField: [udSource objectForKey: @"IMAPHostFieldName"] IMAPLoginField: [udSource objectForKey: @"IMAPLoginFieldName"] + SieveHostField: [udSource objectForKey: @"SieveHostFieldName"] bindFields: [udSource objectForKey: @"bindFields"] kindField: [udSource objectForKey: @"KindFieldName"] andMultipleBookingsField: [udSource objectForKey: @"MultipleBookingsFieldName"]]; @@ -311,6 +314,7 @@ static Class NSStringK; searchFields: (NSArray *) newSearchFields IMAPHostField: (NSString *) newIMAPHostField IMAPLoginField: (NSString *) newIMAPLoginField + SieveHostField: (NSString *) newSieveHostField bindFields: (id) newBindFields kindField: (NSString *) newKindField andMultipleBookingsField: (NSString *) newMultipleBookingsField @@ -326,6 +330,8 @@ andMultipleBookingsField: (NSString *) newMultipleBookingsField ASSIGN(IMAPHostField, [newIMAPHostField lowercaseString]); if (newIMAPLoginField) ASSIGN(IMAPLoginField, [newIMAPLoginField lowercaseString]); + if (newSieveHostField) + ASSIGN(SieveHostField, [newSieveHostField lowercaseString]); if (newMailFields) ASSIGN(mailFields, newMailFields); if (newSearchFields) @@ -586,7 +592,10 @@ andMultipleBookingsField: (NSString *) newMultipleBookingsField pass = [plainPassword asCryptedPassUsingScheme: _userPasswordAlgorithm]; if (pass == nil) - [self errorWithFormat: @"Unsupported user-password algorithm: %@", _userPasswordAlgorithm]; + { + [self errorWithFormat: @"Unsupported user-password algorithm: %@", _userPasswordAlgorithm]; + return nil; + } return [NSString stringWithFormat: @"{%@}%@", _userPasswordAlgorithm, pass]; } @@ -629,24 +638,34 @@ andMultipleBookingsField: (NSString *) newMultipleBookingsField NGLdapModification *mod; NGLdapAttribute *attr; NSArray *changes; + NSString* encryptedPass; attr = [[NGLdapAttribute alloc] initWithAttributeName: @"userPassword"]; if ([_userPasswordAlgorithm isEqualToString: @"none"]) - [attr addStringValue: newPassword]; - else - [attr addStringValue: [self _encryptPassword: newPassword]]; - - mod = [NGLdapModification replaceModification: attr]; - changes = [NSArray arrayWithObject: mod]; - *perr = PolicyNoError; + { + encryptedPass = newPassword; + } + else + { + encryptedPass = [self _encryptPassword: newPassword]; + } + if(encryptedPass != nil) + { + [attr addStringValue: encryptedPass]; + mod = [NGLdapModification replaceModification: attr]; + changes = [NSArray arrayWithObject: mod]; + *perr = PolicyNoError; - if ([bindConnection bindWithMethod: @"simple" - binddn: userDN - credentials: oldPassword]) - didChange = [bindConnection modifyEntryWithDN: userDN - changes: changes]; - else - didChange = NO; + if ([bindConnection bindWithMethod: @"simple" + binddn: userDN + credentials: oldPassword]) + { + didChange = [bindConnection modifyEntryWithDN: userDN + changes: changes]; + } + else + didChange = NO; + } } else didChange = [bindConnection changePasswordAtDn: userDN @@ -835,6 +854,13 @@ andMultipleBookingsField: (NSString *) newMultipleBookingsField if ([ldapValue length] > 0) [ldifRecord setObject: ldapValue forKey: @"c_imaplogin"]; } + + if (SieveHostField) + { + ldapValue = [[ldapEntry attributeWithName: SieveHostField] stringValueAtIndex: 0]; + if ([ldapValue length] > 0) + [ldifRecord setObject: ldapValue forKey: @"c_sievehostname"]; + } } - (void) _fillConstraints: (NGLdapEntry *) ldapEntry @@ -1596,6 +1622,7 @@ _makeLDAPChanges (NGLdapConnection *ldapConnection, searchFields: nil IMAPHostField: nil IMAPLoginField: nil + SieveHostField: nil bindFields: nil kindField: nil andMultipleBookingsField: nil]; diff --git a/SoObjects/SOGo/NSString+Crypto.h b/SoObjects/SOGo/NSString+Crypto.h index cc35a89d5..100bfaced 100644 --- a/SoObjects/SOGo/NSString+Crypto.h +++ b/SoObjects/SOGo/NSString+Crypto.h @@ -56,7 +56,7 @@ typedef enum { - (NSString *) asSHA1String; - (NSString *) asMD5String; -+ (keyEncoding) getDefaultEncodingForScheme: (NSString *) passwordScheme; ++ (NSArray *) getDefaultEncodingForScheme: (NSString *) passwordScheme; @end diff --git a/SoObjects/SOGo/NSString+Crypto.m b/SoObjects/SOGo/NSString+Crypto.m index f3370b8b5..7a720d442 100644 --- a/SoObjects/SOGo/NSString+Crypto.m +++ b/SoObjects/SOGo/NSString+Crypto.m @@ -71,8 +71,7 @@ { NSString *scheme; NSString *pass; - NSArray *schemeComps; - keyEncoding encoding; + NSArray *encodingAndScheme; NSRange range; int selflen, len; @@ -88,32 +87,11 @@ if (len == 0) scheme = defaultScheme; - encoding = [NSString getDefaultEncodingForScheme: scheme]; - - // get the encoding which may be part of the scheme - // e.g. ssha.hex forces a hex encoded ssha scheme - // possible is "b64" or "hex" - schemeComps = [scheme componentsSeparatedByString: @"."]; - if ([schemeComps count] == 2) - { - NSString *stringEncoding; - // scheme without encoding string is the first item - scheme = [schemeComps objectAtIndex: 0]; - // encoding string is second item - stringEncoding = [schemeComps objectAtIndex: 1]; - if ([stringEncoding caseInsensitiveCompare: @"hex"] == NSOrderedSame) - { - encoding = encHex; - } - else if ([stringEncoding caseInsensitiveCompare: @"b64"] == NSOrderedSame || - [stringEncoding caseInsensitiveCompare: @"base64"] == NSOrderedSame) - { - encoding = encBase64; - } - } + encodingAndScheme = [NSString getDefaultEncodingForScheme: scheme]; pass = [self substringWithRange: range]; - return [NSArray arrayWithObjects: scheme, pass, [NSNumber numberWithInt: encoding], nil]; + // return array with [scheme, password, encoding] + return [NSArray arrayWithObjects: [encodingAndScheme objectAtIndex: 1], pass, [encodingAndScheme objectAtIndex: 0], nil]; } /** @@ -147,7 +125,7 @@ if (encoding == encHex) { decodedData = [NSData decodeDataFromHexString: pass]; - + if(decodedData == nil) { decodedData = [NSData data]; @@ -208,8 +186,10 @@ * * @param passwordScheme The scheme to use * @param theSalt The binary data of the salt - * @param userEncoding The encoding (plain, hex, base64) to be used - * @return If successful, the encrypted and encoded NSString of the format {scheme}pass, or nil if the scheme did not exists or an error occured + * @param userEncoding The encoding (plain, hex, base64) to be used. If set to + * encDefault, the encoding will be detected from scheme name. + * @return If successful, the encrypted and encoded NSString of the format {scheme}pass, + * or nil if the scheme did not exists or an error occured. */ - (NSString *) asCryptedPassUsingScheme: (NSString *) passwordScheme withSalt: (NSData *) theSalt @@ -217,6 +197,22 @@ { keyEncoding dataEncoding; NSData* cryptedData; + + // use default encoding scheme, when set to default + if (userEncoding == encDefault) + { + // the encoding needs to be detected before crypting, + // to get the plain scheme (without encoding identifier) + NSArray* encodingAndScheme; + encodingAndScheme = [NSString getDefaultEncodingForScheme: passwordScheme]; + dataEncoding = [[encodingAndScheme objectAtIndex: 0] intValue]; + passwordScheme = [encodingAndScheme objectAtIndex: 1]; + } + else + { + dataEncoding = userEncoding; + } + // convert NSString to NSData and apply encryption scheme cryptedData = [self dataUsingEncoding: NSUTF8StringEncoding]; cryptedData = [cryptedData asCryptedPassUsingScheme: passwordScheme withSalt: theSalt]; @@ -224,12 +220,6 @@ if (cryptedData == nil) return nil; - // use default encoding scheme, when set to default - if (userEncoding == encDefault) - dataEncoding = [NSString getDefaultEncodingForScheme: passwordScheme]; - else - dataEncoding = userEncoding; - if (dataEncoding == encHex) { // hex encoding @@ -250,19 +240,49 @@ /** * Returns the encoding for a specified scheme * - * @param passwordScheme The scheme for which to get the encoding. + * @param passwordScheme The scheme for which to get the encoding. Can be "scheme.encoding" in which case the encoding is returned * @see keyEncoding - * @return returns the encoding, if unknown returns encPlain + * @return returns NSArray with elements {NSNumber encoding, NSString* scheme} where scheme is the 'real' scheme without the ".encoding" part. + * 'encoding' is stored as NSNumber in the array. If the encoding was not detected, encPlain is used for encoding. */ -+ (keyEncoding) getDefaultEncodingForScheme: (NSString *) passwordScheme ++ (NSArray *) getDefaultEncodingForScheme: (NSString *) passwordScheme { + NSArray *schemeComps; + NSString *trueScheme; + keyEncoding encoding = encPlain; + + // get the encoding which may be part of the scheme + // e.g. ssha.hex forces a hex encoded ssha scheme + // possible is "b64" or "hex" + schemeComps = [passwordScheme componentsSeparatedByString: @"."]; + if ([schemeComps count] == 2) + { + trueScheme = [schemeComps objectAtIndex: 0]; + NSString *stringEncoding; + // encoding string is second item + stringEncoding = [schemeComps objectAtIndex: 1]; + if ([stringEncoding caseInsensitiveCompare: @"hex"] == NSOrderedSame) + { + encoding = encHex; + } + else if ([stringEncoding caseInsensitiveCompare: @"b64"] == NSOrderedSame || + [stringEncoding caseInsensitiveCompare: @"base64"] == NSOrderedSame) + { + encoding = encBase64; + } + } + else + { + trueScheme = passwordScheme; + } + // in order to keep backwards-compatibility, hex encoding is used for sha1 here if ([passwordScheme caseInsensitiveCompare: @"md5"] == NSOrderedSame || [passwordScheme caseInsensitiveCompare: @"plain-md5"] == NSOrderedSame || [passwordScheme caseInsensitiveCompare: @"sha"] == NSOrderedSame || [passwordScheme caseInsensitiveCompare: @"cram-md5"] == NSOrderedSame) { - return encHex; + encoding = encHex; } else if ([passwordScheme caseInsensitiveCompare: @"smd5"] == NSOrderedSame || [passwordScheme caseInsensitiveCompare: @"ldap-md5"] == NSOrderedSame || @@ -272,9 +292,9 @@ [passwordScheme caseInsensitiveCompare: @"sha512"] == NSOrderedSame || [passwordScheme caseInsensitiveCompare: @"ssha512"] == NSOrderedSame) { - return encBase64; + encoding = encBase64; } - return encPlain; + return [NSArray arrayWithObjects: [NSNumber numberWithInt: encoding], trueScheme, nil]; } /** diff --git a/SoObjects/SOGo/NSString+Utilities.m b/SoObjects/SOGo/NSString+Utilities.m index da5a69993..5a37812b3 100644 --- a/SoObjects/SOGo/NSString+Utilities.m +++ b/SoObjects/SOGo/NSString+Utilities.m @@ -134,15 +134,16 @@ static int cssEscapingCount; start--; start++; + length = [self length]; // In [UIxMailPartTextViewer flatContentAsString], we first escape HTML entities and then // add URLs. Therefore, the brackets (inequality signs <>) have been encoded at this point. - if ([[self substringWithRange: NSMakeRange (start, 4)] compare: @"<"] == NSOrderedSame) + if (length > (start + 4) + && [[self substringWithRange: NSMakeRange (start, 4)] compare: @"<"] == NSOrderedSame) start += 4; - length = [self length] - start; - workRange = NSMakeRange (start, length); + length -= start; workRange = [self rangeOfCharacterFromSet: urlAfterEndingChars - options: NSLiteralSearch range: workRange]; + options: NSLiteralSearch range: NSMakeRange (start, length)]; if (workRange.location != NSNotFound) length = workRange.location - start; while diff --git a/SoObjects/SOGo/SOGoCache.h b/SoObjects/SOGo/SOGoCache.h index 663c7934d..b1277937b 100644 --- a/SoObjects/SOGo/SOGoCache.h +++ b/SoObjects/SOGo/SOGoCache.h @@ -111,6 +111,11 @@ - (void) setCASPGTId: (NSString *) pgtId forPGTIOU: (NSString *) pgtIou; +// SAML2 support +- (NSDictionary *) saml2LoginDumpsForIdentifier: (NSString *) identifier; +- (void) setSaml2LoginDumps: (NSDictionary *) dump + forIdentifier: (NSString *) identifier; + // // ACL caching support // diff --git a/SoObjects/SOGo/SOGoCache.m b/SoObjects/SOGo/SOGoCache.m index 7ede34230..e815224e1 100644 --- a/SoObjects/SOGo/SOGoCache.m +++ b/SoObjects/SOGo/SOGoCache.m @@ -520,6 +520,27 @@ static memcached_st *handle = NULL; forKey: [NSString stringWithFormat: @"cas-pgtiou:%@", pgtIou]]; } +// SAML2 support +- (NSDictionary *) saml2LoginDumpsForIdentifier: (NSString *) identifier +{ + NSString *key, *jsonString; + + key = [NSString stringWithFormat: @"saml2-login:%@", identifier]; + jsonString = [self valueForKey: key]; + + return [jsonString objectFromJSONString]; +} + +- (void) setSaml2LoginDumps: (NSDictionary *) dump + forIdentifier: (NSString *) identifier +{ + NSString *key; + + key = [NSString stringWithFormat: @"saml2-login:%@", identifier]; + + [self setValue: [dump jsonRepresentation] forKey: key]; +} + // // ACL caching code // diff --git a/SoObjects/SOGo/SOGoDefaults.plist b/SoObjects/SOGo/SOGoDefaults.plist index 127ddc2a8..24dbccfaf 100644 --- a/SoObjects/SOGo/SOGoDefaults.plist +++ b/SoObjects/SOGo/SOGoDefaults.plist @@ -36,7 +36,7 @@ SOGoSupportedLanguages = ( "Catalan", "Czech", "Dutch", "Danish", "Welsh", "English", "SpanishSpain", "SpanishArgentina", "French", "German", "Icelandic", "Italian", "Hungarian", "BrazilianPortuguese", - "NorwegianBokmal", "NorwegianNynorsk", "Polish", "Russian", + "NorwegianBokmal", "NorwegianNynorsk", "Polish", "Russian", "Slovak", "Ukrainian", "Swedish" ); SOGoTimeZone = "UTC"; diff --git a/SoObjects/SOGo/SOGoDomainDefaults.m b/SoObjects/SOGo/SOGoDomainDefaults.m index 1b822b487..998d43db1 100644 --- a/SoObjects/SOGo/SOGoDomainDefaults.m +++ b/SoObjects/SOGo/SOGoDomainDefaults.m @@ -205,7 +205,7 @@ mailingMechanism = nil; } - return mailingMechanism; + return [mailingMechanism lowercaseString]; } - (NSArray *) mailPollingIntervals @@ -220,7 +220,7 @@ - (NSString *) smtpAuthenticationType { - return [self stringForKey: @"SOGoSMTPAuthenticationType"]; + return [[self stringForKey: @"SOGoSMTPAuthenticationType"] lowercaseString]; } - (NSString *) mailSpoolPath diff --git a/SoObjects/SOGo/SOGoGCSFolder.m b/SoObjects/SOGo/SOGoGCSFolder.m index 13a02abc0..86fcf1639 100644 --- a/SoObjects/SOGo/SOGoGCSFolder.m +++ b/SoObjects/SOGo/SOGoGCSFolder.m @@ -1,7 +1,7 @@ /* SOGoGCSFolder.m - this file is part of SOGo * * Copyright (C) 2004-2005 SKYRIX Software AG - * Copyright (C) 2006-2010 Inverse inc. + * Copyright (C) 2006-2012 Inverse inc. * * Author: Wolfgang Sourdeau * @@ -835,7 +835,7 @@ static NSArray *childRecordFields = nil; - (BOOL) subscribeUserOrGroup: (NSString *) theIdentifier reallyDo: (BOOL) reallyDo { - NSMutableDictionary *moduleSettings; + NSMutableDictionary *moduleSettings, *folderShowAlarms; NSMutableArray *folderSubscription; NSString *subscriptionPointer; NSMutableArray *allUsers; @@ -886,6 +886,8 @@ static NSArray *childRecordFields = nil; folderSubscription = [moduleSettings objectForKey: @"SubscribedFolders"]; subscriptionPointer = [self folderReference]; + + folderShowAlarms = [moduleSettings objectForKey: @"FolderShowAlarms"]; if (reallyDo) { @@ -897,14 +899,26 @@ static NSArray *childRecordFields = nil; forKey: @"SubscribedFolders"]; } + if (!(folderShowAlarms + && [folderShowAlarms isKindOfClass: [NSMutableDictionary class]])) + { + folderShowAlarms = [NSMutableDictionary dictionary]; + [moduleSettings setObject: folderShowAlarms + forKey: @"FolderShowAlarms"]; + } + [folderSubscription addObjectUniquely: subscriptionPointer]; + + // By default, we disable alarms on subscribed calendars + [folderShowAlarms setObject: [NSNumber numberWithBool: NO] + forKey: subscriptionPointer]; } else { [self removeFolderSettings: moduleSettings withReference: subscriptionPointer]; [folderSubscription removeObject: subscriptionPointer]; - + [folderShowAlarms removeObjectForKey: subscriptionPointer]; } [us synchronize]; diff --git a/SoObjects/SOGo/SOGoGroup.m b/SoObjects/SOGo/SOGoGroup.m index 1718ccdf2..63010ec13 100644 --- a/SoObjects/SOGo/SOGoGroup.m +++ b/SoObjects/SOGo/SOGoGroup.m @@ -69,6 +69,11 @@ #import #import +#define CHECK_CLASS(o) ({ \ + if ([o isKindOfClass: [NSString class]]) \ + o = [NSArray arrayWithObject: o]; \ +}) + @implementation SOGoGroup - (id) initWithIdentifier: (NSString *) theID @@ -232,14 +237,17 @@ // Fetch "members" - we get DNs d = [_entry asDictionary]; o = [d objectForKey: @"member"]; + CHECK_CLASS(o); if (o) [dns addObjectsFromArray: o]; // Fetch "uniqueMembers" - we get DNs o = [d objectForKey: @"uniquemember"]; + CHECK_CLASS(o); if (o) [dns addObjectsFromArray: o]; // Fetch "memberUid" - we get UID (like login names) o = [d objectForKey: @"memberuid"]; + CHECK_CLASS(o); if (o) [uids addObjectsFromArray: o]; c = [dns count] + [uids count]; diff --git a/SoObjects/SOGo/SOGoObject.m b/SoObjects/SOGo/SOGoObject.m index 8a0f0e24d..90df71afe 100644 --- a/SoObjects/SOGo/SOGoObject.m +++ b/SoObjects/SOGo/SOGoObject.m @@ -1236,7 +1236,7 @@ - (SOGoWebDAVValue *) davCurrentUserPrincipal { NSDictionary *userHREF; - NSString *login; + NSString *login, *s; SOGoUser *activeUser; SOGoWebDAVValue *davCurrentUserPrincipal; @@ -1246,7 +1246,8 @@ davCurrentUserPrincipal = nil; else { - userHREF = davElementWithContent (@"href", XMLNS_WEBDAV, [self davURLAsString]); + s = [NSString stringWithFormat: @"/SOGo/dav/%@", login]; + userHREF = davElementWithContent (@"href", XMLNS_WEBDAV, s); davCurrentUserPrincipal = [davElementWithContent (@"current-user-principal", XMLNS_WEBDAV, diff --git a/SoObjects/SOGo/SOGoSAML2Session.h b/SoObjects/SOGo/SOGoSAML2Session.h new file mode 100644 index 000000000..00a3c4945 --- /dev/null +++ b/SoObjects/SOGo/SOGoSAML2Session.h @@ -0,0 +1,60 @@ +/* SOGoSAML2Session.h - this file is part of SOGo + * + * Copyright (C) 2012 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * 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. + */ + +#ifndef SOGOSAML2SESSION_H +#define SOGOSAML2SESSION_H + +/* implementation of the SAML2 protocol as required for a client: + https://www.oasis-open.org/standards#samlv2.0 */ + +#import + +#include + +@class NSString; + +@interface SOGoSAML2Session : NSObject +{ + LassoLogin *lassoLogin; + + NSString *login; + NSString *identifier; + NSString *assertion; +} + ++ (NSString *) metadataInContext: (WOContext *) context; ++ (NSString *) authenticationURLInContext: (WOContext *) context; + ++ (SOGoSAML2Session *) SAML2SessionInContext: (WOContext *) context; + ++ (SOGoSAML2Session *) SAML2SessionWithIdentifier: (NSString *) newIdentifier + inContext: (WOContext *) context; + +- (void) processAuthnResponse: (NSString *) authnResponse; + +- (NSString *) login; +- (NSString *) identifier; +- (NSString *) assertion; + +@end + +#endif /* SOGOSAML2SESSION_H */ diff --git a/SoObjects/SOGo/SOGoSAML2Session.m b/SoObjects/SOGo/SOGoSAML2Session.m new file mode 100644 index 000000000..e9258d694 --- /dev/null +++ b/SoObjects/SOGo/SOGoSAML2Session.m @@ -0,0 +1,424 @@ +/* SOGoSAML2Session.m - this file is part of SOGo + * + * Copyright (C) 2012 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * 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 +#include +#include +#include +#include +#include +#include + +#import +#import +#import +#import +#import +#import + +#import +#import +#import +#import + +#import "SOGoCache.h" +#import "SOGoSAML2Exceptions.h" +#import "SOGoSystemDefaults.h" + +#import "SOGoSAML2Session.h" + +@interface WOContext (SOGoSAML2Extension) + +- (NSString *) SAML2ServerURLString; + +@end + +@implementation WOContext (SOGoSAML2Extension) + +- (NSString *) SAML2ServerURLString +{ + NSString *appName; + NSURL *serverURL; + + appName = [[WOApplication application] name]; + serverURL = [NSURL URLWithString: [NSString stringWithFormat: @"/%@", + appName] + relativeToURL: [self serverURL]]; + + return [serverURL absoluteString]; +} + +@end + +@implementation SOGoSAML2Session + +static NSMapTable *serverTable = nil; + ++ (void) initialize +{ + if (!serverTable) + { + serverTable = [NSMapTable mapTableWithStrongToWeakObjects]; + [serverTable retain]; + } + lasso_init (); +} + +static LassoServer * +LassoServerInContext (WOContext *context) +{ + NSString *urlString, *metadata, *filename, *keyContent, *certContent, + *idpKeyFilename, *idpCertFilename; + LassoServer *server; + SOGoSystemDefaults *sd; + + urlString = [context SAML2ServerURLString]; + server = NSMapGet (serverTable, urlString); + if (!server) + { + sd = [SOGoSystemDefaults sharedSystemDefaults]; + + filename = [sd SAML2PrivateKeyLocation]; + if (!filename) + [NSException raise: NSInvalidArgumentException + format: @"'SAML2PrivateKeyLocation' not set"]; + keyContent = [NSString stringWithContentsOfFile: filename]; + if (!keyContent) + [NSException raise: NSGenericException + format: @"private key file '%@' could not be read", + filename]; + + filename = [sd SAML2CertificateLocation]; + if (!filename) + [NSException raise: NSInvalidArgumentException + format: @"'SAML2CertificateLocation' not set"]; + certContent = [NSString stringWithContentsOfFile: filename]; + if (!certContent) + [NSException raise: NSGenericException + format: @"certificate file '%@' could not be read", + filename]; + + metadata = [SOGoSAML2Session metadataInContext: context]; + /* FIXME: enable key password in config ? */ + server = lasso_server_new_from_buffers ([metadata UTF8String], + [keyContent UTF8String], + NULL, + [certContent UTF8String]); + + filename = [sd SAML2IdpMetadataLocation]; + idpKeyFilename = [sd SAML2IdpPublicKeyLocation]; + idpCertFilename = [sd SAML2IdpCertificateLocation]; + lasso_server_add_provider (server, LASSO_PROVIDER_ROLE_IDP, + [filename UTF8String], + [idpKeyFilename UTF8String], + [idpCertFilename UTF8String]); + NSMapInsert (serverTable, urlString, server); + } + + return server; +} + ++ (NSString *) authenticationURLInContext: (WOContext *) context +{ + lasso_error_t rc; + LassoServer *server; + LassoLogin *tempLogin; + LassoSamlp2AuthnRequest *request; + NSString *url; + GList *providers; + + server = LassoServerInContext (context); + tempLogin = lasso_login_new (server); + + providers = g_hash_table_get_keys (server->providers); + rc = lasso_login_init_authn_request (tempLogin, providers->data, LASSO_HTTP_METHOD_REDIRECT); + if (rc) + [NSException raiseSAML2Exception: rc]; + + request = LASSO_SAMLP2_AUTHN_REQUEST (LASSO_PROFILE (tempLogin)->request); + if (request->NameIDPolicy->Format) { + g_free (request->NameIDPolicy->Format); + } + request->NameIDPolicy->Format = g_strdup(LASSO_SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT); + request->NameIDPolicy->AllowCreate = 1; + request->ForceAuthn = TRUE; + request->IsPassive = FALSE; + if (request->ProtocolBinding) { + g_free (request->ProtocolBinding); + } + // request->NameIDPolicy = strdup (LASSO_LIB_NAMEID_POLICY_TYPE_FEDERATED); + // request->consent = strdup (LASSO_LIB_CONSENT_OBTAINED); + rc = lasso_login_build_authn_request_msg (tempLogin); + if (rc) + [NSException raiseSAML2Exception: rc]; + + url = [NSString stringWithUTF8String: LASSO_PROFILE (tempLogin)->msg_url]; + + g_object_unref (tempLogin); + + return url; +} + ++ (NSString *) metadataInContext: (WOContext *) context +{ + NSString *metadata, *serverURLString, *filename; + NSBundle *bundle; + + bundle = [NSBundle bundleForClass: self]; + filename = [bundle pathForResource: @"SOGoSAML2Metadata" ofType: @"xml"]; + if (filename) + { + serverURLString = [context SAML2ServerURLString]; + metadata = [[NSString stringWithContentsOfFile: filename] + stringByReplacingString: @"%{base_url}" + withString: serverURLString]; + } + else + metadata = nil; + + return metadata; +} + +- (id) init +{ + if ((self = [super init])) + { + lassoLogin = NULL; + login = nil; + identifier = nil; + assertion = nil; + } + + return self; +} + +- (void) _updateDataFromLogin +{ + // LassoSamlp2Response *response; + LassoSaml2Assertion *saml2Assertion; + GList *statementList, *attributeList; + LassoSaml2AttributeStatement *statement; + LassoSaml2Attribute *attribute; + LassoSaml2AttributeValue *value; + LassoMiscTextNode *textNode; + LassoSaml2NameID *nameIdentifier; + gchar *dump; + + saml2Assertion + = LASSO_SAML2_ASSERTION (lasso_login_get_assertion (lassoLogin)); + if (saml2Assertion) + { + /* deduce user login */ + [login release]; + login = nil; + + statementList = saml2Assertion->AttributeStatement; + while (!login && statementList) + { + statement = LASSO_SAML2_ATTRIBUTE_STATEMENT (statementList->data); + attributeList = statement->Attribute; + while (!login && attributeList) + { + attribute = LASSO_SAML2_ATTRIBUTE (attributeList->data); + if (strcmp (attribute->Name, "uid") == 0) + { + value = LASSO_SAML2_ATTRIBUTE_VALUE (attribute->AttributeValue->data); + textNode = value->any->data; + login = [NSString stringWithUTF8String: textNode->content]; + [login retain]; + } + else + attributeList = attributeList->next; + } + statementList = statementList->next; + } + + /* serialize assertion */ + [assertion release]; + dump = lasso_node_export_to_xml (LASSO_NODE (saml2Assertion)); + if (dump) + { + assertion = [NSString stringWithUTF8String: dump]; + [assertion retain]; + g_free (dump); + } + else + assertion = nil; + } + + nameIdentifier + = LASSO_SAML2_NAME_ID (LASSO_PROFILE (lassoLogin)->nameIdentifier); + if (nameIdentifier) + { + /* deduce session id */ + [identifier release]; + identifier = [NSString stringWithUTF8String: nameIdentifier->content]; + [identifier retain]; + } +} + +- (id) _initWithDump: (NSDictionary *) saml2Dump + inContext: (WOContext *) context +{ + // lasso_error_t rc; + LassoServer *server; + LassoProfile *profile; + const gchar *dump; + + if ((self = [self init])) + { + server = LassoServerInContext (context); + lassoLogin = lasso_login_new (server); + if (saml2Dump) + { + profile = LASSO_PROFILE (lassoLogin); + ASSIGN (login, [saml2Dump objectForKey: @"login"]); + ASSIGN (identifier, [saml2Dump objectForKey: @"identifier"]); + ASSIGN (assertion, [saml2Dump objectForKey: @"assertion"]); + dump = [[saml2Dump objectForKey: @"identity"] UTF8String]; + if (dump) + lasso_profile_set_identity_from_dump (profile, dump); + dump = [[saml2Dump objectForKey: @"session"] UTF8String]; + if (dump) + lasso_profile_set_session_from_dump (profile, dump); + lasso_login_accept_sso (lassoLogin); + // if (rc) + // [NSException raiseSAML2Exception: rc]; + [self _updateDataFromLogin]; + } + } + + return self; +} + +- (void) dealloc +{ + if (lassoLogin) + g_object_unref (lassoLogin); + [login release]; + [identifier release]; + [assertion release]; + [super dealloc]; +} + ++ (SOGoSAML2Session *) _SAML2SessionWithDump: (NSDictionary *) saml2Dump + inContext: (WOContext *) context +{ + SOGoSAML2Session *newSession; + + newSession = [[self alloc] _initWithDump: saml2Dump inContext: context]; + [newSession autorelease]; + + return newSession; +} + ++ (SOGoSAML2Session *) SAML2SessionInContext: (WOContext *) context +{ + return [self _SAML2SessionWithDump: nil inContext: context]; +} + ++ (SOGoSAML2Session *) SAML2SessionWithIdentifier: (NSString *) identifier + inContext: (WOContext *) context +{ + SOGoSAML2Session *session = nil; + NSDictionary *saml2Dump; + + if (identifier) + { + saml2Dump = [[SOGoCache sharedCache] + saml2LoginDumpsForIdentifier: identifier]; + if (saml2Dump) + session = [self _SAML2SessionWithDump: saml2Dump + inContext: context]; + } + + return session; +} + +- (NSString *) login +{ + return login; +} + +- (NSString *) identifier +{ + return identifier; +} + +- (NSString *) assertion +{ + return assertion; +} + +- (void) processAuthnResponse: (NSString *) authnResponse +{ + lasso_error_t rc; + gchar *responseData, *dump; + LassoProfile *profile; + LassoIdentity *identity; + LassoSession *session; + NSString *nsDump; + NSMutableDictionary *saml2Dump; + + responseData = strdup ([authnResponse UTF8String]); + + rc = lasso_login_process_authn_response_msg (lassoLogin, responseData); + if (rc) + [NSException raiseSAML2Exception: rc]; + + rc = lasso_login_accept_sso (lassoLogin); + if (rc) + [NSException raiseSAML2Exception: rc]; + + [self _updateDataFromLogin]; + + saml2Dump = [NSMutableDictionary dictionary]; + [saml2Dump setObject: login forKey: @"login"]; + [saml2Dump setObject: identifier forKey: @"identifier"]; + [saml2Dump setObject: assertion forKey: @"assertion"]; + + profile = LASSO_PROFILE (lassoLogin); + + session = lasso_profile_get_session (profile); + if (session) + { + dump = lasso_session_dump (session); + nsDump = [NSString stringWithUTF8String: dump]; + [saml2Dump setObject: nsDump forKey: @"session"]; + lasso_session_destroy (session); + } + + identity = lasso_profile_get_identity (profile); + if (identity) + { + dump = lasso_identity_dump (identity); + nsDump = [NSString stringWithUTF8String: dump]; + [saml2Dump setObject: nsDump forKey: @"identity"]; + lasso_identity_destroy (identity); + } + + [[SOGoCache sharedCache] setSaml2LoginDumps: saml2Dump + forIdentifier: identifier]; + free (responseData); +} + +@end diff --git a/SoObjects/SOGo/SOGoSession.h b/SoObjects/SOGo/SOGoSession.h index f0b5fc128..42e2ddd9a 100644 --- a/SoObjects/SOGo/SOGoSession.h +++ b/SoObjects/SOGo/SOGoSession.h @@ -43,6 +43,7 @@ login: (NSString **) theLogin domain: (NSString **) theDomain password: (NSString **) thePassword; + @end #endif diff --git a/SoObjects/SOGo/SOGoSession.m b/SoObjects/SOGo/SOGoSession.m index 1c8f9abbd..e2137349f 100644 --- a/SoObjects/SOGo/SOGoSession.m +++ b/SoObjects/SOGo/SOGoSession.m @@ -26,6 +26,8 @@ #include "SOGoCache.h" +#import + #import #import #import diff --git a/SoObjects/SOGo/SOGoSieveManager.m b/SoObjects/SOGo/SOGoSieveManager.m index c050911a5..d75f9dba4 100644 --- a/SoObjects/SOGo/SOGoSieveManager.m +++ b/SoObjects/SOGo/SOGoSieveManager.m @@ -51,7 +51,7 @@ static NSMutableDictionary *fieldTypes = nil; static NSDictionary *sieveFields = nil; static NSDictionary *sieveFlags = nil; static NSDictionary *operatorRequirements = nil; -static NSDictionary *methodRequirements = nil; +static NSMutableDictionary *methodRequirements = nil; static NSString *sieveScriptName = @"sogo"; @@ -188,16 +188,16 @@ static NSString *sieveScriptName = @"sogo"; if (!methodRequirements) { methodRequirements - = [NSDictionary dictionaryWithObjectsAndKeys: - @"imapflags", @"addflag", - @"imapflags", @"removeflag", - @"imapflags", @"flag", - @"vacation", @"vacation", - @"notify", @"notify", - @"fileinto", @"fileinto", - @"reject", @"reject", - @"regex", @"regex", - nil]; + = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"imapflags", @"addflag", + @"imapflags", @"removeflag", + @"imapflags", @"flag", + @"vacation", @"vacation", + @"notify", @"notify", + @"fileinto", @"fileinto", + @"reject", @"reject", + @"regex", @"regex", + nil]; [methodRequirements retain]; } } @@ -615,8 +615,8 @@ static NSString *sieveScriptName = @"sogo"; SOGoUserDefaults *ud; SOGoDomainDefaults *dd; NGSieveClient *client; - NSString *filterScript, *v, *sieveServer; - NSURL *url; + NSString *filterScript, *v, *sieveServer, *sieveScheme, *sieveQuery, *imapServer; + NSURL *url, *cUrl; int sievePort; BOOL b, connected; @@ -631,6 +631,115 @@ static NSString *sieveScriptName = @"sogo"; connected = YES; b = NO; + + // We connect to our Sieve server and check capabilities, in order + // to generate the right script, based on capabilities + // + // sieveServer might have the following format: + // + // sieve://localhost + // sieve://localhost:2000 + // sieve://localhost:2000/?tls=YES + // + // Values such as "localhost" or "localhost:2000" are NOT supported. + // + // We first try to get the user's preferred Sieve server + sieveServer = [[[user mailAccounts] objectAtIndex: 0] objectForKey: @"sieveServerName"]; + imapServer = [[[user mailAccounts] objectAtIndex: 0] objectForKey: @"serverName"]; + + cUrl = [NSURL URLWithString: (sieveServer ? sieveServer : @"")]; + + if ([dd sieveServer] && [[dd sieveServer] length] > 0) + url = [NSURL URLWithString: [dd sieveServer]]; + else + url = [NSURL URLWithString: @"localhost"]; + + if ([cUrl host]) + sieveServer = [cUrl host]; + if (!sieveServer && [url host]) + sieveServer = [url host]; + if (!sieveServer && [dd sieveServer]) + sieveServer = [dd sieveServer]; + if (!sieveServer && imapServer) + sieveServer = [[NSURL URLWithString: imapServer] host]; + if (!sieveServer) + sieveServer = @"localhost"; + + sieveScheme = [cUrl scheme] ? [cUrl scheme] : [url scheme]; + if (!sieveScheme) + sieveScheme = @"sieve"; + + if ([cUrl port]) + sievePort = [[cUrl port] intValue]; + else + if ([url port]) + sievePort = [[url port] intValue]; + else + sievePort = 2000; + + sieveQuery = [cUrl query] ? [cUrl query] : [url query]; + if (sieveQuery) + sieveQuery = [NSString stringWithFormat: @"/?%@", sieveQuery]; + else + sieveQuery = @""; + + url = [NSURL URLWithString: [NSString stringWithFormat: @"%@://%@:%d%@", + sieveScheme, sieveServer, sievePort, sieveQuery]]; + + client = [[NGSieveClient alloc] initWithURL: url]; + + if (!client) { + NSLog(@"Sieve connection failed on %@", [url description]); + return NO; + } + + if (!thePassword) { + [client closeConnection]; + return NO; + } + + NS_DURING + { + result = [client login: theLogin authname: theAuthName password: thePassword]; + } + NS_HANDLER + { + connected = NO; + } + NS_ENDHANDLER + + if (!connected) + { + NSLog(@"Sieve connection failed on %@", [url description]); + return NO; + } + + if (![[result valueForKey:@"result"] boolValue]) { + NSLog(@"failure. Attempting with a renewed password (no authname supported)"); + thePassword = [theAccount imap4PasswordRenewed: YES]; + result = [client login: theLogin password: thePassword]; + } + + if (![[result valueForKey:@"result"] boolValue]) { + NSLog(@"Could not login '%@' on Sieve server: %@: %@", + theLogin, client, result); + [client closeConnection]; + return NO; + } + + // We adjust the "methodRequirements" based on the server's + // capabilities. Cyrus exposes "imapflags" while Dovecot (and + // potentially others) expose "imap4flags" as specified in RFC5332 + if ([client hasCapability: @"imap4flags"]) + { + [methodRequirements setObject: @"imap4flags" forKey: @"addflag"]; + [methodRequirements setObject: @"imap4flags" forKey: @"removeflag"]; + [methodRequirements setObject: @"imap4flags" forKey: @"flag"]; + } + + // + // Now let's generate the script + // script = [NSMutableString string]; // We first handle filters @@ -646,6 +755,7 @@ static NSString *sieveScriptName = @"sogo"; else { NSLog(@"Sieve generation failure: %@", [self lastScriptError]); + [client closeConnection]; return NO; } @@ -726,87 +836,6 @@ static NSString *sieveScriptName = @"sogo"; [script insertString: header atIndex: 0]; } - // We connect to our Sieve server and upload the script. - // - // sieveServer might have the following format: - // - // sieve://localhost - // sieve://localhost:2000 - // sieve://localhost:2000/?tls=YES - // - // Values such as "localhost" or "localhost:2000" are NOT supported. - // - sieveServer = [dd sieveServer]; - sievePort = 2000; - url = nil; - - if (!sieveServer) - { - NSString *s; - - s = [dd imapServer]; - - if (s) - { - NSURL *url; - - url = [NSURL URLWithString: s]; - - if ([url host]) - sieveServer = [url host]; - else - sieveServer = s; - } - else - sieveServer = @"localhost"; - - url = [NSURL URLWithString: [NSString stringWithFormat: @"%@:%d", sieveServer, sievePort]]; - } - else - { - url = [NSURL URLWithString: sieveServer]; - } - - client = [[NGSieveClient alloc] initWithURL: url]; - - if (!client) { - NSLog(@"Sieve connection failed on %@", [url description]); - return NO; - } - - if (!thePassword) { - [client closeConnection]; - return NO; - } - - NS_DURING - { - result = [client login: theLogin authname: theAuthName password: thePassword]; - } - NS_HANDLER - { - connected = NO; - } - NS_ENDHANDLER - - if (!connected) - { - NSLog(@"Sieve connection failed on %@", [url description]); - return NO; - } - - if (![[result valueForKey:@"result"] boolValue]) { - NSLog(@"failure. Attempting with a renewed password (no authname supported)"); - thePassword = [theAccount imap4PasswordRenewed: YES]; - result = [client login: theLogin password: thePassword]; - } - - if (![[result valueForKey:@"result"] boolValue]) { - NSLog(@"Could not login '%@' on Sieve server: %@: %@", - theLogin, client, result); - [client closeConnection]; - return NO; - } /* We ensure to deactive the current active script since it could prevent its deletion from the server. */ diff --git a/SoObjects/SOGo/SOGoSystemDefaults.h b/SoObjects/SOGo/SOGoSystemDefaults.h index 8f17eb39c..24d211350 100644 --- a/SoObjects/SOGo/SOGoSystemDefaults.h +++ b/SoObjects/SOGo/SOGoSystemDefaults.h @@ -76,6 +76,13 @@ - (NSString *) CASServiceURL; - (BOOL) CASLogoutEnabled; +- (NSString *) SAML2PrivateKeyLocation; +- (NSString *) SAML2CertificateLocation; +- (NSString *) SAML2IdpMetadataLocation; +- (NSString *) SAML2IdpPublicKeyLocation; +- (NSString *) SAML2IdpCertificateLocation; +- (BOOL) SAML2LogoutEnabled; + - (BOOL) enablePublicAccess; @end diff --git a/SoObjects/SOGo/SOGoSystemDefaults.m b/SoObjects/SOGo/SOGoSystemDefaults.m index 9818f70b7..67101044f 100644 --- a/SoObjects/SOGo/SOGoSystemDefaults.m +++ b/SoObjects/SOGo/SOGoSystemDefaults.m @@ -379,7 +379,15 @@ _injectConfigurationFromFile (NSUserDefaults *ud, - (NSArray *) supportedLanguages { - return [self stringArrayForKey: @"SOGoSupportedLanguages"]; + static NSArray *supportedLanguages = nil; + + if (!supportedLanguages) + { + supportedLanguages = [self stringArrayForKey: @"SOGoSupportedLanguages"]; + [supportedLanguages retain]; + } + + return supportedLanguages; } - (BOOL) userCanChangePassword @@ -417,6 +425,37 @@ _injectConfigurationFromFile (NSUserDefaults *ud, return [self boolForKey: @"SOGoCASLogoutEnabled"]; } +/* SAML2 support */ +- (NSString *) SAML2PrivateKeyLocation +{ + return [self stringForKey: @"SOGoSAML2PrivateKeyLocation"]; +} + +- (NSString *) SAML2CertificateLocation; +{ + return [self stringForKey: @"SOGoSAML2CertificateLocation"]; +} + +- (NSString *) SAML2IdpMetadataLocation +{ + return [self stringForKey: @"SOGoSAML2IdpMetadataLocation"]; +} + +- (NSString *) SAML2IdpPublicKeyLocation +{ + return [self stringForKey: @"SOGoSAML2IdpPublicKeyLocation"]; +} + +- (NSString *) SAML2IdpCertificateLocation +{ + return [self stringForKey: @"SOGoSAML2IdpCertificateLocation"]; +} + +- (BOOL) SAML2LogoutEnabled +{ + return [self boolForKey: @"SOGoSAML2LogoutEnabled"]; +} + - (BOOL) enablePublicAccess { return [self boolForKey: @"SOGoEnablePublicAccess"]; diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index 6a6f7b7b3..06f663c55 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -576,13 +576,13 @@ - (void) _appendSystemMailAccount { - NSString *fullName, *replyTo, *imapLogin, *imapServer, *signature, - *encryption, *scheme, *action, *query, *customEmail; + NSString *fullName, *replyTo, *imapLogin, *imapServer, *cImapServer, *signature, + *encryption, *scheme, *action, *query, *customEmail, *sieveServer; NSMutableDictionary *mailAccount, *identity, *mailboxes, *receipts; NSNumber *port; NSMutableArray *identities; NSArray *mails; - NSURL *url; + NSURL *url, *cUrl; unsigned int count, max; NSInteger defaultPort; @@ -606,16 +606,22 @@ // imaps://localhost:143/?tls=YES // imaps://localhost/?tls=YES - imapServer = [self _fetchFieldForUser: @"c_imaphostname"]; - if (!imapServer) - imapServer = [[self domainDefaults] imapServer]; + cImapServer = [self _fetchFieldForUser: @"c_imaphostname"]; + imapServer = [[self domainDefaults] imapServer]; + cUrl = [NSURL URLWithString: (cImapServer ? cImapServer : @"")]; url = [NSURL URLWithString: imapServer]; - if ([url host]) - imapServer = [url host]; + if([cUrl host]) + imapServer = [cUrl host]; + else + if(cImapServer) + imapServer = cImapServer; + else + if([url host]) + imapServer = [url host]; [mailAccount setObject: imapServer forKey: @"serverName"]; // 3. port & encryption - scheme = [url scheme]; + scheme = [cUrl scheme] ? [cUrl scheme] : [url scheme]; if (scheme && [scheme caseInsensitiveCompare: @"imaps"] == NSOrderedSame) { @@ -624,19 +630,28 @@ } else { - query = [url query]; + query = [cUrl query] ? [cUrl query] : [url query]; if (query && [query caseInsensitiveCompare: @"tls=YES"] == NSOrderedSame) encryption = @"tls"; else encryption = @"none"; defaultPort = 143; } - port = [url port]; + port = [cUrl port] ? [cUrl port] : [url port]; if ([port intValue] == 0) /* port is nil or intValue == 0 */ port = [NSNumber numberWithInt: defaultPort]; [mailAccount setObject: port forKey: @"port"]; [mailAccount setObject: encryption forKey: @"encryption"]; + // Sieve server + sieveServer = [self _fetchFieldForUser: @"c_sievehostname"]; + + if (sieveServer) + { + [mailAccount setObject: sieveServer forKey: @"sieveServerName"]; + } + + /* identities */ identities = [NSMutableArray new]; mails = [self allEmails]; diff --git a/SoObjects/SOGo/SOGoUserDefaults.h b/SoObjects/SOGo/SOGoUserDefaults.h index 287d0a0ca..0a6cdb818 100644 --- a/SoObjects/SOGo/SOGoUserDefaults.h +++ b/SoObjects/SOGo/SOGoUserDefaults.h @@ -35,6 +35,9 @@ extern NSString *SOGoWeekStartFirst4DayWeek; extern NSString *SOGoWeekStartFirstFullWeek; @interface SOGoUserDefaults : SOGoDefaultsSource +{ + NSString *userLanguage; +} + (SOGoUserDefaults *) defaultsForUser: (NSString *) userId inDomain: (NSString *) domainId; @@ -115,6 +118,9 @@ extern NSString *SOGoWeekStartFirstFullWeek; - (void) setMailComposeMessageType: (NSString *) newValue; - (NSString *) mailComposeMessageType; +- (void) setMailDisplayRemoteInlineImages: (NSString *) newValue; +- (NSString *) mailDisplayRemoteInlineImages; + - (void) setMailMessageForwarding: (NSString *) newValue; - (NSString *) mailMessageForwarding; diff --git a/SoObjects/SOGo/SOGoUserDefaults.m b/SoObjects/SOGo/SOGoUserDefaults.m index 3d728d398..81f6cada8 100644 --- a/SoObjects/SOGo/SOGoUserDefaults.m +++ b/SoObjects/SOGo/SOGoUserDefaults.m @@ -22,6 +22,7 @@ #import #import +#import #import #import @@ -91,6 +92,22 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek"; return ud; } +- (id) init +{ + if ((self = [super init])) + { + userLanguage = nil; + } + + return self; +} + +- (void) dealloc +{ + [userLanguage release]; + [super dealloc]; +} + - (BOOL) _migrateLastModule { BOOL rc; @@ -355,21 +372,25 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek"; - (NSString *) language { - NSString *language; NSArray *supportedLanguages; - - /* see SOGoDomainDefaults for the meaning of this */ - language = [source objectForKey: @"SOGoLanguage"]; - if (!(language && [language isKindOfClass: [NSString class]])) - language = [(SOGoDomainDefaults *) parentSource language]; - - /* make sure the language is part of the supported languages */ - supportedLanguages = [[SOGoSystemDefaults sharedSystemDefaults] - supportedLanguages]; - if (![supportedLanguages containsObject: language]) - language = [parentSource stringForKey: @"SOGoLanguage"]; - return language; + if (!userLanguage) + { + /* see SOGoDomainDefaults for the meaning of this */ + userLanguage = [source objectForKey: @"SOGoLanguage"]; + if (!(userLanguage && [userLanguage isKindOfClass: [NSString class]])) + userLanguage = [(SOGoDomainDefaults *) parentSource language]; + + supportedLanguages = [[SOGoSystemDefaults sharedSystemDefaults] + supportedLanguages]; + + /* make sure the language is part of the supported languages */ + if (![supportedLanguages containsObject: userLanguage]) + userLanguage = [parentSource stringForKey: @"SOGoLanguage"]; + [userLanguage retain]; + } + + return userLanguage; } - (void) setMailShowSubscribedFoldersOnly: (BOOL) newValue @@ -472,6 +493,16 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek"; return [self stringForKey: @"SOGoMailComposeMessageType"]; } +- (void) setMailDisplayRemoteInlineImages: (NSString *) newValue; +{ + [self setObject: newValue forKey: @"SOGoMailDisplayRemoteInlineImages"]; +} + +- (NSString *) mailDisplayRemoteInlineImages; +{ + return [self stringForKey: @"SOGoMailDisplayRemoteInlineImages"]; +} + - (void) setMailMessageForwarding: (NSString *) newValue { [self setObject: newValue forKey: @"SOGoMailMessageForwarding"]; diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index af11e0db2..4b630213f 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -595,7 +595,7 @@ static Class NSNullK; withUIDorEmail: (NSString *) uid inDomain: (NSString *) domain { - NSString *sourceID, *cn, *c_domain, *c_uid, *c_imaphostname, *c_imaplogin; + NSString *sourceID, *cn, *c_domain, *c_uid, *c_imaphostname, *c_imaplogin, *c_sievehostname; NSObject *currentSource; NSEnumerator *sogoSources; NSDictionary *userEntry; @@ -610,6 +610,7 @@ static Class NSNullK; c_domain = nil; c_imaphostname = nil; c_imaplogin = nil; + c_sievehostname = nil; [currentUser setObject: [NSNumber numberWithBool: YES] forKey: @"CalendarAccess"]; @@ -640,6 +641,8 @@ static Class NSNullK; c_imaphostname = [userEntry objectForKey: @"c_imaphostname"]; if (!c_imaplogin) c_imaplogin = [userEntry objectForKey: @"c_imaplogin"]; + if (!c_sievehostname) + c_sievehostname = [userEntry objectForKey: @"c_sievehostname"]; access = [[userEntry objectForKey: @"CalendarAccess"] boolValue]; if (!access) [currentUser setObject: [NSNumber numberWithBool: NO] @@ -675,6 +678,8 @@ static Class NSNullK; [currentUser setObject: c_imaphostname forKey: @"c_imaphostname"]; if (c_imaplogin) [currentUser setObject: c_imaplogin forKey: @"c_imaplogin"]; + if (c_sievehostname) + [currentUser setObject: c_sievehostname forKey: @"c_sievehostname"]; [currentUser setObject: emails forKey: @"emails"]; [currentUser setObject: cn forKey: @"cn"]; diff --git a/SoObjects/SOGo/SOGoWebAuthenticator.h b/SoObjects/SOGo/SOGoWebAuthenticator.h index 870a4c416..5a3533c70 100644 --- a/SoObjects/SOGo/SOGoWebAuthenticator.h +++ b/SoObjects/SOGo/SOGoWebAuthenticator.h @@ -32,6 +32,9 @@ @class NSString; +@class WOContext; +@class WOCookie; + @class SOGoUser; @interface SOGoWebAuthenticator : SoCookieAuthenticator @@ -45,6 +48,10 @@ expire: (int *) _expire grace: (int *) _grace; +- (WOCookie *) cookieWithUsername: (NSString *) username + andPassword: (NSString *) password + inContext: (WOContext *) context; + @end #endif /* _SOGOWEBAUTHENTICATOR_H_ */ diff --git a/SoObjects/SOGo/SOGoWebAuthenticator.m b/SoObjects/SOGo/SOGoWebAuthenticator.m index ac35d31e2..cfe2482f0 100644 --- a/SoObjects/SOGo/SOGoWebAuthenticator.m +++ b/SoObjects/SOGo/SOGoWebAuthenticator.m @@ -32,9 +32,12 @@ #import #import #import +#import #import +#import #import #import +#import #import #import @@ -47,7 +50,9 @@ #import "SOGoSystemDefaults.h" #import "SOGoUser.h" #import "SOGoUserManager.h" - +#if defined(SAML2_CONFIG) +#import "SOGoSAML2Session.h" +#endif #import "SOGoWebAuthenticator.h" @implementation SOGoWebAuthenticator @@ -107,11 +112,13 @@ { SOGoCASSession *session; SOGoSystemDefaults *sd; + NSString *authenticationType; BOOL rc; sd = [SOGoSystemDefaults sharedSystemDefaults]; - if ([[sd authenticationType] isEqualToString: @"cas"]) + authenticationType = [sd authenticationType]; + if ([authenticationType isEqualToString: @"cas"]) { session = [SOGoCASSession CASSessionWithIdentifier: _pwd fromProxy: NO]; if (session) @@ -119,6 +126,18 @@ else rc = NO; } +#if defined(SAML2_CONFIG) + else if ([authenticationType isEqualToString: @"saml2"]) + { + SOGoSAML2Session *saml2Session; + WOContext *context; + + context = [[WOApplication application] context]; + saml2Session = [SOGoSAML2Session SAML2SessionWithIdentifier: _pwd + inContext: context]; + rc = [[saml2Session login] isEqualToString: _login]; + } +#endif /* SAML2_CONFIG */ else rc = [[SOGoUserManager sharedUserManager] checkLogin: _login password: _pwd @@ -225,16 +244,18 @@ forURL: (NSURL *) server forceRenew: (BOOL) renew { - NSString *password, *service, *scheme; - SOGoCASSession *session; - SOGoSystemDefaults *sd; + NSString *authType, *password; password = [self passwordInContext: context]; if ([password length]) { - sd = [SOGoSystemDefaults sharedSystemDefaults]; - if ([[sd authenticationType] isEqualToString: @"cas"]) + authType = [[SOGoSystemDefaults sharedSystemDefaults] + authenticationType]; + if ([authType isEqualToString: @"cas"]) { + SOGoCASSession *session; + NSString *service, *scheme; + session = [SOGoCASSession CASSessionWithIdentifier: password fromProxy: NO]; @@ -252,6 +273,23 @@ if ([password length] || renew) [session updateCache]; } +#if defined(SAML2_CONFIG) + else if ([authType isEqualToString: @"saml2"]) + { + SOGoSAML2Session *session; + WOContext *context; + NSData *assertion; + + context = [[WOApplication application] context]; + session = [SOGoSAML2Session SAML2SessionWithIdentifier: password + inContext: context]; + assertion = [[session assertion] + dataUsingEncoding: NSUTF8StringEncoding]; + password = [[[assertion compress] stringByEncodingBase64] + stringByReplacingString: @"\n" + withString: @""]; + } +#endif } return password; @@ -314,4 +352,44 @@ [response addCookie: authCookie]; } +- (WOCookie *) cookieWithUsername: (NSString *) username + andPassword: (NSString *) password + inContext: (WOContext *) context +{ + WOCookie *authCookie; + NSString *cookieValue, *cookieString, *appName, *sessionKey, *userKey, *securedPassword; + + // + // We create a new cookie - thus we create a new session + // associated to the user. For security, we generate: + // + // A- a session key + // B- a user key + // + // In memcached, the session key will be associated to the user's password + // which will be XOR'ed with the user key. + // + sessionKey = [SOGoSession generateKeyForLength: 16]; + userKey = [SOGoSession generateKeyForLength: 64]; + + NSString *value = [NSString stringWithFormat: @"%@:%@", username, password]; + securedPassword = [SOGoSession securedValue: value usingKey: userKey]; + + + [SOGoSession setValue: securedPassword forSessionKey: sessionKey]; + + //cookieString = [NSString stringWithFormat: @"%@:%@", + // username, password]; + cookieString = [NSString stringWithFormat: @"%@:%@", + userKey, sessionKey]; + cookieValue = [NSString stringWithFormat: @"basic %@", + [cookieString stringByEncodingBase64]]; + authCookie = [WOCookie cookieWithName: [self cookieNameInContext: context] + value: cookieValue]; + appName = [[context request] applicationName]; + [authCookie setPath: [NSString stringWithFormat: @"/%@/", appName]]; + + return authCookie; +} + @end /* SOGoWebAuthenticator */ diff --git a/SoObjects/SOGo/SQLSource.h b/SoObjects/SOGo/SQLSource.h index eeac526cf..00bf48dda 100644 --- a/SoObjects/SOGo/SQLSource.h +++ b/SoObjects/SOGo/SQLSource.h @@ -43,6 +43,7 @@ NSArray *_mailFields; NSString *_imapLoginField; NSString *_imapHostField; + NSString *_sieveHostField; NSString *_userPasswordAlgorithm; NSURL *_viewURL; BOOL _prependPasswordScheme; diff --git a/SoObjects/SOGo/SQLSource.m b/SoObjects/SOGo/SQLSource.m index 2c5091306..c2db99f7d 100644 --- a/SoObjects/SOGo/SQLSource.m +++ b/SoObjects/SOGo/SQLSource.m @@ -98,6 +98,7 @@ _kindField = nil; _multipleBookingsField = nil; _imapHostField = nil; + _sieveHostField = nil; } return self; @@ -115,6 +116,7 @@ [_multipleBookingsField release]; [_domainField release]; [_imapHostField release]; + [_sieveHostField release]; [super dealloc]; } @@ -131,6 +133,7 @@ ASSIGN(_userPasswordAlgorithm, [udSource objectForKey: @"userPasswordAlgorithm"]); ASSIGN(_imapLoginField, [udSource objectForKey: @"IMAPLoginFieldName"]); ASSIGN(_imapHostField, [udSource objectForKey: @"IMAPHostFieldName"]); + ASSIGN(_sieveHostField, [udSource objectForKey: @"SieveHostFieldName"]); ASSIGN(_kindField, [udSource objectForKey: @"KindFieldName"]); ASSIGN(_multipleBookingsField, [udSource objectForKey: @"MultipleBookingsFieldName"]); ASSIGN(_domainField, [udSource objectForKey: @"DomainFieldName"]); @@ -187,7 +190,10 @@ pass = [plainPassword asCryptedPassUsingScheme: _userPasswordAlgorithm]; if (pass == nil) - [self errorWithFormat: @"Unsupported user-password algorithm: %@", _userPasswordAlgorithm]; + { + [self errorWithFormat: @"Unsupported user-password algorithm: %@", _userPasswordAlgorithm]; + return nil; + } if (_prependPasswordScheme) result = [NSString stringWithFormat: @"{%@}%@", _userPasswordAlgorithm, pass]; @@ -308,18 +314,20 @@ NSString *sqlstr; BOOL didChange; BOOL isOldPwdOk; - + isOldPwdOk = NO; didChange = NO; - + // Verify current password isOldPwdOk = [self checkLogin:login password:oldPassword perr:perr expire:0 grace:0]; - + if (isOldPwdOk) { // Encrypt new password NSString *encryptedPassword = [self _encryptPassword: newPassword]; - + if(encryptedPassword == nil) + return NO; + // Save new password login = [login stringByReplacingString: @"'" withString: @"''"]; cm = [GCSChannelManager defaultChannelManager]; @@ -519,6 +527,13 @@ [response setObject: value forKey: @"c_imaphostname"]; } + if (_sieveHostField) + { + value = [response objectForKey: _sieveHostField]; + if ([value isNotNull]) + [response setObject: value forKey: @"c_sievehostname"]; + } + // We check if the user can authenticate if (_authenticationFilter) { diff --git a/SoObjects/SOGo/gen-saml2-exceptions.py b/SoObjects/SOGo/gen-saml2-exceptions.py new file mode 100755 index 000000000..3738f6750 --- /dev/null +++ b/SoObjects/SOGo/gen-saml2-exceptions.py @@ -0,0 +1,158 @@ +#!/usr/bin/python + +include_dirs = [] + +output = "-" + +import os +import sys + +m_template = """/* %(module)s.m (auto-generated) */ + +#include +#include + +#import +#import +#import + +#import "%(module)s.h" + +%(exception_init)s + +static NSMutableDictionary *exceptionTable = nil; + +@implementation NSException (SOGoSAML2Extension) + +static void +InitExceptionTable () +{ + exceptionTable = [NSMutableDictionary new]; + %(exception_table_init)s +} + ++ (void) raiseSAML2Exception: (lasso_error_t) lassoError +{ + NSString *exceptionName, *reason; + + if (!exceptionTable) + InitExceptionTable (); + + exceptionName = [exceptionTable objectForKey: [NSNumber numberWithInt: lassoError]]; + if (!exceptionName) + exceptionName = NSGenericException; + + reason = [NSString stringWithUTF8String: lasso_strerror (lassoError)]; + if (!reason) + reason = @"unspecified"; + + [self raise: exceptionName format: @"%%@", reason]; +} + +@end +""" + +h_template = """/* %(module)s.h (auto-generated) */ + +#ifndef %(h_exclusion)s +#define %(h_exclusion)s 1 + +#include +#import + +@class NSString; + +%(exception_decls)s + +@interface NSException (SOGoSAML2Extension) + ++ (void) raiseSAML2Exception: (lasso_error_t) lassoError; + +@end + +#endif /* %(h_exclusion)s */ +""" + +def ParseErrorsHLine(line): + result = None + if line.startswith("#define LASSO_"): + next_space = line.find(" ", 19) + result = line[8:next_space] + + return result + +def ParseIncludeDirs(args): + dirs = ["/usr/include", "/usr/local/include"] + ignore = True + for arg in args: + if ignore: + if arg == "-I": + ignore = False + elif arg.startswith("-I"): + dirs.append(arg[2:]) + else: + dirs.append(arg) + ignore = True + + return dirs + +def FindHFile(args, filename): + found = None + + include_dirs = ParseIncludeDirs(args) + for dirname in include_dirs: + full_filename = "%s/%s" % (dirname, filename) + if os.path.exists(full_filename): + found = full_filename + + if found is None: + raise Exception, "'%s' not found in include dirs" % filename + + return found + +def ErrorCodeToName(name): + parts = name.split("_") + cap_parts = [part.capitalize() for part in parts] + + return "".join(cap_parts) + +if __name__ == "__main__": + errors_filename = FindHFile(sys.argv, os.path.join("lasso", "errors.h")) + + inf = open(errors_filename) + error_codes = {} + line = inf.readline() + while line != "": + error_code = ParseErrorsHLine(line) + if error_code: + error_codes[error_code] = ErrorCodeToName(error_code) + line = inf.readline() + inf.close() + + exception_decls = [] + exception_init = [] + exception_table_init = [] + + exc_table_format \ + = (" [exceptionTable setObject: %s\n" + " forKey: [NSNumber numberWithInt: %s]];") + for error_code in error_codes: + name = error_codes[error_code]; + exception_init.append("NSString * const %s = @\"%s\";" % (name, name)) + exception_decls.append("extern NSString * const %s;" % name) + exception_table_init.append(exc_table_format % (name, error_code)) + + module = "SOGoSAML2Exceptions" + outvars = {"module": module, + "h_exclusion": "%s_H" % module.upper(), + "exception_decls": "\n".join(exception_decls), + "exception_init": "\n".join(exception_init), + "exception_table_init": "\n".join(exception_table_init)} + + outf = open("%s.m" % module, "w+") + outf.write(m_template % outvars) + outf.close() + + outf = open("%s.h" % module, "w+") + outf.write(h_template % outvars) + outf.close() diff --git a/Tests/Integration/preferences.py b/Tests/Integration/preferences.py index 626d2e209..8290ac385 100644 --- a/Tests/Integration/preferences.py +++ b/Tests/Integration/preferences.py @@ -13,7 +13,7 @@ import sogoLogin SOGoSupportedLanguages = [ "Catalan", "Czech", "Dutch", "Danish", "Welsh", "English", "SpanishSpain", "SpanishArgentina", "French", "German", "Icelandic", "Italian", "Hungarian", "BrazilianPortuguese", - "NorwegianBokmal", "NorwegianNynorsk", "Polish", "Russian", + "NorwegianBokmal", "NorwegianNynorsk", "Polish", "Russian", "Slovak", "Ukrainian", "Swedish" ]; daysBetweenResponseList=[1,2,3,5,7,14,21,30] diff --git a/Tests/Integration/test-davacl.py b/Tests/Integration/test-davacl.py index 10a067c3e..0298a973a 100755 --- a/Tests/Integration/test-davacl.py +++ b/Tests/Integration/test-davacl.py @@ -208,8 +208,8 @@ class DAVAclTest(unittest.TestCase): return versitStruct event_template = """BEGIN:VCALENDAR -VERSION:2.0 PRODID:-//Inverse//Event Generator//EN +VERSION:2.0 BEGIN:VEVENT SEQUENCE:0 TRANSP:OPAQUE diff --git a/Tests/Unit/GNUmakefile b/Tests/Unit/GNUmakefile index c95bd73c3..a7a8376bf 100644 --- a/Tests/Unit/GNUmakefile +++ b/Tests/Unit/GNUmakefile @@ -38,10 +38,9 @@ ADDITIONAL_LIB_DIRS += \ -Wl,-rpath,../../SoObjects/SOGo/SOGo.framework/Versions/Current -Wl,-rpath,../../SOPE/NGCards/obj -Wl,-rpath,../../SOPE/GDLContentStore/obj -Wl,-rpath,../../OGoContentStore/obj ADDITIONAL_LDFLAGS += -Wl,--no-as-needed -check :: - ./obj/sogo-tests - -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/test-tool.make -include GNUmakefile.postamble +check :: + ./obj/sogo-tests diff --git a/Tools/SOGoToolRenameUser.m b/Tools/SOGoToolRenameUser.m index 860f98e0f..937424d76 100644 --- a/Tools/SOGoToolRenameUser.m +++ b/Tools/SOGoToolRenameUser.m @@ -35,6 +35,7 @@ #import #import #import +#import #import #import @@ -113,6 +114,7 @@ BOOL rc = NO; GCSFolderManager *fm; GCSChannelManager *cm; + GCSSpecialQueries *specialQueries; NSURL *folderLocation; EOAdaptorContext *ac; EOAdaptorChannel *fc; @@ -125,6 +127,7 @@ folderLocation = [fm folderInfoLocation]; fc = [cm acquireOpenChannelForURL: folderLocation]; ac = [fc adaptorContext]; + specialQueries = [fc specialQueries]; sqlFromUserID = [fromUserID asSafeSQLString]; sqlToUserID = [toUserID asSafeSQLString]; @@ -137,15 +140,16 @@ if (!sqlError) { sql - = [NSString stringWithFormat: @"UPDATE %@" - @" SET c_path = '/'||c_path1||'/'||c_path2||'/'||c_path3||'/'||c_path4" - @" WHERE c_path2 = '%@'", - [folderLocation gcsTableName], sqlToUserID]; + = [specialQueries updateCPathInFolderInfo: [folderLocation gcsTableName] + withCPath2: sqlToUserID]; sqlError = [fc evaluateExpressionX: sql]; } if (sqlError) - [ac rollbackTransaction]; + { + [ac rollbackTransaction]; + NSLog([sqlError reason]); + } else rc = [ac commitTransaction]; @@ -195,7 +199,10 @@ [profileLocation gcsTableName], sqlToUserID, sqlFromUserID]; sqlError = [fc evaluateExpressionX: sql]; if (sqlError) - [ac rollbackTransaction]; + { + [ac rollbackTransaction]; + NSLog([sqlError reason]); + } else rc = [ac commitTransaction]; diff --git a/Tools/SOGoToolRestore.m b/Tools/SOGoToolRestore.m index 3b19fff7c..0cdda3b29 100644 --- a/Tools/SOGoToolRestore.m +++ b/Tools/SOGoToolRestore.m @@ -21,6 +21,7 @@ */ #import +#import #import #import #import @@ -346,6 +347,7 @@ typedef enum SOGoToolRestoreMode { - (BOOL) restoreRecords: (NSArray *) records ofFolder: (GCSFolder *) gcsFolder { + NSAutoreleasePool *pool; NSDictionary *existingRecords, *currentRecord; NSString *cName, *cContent; int count, max; @@ -354,12 +356,18 @@ typedef enum SOGoToolRestoreMode { if (records) { + existingRecords = [self fetchExistingRecordsFromFolder: gcsFolder]; + pool = [[NSAutoreleasePool alloc] init]; version = 0; rc = YES; - existingRecords = [self fetchExistingRecordsFromFolder: gcsFolder]; max = [records count]; for (count = 0; count < max; count++) { + if (count > 0 && count%100 == 0) + { + DESTROY(pool); + pool = [[NSAutoreleasePool alloc] init]; + } currentRecord = [records objectAtIndex: count]; cName = [currentRecord objectForKey: @"c_name"]; if (![existingRecords objectForKey: cName]) @@ -370,6 +378,7 @@ typedef enum SOGoToolRestoreMode { baseVersion: &version]; } } + DESTROY(pool); } else { diff --git a/UI/AdministrationUI/GNUmakefile b/UI/AdministrationUI/GNUmakefile index ef8acf8f4..df3b4cb57 100644 --- a/UI/AdministrationUI/GNUmakefile +++ b/UI/AdministrationUI/GNUmakefile @@ -6,7 +6,7 @@ BUNDLE_NAME = AdministrationUI AdministrationUI_PRINCIPAL_CLASS = AdministrationUIProduct -AdministrationUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Italian NorwegianBokmal NorwegianNynorsk Polish Russian SpanishSpain SpanishArgentina Swedish Ukrainian Welsh +AdministrationUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh AdministrationUI_OBJC_FILES = \ AdministrationUIProduct.m \ diff --git a/UI/AdministrationUI/Slovak.lproj/Localizable.strings b/UI/AdministrationUI/Slovak.lproj/Localizable.strings new file mode 100644 index 000000000..917cab3b1 --- /dev/null +++ b/UI/AdministrationUI/Slovak.lproj/Localizable.strings @@ -0,0 +1,15 @@ +/* this file is in UTF-8 format! */ + +"Help" = "Pomoc"; +"Close" = "Zavrieť"; + +"Modules" = "Moduly"; + +/* Modules short names */ +"ACLs" = "ACL"; + +/* Modules titles */ +"ACLs_title" = "Spravovanie ACL zložiek uzívateľov"; + +/* Modules descriptions */ +"ACLs_description" = "

Administrácia kontroly prístupových práv (ACL) dovoluje spravovať ACLs kalendárov a adresárov pre všetkých užívateľov.

Pre úpravu ACL zložky užívateľa, napíšte meno užívateľa v kolonke hľadaj hore v okne a dvojklikom potvrďte výber zložky.

"; diff --git a/UI/Common/GNUmakefile b/UI/Common/GNUmakefile index a8bc5e043..450aaf759 100644 --- a/UI/Common/GNUmakefile +++ b/UI/Common/GNUmakefile @@ -6,7 +6,7 @@ BUNDLE_NAME = CommonUI CommonUI_PRINCIPAL_CLASS = CommonUIProduct -CommonUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian SpanishSpain SpanishArgentina Swedish Ukrainian Welsh +CommonUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh CommonUI_OBJC_FILES += \ CommonUIProduct.m \ diff --git a/UI/Common/Polish.lproj/Localizable.strings b/UI/Common/Polish.lproj/Localizable.strings index 74878d05e..9efab19e5 100644 --- a/UI/Common/Polish.lproj/Localizable.strings +++ b/UI/Common/Polish.lproj/Localizable.strings @@ -25,7 +25,7 @@ "Owner:" = "Właściciel:"; "Publish the Free/Busy information" = "Opublikuj informację wolny/zajęty"; -"Add..." = "Dodaj..."; +"Add..." = "Dodaj"; "Remove" = "Usuń"; "Subscribe User" = "Subskrybuj użytkownika"; @@ -39,7 +39,7 @@ "Any user with an account on this system will be able to access your mailbox \"%{0}\". Are you certain you trust them all?" = "Dowolny użytkownik systemu będzie miał dostęp do Twojej skrzynki \"%{0}\". Naprawdę ufasz im wszystkim?"; -"Any user with an account on this system will be able to access your calendar \"%{0}\". Are you certain you trust them all?" +"Any user with an account on this system will be able to access your calendar \"%{0}\". Are you certain you trust them all?" = "Dowolny użytkownik systemu będzie miał dostęp do Twojego kalendarza \"%{0}\". Naprawdę ufasz im wszystkim?"; "Potentially anyone on the Internet will be able to access your calendar \"%{0}\", even if they do not have an account on this system. Is this information suitable for the public Internet?" = "Twój kalendarz \"%{0}\" będzie publiczne dostępny dla każdego w Internecie. Czy te informacje napewno mają być tak upublicznione?"; @@ -52,14 +52,14 @@ /* generic.js */ "Unable to subscribe to that folder!" - = "Nie można subskrybować tego foldera!"; + = "Nie można subskrybować tego folderu!"; "You cannot subscribe to a folder that you own!" - = "Nie możesz subskrybować foldera, który jest twoją własnością!"; + = "Nie możesz subskrybować folderu, który jest twoją własnością!"; "Unable to unsubscribe from that folder!" - = "Nie można wyłączyć subskrypcji tego foldera!"; + = "Nie można wyłączyć subskrypcji tego folderu!"; "You cannot unsubscribe from a folder that you own!" - = "Nie możesz wyłączyć subskrypcji foldera, który jest twoją własnością!"; -"Unable to rename that folder!" = "Nie można zmienić nazwy tego foldera!"; + = "Nie możesz wyłączyć subskrypcji folderu, który jest twoją własnością!"; +"Unable to rename that folder!" = "Nie można zmienić nazwy tego folderu!"; "You have already subscribed to that folder!" = "Już subskrybujesz ten folder!"; "The user rights cannot be edited for this object!" @@ -79,7 +79,7 @@ "delegate is a participant" = "Delegat jest już uczestnikiem."; "delegate is a group" = "Wskazany adres jest grupą. Możesz oddelegować tylko pojedynczną osobę."; -"Snooze for " = "Drzemka przez"; +"Snooze for " = "Drzemka przez "; "5 minutes" = "5 minut"; "10 minutes" = "10 minut"; "15 minutes" = "15 minut"; @@ -106,4 +106,4 @@ "a2_Wednesday" = "Śr"; "a2_Thursday" = "Cz"; "a2_Friday" = "Pi"; -"a2_Saturday" = "So"; \ No newline at end of file +"a2_Saturday" = "So"; diff --git a/UI/Common/Slovak.lproj/Localizable.strings b/UI/Common/Slovak.lproj/Localizable.strings new file mode 100644 index 000000000..80cf35232 --- /dev/null +++ b/UI/Common/Slovak.lproj/Localizable.strings @@ -0,0 +1,109 @@ +/* this file is in UTF-8 format! */ + +/* toolbars */ +"Save" = "Uložiť"; +"Close" = "Zavrieť"; +"Edit User Rights" = "Upraviť uživateľské práva"; + +"Home" = "Domov"; +"Calendar" = "Kalendár"; +"Address Book" = "Adresár"; +"Mail" = "Pošta"; +"Preferences" = "Predvoľby"; +"Administration" = "Správa"; +"Disconnect" = "Odpojiť"; +"Right Administration" = "Administrácia práv"; +"Log Console (dev.)" = "Log konzola (vývoj)"; + +"User" = "Užívateľ"; + +"Help" = "Pomoc"; + +"noJavascriptError" = "Sogo vyžaduje pre spustenie JavaScript. Uistite sa, že táto možnosť je k dispozícii a aktivovaná v prehliadači."; +"noJavascriptRetry" = "Opakovať"; + +"Owner:" = "Vlastník:"; +"Publish the Free/Busy information" = "Publikovanie Free / Busy informácií"; + +"Add..." = "Pridať..."; +"Remove" = "Odstrániť"; + +"Subscribe User" = "Prihlásiť užívateľa k odberu"; + +"Any Authenticated User" = "Všetkým prihláseným užívateľom"; +"Public Access" = "Verejný prístup"; +"Any user not listed above" = "Každý užívateľ, ktorý nie je uvedený vyššie"; +"Anybody accessing this resource from the public area" = "Každý, kto prístupuje k tomuto zdroju z verejného priestoru"; + +"Sorry, the user rights can not be configured for that object." = "Je nám ľúto, užívateľské práva nie je možné konfigurovať pre daný objekt."; + +"Any user with an account on this system will be able to access your mailbox \"%{0}\". Are you certain you trust them all?" + = "Ktorýkoľvek užívateľ tohoto systému bude môcť vidieť Vašu emailovú shránku \"%{0}\". Ste si istý že veríte všetkým užívateľom?"; +"Any user with an account on this system will be able to access your calendar \"%{0}\". Are you certain you trust them all?" + = "Ktorýkoľvek užívateľ tohoto systému bude môcť vidieť Váš kalendár \"%{0}\". Ste si istý že veríte všetkým užívateľom?"; +"Potentially anyone on the Internet will be able to access your calendar \"%{0}\", even if they do not have an account on this system. Is this information suitable for the public Internet?" + = "Potencionálne ktokoľvek na internete bude môcť vidieť Váš kalendár \"%{0}\", napriek tomu že nemá účet v tomto systéme. Sú tieto informácie vhodné pre verejnosť?"; +"Any user with an account on this system will be able to access your address book \"%{0}\". Are you certain you trust them all?" + = "Ktorýkoľvek užívateľ tohoto systému bude môcť vidieť Váš adresár \"%{0}\". Ste si istý že veríte všetkým užívateľom?"; +"Potentially anyone on the Internet will be able to access your address book \"%{0}\", even if they do not have an account on this system. Is this information suitable for the public Internet?" + = "Potencionálne ktokoľvek na internete bude môcť vidieť Váš adresár \"%{0}\", napriek tomu že nemá účet v tomto systéme. Sú tieto informácie vhodné pre verejnosť?"; +"Give Access" = "Daj prístup"; +"Keep Private" = "Nechaj súkromné"; + +/* generic.js */ +"Unable to subscribe to that folder!" + = "Nedá sa prihlásiť k odberu tejto zložky!"; +"You cannot subscribe to a folder that you own!" + = "Nemôžete sa prihlásiť k odberu zložky, ktorú vlastnite!"; +"Unable to unsubscribe from that folder!" + = "Nedá sa odhlásiť z tejto zložky!"; +"You cannot unsubscribe from a folder that you own!" + = "Nemôžete sa odhlásiť zo zložky, ktorú vlastnite!"; +"Unable to rename that folder!" = "Nemožno premenovať túto zložku!"; +"You have already subscribed to that folder!" + = "Už ste prihlásení k odberu tejto zložky!"; +"The user rights cannot be edited for this object!" + = "Užívateľské práva nemožno upraviť pre tento objekt!"; +"A folder by that name already exists." = "Zložka s týmto názvom už existuje."; +"You cannot create a list in a shared address book." + = "Nemôžete vytvoriť zoznam v zdieľanom adresári."; +"Warning" = "Varovanie"; + +"You are not allowed to access this module or this system. Please contact your system administrator." += "Nemate dovolený prístup k tomuto modulu alebo tento systém. Obráťte sa na správcu systému."; +"You don't have the required privileges to perform the operation." += "Nemáte potrebné oprávnenia na vykonanie operácie."; + +"noEmailForDelegation" = "Musíte zadať adresu, na ktorú chcete delegovať vaše pozvanie."; +"delegate is organizer" = "Delegát je organizátorom. Zadajte prosím iného delegáta."; +"delegate is a participant" = "Delegát je už účastníkom."; +"delegate is a group" = "Zadaná adresa zodpovedá skupine. Môžete ju delegovať len na jedinečnú osobu."; + +"Snooze for " = "Odložiť"; +"5 minutes" = "5 minút"; +"10 minutes" = "10 minút"; +"15 minutes" = "15 minút"; +"30 minutes" = "30 minút"; +"45 minutes" = "45 minút"; +"1 hour" = "1 hodinu"; + + +/* common buttons */ +"OK" = "OK"; +"Cancel" = "Zrušiť"; +"Yes" = "Áno"; +"No" = "Nie"; + +/* alarms */ +"Reminder:" = "Pripomienka:"; +"Start:" = "Štart:"; +"Due Date:" = "Splatnosť:"; +"Location:" = "Umiestnenie:"; + +"a2_Sunday" = "Ne"; +"a2_Monday" = "Po"; +"a2_Tuesday" = "Ut"; +"a2_Wednesday" = "St"; +"a2_Thursday" = "Št"; +"a2_Friday" = "Pi"; +"a2_Saturday" = "So"; diff --git a/UI/Common/UIxPageFrame.m b/UI/Common/UIxPageFrame.m index 60d9bca41..215088a55 100644 --- a/UI/Common/UIxPageFrame.m +++ b/UI/Common/UIxPageFrame.m @@ -485,13 +485,17 @@ BOOL canLogoff; id auth; SOGoSystemDefaults *sd; + NSString *authType; auth = [[self clientObject] authenticatorInContext: context]; if ([auth respondsToSelector: @selector (cookieNameInContext:)]) { sd = [SOGoSystemDefaults sharedSystemDefaults]; - if ([[sd authenticationType] isEqualToString: @"cas"]) + authType = [sd authenticationType]; + if ([authType isEqualToString: @"cas"]) canLogoff = [sd CASLogoutEnabled]; + else if ([authType isEqualToString: @"saml2"]) + canLogoff = [sd SAML2LogoutEnabled]; else canLogoff = [[auth cookieNameInContext: context] length] > 0; } diff --git a/UI/Contacts/BrazilianPortuguese.lproj/Localizable.strings b/UI/Contacts/BrazilianPortuguese.lproj/Localizable.strings index c276a4c56..da9156772 100644 --- a/UI/Contacts/BrazilianPortuguese.lproj/Localizable.strings +++ b/UI/Contacts/BrazilianPortuguese.lproj/Localizable.strings @@ -195,9 +195,11 @@ "Lists can't be moved or copied." = "Lists can't be moved or copied."; "Export" = "Export"; "Export Address Book..." = "Export Address Book..."; +"View Raw Source" = "Visualizar Fonte"; "Import Cards" = "Import Cards"; "Select a vCard or LDIF file." = "Select a vCard or LDIF file."; "Upload" = "Upload"; +"Uploading" = "Carregando"; "Done" = "Done"; "An error occured while importing contacts." = "An error occured while importing contacts."; "No card was imported." = "No card was imported."; diff --git a/UI/Contacts/GNUmakefile b/UI/Contacts/GNUmakefile index 8ba2a84b2..bc2d402b4 100644 --- a/UI/Contacts/GNUmakefile +++ b/UI/Contacts/GNUmakefile @@ -6,7 +6,7 @@ BUNDLE_NAME = ContactsUI ContactsUI_PRINCIPAL_CLASS = ContactsUIProduct -ContactsUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian SpanishSpain SpanishArgentina Swedish Ukrainian Welsh +ContactsUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh ContactsUI_OBJC_FILES = \ UIxContactsUserFolders.m \ diff --git a/UI/Contacts/Polish.lproj/Localizable.strings b/UI/Contacts/Polish.lproj/Localizable.strings index 8a2c84c55..46c61ce70 100644 --- a/UI/Contacts/Polish.lproj/Localizable.strings +++ b/UI/Contacts/Polish.lproj/Localizable.strings @@ -65,11 +65,11 @@ "New Card" = "Nowy kontakt"; "New List" = "Nowa lista"; "Properties" = "Właściwości"; -"Sharing..." = "Udostępnianie..."; +"Sharing..." = "Udostępnianie"; "Write" = "Napisz"; "Delete" = "Usuń"; "Instant Message" = "Szybka wiadomość"; -"Add..." = "Dodaj..."; +"Add..." = "Dodaj"; "Remove" = "Usuń"; "Please wait..." = "Zaczekaj chwilę..."; @@ -84,7 +84,7 @@ "Phone Number:" = "Numer telefonu:"; "Prefers to receive messages formatted as:" = "Preferuje wiadomości w formacie:"; "Screen Name:" = "Nazwa ekranowa:"; -"Categories:" = "Categories:"; +"Categories:" = "Kategorie:"; "First:" = "Imię:"; "Last:" = "Nazwisko:"; @@ -98,9 +98,9 @@ "Pager:" = "Pager:"; /* categories */ -"contacts_category_labels" = "Colleague, Competitor, Customer, Friend, Family, Business Partner, Provider, Press, VIP"; -"Categories" = "Categories"; -"New category" = "New category"; +"contacts_category_labels" = "Kolega, Konkurencja, Klient, Przyjaciel, Rodzina, Biznes, Dostawca, Prasa, VIP"; +"Categories" = "Kategorie"; +"New category" = "Nowa kategoria"; /* adresses */ "Title:" = "Tytuł:"; @@ -124,13 +124,13 @@ "Birthday (yyyy-mm-dd):" = "Urodziny (yyyy-mm-dd):"; "Freebusy URL:" = "URL statusu wolny-zajęty:"; -"Add as..." = "Dodaj jako..."; +"Add as..." = "Dodaj jako"; "Recipient" = "Odbiorca"; "Carbon Copy" = "Do wiadomości"; "Blind Carbon Copy" = "Ukryte do wiadomości"; -"New Addressbook..." = "Nowa książka adresowa..."; -"Subscribe to an Addressbook..." = "Subskrybuj książkę adresową..."; +"New Addressbook..." = "Nowa książka adresowa"; +"Subscribe to an Addressbook..." = "Subskrybuj książkę adresową"; "Remove the selected Addressbook" = "Usuń zaznaczoną książkę adresową"; "Name of the Address Book" = "Nazwa książki adresowej"; @@ -194,7 +194,7 @@ "Add" = "Dodaj"; "Lists can't be moved or copied." = "Listy nie mogą być przeniesione ani skopiowane."; "Export" = "Eksport"; -"Export Address Book..." = "Eksportuj książkę adresową..."; +"Export Address Book..." = "Eksportuj książkę adresową"; "View Raw Source" = "Obejrzyj źródło"; "Import Cards" = "Importuj kontakty"; "Select a vCard or LDIF file." = "Wskaż plik vCard lub LDIF."; diff --git a/UI/Contacts/Slovak.lproj/Localizable.strings b/UI/Contacts/Slovak.lproj/Localizable.strings new file mode 100644 index 000000000..00c9c1bc9 --- /dev/null +++ b/UI/Contacts/Slovak.lproj/Localizable.strings @@ -0,0 +1,208 @@ +/* this file is in UTF-8 format! */ + +"Contact" = "Kontakt"; +"Address" = "Adresa"; +"Photos" = "Fotka"; +"Other" = "Ďalšie"; + +"Address Books" = "Adresáre"; +"Addressbook" = "Adresár"; +"Addresses" = "Adresy"; +"Update" = "Aktualizovať"; +"Cancel" = "Zrušiť"; +"Common" = "Spoločný"; +"Contact editor" = "Editor kontaktov"; +"Contact viewer" = "Prehliadač kontaktov"; +"Email" = "Email"; +"Screen Name" = "Zobrazované meno"; +"Extended" = "Rozšírené"; +"Fax" = "Fax"; +"Firstname" = "Meno"; +"Home" = "Domov"; +"HomePhone" = "Telefón domov"; +"Lastname" = "Priezvysko"; +"Location" = "Umiestnenie"; +"MobilePhone" = "Telefón mobil"; +"Name" = "Meno"; +"OfficePhone" = "Telefón kancelária"; +"Organization" = "Organizácia"; +"Work Phone" = "Telefón práca"; +"Phone" = "Telefón"; +"Phones" = "Telefóny"; +"Postal" = "Poštové"; +"Save" = "Uložiť"; +"Internet" = "Internet"; +"Unit" = "Zariadenie"; +"delete" = "zmazať"; +"edit" = "editovať"; +"invalidemailwarn" = "Zvolený email je neplatný"; +"invaliddatewarn" = "Zvolený dátum je neplatný"; +"new" = "nový"; +"Preferred Phone" = "Preferovaný telefón"; + +"Move To" = "Presuň do"; +"Copy To" = "Kopíruj do"; +"Add to:" = "Pridaj do:"; + +/* Tooltips */ + +"Create a new address book card" = "Vytvor novú vizitku"; +"Create a new list" = "Vytvor nový zoznam"; +"Edit the selected card" = "Uprav zvolenú vizitku"; +"Send a mail message" = "Pošli emailovú správu"; +"Delete selected card or address book" = "Vymaž označenú vizitku alebo adresár"; +"Reload all contacts" = "Znovu načítaj všetky kontakty"; + +"htmlMailFormat_UNKNOWN" = "Neznámy"; +"htmlMailFormat_FALSE" = "Jednoduchý text"; +"htmlMailFormat_TRUE" = "HTML"; + +"Name or Email" = "Meno alebo Email"; +"Category" = "Kategória"; +"Personal Addressbook" = "Osobný adresár"; +"Search in Addressbook" = "Hľadaj v adresári"; + +"New Card" = "Nová vizitka"; +"New List" = "Nový zoznam"; +"Properties" = "Možnosti"; +"Sharing..." = "Zdielanie..."; +"Write" = "Napíš"; +"Delete" = "Vymaž"; +"Instant Message" = "Okamžitá správa"; +"Add..." = "Pridaj..."; +"Remove" = "Odstráň"; + +"Please wait..." = "Prosím čakajte..."; +"No possible subscription" = "Žiadne možnosti odberu"; + +"Preferred" = "Preferovaný"; +"Display:" = "Zobraz:"; +"Display Name:" = "Zobrazované meno:"; +"Email:" = "Email:"; +"Additional Email:" = "Další email:"; + +"Phone Number:" = "Telefónne číslo:"; +"Prefers to receive messages formatted as:" = "Preferuje prijímať správy formátované ako:"; +"Screen Name:" = "Zobrazované meno:"; +"Categories:" = "Kategórie:"; + +"First:" = "Meno:"; +"Last:" = "Priezvisko:"; +"Nickname:" = "Prezývka:"; + +"Telephone" = "Telefón"; +"Work:" = "Do práce:"; +"Home:" = "Domov:"; +"Fax:" = "Fax:"; +"Mobile:" = "Mobil:"; +"Pager:" = "Pager:"; + +/* categories */ +"contacts_category_labels" = "Kolega, Konkurent, Zákazník, Priateľ, Rodina, Obchodný partner, Dodávateľ, Novinár, VIP"; +"Categories" = "Kategórie"; +"New category" = "Nová kategória"; + +/* adresses */ +"Title:" = "Názov:"; +"Service:" = "Služba:"; +"Company:" = "Spoločnosť:"; +"Department:" = "Oddelenie:"; +"Organization:" = "Organizácia:"; +"Address:" = "Adresa:"; +"City:" = "Mesto:"; +"State_Province:" = "Štát:"; +"ZIP_Postal Code:" = "Poštové smerové číslo:"; +"Country:" = "Krajina:"; +"Web Page:" = "WWW stránka:"; + +"Work" = "Práca"; +"Other Infos" = "Ostatné informácie"; + +"Note:" = "Poznámky:"; +"Timezone:" = "Časová zóna:"; +"Birthday:" = "Narodeniny:"; +"Birthday (yyyy-mm-dd):" = "Narodeniny (dd-mm-yyyy):"; +"Freebusy URL:" = "URL voľný alebo obsadený:"; + +"Add as..." = "Pridaj ako..."; +"Recipient" = "Príjemca"; +"Carbon Copy" = "Kópia"; +"Blind Carbon Copy" = "Skrytá kópia"; + +"New Addressbook..." = "Nový adresár..."; +"Subscribe to an Addressbook..." = "Odoberať adresár..."; +"Remove the selected Addressbook" = "Odstráň označený adresár"; + +"Name of the Address Book" = "Názov adresára"; +"Are you sure you want to delete the selected address book?" += "Ste si istý že chcete odstrániť označený adresár?"; +"You cannot remove nor unsubscribe from a public addressbook." += "Nemôžete odstrániť ani zrušiť odber verejného adresára."; +"You cannot remove nor unsubscribe from your personal addressbook." += "Nemôžete odstrániť ani zrušiť odber súkromného adresára."; + +"Are you sure you want to delete the selected contacts?" += "Ste si istý že chcete odstrániť označené kontakty?"; + +"You cannot delete the card of \"%{0}\"." += "Nemôžete odstrániť vizitku \"%{0}\"."; + +"Address Book Name" = "Meno adresára"; + +"You cannot subscribe to a folder that you own!" += "Nemôžete sa prihlásiť na odber svojej vlastnej zložky."; +"Unable to subscribe to that folder!" += "Nedá sa prihlásiť na odber tejto zložky."; + +/* acls */ +"Access rights to" = "Prístupové práva pre"; +"For user" = "Pre užívateľa"; + +"Any Authenticated User" = "Akýkoľvek neoverený užívateľ"; +"Public Access" = "Verejný prístup"; + +"This person can add cards to this addressbook." += "Táto osoba môže pridávať vizitky do tohoto adresára."; +"This person can edit the cards of this addressbook." += "Táto osoba môže upravovať vizitky v tomto adresári."; +"This person can list the content of this addressbook." += "Táto osoba môže prehľadávať obsah tohoto adresára."; +"This person can read the cards of this addressbook." += "Táto osoba môže prezerať vizitky v tomto adresári."; +"This person can erase cards from this addressbook." += "Táto osoba môže mazať vizitky z tohoto adresára."; + +"The selected contact has no email address." += "Vybraný kontakt nemá žiadny email."; + +"Please select a contact." = "Prosím vyberte kontakt."; + +/* Error messages for move and copy */ + +"SoAccessDeniedException" = "Nemôžete písať do tohoto adresára."; +"Forbidden" = "Nemôžete písať do tohoto adresára."; +"Invalid Contact" = "Zvolený kontakt už neexistuje."; +"Unknown Destination Folder" = "Vybraný adresár už neexistuje."; + +/* Lists */ +"List details" = "Detaily zoznamu"; +"List name:" = "Meno zoznamu:"; +"List nickname:" = "Prezývka zoznamu:"; +"List description:" = "Popis zoznamu:"; +"Members" = "Členovia"; +"Contacts" = "Kontakty"; +"Add" = "Pridaj"; +"Lists can't be moved or copied." = "Zoznamy nemôžu byť presunuté alebo kopírované."; +"Export" = "Export"; +"Export Address Book..." = "Exportuj adresár..."; +"View Raw Source" = "Zobraziť surový zdroj"; +"Import Cards" = "Importuj vizitky"; +"Select a vCard or LDIF file." = "Vyber vCard alebo LDIF súbor."; +"Upload" = "Nahraj"; +"Uploading" = "Nahrávam"; +"Done" = "Hotovo"; +"An error occured while importing contacts." = "Počas importovania kontaktov sa vyskytla chyba."; +"No card was imported." = "Žiadne vizitky neboli importované"; +"A total of %{0} cards were imported in the addressbook." = "Dokopy bolo do adresára importovaných %{0} vizitiek."; + +"Reload" = "Znovu načítaj"; diff --git a/UI/Contacts/UIxContactFolderActions.m b/UI/Contacts/UIxContactFolderActions.m index a8831a12c..8e2bde448 100644 --- a/UI/Contacts/UIxContactFolderActions.m +++ b/UI/Contacts/UIxContactFolderActions.m @@ -1,14 +1,15 @@ /* Copyright (C) 2004-2005 SKYRIX Software AG + Copyright (C) 2006-2012 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. diff --git a/UI/Contacts/UIxContactsFilterPanel.m b/UI/Contacts/UIxContactsFilterPanel.m index a0f5721bb..75af540ee 100644 --- a/UI/Contacts/UIxContactsFilterPanel.m +++ b/UI/Contacts/UIxContactsFilterPanel.m @@ -32,15 +32,6 @@ @implementation UIxContactsFilterPanel -static NSMutableArray *filters = nil; - -+ (void) initialize -{ -#warning how useful is this? - if (!filters) - filters = [[NSMutableArray alloc] initWithCapacity:4]; -} - - (id) init { if ((self = [super init])) @@ -87,13 +78,6 @@ static NSMutableArray *filters = nil; return searchCriteria; } -/* filters */ - -- (NSArray *) filters -{ - return filters; -} - /* qualifiers */ - (NSString *) filterLabel diff --git a/UI/Contacts/UIxContactsListActions.m b/UI/Contacts/UIxContactsListActions.m index f6941bc0f..1b9ab62f4 100644 --- a/UI/Contacts/UIxContactsListActions.m +++ b/UI/Contacts/UIxContactsListActions.m @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2011 Inverse inc. + Copyright (C) 2006-2012 Inverse inc. Copyright (C) 2004-2005 SKYRIX Software AG - This file is part of OpenGroupware.org. + This file is part of SOGo. SOGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the diff --git a/UI/MailPartViewers/GNUmakefile b/UI/MailPartViewers/GNUmakefile index 7316f2cc9..30a96e374 100644 --- a/UI/MailPartViewers/GNUmakefile +++ b/UI/MailPartViewers/GNUmakefile @@ -6,7 +6,7 @@ BUNDLE_NAME = MailPartViewers MailPartViewers_PRINCIPAL_CLASS = MailPartViewersProduct -MailPartViewers_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian SpanishSpain SpanishArgentina Swedish Ukrainian Welsh +MailPartViewers_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh MailPartViewers_OBJC_FILES += \ MailPartViewersProduct.m \ diff --git a/UI/MailPartViewers/Polish.lproj/Localizable.strings b/UI/MailPartViewers/Polish.lproj/Localizable.strings index e62fe51c6..5d4038cc5 100644 --- a/UI/MailPartViewers/Polish.lproj/Localizable.strings +++ b/UI/MailPartViewers/Polish.lproj/Localizable.strings @@ -23,7 +23,7 @@ request_info = "zaprasza cię na spotkanie."; Accept = "Akceptuj"; Decline = "Odmów"; Tentative = "Niepewny"; -"Delegate ..." = "Przekaż ..."; +"Delegate ..." = "Przekaż"; "Delegated to" = "Przekazane do"; "Update status in calendar" = "Zaktualizuj status w kalendarzu"; "delegated from" = "przekazane z"; diff --git a/UI/MailPartViewers/Slovak.lproj/Localizable.strings b/UI/MailPartViewers/Slovak.lproj/Localizable.strings new file mode 100644 index 000000000..3cc9becbf --- /dev/null +++ b/UI/MailPartViewers/Slovak.lproj/Localizable.strings @@ -0,0 +1,46 @@ +ACCEPTED = "akceptovaný"; +COMPLETED = "kompeltný"; +DECLINED = "zamietnutý"; +DELEGATED = "delegovaný"; +"IN-PROCESS" = "v procesu"; +"NEEDS-ACTION" = "vyžaduje akciu"; +TENTATIVE = "nerozhodný"; +organized_by_you = "organizovaný Vami"; +you_are_an_attendee = "ste účastník"; +add_info_text = "iMIP 'Pridaj' žiadosť zatiaľ nie je SOGo-m podporovaná."; +publish_info_text = "Odosielateľ Vás informuje o priloženej udalosti."; +cancel_info_text = "Vaša pozvánka alebo celá udalosť bola zrušená."; +request_info_no_attendee = "navrhuje stretnutie účastníkom. Tento email je notifikácia, nie ste dohodnutý účastník."; +Appointment = "Schôdzka"; + +Organizer = "Organizátor"; +Time = "Čas"; +Attendees = "Účastníci"; +request_info = "Vás pozýva na účasť na stretnutí"; +"Add to calendar" = "Pridať do kalendára"; +"Delete from calendar" = "Vymazať z kalendára"; +"Update status" = "Aktualizovať stav"; +Accept = "Prijať"; +Decline = "Zamietnuť"; +Tentative = "Nerozhodný"; +"Delegate ..." = "Delegovať ..."; +"Delegated to" = "Delegované na"; +"Update status in calendar" = "Aktualizovať stav v kalendári"; +"delegated from" = "delegované od"; + +reply_info_no_attendee = "Dostali ste odpoveď o dohadovaní stretnutia ale odosielateľ tejto správy nie je účastník."; +reply_info = "Toto je odpoveď na Vašu pozvánku na udalosť."; + +"to" = "pre"; + +"Untitled" = "Bez mena"; + +"Size" = "Veľkosť"; + +"Digital signature is not valid" = "Digitálny podpis nie je platný"; +"Message is signed" = "Správa je podpísaná"; +"Subject" = "Predmet"; +"From" = "Od"; +"Date" = "Dátum"; +"To" = "Komu"; +"Issuer" = "Vystavovateľ"; diff --git a/UI/MailPartViewers/UIxMailPartHTMLViewer.m b/UI/MailPartViewers/UIxMailPartHTMLViewer.m index 8f5d3daca..29d425a03 100644 --- a/UI/MailPartViewers/UIxMailPartHTMLViewer.m +++ b/UI/MailPartViewers/UIxMailPartHTMLViewer.m @@ -63,6 +63,7 @@ _xmlCharsetForCharset (NSString *charset) struct { NSString *name; xmlCharEncoding encoding; } xmlEncodings[] = { { @"us-ascii", XML_CHAR_ENCODING_ASCII}, { @"utf-8", XML_CHAR_ENCODING_UTF8}, + { @"utf8", XML_CHAR_ENCODING_UTF8}, // broken mailers { @"utf-16le", XML_CHAR_ENCODING_UTF16LE}, { @"utf-16be", XML_CHAR_ENCODING_UTF16BE}, { @"ucs-4le", XML_CHAR_ENCODING_UCS4LE}, diff --git a/UI/MailerUI/BrazilianPortuguese.lproj/Localizable.strings b/UI/MailerUI/BrazilianPortuguese.lproj/Localizable.strings index cda934691..3a8455768 100644 --- a/UI/MailerUI/BrazilianPortuguese.lproj/Localizable.strings +++ b/UI/MailerUI/BrazilianPortuguese.lproj/Localizable.strings @@ -107,8 +107,6 @@ "cc" = "Cc"; "bcc" = "Bcc"; -"Addressbook" = "74dac49ea10c32f4141ab15f89148aa0_tr"; - "Edit Draft..." = "Editar Rascunho..."; "Load Images" = "Carregar Imagens"; @@ -285,9 +283,9 @@ = "As mensagens não podem ser movidas para a lixeira. Gostaria de excluí-las imediatamente?"; /* Message editing */ -"error_validationfailed" = "Validação falhou"; "error_missingsubject" = "Está faltando o Assunto"; "error_missingrecipients" = "Sem destinatários selecionados"; +"Send Anyway" = "Enviar assim mesmo"; /* Message sending */ "cannot send message: (smtp) all recipients discarded" = "Não é possível enviar a mensagem: todos os destinatários são inválidos."; diff --git a/UI/MailerUI/Dutch.lproj/Localizable.strings b/UI/MailerUI/Dutch.lproj/Localizable.strings index 73e2313e1..26336acf6 100644 --- a/UI/MailerUI/Dutch.lproj/Localizable.strings +++ b/UI/MailerUI/Dutch.lproj/Localizable.strings @@ -9,7 +9,7 @@ "Get Mail" = "E-mail ophalen"; "Junk" = "Ongewenst"; "Reply" = "Beantwoorden"; -"Reply All" = "Allen beantwoorden"; +"Reply All" = "Allen antwoorden"; "Print" = "Afdrukken"; "Stop" = "Stoppen"; "Write" = "Opstellen"; @@ -32,7 +32,7 @@ "Create a new message" = "Maak een nieuw bericht"; "Go to address book" = "Ga naar adresboek"; "Reply to the message" = "Beantwoord het bericht"; -"Reply to sender and all recipients" = "Antwoord naar verzender en alle ontvangers"; +"Reply to sender and all recipients" = "Antwoord aan verzender en alle ontvangers"; "Forward selected message" = "Geselecteerd bericht doorsturen"; "Delete selected message or folder" = "Verwijder geselecteerd bericht of map"; "Mark the selected messages as junk" = "Markeer de geselecteerde berichten als ongewenst"; @@ -210,7 +210,7 @@ /* Message list popup menu */ "Open Message In New Window" = "In nieuw venster openen"; "Reply to Sender Only" = "Beantwoorden"; -"Reply to All" = "Allen beantwoorden"; +"Reply to All" = "Allen antwoorden"; "Edit As New..." = "Als nieuw bewerken"; "Move To" = "Verplaatsen naar"; "Copy To" = "Kopiëren naar"; @@ -248,7 +248,7 @@ "Enter the new name of your folder :" = "Geef de nieuw naam van de map op:"; "Do you really want to move this folder into the trash ?" - = "Weet u zeker dat u deze map wilt verplaatsen naar de prullenbak"; + = "Weet u zeker dat u deze map naar de prullenbak wilt verplaatsen?"; "Operation failed" = "Bewerking mislukt."; "Quota" = "Quota:"; diff --git a/UI/MailerUI/GNUmakefile b/UI/MailerUI/GNUmakefile index 129c46845..65e94bf1f 100644 --- a/UI/MailerUI/GNUmakefile +++ b/UI/MailerUI/GNUmakefile @@ -6,7 +6,7 @@ BUNDLE_NAME = MailerUI MailerUI_PRINCIPAL_CLASS = MailerUIProduct -MailerUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian SpanishSpain SpanishArgentina Swedish Ukrainian Welsh +MailerUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh MailerUI_OBJC_FILES += \ MailerUIProduct.m \ diff --git a/UI/MailerUI/Polish.lproj/Localizable.strings b/UI/MailerUI/Polish.lproj/Localizable.strings index 9c45d0204..ec70ec4ac 100644 --- a/UI/MailerUI/Polish.lproj/Localizable.strings +++ b/UI/MailerUI/Polish.lproj/Localizable.strings @@ -70,17 +70,17 @@ "Any Authenticated User" = "Dowolny zalogowany użytkownik"; "List and see this folder" = "Wylistuj i zobacz ten folder"; -"Read mails from this folder" = "Czytaj wiadomości z tego foldera"; +"Read mails from this folder" = "Czytaj wiadomości z tego folderu"; "Mark mails read and unread" = "Zaznacz wiadomości jako przeczytane lub nie przeczytane"; "Modify the flags of the mails in this folder" = "Zmień oflagowanie wiadomości w tym folderze"; -"Insert, copy and move mails into this folder" = "Wstaw, kopiuj lub przenieś wiadomości do tego foldera"; +"Insert, copy and move mails into this folder" = "Wstaw, kopiuj lub przenieś wiadomości do tego folderu"; "Post mails" = "Wyślij wiadomości"; "Add subfolders to this folder" = "Utwórz podfoldery w tym folderze"; "Remove this folder" = "Usuń ten folder"; -"Erase mails from this folder" = "Usuń wiadomości z tego foldera"; +"Erase mails from this folder" = "Usuń wiadomości z tego folderu"; "Expunge this folder" = "Wyczyść ostatecznie ten folder"; "Archive This Folder" = "Zarchiwizuj ten folder"; -"Modify the acl of this folder" = "Modyfikuj uprawnienia ACL tego foldera"; +"Modify the acl of this folder" = "Modyfikuj uprawnienia ACL tego folderu"; "Saved Messages.zip" = "Zapisano Messages.zip"; @@ -100,20 +100,20 @@ "Attachments:" = "Załączniki:"; "Open" = "Otwórz"; "Select All" = "Zaznacz wszystkie"; -"Attach Web Page..." = "Załącz stronę Web..."; -"Attach File(s)..." = "Załącz plik(i)..."; +"Attach Web Page..." = "Załącz stronę Web"; +"Attach File(s)..." = "Załącz plik(i)"; "to" = "Do"; "cc" = "DW"; "bcc" = "UDW"; -"Edit Draft..." = "Edytuj szkic..."; +"Edit Draft..." = "Edytuj szkic"; "Load Images" = "Załaduj obrazki"; "Return Receipt" = "Potwierdzenie"; "The sender of this message has asked to be notified when you read this message. Do you with to notify the sender?" = "Nadawca maila prosi o powiadomienie odczytania wiadomości. Czy chcesz je wysłać?"; "Return Receipt (displayed) - %@"= "Potwierdzenie (wyświetlone) - %@"; -"This is a Return Receipt for the mail that you sent to %@.\n\nNote: This Return Receipt only acknowledges that the message was displayed on the recipient's computer. There is no guarantee that the recipient has read or understood the message contents." = "To jest potwierdzenie dla e-maila, który był wysłany do %@.⏎ ⏎Uwaga: To jest potwierdzenie otwarcia maila. Nie gwarantuje ono, że odbiorca przeczytał wiadomość i ją zrozumiał."; +"This is a Return Receipt for the mail that you sent to %@.\n\nNote: This Return Receipt only acknowledges that the message was displayed on the recipient's computer. There is no guarantee that the recipient has read or understood the message contents." = "To jest potwierdzenie dla e-maila, który był wysłany do %@.\n\nUwaga: To jest potwierdzenie otwarcia maila. Nie gwarantuje ono, że odbiorca przeczytał wiadomość i ją zrozumiał."; "Priority" = "Priorytet"; "highest" = "Najwyższy"; @@ -124,7 +124,7 @@ "This mail is being sent from an unsecure network!" = "Ta wiadomość jest wysyłana z niezabezpieczonej sieci!"; -"Address Book:" = "Książka adresowa"; +"Address Book:" = "Książka adresowa:"; "Search For:" = "Szukaj:"; /* Popup "show" */ @@ -177,9 +177,9 @@ "MoveTo" = "Przenieś …"; /* Address Popup menu */ -"Add to Address Book..." = "Dodaj do książki adresowej..."; +"Add to Address Book..." = "Dodaj do książki adresowej"; "Compose Mail To" = "Utwórz wiadomość do"; -"Create Filter From Message..." = "Utwórz filtr z wiadomości..."; +"Create Filter From Message..." = "Utwórz filtr z wiadomości"; /* Image Popup menu */ "Save Image" = "Zapisz obrazek"; @@ -188,14 +188,14 @@ /* Mailbox popup menus */ "Open in New Mail Window" = "Otwórz w nowym oknie"; "Copy Folder Location" = "Kopiuj położenie foldera"; -"Subscribe..." = "Subskrybuj..."; -"Mark Folder Read..." = "Oznacz folder jako przeczytany..."; -"New Folder..." = "Nowy folder..."; +"Subscribe..." = "Subskrybuj"; +"Mark Folder Read..." = "Oznacz folder jako przeczytany"; +"New Folder..." = "Nowy folder"; "Compact This Folder" = "Kompaktuj ten folder"; -"Search Messages..." = "Szukaj wiadomości..."; -"Sharing..." = "Udostępnianie..."; -"New Subfolder..." = "Nowy podfolder..."; -"Rename Folder..." = "Zmień nazwę foldera..."; +"Search Messages..." = "Szukaj wiadomości"; +"Sharing..." = "Udostępnianie"; +"New Subfolder..." = "Nowy podfolder"; +"Rename Folder..." = "Zmień nazwę foldera"; "Delete Folder" = "Usuń folder"; "Use This Folder For" = "Użyj tego foldera do"; "Get Messages for Account" = "Pobierz wiadomości z konta"; @@ -211,12 +211,12 @@ "Open Message In New Window" = "Otwórz wiadomość w nowym oknie"; "Reply to Sender Only" = "Odpowiedz tylko nadawcy"; "Reply to All" = "Odpowiedz wszystkim"; -"Edit As New..." = "Edytuj jako nową..."; +"Edit As New..." = "Edytuj jako nową"; "Move To" = "Przenieś do"; "Copy To" = "Kopiuj do"; "Label" = "Etykieta"; "Mark" = "Oznacz"; -"Save As..." = "Zapisz jako..."; +"Save As..." = "Zapisz jako"; "Print Preview" = "Podgląd wydruku"; "View Message Source" = "Pokaż źródło wiadomości"; "Print..." = "Drukuj..."; @@ -236,7 +236,7 @@ /* Mark popup menu */ "As Read" = "Jako przeczytane"; "Thread As Read" = "Wątek jako przeczytany"; -"As Read By Date..." = "jako przeczytane do daty..."; +"As Read By Date..." = "jako przeczytane do daty"; "All Read" = "wszystkie przeczytane"; "Flag" = "Flaga"; "As Junk" = "Jako śmieć"; @@ -246,7 +246,7 @@ /* Folder operations */ "Name :" = "Nazwa :"; "Enter the new name of your folder :" - = "Wprowadź nową nazwę twojego foldera :"; + = "Wprowadź nową nazwę twojego folderu:"; "Do you really want to move this folder into the trash ?" = "Czy na pewno chcesz przenieść ten folder do kosza ?"; "Operation failed" = "Operacja nie powiodła się"; @@ -261,22 +261,22 @@ "The folder with name \"%{0}\" could not be created." -= "Nie można było utworzyć foldera o nazwie \"%{0}\"."; += "Nie można było utworzyć folderu o nazwie \"%{0}\"."; "This folder could not be renamed to \"%{0}\"." -= "Nie można było zmienić nazwy foldera na \"%{0}\"."; += "Nie można było zmienić nazwy folderau{0}\"."; "The folder could not be deleted." -= "Nie można było usunąć foldera."; += "Nie można było usunąć folderu."; "The trash could not be emptied." = "Nie można było opróżnić kosza."; "The folder functionality could not be changed." -= "Nie można było zmienić funkcjonalności foldera."; += "Nie można było zmienić funkcjonalności folderu."; "You need to choose a non-virtual folder!" = "Musisz wybrać folder, który nie jest wirtualny!"; "Moving a message into its own folder is impossible!" -= "Przenoszenie wiadomości do jej obecnego foldera nie jest możliwe!"; += "Przenoszenie wiadomości do jej obecnego folderu nie jest możliwe!"; "Copying a message into its own folder is impossible!" -= "Kopiowanie wiadomości do jej obecnego foldera nie jest możliwe!"; += "Kopiowanie wiadomości do jej obecnego folderu nie jest możliwe!"; /* Message operations */ "The messages could not be moved to the trash folder. Would you like to delete them immediately?" diff --git a/UI/MailerUI/Slovak.lproj/Localizable.strings b/UI/MailerUI/Slovak.lproj/Localizable.strings new file mode 100644 index 000000000..e5c19b951 --- /dev/null +++ b/UI/MailerUI/Slovak.lproj/Localizable.strings @@ -0,0 +1,293 @@ +/* this file is in UTF-8 format! */ + +/* Icon's label */ +"Create" = "Vytvoriť"; +"Empty Trash" = "Vyprázdniť kôš"; +"Delete" = "Zmazať"; +"Expunge" = "Vyškrtnúť"; +"Forward" = "Preposlať"; +"Get Mail" = "Prijať"; +"Junk" = "Spam"; +"Reply" = "Odpovedať"; +"Reply All" = "Odpovedať všetkým"; +"Print" = "Tlačiť"; +"Stop" = "Stop"; +"Write" = "Písať"; + +"Send" = "Poslať"; +"Contacts" = "Kontakty"; +"Attach" = "Príloha"; +"Save" = "Uložiť"; +"Options" = "Voľby"; +"Close" = "Zavrieť"; +"Size" = "Veľkosť"; + +/* Tooltips */ + +"Send this message now" = "Poslať správu"; +"Select a recipient from an Address Book" = "Vyberte príjemcu z adresára"; +"Include an attachment" = "Zahrnúť prílohu"; +"Save this message" = "Uložiť správu"; +"Get new messages" = "Prijať nové správy"; +"Create a new message" = "Vytvoriť novú správu"; +"Go to address book" = "Prejsť do adresára"; +"Reply to the message" = "Odpoveď na správu"; +"Reply to sender and all recipients" = "Odpovedať odosielateľovi a všetkým príjemcom"; +"Forward selected message" = "Prepošli označené správy"; +"Delete selected message or folder" = "Odstráň označenú správu alebo priečinok"; +"Mark the selected messages as junk" = "Označ vybrané správy ako spam"; +"Print this message" = "Vytlačiť správu"; +"Stop the current transfer" = "Zastav prebiehajúci presun"; +"Attachment" = "Príloha"; +"Unread" = "Neprečítané"; +"Flagged" = "Označené zástavkou"; + +/* Main Frame */ + +"Home" = "Domov"; +"Calendar" = "Kalendár"; +"Addressbook" = "Kontakty"; +"Mail" = "Pošta"; +"Right Administration" = "Administrácia práv"; + +"Help" = "Pomoc"; + +/* Mail account main windows */ + +"Welcome to the SOGo Mailer. Use the folder tree on the left to browse your mail accounts!" = "Vitajte v SOGo Mailer. Použite zoznam zložiek vľavo na prehliadanie Vášho emailového účtu!"; + +"Read messages" = "Čítať správu"; +"Write a new message" = "Nápísať správu"; + +"Share: " = "Zdielať"; +"Account: " = "Účet"; +"Shared Account: " = "Zdielať účet"; + +/* acls */ +"Access rights to" = "Pristupové práva k"; +"For user" = "Pre užívateľa"; + +"Any Authenticated User" = "Akýkoľvek overení užívateľ"; + +"List and see this folder" = "Zoraď a zobraz tento priečinok"; +"Read mails from this folder" = "Čitať maile z tejto zložky"; +"Mark mails read and unread" = "Označ maily ako prečítané a neprečítané"; +"Modify the flags of the mails in this folder" = "Uprav zástavky mailov v tejto zložke"; +"Insert, copy and move mails into this folder" = "Vlož, kopíruj a presuň maile do tejto zložky"; +"Post mails" = "Zverejni maily"; +"Add subfolders to this folder" = "Pridať podadresáre pre tento adresár"; +"Remove this folder" = "Zmazať adresár"; +"Erase mails from this folder" = "Zmazať správy z adresára"; +"Expunge this folder" = "Vyprázdniť adresár"; +"Archive This Folder" = "Archivovať adresár"; +"Modify the acl of this folder" = "Uprav ACL tejto zložky"; + +"Saved Messages.zip" = "Uložené Správy.zip"; + +"Update" = "Aktualizuj"; +"Cancel" = "Zrušiť"; + +/* Mail edition */ + +"From" = "Od"; +"Subject" = "Predmet"; +"To" = "Pre"; +"Cc" = "Kópia"; +"Bcc" = "Skrytá kópia"; +"Reply-To" = "Odpovedz odosielateľovi"; +"Add address" = "Pridať adresu"; + +"Attachments:" = "Prílohy"; +"Open" = "Otvoriť"; +"Select All" = "Vyber všetko"; +"Attach Web Page..." = "Prilož WWW stránku..."; +"Attach File(s)..." = "Prilož súbor(y)..."; + +"to" = "Pre"; +"cc" = "Kópia"; +"bcc" = "Skrytá kópia"; + +"Edit Draft..." = "Uprav rozpísané..."; +"Load Images" = "Nahraj obrázky"; + +"Return Receipt" = "Notifikácia o doručení"; +"The sender of this message has asked to be notified when you read this message. Do you with to notify the sender?" = "Odosielateľ tejto správy by chcel byť informovaný o jej prečítaní. Checete informovať odosielateľa?"; +"Return Receipt (displayed) - %@"= "Notifikácia o doručení (zobrazená) - %@"; +"This is a Return Receipt for the mail that you sent to %@.\n\nNote: This Return Receipt only acknowledges that the message was displayed on the recipient's computer. There is no guarantee that the recipient has read or understood the message contents." = "Toto je potvrdenie o prečítaní ku správe, ktorú ste poslali pre %@.⏎ ⏎ Poznámka: Potvrdenie o prijatí znamená iba to, že sa správa zobrazila na počítači adresáta. Nie je ale zaručené, že adresát správu čítal a porozumel jej obsahu."; + +"Priority" = "Priorita"; +"highest" = "Najvyššia"; +"high" = "Vysoká"; +"normal" = "Normálna"; +"low" = "Nízka"; +"lowest" = "Najnižšia"; + +"This mail is being sent from an unsecure network!" = "Tento email bude odoslaný z nezabezpečenej siete!"; + +"Address Book:" = "Adresár:"; +"Search For:" = "Hľadať v:"; + +/* Popup "show" */ + +"all" = "všetko"; +"read" = "čítať"; +"unread" = "prečítané"; +"deleted" = "zmazané"; +"flagged" = "označené"; + +/* MailListView */ + +"Sender" = "Odosielateľ"; +"Subject or Sender" = "Predmet alebo Odosielateľ"; +"To or Cc" = "Pre alebo Kópia"; +"Entire Message" = "Celá správa"; + +"Date" = "Dátum"; +"View" = "Pozrieť"; +"All" = "Všetko"; +"No message" = "Žiadna správa"; +"messages" = "správa"; + +"first" = "Prvá"; +"previous" = "Predošlá"; +"next" = "Ďalšia"; +"last" = "Posledná"; + +"msgnumber_to" = "pre"; +"msgnumber_of" = "o"; + +"Mark Unread" = "Označ ako neprečítané"; +"Mark Read" = "Označ ako prečítané"; + +"Untitled" = "Bez mena"; + +/* Tree */ + +"SentFolderName" = "Poslať"; +"TrashFolderName" = "Kôš"; +"InboxFolderName" = "Prijaté"; +"DraftsFolderName" = "Koncepty"; +"SieveFolderName" = "Filtre"; +"OtherUsersFolderName" = "Ostatní užívatelia"; +"SharedFoldersName" = "Zdielané adresáre"; +"Folders" = "Adresáre"; /* title line */ + +/* MailMoveToPopUp */ + +"MoveTo" = "Presuň …"; + +/* Address Popup menu */ +"Add to Address Book..." = "Pridaj do adresára..."; +"Compose Mail To" = "Napísať mail pre"; +"Create Filter From Message..." = "Vytvoriť filter zo správy..."; + +/* Image Popup menu */ +"Save Image" = "Uložiť obrázok"; +"Save Attachment" = "Uložiť prílohu"; + +/* Mailbox popup menus */ +"Open in New Mail Window" = "Otvoriť v novom okne"; +"Copy Folder Location" = "Kopírovať adresu priečinka"; +"Subscribe..." = "Potvrď odber..."; +"Mark Folder Read..." = "Označ priečinok ako prečítaný..."; +"New Folder..." = "Nový adresár"; +"Compact This Folder" = "Vykonaj údržbu tohoto priečinku"; +"Search Messages..." = "Hľadať správy"; +"Sharing..." = "Zdieľanie"; +"New Subfolder..." = "Nový podadresár"; +"Rename Folder..." = "Premenovať adresár"; +"Delete Folder" = "Zmazať adresár"; +"Use This Folder For" = "Použitie tejto zložky"; +"Get Messages for Account" = "Prijať správy na účet"; +"Properties..." = "Vlastnosti"; +"Delegation..." = "Delegácia ..."; + +/* Use This Folder menu */ +"Sent Messages" = "Poslať Správu"; +"Drafts" = "Koncepty"; +"Deleted Messages" = "Zmazať správy"; + +/* Message list popup menu */ +"Open Message In New Window" = "Otvoriť správu v novom okne"; +"Reply to Sender Only" = "Odpovedať len odosielateľovi"; +"Reply to All" = "Odpovedať všetkým"; +"Edit As New..." = "Editovať nové..."; +"Move To" = "Presunúť do"; +"Copy To" = "Kopírovať do"; +"Label" = "Štítok"; +"Mark" = "Označiť"; +"Save As..." = "Uložiť ako..."; +"Print Preview" = "Náhľad pred tlačou"; +"View Message Source" = "Ukázať zdroj správy"; +"Print..." = "Tlačiť"; +"Delete Message" = "Zmazať správu"; +"Delete Selected Messages" = "Zmazať vybrané správy"; + +"This Folder" = "Adresár"; + +/* Label popup menu */ +"None" = "Žiaden"; +"Important" = "Dôležité"; +"Work" = "Pracovné"; +"Personal" = "Osobné"; +"To Do" = "Treba urobiť"; +"Later" = "Neskôr"; + +/* Mark popup menu */ +"As Read" = "Prečítané"; +"Thread As Read" = "Konverzáciu ako prečítanú"; +"As Read By Date..." = "Prečítané dátumom..."; +"All Read" = "Prečítať všetko"; +"Flag" = "Označ zástavkou"; +"As Junk" = "Ako SPAM"; +"As Not Junk" = "Ako nie SPAM"; +"Run Junk Mail Controls" = "Spusti kontrolu SPAMu"; + +/* Folder operations */ +"Name :" = "Meno:"; +"Enter the new name of your folder :" + = "Zadajte nové meno adresára:"; +"Do you really want to move this folder into the trash ?" + = "Skutočne chcete presunúť tento priečinok do koša?"; +"Operation failed" = "Operácia zlyhala"; + +"Quota" = "Kvóta:"; +"quotasFormat" = "%{0}% použité z %{1} MB"; + +"Please select a message." = "Prsím vyberte správu"; +"Please select a message to print." = "Prosím vyberte správu ktorú chcete tlačiť."; +"Please select only one message to print." = "Prosím vyberte iba jednu správu ktorú chcete tlačiť."; +"The message you have selected doesn't exist anymore." = "Správa ktorú ste vybrali už neexistuje."; + + +"The folder with name \"%{0}\" could not be created." += "Priečinok s menom \"%{0}\" nemôže byť vytvorení."; +"This folder could not be renamed to \"%{0}\"." += "Tento priečinok sa nedá premenovať na \"%{0}\"."; +"The folder could not be deleted." += "Priečinok sa nedá odstrániť."; +"The trash could not be emptied." += "Kôš sa nedá vyprázniť."; +"The folder functionality could not be changed." += "Funkcia priečinka sa nedá zmeniť."; + +"You need to choose a non-virtual folder!" = "Musíte zvoliť priečinok ktorý nie je virtuálny!"; + +"Moving a message into its own folder is impossible!" += "Presunúť správu do jej vlastného priečinka sa nedá!"; +"Copying a message into its own folder is impossible!" += "Kopírovať správu do jej vlastného priečinka sa nedá!"; + +/* Message operations */ +"The messages could not be moved to the trash folder. Would you like to delete them immediately?" += "Správy nemôžu byť presunuté do koša. Chcete ich vymazať okamžite?"; + +/* Message editing */ +"error_missingsubject" = "Správa nemá žiadny predmet. Skutočne ju checete odoslať?"; +"error_missingrecipients" = "Prosím zvoľte aspoň jedného príjemcu."; +"Send Anyway" = "Poslať napriek tomu"; + +/* Message sending */ +"cannot send message: (smtp) all recipients discarded" = "Správa sa nedá odoslať: žiadny príjemca nie je platný."; +"cannot send message (smtp) - recipients discarded:" = "Správa sa nedá odoslať: Nasledujúci príjemcovia nemajú platnú adresu:"; +"cannot send message: (smtp) error when connecting" = "Správa sa nedá odoslať: chyba pri pripájaní na SMTP server."; diff --git a/UI/MailerUI/UIxMailAccountActions.m b/UI/MailerUI/UIxMailAccountActions.m index 2f9911ee8..5f1ab0c2a 100644 --- a/UI/MailerUI/UIxMailAccountActions.m +++ b/UI/MailerUI/UIxMailAccountActions.m @@ -209,11 +209,11 @@ - (WOResponse *) composeAction { - SOGoDraftsFolder *drafts; + NSString *urlBase, *url, *value, *signature, *nl; SOGoDraftObject *newDraftMessage; - NSString *urlBase, *url, *value, *signature; - id mailTo; NSMutableDictionary *headers; + SOGoDraftsFolder *drafts; + id mailTo; BOOL save; drafts = [[self clientObject] draftsFolderInContext: context]; @@ -246,8 +246,10 @@ signature = [[self clientObject] signature]; if ([signature length]) { + nl = ([[[[context activeUser] userDefaults] mailComposeMessageType] isEqualToString: @"html"] ? @"
" : @"\n"); + [newDraftMessage - setText: [NSString stringWithFormat: @"\n\n-- \n%@", signature]]; + setText: [NSString stringWithFormat: @"%@%@-- %@%@", nl, nl, nl, signature]]; save = YES; } if (save) diff --git a/UI/MainUI/BrazilianPortuguese.lproj/Localizable.strings b/UI/MainUI/BrazilianPortuguese.lproj/Localizable.strings index 7f4bedbf9..d68c86251 100644 --- a/UI/MainUI/BrazilianPortuguese.lproj/Localizable.strings +++ b/UI/MainUI/BrazilianPortuguese.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Espanhol (Espanha)"; "SpanishArgentina" = "Espanhol (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/Catalan.lproj/Localizable.strings b/UI/MainUI/Catalan.lproj/Localizable.strings index 826ecba5f..ab8d287bb 100644 --- a/UI/MainUI/Catalan.lproj/Localizable.strings +++ b/UI/MainUI/Catalan.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/Czech.lproj/Localizable.strings b/UI/MainUI/Czech.lproj/Localizable.strings index 38a0e0cd6..29fe7b3a8 100644 --- a/UI/MainUI/Czech.lproj/Localizable.strings +++ b/UI/MainUI/Czech.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/Danish.lproj/Localizable.strings b/UI/MainUI/Danish.lproj/Localizable.strings index fc9aef0e8..802c9fd12 100644 --- a/UI/MainUI/Danish.lproj/Localizable.strings +++ b/UI/MainUI/Danish.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Spansk (Spanien)"; "SpanishArgentina" = "Spansk (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/Dutch.lproj/Localizable.strings b/UI/MainUI/Dutch.lproj/Localizable.strings index 4092a5751..f3dba7091 100644 --- a/UI/MainUI/Dutch.lproj/Localizable.strings +++ b/UI/MainUI/Dutch.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/English.lproj/Localizable.strings b/UI/MainUI/English.lproj/Localizable.strings index cf33ad670..eaa726402 100644 --- a/UI/MainUI/English.lproj/Localizable.strings +++ b/UI/MainUI/English.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/French.lproj/Localizable.strings b/UI/MainUI/French.lproj/Localizable.strings index a1c17d829..ad7854e21 100644 --- a/UI/MainUI/French.lproj/Localizable.strings +++ b/UI/MainUI/French.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/GNUmakefile b/UI/MainUI/GNUmakefile index bf49f1135..a0e53e212 100644 --- a/UI/MainUI/GNUmakefile +++ b/UI/MainUI/GNUmakefile @@ -6,7 +6,7 @@ BUNDLE_NAME = MainUI MainUI_PRINCIPAL_CLASS = MainUIProduct -MainUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian SpanishSpain SpanishArgentina Swedish Ukrainian Welsh +MainUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh MainUI_OBJC_FILES += \ MainUIProduct.m \ @@ -15,6 +15,10 @@ MainUI_OBJC_FILES += \ SOGoBrowsersPanel.m \ UIxLoading.m \ +ifeq ($(saml2_config), yes) + MainUI_OBJC_FILES += SOGoSAML2Actions.m +endif + MainUI_RESOURCE_FILES += \ product.plist \ SOGoProfile.sql \ diff --git a/UI/MainUI/GNUmakefile.preamble b/UI/MainUI/GNUmakefile.preamble index 1f7acaf9c..ec6ba0c4f 100644 --- a/UI/MainUI/GNUmakefile.preamble +++ b/UI/MainUI/GNUmakefile.preamble @@ -4,3 +4,7 @@ ADDITIONAL_CPPFLAGS += \ -DSOGO_MAJOR_VERSION=$(MAJOR_VERSION) \ -DSOGO_MINOR_VERSION=$(MINOR_VERSION) \ -DSOGO_SUBMINOR_VERSION=$(SUBMINOR_VERSION) + +ifeq ($(HAS_LIBRARY_lasso), yes) +ADDITIONAL_CPPFLAGS += $(LASSO_CFLAGS) +endif diff --git a/UI/MainUI/German.lproj/Localizable.strings b/UI/MainUI/German.lproj/Localizable.strings index a5796dd8c..0ce176bdf 100644 --- a/UI/MainUI/German.lproj/Localizable.strings +++ b/UI/MainUI/German.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentinien)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/Hungarian.lproj/Localizable.strings b/UI/MainUI/Hungarian.lproj/Localizable.strings index 1b2e677f0..39315f528 100644 --- a/UI/MainUI/Hungarian.lproj/Localizable.strings +++ b/UI/MainUI/Hungarian.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/Icelandic.lproj/Localizable.strings b/UI/MainUI/Icelandic.lproj/Localizable.strings index bb1cdde9a..f6ee8bf02 100644 --- a/UI/MainUI/Icelandic.lproj/Localizable.strings +++ b/UI/MainUI/Icelandic.lproj/Localizable.strings @@ -33,6 +33,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/Italian.lproj/Localizable.strings b/UI/MainUI/Italian.lproj/Localizable.strings index 46c0a3036..29573ef5a 100644 --- a/UI/MainUI/Italian.lproj/Localizable.strings +++ b/UI/MainUI/Italian.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/NorwegianBokmal.lproj/Localizable.strings b/UI/MainUI/NorwegianBokmal.lproj/Localizable.strings index a4ccbbd14..ec425f5de 100644 --- a/UI/MainUI/NorwegianBokmal.lproj/Localizable.strings +++ b/UI/MainUI/NorwegianBokmal.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/NorwegianNynorsk.lproj/Localizable.strings b/UI/MainUI/NorwegianNynorsk.lproj/Localizable.strings index 8fc406192..643e30acb 100644 --- a/UI/MainUI/NorwegianNynorsk.lproj/Localizable.strings +++ b/UI/MainUI/NorwegianNynorsk.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/Polish.lproj/Localizable.strings b/UI/MainUI/Polish.lproj/Localizable.strings index 4436b7018..d0487e3c5 100644 --- a/UI/MainUI/Polish.lproj/Localizable.strings +++ b/UI/MainUI/Polish.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/Russian.lproj/Localizable.strings b/UI/MainUI/Russian.lproj/Localizable.strings index fb545692f..22bf1cf7c 100644 --- a/UI/MainUI/Russian.lproj/Localizable.strings +++ b/UI/MainUI/Russian.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/SOGoRootPage.m b/UI/MainUI/SOGoRootPage.m index 1d2ed529d..52508de50 100644 --- a/UI/MainUI/SOGoRootPage.m +++ b/UI/MainUI/SOGoRootPage.m @@ -47,6 +47,9 @@ #import #import #import +#if defined(SAML2_CONFIG) +#import +#endif /* SAML2_ENABLE */ #import #import #import @@ -100,46 +103,6 @@ return ([[self cookieUsername] length]); } -- (WOCookie *) _cookieWithUsername: (NSString *) username - andPassword: (NSString *) password - forAuthenticator: (SOGoWebAuthenticator *) auth -{ - WOCookie *authCookie; - NSString *cookieValue, *cookieString, *appName, *sessionKey, *userKey, *securedPassword; - - // - // We create a new cookie - thus we create a new session - // associated to the user. For security, we generate: - // - // A- a session key - // B- a user key - // - // In memcached, the session key will be associated to the user's password - // which will be XOR'ed with the user key. - // - sessionKey = [SOGoSession generateKeyForLength: 16]; - userKey = [SOGoSession generateKeyForLength: 64]; - - NSString *value = [NSString stringWithFormat: @"%@:%@", username, password]; - securedPassword = [SOGoSession securedValue: value usingKey: userKey]; - - - [SOGoSession setValue: securedPassword forSessionKey: sessionKey]; - - //cookieString = [NSString stringWithFormat: @"%@:%@", - // username, password]; - cookieString = [NSString stringWithFormat: @"%@:%@", - userKey, sessionKey]; - cookieValue = [NSString stringWithFormat: @"basic %@", - [cookieString stringByEncodingBase64]]; - authCookie = [WOCookie cookieWithName: [auth cookieNameInContext: context] - value: cookieValue]; - appName = [[context request] applicationName]; - [authCookie setPath: [NSString stringWithFormat: @"/%@/", appName]]; - - return authCookie; -} - - (WOCookie *) _cookieWithUsername: (NSString *) username { WOCookie *loginCookie; @@ -172,7 +135,8 @@ return loginCookie; } -- (WOCookie *) _casLocationCookie: (BOOL) cookieReset +- (WOCookie *) _authLocationCookie: (BOOL) cookieReset + withName: (NSString *) cookieName { WOCookie *locationCookie; NSString *appName; @@ -180,7 +144,7 @@ NSCalendarDate *date; rq = [context request]; - locationCookie = [WOCookie cookieWithName: @"cas-location" value: [rq uri]]; + locationCookie = [WOCookie cookieWithName: cookieName value: [rq uri]]; appName = [rq applicationName]; [locationCookie setPath: [NSString stringWithFormat: @"/%@/", appName]]; if (cookieReset) @@ -261,9 +225,9 @@ username = [NSString stringWithFormat: @"%@@%@", username, domain]; } - authCookie = [self _cookieWithUsername: username - andPassword: password - forAuthenticator: auth]; + authCookie = [auth cookieWithUsername: username + andPassword: password + inContext: context]; [response addCookie: authCookie]; supportedLanguages = [[SOGoSystemDefaults sharedSystemDefaults] @@ -357,14 +321,15 @@ { auth = [[WOApplication application] authenticatorInContext: context]; - casCookie = [self _cookieWithUsername: login - andPassword: [casSession identifier] - forAuthenticator: auth]; + casCookie = [auth cookieWithUsername: login + andPassword: [casSession identifier] + inContext: context]; [casSession updateCache]; newLocation = [rq cookieValueForKey: @"cas-location"]; /* login callback, we expire the "cas-location" cookie, created below */ - casLocationCookie = [self _casLocationCookie: YES]; + casLocationCookie = [self _authLocationCookie: YES + withName: @"cas-location"]; } } } @@ -388,7 +353,8 @@ newLocation = [SOGoCASSession CASURLWithAction: @"login" andParameters: [self _casRedirectKeys]]; - casLocationCookie = [self _casLocationCookie: NO]; + casLocationCookie = [self _authLocationCookie: NO + withName: @"cas-location"]; } response = [self redirectToLocation: newLocation]; if (casCookie) @@ -399,6 +365,51 @@ return response; } +#if defined(SAML2_CONFIG) +- (id ) _saml2DefaultAction +{ + WOResponse *response; + NSString *login, *newLocation, *oldLocation; + WOCookie *saml2LocationCookie; + WORequest *rq; + + saml2LocationCookie = nil; + + newLocation = nil; + + login = [[context activeUser] login]; + if ([login isEqualToString: @"anonymous"]) + login = nil; + + if (login) + { + rq = [context request]; + newLocation = [rq cookieValueForKey: @"saml2-location"]; + if (newLocation) + saml2LocationCookie = [self _authLocationCookie: YES + withName: @"saml2-location"]; + else + { + oldLocation = [[self clientObject] baseURLInContext: context]; + newLocation = [NSString stringWithFormat: @"%@%@", + oldLocation, [login stringByEscapingURL]]; + } + } + else + { + newLocation = [SOGoSAML2Session authenticationURLInContext: context]; + saml2LocationCookie = [self _authLocationCookie: NO + withName: @"saml2-location"]; + } + + response = [self redirectToLocation: newLocation]; + if (saml2LocationCookie) + [response addCookie: saml2LocationCookie]; + + return response; +} +#endif /* SAML2_CONFIG */ + - (id ) _standardDefaultAction { NSObject *response; @@ -433,13 +444,21 @@ - (id ) defaultAction { - SOGoSystemDefaults *sd; + NSString *authenticationType; + id result; - sd = [SOGoSystemDefaults sharedSystemDefaults]; + authenticationType = [[SOGoSystemDefaults sharedSystemDefaults] + authenticationType]; + if ([authenticationType isEqualToString: @"cas"]) + result = [self _casDefaultAction]; +#if defined(SAML2_CONFIG) + else if ([authenticationType isEqualToString: @"saml2"]) + result = [self _saml2DefaultAction]; +#endif /* SAML2_CONFIG */ + else + result = [self _standardDefaultAction]; - return ([[sd authenticationType] isEqualToString: @"cas"] - ? [self _casDefaultAction] - : [self _standardDefaultAction]); + return result; } - (BOOL) isPublicInContext: (WOContext *) localContext @@ -553,9 +572,9 @@ } response = [self responseWith204]; - authCookie = [self _cookieWithUsername: username - andPassword: newPassword - forAuthenticator: auth]; + authCookie = [auth cookieWithUsername: username + andPassword: newPassword + inContext: context]; [response addCookie: authCookie]; } else diff --git a/UI/MainUI/SOGoSAML2Actions.m b/UI/MainUI/SOGoSAML2Actions.m new file mode 100644 index 000000000..d081f63d2 --- /dev/null +++ b/UI/MainUI/SOGoSAML2Actions.m @@ -0,0 +1,117 @@ +/* SOGoSAML2Actions.m - this file is part of SOGo + * + * Copyright (C) 2012 Inverse inc + * + * Author: Wolfgang Sourdeau + * + * 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 +#import +#import +#import +#import +#import + +#import +#import + +@interface SOGoSAML2Actions : WODirectAction +@end + +@implementation SOGoSAML2Actions + +- (WOResponse *) saml2MetadataAction +{ + WOResponse *response; + NSString *metadata; + + response = [context response]; + [response setHeader: @"application/xml; charset=utf-8" + forKey: @"content-type"]; + + metadata = [SOGoSAML2Session metadataInContext: context]; + [response setContentEncoding: NSUTF8StringEncoding]; + [response appendContentString: metadata]; + + return response; +} + +- (WOCookie *) _authLocationResetCookieWithName: (NSString *) cookieName +{ + WOCookie *locationCookie; + NSString *appName; + WORequest *rq; + NSCalendarDate *date; + + rq = [context request]; + locationCookie = [WOCookie cookieWithName: cookieName value: [rq uri]]; + appName = [rq applicationName]; + [locationCookie setPath: [NSString stringWithFormat: @"/%@/", appName]]; + date = [NSCalendarDate calendarDate]; + [date setTimeZone: [NSTimeZone timeZoneWithAbbreviation: @"GMT"]]; + [locationCookie setExpires: [date yesterday]]; + + return locationCookie; +} + +- (WOResponse *) saml2SignOnPOSTAction +{ + WORequest *rq; + WOResponse *response; + SoApplication *application; + SOGoSAML2Session *newSession; + WOCookie *authCookie; + NSString *login, *oldLocation, *newLocation; + SOGoWebAuthenticator *auth; + + rq = [context request]; + if ([[rq method] isEqualToString: @"POST"]) + { + newSession = [SOGoSAML2Session SAML2SessionInContext: context]; + [newSession processAuthnResponse: [rq formValueForKey: @"SAMLResponse"]]; + login = [newSession login]; + + application = [SoApplication application]; + auth = [application authenticatorInContext: context]; + authCookie = [auth cookieWithUsername: login + andPassword: [newSession identifier] + inContext: context]; + + oldLocation = [[context clientObject] baseURLInContext: context]; + newLocation = [NSString stringWithFormat: @"%@/%@", + oldLocation, [login stringByEscapingURL]]; + + response = [context response]; + [response setStatus: 302]; + [response setHeader: @"text/plain; charset=utf-8" + forKey: @"content-type"]; + [response setHeader: newLocation forKey: @"location"]; + [response addCookie: authCookie]; + } + + return response; +} + +@end diff --git a/UI/MainUI/Slovak.lproj/Locale b/UI/MainUI/Slovak.lproj/Locale new file mode 100644 index 000000000..22d21d69a --- /dev/null +++ b/UI/MainUI/Slovak.lproj/Locale @@ -0,0 +1,34 @@ +/* Slovak */ +{ + NSLanguageName = "Slovensky"; + NSFormalName = "Slovak"; + NSLocaleCode = "sk"; /* ISO 639-1 */ + NSLanguageCode = "slk"; /* ISO 639-2 */ + NSParentContext = ""; + + NSCurrencySymbol = "€"; + NSDateFormatString = "%A, %d. %B %Y"; + NSDateTimeOrdering = DMYH; + NSDecimalDigits = ("0", "1", "2", "3", "4", "5", "6", "7", "8", "9"); + NSDecimalSeparator = ","; + NSEarlierTimeDesignations = ("predchádzajúci", "posledný", "minulý", "pred"); + NSHourNameDesignations = ((0, "polnoc"), (10, "ráno"), (12, "poludnie", "obed"), (14, "poobedie"), (19, "večer")); + NSInternationalCurrencyString = EUR; /* ISO 4217 */ + NSLaterTimeDesignations = ("nasledujúci"); + NSMonthNameArray = ("Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Október", "November", "December"); + NSNextDayDesignations = ("zajtra"); + NSNextNextDayDesignations = ("pozajtra"); + NSPriorDayDesignations = ("včera"); + NSShortDateFormatString = "%d.%m.%Y"; + NSShortMonthNameArray = ("Jan", "Feb", "Mar", "Apr", "Máj", "Jún", "Júl", "Aug", "Sep", "Okt", "Nov", "Dec"); + NSShortTimeDateFormatString = "%H:%M %d.%m.%Y"; + NSShortWeekDayNameArray = ("Ne", "Po", "Ut", "St", "Št", "Pi", "So"); + NSThisDayDesignations = ("dnes"); + NSThousandsSeparator = "."; + NSTimeDateFormatString = "%A %e %B %Y %H:%M:%S %Z"; + NSTimeFormatString = "%H:%M:%S"; + NSWeekDayNameArray = ("Nedela", "Pondelok", "Utorok", "Streda", "Štvrtok", "Piatok", "Sobota"); + NSYearMonthWeekDesignations = ("rok", "mesiac", "týždeň"); + NSPositiveCurrencyFormatString = "9.999,00 €"; + NSNegativeCurrencyFormatString = "-9.999,00 €"; +} diff --git a/UI/MainUI/Slovak.lproj/Localizable.strings b/UI/MainUI/Slovak.lproj/Localizable.strings new file mode 100644 index 000000000..2f47fd423 --- /dev/null +++ b/UI/MainUI/Slovak.lproj/Localizable.strings @@ -0,0 +1,75 @@ +/* this file is in UTF-8 format! */ + +"title" = "SOGo"; + +"Username:" = "Užívateľské meno:"; +"Password:" = "Heslo:"; +"Domain:" = "Doména:"; +"Remember username" = "Zapamätať uživateľské meno"; + +"Connect" = "Pripojiť"; + +"Wrong username or password." = "Nesprávne uživateľské meno alebo heslo."; +"cookiesNotEnabled" = "Nemôžete sa prihlásiť, pretože vo svojom prehliadači máte zakázané cookies. Prosím povoľte cookies vo vašom prehliadači a skúste to znova."; + +"browserNotCompatible" = "Zistili sme že Váš prehliadač nie je našou stránkou momentálne podporovaný. Odporúčame používať Firefox. Kliknite na odkaz nižšie a stiahnite si aktuálnu verziu tohoto prehliadača"; +"alternativeBrowsers" = "Prípadne môžete tiež použiť nasledujúce kompatibilné prehliadače"; +"alternativeBrowserSafari" = "Alternatívne je možné použiť aj Safari."; +"Download" = "Stiahnuť"; + +"Language:" = "Jazyk:"; +"choose" = "Výber ..."; +"Catalan" = "Katalánsky"; +"Czech" = "Česky"; +"Danish" = "Dansk (Danmark)"; +"Dutch" = "Holandsky"; +"English" = "Anglicky"; +"French" = "Francúzsky"; +"German" = "Nemecky"; +"Hungarian" = "Maďarsky"; +"Icelandic" = "Islandčina"; +"Italian" = "Taliansky"; +"NorwegianBokmal" = "Nórčina bokmål"; +"NorwegianNynorsk" = "Nórčina nynorsk"; +"Polish" = "Poľština"; +"BrazilianPortuguese" = "Portugalská brazílština"; +"Russian" = "Ruština"; +"SpanishSpain" = "Španielčina (Španielsko)"; +"SpanishArgentina" = "Španielčina (Argentína)"; +"Swedish" = "Švédčina"; +"Ukrainian" = "Ukrajinčina"; +"Welsh" = "Galčina"; + +"About" = "O"; +"AboutBox" = "Vyvinuté Inverse, SOGo je plne vybavený groupware server s dôrazom na škálovateľnosť a jednoduchosť.

\nSOGo ponúka bohaté Web rozhranie na báze AJAX-u a natívne podporuje mnoho klientov použitím štandardov ako sú CalDAV a CardDAV.

\nSOGo je distribuované pod licenciou GNU GPL verzie 2 alebo novšej a niektoré časti pod licenciou GNU LGPL verzie 2. Toto je voľne šíritelný softvér: môžete ho meniť a šíriť ďalej. Neexistuje ŽIADNA ZÁRUKA, v rozsahu povolenom zákonom.

\nPozrite si túto stránku pre rôzne možnosti podpory."; + +"Your account was locked due to too many failed attempts." = "Váš účet bol uzamknutý kvôli príliš mnohých neúspešným pokusom."; +"Your account was locked due to an expired password." = "Váš účet bol uzamknutý kvôli neplatnému heslu."; +"Login failed due to unhandled error case: " = "Prihlásenie zlyhalo kvôli neošetrenej prípade chyby:"; +"Change your Password" = "Zmeniť heslo"; +"The password was changed successfully." = "Vaše heslo bolo zmené."; +"Your password has expired, please enter a new one below:" = "Vaše heslo vypršalo, zadajte prosím nové nižšie:"; +"Password must not be empty." = "Heslo nesmie byť prázdne."; +"The passwords do not match. Please try again." = "Heslá sa nezhodujú. Skúste to znova."; +"Password Grace Period" = "Doba platnosti hesla"; +"You have %{0} logins remaining before your account is locked. Please change your password in the preference dialog." = "Ostáva Vám % {0} prihlásení do uzamknutia Vášho účtu. Zmeňte prosím Vaše heslo."; +"Password about to expire" = "Heslo čoskoro vyprší"; +"Your password is going to expire in %{0} %{1}." = "Vaše heslo vyprší za % {0} {1}%."; +"days" = "dni"; +"hours" = "hodiny"; +"minutes" = "minúty"; +"seconds" = "sekundy"; +"Password change failed" = "Zmena hesla zlyhala"; +"Password change failed - Permission denied" = "Zmena hesla zlyhala - oprávnenie bolo odopreté"; +"Password change failed - Insufficient password quality" = "Zmena hesla zlyhala - nedostatočná kvalita hesla"; +"Password change failed - Password is too short" = "Zmena hesla zlyhala - heslo je príliš krátke"; +"Password change failed - Password is too young" = "Zmena hesla nebola úspešná - heslo sa nesmie opakovať"; +"Password change failed - Password is in history" = "Zmena hesla zlyhala - heslo je v histórii"; +"Unhandled policy error: %{0}" = "Nespracovaná politika. Chyba:% {0}"; +"Unhandled error response" = "Nespracované chyby na odpoveď"; +"Password change is not supported." = "Zmena hesla nieje povolená."; +"Unhandled HTTP error code: %{0}" = "Nespracované HTTP. Kód chyby:% {0}"; +"New password:" = "Nové heslo:"; +"Confirmation:" = "Potvrdiť:"; +"Cancel" = "Zrušiť"; +"Please wait..." = "Prosím čakajte ..."; diff --git a/UI/MainUI/SpanishArgentina.lproj/Localizable.strings b/UI/MainUI/SpanishArgentina.lproj/Localizable.strings index 7c54ecf8c..44ad21bd9 100644 --- a/UI/MainUI/SpanishArgentina.lproj/Localizable.strings +++ b/UI/MainUI/SpanishArgentina.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/SpanishSpain.lproj/Localizable.strings b/UI/MainUI/SpanishSpain.lproj/Localizable.strings index d1392a09f..8e5d932b6 100644 --- a/UI/MainUI/SpanishSpain.lproj/Localizable.strings +++ b/UI/MainUI/SpanishSpain.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/Swedish.lproj/Localizable.strings b/UI/MainUI/Swedish.lproj/Localizable.strings index 531e7a124..cd50cf2b8 100644 --- a/UI/MainUI/Swedish.lproj/Localizable.strings +++ b/UI/MainUI/Swedish.lproj/Localizable.strings @@ -33,6 +33,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/Ukrainian.lproj/Localizable.strings b/UI/MainUI/Ukrainian.lproj/Localizable.strings index 57826d45e..4f00d0a01 100644 --- a/UI/MainUI/Ukrainian.lproj/Localizable.strings +++ b/UI/MainUI/Ukrainian.lproj/Localizable.strings @@ -34,6 +34,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/Welsh.lproj/Localizable.strings b/UI/MainUI/Welsh.lproj/Localizable.strings index 01cc78989..14900700f 100644 --- a/UI/MainUI/Welsh.lproj/Localizable.strings +++ b/UI/MainUI/Welsh.lproj/Localizable.strings @@ -33,6 +33,7 @@ "Polish" = "Polski"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/MainUI/product.plist b/UI/MainUI/product.plist index 212429a0c..399eaad05 100644 --- a/UI/MainUI/product.plist +++ b/UI/MainUI/product.plist @@ -119,21 +119,41 @@ pageName = "SOGoRootPage"; actionName = "casProxy"; }; - /* crash = { - protectedBy = ""; - pageName = "SOGoRootPage"; - actionName = "crash"; - }; - exception = { - protectedBy = ""; - pageName = "SOGoRootPage"; - actionName = "exception"; - }; - raisedException = { - protectedBy = ""; - pageName = "SOGoRootPage"; - actionName = "raisedException"; - }; */ + saml2-metadata = { + protectedBy = ""; + actionClass = "SOGoSAML2Actions"; + actionName = "saml2Metadata"; + }; + saml2-signon-post = { + protectedBy = ""; + actionClass = "SOGoSAML2Actions"; + actionName = "saml2SignOnPOST"; + }; + /* saml2-signon-redirect = { + protectedBy = ""; + actionClass = "SOGoSAML2Actions"; + actionName = "saml2SignOnRedirect"; + }; + saml2-signon-soap = { + protectedBy = ""; + actionClass = "SOGoSAML2Actions"; + actionName = "saml2SignOnSOAP"; + }; + crash = { + protectedBy = ""; + pageName = "SOGoRootPage"; + actionName = "crash"; + }; + exception = { + protectedBy = ""; + pageName = "SOGoRootPage"; + actionName = "exception"; + }; + raisedException = { + protectedBy = ""; + pageName = "SOGoRootPage"; + actionName = "raisedException"; + }; */ connect = { protectedBy = ""; pageName = "SOGoRootPage"; diff --git a/UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings b/UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings index db9d65d02..1aae076f4 100644 --- a/UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings +++ b/UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings @@ -141,6 +141,7 @@ "messageforward_inline" = "No corpo da mensagem"; "messageforward_attached" = "Como anexo"; +"When replying to a message:" = "Ao responder a uma mensagem:"; "replyplacement_above" = "Começar minha resposta acima das citações"; "replyplacement_below" = "Começar minha resposta abaixo das citações"; "And place my signature" = "E colocar minha assinatura"; @@ -149,23 +150,32 @@ "Compose messages in" = "Escrever mensagens em"; "composemessagestype_html" = "HTML"; "composemessagestype_text" = "Texto puro"; +"Display remote inline images" = "Exibir imagens remotas"; +"displayremoteinlineimages_never" = "Nunca"; +"displayremoteinlineimages_always" = "Sempre"; /* IMAP Accounts */ "New Mail Account" = "Nova conta de e-mail"; "Server Name:" = "Nome do Servidor:"; "Port:" = "Porta:"; +"Encryption:" = "Encriptação:"; +"None" = "Nenhum"; "User Name:" = "Nome do Usuário:"; "Password:" = "Senha:"; "Full Name:" = "Nome Compelto:"; "Email:" = "E-mail:"; +"Reply To Email:" = "Responder para o Email:"; "Signature:" = "Assinatura:"; "(Click to create)" = "(Click para criar)"; "Signature" = "Assinatura"; "Please enter your signature below:" = "Por favor, digite sua assinatura abaixo:"; +"Please specify a valid sender address." = "Por favor, especifique um endereço de email válido."; +"Please specify a valid reply-to address." = "Por favor,especifique um endereço de resposta válido."; + /* Additional Parameters */ "Additional Parameters" = "Parâmetros Adicionais"; @@ -207,6 +217,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Eslovaco"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; @@ -238,6 +249,7 @@ "match any of the following rules:" = "corresponde a nenhuma das seguintes regras:"; "match all messages" = "corresponder a todas as mensagens"; "Perform these actions:" = "Realizar essas ações:"; +"Untitled Filter" = "Filtro sem título"; "Subject" = "Assunto"; "From" = "De"; @@ -278,6 +290,7 @@ "Label 4" = "Rótulo 4"; "Label 5" = "Rótulo 5"; +"The password was changed successfully." = "Senha alterada com sucesso."; "Password must not be empty." = "Le mot de passe ne doit pas être vide."; "The passwords do not match. Please try again." = "Les mots de passe ne sont pas identiques. Essayez de nouveau."; "Password change failed" = "Échec au changement"; diff --git a/UI/PreferencesUI/Catalan.lproj/Localizable.strings b/UI/PreferencesUI/Catalan.lproj/Localizable.strings index 140fc1e83..eb4d65e13 100644 --- a/UI/PreferencesUI/Catalan.lproj/Localizable.strings +++ b/UI/PreferencesUI/Catalan.lproj/Localizable.strings @@ -211,6 +211,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/Czech.lproj/Localizable.strings b/UI/PreferencesUI/Czech.lproj/Localizable.strings index eb6226ac5..8b78463a4 100644 --- a/UI/PreferencesUI/Czech.lproj/Localizable.strings +++ b/UI/PreferencesUI/Czech.lproj/Localizable.strings @@ -208,6 +208,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Portugues brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/Danish.lproj/Localizable.strings b/UI/PreferencesUI/Danish.lproj/Localizable.strings index 7cfb550ff..aabc91239 100644 --- a/UI/PreferencesUI/Danish.lproj/Localizable.strings +++ b/UI/PreferencesUI/Danish.lproj/Localizable.strings @@ -198,6 +198,7 @@ "NorwegianNynorsk" = "Nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Spansk (Spanien)"; "SpanishArgentina" = "Spansk (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/Dutch.lproj/Localizable.strings b/UI/PreferencesUI/Dutch.lproj/Localizable.strings index b21360296..47efd0963 100644 --- a/UI/PreferencesUI/Dutch.lproj/Localizable.strings +++ b/UI/PreferencesUI/Dutch.lproj/Localizable.strings @@ -141,6 +141,7 @@ "messageforward_inline" = "In het bericht"; "messageforward_attached" = "Als bijlage"; +"When replying to a message:" = "Bij het beantwoorden van een bericht:"; "replyplacement_above" = "Reactie boven orginele tekst"; "replyplacement_below" = "Reactie onder orginele tekst"; "And place my signature" = "Ondertekening plaatsen"; @@ -149,12 +150,17 @@ "Compose messages in" = "Berichten opstellen in"; "composemessagestype_html" = "HTML"; "composemessagestype_text" = "Platte tekst"; +"Display remote inline images" = "Externe afbeeldingen tonen"; +"displayremoteinlineimages_never" = "Nooit"; +"displayremoteinlineimages_always" = "Altijd"; /* IMAP Accounts */ "New Mail Account" = "Nieuw mailaccount"; "Server Name:" = "Servernaam:"; "Port:" = "Poort:"; +"Encryption:" = "Encryptie:"; +"None" = "Geen"; "User Name:" = "Gebruikersnaam:"; "Password:" = "Wachtwoord:"; @@ -211,6 +217,7 @@ "NorwegianNynorsk" = "Norsk Nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentinië)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/English.lproj/Localizable.strings b/UI/PreferencesUI/English.lproj/Localizable.strings index b807a9129..55ccf5d36 100644 --- a/UI/PreferencesUI/English.lproj/Localizable.strings +++ b/UI/PreferencesUI/English.lproj/Localizable.strings @@ -141,6 +141,7 @@ "messageforward_inline" = "Inline"; "messageforward_attached" = "As Attachment"; +"When replying to a message:" = "When replying to a message:"; "replyplacement_above" = "Start my reply above the quote"; "replyplacement_below" = "Start my reply below the quote"; "And place my signature" = "And place my signature"; @@ -149,12 +150,17 @@ "Compose messages in" = "Compose messages in"; "composemessagestype_html" = "HTML"; "composemessagestype_text" = "Plain text"; +"Display remote inline images" = "Display remote inline images"; +"displayremoteinlineimages_never" = "Never"; +"displayremoteinlineimages_always" = "Always"; /* IMAP Accounts */ "New Mail Account" = "New Mail Account"; "Server Name:" = "Server Name:"; "Port:" = "Port:"; +"Encryption:" = "Encryption:"; +"None" = "None"; "User Name:" = "User Name:"; "Password:" = "Password:"; @@ -211,6 +217,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/French.lproj/Localizable.strings b/UI/PreferencesUI/French.lproj/Localizable.strings index dbc479d83..b9f57a1c4 100644 --- a/UI/PreferencesUI/French.lproj/Localizable.strings +++ b/UI/PreferencesUI/French.lproj/Localizable.strings @@ -141,6 +141,7 @@ "messageforward_inline" = "intégrés"; "messageforward_attached" = "en pièces jointes"; +"When replying to a message:" = "En répondant à un message"; "replyplacement_above" = "Placer ma réponse avant la citation"; "replyplacement_below" = "Placer ma réponse après la citation"; "And place my signature" = "Et placer ma signature"; @@ -149,12 +150,17 @@ "Compose messages in" = "Composer les messages en"; "composemessagestype_html" = "HTML"; "composemessagestype_text" = "Texte"; +"Display remote inline images" = "Afficher les images externes"; +"displayremoteinlineimages_never" = "Jamais"; +"displayremoteinlineimages_always" = "Toujours"; /* IMAP Accounts */ "New Mail Account" = "Nouveau compte"; "Server Name:" = "Serveur :"; "Port:" = "Port :"; +"Encryption:" = "Chiffrement :"; +"None" = "Aucun"; "User Name:" = "Utilisateur :"; "Password:" = "Mot de passe :"; @@ -211,6 +217,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/GNUmakefile b/UI/PreferencesUI/GNUmakefile index 596b1d213..f9e9ea230 100644 --- a/UI/PreferencesUI/GNUmakefile +++ b/UI/PreferencesUI/GNUmakefile @@ -6,7 +6,7 @@ BUNDLE_NAME = PreferencesUI PreferencesUI_PRINCIPAL_CLASS = PreferencesUIProduct -PreferencesUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian SpanishSpain SpanishArgentina Swedish Ukrainian Welsh +PreferencesUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh PreferencesUI_OBJC_FILES = \ PreferencesUIProduct.m \ diff --git a/UI/PreferencesUI/German.lproj/Localizable.strings b/UI/PreferencesUI/German.lproj/Localizable.strings index b906b057e..1f4ffcfb9 100644 --- a/UI/PreferencesUI/German.lproj/Localizable.strings +++ b/UI/PreferencesUI/German.lproj/Localizable.strings @@ -75,17 +75,17 @@ "longDateFmt_1" = "%A, %e. %B %Y"; "longDateFmt_2" = "%a. %d. %B %Y"; "longDateFmt_3" = "%a. %e. %B %Y"; -"longDateFmt_4" = "%A, %d. %b. %Y"; -"longDateFmt_5" = "%A, %e. %b. %Y"; -"longDateFmt_6" = "%a. %d. %b. %Y"; -"longDateFmt_7" = "%a. %e. %b. %Y"; -"longDateFmt_8" = "%d. %B %Y"; -"longDateFmt_9" = "%e. %B %Y"; +"longDateFmt_4" = ""; +"longDateFmt_5" = ""; +"longDateFmt_6" = ""; +"longDateFmt_7" = ""; +"longDateFmt_8" = ""; +"longDateFmt_9" = ""; "longDateFmt_10" = ""; "timeFmt_0" = "%H:%M"; "timeFmt_1" = "%Hh:%Mm"; -"timeFmt_2" = "%Hh %Mm"; +"timeFmt_2" = ""; "timeFmt_3" = ""; "timeFmt_4" = ""; @@ -141,6 +141,7 @@ "messageforward_inline" = "Eingebunden"; "messageforward_attached" = "Als Anhang"; +"When replying to a message:" = "Wenn auf eine Nachricht geantwortet wird: "; "replyplacement_above" = "Antwort oberhalb des Zitates beginnen"; "replyplacement_below" = "Antwort unterhalb des Zitates beginnen"; "And place my signature" = "Und setze meine Signatur"; @@ -149,12 +150,17 @@ "Compose messages in" = "Nachrichten verfassen in"; "composemessagestype_html" = "HTML"; "composemessagestype_text" = "Reintext"; +"Display remote inline images" = "Entfernte eingebettete Bilder anzeigen"; +"displayremoteinlineimages_never" = "Niemals"; +"displayremoteinlineimages_always" = "Immer"; /* IMAP Accounts */ "New Mail Account" = "Neues E-Mail-Konto"; "Server Name:" = "Servername:"; "Port:" = "Port:"; +"Encryption:" = "Verschlüsselung:"; +"None" = "Keine"; "User Name:" = "Benutzername:"; "Password:" = "Passwort:"; @@ -211,6 +217,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slowenisch"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/Hungarian.lproj/Localizable.strings b/UI/PreferencesUI/Hungarian.lproj/Localizable.strings index 871d463e4..c19ea13ac 100644 --- a/UI/PreferencesUI/Hungarian.lproj/Localizable.strings +++ b/UI/PreferencesUI/Hungarian.lproj/Localizable.strings @@ -141,6 +141,7 @@ "messageforward_inline" = "Levélként"; "messageforward_attached" = "Mellékletként"; +"When replying to a message:" = "Amikor válaszol egy üzenetre:"; "replyplacement_above" = "Válasz elhelyezése az idézet fölött"; "replyplacement_below" = "Válasz elhelyezése az idézet alatt"; "And place my signature" = "Aláírás beszúrása"; @@ -149,12 +150,17 @@ "Compose messages in" = "Üzenet formátuma"; "composemessagestype_html" = "HTML"; "composemessagestype_text" = "Egyszerű szöveg"; +"Display remote inline images" = "Távoli beágyazott képek megjelenítése"; +"displayremoteinlineimages_never" = "Soha"; +"displayremoteinlineimages_always" = "Mindig"; /* IMAP Accounts */ "New Mail Account" = "Új email fiók"; "Server Name:" = "Kiszolgáló neve:"; "Port:" = "Port:"; +"Encryption:" = "Titkosítás:"; +"None" = "Nincs"; "User Name:" = "Felhasználónév:"; "Password:" = "Jelszó:"; @@ -211,6 +217,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Szlovén"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/Icelandic.lproj/Localizable.strings b/UI/PreferencesUI/Icelandic.lproj/Localizable.strings index 3c5e832ed..4f3275991 100644 --- a/UI/PreferencesUI/Icelandic.lproj/Localizable.strings +++ b/UI/PreferencesUI/Icelandic.lproj/Localizable.strings @@ -188,6 +188,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/Italian.lproj/Localizable.strings b/UI/PreferencesUI/Italian.lproj/Localizable.strings index 233bcb635..bffab48a5 100644 --- a/UI/PreferencesUI/Italian.lproj/Localizable.strings +++ b/UI/PreferencesUI/Italian.lproj/Localizable.strings @@ -208,6 +208,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings b/UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings index a9ee05fc2..59b13dadc 100644 --- a/UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings +++ b/UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings @@ -206,6 +206,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/NorwegianNynorsk.lproj/Localizable.strings b/UI/PreferencesUI/NorwegianNynorsk.lproj/Localizable.strings index 28adde8b1..b995cfb9a 100644 --- a/UI/PreferencesUI/NorwegianNynorsk.lproj/Localizable.strings +++ b/UI/PreferencesUI/NorwegianNynorsk.lproj/Localizable.strings @@ -194,6 +194,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/Polish.lproj/Localizable.strings b/UI/PreferencesUI/Polish.lproj/Localizable.strings index 070781c3a..374c9e8f6 100644 --- a/UI/PreferencesUI/Polish.lproj/Localizable.strings +++ b/UI/PreferencesUI/Polish.lproj/Localizable.strings @@ -5,7 +5,7 @@ /* tabs */ "General" = "Ogólne"; "Calendar Options" = "Opcje kalendarza"; -"Contacts Options" = "Contacts Options"; +"Contacts Options" = "Opcje kontaktów"; "Mail Options" = "Opcje poczty"; "IMAP Accounts" = "Konta IMAP"; "Vacation" = "Nieobecność"; @@ -18,7 +18,7 @@ "Delete" = "Usuń"; /* contacts categories */ -"contacts_category_labels" = "Colleague, Competitor, Customer, Friend, Family, Business Partner, Provider, Press, VIP"; +"contacts_category_labels" = "Kolega, Konkurencja, Klient, Przyjaciel, Rodzina, Biznes, Dostawca, Prasa, VIP"; /* vacation (auto-reply) */ "Enable vacation auto reply" = "Włącz autoodpowiedź podczas nieobecności"; @@ -141,6 +141,7 @@ "messageforward_inline" = "w treści"; "messageforward_attached" = "jako załącznik"; +"When replying to a message:" = "Gdy odpowiadam na wiadomość:"; "replyplacement_above" = "Rozpocznij moją odpowiedź powyżej cytatu"; "replyplacement_below" = "Rozpocznij moją odpowiedź poniżej cytatu"; "And place my signature" = "i wstaw mój podpis"; @@ -149,12 +150,17 @@ "Compose messages in" = "Twórz wiadomości"; "composemessagestype_html" = "HTML"; "composemessagestype_text" = "czysty tekst"; +"Display remote inline images" = "Pokazuj podlinkowane zdalne obrazy"; +"displayremoteinlineimages_never" = "Nigdy"; +"displayremoteinlineimages_always" = "Zawsze"; /* IMAP Accounts */ "New Mail Account" = "Nowe konto"; "Server Name:" = "Nazwa serwera:"; "Port:" = "Port:"; +"Encryption:" = "Szyfrowanie:"; +"None" = "Brak"; "User Name:" = "Użytkownik:"; "Password:" = "Hasło:"; @@ -194,10 +200,10 @@ "Contacts" = "Książka adresowa"; "Mail" = "Poczta"; "Last" = "Ostatnio używane"; -"Default module :" = "Tryb domyślny :"; +"Default module :" = "Tryb domyślny:"; -"Language :" = "Język :"; -"choose" = "Wybierz ..."; +"Language :" = "Język:"; +"choose" = "Wybierz"; "Catalan" = "Català"; "Czech" = "Česky"; "Danish" = "Dansk (Danmark)"; @@ -211,6 +217,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovenská"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; @@ -268,8 +275,8 @@ "does not contain" = "nie zawiera"; "matches" = "pasuje do"; "does not match" = "nie pasuje do"; -"matches regex" = "pasuje do regex"; -"does not match regex" = "nie pasuje do regex"; +"matches regex" = "pasuje do wzorca"; +"does not match regex" = "nie pasuje do wzorca"; "Seen" = "Obejrzane"; "Deleted" = "Usunięte"; diff --git a/UI/PreferencesUI/Russian.lproj/Localizable.strings b/UI/PreferencesUI/Russian.lproj/Localizable.strings index b7a6d3b28..e2b8aeed0 100644 --- a/UI/PreferencesUI/Russian.lproj/Localizable.strings +++ b/UI/PreferencesUI/Russian.lproj/Localizable.strings @@ -211,6 +211,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/Slovak.lproj/Localizable.strings b/UI/PreferencesUI/Slovak.lproj/Localizable.strings new file mode 100644 index 000000000..e48ca52f4 --- /dev/null +++ b/UI/PreferencesUI/Slovak.lproj/Localizable.strings @@ -0,0 +1,305 @@ +/* toolbar */ +"Save and Close" = "Uložiť a zavrieť"; +"Close" = "Zavrieť"; + +/* tabs */ +"General" = "Všeobecné"; +"Calendar Options" = "Vlastnosti kalendára"; +"Contacts Options" = "Vlastnosti kontaktov"; +"Mail Options" = "Vlastnosti pošty"; +"IMAP Accounts" = "imap účty"; +"Vacation" = "Dovolenka"; +"Forward" = "Dopredu"; +"Password" = "Heslo"; +"Categories" = "Kategórie"; +"Name" = "Meno"; +"Color" = "Farba"; +"Add" = "Pridať"; +"Delete" = "Zmazať"; + +/* contacts categories */ +"contacts_category_labels" = "Kolega, Účastník, Zákazník, Priateľ, Rodina, Obchodný partner, Poskytovateľ, Tlač, VIP"; + +/* vacation (auto-reply) */ +"Enable vacation auto reply" = "Zapnúť automatickú odpoveď"; +"Auto reply message :" = "Automatická odpoveď:"; +"Email addresses (separated by commas) :" = "Emailové adresy (oddelené čiarkami):"; +"Add default email addresses" = "Pridať východziu emailovú adresu"; +"Days between responses :" = "Dni medzi odpoveďami:"; +"Do not send responses to mailing lists" = "Neposielať odpoveď emailovým skupinám"; +"Disable auto reply on" = "Vypnúť automatickú odpoveď"; +"Please specify your message and your email addresses for which you want to enable auto reply." += "Prosím špecifikujte Vašu správu a emailovú adresu pre ktorú chcete zapnút automatickú odpoveď."; +"Your vacation message must not end with a single dot on a line." = "Vaša dovolenková správa nesmie končit samotnou bodkou v riadku."; +"End date of your auto reply must be in the future." += "Dátum konca platnosti automatickej odpovede musí byť v budúcnosti."; + +/* forward messages */ +"Forward incoming messages" = "Prepošli prichádzajúce správy"; +"Keep a copy" = "Ponechaj kópiu"; +"Please specify an address to which you want to forward your messages." += "Prosím zvoľte adresu na ktorú checete preposielať Vaše správy"; + +/* d & t */ +"Current Time Zone :" = "Aktuálna Časová Zóna:"; +"Short Date Format :" = "Krátky formát dátumu:"; +"Long Date Format :" = "Dlhý formát dátumu:"; +"Time Format :" = "Formát času:"; + +"default" = "Predvolený"; + +"shortDateFmt_0" = "%d-%b-%y"; + +"shortDateFmt_1" = "%d-%m-%y"; +"shortDateFmt_2" = "%d/%m/%y"; +"shortDateFmt_3" = "%e/%m/%y"; + +"shortDateFmt_4" = "%d-%m-%Y"; +"shortDateFmt_5" = "%d/%m/%Y"; + +"shortDateFmt_6" = "%m-%d-%y"; +"shortDateFmt_7" = "%m/%d/%y"; +"shortDateFmt_8" = "%m/%e/%y"; + +"shortDateFmt_9" = "%y-%m-%d"; +"shortDateFmt_10" = "%y/%m/%d"; +"shortDateFmt_11" = "%y.%m.%d"; + +"shortDateFmt_12" = "%Y-%m-%d"; +"shortDateFmt_13" = "%Y/%m/%d"; +"shortDateFmt_14" = "%Y.%m.%d"; + +"shortDateFmt_15" = ""; + +"longDateFmt_0" = "%A, %B %d, %Y"; +"longDateFmt_1" = "%B %d, %Y"; +"longDateFmt_2" = "%A, %d %B, %Y"; +"longDateFmt_3" = "%d %B, %Y"; +"longDateFmt_4" = ""; +"longDateFmt_5" = ""; +"longDateFmt_6" = ""; +"longDateFmt_7" = ""; +"longDateFmt_8" = ""; +"longDateFmt_9" = ""; +"longDateFmt_10" = ""; + +"timeFmt_0" = "%I:%M %p"; +"timeFmt_1" = "%HH:%MM"; +"timeFmt_2" = ""; +"timeFmt_3" = ""; +"timeFmt_4" = ""; + +/* calendar */ +"Week begins on :" = "Týždeň začína v:"; +"Day start time :" = "Začiatok dňa:"; +"Day end time :" = "Koniec dňa:"; +"Day start time must be prior to day end time." = "Začiatok dňa musí byť skôr ako koniec dňa."; +"Show time as busy outside working hours" = "Mimo pracovných hodín ukáž čas ako obsadený"; +"First week of year :" = "Prvý týždeň roka:"; +"Enable reminders for Calendar items" = "Zapni pripomienky pre položky Kalendára"; +"Play a sound when a reminder comes due" += "Prehraj zvuk keď začne pripomienka"; +"Default reminder :" = "Predvolená pripomienka:"; + +"firstWeekOfYear_January1" = "Začína 1. Januárom"; +"firstWeekOfYear_First4DayWeek" = "Prvý 4-dňový týždeň"; +"firstWeekOfYear_FirstFullWeek" = "Prvý celý týžden"; + +/* Default Calendar */ +"Default calendar :" = "Predvolený kalendár:"; +"selectedCalendar" = "Zvolený kalendár"; +"personalCalendar" = "Osobný kalendár"; +"firstCalendar" = "Prvý zapnutý kalendár"; + +"reminderTime_0000" = "0 minút"; +"reminderTime_0005" = "5 minút"; +"reminderTime_0010" = "10 minút"; +"reminderTime_0015" = "15 minút"; +"reminderTime_0030" = "30 minút"; +"reminderTime_0100" = "1 hodina"; +"reminderTime_0200" = "2 hodiny"; +"reminderTime_0400" = "4 hodiny"; +"reminderTime_0800" = "8 hodín"; +"reminderTime_1200" = "1/2 dňa"; +"reminderTime_2400" = "1 deň"; +"reminderTime_4800" = "2 dni"; + +/* Mailer */ +"Show subscribed mailboxes only" = "Ukazuj iba odoberané účty"; +"Sort messages by threads" = "Zoraď správy do konverzácií"; +"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"; + +"Forward messages:" = "Preposielaj správy:"; +"messageforward_inline" = "Vrade"; +"messageforward_attached" = "Ako prílohu"; + +"When replying to a message:" = "Pri odpovedaní na správu:"; +"replyplacement_above" = "Odpoveď začína nad citáciou"; +"replyplacement_below" = "Odpoveď začína pod citáciou"; +"And place my signature" = "A vlož môj podpis"; +"signatureplacement_above" = "pod odpoveďou"; +"signatureplacement_below" = "pod citáciou"; +"Compose messages in" = "Vytvor správu v "; +"composemessagestype_html" = "HTML"; +"composemessagestype_text" = "Čistý text"; +"Display remote inline images" = "Zobraziť externe pripojené obrázky"; +"displayremoteinlineimages_never" = "Nikdy"; +"displayremoteinlineimages_always" = "Vždy"; + +/* IMAP Accounts */ +"New Mail Account" = "Nový mailový účet"; + +"Server Name:" = "Meno servera:"; +"Port:" = "Port:"; +"Encryption:" = "Šifrovanie:"; +"None" = "Žiadne"; +"User Name:" = "Užívateľské meno:"; +"Password:" = "Heslo:"; + +"Full Name:" = "Celé meno:"; +"Email:" = "Email:"; +"Reply To Email:" = "Email pre odpoveď:"; +"Signature:" = "Podpis:"; +"(Click to create)" = "(klikni pre vytvorenie)"; + +"Signature" = "Podpis"; +"Please enter your signature below:" = "Prosím vložte svoj podpis nižšie:"; + +"Please specify a valid sender address." = "Prosím zvoľte platnú adresu odosielateľa"; +"Please specify a valid reply-to address." = "Prosím zvoľte platnú adresu pre odpoveď."; + +/* Additional Parameters */ +"Additional Parameters" = "Dalšie parametre"; + +/* password */ +"New password:" = "Nové heslo:"; +"Confirmation:" = "Potvrdenie:"; +"Change" = "Zmena"; + +/* Event+task classifications */ +"Default events classification :" = "Predvolená klasifikácia udalostí"; +"Default tasks classification :" = "Predvolená klasifikácia úloh"; +"PUBLIC_item" = "Verejný"; +"CONFIDENTIAL_item" = "Dôverný"; +"PRIVATE_item" = "Súkromný"; + +/* Event+task categories */ +"category_none" = "Žiadne"; +"calendar_category_labels" = "Výročia,Narodeniny,Obchod,Hovory,Zákazníci,Konkurencia,Obľúbene,Sledovať,Darčeky,Prázdniny,Nápady,Stretnutia,Probléma,Rôzne,Osobné,Projekty,Štátne sviatky,Stav,Dodávatelia,Cestovanie,Dovolenka"; + +/* Default module */ +"Calendar" = "Kalendár"; +"Contacts" = "Adresár"; +"Mail" = "Pošta"; +"Last" = "Naposledy použité"; +"Default module :" = "Predvolený modul:"; + +"Language :" = "Jazyk:"; +"choose" = "Vyber..."; +"Catalan" = "Català"; +"Czech" = "Česky"; +"Danish" = "Dansk (Danmark)"; +"Dutch" = "Netherlands"; +"English" = "English"; +"French" = "Français"; +"German" = "Deutsch"; +"Hungarian" = "Magyar"; +"Italian" = "Italiano"; +"NorwegianBokmal" = "Norsk bokmål"; +"NorwegianNynorsk" = "Norsk nynorsk"; +"BrazilianPortuguese" = "Português brasileiro"; +"Russian" = "Русский"; +"Slovak" = "Slovensky"; +"SpanishSpain" = "Español (España)"; +"SpanishArgentina" = "Español (Argentina)"; +"Swedish" = "Svenska"; +"Ukrainian" = "Українська"; +"Welsh" = "Cymraeg"; + +/* Return receipts */ +"When I receive a request for a return receipt:" = "Keď dostanem požiadavku na potvrdenie o doručení"; +"Never send a return receipt" = "Nikdy neposielať potvrdenie o doručení"; +"Allow return receipts for some messages" = "Povoliť potvrdenie o doručení pre niektoré správy"; +"If I'm not in the To or Cc of the message:" = "Pokial nie som v Pre alebo Kópia políčku správy:"; +"If the sender is outside my domain:" = "Pokiaľ je odosielateľ mimo mojej domény:"; +"In all other cases:" = "Vo všetkých ostatných prípadoch:"; + +"Never send" = "Nikdy neposielaj"; +"Always send" = "Vždy posielaj"; +"Ask me" = "Opytať sa"; + +/* Filters - UIxPreferences */ +"Filters" = "Filtre"; +"Active" = "Aktívne"; +"Move Up" = "Posuň hore"; +"Move Down" = "Posuň dole"; + +/* Filters - UIxFilterEditor */ +"Filter name:" = "Meno filtra:"; +"For incoming messages that" = "Pre prichádzajúce správy ktoré"; +"match all of the following rules:" = "splň všetky nasledujúce pravidlá:"; +"match any of the following rules:" = "zodpovedá ktorémukoľvek z nasledujúcich pravidiel:"; +"match all messages" = "zodpovedá pre všetky správy"; +"Perform these actions:" = "Vykonaj nasledovné úlohy:"; +"Untitled Filter" = "Nepomenovaný Filter"; + +"Subject" = "Predmet"; +"From" = "Od"; +"To" = "Pre"; +"Cc" = "Kópia"; +"To or Cc" = "Pre alebo Kópia"; +"Size (Kb)" = "Vľkosť (Kb)"; +"Header" = "Hlavička"; +"Flag the message with:" = "Nasledujúce správy označ zástavkou:"; +"Discard the message" = "Zahoď správu"; +"File the message in:" = "Súbor správy v:"; +"Keep the message" = "Ponechaj správu"; +"Forward the message to:" = "Prepošli správu:"; +"Send a reject message:" = "Pošli odmietnutie:"; +"Send a vacation message" = "Odošli správu o dovolenke"; +"Stop processing filter rules" = "Zastav spracovávanie filtrovacích pravidiel"; + +"is under" = "je pod"; +"is over" = "je nad"; +"is" = "je"; +"is not" = "nie je "; +"contains" = "obsahuje"; +"does not contain" = "neobsahuje"; +"matches" = "zodpovedá"; +"does not match" = "nezodpovedá"; +"matches regex" = "zodpovedá regulárnemu výrazu"; +"does not match regex" = "nezodpovedá regulárnemu výrazu"; + +"Seen" = "Videné"; +"Deleted" = "Vymazané"; +"Answered" = "Odpovedané"; +"Flagged" = "Označené zástavkou"; +"Junk" = "Spam"; +"Not Junk" = "Nie je Spam"; +"Label 1" = "Označenie 1"; +"Label 2" = "Označenie 2"; +"Label 3" = "Označenie 3"; +"Label 4" = "Označenie 4"; +"Label 5" = "Označenie 5"; + +"The password was changed successfully." = "Heslo bolo úspešne zmenené."; +"Password must not be empty." = "Heslo nemôže byť prázdne."; +"The passwords do not match. Please try again." = "Heslá sa nezhodujú. Skúste to znova."; +"Password change failed" = "Zmena hesla nebola úspešná"; +"Password change failed - Permission denied" = "Zmena hesla nebola úspešná - Nemáte dostatočné oprávnenia"; +"Password change failed - Insufficient password quality" = "Zmena hesla nebola úspešná - Nedostatočná kvalita hesla"; +"Password change failed - Password is too short" = "Zmena hesla nebola úspešná - Heslo je príliš krátke"; +"Password change failed - Password is too young" = "Zmena hesla nebola úspešná - Heslo bolo nedávno použité"; +"Password change failed - Password is in history" = "Zmena hesla nebola úspešná - Heslo je v histórii"; +"Unhandled policy error: %{0}" = "Neočakávaná chyba v postupe: %{0}"; +"Unhandled error response" = "Neočakávaná chybová odpoveď"; +"Password change is not supported." = "Zmena hesla nie je podporovaná."; +"Unhandled HTTP error code: %{0}" = "Neočakávaná HTTP chybová hláška: %{0}"; diff --git a/UI/PreferencesUI/SpanishArgentina.lproj/Localizable.strings b/UI/PreferencesUI/SpanishArgentina.lproj/Localizable.strings index 0228df62f..8452e95d4 100644 --- a/UI/PreferencesUI/SpanishArgentina.lproj/Localizable.strings +++ b/UI/PreferencesUI/SpanishArgentina.lproj/Localizable.strings @@ -211,6 +211,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings b/UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings index fc8aff84c..bc93caf11 100644 --- a/UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings +++ b/UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings @@ -141,6 +141,7 @@ "messageforward_inline" = "Incorporado"; "messageforward_attached" = "Como adjunto"; +"When replying to a message:" = "Cuando se contesta a un mensaje:"; "replyplacement_above" = "Empieza mi respuesta sobre el texto"; "replyplacement_below" = "Empieza mi respuesta bajo el texto"; "And place my signature" = "Y añade mi firma"; @@ -149,12 +150,17 @@ "Compose messages in" = "Redactar el mensaje en"; "composemessagestype_html" = "HTML"; "composemessagestype_text" = "Texto plano"; +"Display remote inline images" = "Enseña imágenes remotas de forma integrada"; +"displayremoteinlineimages_never" = "Nunca"; +"displayremoteinlineimages_always" = "Siempre"; /* IMAP Accounts */ "New Mail Account" = "Nueva Cuenta de Correo"; "Server Name:" = "Nombre de Servidor:"; "Port:" = "Puerto:"; +"Encryption:" = "Cifrado:"; +"None" = "Ninguno"; "User Name:" = "Nombre de usuario:"; "Password:" = "Contraseña:"; @@ -211,6 +217,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Eslovaquia"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/Swedish.lproj/Localizable.strings b/UI/PreferencesUI/Swedish.lproj/Localizable.strings index 67ca8f880..7e098f82d 100644 --- a/UI/PreferencesUI/Swedish.lproj/Localizable.strings +++ b/UI/PreferencesUI/Swedish.lproj/Localizable.strings @@ -196,6 +196,7 @@ Servernamn:"; "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/UIxPreferences.m b/UI/PreferencesUI/UIxPreferences.m index d3473ae71..8d6bcb227 100644 --- a/UI/PreferencesUI/UIxPreferences.m +++ b/UI/PreferencesUI/UIxPreferences.m @@ -759,6 +759,28 @@ [userDefaults setMailComposeMessageType: newType]; } +/* Display remote inline images */ +- (NSArray *) displayRemoteInlineImages +{ + return [NSArray arrayWithObjects: @"never", @"always", nil]; +} + +- (NSString *) itemDisplayRemoteInlineImagesText +{ + return [self labelForKey: [NSString stringWithFormat: + @"displayremoteinlineimages_%@", item]]; +} + +- (NSString *) userDisplayRemoteInlineImages +{ + return [userDefaults mailDisplayRemoteInlineImages]; +} + +- (void) setUserDisplayRemoteInlineImages: (NSString *) newType +{ + [userDefaults setMailDisplayRemoteInlineImages: newType]; +} + /* mail autoreply (vacation) */ - (BOOL) isSieveScriptsEnabled diff --git a/UI/PreferencesUI/Ukrainian.lproj/Localizable.strings b/UI/PreferencesUI/Ukrainian.lproj/Localizable.strings index 2c63a85cc..170e551e7 100644 --- a/UI/PreferencesUI/Ukrainian.lproj/Localizable.strings +++ b/UI/PreferencesUI/Ukrainian.lproj/Localizable.strings @@ -206,6 +206,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/PreferencesUI/Welsh.lproj/Localizable.strings b/UI/PreferencesUI/Welsh.lproj/Localizable.strings index cebc8afcb..00171753f 100644 --- a/UI/PreferencesUI/Welsh.lproj/Localizable.strings +++ b/UI/PreferencesUI/Welsh.lproj/Localizable.strings @@ -194,6 +194,7 @@ "NorwegianNynorsk" = "Norsk nynorsk"; "BrazilianPortuguese" = "Português brasileiro"; "Russian" = "Русский"; +"Slovak" = "Slovensky"; "SpanishSpain" = "Español (España)"; "SpanishArgentina" = "Español (Argentina)"; "Swedish" = "Svenska"; diff --git a/UI/SOGoUI/GNUmakefile.preamble b/UI/SOGoUI/GNUmakefile.preamble index 9288140ff..babfaf5bc 100644 --- a/UI/SOGoUI/GNUmakefile.preamble +++ b/UI/SOGoUI/GNUmakefile.preamble @@ -10,7 +10,8 @@ libSOGoUI_LIBRARIES_DEPEND_UPON += \ -lNGObjWeb \ -lNGMime \ -lNGExtensions -lEOControl \ - -lSaxObjC -lgnustep-base -lSOGo -lobjc + -lSaxObjC -lSOGo \ + $(BASE_LIBS) SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib ADDITIONAL_INCLUDE_DIRS += -I../../SoObjects diff --git a/UI/SOGoUI/UIxComponent.m b/UI/SOGoUI/UIxComponent.m index d415932c3..f80e9e9ec 100644 --- a/UI/SOGoUI/UIxComponent.m +++ b/UI/SOGoUI/UIxComponent.m @@ -146,6 +146,8 @@ static SoProduct *commonProduct = nil; _selectedDate = nil; queryParameters = nil; ASSIGN (userDefaults, [[context activeUser] userDefaults]); + if (!userDefaults) + ASSIGN (userDefaults, [SOGoSystemDefaults sharedSystemDefaults]); language = [userDefaults language]; ASSIGN (locale, [[self resourceManager] localeForLanguageNamed: language]); diff --git a/UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings b/UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings index d9519b0ed..70e8115cd 100644 --- a/UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings +++ b/UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings @@ -60,6 +60,7 @@ "Import Events" = "Importar Eventos"; "Select an iCalendar file (.ics)." = "Selecione um arquivo iCalendar (.ics)."; "Upload" = "Carregar"; +"Uploading" = "Carregando"; "Publish Calendar..." = "Publicar Calendário..."; "Reload Remote Calendars" = "Recarregar Calendários Remotos"; "Properties" = "Propriedades"; @@ -379,6 +380,7 @@ validate_invalid_startdate = "Campo Data Inicial incorreto!"; validate_invalid_enddate = "Campo Data Final incorreto!"; validate_endbeforestart = "A data que você informou ocorre antes da data inicial."; +"Events" = "Eventos"; "Tasks" = "Tarefas"; "Show completed tasks" = "Exibir tarefas completadas"; @@ -452,14 +454,18 @@ validate_endbeforestart = "A data que você informou ocorre antes da data ini "Title" = "Título"; "Start" = "Início"; "End" = "Fim"; -"Due Date" = "Data"; +"Due Date" = "Data de Vencimento"; "Location" = "Localização"; + "(Private Event)" = "(Evento Privado)"; vevent_class0 = "(Evento Público)"; vevent_class1 = "(Evento Privado)"; vevent_class2 = "(Evento Confidencial)"; +"Priority" = "Prioridade"; +"Category" = "Categoria"; + vtodo_class0 = "(Tarefa Pública)"; vtodo_class1 = "(Tarefa Privada)"; vtodo_class2 = "(Tarefa Confidencial)"; @@ -487,6 +493,11 @@ vtodo_class2 = "(Tarefa Confidencial)"; "Show alarms" = "Exibir alarmes"; "Show tasks" = "Exibir tarefas"; +"Notifications" = "Notificações"; +"Receive a mail when I modify my calendar" = "Receber um email quando eu modificar meu calendário"; +"Receive a mail when someone else modifies my calendar" = "Receber um email quando alguem modificar meu calendário"; +"When I modify my calendar, send a mail to:" = "Quando eu modificar meu calendário, enviar um email para:"; + "Links to this Calendar" = "Links para este Calendário"; "Authenticated User Access" = "Acesso a Usuário Autenticado"; "CalDAV URL" = "CalDAV url"; @@ -515,12 +526,10 @@ vtodo_class2 = "(Tarefa Confidencial)"; "Delete Task" = "Remover Tarefa"; "Delete Event" = "Remover Evento"; "Copy event to my calendar" = "Copiar evento para o meu calendário"; +"View Raw Source" = "Visualizar Fonte"; "Subscribe to a web calendar..." = "Inscrever-se a um calendário web..."; "URL of the Calendar" = "URL do Calendário"; "Web Calendar" = "Calendário Web"; "Reload on login" = "Recarregar no login"; "Invalid number." = "Número inválido."; - -"Category" = "Categoria"; -"Priority" = "Prioridade"; diff --git a/UI/Scheduler/Dutch.lproj/Localizable.strings b/UI/Scheduler/Dutch.lproj/Localizable.strings index 7f9285a30..04d2f20fe 100644 --- a/UI/Scheduler/Dutch.lproj/Localizable.strings +++ b/UI/Scheduler/Dutch.lproj/Localizable.strings @@ -493,6 +493,7 @@ vtodo_class2 = "(Vertrouwelijke taak)"; "Show alarms" = "Alarmen tonen"; "Show tasks" = "Taken tonen"; +"Notifications" = "Notificaties"; "Receive a mail when I modify my calendar" = "Ontvang een e-mail als ik mijn agenda verander"; "Receive a mail when someone else modifies my calendar" = "Ontvang een e-mail als iemand anders mijn agenda verandert"; "When I modify my calendar, send a mail to:" = "Als ik mijn agenda verader, stuur een e-mail naar:"; diff --git a/UI/Scheduler/English.lproj/Localizable.strings b/UI/Scheduler/English.lproj/Localizable.strings index c18bbe825..6fe90daf0 100644 --- a/UI/Scheduler/English.lproj/Localizable.strings +++ b/UI/Scheduler/English.lproj/Localizable.strings @@ -493,6 +493,7 @@ vtodo_class2 = "(Confidential task)"; "Show alarms" = "Show alarms"; "Show tasks" = "Show tasks"; +"Notifications" = "Notifications"; "Receive a mail when I modify my calendar" = "Receive a mail when I modify my calendar"; "Receive a mail when someone else modifies my calendar" = "Receive a mail when someone else modifies my calendar"; "When I modify my calendar, send a mail to:" = "When I modify my calendar, send a mail to:"; diff --git a/UI/Scheduler/French.lproj/Localizable.strings b/UI/Scheduler/French.lproj/Localizable.strings index 41206ead0..9d84f0d35 100644 --- a/UI/Scheduler/French.lproj/Localizable.strings +++ b/UI/Scheduler/French.lproj/Localizable.strings @@ -493,6 +493,7 @@ vtodo_class2 = "(Tâche confidentielle)"; "Show alarms" = "Afficher les alarmes"; "Show tasks" = "Afficher les tâches"; +"Notifications" = "Notifications"; "Receive a mail when I modify my calendar" = "Émettre un courrier quand je modifie mon agenda"; "Receive a mail when someone else modifies my calendar" = "Émettre un courrier quand quelqu'un d'autre modifie mon agenda"; "When I modify my calendar, send a mail to:" = "Quand je modifie mon agenda, émettre un courrier à :"; diff --git a/UI/Scheduler/GNUmakefile b/UI/Scheduler/GNUmakefile index f71bcd6cd..b7df6e9d5 100644 --- a/UI/Scheduler/GNUmakefile +++ b/UI/Scheduler/GNUmakefile @@ -6,7 +6,7 @@ BUNDLE_NAME = SchedulerUI SchedulerUI_PRINCIPAL_CLASS = SchedulerUIProduct -SchedulerUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian SpanishSpain SpanishArgentina Swedish Ukrainian Welsh +SchedulerUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh SchedulerUI_OBJC_FILES = \ SchedulerUIProduct.m \ diff --git a/UI/Scheduler/German.lproj/Localizable.strings b/UI/Scheduler/German.lproj/Localizable.strings index 8276fd18e..5398716d2 100644 --- a/UI/Scheduler/German.lproj/Localizable.strings +++ b/UI/Scheduler/German.lproj/Localizable.strings @@ -493,6 +493,7 @@ vtodo_class2 = "(Vertrauliche Aufgabe)"; "Show alarms" = "Zeige Erinnerungen"; "Show tasks" = "Zeige Aufgaben"; +"Notifications" = "Benachrichtigungen"; "Receive a mail when I modify my calendar" = "E-Mail erhalten, wenn ich meinen Kalender verändere"; "Receive a mail when someone else modifies my calendar" = "E-Mail erhalten, wenn jemand anderes meinen Kalender verändert"; "When I modify my calendar, send a mail to:" = "Wenn ich meinen Kalender verändere, schicke eine E-Mail an: "; diff --git a/UI/Scheduler/Hungarian.lproj/Localizable.strings b/UI/Scheduler/Hungarian.lproj/Localizable.strings index 6029e7433..0aaf22a76 100644 --- a/UI/Scheduler/Hungarian.lproj/Localizable.strings +++ b/UI/Scheduler/Hungarian.lproj/Localizable.strings @@ -493,6 +493,7 @@ vtodo_class2 = "(Bizalmas feladat)"; "Show alarms" = "Riasztások megjelenítése"; "Show tasks" = "Feladatok megjelenítése"; +"Notifications" = "Értesítések"; "Receive a mail when I modify my calendar" = "Kapjak email értesítést, amikor módosítok a naptáramon"; "Receive a mail when someone else modifies my calendar" = "Kapjak email értesítést, amikor mások módosítják a naptáramat"; "When I modify my calendar, send a mail to:" = "Email értesítés küldése az alábbi címre a naptáram módosításakor"; diff --git a/UI/Scheduler/Polish.lproj/Localizable.strings b/UI/Scheduler/Polish.lproj/Localizable.strings index 3d408c7d0..e1af7dc11 100644 --- a/UI/Scheduler/Polish.lproj/Localizable.strings +++ b/UI/Scheduler/Polish.lproj/Localizable.strings @@ -7,9 +7,9 @@ "Edit this event or task" = "Edytuj to wydarzenie lub zadanie"; "Delete this event or task" = "Usuń to wydarzenie lub zadanie"; "Go to today" = "Przejdź do dnia dzisiejszego"; -"Switch to day view" = "Przełącz do widoku dnia"; -"Switch to week view" = "Przełącz do widoku tygodnia"; -"Switch to month view" = "Przełącz do widoku miesiąca"; +"Switch to day view" = "Przełącz na widok dnia"; +"Switch to week view" = "Przełącz na widok tygodnia"; +"Switch to month view" = "Przełącz na widok miesiąca"; "Reload all calendars" = "Przeładuj wszystkie kalendarze"; /* Tabs */ @@ -19,7 +19,7 @@ /* Day */ "DayOfTheMonth" = "Dzień miesiąca"; -"dayLabelFormat" = "%Y-%m-%d"; +"dayLabelFormat" = "%d.%m.%Y"; "today" = "Dzisiaj"; "Previous Day" = "Poprzedni dzień"; @@ -51,17 +51,17 @@ "Calendar" = "Kalendarz"; "Contacts" = "Kontakty"; -"New Calendar..." = "Nowy kalendarz..."; -"Delete Calendar" = "Usuń kalendarz..."; +"New Calendar..." = "Nowy kalendarz"; +"Delete Calendar" = "Usuń kalendarz"; "Unsubscribe Calendar" = "Wyłącz subskrypcję kalendarza"; -"Sharing..." = "Udostępnianie..."; -"Export Calendar..." = "Eksportuj kalendarz..."; -"Import Events..." = "Importuj wydarzenia..."; -"Import Events" = "Importuj wydarzenia"; +"Sharing..." = "Udostępnianie"; +"Export Calendar..." = "Eksportuj kalendarz"; +"Import Events..." = "Importuj wydarzenia"; +"Import Events" = "Importowanie wydarzeń"; "Select an iCalendar file (.ics)." = "Wybierz plik iCalendar (.ics)."; "Upload" = "Wyślij"; "Uploading" = "Wysyłanie"; -"Publish Calendar..." = "Opublikuj kalendarz..."; +"Publish Calendar..." = "Opublikuj kalendarz"; "Reload Remote Calendars" = "Przeładuj zdalne kalendarze"; "Properties" = "Właściwości"; "Done" = "Zrobione"; @@ -111,7 +111,7 @@ /* Button Titles */ -"Subscribe to a Calendar..." = "Subskrybuj kalendarz..."; +"Subscribe to a Calendar..." = "Subskrybuj kalendarz użytkownika"; "Remove the selected Calendar" = "Usuń zaznaczony kalendarz"; "Name of the Calendar" = "Nazwa kalendarza"; @@ -137,7 +137,7 @@ "No appointments found" = "Brak spotkań"; "Meetings proposed by you" = "Spotkania zaproponowane przez ciebie"; "Meetings proposed to you" = "Spotkania zaproponowane tobie"; -"sched_startDateFormat" = "%m/%d %H:%M"; +"sched_startDateFormat" = "%d.%m %H:%M"; "action" = "Akcja"; "accept" = "Zaakceptuj"; "decline" = "Odmów"; @@ -195,7 +195,7 @@ "empty title" = "Pusty tytuł"; "private appointment" = "Spotkanie prywatne"; -"Change..." = "Zmień..."; +"Change..." = "Zmień"; /* Appointments (participation state) */ @@ -228,7 +228,7 @@ "Search" = "Szukaj"; "Search attendees" = "Szukaj uczestników"; -"Search resources" = "Szukaj zasoby"; +"Search resources" = "Szukaj zasobów"; "Search appointments" = "Szukaj spotkania"; "All day Event" = "Wydarzenie całodniowe"; @@ -302,7 +302,7 @@ "Days" = "Dni"; "Week(s)" = "Tygodni(e)"; "On" = "w"; -"Month(s)" = "Miesiące(ęcy)"; +"Month(s)" = "Miesiące(cy)"; "The" = " "; "Recur on day(s)" = "Powtarzaj w dni"; "Year(s)" = "Lat(a)"; @@ -331,7 +331,7 @@ "repeat_EVERY WEEKDAY" = "W dni powszednie"; "repeat_MONTHLY" = "Co miesiąc"; "repeat_YEARLY" = "Co rok"; -"repeat_CUSTOM" = "Inaczej..."; +"repeat_CUSTOM" = "Inaczej"; "reminder_NONE" = "Bez przypomnienia"; "reminder_5_MINUTES_BEFORE" = "5 minut przed"; @@ -346,7 +346,7 @@ "reminder_1_DAY_BEFORE" = "1 dzień przed"; "reminder_2_DAYS_BEFORE" = "2 dni przed"; "reminder_1_WEEK_BEFORE" = "1 tydzień przed"; -"reminder_CUSTOM" = "Inaczej..."; +"reminder_CUSTOM" = "Inaczej"; "reminder_MINUTES" = "minut(y)"; "reminder_HOURS" = "godzin(y)"; @@ -357,11 +357,11 @@ "reminder_END" = "końcem wydarzenia"; "Reminder Details" = "Szczegóły przypomnienia"; -"Choose a Reminder Action" = "Choose a Reminder Action"; -"Show an Alert" = "Show an Alert"; -"Send an E-mail" = "Send an E-mail"; -"Email Organizer" = "Email Organizer"; -"Email Attendees" = "Email Attendees"; +"Choose a Reminder Action" = "Wybierz sposób przypomnienia"; +"Show an Alert" = "Pokaż ostrzeżenie"; +"Send an E-mail" = "Wyślij e-mail"; +"Email Organizer" = "E-mail do organizatora"; +"Email Attendees" = "E-mail do uczestników"; "zoom_400" = "400%"; "zoom_200" = "200%"; @@ -403,9 +403,9 @@ validate_endbeforestart = "Podana data końca jest wcześniejsza niż data po "eventPartStatModificationError" = "Twój status uczestnictwa nie mógł być zmodyfikowany."; /* menu */ -"New Event..." = "Nowe wydarzenie..."; -"New Task..." = "Nowe zadanie..."; -"Edit Selected Event..." = "Edytuj zaznaczone wydarzenie..."; +"New Event..." = "Nowe wydarzenie"; +"New Task..." = "Nowe zadanie"; +"Edit Selected Event..." = "Edytuj zaznaczone wydarzenie"; "Delete Selected Event" = "Usuń zaznaczone wydarzenie"; "Select All" = "Zaznacz wszystkie"; "Workweek days only" = "Tylko dni powszednie"; @@ -454,7 +454,7 @@ validate_endbeforestart = "Podana data końca jest wcześniejsza niż data po "Title" = "Tytuł"; "Start" = "Początek"; "End" = "Koniec"; -"Due Date" = "Termin:"; +"Due Date" = "Termin"; "Location" = "Miejsce"; "(Private Event)" = "(Wydarzenie prywatne)"; @@ -493,6 +493,7 @@ vtodo_class2 = "(Zadanie poufne)"; "Show alarms" = "Pokaż alarmy"; "Show tasks" = "Pokaż zadania"; +"Notifications" = "Powiadomienia"; "Receive a mail when I modify my calendar" = "Przyślij e-mail, gdy zmieniam swój kalendarz"; "Receive a mail when someone else modifies my calendar" = "Przyślij e-mail, gdy ktoś zmienia mój kalendarz"; "When I modify my calendar, send a mail to:" = "Gdy zmieniam swój kalendarz, wyślij e-mail do:"; @@ -511,24 +512,24 @@ vtodo_class2 = "(Zadanie poufne)"; "yearFieldInvalid" = "W polu Lata wprowadź liczbę równą lub większą od 1."; "appointmentFieldInvalid" = "W polu Spotkania wprowadź liczbę równą lub większą od 1."; "recurrenceUnsupported" = "Ten typ powtórzeń obecnie nie jest obsługiwany."; -"Please specify a calendar name." = "Please specify a calendar name."; +"Please specify a calendar name." = "Proszę podać nazwę kalendarza."; "tagNotDefined" = "Musisz podać znacznik, jeśli chcesz synchronizować ten kalendarz."; "tagAlreadyExists" = "Podany znacznik jest już skojarzony z innym kalendarzem."; "tagHasChanged" = "Jeśli zmienisz znacznik kalendarza, musisz przeładować dane na swoim urządzeniu mobilnym.\nKontynuować?"; "tagWasAdded" = "Jeśli chesz synchronizować ten kalendarz, będziesz musiał(a) przeładować dane na swoim urządzeniu mobilnym.\nKontynuować?"; "tagWasRemoved" = "Jeśli usuniesz ten kalendarz z synchronizacji, będziesz musiał(a) przeładować dane na swoim urządzeniu mobilnym.\nKontynuować?"; -"DestinationCalendarError" = "The source and destination calendars are the same. Please try to copy to a different calendar."; -"EventCopyError" = "The copy failed. Please try to copy to a difference calendar."; +"DestinationCalendarError" = "Chcesz kopiować do tego samego kalendarza. Musisz wybrać inny kalendarz."; +"EventCopyError" = "Kopiowanie nie udało się. Wybierz inny kalendarz."; -"Open Task..." = "Otwórz zadanie..."; +"Open Task..." = "Otwórz zadanie"; "Mark Completed" = "Oznacz jako ukończone"; "Delete Task" = "Usuń zadanie"; "Delete Event" = "Usuń wydarzenie"; -"Copy event to my calendar" = "Copy event to my calendar"; +"Copy event to my calendar" = "Kopiuj wydarzenie do mojego kalendarza"; "View Raw Source" = "Obejrzyj źródło"; -"Subscribe to a web calendar..." = "Subskrybuj kalendarz..."; +"Subscribe to a web calendar..." = "Subskrybuj sieciowy kalendarz"; "URL of the Calendar" = "URL do kalendarza"; -"Web Calendar" = "Kalendarz Web"; +"Web Calendar" = "Kalendarz sieciowy"; "Reload on login" = "Przeładuj przy logowaniu"; -"Invalid number." = "Invalid number."; +"Invalid number." = "Błędna liczba."; diff --git a/UI/Scheduler/Slovak.lproj/Localizable.strings b/UI/Scheduler/Slovak.lproj/Localizable.strings new file mode 100644 index 000000000..a4d3501ec --- /dev/null +++ b/UI/Scheduler/Slovak.lproj/Localizable.strings @@ -0,0 +1,535 @@ +/* this file is in UTF-8 format! */ + +/* Tooltips */ + +"Create a new event" = "Vytvoriť novú udalosť"; +"Create a new task" = "Vytvoriť novú úlohu"; +"Edit this event or task" = "Upraviť túto udalosť alebo úlohu"; +"Delete this event or task" = "Odstrániť túto udalosť alebo úlohu"; +"Go to today" = "Prejsť na dnešný deň"; +"Switch to day view" = "Prepnúť na denné zobrazenie"; +"Switch to week view" = "Prepnúť na týždenné zobrazenie"; +"Switch to month view" = "Prepnúť na mesačné zobrazenie"; +"Reload all calendars" = "Aktualizovať všetky kalendáre"; + +/* Tabs */ +"Date" = "Dátum"; +"Calendars" = "Kalendáre"; + +/* Day */ + +"DayOfTheMonth" = "Deň v mesiaci"; +"dayLabelFormat" = "%d/%m/%Y"; +"today" = "Dnes"; + +"Previous Day" = "Predchádzajúci deň"; +"Next Day" = "Nasledujúci deň"; + +/* Week */ + +"Week" = "Týždeň"; +"this week" = "tento týždeň"; + +"Week %d" = "Týždeň %d"; + +"Previous Week" = "Predchádzajúci týždeň"; +"Next Week" = "Nasledujúci týždeň"; + +/* Month */ + +"this month" = "tento mesiac"; + +"Previous Month" = "Predchádzajúci mesiac"; +"Next Month" = "Nasledujúci mesiac"; + +/* Year */ + +"this year" = "tento rok"; + +/* Menu */ + +"Calendar" = "Kalendár"; +"Contacts" = "Kontakty"; + +"New Calendar..." = "Nový kalendár..."; +"Delete Calendar" = "Odstrániť kalendár"; +"Unsubscribe Calendar" = "Odhlásiť odber kalendára"; +"Sharing..." = "Zdieľanie..."; +"Export Calendar..." = "Exportovať kalendár..."; +"Import Events..." = "Importovať udalosti..."; +"Import Events" = "Importovať udalosti"; +"Select an iCalendar file (.ics)." = "Zvoľte súbor iCalendar (*.ics)."; +"Upload" = "Nahrať"; +"Uploading" = "Nahrávanie"; +"Publish Calendar..." = "Publikovať kalendár..."; +"Reload Remote Calendars" = "Aktualizovať vzdialené kalendáre"; +"Properties" = "Vlastnosti"; +"Done" = "Hotovo"; +"An error occurred while importing calendar." = "Počas importovania kalendáru nastala chyba"; +"No event was imported." = "Nebola naimportovaná žiadna udalosť."; +"A total of %{0} events were imported in the calendar." = "Do kalendára bolo naimportovaných %{0} udalostí."; + +"Compose E-Mail to All Attendees" = "Vytvoriť e-mail pre všetkých účastníkov"; +"Compose E-Mail to Undecided Attendees" = "Vytvoriť e-mail pre nerozhodnutých účastníkov"; + +/* Folders */ +"Personal calendar" = "Osobný kalendár"; + +/* Misc */ + +"OpenGroupware.org" = "OpenGroupware.org"; +"Forbidden" = "Zakázané"; + +/* acls */ + +"Access rights to" = "Prítupové práva"; +"For user" = "pre užívateľa"; + +"Any Authenticated User" = "Každý overený užívateľ"; +"Public Access" = "Verejný prístup"; + +"label_Public" = "Verejné"; +"label_Private" = "Súkromné"; +"label_Confidential" = "Dôverné"; + +"label_Viewer" = "Zobraziť všetko"; +"label_DAndTViewer" = "Zobraziť dátum a čas"; +"label_Modifier" = "Upraviť"; +"label_Responder" = "Odpovedať komu"; +"label_None" = "Žiadny"; + +"View All" = "Zobraziť všetko"; +"View the Date & Time" = "Zobraziť dátum a čas"; +"Modify" = "Upraviť"; +"Respond To" = "Odpovedať komu"; +"None" = "Žiadny"; + +"This person can create objects in my calendar." += "Táto osoba môže vytvárať objekty v mojom kalendári."; +"This person can erase objects from my calendar." += "Táto osoba môže odstraňovať objekty z môjho kalendára."; + +/* Button Titles */ + +"Subscribe to a Calendar..." = "Odoberať kalendár..."; +"Remove the selected Calendar" = "Odstrániť zvolený kalendár"; + +"Name of the Calendar" = "Názov kalendára"; + +"new" = "Nový"; +"printview" = "Náhľad tlače"; +"edit" = "Upraviť"; +"delete" = "Odstrániť"; +"proposal" = "Návrh"; +"Save and Close" = "Uložiť a zatvoriť"; +"Close" = "Zatvoriť"; +"Invite Attendees" = "Pozvat účastníkov"; +"Attach" = "Pripojiť"; +"Update" = "Aktualizácia"; +"Cancel" = "Storno"; +"show_rejected_apts" = "Ukázať odmietnuté schôdzky"; +"hide_rejected_apts" = "Skryť odmietnuté schôdzky"; + + +/* Schedule */ + +"Schedule" = "Plán"; +"No appointments found" = "Neboli nájdené žiadne schôdzky"; +"Meetings proposed by you" = "Schôdzky navrhnuté Vami"; +"Meetings proposed to you" = "Schôdzky navrhnuté Vám"; +"sched_startDateFormat" = "%d/%m %H:%M"; +"action" = "Akcia"; +"accept" = "Prijať"; +"decline" = "Odmietnuť"; +"more attendees" = "Viac účastníkov"; +"Hide already accepted and rejected appointments" = "Skryť prijaté a odmietnuté schôdzky"; +"Show already accepted and rejected appointments" = "Zobraziť prijaté a odmietnuté schôdzky"; + + +/* Appointments */ + +"Appointment viewer" = "Zobraziť schôdzky"; +"Appointment editor" = "Editovať schôdzky"; +"Appointment proposal" = "Navrhnúť schôdzku"; +"Appointment on" = "Schôdzka na"; +"Start:" = "Začiatok:"; +"End:" = "Koniec:"; +"Due Date:" = "Dátum splnenia:"; +"Title:" = "Názov:"; +"Calendar:" = "Kalendár:"; +"Name" = "Meno"; +"Email" = "E-Mail"; +"Status:" = "Stav:"; +"% complete" = "% hotovo"; +"Location:" = "Miesto:"; +"Priority:" = "Priorita:"; +"Privacy" = "Súkromie"; +"Cycle" = "Cyklus opakovania"; +"Cycle End" = "Koniec cyklu"; +"Categories" = "Kategórie"; +"Classification" = "Klasifikácia"; +"Duration" = "Trvanie"; +"Attendees:" = "Účastníci:"; +"Resources" = "Zdroje"; +"Organizer:" = "Organizátor:"; +"Description:" = "Popis:"; +"Document:" = "Dokument:"; +"Category:" = "Kategória:"; +"Repeat:" = "Opakovanie:"; +"Reminder:" = "Pripomenutie:"; +"General:" = "Hlavný:"; +"Reply:" = "Odpoveď:"; + +"Target:" = "Cieľ:"; + +"attributes" = "atribúty"; +"attendees" = "účastníci"; +"delegated from" = "delegované od"; + +/* checkbox title */ +"is private" = "je súkromný/á"; +/* classification */ +"Public" = "Verejný"; +"Private" = "Súkromný"; +/* text used in overviews and tooltips */ +"empty title" = "Prázdný názov"; +"private appointment" = "Súkromná schôdzka"; + +"Change..." = "Zmeniť..."; + +/* Appointments (participation state) */ + +"partStat_NEEDS-ACTION" = "Potvrdím neskôr"; +"partStat_ACCEPTED" = "Zúčastním sa"; +"partStat_DECLINED" = "Nezúčastním sa"; +"partStat_TENTATIVE" = "Potvrdzujem nezáväzne"; +"partStat_DELEGATED" = "Delegujem"; +"partStat_OTHER" = "Ostatní"; + +/* Appointments (error messages) */ + +"Conflicts found!" = "Boli nájdené konflikty!"; +"Invalid iCal data!" = "Neplatné iCal údaje!"; +"Could not create iCal data!" = "Nebolo možné vytvoriť iCal údaje!"; + +/* Searching */ + +"view_all" = "Všetky"; +"view_today" = "Dnešné udalosti"; +"view_next7" = "Nasledujúcich 7 dní"; +"view_next14" = "Nasledujúcich 14 dní"; +"view_next31" = "Nasledujúcich 31 dní"; +"view_thismonth" = "Tento mesiac"; +"view_future" = "Všetky budúce udalosti"; +"view_selectedday" = "Zvolený deň"; + +"View:" = "Zobraziť:"; +"Title or Description" = "Názov alebo popis"; + +"Search" = "Vyhľadať"; +"Search attendees" = "Vyhľadať účastníkov"; +"Search resources" = "Vyhľadať zdroje"; +"Search appointments" = "Vyhľadať schôdzky"; + +"All day Event" = "Celodenná udalosť"; +"check for conflicts" = "Skontrolovať konflikty"; + +"Browse URL" = "Preskúmať URL"; + +"newAttendee" = "Pridať účastníka"; + +/* calendar modes */ + +"Overview" = "Prehľad"; +"Chart" = "Tabuľka"; +"List" = "Zoznam"; +"Columns" = "Stĺpce"; + +/* Priorities */ + +"prio_0" = "Nešpecifikovaná"; +"prio_1" = "Vysoká"; +"prio_2" = "Vysoká"; +"prio_3" = "Vysoká"; +"prio_4" = "Vysoká"; +"prio_5" = "Normálna"; +"prio_6" = "Nízka"; +"prio_7" = "Nízka"; +"prio_8" = "Nízka"; +"prio_9" = "Nízka"; + +/* access classes (privacy) */ +"PUBLIC_vevent" = "Verejná udalosť"; +"CONFIDENTIAL_vevent" = "Dôverná udalosť"; +"PRIVATE_vevent" = "Súkromná udalosť"; +"PUBLIC_vtodo" = "Verejná úloha"; +"CONFIDENTIAL_vtodo" = "Dôverná úloha"; +"PRIVATE_vtodo" = "Osobná úloha"; + +/* status type */ +"status_" = "Nešpecifikovaný"; +"status_NOT-SPECIFIED" = "Nešpecifikovaný"; +"status_TENTATIVE" = "Nezáväzný"; +"status_CONFIRMED" = "Potvrdený"; +"status_CANCELLED" = "Zrušený"; +"status_NEEDS-ACTION" = "Vyžaduje akciu"; +"status_IN-PROCESS" = "Prebieha"; +"status_COMPLETED" = "Hotovo"; + +/* Cycles */ + +"cycle_once" = "bez opakovania"; +"cycle_daily" = "denne"; +"cycle_weekly" = "týždenne"; +"cycle_2weeks" = "každý druhý týždeň"; +"cycle_4weeks" = "každý štvrtý týždeň"; +"cycle_monthly" = "mesačne"; +"cycle_weekday" = "každý pracovný deň"; +"cycle_yearly" = "ročne"; + +"cycle_end_never" = "nekonečné opakovanie"; +"cycle_end_until" = "opakovanie do"; + +"Recurrence pattern" = "Vzor opakovania"; +"Range of recurrence" = "Rozsah opakovania"; + +"Repeat" = "Opakovanie"; +"Daily" = "Denné"; +"Weekly" = "Týždenné"; +"Monthly" = "Mesačné"; +"Yearly" = "Ročné"; +"Every" = "Každých"; +"Days" = "Dní"; +"Week(s)" = "Týždňov"; +"On" = "V"; +"Month(s)" = "Mesiacov"; +"The" = "Ten"; +"Recur on day(s)" = "Opakovať v dňoch"; +"Year(s)" = "rokoch"; +"cycle_of" = "s"; +"No end date" = "Bez dátumu ukončenia"; +"Create" = "Vytvoriť"; +"appointment(s)" = "schôdzku/y"; +"Repeat until" = "Opakovať do"; + +"First" = "Prvý"; +"Second" = "Druhý"; +"Third" = "Tretí"; +"Fourth" = "Štvrtý"; +"Fift" = "Piaty"; +"Last" = "Posledný"; + +/* Appointment categories */ + +"category_none" = "Žiadny"; +"category_labels" = "Výročie,Narodeniny,Obchod,Hovory,Klienti,Súťaže,Zákazník,Obľúbené,Sledovanie,Darčeky,Voľno,Nápady,Stretnutie,Problémy,Rôzne,Osobné,Projekty,Štátne sviatky,Stav,Dodávatelia,Cesta,Dovolenka"; + +"repeat_NEVER" = "Neopakuje sa"; +"repeat_DAILY" = "Denne"; +"repeat_WEEKLY" = "Týždenne"; +"repeat_BI-WEEKLY" = "Každé dva týždne"; +"repeat_EVERY WEEKDAY" = "Každý pracovný deň"; +"repeat_MONTHLY" = "Mesačne"; +"repeat_YEARLY" = "Ročne"; +"repeat_CUSTOM" = "Vlastný..."; + +"reminder_NONE" = "Bez pripomenutia"; +"reminder_5_MINUTES_BEFORE" = "5 minút pred"; +"reminder_10_MINUTES_BEFORE" = "10 minút pred"; +"reminder_15_MINUTES_BEFORE" = "15 minút pred"; +"reminder_30_MINUTES_BEFORE" = "30 minút pred"; +"reminder_45_MINUTES_BEFORE" = "45 minút pred"; +"reminder_1_HOUR_BEFORE" = "1 hodinu pred"; +"reminder_2_HOURS_BEFORE" = "2 hodiny pred"; +"reminder_5_HOURS_BEFORE" = "5 hodín pred"; +"reminder_15_HOURS_BEFORE" = "15 hodín pred"; +"reminder_1_DAY_BEFORE" = "1 deň pred"; +"reminder_2_DAYS_BEFORE" = "2 dni pred"; +"reminder_1_WEEK_BEFORE" = "1 týždeň pred"; +"reminder_CUSTOM" = "Vlastný..."; + +"reminder_MINUTES" = "minúty"; +"reminder_HOURS" = "hodiny"; +"reminder_DAYS" = "dni"; +"reminder_BEFORE" = "pred"; +"reminder_AFTER" = "po"; +"reminder_START" = "začiatku/om udalosti"; +"reminder_END" = "konci udalosti"; +"Reminder Details" = "Podrobnosti pripomenutia"; + +"Choose a Reminder Action" = "Zvoliť akciu"; +"Show an Alert" = "Zobraziť výstrahu"; +"Send an E-mail" = "Poslať e-mail"; +"Email Organizer" = "E-mail organizátorovi"; +"Email Attendees" = "E-mail účastníkom"; + +"zoom_400" = "400%"; +"zoom_200" = "200%"; +"zoom_100" = "100%"; +"zoom_50" = "50%"; +"zoom_25" = "25%"; + +/* transparency */ + +"Show Time as Free" = "Čas zobraziť ako voľný"; + +/* validation errors */ + +validate_notitle = "Názov nebol nastavený, pokračovať?"; +validate_invalid_startdate = "Chybný dátum začiatku!"; +validate_invalid_enddate = "Chybný dátum konca!"; +validate_endbeforestart = "Zadaný dátum konca je pred začiatkom udalosti."; + +"Events" = "Události"; +"Tasks" = "Úlohy"; +"Show completed tasks" = "Zobraziť dokončené úlohy"; + +/* tabs */ +"Task" = "Úloha"; +"Event" = "Udalosť"; +"Recurrence" = "Opakovanie"; + +/* toolbar */ +"New Event" = "Nová udalosť"; +"New Task" = "Nová úloha"; +"Edit" = "Upraviť"; +"Delete" = "Odstrániť"; +"Go to Today" = "Dnešný deň"; +"Day View" = "Deň"; +"Week View" = "Týždeň"; +"Month View" = "Mesiac"; +"Reload" = "Aktualizovať"; + +"eventPartStatModificationError" = "Status vašej účasti nemohol byť zmenený."; + +/* menu */ +"New Event..." = "Nová udalosť..."; +"New Task..." = "Nová úloha..."; +"Edit Selected Event..." = "Upraviť označenú udalosť..."; +"Delete Selected Event" = "Odstrániť označenú udalosť"; +"Select All" = "Vybrať všetko"; +"Workweek days only" = "Len pracovné dni"; +"Tasks in View" = "Zobrazené úlohy"; + +"eventDeleteConfirmation" = "Nasledujúca udalosť(i) bude odstránená:\n%{0}\nChcete pokračovať?"; +"taskDeleteConfirmation" = "Odstránenie nasledujúcej úlohy(oh) je nevratné.\n%{0}\nChcete pokračovať?"; + +"You cannot remove nor unsubscribe from your personal calendar." += "Nemôžete odstrániť ani sa odhlásiť z odoberania svojho vlastného kalendára."; +"Are you sure you want to delete the calendar \"%{0}\"?" += "Naozaj chcete odstrániť kalendár \"%{0}\"?"; + +/* Legend */ +"Participant" = "Účastník"; +"Optional Participant" = "Nepovinný účastník"; +"Non Participant" = "Na vedomie"; +"Chair" = "Predsedajúci"; + +"Needs action" = "Vyžaduje akciu"; +"Accepted" = "Zúčastní sa"; +"Declined" = "Nezúčastní sa"; +"Tentative" = "Nezáväzne"; + +"Free" = "Voľno"; +"Busy" = "Nie je voľno"; +"Maybe busy" = "Možno nie je voľno"; +"No free-busy information" = "Bez informácií"; + +/* FreeBusy panel buttons and labels */ +"Suggest time slot:" = "Navrhnúť čas"; +"Zoom:" = "Priblížiť:"; +"Previous slot" = "Predchádzajúci čas"; +"Next slot" = "Nasledujúci čas"; +"Previous hour" = "Predchádzajúca hodina"; +"Next hour" = "Nasledujúca hodina"; +"Work days only" = "Len pracovné dni"; +"The whole day" = "Celý deň"; +"Between" = "medzi"; +"and" = "a"; + +"A time conflict exists with one or more attendees.\nWould you like to keep the current settings anyway?" += "Medzi účastníkmi dochádza k časovému konfliktu.\nPonecháte súčasné nastavenie aj napriek tomu?"; + +/* apt list */ +"Title" = "Názov"; +"Start" = "Začiatok"; +"End" = "Koniec"; +"Due Date" = "Platí do"; +"Location" = "Miesto"; + +"(Private Event)" = "(Súkromná udalosť)"; + +vevent_class0 = "(Verejná udalosť)"; +vevent_class1 = "(Súkromná udalosť)"; +vevent_class2 = "(Dôverná udalosť)"; + +"Priority" = "Priorita"; +"Category" = "Kategória"; + +vtodo_class0 = "(Verejná úloha)"; +vtodo_class1 = "(Súkromná úloha)"; +vtodo_class2 = "(Dôverná úloha)"; + +"closeThisWindowMessage" = "Dakujeme! Teraz môžete okno zatvoriť alebo sa pozrieť na vaše "; +"Multicolumn Day View" = "Viacstĺpcové denné zobrazenie"; + +"Please select an event or a task." = "Vyberte prosím udalosť alebo úlohu."; + +"editRepeatingItem" = "Položka, ktorú upravujete, se opakuje. Chcete opraviť všetky opakovania alebo len toto?"; +"button_thisOccurrenceOnly" = "Len toto opakovanie"; +"button_allOccurrences" = "Všetky opakovania"; + +/* Properties dialog */ +"Name:" = "Názov:"; +"Color:" = "Farba:"; + +"Include in free-busy" = "Zahrnúť do voľný-obsadený"; + +"Synchronization" = "Synchronizácia"; +"Synchronize" = "Synchronizovať"; +"Tag:" = "Štítok:"; + +"Display" = "Zobrazenie"; +"Show alarms" = "Zobraziť pripomenutie"; +"Show tasks" = "Zobraziť úlohy"; + +"Notifications" = "Oznámenia"; +"Receive a mail when I modify my calendar" = "Informuj emailom keď upravím môj kalendár"; +"Receive a mail when someone else modifies my calendar" = "Informuj emailom keď niekto iný upraví môj kalendár"; +"When I modify my calendar, send a mail to:" = "Keď upravím svoj kalendár, pošli email:"; + +"Links to this Calendar" = "Odkazy na tento kalendár"; +"Authenticated User Access" = "Prístup pre overeného užívateľa"; +"CalDAV URL" = "CalDAV url"; +"WebDAV ICS URL" = "WebDAV ICS URL"; +"WebDAV XML URL" = "WebDAV XML URL"; + +/* Error messages */ +"dayFieldInvalid" = "V políčku Dni zadajte číselnú hodnotu väčšiu alebo rovnú 1."; +"weekFieldInvalid" = "V políčku Týždeň zadajte číselnú hodnotu väčšiu alebo rovnú 1."; +"monthFieldInvalid" = "V políčku Mesiac zadajte číselnú hodnotu väčšiu alebo rovnú 1."; +"monthDayFieldInvalid" = "V políčku Deň v mesiaci zadajte číselnú hodnotu väčšiu alebo rovnú 1."; +"yearFieldInvalid" = "V políčku Rok zadajte číselnú hodnotu väčšiu alebo rovnú 1."; +"appointmentFieldInvalid" = "V políčku Pripomenutie zadajte číselnú hodnotu väčšiu alebo rovnú 1."; +"recurrenceUnsupported" = "Tento typ opakovania nie je podporovaný."; +"Please specify a calendar name." = "Prosím zadajte meno kalendára."; +"tagNotDefined" = "Ak chcete synchronizovať tento kalendár, musíte zadať jeho štítok."; +"tagAlreadyExists" = "Zadaný štítok je už priradený inému kalendáru."; +"tagHasChanged" = "Ak zmeníte štítok svojho kalendára, budete musieť znovu načítať údaje do svojho mobilného zariadenia.\nPokračovať?"; +"tagWasAdded" = "Ak chcete synchronizovať tento kalendár, budete musieť znovu načítať údaje do svojho mobilného zariadenia.\nPokračovať?"; +"tagWasRemoved" = "Ak odstránite v tomto kalendári synchronizáciu, budete musieť znovu načítať údaje do svojho mobilného zariadenia.\nPokračovať?"; +"DestinationCalendarError" = "Zdrojový a cieľový kalendár sú rovnaké. Prosím, skúste kopírovať iný kalendár."; +"EventCopyError" = "Kopírovanie sa nepodarilo. Prosím, skúste kopírovať iný kalendár."; + +"Open Task..." = "Otvoriť úlohu..."; +"Mark Completed" = "Označiť ako dokončené"; +"Delete Task" = "Odstrániť úlohu"; +"Delete Event" = "Odstrániť udalosť"; +"Copy event to my calendar" = "Kopírovať udalosť do môjho kalendára"; +"View Raw Source" = "Zobrazit zdroj"; + +"Subscribe to a web calendar..." = "Odoberať vzdialený kalendár na webe"; +"URL of the Calendar" = "Adresa vzdialeného kalendára na webe"; +"Web Calendar" = "Vzdialený kalendár na webe"; +"Reload on login" = "Aktualizovať pri prihlásení"; +"Invalid number." = "Neplatné číslo."; diff --git a/UI/Scheduler/SpanishSpain.lproj/Localizable.strings b/UI/Scheduler/SpanishSpain.lproj/Localizable.strings index d3ba8d3c5..aa16c2d5f 100644 --- a/UI/Scheduler/SpanishSpain.lproj/Localizable.strings +++ b/UI/Scheduler/SpanishSpain.lproj/Localizable.strings @@ -493,6 +493,7 @@ vtodo_class2 = "(Tarea confidencial)"; "Show alarms" = "Muestra alarmas"; "Show tasks" = "Muestra tareas"; +"Notifications" = "Notificaciones"; "Receive a mail when I modify my calendar" = "Recibir un correo electrónico cuando modifico mi calendario"; "Receive a mail when someone else modifies my calendar" = "Recibir un correo electrónico cuando alguien distinto modifica mi calendario"; "When I modify my calendar, send a mail to:" = "Cuando modifico mi calendario, envir un correo electrónico a:"; diff --git a/UI/Scheduler/UIxAppointmentActions.m b/UI/Scheduler/UIxAppointmentActions.m index b180a3161..08d6c9f9c 100644 --- a/UI/Scheduler/UIxAppointmentActions.m +++ b/UI/Scheduler/UIxAppointmentActions.m @@ -104,6 +104,7 @@ if ([event hasRecurrenceRules]) [event updateRecurrenceRulesUntilDate: end]; + [event setLastModified: [NSCalendarDate calendarDate]]; [co saveComponent: event]; response = [self responseWith204]; diff --git a/UI/Scheduler/UIxAppointmentEditor.h b/UI/Scheduler/UIxAppointmentEditor.h index daf7f583a..f3482ce1d 100644 --- a/UI/Scheduler/UIxAppointmentEditor.h +++ b/UI/Scheduler/UIxAppointmentEditor.h @@ -1,6 +1,6 @@ /* UIxAppointmentEditor.h - this file is part of SOGo * - * Copyright (C) 2007-2009 Inverse inc. + * Copyright (C) 2007-2012 Inverse inc. * * Author: Wolfgang Sourdeau * diff --git a/UI/Scheduler/UIxCalFolderActions.m b/UI/Scheduler/UIxCalFolderActions.m index e73268f4d..862e08496 100644 --- a/UI/Scheduler/UIxCalFolderActions.m +++ b/UI/Scheduler/UIxCalFolderActions.m @@ -59,12 +59,14 @@ { SOGoAppointmentFolder *folder; NSMutableDictionary *rc; - WORequest *request; - WOResponse *response; - NSString *fileContent; - id data; iCalCalendar *additions; - int imported; + NSString *fileContent; + WOResponse *response; + WORequest *request; + NSArray *cals; + id data; + + int i, imported; imported = 0; rc = [NSMutableDictionary dictionary]; @@ -86,8 +88,13 @@ if (fileContent && [fileContent length] && [fileContent hasPrefix: @"BEGIN:"]) { - additions = [iCalCalendar parseSingleFromSource: fileContent]; - imported = [folder importCalendar: additions]; + cals = [iCalCalendar parseFromSource: fileContent]; + + for (i = 0; i < [cals count]; i++) + { + additions = [cals objectAtIndex: i]; + imported += [folder importCalendar: additions]; + } } [rc setObject: [NSNumber numberWithInt: imported] diff --git a/UI/Scheduler/UIxCalListingActions.m b/UI/Scheduler/UIxCalListingActions.m index 8ef47f070..cbb0b0087 100644 --- a/UI/Scheduler/UIxCalListingActions.m +++ b/UI/Scheduler/UIxCalListingActions.m @@ -211,11 +211,11 @@ static NSArray *tasksFields = nil; user = [context activeUser]; userLogin = [user login]; + title = [request formValueForKey: @"search"]; param = [request formValueForKey: @"filterpopup"]; if ([param length]) { [self _setupDatesWithPopup: param andUserTZ: userTimeZone]; - title = [request formValueForKey: @"search"]; } else { @@ -723,6 +723,11 @@ _userStateInEvent (NSArray *event) if (eventEnd > endsSecs) eventEnd = endsSecs; + if (eventEnd < startSecs) + // The event doesn't end in the covered period. + // This special case occurs with a DST change. + return; + userState = _userStateInEvent (event); while (currentDayStart + dayLength < eventEnd) { diff --git a/UI/Scheduler/UIxComponentEditor.h b/UI/Scheduler/UIxComponentEditor.h index a38fb7126..2a9f64910 100644 --- a/UI/Scheduler/UIxComponentEditor.h +++ b/UI/Scheduler/UIxComponentEditor.h @@ -1,6 +1,6 @@ /* UIxComponentEditor.h - this file is part of SOGo * - * Copyright (C) 2006-2010 Inverse inc. + * Copyright (C) 2006-2012 Inverse inc. * * Author: Wolfgang Sourdeau * diff --git a/UI/Scheduler/UIxComponentEditor.m b/UI/Scheduler/UIxComponentEditor.m index d53929de0..9aef4cb05 100644 --- a/UI/Scheduler/UIxComponentEditor.m +++ b/UI/Scheduler/UIxComponentEditor.m @@ -1,6 +1,6 @@ /* UIxComponentEditor.m - this file is part of SOGo * - * Copyright (C) 2006-2011 Inverse inc. + * Copyright (C) 2006-2012 Inverse inc. * * Author: Wolfgang Sourdeau * Francis Lachapelle @@ -1462,14 +1462,12 @@ RANGE(2); ////////////////////////////////// JUNK //////////////////////////////////////// - (NSArray *) cycles { - NSBundle *bundle; NSString *path; static NSArray *cycles = nil; if (!cycles) { - bundle = [NSBundle bundleForClass:[self class]]; - path = [bundle pathForResource: @"cycles" ofType: @"plist"]; + path = [[self componentBundle] pathForResource: @"cycles" ofType: @"plist"]; NSAssert(path != nil, @"Cannot find cycles.plist!"); cycles = [[NSArray arrayWithContentsOfFile:path] retain]; NSAssert(cycles != nil, @"Cannot instantiate cycles from cycles.plist!"); @@ -2395,12 +2393,7 @@ RANGE(2); { ownerAttendee = [component userAsAttendee: ownerUser]; if (ownerAttendee) - { - if ([[ownerAttendee rsvp] isEqualToString: @"true"]) - rc = 1; - else - rc = 2; - } + rc = 1; } return rc; diff --git a/UI/Templates/AdministrationUI/UIxAdministrationFilterPanel.wox b/UI/Templates/AdministrationUI/UIxAdministrationFilterPanel.wox index 4c8b24427..705241c1b 100644 --- a/UI/Templates/AdministrationUI/UIxAdministrationFilterPanel.wox +++ b/UI/Templates/AdministrationUI/UIxAdministrationFilterPanel.wox @@ -5,17 +5,16 @@ xmlns:const="http://www.skyrix.com/od/constant" xmlns:label="OGo:label" > - - -
+
+ - - + diff --git a/UI/Templates/Appointments/SOGoAptMailReceipt.wox b/UI/Templates/Appointments/SOGoAptMailReceipt.wox index f574903c3..4ff295e9a 100644 --- a/UI/Templates/Appointments/SOGoAptMailReceipt.wox +++ b/UI/Templates/Appointments/SOGoAptMailReceipt.wox @@ -23,8 +23,8 @@ h1, dd, .dl-list dt { margin-left: 130px; }

-
-
+
+
diff --git a/UI/Templates/ContactsUI/UIxContactsFilterPanel.wox b/UI/Templates/ContactsUI/UIxContactsFilterPanel.wox index c7e87d2d3..672ce6e24 100644 --- a/UI/Templates/ContactsUI/UIxContactsFilterPanel.wox +++ b/UI/Templates/ContactsUI/UIxContactsFilterPanel.wox @@ -5,20 +5,20 @@ xmlns:const="http://www.skyrix.com/od/constant" xmlns:label="OGo:label" > - - -
+
+ - - + +
diff --git a/UI/Templates/MailPartViewers/UIxMailPartICalViewer.wox b/UI/Templates/MailPartViewers/UIxMailPartICalViewer.wox index 9bfaad5db..12fca2152 100644 --- a/UI/Templates/MailPartViewers/UIxMailPartICalViewer.wox +++ b/UI/Templates/MailPartViewers/UIxMailPartICalViewer.wox @@ -193,62 +193,46 @@
- - - - - +
+
:
+
+ + + + + + + + + + + + + + + + +
-
- - - - - - - - - - - - - - -
: - - - - - - - - - - - - - - - - - - -
: - : +
-
: + +
:
-
( , )
-
+
-
: - -
+ +
:
+
+
+
diff --git a/UI/Templates/MailerUI/UIxMailFilterPanel.wox b/UI/Templates/MailerUI/UIxMailFilterPanel.wox index 83a774a3f..a521b664a 100644 --- a/UI/Templates/MailerUI/UIxMailFilterPanel.wox +++ b/UI/Templates/MailerUI/UIxMailFilterPanel.wox @@ -5,25 +5,24 @@ xmlns:const="http://www.skyrix.com/od/constant" xmlns:label="OGo:label" > - - -
+
+ - - + diff --git a/UI/Templates/MailerUI/UIxMailMainFrame.wox b/UI/Templates/MailerUI/UIxMailMainFrame.wox index 30c93a901..c0438bb64 100644 --- a/UI/Templates/MailerUI/UIxMailMainFrame.wox +++ b/UI/Templates/MailerUI/UIxMailMainFrame.wox @@ -7,7 +7,7 @@ xmlns:label="OGo:label" className="UIxPageFrame" title="title" - const:userDefaultsKeys="SOGoMailMessageCheck,SOGoMailSortByThreads,SOGoMailListViewColumnsOrder" + const:userDefaultsKeys="SOGoMailMessageCheck,SOGoMailSortByThreads,SOGoMailListViewColumnsOrder,SOGoMailDisplayRemoteInlineImages" const:userSettingsKeys="Mail" const:jsFiles="dtree.js,MailerUIdTree.js,SOGoAutoCompletion.js,SOGoResizableTable.js,SOGoMailDataSource.js,SOGoDataTable.js,jquery-ui.js">