mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-02-17 07:33:57 +00:00
doc(sogo-tool): Add doc to detailed sogo-tool
This commit is contained in:
@@ -3312,6 +3312,489 @@ 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.
|
||||
* _*Warning*_ Putting anything other that a number will be count as 0 minutes...
|
||||
|
||||
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 --help #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
|
||||
---------
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -138,6 +138,8 @@
|
||||
sessionExpireMinutes = [[arguments objectAtIndex: 0] intValue];
|
||||
}
|
||||
|
||||
NSLog(@"Remove all sessions older than %d min", sessionExpireMinutes);
|
||||
|
||||
if (sessionExpireMinutes >= 0)
|
||||
{
|
||||
rc = [self expireUserSessionOlderThan: sessionExpireMinutes];
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user