Merge branch 'master' into feature-gdpr

This commit is contained in:
smizrahi
2023-12-20 18:01:40 +01:00
379 changed files with 2817 additions and 1217 deletions
+81
View File
@@ -2,6 +2,87 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [5.9.1](https://github.com/Alinto/sogo/compare/SOGo-5.9.0...SOGo-5.9.1) (2023-12-12)
### Features
* **addressbook:** Add global address book autocomplete on vlist ([11ad203](https://github.com/Alinto/sogo/commit/11ad203388ad33a22bd300047745869a27872cd9) [0b1f2b0](https://github.com/Alinto/sogo/commit/0b1f2b0405410628cb7ba8602b9286d71256d8e6) [0560efd](https://github.com/Alinto/sogo/commit/0560efd1f6a94bcb256d970ebe5535954e36cafe), [f85c531](https://github.com/Alinto/sogo/commit/f85c53190c38c4e28536f78e43623f6776248291))
* **core:** Add mobile provisioning download for Apple's devices ([19915e3](https://github.com/Alinto/sogo/commit/19915e3dffc14c90b03277f9f97b4e6b1158aa87) [6d16ee7](https://github.com/Alinto/sogo/commit/6d16ee798863a7f196c14915c47888adf0758f1a) [d38cc86](https://github.com/Alinto/sogo/commit/d38cc86d29ffce580bf26dd278a6b68556471c14) [cd50ee0](https://github.com/Alinto/sogo/commit/cd50ee017656f3e6cfd46cff7147258d4893706b) [65f8336](https://github.com/Alinto/sogo/commit/65f8336255577566282039f4058fe4f3c38a16d4) [4fe01f9](https://github.com/Alinto/sogo/commit/4fe01f96d73690bf1a2d60755bb552d25324ccaf) [a273f7a](https://github.com/Alinto/sogo/commit/a273f7aca5df120a50af0486161880040ee20519))
* **core:** add SOGoDisableExport option to disable export for mail, calendar and contacts ([d0b4b50](https://github.com/Alinto/sogo/commit/d0b4b50456cf3e23aa12d5cf7165531a7670edf6))
* **core:** Add SOGoDisableSharingAnyAuthUser option to disable sharing to any user authenticated for mail, contacts and calendar ([e0ef59d](https://github.com/Alinto/sogo/commit/e0ef59d5f212aced72a17e3af9e72a434eedd68e))
* **mail:** Add an option in Preferences to display full email instead of name alone in mailboxes ([2e670f7](https://github.com/Alinto/sogo/commit/2e670f7e6293b703f8cfe23ebf923ce13b463a19))
* **mail:** Add SOGoMailHideInlineAttachments option to hide attachments when inline. Fixes [#5490](https://bugs.sogo.nu/view.php?id=5490). ([f41ab2e](https://github.com/Alinto/sogo/commit/f41ab2ed0c71903b80bda66adc54cc94b0cf70d6) [abce5f4](https://github.com/Alinto/sogo/commit/abce5f42cf4daef721ebf6b48d727eb957e20b14) [aa53524](https://github.com/Alinto/sogo/commit/aa535247513b06804fce666fe20ebcc9bd231c1f) [ca2c5c1](https://github.com/Alinto/sogo/commit/ca2c5c188ed980629f494e5b8e23ba42cdd54f58))
* **password:** Add specials characters to POLICY_MIN_SPECIAL_SYMBOLS ([7d66699](https://github.com/Alinto/sogo/commit/7d666992198e5e91e29081b99443607b1c96d354))
* **preferences:** can set SOGoForwardConstraints to 3 to accept both internal and external domains from SOGoForwardConstraintsDomains ([c872fb4](https://github.com/Alinto/sogo/commit/c872fb4d9c68382431a52181073ba1964cf44c22))
* **reply:** add references header when replying ([b396a27](https://github.com/Alinto/sogo/commit/b396a277f00d879d2c179db780d6f621a9057d0c))
* **ux:** select all button will unselect all if click again ([6e60b10](https://github.com/Alinto/sogo/commit/6e60b107556212123f41d95e4399d9605a4c16f9) [1ae02eb](https://github.com/Alinto/sogo/commit/1ae02ebd708da0a53ae588531e122adddaa7a5de))
### Bug Fixes
* **addressbook:** autocomplete correctly return two contacts from two ldap with same id ([1d3da92](https://github.com/Alinto/sogo/commit/1d3da92bab972ec7ec935eba72128e72387216c0))
* **calendar:** do not let DURATION and DTEND be both present in vevent ([0023a9c](https://github.com/Alinto/sogo/commit/0023a9ce3c4027bb32699efc5529a4a53d7699f6))
* **calendar:** If content is NSData, properly convert it to NSString ([21571ab](https://github.com/Alinto/sogo/commit/21571ab1e000da47b91b3f21bfaba89d1abec71f))
* **calendar:** properly set the start date range for yearly events ([1e8127b](https://github.com/Alinto/sogo/commit/1e8127b46122e83df02c394536950288b0ee16aa))
* **core:** Add cache for CDefaultsSize to avoid spamming SQL request ([87e1240](https://github.com/Alinto/sogo/commit/87e1240ace297645559e698a8c1f1a76b9901895) [81f2d88](https://github.com/Alinto/sogo/commit/81f2d88db362cc21c50858295d0e9d375db61f67))
* **core:** Fix calendar issues with Thunderbird related to vlist exclusion. Fix error log on photo. Closes [#5885](https://bugs.sogo.nu/view.php?id=5885) ([6b08f2e](https://github.com/Alinto/sogo/commit/6b08f2e4decc87ee57609355dee5a6657bca6110))
* **core:** Fix user profile retrieval when using utf8mb4_bin collation - in this case the SQL results may return NSdata instead of NSString. Fixes [#5902](https://bugs.sogo.nu/view.php?id=5902). ([3cd9910](https://github.com/Alinto/sogo/commit/3cd991063805f88a5672b10fbcc04a4149e13e26))
* **hmtl:** prevent html injection of tag form ([7481ccf](https://github.com/Alinto/sogo/commit/7481ccf37087c3f456d7e5a844da01d0f8883098))
* **http:** set correct Accept header when dowloading eml file ([c569ed2](https://github.com/Alinto/sogo/commit/c569ed2d77cf23c274c3dfc7cd3533cf268d09af))
* **mail:** Clean temporary files when mail is sent ([f35a37b](https://github.com/Alinto/sogo/commit/f35a37bbdd2005a63b42f9bab1588ce9a935b112) [d163405](https://github.com/Alinto/sogo/commit/d1634054d6f4dd18bdb82a7903b3bbbceae5b0e8))
* **mail:** Fix duplication of images when saving draft. Fixes [#5888](https://bugs.sogo.nu/view.php?id=5888) ([ee9899f](https://github.com/Alinto/sogo/commit/ee9899fe3d6aa7bf694f959a8e4f09faa39e737a) [9c09485](https://github.com/Alinto/sogo/commit/9c0948518b1e8365d6fadb3fccae1a0257b518ed))
* **scripts:** wrong type for c_value in script for complete unicode coverage ([65374e4](https://github.com/Alinto/sogo/commit/65374e44fc2a861d3a7c9f1f9ba25505601d79f1))
* **sogo-tool:** add protection to expire-sessions if the input is not an integer ([bb943e4](https://github.com/Alinto/sogo/commit/bb943e414d3fc8b71ebb169e31c261cd2dcd6d37))
* **translation:** incorret value causing trouble to transifex ([4b45dc7](https://github.com/Alinto/sogo/commit/4b45dc7584984602071efe99b9638c6231efba8c))
### Localization
* **ar:** Update Arabic translations ([28d883d](https://github.com/Alinto/sogo/commit/28d883dac1ccbafb878b9e13ba38f570f44ea325))
* **bg_BG:** Update Bulgarian translations ([3815bc1](https://github.com/Alinto/sogo/commit/3815bc1c5e6fe37aaad5492c246697fe34e4286d))
* **bs_BA:** Update Bosnian translations ([2afbcbe](https://github.com/Alinto/sogo/commit/2afbcbeaed24571785437aa5af1c092ba129ce97))
* **ca:** Update Catalan translations ([3040543](https://github.com/Alinto/sogo/commit/3040543c797fe9176df048b8a72a2c6f7dbfd3b7))
* **cs:** Update Czech translations ([029a821](https://github.com/Alinto/sogo/commit/029a82143f1d0d82ca8d6a5c9e5a14ac351718bf))
* **cy:** Update Welsh translations ([06a6ed7](https://github.com/Alinto/sogo/commit/06a6ed776824f47e5606c29a162903380e72fbd9))
* **da_DK:** Update Danish translations ([76911fd](https://github.com/Alinto/sogo/commit/76911fd4454c9f0213f11b4e2e95b29010eed9a4))
* **de:** Update German translations ([8a4bc2a](https://github.com/Alinto/sogo/commit/8a4bc2a71642a2a431008c02214ffdd0eb2ace23))
* **es_AR:** Update SpanishArgentina translations ([527fded](https://github.com/Alinto/sogo/commit/527fded19ceaf995963e997659b79c5e1290b8c5))
* **es_ES:** Update SpanishSpain translations ([057a1ba](https://github.com/Alinto/sogo/commit/057a1ba1053f462cd0633b86c3ee86d76acbd6bb))
* **eu:** Update Basque translations ([33f3a1b](https://github.com/Alinto/sogo/commit/33f3a1b716a006df8a28c416fc947e44fc285e37))
* **fi:** Update Finnish translations ([dba2332](https://github.com/Alinto/sogo/commit/dba2332864fa38116615c9b58eb3590fe251a37a))
* **gl:** Change Galician name to Galego ([6eae3f2](https://github.com/Alinto/sogo/commit/6eae3f2b1601033558a791c27bc4e27acf0825e7))
* **gl:** Update Galician translations ([5aa7ebf](https://github.com/Alinto/sogo/commit/5aa7ebf2aefef6e45423b2193c136fadced51375))
* **he:** Update Hebrew translations ([694c21d](https://github.com/Alinto/sogo/commit/694c21de99522733c95304d0e775e81493ff7200))
* **hr_HR:** Update Croatian translations ([715d25d](https://github.com/Alinto/sogo/commit/715d25d40a84b518b1d8f97b4946045a4be761b5))
* **hu:** Update Hungarian translations ([0b22fa6](https://github.com/Alinto/sogo/commit/0b22fa6cd5b55db5d021bbbfcc53d411ff4bb9d7))
* **id_ID:** Update Indonesian translations ([a16d29b](https://github.com/Alinto/sogo/commit/a16d29b70b50eeee14a3ad1b627e8f8a59216461))
* **is:** Update Icelandic translations ([2de6241](https://github.com/Alinto/sogo/commit/2de624122045d9df877f39f665d271056af0fba8))
* **it:** Update Italian translations ([53036b3](https://github.com/Alinto/sogo/commit/53036b323fe65b4bf40c838ff0578fa076bfea93))
* **ja:** Update Japanese translations ([41fb85e](https://github.com/Alinto/sogo/commit/41fb85e6a320b25776ce63672ef4251e932f82f0))
* **kk:** Update Kazakh translations ([2174195](https://github.com/Alinto/sogo/commit/21741954dd2762b3f03c0b5b21b8feb4d826cfb1))
* **lt:** Update Lithuanian translations ([6e9e7f9](https://github.com/Alinto/sogo/commit/6e9e7f98ef379ce26937e00daedfad88383615a4))
* **lv:** Update Latvian translations ([a9ecaed](https://github.com/Alinto/sogo/commit/a9ecaed5fa6fe8fecf08ec0354bbb187824d2fbb))
* **mk_MK:** Update Macedonian translations ([d6c9ecd](https://github.com/Alinto/sogo/commit/d6c9ecdeb0490fa44bc1c444819b5c82ccf89073))
* **nb_NO:** Update NorwegianBokmal translations ([3d5f352](https://github.com/Alinto/sogo/commit/3d5f35211189802ef031be688cadddc2ab684d37))
* **nl:** Update Dutch translations ([402c3d0](https://github.com/Alinto/sogo/commit/402c3d0a1f83d32af2fca2f3e5abafbe8850de08))
* **nn_NO:** Update NorwegianNynorsk translations ([6d270fe](https://github.com/Alinto/sogo/commit/6d270fe7a4bad2253f7e8427be660405460b2139))
* **pl:** Update Polish translations ([c75f210](https://github.com/Alinto/sogo/commit/c75f210864de1a7bb313c1ba21be987143a2f7ca))
* **pt_BR:** Update BrazilianPortuguese translations ([cfab856](https://github.com/Alinto/sogo/commit/cfab85624b3e725f121ea61d181340189e969229))
* **pt:** Update Portuguese translations ([e4f07c4](https://github.com/Alinto/sogo/commit/e4f07c466e195d59f72b934567cb3aa4d18cb9f3))
* **ro_RO:** Update Romanian translations ([d9c716c](https://github.com/Alinto/sogo/commit/d9c716c1b679a792876c9bc7ebed2d530ab8d89f))
* **ru:** Update Russian translations ([3809ec3](https://github.com/Alinto/sogo/commit/3809ec3904a7882239e50c671aa72c9f7f013c62))
* **sk:** Update Slovak translations ([cd7e06c](https://github.com/Alinto/sogo/commit/cd7e06c2ede339d078e54b76b6078523b78383fc))
* **sl_SI:** Update Slovenian translations ([ca21bf4](https://github.com/Alinto/sogo/commit/ca21bf4ce1758717eac8ec961788d067e9428456))
* **sr_ME@latin:** Update Montenegrin translations ([fe7369e](https://github.com/Alinto/sogo/commit/fe7369e427d7cc6f4efb23a78437bd2b2c65e6cd))
* **sr@latin:** Update SerbianLatin translations ([9126cae](https://github.com/Alinto/sogo/commit/9126cae27d49b7f199f2a6b259eb40589b011a55))
* **sr:** Update Serbian translations ([ed444fd](https://github.com/Alinto/sogo/commit/ed444fdc2266888f9d15d557e1ba92896158d870))
* **sv:** Update Swedish translations ([10369aa](https://github.com/Alinto/sogo/commit/10369aa654058b50285ae7239a9356f736c7ac1c))
* **tr_TR:** Update TurkishTurkey translations ([8d1fc1e](https://github.com/Alinto/sogo/commit/8d1fc1e306d926b3efeab2e3017823201254caf0))
* **uk:** Update Ukrainian translations ([0e50d37](https://github.com/Alinto/sogo/commit/0e50d37531d850b46009af2af5049a6b46541da0))
* **zh_CN:** Update ChineseChina translations ([cf87022](https://github.com/Alinto/sogo/commit/cf87022348296b9659e83e3a3985b48d89f5e01f))
* **zh_TW:** Update ChineseTaiwan translations ([fc2a82c](https://github.com/Alinto/sogo/commit/fc2a82c3b0f4b780df3b4d27ad0da78e34f665c6))
## [5.9.0](https://github.com/Alinto/sogo/compare/SOGo-5.8.3...SOGo-5.9.0) (2023-09-27)
+525 -6
View File
@@ -21,7 +21,7 @@ devices with SOGo.
The instructions are based on version {release_version} of SOGo.
The latest version of this guide is available
at https://sogo.nu/downloads/documentation.html.
at https://www.sogo.nu/support.html#/documentation.
Introduction
------------
@@ -693,6 +693,13 @@ Defaults to `NO` when unset.
|S |SOGoDisableSharing
|List of modules where sharing should be disabled, for example `(Mail, Calendar)`. Modules can be `Mail`, `Contacts` and `Calendar`. Default value empty list (sharing enabled for everybody).
|S |SOGoDisableSharingAnyAuthUser
|List of modules where sharing with any authenticated user option should be disabled, for example `(Mail, Calendar)`. Modules can be `Mail`, `Contacts` and `Calendar`. Default value empty list (sharing enabled for everybody).
|S |SOGoDisableExport
|List of modules where export should be disabled, for example `(Mail, Calendar)`. Modules can be `Mail`, `Contacts` and `Calendar`. Default value empty list (export enabled for everybody).
|S |SOGoPasswordChangeEnabled
|Parameter used to allow or not users to change their passwords from
SOGo.
@@ -819,8 +826,17 @@ specified as an array of dictionaries.
|D |SOGoCreateIdentitiesDisabled
|Disable identity creation for users in preferences. If `YES`, users won't be able to add new identities and will allow to change only full name, signature and default identity. Default value is `NO`. Note : If this settings is set to `YES`, it will not be possible to crete auxiliary mail accounts.
<<<<<<< HEAD
|S |SOGoURLEncryptionEnabled
|Enable URL encryption to make SOGo GDPR compatible. Setting this parameter to `YES` will encrypt username in URL. The encryption data are cached to avoid high cpu usage. If the encryption is enabled, the DAV url will change. Default value is `NO`.
||||||| 65f833625
=======
|S |SOGoGlobalAddressBookFirstEntries
|Display first entries in Global Address Book. Default value is `NO`. If source is LDAP, the LDAP overlay `sssvlv` must be enabled on the system for server side sorting.
|S |SOGoGlobalAddressBookFirstEntriesCount
|Number of entries displayed when `SOGoGlobalAddressBookFirstEntries` is enabled. Default value is `100`.
>>>>>>> master
|S |SOGoURLEncryptionPassphrase
|Passphrase for `SOGoURLEncryptionEnabled`. The string must be 128 bits (16 characters). If this settings change, the cache server must be restarted, and the DAV url will change. Default value is `SOGoSuperSecret0`.
@@ -2277,12 +2293,14 @@ Defaults to `NO` when unset.
|D |SOGoForwardConstraints
|Parameter used to set constraints on possible addresses used when
automatically forwarding mails. When set to `0` (default), no constraint
is enforced. When set to `1`, only internal domains can be used. When
set to `2`, only external domains can be used.
is enforced. When set to `1`, only internal domains can be used.
When set to `2`, only external domains defined in `SOGoForwardConstraintsDomains`
can be used. When set to `3`, internal domains and other domains defined
in `SOGoForwardConstraintsDomains` can be used.
|D |SOGoForwardConstraintsDomains
|Parameter used to set which domains are allowed as external domains
when SOGoForwardConstraints is set to `2`. For example, setting:
|Parameter used to set which external domains are allowed
when SOGoForwardConstraints is set to `2` or `3`. For example, setting:
SOGoForwardConstraintsDomains = ("gmail.com", "googlemail.com");
@@ -2485,6 +2503,13 @@ Defaults to `NO` when unset.
Defaults to `inline` when unset.
|U |SOGoMailDisplayFullEmail
|Show recipients or sender full email in mailboxes if set to `YES`. Default value is `NO`.
|U |SOGoMailHideInlineAttachments
|Hide inline message as attachements if set to `YES`. Default value is `NO`.
|U |SOGoMailCustomFullName
|The string to use as full name when composing an email, if
_SOGoMailCustomFromEnabled_ is set in the user's domain defaults.
@@ -3210,7 +3235,7 @@ your site. However, be aware that in order to use the SOGo Integrator
plug in, you will need to repackage it with specific modifications.
Please refer to the documentation published online:
https://sogo.nu/downloads/documentation.html
https://www.sogo.nu/support.html#/documentation
If you only use the SOGo Connector plug in, you can still easily access
your data.
@@ -3247,6 +3272,12 @@ http://127.0.0.1/SOGo/dav/jdoe/
Note that the trailing slash is important for the old Apple iCal 3 application.
Since SOGo 5.9.1, calendar can be installed using provisioning profiles. On the calendar interface next to the calendar name (eg `Personal`), click on the three dots button and click on `Download iOS - MacOS configuration profile`.
You have to add the profile to your device :
* Go to Settings / Profiles / Click on + / Continue
* Type your SOGo account password and click on install
Apple AddressBook
~~~~~~~~~~~~~~~~~
@@ -3290,6 +3321,12 @@ The virtual host should be defined like:
This configuration is also required if you want to configure a CardDAV
account on an Apple iOS device (version 4.0 and later).
Since SOGo 5.9.1, address book can be installed using provisioning profiles. On the address book interface next to the address book name (eg `Personal`), click on the three dots button and click on `Download iOS - MacOS configuration profile`.
You have to add the profile to your device :
* Go to Settings / Profiles / Click on + / Continue
* Type your SOGo account password and click on install
Microsoft ActiveSync
~~~~~~~~~~~~~~~~~~~~
@@ -3300,6 +3337,488 @@ any mobile devices that support Microsoft ActiveSync. Microsoft Outlook
The Microsoft ActiveSync server URL is generally something
like: `http://127.0.0.1/Microsoft-Server-ActiveSync`.
Using sogo-tool
---------------
The command _sogo-tool_ allows to do some operations on database and sieve filter. It is included with
the sogo package on Debian/Ubuntu but must be installed manually on RHEl/CentOS:
yum install sogo-tool
*_WARNING_: Use sogo-tool with full awareness of what you are doing. This is an admin tool that can cause loss of data
or completely make the webmail unusable by a user.*
sogo-tool backup/restore
~~~~~~~~~~~~~~~~~~~~~~~~
The backup tool saves the information of a user into a file. The information saved are its preferences, its events and its contacts.
sogo-tool backup directory ALL|user1 [user2] ...
* First argument, *directory* must be a path, only the last subdirectory will be created, the previous ones must exist.
* Second argument is *ALL* to backup all users or put each user space-separated.
* Each user's info will take one file, the filename will be the username.
* The files are readable but in a specific format for _sogo-tool restore_.
Example:
----
sogo-tool backup /tmp/foo ALL # Will save all users into /tmp/foo
sogo-tool backup /etc/sogo_backup/foo user1 user2 # Will save only user1 and user2. The directory /etc/sogo_backup must exist.
----
Using the files produced by the backup, you can restore all or some information of a user with the _restore_ command:
sogo-tool restore [-l|-p|-f/-F folder/ALL] [-c credentialFile] directory user
* First argument must be one of the four mode options *-l*, *-p*, *-f* or *-F*.
* Second, optional, is *-c* with the credential file. Only useful with *-p* mode.
* *directory* is the path where the backup file is.
* *user* is the name of the backup file, which is the username if you use the _backup_ tool.
The differents mode are:
* *-l* will only list the folders (meaning calendar and address book) that would be restored with *-f* or *-F*.
Example:
----
sogo-tool restore -l /tmp/backup user1
----
Result:
----
Calendar/60C8-65323D80-7-4D9F7D80 (new_calendar)
Calendar/personal (Personal Calendar)
Contacts/personal (Personal Address Book)
----
* *-p* will restore the user's preferences. If the user has an active sieve script (filter, vacation, forward...) you must provide a credential file with
the parameters *-c*. The credential file is a simple one-line file that contains the "username:password" of an admin account of your imap/sieve server.
Example:
----
sogo-tool restore -p /tmp/backup user1
sogo-tool restore -p -c /var/sogo/cred /tmp/backup user1
----
* *-f* will restore the events/contacts of folders (calendar and address book) from the backup file that don't exist in the database. If the event/contact
was deleted but is in the backup file, it will be restored. If the event/contact exist, nothing will be done even if it has been modified compared to the
backup file. If a whole folder has been deleted but is in the backup file, it will be restored. *-f* expect a value that can be ALL to restore all folders,
or the name of the folder to restore. You can list them with the *-l* mode.
Example:
----
sogo-tool restore -f ALL /tmp/backup user1
sogo-tool restore -f "Contacts/personal" tmp/backup user1
sogo-tool restore -f "Calendar/60C8-65323D80-7-4D9F7D80" tmp/backup user1
----
The commands will either prints out nothing or any events/contacts restored:
----
restoring record '60CA-65323D00-1-680B0A00.ics'
restoring record '60C8-65323D00-1-4D9F7D80.vcf'
restoring record '60C8-65323D80-9-4D9F7D80.ics'
----
* *-F* has the same behavior as *-f* but it will first delete all contacts and events in database before restoring the backup.
So if an event/contact is not in the backup file, it will be lost. If a folder exists but is not in the backup file, nothing will happen
to it and its content.
*-F* expect a value that can be ALL to restore all folders, or the name of the folder to restore. You can list them with the *-l* mode.
Example:
----
sogo-tool restore -F ALL /tmp/backup user1
sogo-tool restore -F "Contacts/personal" tmp/backup user1
sogo-tool restore -F "Calendar/60C8-65323D80-7-4D9F7D80" tmp/backup user1
----
sogo-tool checkup
~~~~~~~~~~~~~~~~~
Check the events and contacts data's integrity of a user
sogo-tool checkup [-d] user...
* *-d*, optional, will delete all corrupted data.
* *user* is a single username or multiple user each space-separated.
Will print out nothing if no corrupted data were found or one of the following messages:
* Corrupted calendar item (missing tags) in path <path> with c_name = <ics_id>
* Corrupted calendar item (unparsable) in path <path> with c_name = <ics_id>
* Missing start date of event in path <path> with c_name = <ics_id> (<event_name>)"
* Missing end date of event in path <path> with c_name = <ics_id> (<event_name>)"
* Start date (<start_date>) is not before end date (<end_date>) for event in path <path> with c_name = <ics_id> (<event_name>)
* Corrupted card item (unparsable) in path <path> with c_name = <vcard_id>
It can also print log from SOGo if it raise errors:
* <0x0x55e0956c4d00[VSCardSaxDriver]> serious inconsistency among begin/end tags
Example:
----
sogo-tool checkup user1
sogo-tool checkup -d user1
----
sogo-tool cleanup
~~~~~~~~~~~~~~~~~
Will purge all user's deleted events and contacts which the deletion is older than a number of days.
sogo-tool cleanup [days] ALL|user1 [user2]
* *days* the age of deleted records to purge in days
* Second argument is *ALL* to purge events of all users or put each user space-separated.
Example:
----
sogo-tool cleanup 30 ALL
sogo-tool cleanup 30 user1 user2
----
Outputs:
----
Purged 3 records from folder /Users/user1/Calendar/60C7-65325300-9-18F39AA0
Purged 1 records from folder /Users/user1/Calendar/60C8-65323D80-7-4D9F7D80
Purged 0 records from folder /Users/user1/Calendar/personal
Purged 0 records from folder /Users/user1/Contacts/personal
Purged 5 records from folder /Users/user2/Calendar/personal
----
sogo-tool create-folder
~~~~~~~~~~~~~~~~~~~~~~~
Create a folder (Calendar or Address Book) for a user.
create-folder user type [displayname ...]
* *user* is the name of the user
* *type* is either "Calendar" or "Contacts"
* *displayname* is the folder's name. If the name is already taken, a new folder will still be made but with another uid.
Example:
----
sogo-tool create-folder user1 Contacts Pro_Contacts Ext_Contacts
sogo-tool create-folder user2 Calendar Pro_Calendar
----
sogo-tool dump-defaults
~~~~~~~~~~~~~~~~~~~~~~~
Output all current defaults value of GNUstep and SOGo (sogo.conf)
sogo-tool dump-defaults [-f <filename>|[all]]
* Can be used without arguments and will output the defaults for gnustep domain 'sogod'.
* *all* option will output all defaults value found from sogo and gnustep in property list format.
* *-f* expect a filepath of an .xml file and will output it in property list format (sogo.conf). May need some tweaks, though.
Example:
----
sogo-tool dump-defaults
sogo-tool dump-defaults all
sogo-tool dump-defaults -f /tmp/foo/conf.xml
----
sogo-tool expire-sessions
~~~~~~~~~~~~~~~~~~~~~~~~~
Expires user sessions from database without activity for specified number of minutes. When a user log in to sogo for
the first time, sogo will create a entry in database's table OCSSessionsFolderURL with the user's information. Sogo will
also set a cookie with an encoded value to fetch this database table. That way, each time the user make a request with that cookie,
sogo will know which connected user it is. This command will remove all user's session from database
without activity for specified number of minutes. Those users will have to log in again.
sogo-tool expire-sessions [nbMinutes]
* *nbMinutes* Integer, number of minutes. All session without activity in these last minutes will be removed.
Example:
----
sogo-tool expire-sessions #Will print usage.
sogo-tool expire-sessions 160 #Will remove session which last activity is older than 160 minutes.
sogo-tool expire-sessions 0 #Will remove session which last activity is older than 0 minutes.
----
sogo-tool manage-acl
~~~~~~~~~~~~~~~~~~~~
Manage access-control list (ACL) of a user for folders (Calendar and Address Book).
sogo-tool manage-acl get|add|remove|subscribe|unsubscribe owner folder user|group <rights>
* First argument is the action among *get*, *add*, *remove*, *subscribe* and *unsubscribe*.
* Second argument is the username of the folder's owner.
* Third argument is the name of the folder.
* Fourth argument is the user whom to manage its acl. It also can be _ALL_, _anonymous_ and _<defaults>_.
* Fifth argument, only needed with *add* action, is the rights to set for the user.
The actions:
* *get* will print out the folder's rights of the user or nothing if the user is not found or doesn't have any rights.
Example:
----
sogo-tool manage-acl get sogo-tests1 Calendar/5E1F-653FC400-1-38155940 sogo-tests2
----
Result:
----
Rights for sogo-tests2 ["PublicModifier", "ConfidentialModifier", "PrivateModifier", "ObjectCreator", "ObjectEraser"]
----
* *add* will add the given rights to the user for the given folder. the value right is a json string of an array with each right to set.
Be Careful as there is no check for the rights already set. It could be better to first remove them, then add them.
The rights for Address Book are:
* _ObjectCreator_: can create cards (contact of list)
* _ObjectEditor_: can modify cards
* _ObjectViewer_: can view cards
* _ObjectEraser_: can delete cards
The rights for Calendar are:
* _ObjectCreator_: can create event or task
* _ObjectEraser_: can delete event or task
* _<type>_ can be _Public_, _Confidential_ or _Private_
* _<type>Viewer_: can view the whole events (ex: PrivateViewer)
* _<type>DAndTViewer_: can only view the date and time of events
* _<type>Modifier_: can view and edit the events
* _<type>Responder_: can view the events
Example:
----
sogo-tool manage-acl add sogo-tests1 Contacts/5E1D-653FC400-1-1A330C40 sogo-tests2 '["ObjectViewer", "ObjectEraser"]'
----
* *remove* all user's rights to the folder.
Example:
----
sogo-tool manage-acl remove sogo-tests1 Contacts/5E1D-653FC400-1-1A330C40 sogo-tests2
----
* *subscribe* the user to the folder.
Example:
----
sogo-tool manage-acl subscribe sogo-tests1 Contacts/5E1D-653FC400-1-1A330C40 sogo-tests2
----
* *unsubscribe* the user to the folder.
Example:
----
sogo-tool manage-acl unsubscribe sogo-tests1 Contacts/5E1D-653FC400-1-1A330C40 sogo-tests2
----
sogo-tool manage-eas
~~~~~~~~~~~~~~~~~~~~
Manage EAS folders
sogo-tool manage-eas listdevices|listfolders|resetdevice|resetfolder|mergevcard|mergevevent user <deviceId | folderId> <YES | NO>
* First argument is the action among *listdevices*, *listfolders*, *resetdevice*, *resetfolder*, *mergevcard* and *mergevevent*.
* Second argument is the *user* whom to perform the action.
* Third argument is the *deviceId* of, if the action is *resetFolder*, the *folderId*. No need of this argument if the action is *listdevices*
* Fourth argument, only use with *mergevcard* and *mergevevent* is either YES to merge and *NO* to un-merge.
The actions:
* *listdevices*: list the devices belonging to user.
* *listfolders*: list all folders of deviceId for user.
* *resetdevice*: force deviceId of user to resync everything.
* *resetfolder*: force folderId of user to resync everything.
* *mergevcard*: merge/un-merge all addressbooks into one for deviceId of user.
* *mergevevent*: merge/un-merge all calendars into one for deviceId of user.
Examples:
----
sogo-tool manage-eas listdevices janedoe
sogo-tool manage-eas listfolders janedoe androidc316986417
sogo-tool manage-eas resetdevice janedoe androidc316986417
sogo-tool manage-eas resetfolder janedow androidc316986417 folderlala-dada-sasa_7a13_1a2386e0_e
sogo-tool manage-eas mergevcard janedow androidc316986417 YES
sogo-tool manage-eas mergevevent janedow androidc316986417 YES
----
sogo-tool remove
~~~~~~~~~~~~~~~~
Remove all folders (Calendar and Address Book) and Preference settings of a user. The personal Calendar and Address Book
will stay but be emptied of all entries. The Preferences will go back to defaults values as for a new user.
sogo-tool remove user1 [user2]
* Arguments one user or several space-separated.
* You can add -v after sogo*tool to list all removed folders
Example:
----
sogo-tool remove user1
sogo-tool -v remove user2
----
Output example with -v options:
----
Deleting /Users/user2/Calendar/B088-65363400-3-2B9DF0C0
Deleting /Users/user2/Calendar/personal
Deleting /Users/user2/Contacts/B087-65363380-5-374DA380
Deleting /Users/user2/Contacts/B087-65363400-7-374DA380
Deleting /Users/user2/Contacts/personal
----
sogo-tool remove-doubles
~~~~~~~~~~~~~~~~~~~~~~~~
remove duplicate contacts from the specified user addressbook
sogo-tool remove-doubles USER FOLDER
* *USER* is the name of the user to perform the removal
* *FOLDER* is the name of the folder to clean from duplicates
Two contacts are considered duplicates when they have the same mails or display name. When two or more contacts
are duplicates, each one will get a score. The ones with the highest score will be kept and the others
will be discarded. If two records have the same score, the first one to have reach it will be kept.
The scores are distributed as such:
* Record which has been the last modified: +1
* Record has the most content: +2
* Record has the most quick field set: +3
* Record is in a contact list: +6
Example:
----
sogo-tool remove-doubles user1 personal
sogo-tool remove-doubles user2 489-65376E80-1-2D2BA000
----
sogo-tool rename-user
~~~~~~~~~~~~~~~~~~~~~
Update records pertaining to a user after a change of user id. Will change all folders path, subscriptions from others users,
all mention of user id in database.
sogo-tool rename-user fromuserid touserid
* *fromuserid* Previous user id
* *touserid* New user id
If the new user id already exist, the command will output a message and do nothing.
**WARNING** This command only change database of sogo, if you use ldap or others databases they will still keep the old id.
Example:
----
sogo-tool rename-user old_username new_username
----
sogo-tool truncate-calendar
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Remove old calendar entries from the specified user calendar.
sogo-tool truncate-calendar [-r] USER FOLDER DATE
* *-r* optional, to also delete recurrent events that have occurrence after *DATE*
* *USER* is the name of the owner of the calendar
* *FOLDER* is the name of the calendar folder to clean up
* *DATE* UTC datetime, event older than this date will be removed
Without *-r*, only reccurrent events which all occurrences are older than *DATE* will be removed.
With *-r*, event the if there are occurrences after *DATE*, the recurrent event will be removed.
*DATE* can take the value `date +%FT%T` which is the current time
Example:
----
sogo-tool truncate-calendar sogo-tests1 personal 2023-10-25T00:00:00
sogo-tool truncate-calendar -r sogo-tests2 5E38-6538BE80-5-AFF8310 2022-01-01T15:30:00
sogo-tool truncate-calendar -r sogo-tests2 personal `date +%FT%T` #will delete all event older than now
----
Result:
----
No record to remove. All records kept.
----
----
Removing 1 records...
Removed 1 records.
----
sogo-tool update-autoreply
~~~~~~~~~~~~~~~~~~~~~~~~~~
_This command is only useful if your sieve server doesn't have the capabilities *date* or *relational*_
In that case this command will check vacation's setting of all the users. If vacation is enabled/disabled,
the starting and ending date, the body and others parameters. If needed, the command
will write the sieve script accordingly.
sogo-tool update-autoreply -p credentialFile
* *-p- The credential file, a simple one-line file that contains "username:password" of an admin account of your imap/sieve server.
Example:
----
sogo-tool update-autoreply -p /var/sogo/cred
----
sogo-tool user-preferences
~~~~~~~~~~~~~~~~~~~~~~~~~~
Get, set or unset user defaults / settings in the database.
_Settings_ stores parameters for user's calendar, mail and contacts. It can be graphic
as month view or week view for calendar but it also stores subscription, delegation...
It also stores the private Salt for TOTP and the parameter ForceResetPassword to force the
user to change password.
_Defaults_ stores all parameters that can be found in Preferences panel. So it goes from default language to
autoreply to many others options.
user-preferences get|set|unset defaults|settings user key [value|-f filename] [-p credentialFile]
* First argument is the action *get*, *set* or *unset*
* Second argument is parameter type *settings* or *defaults*
* Third argument *user* is the name of the user where to make the action
* Fourth argument *key* is the name of the parameters where to make the action
* If the action is *set*, you should provide either *value* as fifth argument or a file with the value inside with *-f* filename/path
* If the action is *set* or *unset* and the *key* concerns a sieve script (filter, vacation, forward...), you
should provide a credential file, a one-line file that contains "username:password" of an admin account of your imap/sieve server.
As there is a lot of parameters, this documentation will not go into details for each one. To know what are
the key names and their value you should got to your database in table defined by _SOGoProfileURL_ in your sogo.conf.
Here, for each row (user) you will find c_defaults and c_settings which are json with the keys. However, if
a parameter has never been set, it won't appears in those json. The clean way to know the missing keys is to
set it up in one of your dummy/dev/test account then see the values in _SOGoProfileURL_. Be careful, a value
can be a json itself, only the primary key can be get/set/unset.
Example with forwarding, *get* action:
----
sogo-tool user-preferences get defaults user1 Forward
----
If forward has never been set the result will be:
----
Value for key "Forward" not found in defaults
----
Else it will be
----
{"forwardAddress":["sogo-tests2@sogo.alinto"],"enabled":1,"keepCopy":1}
----
*unset* action:
----
sogo-tool user-preferences unset defaults user1 Forward -p /etc/sogo/cred
----
*set* action:
----
sogo-tool user-preferences set defaults user1 Forward '{"forwardAddress":["sogo-tests2@sogo.alinto"],"enabled":1,"keepCopy":0}' -p cred
----
or create a json file which contains _{"forwardAddress":["sogo-tests2@sogo.alinto"],"enabled":1,"keepCopy":0}_ then:
----
sogo-tool user-preferences set defaults user1 Forward -f /path/filename -p cred
----
Upgrading
---------
@@ -22,7 +22,7 @@ devices (iPhone, iPod touch, and iPad).
The instructions are based on version {release_version} of SOGo.
The latest version of this guide is available at
https://sogo.nu/downloads/documentation.html.
https://www.sogo.nu/support.html#/documentation.
Introduction
------------
@@ -22,7 +22,7 @@ Guide_ for more information on installing and configuring SOGo.
The instructions are based on version {release_version} of SOGo.
The latest version of this guide is available
at https://sogo.nu/downloads/documentation.html.
at https://www.sogo.nu/support.html#/documentation.
Introduction
------------
+6
View File
@@ -72,8 +72,14 @@
- (void) setEndDate: (NSCalendarDate *) newEndDate
{
CardElement *c;
[(iCalDateTime *) [self uniqueChildWithTag: @"dtend"]
setDateTime: newEndDate];
c = [self uniqueChildWithTag: @"duration"];
if (c)
[self removeChild: c];
}
- (NSCalendarDate *) endDate
+25 -11
View File
@@ -44,10 +44,11 @@
{
NSMutableArray *ranges;
NSArray *byMonth;
NSCalendarDate *firStart, *lastDate, *rStart, *rEnd, *until, *referenceDate;
NSCalendarDate *firStart, *lastDate, *rStart, *rEnd, *until, *referenceDate, *rTemp;
NSInteger *hoursOfOffset;
iCalMonthlyRecurrenceCalculator *monthlyCalc;
unsigned j, yearIdxInRange, numberOfYearsInRange, count, interval, monthDiff;
int diff, repeatCount, currentMonth;
int diff, repeatCount, currentMonth, origNbDaysInMonth;
firStart = [firstRange startDate];
rStart = [_r startDate];
@@ -186,18 +187,31 @@
days: 0];
//Due to the bug with dateByAddingYears, we have to take off one day (see line 133)
rStart = [NSCalendarDate dateWithYear: [rStart yearOfCommonEra]
month: [rStart monthOfYear]
day: 0
hour: [rStart hourOfDay]
minute: [rStart minuteOfHour]
second: 0
timeZone: [rStart timeZone]];
//Due to the bug with dateByAddingYears, we may take the previous day (see line 133)
hoursOfOffset = [rStart hourOfDay];
origNbDaysInMonth = [rStart numberOfDaysInMonth];
if(hoursOfOffset > 12) {
//If rStart is 1st 22:00, we should start at the previous day 22:00
rTemp = [NSCalendarDate dateWithYear: [rStart yearOfCommonEra]
month: 1+([rStart monthOfYear]-2)%12
day: 1
hour: [rStart hourOfDay]
minute: [rStart minuteOfHour]
second: 0
timeZone: [rStart timeZone]];
rStart = [NSCalendarDate dateWithYear: [rStart yearOfCommonEra]
month: 1+([rStart monthOfYear]-2)%12
day: [rTemp numberOfDaysInMonth]
hour: [rStart hourOfDay]
minute: [rStart minuteOfHour]
second: 0
timeZone: [rStart timeZone]];
}
rEnd = [rStart dateByAddingYears: 0
months: 0
days: [rStart numberOfDaysInMonth]];
days: origNbDaysInMonth];
rangeForMonth = [NGCalendarDateRange calendarDateRangeWithStartDate: rStart
+1 -1
View File
@@ -141,7 +141,7 @@ CREATE TABLE sogo_quick_contact (
CREATE TABLE sogo_sessions_folder (
c_id varchar(255) NOT NULL,
c_value varchar(255) NOT NULL,
c_value varchar(4096) NOT NULL,
c_creationdate int(11) NOT NULL,
c_lastseen int(11) NOT NULL,
PRIMARY KEY (c_id)
@@ -53,7 +53,7 @@ vtodo_class2 = "(Vertrauliche Aufgabe)";
"The following parameters have changed in the \"%{Summary}\" meeting:"
= "Folgendes wurde am Termin \"%{Summary}\" geändert:";
"Please accept or decline those changes."
= "Bitte akzeptieren Sie diese Änderung, oder lehnen Sie diese ab.";
= "Bitte akzeptieren Sie diese Änderungen, oder lehnen Sie diese ab.";
/* Reply */
"Accepted invitation: \"%{Summary}\"" = "Einladung zugestimmt: \"%{Summary}\"";
@@ -12,9 +12,9 @@ vtodo_class2 = "(Konfidenciali užduotis)";
"The event \"%{Summary}\" was created" = "Įvykis \"%{summary}\" buvo sukurtas";
"The event \"%{Summary}\" was deleted" = "Įvykis \"%{Summary}\" buvo ištrintas";
"The event \"%{Summary}\" was updated" = "Įvykis \"%{Summary}\" buvo atnaujintas";
"The task \"%{Summary}\" was created" = "Įvykis \\"%{summary}\\" buvo sukurtas";
"The task \"%{Summary}\" was deleted" = "Įvykis \\"%{Summary}\\" buvo ištrintas";
"The task \"%{Summary}\" was updated" = "Įvykis \\"%{Summary}\\" buvo atnaujintas";
"The task \"%{Summary}\" was created" = "Įvykis \"%{summary}\" buvo sukurtas";
"The task \"%{Summary}\" was deleted" = "Įvykis \"%{Summary}\" buvo ištrintas";
"The task \"%{Summary}\" was updated" = "Įvykis \"%{Summary}\" buvo atnaujintas";
"The following attendees(s) were notified" = "Šiems dalyviui(iams) buvo pranešta";
"The following attendees(s) were added" = "Šie dalyvis(iai) buvo pridėti";
"The following attendees(s) were removed" = "Šie dalyvis(iai) buvo pašalinti";
@@ -33,13 +33,13 @@ vtodo_class2 = "(Konfidenciali užduotis)";
"attendee_label" = "Dalyvis";
/* Invitation */
"Event Invitation: \"%{Summary}\"" = "Įvykio pakvietimas: \"%{Summary}\"";
"(sent by %{SentBy}) " = "(išsiųsta nuo %{SentBy}) ";
"Event Invitation: \"%{Summary}\"" = "Kvietimas į renginį: \"%{Summary}\"";
"(sent by %{SentBy}) " = "(išsiųsta %{SentBy}) ";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" = "%{Organizer} %{SentByText} pakvietė Jus į %{Summary}.\nPradžia: %{StartDate}\nPabaiga: %{EndDate}\nAprašymas: %{Description}";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" = "%{Organizer} %{SentByText} pakvietė Jus į %{Summary}.\n\nPradžia: %{StartDate} nuo %{StartTime}\nPabaiga: %{EndDate} nuo %{EndTime}\nAprašymas: %{Description}";
/* Deletion */
"Event Cancelled: \"%{Summary}\"" = "Įvykis atšauktas: \\"%{Summary}\\"";
"Event Cancelled: \"%{Summary}\"" = "Įvykis atšauktas: \"%{Summary}\"";
"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}"
= "%{Organizer} %{SentByText} atšaukė šį įvykį: %{Summary}.\n\nPradžia: %{StartDate}\nPabaiga: %{EndDate}\nAprašymas: %{Description}";
"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}"
@@ -63,11 +63,11 @@ vtodo_class2 = "(Konfidenciali užduotis)";
"%{Attendee} %{SentByText}has accepted your event invitation."
= "%{Attendee} %{SentByText} priėmė Jūsų įvykio pakvietimą.";
"%{Attendee} %{SentByText}has declined your event invitation."
= "%{Attendee} %{SentByText} atmetė Jūsų įvykio pakvietimą.";
= "%{Attendee} %{SentByText} atmetė Jūsų pakvietimą į renginį.";
"%{Attendee} %{SentByText}has delegated the invitation to %{Delegate}."
= "%{Attendee} %{SentByText} delegavo pakvietimą į %{Delegate}.";
"%{Attendee} %{SentByText}has not yet decided upon your event invitation."
= "%{Attendee} %{SentByText} neapsisprendė dėl Jūsų įvykio pakvietimo.";
= "%{Attendee} %{SentByText} neapsisprendė dėl Jūsų kvietimo į renginį.";
/* Reminder */
"Reminder: \"%{Summary}\" - %{StartDate}" = "Priminimas: \"%{Summary}\" - %{StartDate}";
@@ -1,2 +1,2 @@
"Personal Address Book" = "Asmeninė adresų knyga";
"Collected Address Book" = "Rinktinė adresų knyga";
"Collected Address Book" = "Rinktinė adresų knygą";
+1 -1
View File
@@ -418,7 +418,7 @@ convention:
[self setCategories: [o componentsSeparatedByString: @","]];
// Photo
if ([ldifRecord objectForKey: @"photo"])
if ([ldifRecord objectForKey: @"photo"] && [ldifRecord objectForKey: @"photo"] != [NSNull null])
[self setPhoto: [[ldifRecord objectForKey: @"photo"] stringByEncodingBase64]];
[self cleanupEmptyChildren];
@@ -271,6 +271,9 @@ static NSArray *folderListingFields = nil;
if ([data length])
[contactRecord setObject: data forKey: @"id"];
// Container name
[contactRecord setObject: [self displayName] forKey: @"containerName"];
// c_cn
data = [contactRecord objectForKey: @"c_cn"];
if (![data length])
+35 -14
View File
@@ -242,6 +242,10 @@
//source id
[newRecord setObject: [source sourceID] forKey: @"sourceID"];
//source display name
[newRecord setObject: [self displayName]
forKey: @"containerName"];
// c_name => id
[newRecord setObject: [oldRecord objectForKey: @"c_name"]
forKey: @"c_name"];
@@ -430,26 +434,43 @@
{
NSArray *records, *result;
EOSortOrdering *ordering;
BOOL processed;
result = nil;
processed = NO;
if ([filter length] > 0 || ![source listRequiresDot])
[source setListRequiresDot: NO];
if ( ![source listRequiresDot])
{
records = [source fetchContactsMatching: filter
if ([filter length] > 0) {
records = [source fetchContactsMatching: filter
withCriteria: criteria
inDomain: domain];
[childRecords setObjects: records
forKeys: [records objectsForKey: @"c_name"
notFoundMarker: nil]];
records = [self _flattenedRecords: records];
ordering
= [EOSortOrdering sortOrderingWithKey: sortKey
selector: ((sortOrdering == NSOrderedDescending)
? EOCompareCaseInsensitiveDescending
: EOCompareCaseInsensitiveAscending)];
result
= [records sortedArrayUsingKeyOrderArray:
[NSArray arrayWithObject: ordering]];
processed = YES;
} else if ([[SOGoSystemDefaults sharedSystemDefaults] globalAddressBookFirstEntriesEnabled]) {
records = [source fetchContactsMatching: filter
withCriteria: criteria
inDomain: domain
limit: [[SOGoSystemDefaults sharedSystemDefaults] globalAddressBookFirstEntriesCount]];
processed = YES;
}
if (processed) {
[childRecords setObjects: records
forKeys: [records objectsForKey: @"c_name"
notFoundMarker: nil]];
records = [self _flattenedRecords: records];
ordering
= [EOSortOrdering sortOrderingWithKey: sortKey
selector: ((sortOrdering == NSOrderedDescending)
? EOCompareCaseInsensitiveDescending
: EOCompareCaseInsensitiveAscending)];
result
= [records sortedArrayUsingKeyOrderArray:
[NSArray arrayWithObject: ordering]];
}
}
return result;
+1
View File
@@ -64,6 +64,7 @@
BOOL isHTML;
BOOL sign;
BOOL encrypt;
NSMutableArray *tmpFiles;
// Used during S/MIME encryption
NSMutableDictionary *certificates;
+52 -51
View File
@@ -67,6 +67,7 @@
#import <SOGo/SOGoUserFolder.h>
#import <SOGo/SOGoUserDefaults.h>
#import <SOGo/SOGoSystemDefaults.h>
#import <SOGo/NGMimeFileData+SOGo.h>
#import <NGCards/NGVCard.h>
@@ -142,6 +143,7 @@ static NSString *userAgent = nil;
isHTML = NO;
sign = NO;
encrypt = NO;
tmpFiles = [[NSMutableArray alloc] init];
}
return self;
@@ -157,6 +159,7 @@ static NSString *userAgent = nil;
[sourceFlag release];
[inReplyTo release];
[references release];
[tmpFiles release];
[super dealloc];
}
@@ -932,7 +935,6 @@ static NSString *userAgent = nil;
if (filename)
{
NSMutableDictionary *currentInfo;
currentInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
filename, @"filename",
mimeType, @"mimetype",
@@ -1922,8 +1924,10 @@ static NSString *userAgent = nil;
if (_extractImages)
{
newText = [text htmlByExtractingImages: extractedBodyParts];
if ([extractedBodyParts count])
if ([extractedBodyParts count]) {
[self setText: newText];
[self addTmpFiles: extractedBodyParts];
}
}
@@ -1935,8 +1939,11 @@ static NSString *userAgent = nil;
//[self debugWithFormat: @"MIME Envelope: %@", map];
allBodyParts = [self bodyPartsForAllAttachments];
if (!allBodyParts)
return nil;
if (!allBodyParts) {
return nil;
} else {
[self addTmpFiles: allBodyParts];
}
//[self debugWithFormat: @"attachments: %@", bodyParts];
@@ -1955,53 +1962,8 @@ static NSString *userAgent = nil;
}
}
if (_extractImages)
{
int i;
for (i = 0 ; i < [extractedBodyParts count] ; i++) {
NSMutableDictionary *currentInfo;
NSString *filename, *mimeType, *bodyId, *encoding;
NSData *body;
NGMimeBodyPart *extractedBodyPart;
NGMimeContentDispositionHeaderField *contentDisposition;
extractedBodyPart = [extractedBodyParts objectAtIndex:i];
if (extractedBodyPart && [extractedBodyPart headerForKey: @"content-disposition"]) {
encoding = [extractedBodyPart encoding];
contentDisposition = [[NGMimeContentDispositionHeaderField alloc] initWithString: [extractedBodyPart headerForKey: @"content-disposition"]];
if (encoding
&& [extractedBodyPart contentType]
&& [extractedBodyPart contentId]
&& [contentDisposition filename]) {
mimeType = [[extractedBodyPart contentType] stringValue];
bodyId = [[extractedBodyPart contentId] stringValue];
filename = [contentDisposition filename];
currentInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
filename, @"filename",
mimeType, @"mimetype",
bodyId, @"bodyId",
nil];
if ([[extractedBodyParts objectAtIndex:i] body]) {
if (encoding && [encoding rangeOfString:@"base64"].location != NSNotFound)
body = [[[extractedBodyParts objectAtIndex:i] body] dataByDecodingBase64];
else
body = [[extractedBodyParts objectAtIndex:i] body];
[self saveAttachment: body
withMetadata: currentInfo];
}
}
[contentDisposition release];
}
}
}
return message;
}
}
//
// Return a NGMimeMessage object with inline HTML images (<img src=data>) extracted as attachments (<img src=cid>).
@@ -2271,6 +2233,41 @@ static NSString *userAgent = nil;
return [self sendMailAndCopyToSent: YES];
}
// Extract tmp files in NGMimeBuildMimeTempDirectory from NSArray and store locally
// The tmp files will be deleted once the message sent
- (void) addTmpFiles:(NSArray *) parts {
NGMimeBodyPart *part;
for (part in parts) {
NGMimeFileData *body;
NSString *path;
body = [part body];
if (body && [body isKindOfClass: [NGMimeFileData class]]) {
path = [body path];
if (path) {
[tmpFiles addObject: path];
}
}
}
}
// Clean temporary files
- (void) cleanTmpFiles {
NSString *path;
NSFileManager *fm;
fm = [NSFileManager defaultManager];
for (path in tmpFiles) {
if ([fm fileExistsAtPath: path])
[fm removeFileAtPath: path handler: nil];
}
// Clean tmp files
[tmpFiles removeAllObjects];
}
//
//
//
@@ -2316,8 +2313,10 @@ static NSString *userAgent = nil;
inContext: context
systemMessage: NO];
if (error)
if (error) {
[self cleanTmpFiles];
return error;
}
}
// If the current user isn't part of the recipient list for encrypted emails
@@ -2376,6 +2375,8 @@ static NSString *userAgent = nil;
[imap4 doesMailboxExistAtURL: [container imap4URL]])
[(SOGoDraftsFolder *) container expunge];
[self cleanTmpFiles];
return error;
}
+2
View File
@@ -94,6 +94,7 @@ SOGo_HEADER_FILES = \
JWT.h \
\
NGMimeBodyPart+SOGo.h \
NGMimeFileData+SOGo.h \
\
SOGoMobileProvision.h
@@ -183,6 +184,7 @@ SOGo_OBJC_FILES = \
JWT.m \
\
NGMimeBodyPart+SOGo.m \
NGMimeFileData+SOGo.m \
\
SOGoMobileProvision.m
+59 -12
View File
@@ -1384,6 +1384,21 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses
- (NSArray *) fetchContactsMatching: (NSString *) match
withCriteria: (NSArray *) criteria
inDomain: (NSString *) theDomain
{
if ([match length] > 0) {
return [self fetchContactsMatching: (NSString *) match
withCriteria: (NSArray *) criteria
inDomain: (NSString *) theDomain
limit: -1];
} else {
return [NSMutableArray array];
}
}
- (NSArray *) fetchContactsMatching: (NSString *) match
withCriteria: (NSArray *) criteria
inDomain: (NSString *) theDomain
limit: (int) limit
{
NSAutoreleasePool *pool;
NGLdapConnection *ldapConnection;
@@ -1392,6 +1407,8 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses
NSMutableArray *contacts;
EOQualifier *qualifier;
unsigned int i;
NSString *sortAttribute;
BOOL sortReverse;
contacts = [NSMutableArray array];
@@ -1400,18 +1417,48 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses
ldapConnection = [self _ldapConnection];
qualifier = [self _qualifierForFilter: match onCriteria: criteria];
if ([_scope caseInsensitiveCompare: @"BASE"] == NSOrderedSame)
entries = [ldapConnection baseSearchAtBaseDN: _baseDN
qualifier: qualifier
attributes: _lookupFields];
else if ([_scope caseInsensitiveCompare: @"ONE"] == NSOrderedSame)
entries = [ldapConnection flatSearchAtBaseDN: _baseDN
qualifier: qualifier
attributes: _lookupFields];
else /* we do it like before */
entries = [ldapConnection deepSearchAtBaseDN: _baseDN
qualifier: qualifier
attributes: _lookupFields];
if (limit > 0) {
[ldapConnection setQuerySizeLimit: limit];
}
if (limit > 0) {
// Sort results
sortAttribute = @"cn";
sortReverse = NO;
if ([_scope caseInsensitiveCompare: @"BASE"] == NSOrderedSame)
entries = [ldapConnection baseSearchAtBaseDN: _baseDN
qualifier: qualifier
attributes: _lookupFields
sortAttribute: sortAttribute
sortReverse: sortReverse];
else if ([_scope caseInsensitiveCompare: @"ONE"] == NSOrderedSame)
entries = [ldapConnection flatSearchAtBaseDN: _baseDN
qualifier: qualifier
attributes: _lookupFields
sortAttribute: sortAttribute
sortReverse: sortReverse];
else /* we do it like before */
entries = [ldapConnection deepSearchAtBaseDN: _baseDN
qualifier: qualifier
attributes: _lookupFields
sortAttribute: sortAttribute
sortReverse: sortReverse];
} else {
// No sort results
if ([_scope caseInsensitiveCompare: @"BASE"] == NSOrderedSame)
entries = [ldapConnection baseSearchAtBaseDN: _baseDN
qualifier: qualifier
attributes: _lookupFields];
else if ([_scope caseInsensitiveCompare: @"ONE"] == NSOrderedSame)
entries = [ldapConnection flatSearchAtBaseDN: _baseDN
qualifier: qualifier
attributes: _lookupFields];
else /* we do it like before */
entries = [ldapConnection deepSearchAtBaseDN: _baseDN
qualifier: qualifier
attributes: _lookupFields];
}
i = 0;
pool = [NSAutoreleasePool new];
+34
View File
@@ -0,0 +1,34 @@
/* NGMimeFileData+SOGo.h - this file is part of SOGo
*
* Copyright (C) 2023 Alinto
*
* Author: Sébastien Mizrahi <smizrahi@alinto.eu>
*
* 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 NGMIMEFILEDATA_SOGO_H
#define NGMIMEFILEDATA_SOGO_H
#import <NGMime/NGMimeFileData.h>
@interface NGMimeFileData (SOGoExtensions)
- (NSString *) path;
@end
#endif /* NGMIMEFILEDATA_SOGO_H */
+32
View File
@@ -0,0 +1,32 @@
/* NGMimeFileData+SOGo.m - this file is part of SOGo
*
* Copyright (C) 2023 Alinto
*
* Author: Sébastien Mizrahi <smizrahi@alinto.eu>
*
* 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 "NGMimeFileData+SOGo.h"
@implementation NGMimeFileData (SOGoExtensions)
- (NSString *) path {
return path;
}
@end
+1
View File
@@ -65,6 +65,7 @@
- (id) objectFromJSONString;
/* bare email addresses */
- (NSString *) mailDomain;
- (NSString *) pureEMailAddress;
- (NSString *) asQPSubjectString: (NSString *) encoding;
+24
View File
@@ -609,6 +609,18 @@ static int cssEscapingCount;
return newString;
}
- (NSString *) mailDomain
{
NSArray *mailSeparated;
mailSeparated = [self componentsSeparatedByString: @"@"];
if([mailSeparated count] == 2)
return [mailSeparated objectAtIndex: 1];
[self logWithFormat: @"Error while extracting domain from : %@", self];
return nil;
}
- (NSString *) pureEMailAddress
{
NSString *pureAddress;
@@ -979,6 +991,18 @@ static int cssEscapingCount;
newResult = [regex stringByReplacingMatchesInString:result options:0 range:NSMakeRange(0, [result length]) withTemplate:@"<ifr***"];
result = [NSString stringWithString: newResult];
// Remove <form
regex = [NSRegularExpression regularExpressionWithPattern:@"<[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*f[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*o[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*r[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*m"
options: NSRegularExpressionCaseInsensitive error:&error];
newResult = [regex stringByReplacingMatchesInString:result options:0 range:NSMakeRange(0, [result length]) withTemplate:@"<for*"];
result = [NSString stringWithString: newResult];
// Remove </form
regex = [NSRegularExpression regularExpressionWithPattern:@"<[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*/[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*f[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*o[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*r[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*m"
options: NSRegularExpressionCaseInsensitive error:&error];
newResult = [regex stringByReplacingMatchesInString:result options:0 range:NSMakeRange(0, [result length]) withTemplate:@"</for*"];
result = [NSString stringWithString: newResult];
// Remove onload
regex = [NSRegularExpression regularExpressionWithPattern:@"onload="
options: NSRegularExpressionCaseInsensitive error:&error];
+13 -2
View File
@@ -100,8 +100,19 @@
if (data) {
if ([data isKindOfClass: [NSString class]])
ASSIGN (content, data);
else
ASSIGN (content, [NSString stringWithUTF8String:[data bytes]]);
else {
char lastByte;
[data getBytes:&lastByte range:NSMakeRange([data length]-1, 1)];
if (lastByte == 0x0) {
// string is null terminated
ASSIGN (content, [NSString stringWithUTF8String: [data bytes]]);
} else {
// string is not null terminated
NSString* myString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
ASSIGN (content, myString);
[myString release];
}
}
}
data = [objectRecord objectForKey: @"c_version"];
if (data)
+2
View File
@@ -123,6 +123,8 @@
SOGoTemplatesFolderName = "Templates";
SOGoMailComposeMessageType = "html";
SOGoMailComposeFontSize = "0";
SOGoMailHideInlineAttachments = NO;
SOGoMailDisplayFullEmail = NO;
SOGoMailDisplayRemoteInlineImages = "never";
SOGoMailCertificateEnabled = YES;
+1 -1
View File
@@ -217,7 +217,7 @@
v = [self integerForKey: @"SOGoForwardConstraints"];
return (v > 2 ? 0 : v);
return (v > 3 ? 0 : v);
}
- (NSArray *) forwardConstraintsDomains
+4 -2
View File
@@ -739,7 +739,8 @@ static NSArray *childRecordFields = nil;
qualifier = aclQualifier;
// For Thunderbird, disable contact list
if ([[context request] isThunderbird]) {
// This will be removed when VCARD will be implemented
if ([[context request] isThunderbird] && [self isKindOfClass: NSClassFromString(@"SOGoContactGCSFolder")]) {
vlistExclusionQualifier = [EOQualifier qualifierWithQualifierFormat: @"c_component != 'vlist'"];
qualifier = [[[EOAndQualifier alloc] initWithQualifiers:
vlistExclusionQualifier,
@@ -1191,7 +1192,8 @@ static NSArray *childRecordFields = nil;
folder = [self ocsFolder];
// For Thunderbird, disable contact list
if ([[context request] isThunderbird]) {
// This will be removed when VCARD will be implemented
if ([[context request] isThunderbird] && [self isKindOfClass: NSClassFromString(@"SOGoContactGCSFolder")]) {
vlistExclusionQualifier = [EOQualifier qualifierWithQualifierFormat: @"c_component != 'vlist'"];
qualifier = [[[EOAndQualifier alloc] initWithQualifiers:
vlistExclusionQualifier,
+11 -1
View File
@@ -35,6 +35,7 @@
NSDictionary *provisioning;
NSError *error;
NSString *payloadType, *prefix, *type;
NSNumber *port;
activeUser = [context activeUser];
serverURL = [context serverURL];
@@ -57,11 +58,20 @@
break;
}
port = [serverURL port];
if (!port) {
if ([[serverURL scheme] isEqualToString:@"https"]) {
port = [NSNumber numberWithInt: 443];
} else {
port = [NSNumber numberWithInt: 80];
}
}
provisioning = [NSDictionary dictionaryWithObjectsAndKeys:
[NSArray arrayWithObject: [NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat:@"%@ %@", type, name], [NSString stringWithFormat:@"%@%@", prefix, @"AccountDescription"],
[serverURL host], [NSString stringWithFormat:@"%@%@", prefix, @"HostName"],
[serverURL port], [NSString stringWithFormat:@"%@%@", prefix, @"Port"],
port, [NSString stringWithFormat:@"%@%@", prefix, @"Port"],
path, [NSString stringWithFormat:@"%@%@", prefix, @"PrincipalURL"],
[NSNumber numberWithBool:[[serverURL scheme] isEqualToString:@"https"]], [NSString stringWithFormat:@"%@%@", prefix, @"UseSSL"],
[activeUser login], [NSString stringWithFormat:@"%@%@", prefix, @"Username"],
+1 -1
View File
@@ -33,7 +33,7 @@ static const NSString *POLICY_MIN_DIGIT = @"POLICY_MIN_DIGIT";
static const NSString *POLICY_MIN_SPECIAL_SYMBOLS = @"POLICY_MIN_SPECIAL_SYMBOLS";
static const NSString *POLICY_MIN_LENGTH = @"POLICY_MIN_LENGTH";
static const NSString *SPECIAL_SYMBOL_ALLOWED = @"%$&*(){}!?\\@#.,:;+=";
static const NSString *SPECIAL_SYMBOL_ALLOWED = @"%$&*(){}!?\\@#.,:;+=\\[\\]\\|<>\\/-_";
@implementation SOGoPasswordPolicy
+10 -2
View File
@@ -102,10 +102,12 @@ static const NSString *kCDefaultsLenKey = @"kCDefaultsLenKey";
EOAdaptorChannel *channel;
NSDictionary *row;
NSException *ex;
NSString *sql, *value;
NSString *sql, *result;
id value;
NSArray *attrs;
value = nil;
result = nil;
cm = [GCSChannelManager defaultChannelManager];
channel = [cm acquireOpenChannelForURL: tableURL];
@@ -136,6 +138,12 @@ static const NSString *kCDefaultsLenKey = @"kCDefaultsLenKey";
value = [row objectForKey: fieldName];
if (![value isNotNull])
value = nil; /* we discard any NSNull instance */
if (value && [value isKindOfClass: [NSData class]]) {
result = [NSString stringWithUTF8String: [value bytes]];
} else if (value && [value isKindOfClass: [NSString class]]) {
result = value;
}
}
[cm releaseChannel: channel];
@@ -147,7 +155,7 @@ static const NSString *kCDefaultsLenKey = @"kCDefaultsLenKey";
tableURL];
}
return value;
return result;
}
- (NSString *) generateSQLForInsert: (NSString *) jsonRepresentation
+5
View File
@@ -75,6 +75,11 @@
- (NSArray *) fetchContactsMatching: (NSString *) filter
withCriteria: (NSArray *) criteria
inDomain: (NSString *) domain;
- (NSArray *)fetchContactsMatching:(NSString *)filter
withCriteria:(NSArray *)criteria
inDomain:(NSString *)domain
limit:(int)limit;
- (NSArray *) lookupContactsWithQualifier: (EOQualifier *) qualifier
andSortOrdering: (EOSortOrdering *) ordering
inDomain: (NSString *) domain;
+5
View File
@@ -130,6 +130,11 @@ NSComparisonResult languageSort(id el1, id el2, void *context);
- (NSString *) JWTSecret;
- (NSArray *) disableSharing;
- (NSArray *) disableSharingAnyAuthUser;
- (NSArray *) disableExport;
- (BOOL) enableGlobalAddressBookFirstEntries;
- (int) globalAddressBookFirstEntriesCount;
- (BOOL)isURLEncryptionEnabled;
- (NSString *)urlEncryptionPassphrase;
+43
View File
@@ -835,4 +835,47 @@ NSComparisonResult languageSort(id el1, id el2, void *context)
return passphrase;
}
- (NSArray *) disableSharingAnyAuthUser
{
static NSArray *disableSharingAnyAuthUser = nil;
if (!disableSharingAnyAuthUser)
{
disableSharingAnyAuthUser = [self stringArrayForKey: @"SOGoDisableSharingAnyAuthUser"];
[disableSharingAnyAuthUser retain];
}
return disableSharingAnyAuthUser;
}
- (NSArray *) disableExport
{
static NSArray *disableExport = nil;
if (!disableExport)
{
disableExport = [self stringArrayForKey: @"SOGoDisableExport"];
[disableExport retain];
}
return disableExport;
}
- (BOOL) globalAddressBookFirstEntriesEnabled
{
return [self boolForKey: @"SOGoGlobalAddressBookFirstEntries"];
}
- (int) globalAddressBookFirstEntriesCount
{
int v;
v = [self integerForKey: @"SOGoGlobalAddressBookFirstEntriesCount"];
if (!v)
v = 100;
return v;
}
@end
+7 -1
View File
@@ -156,6 +156,9 @@ extern NSString *SOGoPasswordRecoverySecondaryEmail;
- (void) setMailComposeFontSize: (int) newValue;
- (int) mailComposeFontSize;
- (void) setMailDisplayFullEmail: (BOOL *) newValue;
- (BOOL *) mailDisplayFullEmail;
- (void) setMailDisplayRemoteInlineImages: (NSString *) newValue;
- (NSString *) mailDisplayRemoteInlineImages;
@@ -228,8 +231,11 @@ extern NSString *SOGoPasswordRecoverySecondaryEmail;
- (void) setMailLabelsColors: (NSDictionary *) newValues;
- (NSDictionary *) mailLabelsColors;
- (void)setHideInlineAttachments:(BOOL)newValue;
- (BOOL)hideInlineAttachments;
/* calendar */
- (void) setCalendarCategories: (NSArray *) newValues;
- (void)setCalendarCategories : (NSArray *)newValues;
- (NSArray *) calendarCategories;
- (void) setCalendarCategoriesColors: (NSDictionary *) newValues;
+20
View File
@@ -631,6 +631,16 @@ NSString *SOGoPasswordRecoverySecondaryEmail = @"SecondaryEmail";
return [self integerForKey: @"SOGoMailComposeFontSize"];
}
- (void) setMailDisplayFullEmail: (BOOL *) newValue
{
[self setBool: newValue forKey: @"SOGoMailDisplayFullEmail"];
}
- (BOOL *) mailDisplayFullEmail;
{
return [self boolForKey: @"SOGoMailDisplayFullEmail"];
}
- (void) setMailDisplayRemoteInlineImages: (NSString *) newValue
{
[self setObject: newValue forKey: @"SOGoMailDisplayRemoteInlineImages"];
@@ -959,6 +969,16 @@ NSString *SOGoPasswordRecoverySecondaryEmail = @"SecondaryEmail";
return [self objectForKey: @"SOGoMailLabelsColors"];
}
- (void) setHideInlineAttachments: (BOOL) newValue
{
[self setBool: newValue forKey: @"SOGoMailHideInlineAttachments"];
}
- (BOOL) hideInlineAttachments
{
return [self boolForKey: @"SOGoMailHideInlineAttachments"];
}
- (void) setSieveFilters: (NSArray *) newValue
{
[self setObject: newValue forKey: @"SOGoSieveFilters"];
+18
View File
@@ -924,6 +924,22 @@
- (NSArray *) fetchContactsMatching: (NSString *) filter
withCriteria: (NSArray *) criteria
inDomain: (NSString *) domain
{
if ([filter length] > 0) {
return [self fetchContactsMatching: (NSString *) filter
withCriteria: (NSArray *) criteria
inDomain: (NSString *) domain
limit: -1];
} else {
return [NSMutableArray array];
}
}
- (NSArray *)fetchContactsMatching: (NSString *)filter
withCriteria: (NSArray *)criteria
inDomain: (NSString *)domain
limit: (int)limit
{
EOAdaptorChannel *channel;
NSEnumerator *criteriaList;
@@ -994,6 +1010,8 @@
[sql appendFormat: @" AND %@ IS NULL", _domainField];
}
if (limit > 0)
[sql appendFormat: @" ORDER BY c_cn ASC LIMIT %i", limit];
ex = [channel evaluateExpressionX: sql];
if (!ex)
{
+1
View File
@@ -105,6 +105,7 @@
testEquals([[NSString stringWithString:@"<img vbscript:test"] stringWithoutHTMLInjection: NO], @"<img test");
testEquals([[NSString stringWithString:@"<img javascript:test"] stringWithoutHTMLInjection: NO], @"<img test");
testEquals([[NSString stringWithString:@"<img livescript:test"] stringWithoutHTMLInjection: NO], @"<img test");
testEquals([[NSString stringWithString:@"foobar <form action=\"\">bar</form>"] stringWithoutHTMLInjection: NO], @"foobar <for* action=\"\">bar</for*>");
testEquals([[NSString stringWithString:@"foobar <iframe src=\"\">bar</iframe>"] stringWithoutHTMLInjection: NO], @"foobar <ifr*** src=\"\">bar</iframe>");
testEquals([[NSString stringWithString:@"foobar <img onload=foo bar"] stringWithoutHTMLInjection: NO], @"foobar <img onl***=foo bar");
testEquals([[NSString stringWithString:@"foobar <img onmouseover=foo bar"] stringWithoutHTMLInjection: NO], @"foobar <img onmouseo***=foo bar");
+70 -70
View File
@@ -221,95 +221,95 @@
count = [objects count];
for (i = 0; i < count; i++)
{
content = [[[objects objectAtIndex: i] objectForKey: @"c_content"] stringByTrimmingSpaces];
c_name = [[objects objectAtIndex: i] objectForKey: @"c_name"];
if (is_calendar)
{
// We check for
// BEGIN:VCALENDAR
// ..
// END:VCALENDAR
iCalCalendar *calendar;
{
content = [[[objects objectAtIndex: i] objectForKey: @"c_content"] stringByTrimmingSpaces];
c_name = [[objects objectAtIndex: i] objectForKey: @"c_name"];
if (is_calendar)
{
// We check for
// BEGIN:VCALENDAR
// ..
// END:VCALENDAR
iCalCalendar *calendar;
if ([content length] < 30 ||
if ([content length] < 30 ||
[[content substringToIndex: 15] caseInsensitiveCompare: @"BEGIN:VCALENDAR"] != NSOrderedSame ||
[[content substringFromIndex: [content length]-13] caseInsensitiveCompare: @"END:VCALENDAR"] != NSOrderedSame)
{
NSLog(@"Corrupted calendar item (missing tags) in path %@ with c_name = %@", folder, c_name);
if (delete)
[gcsFolder deleteContentWithName: c_name];
[gcsFolder deleteContentWithName: c_name];
rc = NO;
}
else
else
{
calendar = [iCalCalendar parseSingleFromSource: content];
if (!calendar)
{
NSLog(@"Corrupted calendar item (unparsable) in path %@ with c_name = %@", folder, c_name);
if (delete)
[gcsFolder deleteContentWithName: c_name];
rc = NO;
}
else
{
iCalEvent *event;
{
NSLog(@"Corrupted calendar item (unparsable) in path %@ with c_name = %@", folder, c_name);
if (delete)
[gcsFolder deleteContentWithName: c_name];
rc = NO;
}
else
{
iCalEvent *event;
event = (iCalEvent *) [calendar firstChildWithTag: @"vevent"];
if (event)
{
iCalDateTime *startDate, *endDate;
event = (iCalEvent *) [calendar firstChildWithTag: @"vevent"];
if (event)
{
iCalDateTime *startDate, *endDate;
startDate = (iCalDateTime *) [event uniqueChildWithTag: @"dtstart"];
if (![startDate dateTime])
{
NSLog(@"Missing start date of event in path %@ with c_name = %@ (%@)", folder, c_name, [event summary]);
if (delete)
[gcsFolder deleteContentWithName: c_name];
rc = NO;
}
endDate = (iCalDateTime *) [event uniqueChildWithTag: @"dtend"];
if (![endDate dateTime] && ![event hasDuration])
{
NSLog(@"Missing end date of event in path %@ with c_name = %@ (%@)", folder, c_name, [event summary]);
if (delete)
[gcsFolder deleteContentWithName: c_name];
rc = NO;
}
if ([startDate dateTime] && [endDate dateTime])
{
NSComparisonResult comparison;
startDate = (iCalDateTime *) [event uniqueChildWithTag: @"dtstart"];
if (![startDate dateTime])
{
NSLog(@"Missing start date of event in path %@ with c_name = %@ (%@)", folder, c_name, [event summary]);
if (delete)
[gcsFolder deleteContentWithName: c_name];
rc = NO;
}
endDate = (iCalDateTime *) [event uniqueChildWithTag: @"dtend"];
if (![endDate dateTime] && ![event hasDuration])
{
NSLog(@"Missing end date of event in path %@ with c_name = %@ (%@)", folder, c_name, [event summary]);
if (delete)
[gcsFolder deleteContentWithName: c_name];
rc = NO;
}
if ([startDate dateTime] && [endDate dateTime])
{
NSComparisonResult comparison;
comparison = [[startDate dateTime] compare: [endDate dateTime]];
if (([event isAllDay] && comparison == NSOrderedDescending) ||
(![event isAllDay] && comparison != NSOrderedAscending))
{
NSLog(@"Start date (%@) is not before end date (%@) for event in path %@ with c_name = %@ (%@)",
[startDate dateTime], [endDate dateTime], folder, c_name, [event summary]);
if (delete)
[gcsFolder deleteContentWithName: c_name];
rc = NO;
}
}
}
}
comparison = [[startDate dateTime] compare: [endDate dateTime]];
if (([event isAllDay] && comparison == NSOrderedDescending) ||
(![event isAllDay] && comparison != NSOrderedAscending))
{
NSLog(@"Start date (%@) is not before end date (%@) for event in path %@ with c_name = %@ (%@)",
[startDate dateTime], [endDate dateTime], folder, c_name, [event summary]);
if (delete)
[gcsFolder deleteContentWithName: c_name];
rc = NO;
}
}
}
}
}
}
else
{
NGVCard *card;
}
else
{
NGVCard *card;
card = [NGVCard parseSingleFromSource: content];
card = [NGVCard parseSingleFromSource: content];
if (!card)
if (!card)
{
NSLog(@"Corrupted card item (unparsable) in path %@ with c_name = %@", folder, c_name);
if (delete)
[gcsFolder deleteContentWithName: c_name];
rc = NO;
NSLog(@"Corrupted card item (unparsable) in path %@ with c_name = %@", folder, c_name);
if (delete)
[gcsFolder deleteContentWithName: c_name];
rc = NO;
}
}
}
}
}
return rc;
}
+8 -1
View File
@@ -138,7 +138,14 @@
sessionExpireMinutes = [[arguments objectAtIndex: 0] intValue];
}
if (sessionExpireMinutes >= 0)
NSLog(@"Remove all sessions older than %d min", sessionExpireMinutes);
if (sessionExpireMinutes == 0 && ![[arguments objectAtIndex: 0] isEqualToString:@"0"])
{
//If the input is not a number intValue return 0 so we check that's really the case
[self usage];
}
else if (sessionExpireMinutes >= 0)
{
rc = [self expireUserSessionOlderThan: sessionExpireMinutes];
}
+5 -5
View File
@@ -113,13 +113,13 @@ typedef enum
" remove remove all ACL information of folder for user\n"
" subscribe subscribe user to owner's folder\n"
" unsubscribe unsubscribe user to owner's folder\n"
" owner the user owning the folder\n"
" owner the user owning the folder\n"
" folder the folder - Calendar/<ID> or Contacts/<ID>\n"
" user the user (or group without the @ prefix) to get/set rights for - 'ALL', '<default>', 'anonymous' are supported\n"
" rights rights to add\n\n"
"Example: sogo-tool manage-acl get jdoe Calendar/personal ALL\n\n"
"Note: You can add only one access right at the time. To set them all at once,\n"
" invoke 'remove' first to remove them all.\n\n");
" rights rights to add\n\n"
"Example: sogo-tool manage-acl get jdoe Calendar/personal ALL\n\n"
"Note: You can add only one access right at the time. To set them all at once,\n"
" invoke 'remove' first to remove them all.\n\n");
}
- (BOOL) parseArguments
+65 -50
View File
@@ -86,15 +86,15 @@
/* we want to match the field value case-insensitively */
recordEmail = [[record objectForKey: field] uppercaseString];
if ([recordEmail length])
{
recordList = [doubleEmails objectForKey: recordEmail];
if (!recordList)
{
recordList = [doubleEmails objectForKey: recordEmail];
if (!recordList)
{
recordList = [NSMutableArray arrayWithCapacity: 5];
[doubleEmails setObject: recordList forKey: recordEmail];
}
[recordList addObject: record];
recordList = [NSMutableArray arrayWithCapacity: 5];
[doubleEmails setObject: recordList forKey: recordEmail];
}
[recordList addObject: record];
}
}
- (void) cleanupSingleRecords: (NSMutableDictionary *) doubleEmails
@@ -220,21 +220,20 @@
recordsToRemove = [NSMutableArray arrayWithCapacity: (max - 1)];
for (count = 0; count < max; count++)
{
if (count != keptRecord)
{
if (count != keptRecord)
{
currentRecord = [records objectAtIndex: count];
[recordsToRemove
addObject: [currentRecord objectForKey: @"c_name"]];
}
currentRecord = [records objectAtIndex: count];
[recordsToRemove addObject: [currentRecord objectForKey: @"c_name"]];
}
}
return recordsToRemove;
}
- (NSArray *) records: (NSArray *) records
withLowestScores: (unsigned int *) scores
count: (unsigned int) max
count: (unsigned int) max
{
unsigned int count, highestScore;
int highestScoreRecord;
@@ -242,13 +241,13 @@
highestScore = 0;
highestScoreRecord = -1;
for (count = 0; count < max; count++)
{
if (scores[count] > highestScore)
{
if (scores[count] > highestScore)
{
highestScore = scores[count];
highestScoreRecord = count;
}
highestScore = scores[count];
highestScoreRecord = count;
}
}
if (highestScoreRecord == -1)
highestScoreRecord = 0;
@@ -268,16 +267,15 @@
highestVersion = 0;
for (count = 0; count < max; count++)
{
currentVersion = [[records objectAtIndex: count] objectForKey: @"c_version"];
version = [currentVersion intValue];
if (version > highestVersion)
{
currentVersion
= [[records objectAtIndex: count] objectForKey: @"c_version"];
version = [currentVersion intValue];
if (version > highestVersion)
{
mostModified = count;
highestVersion = version;
}
mostModified = count;
highestVersion = version;
}
}
return mostModified;
}
@@ -291,25 +289,25 @@
amount = 0;
if (!quickFields)
{
quickFields = [NSArray arrayWithObjects: @"c_givenname", @"c_cn",
@"c_sn", @"c_screenname", @"c_l", @"c_mail",
@"c_o", @"c_ou", @"c_telephonenumber", nil];
[quickFields retain];
}
{
quickFields = [NSArray arrayWithObjects: @"c_givenname", @"c_cn",
@"c_sn", @"c_screenname", @"c_l", @"c_mail",
@"c_o", @"c_ou", @"c_telephonenumber", nil];
[quickFields retain];
}
max = [quickFields count];
for (count = 0; count < max; count++)
{
value = [record objectForKey: [quickFields objectAtIndex: count]];
if ([value isKindOfClass: [NSString class]])
{
value = [record objectForKey: [quickFields objectAtIndex: count]];
if ([value isKindOfClass: [NSString class]])
{
if ([value length])
amount++;
}
else if ([value isKindOfClass: [NSNumber class]])
amount++;
if ([value length])
amount++;
}
else if ([value isKindOfClass: [NSNumber class]])
amount++;
}
return amount;
}
@@ -323,15 +321,14 @@
highestQFields = 0;
for (count = 0; count < max; count++)
{
currentQFields = [self amountOfFilledQuickFields: [records objectAtIndex: count]];
if (currentQFields > highestQFields)
{
currentQFields
= [self amountOfFilledQuickFields: [records objectAtIndex: count]];
if (currentQFields > highestQFields)
{
mostQuickFields = count;
highestQFields = currentQFields;
}
mostQuickFields = count;
highestQFields = currentQFields;
}
}
return mostQuickFields;
}
@@ -399,10 +396,28 @@
}
- (void) assignScores: (unsigned int *) scores
toRecords: (NSArray *) records
count: (unsigned int) max
toRecords: (NSArray *) records
count: (unsigned int) max
withCardsInLists: (NSArray *) cardsInLists
{
/*
Records is an Array of record which are duplicates of each other.
The goal here is to know which one to keep and whoch ones to discard.
We will assign a score to each record, the one with the best scores is kept
Record which has been the last modified: +1
Record has the most content: +2
Record has the most quick field set: +3
Record is in a list: +6
If two record have the same, for exemple, content. It's the first one on the list
that will get the points.
If two recors have the same score. t's the first one on the list
that will get the points.
quick fiels are =("c_givenname": Firstname, @"c_cn": Display,
@"c_sn": LastName, @"c_screenname": Screen Name @"c_l": City, @"c_mail": mails,
@"c_o": organisation, @"c_ou": organisation unit, @"c_telephonenumber": telephone)
*/
int recordIndex;
recordIndex = [self mostModifiedRecord: records count: max];
+1 -1
View File
@@ -634,7 +634,7 @@
if (authname == nil || authpwd == nil)
{
NSLog(@"To update Sieve scripts, you must provide the \"-p credentialFile\" parameter");
NSLog(@"To update Sieve scripts, you must provide the \"-c credentialFile\" parameter");
return NO;
}
+3 -3
View File
@@ -210,8 +210,7 @@
GCSFolder *folder;
BOOL rc;
folderPath = [NSString stringWithFormat: @"/Users/%@/Calendar/%@",
username, folderId];
folderPath = [NSString stringWithFormat: @"/Users/%@/Calendar/%@", username, folderId];
folder = [fom folderAtPath: folderPath];
if (folder)
rc = [self truncateEntriesFromFolder: folder usingDate: date];
@@ -238,12 +237,13 @@
// in the default timezone.
s = [NSString stringWithFormat: @"%@ GMT", date];
d = [NSCalendarDate dateWithString: s calendarFormat: @"%Y-%m-%dT%H:%M:%S %Z"];
NSLog(@"Date is: %@", d);
fom = [GCSFolderManager defaultFolderManager];
if (d && fom)
rc = [self processFolder: folder
ofUser: username
date: d
date: d
withFoM: fom];
else
rc = NO;
+3
View File
@@ -146,6 +146,9 @@
[helpString appendFormat: @"\t%-20@-- %@\n",
command, [currentTool objectAtIndex: 1]];
}
[helpString appendString: @"\n Visit https://www.sogo.nu/files/docs/SOGoInstallationGuide.html#_using_sogo_tool to get more infos"];
NSLog (@"%@", helpString);
}
@@ -1,7 +1,7 @@
/* this file is in UTF-8 format! */
"Help" = "Pagalba";
"Close" = "Uždarytis";
"Close" = "Uždaryti";
"Modules" = "Moduliai";
/* Modules short names */
"ACLs" = "ACLs";
@@ -14,7 +14,7 @@
/* Rights module: initial search message */
"Start a search to edit the rights" = "Pradėti paiešką redaguoti savo teisėms";
/* Rights module: Empty search result */
"No matching user" = "Nerasta atitinkantis vartotojas";
"No matching user" = "Nėra atitinkamo naudotojo";
/* Rights module: no selection */
"No resource selected" = "Nėra pasirinkta išteklių";
"Add User" = "Pridėti vartotoją";
@@ -45,7 +45,7 @@
"Reduce" = "Reduzir";
/* tooltip */
"Refresh" = "Refresh";
"Refresh" = "Atualizar";
/* generic.js */
"Unable to subscribe to that folder!"
@@ -109,7 +109,7 @@
"Personal" = "Pessoal";
"To Do" = "Tarefa";
"Later" = "Adiar";
"Forwarded" = "Forwarded";
"Forwarded" = "Encaminhado";
"Return Receipt Sent" = "Confirmação de recebimento enviada";
"a2_Sunday" = "Dom";
"a2_Monday" = "Seg";
@@ -227,9 +227,9 @@
"Move forward" = "Mover para frente";
/* Password Recovery */
"passwordRecovery_Disabled" = "Disabled";
"passwordRecovery_SecretQuestion" = "Secret question";
"passwordRecovery_SecretQuestion1" = "What is the name of your first pet ?";
"passwordRecovery_SecretQuestion2" = "What was your first car ?";
"passwordRecovery_SecretQuestion3" = "What is your favorite movie ?";
"passwordRecovery_SecondaryEmail" = "Secondary E-mail";
"passwordRecovery_Disabled" = "Desabilitado";
"passwordRecovery_SecretQuestion" = "Pergunta secreta";
"passwordRecovery_SecretQuestion1" = "Qual é o nome do seu primeiro animal de estimação?";
"passwordRecovery_SecretQuestion2" = "Qual foi o seu primeiro carro?";
"passwordRecovery_SecretQuestion3" = "Qual é o seu filme favorito ?";
"passwordRecovery_SecondaryEmail" = "E-mail secundário";
+16 -16
View File
@@ -26,15 +26,15 @@
"Subscribe User" = "Prenumeruoti vartotoją";
"Any Authenticated User" = "Bet kokiam autentifikuotam vartotojui";
"Public Access" = "Vieša prieiga";
"Any user not listed above" = "Bet kuris vartotojas, nesantis aukščiau išvardytų";
"Anybody accessing this resource from the public area" = "Kas nors jungiansi prie šio šaltinio iš viešos erdvės";
"Sorry, the user rights can not be configured for that object." = "Atsiprašome, vartotojo teisės negali būti konfiguruojamos šiam objektui.";
"Any user not listed above" = "Bet kuris pirmiau nenurodytas naudotojas";
"Anybody accessing this resource from the public area" = "Visi, kurie prie šio ištekliaus prieina iš viešosios erdvės.";
"Sorry, the user rights can not be configured for that object." = "Atsiprašome, naudotojo teisių šiam objektui konfigūruoti negalima.";
"Any user with an account on this system will be able to access your mailbox \"%{0}\". Are you certain you trust them all?"
= "Bet kuris vartotojas turintis paskyrą šioje sistemoje galės prieiti prie Jūsų elektroninės pašto dėžutės \"%{0}\". Ar Jūs tikrai jais pasitikite?";
"Any user with an account on this system will be able to access your calendar \"%{0}\". Are you certain you trust them all?"
= "Bet kuris vartotojas turintis paskyrą šioje sistemoje galės prieiti prie Jūsų kalendoriaus \"%{0}\". Ar Jūs tikrai jais pasitikite?";
"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?"
= "Potencialiai visi internete galės prieiti prie Jūsų kalendoriaus \"%{0}\", net jei jie ir neturi paskyros šioje sistemoje. Ar ši informacija tinka viešai prieigai?";
= "Prie Jūsų kalendoriaus \"%{0}\" galės prieiti bet kuris internete esantis asmuo, net jei jis neturi paskyros šioje sistemoje. Ar ši informacija tinka viešai prieigai?";
"Any user with an account on this system will be able to access your address book \"%{0}\". Are you certain you trust them all?"
= "Visi vartotojai turintys paskyras šioje sistemoje galės prieiti prie adresų knygos \"%{0}\". Ar Jūs tikrai jais pasitikite?";
"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?"
@@ -51,29 +51,29 @@
"Unable to subscribe to that folder!"
= "Neįmanoma prenumeruoti šio aplanko!";
"You cannot subscribe to a folder that you own!"
= "Jūs negalite prenumeruoti savo aplanko!";
= "Jūs negalite prenumeruoti Jums priklausančio aplanko!";
"Unable to unsubscribe from that folder!"
= "Negalima neprenumeruoti iš šio aplanko!";
= "Nepavyksta atsisakyti prenumeratos šiame aplanke!";
"You cannot unsubscribe from a folder that you own!"
= "Jūs negalite neprenumeruoti savo aplanko!";
= "Negalite atsisakyti prenumeratos iš Jums priklausančio aplanko!";
"Unable to rename that folder!" = "Negalima pervardinti aplanko!";
"You have already subscribed to that folder!"
= "Jūs jau prenumeruojate šį aplanką!";
= "Jūs jau užsiprenumeravote šį aplanką!";
"The user rights cannot be edited for this object!"
= "Vartotojo teisės negali būti keičiamos šiam objektui!";
"A folder by that name already exists." = "Aplankas tokiu pavadinimu jau egzistuoja.";
"You cannot create a list in a shared address book."
= "Jūs negalite sukurti sąrašo pasidalintoje adresų knygoje.";
= "Bendrai naudojamoje adresų knygoje negalima sukurti sąrašo.";
"Warning" = "Įspėjimas";
"Can't contact server" = "Įvyko klaida, kai buvo bandoma susisiekti su serveriu. Prašome bandyti dar kartą.";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "Jums negalima prieiti prie šio modulio ar šios sistemos. Prašome susisiekti su Jūsų sistemos administratoriumi.";
"You don't have the required privileges to perform the operation."
= "Jūs neturite reikalingų teisių atlikti šiam veiksmui.";
"noEmailForDelegation" = "Jūs turite nurodyti adresą, kurį norite perduoti Jūsų kvietime.";
= "Neturite reikalingų teisių šiam veiksmui atlikti.";
"noEmailForDelegation" = "Turite nurodyti adresą, kuriam norite perduoti kvietimą.";
"delegate is organizer" = "Atstovas yra kelionių organizatorius. Prašome nurodyti kitą ";
"delegate is a participant" = "Atstovas jau yra dalyvis.";
"delegate is a group" = "Nurodytas adresas atitinka grupę. Jūs galite tik atstovauti unikalų asmenį.";
"delegate is a group" = "Nurodytas adresas atitinka grupę. Deleguoti galima tik unikaliam asmeniui.";
/* common buttons */
"OK" = "Gerai";
@@ -119,14 +119,14 @@
"a2_Friday" = "Pn";
"a2_Saturday" = "Š";
"Access Rights" = "Prieigos teisės";
"Add User" = "Pridėti vartotoją";
"Add User" = "Pridėti naudotoją";
"Loading" = "Įkrovimas";
"No such user." = "Tokio vartotojo nėra.";
"No such user." = "Tokio naudotojo nėra.";
"You cannot (un)subscribe to a folder that you own!" = "Jūs negalite (atsisakyti) užsiregistruoti šio aplanko, nes jis jums priklauso!";
/* SMIME Certificate field */
"S/MIME Certificate" = "S/MIME Certificate";
"Subject Name" = "Subject Name";
"S/MIME Certificate" = "S/MIME Sertifikatas";
"Subject Name" = "Temos pavadinimas";
"Issuer" = "Issuer";
"streetAddress" = "Street";
"stateOrProvinceName" = "State or Province";
+8 -8
View File
@@ -45,7 +45,7 @@
"Reduce" = "Zmniejsz";
/* tooltip */
"Refresh" = "Refresh";
"Refresh" = "Odśwież";
/* generic.js */
"Unable to subscribe to that folder!"
@@ -109,7 +109,7 @@
"Personal" = "Osobiste";
"To Do" = "Do zrobienia";
"Later" = "Później";
"Forwarded" = "Forwarded";
"Forwarded" = "Przekazane";
"Return Receipt Sent" = "Potwierdzenie wysłane";
"a2_Sunday" = "Ni";
"a2_Monday" = "Pn";
@@ -227,9 +227,9 @@
"Move forward" = "Idź naprzód";
/* Password Recovery */
"passwordRecovery_Disabled" = "Disabled";
"passwordRecovery_SecretQuestion" = "Secret question";
"passwordRecovery_SecretQuestion1" = "What is the name of your first pet ?";
"passwordRecovery_SecretQuestion2" = "What was your first car ?";
"passwordRecovery_SecretQuestion3" = "What is your favorite movie ?";
"passwordRecovery_SecondaryEmail" = "Secondary E-mail";
"passwordRecovery_Disabled" = "Zablokowane";
"passwordRecovery_SecretQuestion" = "Poufne pytanie";
"passwordRecovery_SecretQuestion1" = "Jakie jest imię twojego pierwszego zwierzaka?";
"passwordRecovery_SecretQuestion2" = "Jaki miałeś pierwszy samochód?";
"passwordRecovery_SecretQuestion3" = "Jaki jest twój ulubiony film?";
"passwordRecovery_SecondaryEmail" = "Dodatkowy e-mail";
+24 -1
View File
@@ -101,7 +101,11 @@
NSDictionary *currentUserInfos;
NSMutableDictionary *userData;
id <WOActionResults> result;
WORequest *request;
NSArray *reqPathArray;
NSEnumerator *aclsEnum;
BOOL defaultUserDisable;
SOGoSystemDefaults *sd;
if (!prepared)
{
@@ -142,8 +146,27 @@
}
// Add the 'Any authenticated' user
if (defaultUserID)
request = [[self context] request];
reqPathArray = [request requestHandlerPathArray];
sd = [SOGoSystemDefaults sharedSystemDefaults];
if (NSNotFound != [reqPathArray indexOfObject: kDisableSharingMail]
&& nil != [sd disableSharingAnyAuthUser]
&& NSNotFound != [[sd disableSharingAnyAuthUser] indexOfObject: kDisableSharingMail]) {
defaultUserDisable = YES;
}
if (NSNotFound != [reqPathArray indexOfObject: kDisableSharingContacts]
&& nil != [sd disableSharingAnyAuthUser]
&& NSNotFound != [[sd disableSharingAnyAuthUser] indexOfObject: kDisableSharingContacts]) {
defaultUserDisable = YES;
}
if (NSNotFound != [reqPathArray indexOfObject: kDisableSharingCalendar]
&& nil != [sd disableSharingAnyAuthUser]
&& NSNotFound != [[sd disableSharingAnyAuthUser] indexOfObject: kDisableSharingCalendar]) {
defaultUserDisable = YES;
}
if (!defaultUserDisable && defaultUserID)
{
userData = [NSDictionary dictionaryWithObjectsAndKeys:
defaultUserID, @"uid",
[self labelForKey: @"Any Authenticated User"], @"cn",
+26
View File
@@ -292,6 +292,32 @@
while ((currentUser = [usersList nextObject]))
{
currentUid = [currentUser objectForKey: @"uid"];
//Check if we disable the fact to set rights for defaultsUser
if (!defaultUserID)
ASSIGN (defaultUserID, [[self clientObject] defaultUserID]);
if([currentUid isEqualToString: defaultUserID])
{
if (NSNotFound != [reqPathArray indexOfObject: kDisableSharingMail]
&& nil != [sd disableSharingAnyAuthUser]
&& NSNotFound != [[sd disableSharingAnyAuthUser] indexOfObject: kDisableSharingMail]) {
response = [self responseWithStatus: 403];
return response;
}
if (NSNotFound != [reqPathArray indexOfObject: kDisableSharingContacts]
&& nil != [sd disableSharingAnyAuthUser]
&& NSNotFound != [[sd disableSharingAnyAuthUser] indexOfObject: kDisableSharingContacts]) {
response = [self responseWithStatus: 403];
return response;
}
if (NSNotFound != [reqPathArray indexOfObject: kDisableSharingCalendar]
&& nil != [sd disableSharingAnyAuthUser]
&& NSNotFound != [[sd disableSharingAnyAuthUser] indexOfObject: kDisableSharingCalendar]) {
response = [self responseWithStatus: 403];
return response;
}
}
if (!([self _initRightsForUserID: currentUid]))
{
jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"No such user."]
@@ -193,6 +193,7 @@
"Work" = "العمل";
"Mobile" = "Mobile";
"Pager" = "النداء";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "الزميل، المنافس، العملاء، الصديق، العائلة، شريك تجاري، مقدم خدمة، الصحافة ، كبار الشخصيات";
@@ -193,6 +193,7 @@
"Work" = "Lana";
"Mobile" = "Mugikorra";
"Pager" = "Orrikatzailea";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Lankide, Lehiakide, Bezero, Lagun, Familia, Negoziokidea, Hornitzailea, Prentsa, VIP";
@@ -193,6 +193,7 @@
"Work" = "Posao";
"Mobile" = "Mobilni";
"Pager" = "Pejdžer";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Kolega, Konkurent, Klijent, Prijatelj, Porodica, Poslovni Partner, Provajder, Štampa, VIP";
@@ -193,6 +193,7 @@
"Work" = "Comercial";
"Mobile" = "Celular";
"Pager" = "Pager";
"Download iOS - MacOS configuration profile" = "Baixe perfil de configuração para iOS -MacOS ";
/* categories */
"contacts_category_labels" = "Colega, Concorrente, Cliente, Amigo, Família, Parceiro de Negócios, Provedor, Press, VIP";
@@ -193,6 +193,7 @@
"Work" = "Работа";
"Mobile" = "Мобилно";
"Pager" = "Пейджър";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Колега, Конкурент, Клиент, Приятел, Член на семейството, Бизнес партньор, Доставчик, Преса, VIP";
@@ -193,6 +193,7 @@
"Work" = "Feina";
"Mobile" = "Mòbil";
"Pager" = "Cercapersones";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Colleague, Competitor, Customer, Friend, Family, Business Partner, Provider, Press, VIP";
@@ -193,6 +193,7 @@
"Work" = "工作";
"Mobile" = "手机";
"Pager" = "传呼";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "同事, 竞争对手, 客户, 朋友, 家庭, 工作伙伴, 供应商, 媒体, VIP";
@@ -193,6 +193,7 @@
"Work" = "公司";
"Mobile" = "手機";
"Pager" = "呼叫器";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "同事,競爭對手,客戶,朋友,家人,事業夥伴,供應商,出版社,VIP";
@@ -193,6 +193,7 @@
"Work" = "Posao";
"Mobile" = "Mobitel";
"Pager" = "Pager";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Kolega, Natjecatelj, Kupac, Prijatelj, Obitelj, Poslovni partner, Uslužitelj, Tisak, VIP";
@@ -193,6 +193,7 @@
"Work" = "Zaměstnání";
"Mobile" = "Mobilní telefon";
"Pager" = "Pager";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Kolega, Konkurent, Zákazník, Přítel, Rodina, Obchodní partner, Dodavatel, Tisk, VIP";
@@ -193,6 +193,7 @@
"Work" = "Arbejde";
"Mobile" = "Mobil";
"Pager" = "Personsøger";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS-konfigurationsprofil";
/* categories */
"contacts_category_labels" = "kollega, konkurrent, kunde, ven, familie, samarbejdspartner, udbyder, presse, VIP";
@@ -193,6 +193,7 @@
"Work" = "Werk";
"Mobile" = "Mobiel";
"Pager" = "Pieper";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Collega, Concurrent, Klant, Vriend, Familie, Zakenpartner, Leverancier, Pers, VIP";
@@ -193,7 +193,7 @@
"Work" = "Work";
"Mobile" = "Mobile";
"Pager" = "Pager";
"Download configuration profile" = "Download configuration profile";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Colleague, Competitor, Customer, Friend, Family, Business Partner, Provider, Press, VIP";
@@ -193,6 +193,7 @@
"Work" = "Työ";
"Mobile" = "GSM";
"Pager" = "Hakulaite";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Kollega, Kilpailija, Asiakas, Ystävä, Perhe, Liikekummpani, Palveluntarjoaja, Lehdistö, VIP";
+1 -1
View File
@@ -193,7 +193,7 @@
"Work" = "Travail";
"Mobile" = "Portable";
"Pager" = "Téléavertisseur";
"Download configuration profile" = "Télécharger le profil de configuration";
"Download iOS - MacOS configuration profile" = "Télécharger le profil de configuration pour iOS - MacOS";
/* categories */
"contacts_category_labels" = "Ami, Client, Collègue, Concurrent, Famille, Fournisseur, Partenaire d'affaire, Presse, VIP";
@@ -193,6 +193,7 @@
"Work" = "Traballo";
"Mobile" = "Móbil";
"Pager" = "Buscapersonas";
"Download iOS - MacOS configuration profile" = "Descargar o perfil de configuración de iOS - MacOS";
/* categories */
"contacts_category_labels" = "Colega, Competidor, Cliente, Amigo, Familia, Socio, Provedor, Prensa, VIP";
@@ -193,6 +193,7 @@
"Work" = "Dienstlich";
"Mobile" = "Handy";
"Pager" = "Pager";
"Download iOS - MacOS configuration profile" = "iOS - MacOS Konfigurationsprofil herunterladen";
/* categories */
"contacts_category_labels" = "Anbieter, Familienmitglied, Freund, Geschäftspartner, Kollegin, Konkurrent, Kunde, Lieferant, Presse, VIP";
@@ -193,6 +193,7 @@
"Work" = "עבודה";
"Mobile" = "נייד";
"Pager" = "ביפר";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "עמית, מתחרה, לקוח, חבר, משפחה, שותף עסקי, ספק, עיתונות, VIP";
@@ -193,6 +193,7 @@
"Work" = "Munkahely";
"Mobile" = "Mobiltelefon";
"Pager" = "Személyhívó";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Munkatárs, Versenytárs, Felhasználó, Barát, Család, Üzleti partner, Szolgáltató, Sajtó, VIP";
@@ -193,6 +193,7 @@
"Work" = "Vinnusími";
"Mobile" = "Farsími";
"Pager" = "Símboði";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Samstarfsmaður, Keppinautur, Viðskiptavinur, Vinur, Fjölskylda, Viðskiptatengsl, Þjónustuaðili, Fjölmiðlar, VIP";
@@ -193,6 +193,7 @@
"Work" = "Kerja";
"Mobile" = "Handphone";
"Pager" = "Pager";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Rekan, Pesaing, Pelanggan, Teman, Keluarga, Mitra Bisnis, Provider, Pers, VIP";
@@ -193,6 +193,7 @@
"Work" = "Lavoro";
"Mobile" = "Cellulare";
"Pager" = "Cerca Persone";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Collega, Concorrente, Cliente, Amico, Famiglia, Socio, Provider, Stampa, VIP";
@@ -193,6 +193,7 @@
"Work" = "職業";
"Mobile" = "携帯電話";
"Pager" = "ポケベル";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "同僚, 競合企業, 顧客, 友達, 家族, ビジネスパートナー, プロバイダー, 報道機関, VIP";
@@ -193,6 +193,7 @@
"Work" = "Жұмыс";
"Mobile" = "Ұялы";
"Pager" = "Пейджер";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Әріптес, Бәсекелес, Клиент, Дос, Отбасы, Серіктес, Жеткізуші, Баспасөз, VIP";
@@ -193,6 +193,7 @@
"Work" = "Darbs";
"Mobile" = "Mobilais";
"Pager" = "Peidžeris";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Kolēģi, konkurenti, klienti, draugi, ģimene, biznesa partneri, piegādātāji, Prese, VIP";
@@ -45,8 +45,8 @@
"Copy To" = "Kopijuoti į";
"Add to" = "Pridėti prie";
"To" = "To";
"Carbon Copy (Cc)" = "Carbon Copy (Cc)";
"Blind Carbon Copy (Bcc)" = "Blind Carbon Copy (Bcc)";
"Carbon Copy (Cc)" = "Kopija (Cc)";
"Blind Carbon Copy (Bcc)" = "Nematomoji kopija (Bcc)";
/* Search scope: name fields */
"name" = "Vardas";
@@ -58,7 +58,7 @@
"mozillanickname" = "Antras el. paštas";
/* Search scope: screen name field */
"nsaimid" = "Screen name";
"nsaimid" = "Abonento vardas";
/* Search scope: mail fields */
"mail" = "Mail";
@@ -174,11 +174,11 @@
"Sharing..." = "Bendrinti...";
"Write" = "Rašyti";
"Delete" = "Panaikinti";
"Instant Message" = "Greitoji žinutė";
"Instant Message" = "Žinutė";
"Add..." = "Pridėti";
"Remove" = "Pašalinti";
"Please wait..." = "Prašome palaukti...";
"No possible subscription" = "Nėra įmanomos prenumeratos";
"No possible subscription" = "Prenumerata negalima";
"Preferred" = "Pageidautina";
"Display" = "Rodyti";
"Display Name" = "Ekrano vardas";
@@ -193,6 +193,7 @@
"Work" = "Darbo";
"Mobile" = "Mobilus:";
"Pager" = "Gaviklis:";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Kolega, konkurentas, Klientas, Draugas, Šeima, Verslo partneris, Teikėjas, Spauda, VIP";
@@ -213,28 +214,28 @@
"Timezone" = "Laiko juosta";
"Birthday" = "Gimtadienis";
"Birthday (yyyy-mm-dd)" = "Gimtadienis (yyyy-mm-dd):";
"Freebusy URL" = "Laisvalaikiui ir užimto adresas";
"Freebusy URL" = "Užimtumo adresas";
"Add as..." = "Pridėti kaip...";
"Recipient" = "Gavėjas";
"Carbon Copy" = "Kopija";
"Blind Carbon Copy" = "Nematoma kopija";
"New Addressbook..." = "Nauja adresų knyga...";
"Subscribe to an Addressbook..." = "Įsirašyti į adresų knygą...";
"Remove the selected Addressbook" = "Ištrinti pažymętus iš adresų knygos";
"Subscribe to a shared contact" = "Subscribe to a shared addressbook";
"Search User" = "Ieškoti vartotojo";
"Subscribe to an Addressbook..." = "Prenumeruoti adresų knygą...";
"Remove the selected Addressbook" = "Pašalinti pasirinktą adresų knygą";
"Subscribe to a shared contact" = "Prisijungti prie bendros adresų knygos";
"Search User" = "Ieškoti naudotojo";
"Name of the Address Book" = "Adresų knygos pavadinimas";
"Are you sure you want to delete the selected address book?"
= "Ar jūs įsitikinęs, jog norite ištrinti pažymėtą adresų knygą?";
"Are you sure you want to delete the addressbook \"%{0}\"?"
= "Ar tikrai norite ištrinti adresų knygelę \"%{0}\"?";
= "Ar tikrai norite ištrinti adresų knygą \"%{0}\"?";
"You cannot remove nor unsubscribe from a public addressbook."
= "Jūs negalite pašalinti arba atsisakyti iš viešos adresų knygos.";
"You cannot remove nor unsubscribe from your personal addressbook."
= "Jūs negalite pašalinti arba atsisakyti iš jūsų asmeninės adresų knygos.";
"Are you sure you want to delete the selected contacts?"
= "Ar tikrai norite ištrinti pasirinktus kontaktus?";
"Are you sure you want to delete the card of %{0}?" = "Are you sure you want to delete the card of %{0}?";
"Are you sure you want to delete the card of %{0}?" = "Ar tikrai norite ištrinti kortelę %{0}?";
"You cannot delete the card of \"%{0}\"."
= "Jūs negalite trinti kortelės iš \"%{0}\".";
"You cannot subscribe to a folder that you own!"
@@ -243,15 +244,15 @@
= "Nepavyko prisijungti prie šio aplanko.";
/* security */
"Security" = "Security";
"Security" = "Saugumas";
"Uninstall" = "Uninstall";
"Error reading the card certificate." = "Error reading the card certificate.";
"No certificate associated to card." = "No certificate associated to card.";
/* acls */
"Access rights to" = "Prieigos teisės";
"For user" = "Vartotojui";
"Any Authenticated User" = "Visiems autorizuotiems vartotojams";
"For user" = "Naudotojui";
"Any Authenticated User" = "Visiems autorizuotiems naudotojams";
"Public Access" = "Viešas priėjimas";
"This person can add cards to this addressbook."
= "Šis asmuo gali pridėti korteles šioje adresų knygoje.";
@@ -193,6 +193,7 @@
"Work" = "Работа";
"Mobile" = "Мобилен";
"Pager" = "Пејџер";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Колега, конкурент, клиент, пријател, фамилија, деловен партнер, провајдер, новинар, ВИП";
@@ -193,6 +193,7 @@
"Work" = "Posao";
"Mobile" = "Mobilni";
"Pager" = "Pejdžer";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Kolega, Konkurent, Klijent, Prijatelj, Porodica, Poslovni Partner, Provajder, Novinar, VIP";
@@ -193,6 +193,7 @@
"Work" = "Arbeid";
"Mobile" = "Mobiltelefon";
"Pager" = "Personsøker";
"Download iOS - MacOS configuration profile" = "Last ned konfigurasjonsprofil for iOS - MacOS";
/* categories */
"contacts_category_labels" = "Kollega, Konkurrent, Kunde, Venn, Familie, Forretningspartner, Leverandør, Presse, VIP";
@@ -193,6 +193,7 @@
"Work" = "Arbeid";
"Mobile" = "Mobiltelefon";
"Pager" = "Personsøker";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Colleague, Competitor, Customer, Friend, Family, Business Partner, Provider, Press, VIP";
@@ -193,6 +193,7 @@
"Work" = "Praca";
"Mobile" = "Telefon kom.";
"Pager" = "Pager";
"Download iOS - MacOS configuration profile" = "Pobierz profil konfiguracyjny iOS - MacOS";
/* categories */
"contacts_category_labels" = "Kolega, Konkurencja, Klient, Przyjaciel, Rodzina, Biznes, Dostawca, Prasa, VIP";
@@ -193,6 +193,7 @@
"Work" = "Trabalho";
"Mobile" = "Móvel";
"Pager" = "Pager";
"Download iOS - MacOS configuration profile" = "Descarregar perfil de configuração para iOS - MacOS";
/* categories */
"contacts_category_labels" = "Colega, Concorrência, Cliente, Amigo, Família, Parceiro de Negócios, Fornecedor, Imprensa, VIP";
@@ -193,6 +193,7 @@
"Work" = "Muncă";
"Mobile" = "Mobil";
"Pager" = "Pager";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Coleg, Competitor, Client, Prieten, Familie, Partener de Business, Furnizor, Presă, VIP";
@@ -193,6 +193,7 @@
"Work" = "Рабочий";
"Mobile" = "Мобильный";
"Pager" = "Пейджер";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Коллега, Конкурент, Клиент, Друг, Семья, Партнер, Поставщик, Пресса, VIP";
@@ -340,7 +341,7 @@
"Import" = "Импорт";
"More options" = "Больше опций";
"Role" = "Роль";
"Add Screen Name" = "Добавить имя экрана";
"Add Screen Name" = "Добавить отображаемое имя";
"Custom 1" = "Настраиваемое 1";
"Custom 2" = "Настраиваемое 2";
"Custom 3" = "Настраиваемое 3";
@@ -193,6 +193,7 @@
"Work" = "Посао";
"Mobile" = "Мобилни";
"Pager" = "Пејџер";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Колега, Конкурент, Клијент, Пријатељ, Породица, Пословни Партнер, Провајдер, Новинар, ВИП";
@@ -193,6 +193,7 @@
"Work" = "Posao";
"Mobile" = "Mobilni";
"Pager" = "Pejdžer";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Kolega, Konkurent, Klijent, Prijatelj, Porodica, Poslovni Partner, Provajder, Novinar, VIP";
@@ -193,6 +193,7 @@
"Work" = "Do práce";
"Mobile" = "Mobil";
"Pager" = "Pager";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Kolega, Konkurent, Zákazník, Priateľ, Rodina, Obchodný partner, Dodávateľ, Novinár, VIP";
@@ -193,6 +193,7 @@
"Work" = "Služba";
"Mobile" = "Mobilni telefon";
"Pager" = "Pozivnik";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Kolega, Tekmec, Stranka, Prijatelj, Družina, Poslovni partner, Dobavitelj, Novinar, VIP";
@@ -193,6 +193,7 @@
"Work" = "Trabajo";
"Mobile" = "Celular";
"Pager" = "Buscapersonas";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Colega, Competidor, Cliente, Amigo, Familia, Socio, Proveedor, Prensa, VIP";
@@ -193,6 +193,7 @@
"Work" = "Trabajo";
"Mobile" = "Móvil";
"Pager" = "Busca";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Colega, Competidor, Cliente, Amigo, Familia, Socio, Proveedor, Prensa, VIP";
@@ -193,6 +193,7 @@
"Work" = "Arbete";
"Mobile" = "Mobiltelefon";
"Pager" = "Personsökare";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Kollega, Konkurrent, Kund, Vän, Familj, Affärspartner, Leverantör, Press, VIP";
@@ -193,6 +193,7 @@
"Work" = "İş";
"Mobile" = "Cep";
"Pager" = "Çağrı cihazı";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Meslektaş, Rakip, Müşteri, Arkadaş, Aile, İş Ortağı, Tedarikçi, Basın, VIP";
+39 -25
View File
@@ -19,6 +19,8 @@
02111-1307, USA.
*/
#import <SOGo/SOGoSystemDefaults.h>
#import <Foundation/Foundation.h>
#import <SoObjects/SOGo/NSArray+Utilities.h>
#import <SoObjects/SOGo/NSDictionary+Utilities.h>
@@ -78,35 +80,47 @@ static NSArray *photoTags = nil;
id currentChild;
SOGoContactGCSFolder *sourceFolder;
NSMutableString *content;
SOGoSystemDefaults *sd;
content = [NSMutableString string];
sourceFolder = [self clientObject];
contactsId = [[[[context request] contentAsString] objectFromJSONString] objectForKey: @"uids"];
sd = [SOGoSystemDefaults sharedSystemDefaults];
if (nil != [sd disableExport] && NSNotFound != [[sd disableExport] indexOfObject: kDisableSharingContacts])
{
response = [self responseWithStatus: 401
andJSONRepresentation: [NSDictionary dictionaryWithObject: @"Exporting contacts folder is not authorized"
forKey: @"message"]];
if (!contactsId)
contactsId = [sourceFolder toOneRelationshipKeys];
}
else
{
content = [NSMutableString string];
sourceFolder = [self clientObject];
contactsId = [[[[context request] contentAsString] objectFromJSONString] objectForKey: @"uids"];
uids = [contactsId objectEnumerator];
while ((uid = [uids nextObject]))
{
currentChild = [sourceFolder lookupName: uid
inContext: [self context]
acquire: NO];
if ([currentChild respondsToSelector: @selector (vCard)])
[content appendFormat: @"%@", [[currentChild ldifRecord] ldifRecordAsString]];
else if ([currentChild respondsToSelector: @selector (vList)])
[content appendFormat: @"%@", [[currentChild vList] ldifString]];
[content appendString: @"\n"];
}
if (!contactsId)
contactsId = [sourceFolder toOneRelationshipKeys];
response = [context response];
[response setHeader: @"application/directory; charset=utf-8"
forKey: @"content-type"];
filename = [NSString stringWithFormat: @"%@.ldif",
[[sourceFolder displayName] asQPSubjectString: @"utf-8"]];
disposition = [NSString stringWithFormat: @"attachment; filename=\"%@\"", filename];
[response setHeader: disposition forKey: @"Content-Disposition"];
[response setContent: [content dataUsingEncoding: NSUTF8StringEncoding]];
uids = [contactsId objectEnumerator];
while ((uid = [uids nextObject]))
{
currentChild = [sourceFolder lookupName: uid
inContext: [self context]
acquire: NO];
if ([currentChild respondsToSelector: @selector (vCard)])
[content appendFormat: @"%@", [[currentChild ldifRecord] ldifRecordAsString]];
else if ([currentChild respondsToSelector: @selector (vList)])
[content appendFormat: @"%@", [[currentChild vList] ldifString]];
[content appendString: @"\n"];
}
response = [context response];
[response setHeader: @"application/directory; charset=utf-8"
forKey: @"content-type"];
filename = [NSString stringWithFormat: @"%@.ldif",
[[sourceFolder displayName] asQPSubjectString: @"utf-8"]];
disposition = [NSString stringWithFormat: @"attachment; filename=\"%@\"", filename];
[response setHeader: disposition forKey: @"Content-Disposition"];
[response setContent: [content dataUsingEncoding: NSUTF8StringEncoding]];
}
return response;
}
+14
View File
@@ -507,6 +507,20 @@ Class SOGoContactSourceFolderK, SOGoGCSFolderK;
return result;
}
- (BOOL) isContactExportEnabled {
BOOL result;
SOGoSystemDefaults *sd;
result = YES;
sd = [SOGoSystemDefaults sharedSystemDefaults];
if (nil != [sd disableExport]
&& NSNotFound != [[sd disableExport] indexOfObject: kDisableSharingContacts]) {
result = NO;
}
return result;
}
- (id) defaultAction
{
// NSString *check;
+78 -6
View File
@@ -42,6 +42,7 @@
#import <SoObjects/Contacts/SOGoContactGCSEntry.h>
#import <SoObjects/Contacts/SOGoContactGCSFolder.h>
#import <SoObjects/Contacts/SOGoContactSourceFolder.h>
#import "UIxContactsListActions.h"
@@ -138,19 +139,20 @@
- (NSArray *) contactInfos
{
id <SOGoContactFolder> folder;
id <SOGoContactFolder> folder, sourceFolder;
NSString *ascending, *valueText;
NSArray *results, *searchFields, *fields;
NSMutableArray *filteredContacts, *headers;
NSArray *searchFields, *fields, *folders, *tmpGlobalAddressBookResults;
NSMutableArray *filteredContacts, *headers, *results, *globalAddressBookResults;
NSDictionary *data, *contact;
BOOL excludeLists;
NSComparisonResult ordering;
NSUInteger max, count;
unsigned int i;
NSSortDescriptor *descriptor;
NSMutableDictionary *tmpDict;
if (!contactInfos)
{
folder = [self clientObject];
data = [self requestData];
ascending = [data objectForKey: @"asc"];
@@ -167,11 +169,80 @@
excludeLists = [[data objectForKey: @"excludeLists"] boolValue];
[contactInfos release];
results = [folder lookupContactsWithFilter: valueText
sourceFolder = [self clientObject];
globalAddressBookResults = nil;
if (![sourceFolder isKindOfClass: [SOGoContactSourceFolder class]]) {
folders = [[[self clientObject] container] subFolders];
for (folder in folders) {
// Global AB
if ([folder isKindOfClass: [SOGoContactSourceFolder class]] && (![folder isEqual: [self clientObject]])) {
tmpGlobalAddressBookResults = [folder lookupContactsWithFilter: valueText
onCriteria: nil
sortBy: [self sortKey]
ordering: ordering
inDomain: [[context activeUser] domain]];
if (globalAddressBookResults) {
globalAddressBookResults = [NSMutableArray arrayWithArray: [globalAddressBookResults arrayByAddingObjectsFromArray: tmpGlobalAddressBookResults]];
} else {
globalAddressBookResults = [NSMutableArray arrayWithArray: tmpGlobalAddressBookResults];
}
}
}
// Process for global address book instead of array
if (globalAddressBookResults) {
for (i = 0 ; i < [globalAddressBookResults count] ; i++) {
tmpDict = [NSMutableDictionary dictionaryWithDictionary: [globalAddressBookResults objectAtIndex: i]];
// Flatten emails
if ([tmpDict objectForKey: @"c_mail"] && [[tmpDict objectForKey: @"c_mail"] isKindOfClass:[NSArray class]] && [[tmpDict objectForKey: @"c_mail"] count] > 0) {
[tmpDict setObject:[[tmpDict objectForKey: @"c_mail"] componentsJoinedByString: @","] forKey:@"c_mail"];
}
if ((![tmpDict objectForKey:@"c_cn"] || [tmpDict objectForKey:@"c_cn"] == [NSNull null]) && [tmpDict objectForKey:@"c_name"]) {
// Replace c_cn if not filled
[tmpDict setObject:[tmpDict objectForKey:@"c_name"] forKey:@"c_cn"];
}
if ((![tmpDict objectForKey:@"c_uid"] || [tmpDict objectForKey:@"c_uid"] == [NSNull null]) && [tmpDict objectForKey:@"c_id"]) {
// Replace c_uid if not filled
[tmpDict setObject:[tmpDict objectForKey:@"c_uid"] forKey:@"c_id"];
}
[globalAddressBookResults replaceObjectAtIndex:i withObject: tmpDict];
}
}
}
// Current AB
results = [NSMutableArray arrayWithArray: [sourceFolder lookupContactsWithFilter: valueText
onCriteria: searchFields
sortBy: [self sortKey]
ordering: ordering
inDomain: [[context activeUser] domain]];
inDomain: [[context activeUser] domain]]];
// Add sourceid for current AB
for (i = 0 ; i < [results count] ; i++) {
tmpDict = [NSMutableDictionary dictionaryWithDictionary: [results objectAtIndex: i]];
// Add sourceid
[tmpDict setObject:[sourceFolder nameInContainer] forKey:@"sourceid"];
[results replaceObjectAtIndex:i withObject: tmpDict];
}
if (globalAddressBookResults && results) { // Both results, merge arrays
// Results in personal folder will appear first
results = [results arrayByAddingObjectsFromArray: globalAddressBookResults];
} else if (globalAddressBookResults) { // No results in personal AB
results = globalAddressBookResults;
}
// Sort the results
descriptor = [[NSSortDescriptor alloc] initWithKey: [self sortKey]
ascending: ordering];
results = [results sortedArrayUsingDescriptors: [NSArray arrayWithObjects: descriptor, nil]];
[descriptor release];
if (excludeLists)
{
filteredContacts = [NSMutableArray array];
@@ -198,6 +269,7 @@
count = 0;
fields = [[contactInfos objectAtIndex: 0] allKeys];
[headers addObject: fields];
while (count < max)
{
[headers addObject: [[contactInfos objectAtIndex: count] objectsForKeys: fields
+32 -3
View File
@@ -35,6 +35,8 @@
#import <SOGo/NSDictionary+Utilities.h>
#import <SOGo/NSString+Utilities.h>
#import <SoObjects/Contacts/SOGoContactSourceFolder.h>
#import <Contacts/SOGoContactGCSEntry.h>
#import <Contacts/SOGoContactGCSFolder.h>
@@ -173,12 +175,14 @@
{
NSAutoreleasePool *pool;
NSDictionary *values;
NSArray *initialReferences, *refs, *emails;
NSArray *initialReferences, *refs, *emails, *folders;
NSDictionary *currentReference;
NSString *uid, *workMail, *fn, *newUID;
int i, count;
NGVCardReference *cardReference;
SOGoContactGCSFolder *folder;
NSMutableArray *publicSourceIDs;
id f;
folder = [co container];
@@ -200,12 +204,25 @@
count = [references count];
pool = [[NSAutoreleasePool alloc] init];
// List container name of global AB
folders = [[[co lookupUserFolder] privateContacts: @"Contacts" inContext: nil] subFolders];
publicSourceIDs = [[NSMutableArray alloc] init];
for (f in folders) {
if ([f isKindOfClass:[SOGoContactSourceFolder class]]) {
[publicSourceIDs addObject: [f nameInContainer]];
}
}
for (i = 0; i < count; i++)
{
if ([[references objectAtIndex: i] isKindOfClass: [NSDictionary class]])
{
currentReference = [references objectAtIndex: i];
uid = [currentReference objectForKey: @"id"];
if (![self cardReferences: [list cardReferences]
contain: uid])
{
@@ -222,8 +239,18 @@
[list addCardReference: cardReference];
}
else
{
else if ([currentReference objectForKey:@"sourceid"] && [publicSourceIDs containsObject:[currentReference objectForKey:@"sourceid"]]) {
// Create reference for shared AB (public)
uid = [currentReference objectForKey: @"id"];
emails = [[currentReference objectForKey: @"c_mail"] componentsSeparatedByString: @","];
cardReference = [NGVCardReference elementWithTag: @"card"];
[cardReference setFn: [currentReference objectForKey: @"c_cn"]];
if ([emails count])
[cardReference setEmail: [emails objectAtIndex: 0]];
[cardReference setReference: uid];
[list addCardReference: cardReference];
} else {
// Invalid UID or no UID
NGVCard *newCard;
CardElement *newWorkMail;
@@ -264,6 +291,8 @@
pool = [[NSAutoreleasePool alloc] init];
}
}
[publicSourceIDs release];
}
- (BOOL) cardReferences: (NSArray *) references
+19 -1
View File
@@ -26,6 +26,8 @@
#import <SOGo/NSArray+Utilities.h>
#import <SOGo/NSDictionary+Utilities.h>
#import <SoObjects/Contacts/SOGoContactSourceFolder.h>
#import "UIxListView.h"
@implementation UIxListView
@@ -36,6 +38,7 @@
NGVCardReference *card, *cardCopy;
int i, count;
id test;
NSArray *folders;
invalid = [NSMutableArray array];
@@ -46,7 +49,22 @@
test = [[co container] lookupName: [card reference]
inContext: context
acquire: NO];
if ([test isKindOfClass: [NSException class]])
if ([test isKindOfClass: [NSException class]]) {
folders = [[[co lookupUserFolder] privateContacts: @"Contacts" inContext: nil] subFolders];
id <SOGoContactFolder> folder;
for (folder in folders) {
// Global AB
if ([folder isKindOfClass: [SOGoContactSourceFolder class]]) {
test = [folder lookupName: [card reference]
inContext: context
acquire: NO];
if (test && ![test isKindOfClass: [NSException class]]) break;
}
}
}
if (test && [test isKindOfClass: [NSException class]])
{
//NSLog (@"%@ not found", [card reference]);
cardCopy = [card copy];
@@ -193,6 +193,7 @@
"Work" = "Робочий";
"Mobile" = "Мобільний";
"Pager" = "Пейджер";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Робота, Конкуренти, Клієнти, Друзі, Родина, Партнери, Постачальники, Преса, ВІП";
@@ -193,6 +193,7 @@
"Work" = "Gwaith";
"Mobile" = "Symudol";
"Pager" = "Peiriant galw";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
/* categories */
"contacts_category_labels" = "Cydweithiwr, Cystadleuydd, Cwsmer, Ffrind, Teulu, Partner Busnes, Darparwr, Y Wasg, Pwysigyn";
@@ -8,9 +8,9 @@ TENTATIVE = "preliminarus";
organized_by_you = "jūsų organizuojama";
you_are_an_attendee = "esate dalyvis";
add_info_text = "iMIP 'Pridėti' prašymus dar nepalaiko SOGo.";
publish_info_text = "Siuntėjas turi pranešti jums apie pridedamą įvykį.";
publish_info_text = "Siuntėjas turi pranešti jums apie pridėtą įvykį.";
cancel_info_text = "Jūsų kvietimas ar visas renginys buvo atšauktas.";
request_info_no_attendee = "siūlo susitikimą dalyviams. Jūs gaunate šį laišką kaip pranešimą, bet Jūs nesate dalyvis.";
request_info_no_attendee = "siūlo susitikimą dalyviams. Šį laišką gaunate kaip pranešimą, bet Jūs nesate dalyvis.";
Appointment = "Paskyrimas";
"Status Update" = "Būsenos atnaujinimas";
was = "buvo";
@@ -18,7 +18,7 @@ was = "buvo";
Organizer = "Organizatorius";
Time = "Laikas";
Attendees = "Dalyviai";
request_info = "kviečia jus dalyvauti posėdyje.";
request_info = "kviečia dalyvauti susitikime.";
"Add to calendar" = "Pridėti į kalendorių";
"Delete from calendar" = "Ištrinti iš kalendoriaus";
"Update status" = "Atnaujinti būseną";
@@ -32,7 +32,7 @@ Tentative = "Preliminarus";
reply_info_no_attendee = "Jūs gavote atsakymą pagal suplanuotą įvykį, bet siuntėjas nėra įvykio dalyvis";
reply_info = "Šis atsakymas į susitikimo kvietimą yra jūsų baigtas.";
"to" = "į";
"Untitled" = "Neaiškus";
"Untitled" = "Be pavadinimo";
"Size" = "Dydis";
"Subject" = "Tema";
"From" = "Nuo";
+19 -7
View File
@@ -27,6 +27,8 @@
#import <NGMime/NGMimeBodyPart.h>
#import <NGMime/NGMimeMultipartBody.h>
#import <SOGo/SOGoUserDefaults.h>
#import <UI/MailerUI/WOContext+UIxMailer.h>
#import "UIxMailRenderingContext.h"
@@ -98,6 +100,7 @@
NSString *contentType;
id viewer, info;
NSArray *parts;
SOGoUserDefaults *ud;
NSUInteger i, max;
@@ -119,14 +122,23 @@
[self setChildInfo: [parts objectAtIndex: i]];
info = [self childInfo];
viewer = [[[self context] mailRenderingContext] viewerForBodyInfo: info];
[viewer setBodyInfo: info];
[viewer setPartPath: [self childPartPath]];
if ([self decodedFlatContent])
[viewer setDecodedContent: [parts objectAtIndex: i]];
[viewer setAttachmentIds: attachmentIds];
ud = [[[self context] activeUser] userDefaults];
[renderedParts addObject: [viewer renderedPart]];
if (!([info objectForKey:@"disposition"]
&& [[info objectForKey:@"disposition"] objectForKey:@"type"]
&& [[[[info objectForKey:@"disposition"] objectForKey:@"type"] uppercaseString] isEqualToString:@"INLINE"]
&& [ud hideInlineAttachments])) {
viewer = [[[self context] mailRenderingContext] viewerForBodyInfo: info];
[viewer setBodyInfo: info];
[viewer setPartPath: [self childPartPath]];
if ([self decodedFlatContent])
[viewer setDecodedContent: [parts objectAtIndex: i]];
[viewer setAttachmentIds: attachmentIds];
[renderedParts addObject: [viewer renderedPart]];
}
}
contentType = [NSString stringWithFormat: @"%@/%@",
@@ -319,7 +319,6 @@
"Thread As Read" = "الموضوع مقروء";
"As Read By Date..." = "كما يقرأ من التاريخ";
"All Read" = "الكل مقروء";
"Flag" = "علم";
"As Junk" = "غير هام";
"As Not Junk" = "ليس غير هام";
"Run Junk Mail Controls" = "تشغيل عناصر تحكم البريد غير المرغوب فيه";

Some files were not shown because too many files have changed in this diff Show More