Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
5f948965d0
@ -1,133 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import subprocess
|
|
||||||
from configobj import ConfigObj
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
from MAPI.Util import *
|
|
||||||
import kopano
|
|
||||||
# Try simplejson if json is not available
|
|
||||||
try:
|
|
||||||
import json
|
|
||||||
except ImportError:
|
|
||||||
import simplejson as json
|
|
||||||
|
|
||||||
|
|
||||||
def encode(value):
|
|
||||||
proc = subprocess.Popen(["php", "deencode.php", "encode", value], stdout=subprocess.PIPE)
|
|
||||||
return proc.communicate()[0]
|
|
||||||
|
|
||||||
|
|
||||||
def opt_args():
|
|
||||||
parser = kopano.parser('skpcfmUP')
|
|
||||||
parser.add_option("--user", dest="user", action="store", help="username")
|
|
||||||
parser.add_option("--file", dest="file", default=[], action="store", help="config file(s) separate by ',' ")
|
|
||||||
parser.add_option("--overwrite", dest="overwrite", action="store_true", help="overwrite files settings")
|
|
||||||
parser.add_option("--default", dest="default", action="store_true",
|
|
||||||
help="use default user and password in the configfile")
|
|
||||||
|
|
||||||
return parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
def read_settings(options):
|
|
||||||
|
|
||||||
try:
|
|
||||||
user = kopano.Server(options).user(options.user)
|
|
||||||
except MAPIErrorLogonFailed as e:
|
|
||||||
print('User \'{}\' not found ({})'.format(options.user, e))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
if not user.store:
|
|
||||||
print('User \'{}\' has no user store ({})'.format(options.user, e))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
try:
|
|
||||||
mapisettings = user.store.prop(PR_EC_WEBACCESS_SETTINGS_JSON).value
|
|
||||||
return mapisettings
|
|
||||||
except Exception:
|
|
||||||
print('{}: Has no or no valid WebApp settings creating empty config tree'.format(user.name))
|
|
||||||
return '{"settings": {"zarafa": {"v1": {"contexts": {"mail": {}}}}}}'
|
|
||||||
|
|
||||||
|
|
||||||
def write_settings(data, options):
|
|
||||||
user = kopano.Server(options).user(options.user)
|
|
||||||
user.store.create_prop(PR_EC_WEBACCESS_SETTINGS_JSON, data.encode('utf-8'))
|
|
||||||
print('Writing settings for user \'{}\''.format(user.fullname))
|
|
||||||
|
|
||||||
|
|
||||||
def files(options):
|
|
||||||
filesjson = '{'
|
|
||||||
if options.overwrite:
|
|
||||||
filesjson = '{"accounts": {'
|
|
||||||
num = 0
|
|
||||||
files = options.file.split(',')
|
|
||||||
for file in files:
|
|
||||||
configfile = ConfigObj(file)
|
|
||||||
if options.default:
|
|
||||||
username = configfile['setting']['default_user']
|
|
||||||
else:
|
|
||||||
username = options.user
|
|
||||||
if num != 0:
|
|
||||||
filesjson += ','
|
|
||||||
id = uuid.uuid4()
|
|
||||||
filesjson += '''
|
|
||||||
"%s": {
|
|
||||||
"status": "ok",
|
|
||||||
"backend_config": {
|
|
||||||
"server_path": "%s",
|
|
||||||
"workgroup": "%s",
|
|
||||||
"server_address": "%s",
|
|
||||||
"server_ssl": %s,
|
|
||||||
"current_account_id": "%s",
|
|
||||||
"use_zarafa_credentials": %s,
|
|
||||||
"user": "%s",
|
|
||||||
"password": "%s",
|
|
||||||
"server_port": "%s"
|
|
||||||
},
|
|
||||||
"cannot_change": false,
|
|
||||||
"name": "%s",
|
|
||||||
"status_description": "Account is ready to use.",
|
|
||||||
"id": "%s",
|
|
||||||
"backend_features": {
|
|
||||||
"Sharing": true,
|
|
||||||
"VersionInfo": true,
|
|
||||||
"Quota": true
|
|
||||||
},
|
|
||||||
"backend": "%s"
|
|
||||||
}''' % (id, encode(configfile['setting']['server_path']), encode(configfile['setting']['workgroup']),
|
|
||||||
encode(configfile['setting']['server_address']), configfile['setting']['server_ssl'],
|
|
||||||
encode('d4cacda458a2a26c301f2b7d75ada530'), configfile['setting']['use_zarafa_credentials'],
|
|
||||||
encode(username), encode(configfile['setting']['default_password']),
|
|
||||||
encode(configfile['setting']['server_port']), configfile['setting']['name'], id, configfile['setting']['type'])
|
|
||||||
num += 1
|
|
||||||
if options.overwrite:
|
|
||||||
filesjson += '}}'
|
|
||||||
else:
|
|
||||||
filesjson += '}'
|
|
||||||
return filesjson
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
options, args = opt_args()
|
|
||||||
|
|
||||||
data = read_settings(options)
|
|
||||||
webappsettings = json.loads(data)
|
|
||||||
|
|
||||||
if not webappsettings['settings']['zarafa']['v1'].get('plugins'):
|
|
||||||
webappsettings['settings']['zarafa']['v1']['plugins'] = {}
|
|
||||||
|
|
||||||
if options.overwrite:
|
|
||||||
webappsettings['settings']['zarafa']['v1']['plugins']['files'] = json.loads(files(options))
|
|
||||||
else:
|
|
||||||
if not webappsettings['settings']['zarafa']['v1']['plugins'].get('files'):
|
|
||||||
webappsettings['settings']['zarafa']['v1']['plugins']['files'] = {}
|
|
||||||
if not webappsettings['settings']['zarafa']['v1']['plugins']['files'].get('accounts'):
|
|
||||||
webappsettings['settings']['zarafa']['v1']['plugins']['files']['accounts'] = {}
|
|
||||||
webappsettings['settings']['zarafa']['v1']['plugins']['files']['accounts'].update(json.loads(files(options)))
|
|
||||||
|
|
||||||
write_settings(json.dumps(webappsettings), options)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
|||||||
Inject-files.py
|
|
||||||
===============
|
|
||||||
|
|
||||||
Script to inject the files setting into the users profile.
|
|
||||||
|
|
||||||
|
|
||||||
Files backend supported
|
|
||||||
=======================
|
|
||||||
|
|
||||||
* SMB
|
|
||||||
* Owncloud
|
|
||||||
* Webddav
|
|
||||||
|
|
||||||
|
|
||||||
Examples
|
|
||||||
========
|
|
||||||
|
|
||||||
python inject-files -user test --file owncloud.cfg,smb.cfg
|
|
||||||
|
|
||||||
Use the username and password provided in the configfile
|
|
||||||
|
|
||||||
python inject-files -user test --file owncloud.cfg,smb.cfg --default
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import kopano
|
|
||||||
from MAPI.Util import *
|
|
||||||
|
|
||||||
try:
|
|
||||||
import json
|
|
||||||
except ImportError:
|
|
||||||
import simplejson as json
|
|
||||||
|
|
||||||
|
|
||||||
def opt_args():
|
|
||||||
parser = kopano.parser('skpcf')
|
|
||||||
parser.add_option("--user", dest="user", action="store", help="Dump signatures for user")
|
|
||||||
return parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
options, args = opt_args()
|
|
||||||
if not options.user:
|
|
||||||
print 'Please use:\n %s --user <username>' % (sys.argv[0])
|
|
||||||
else:
|
|
||||||
user = kopano.Server(options=options).user(options.user)
|
|
||||||
try:
|
|
||||||
settings = json.loads(user.store.prop(PR_EC_WEBACCESS_SETTINGS_JSON).value)
|
|
||||||
except Exception as e:
|
|
||||||
print 'Could not load WebApp settings for user %s (Error: %s)' % (user.name, repr(e))
|
|
||||||
else:
|
|
||||||
if len(settings['settings']['zarafa']['v1']['contexts']['mail']):
|
|
||||||
if 'signatures' in settings['settings']['zarafa']['v1']['contexts']['mail']:
|
|
||||||
for item in settings['settings']['zarafa']['v1']['contexts']['mail']['signatures']['all']:
|
|
||||||
name = settings['settings']['zarafa']['v1']['contexts']['mail']['signatures']['all'][item]['name']
|
|
||||||
filename = '%s-%s-%s.html' % (user.name, name.replace(' ', '-'), item)
|
|
||||||
with open(filename, 'w') as outfile:
|
|
||||||
print 'Dumping: \'%s\' to \'%s\' ' % (name, filename)
|
|
||||||
outfile.write(settings['settings']['zarafa']['v1']['contexts']['mail']['signatures']['all'][item]['content'].encode('utf-8'))
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
@ -1,12 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
dump_webapp_signatures.py
|
|
||||||
=========================
|
|
||||||
Dumps all the signatures in a users Webapp to seperate files, meant as companion to the script setdefaultsignature.py as delivered with Webapp (see /usr/share/doc/kopano-webapp/scripts/signatures/ on your Webapp server.)
|
|
||||||
The files will be written in the current directory.
|
|
||||||
|
|
||||||
#### Usage:
|
|
||||||
```
|
|
||||||
python dump_webapp_signatures.py --user user
|
|
||||||
```
|
|
||||||
|
|
22
files_admin/README.md
Normal file
22
files_admin/README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Files Admin
|
||||||
|
|
||||||
|
Files admin is a command-line interface to modify, inject and export kopano-files settings.
|
||||||
|
|
||||||
|
# Files backend supported
|
||||||
|
|
||||||
|
* SMB
|
||||||
|
* Owncloud
|
||||||
|
* Webddav
|
||||||
|
|
||||||
|
# Example Usage
|
||||||
|
|
||||||
|
Inject settings from owncloud and smb config file
|
||||||
|
> python files_admin -user John --file owncloud.cfg,smb.cfg
|
||||||
|
|
||||||
|
Use the username and password provided in the config file
|
||||||
|
> python files_admin -user John --file owncloud.cfg,smb.cfg --default
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
|
||||||
|
- python-kopano
|
||||||
|
- python-mapi
|
136
files_admin/files_admin.py
Normal file
136
files_admin/files_admin.py
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import subprocess
|
||||||
|
from configobj import ConfigObj
|
||||||
|
import uuid
|
||||||
|
from MAPI.Util import *
|
||||||
|
|
||||||
|
import kopano
|
||||||
|
|
||||||
|
# Try simplejson if json is not available
|
||||||
|
try:
|
||||||
|
import json
|
||||||
|
except ImportError:
|
||||||
|
import simplejson as json
|
||||||
|
|
||||||
|
|
||||||
|
def encode(value):
|
||||||
|
output = subprocess.check_output(["php", "deencode.php", "encode", value])
|
||||||
|
return output.strip()
|
||||||
|
|
||||||
|
|
||||||
|
def opt_args():
|
||||||
|
parser = kopano.parser('skpcfm')
|
||||||
|
parser.add_option("--user", dest="user", action="store", help="username")
|
||||||
|
parser.add_option("--ssl", dest="ssl", action="store_true", help="Use localhost on port 443")
|
||||||
|
parser.add_option("--hostname", dest="hostname", action="store", help="hostname")
|
||||||
|
|
||||||
|
parser.add_option("--file", dest="file", default=[], action="store", help="config file(s) separate by ',' ")
|
||||||
|
parser.add_option("--default", dest="default", action="store_true",
|
||||||
|
help="use default user and password in the configfile")
|
||||||
|
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def read_settings(user):
|
||||||
|
try:
|
||||||
|
mapisettings = user.store.prop(PR_EC_WEBACCESS_SETTINGS_JSON).value.decode('utf-8')
|
||||||
|
settings = json.loads(mapisettings)
|
||||||
|
except Exception as e:
|
||||||
|
print('{}: Has no or no valid WebApp settings creating empty config tree'.format(user.name))
|
||||||
|
settings = json.loads('{"settings": {"zarafa": {"v1": {"contexts": {"mail": {}}}}}}')
|
||||||
|
return settings
|
||||||
|
|
||||||
|
|
||||||
|
def write_settings(user, setting):
|
||||||
|
try:
|
||||||
|
user.store.create_prop(PR_EC_WEBACCESS_SETTINGS_JSON, setting.encode('utf-8'))
|
||||||
|
except Exception as e:
|
||||||
|
print('{}: Error Writing WebApp settings for user: {}'.format(e, user.name))
|
||||||
|
|
||||||
|
|
||||||
|
def files(options):
|
||||||
|
filesjson = {'accounts': {}}
|
||||||
|
|
||||||
|
files = options.file.split(',')
|
||||||
|
for file in files:
|
||||||
|
configfile = ConfigObj(file)
|
||||||
|
if configfile['setting']['use_zarafa_credentials']:
|
||||||
|
username = configfile['setting']['default_user']
|
||||||
|
else:
|
||||||
|
username = options.user
|
||||||
|
password = encode(configfile['setting']['default_password'])
|
||||||
|
backendoptions = {
|
||||||
|
'ftp': {"backend_features": {
|
||||||
|
"Streaming": "true", }},
|
||||||
|
'webdav': {"backend_features": {
|
||||||
|
"Quota": "true",
|
||||||
|
"VersionInfo": "true"}},
|
||||||
|
'owncloud': {"backend_features": {
|
||||||
|
"Quota": "true",
|
||||||
|
"Sharing": "true",
|
||||||
|
"VersionInfo": "true"}},
|
||||||
|
'smb': {"backend_features": {
|
||||||
|
"Quota": "true",
|
||||||
|
"Streaming": "true",
|
||||||
|
"VersionInfo": "true"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
if file == 'seafile.cfg':
|
||||||
|
password = encode(options.user)
|
||||||
|
username = kopano.Server(options).user(options.user).email
|
||||||
|
|
||||||
|
if 'local' in file:
|
||||||
|
if options.ssl:
|
||||||
|
port = '443'
|
||||||
|
address = options.hostname
|
||||||
|
ssl = 'true'
|
||||||
|
else:
|
||||||
|
port = configfile['setting']['server_port']
|
||||||
|
address = configfile['setting']['server_address']
|
||||||
|
ssl = configfile['setting']['server_ssl']
|
||||||
|
else:
|
||||||
|
port = configfile['setting']['server_port']
|
||||||
|
address = configfile['setting']['server_address']
|
||||||
|
ssl = configfile['setting']['server_ssl']
|
||||||
|
id = str(uuid.uuid4())
|
||||||
|
filesjson['accounts'][id] = {
|
||||||
|
"status": "ok",
|
||||||
|
"backend_config": {
|
||||||
|
"server_path": encode(configfile['setting']['server_path']).decode('utf-8'),
|
||||||
|
"workgroup": encode(configfile['setting']['workgroup']).decode('utf-8'),
|
||||||
|
"server_address": encode(address).decode('utf-8'),
|
||||||
|
"server_ssl": ssl,
|
||||||
|
"current_account_id": encode('d4cacda458a2a26c301f2b7d75ada530').decode('utf-8'),
|
||||||
|
"use_zarafa_credentials": configfile['setting']['use_zarafa_credentials'],
|
||||||
|
"user": encode(username).decode('utf-8'),
|
||||||
|
"password": password.decode('utf-8'),
|
||||||
|
"server_port": encode(port).decode('utf-8')
|
||||||
|
},
|
||||||
|
"cannot_change": False,
|
||||||
|
"name": configfile['setting']['name'],
|
||||||
|
"status_description": "Account is ready to use.",
|
||||||
|
"id": id,
|
||||||
|
"backend_features": backendoptions[configfile['setting']['type'].lower()]['backend_features'],
|
||||||
|
"backend": configfile['setting']['type']
|
||||||
|
}
|
||||||
|
|
||||||
|
if configfile['setting']['type'].lower() == 'ftp':
|
||||||
|
filesjson['accounts'][id]['backend_config']['server_pasv'] = configfile['setting']['server_pasv']
|
||||||
|
|
||||||
|
return filesjson
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
options, args = opt_args()
|
||||||
|
|
||||||
|
server = kopano.Server(options)
|
||||||
|
user = server.user(options.user)
|
||||||
|
webappsettings = read_settings(user)
|
||||||
|
if not webappsettings['settings']['zarafa']['v1'].get('plugins'):
|
||||||
|
webappsettings['settings']['zarafa']['v1']['plugins'] = {}
|
||||||
|
webappsettings['settings']['zarafa']['v1']['plugins']['files'] = files(options)
|
||||||
|
write_settings(user, json.dumps(webappsettings))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
@ -1,5 +1,4 @@
|
|||||||
[setting]
|
[setting]
|
||||||
|
|
||||||
name = Owncloud share
|
name = Owncloud share
|
||||||
type = Owncloud
|
type = Owncloud
|
||||||
workgroup =
|
workgroup =
|
@ -1,25 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
# set_webapp_default_signature.py
|
|
||||||
|
|
||||||
Add and set a Default signature in Webapp for user(s), will overwrite any other default.
|
|
||||||
Please use a signature as dumped with dump_webapp_signatures.py
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
### Set signature of a local user on the local server
|
|
||||||
```
|
|
||||||
./set_webapp_default_signature.py -u user1 -f user2-signature.sig
|
|
||||||
```
|
|
||||||
|
|
||||||
### Set signature multiple local users on the local server
|
|
||||||
```
|
|
||||||
./set_webapp_default_signature.py -u user1 -u user3 -f user2-signature.sig
|
|
||||||
```
|
|
||||||
|
|
||||||
### Set signature for all local users on the local server
|
|
||||||
```
|
|
||||||
./set_webapp_default_signature.py -a -f user2-signature.sig
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# coding=utf-8
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
||||||
"""
|
|
||||||
Set A Default WebApp Signature.
|
|
||||||
"""
|
|
||||||
import json
|
|
||||||
import kopano
|
|
||||||
from MAPI.Tags import *
|
|
||||||
|
|
||||||
|
|
||||||
def read_settings(user):
|
|
||||||
try:
|
|
||||||
mapisettings = user.store.prop(PR_EC_WEBACCESS_SETTINGS_JSON).value
|
|
||||||
settings = json.loads(mapisettings)
|
|
||||||
except Exception as e:
|
|
||||||
print '%s: Has no or no valid WebApp settings creating empty config tree' % user.name
|
|
||||||
settings = json.loads(
|
|
||||||
'{"settings": {"zarafa": {"v1": {"contexts": {"mail": {}}}}}}')
|
|
||||||
return settings
|
|
||||||
|
|
||||||
|
|
||||||
def write_settings(user, webappsettings):
|
|
||||||
try:
|
|
||||||
user.store.create_prop(PR_EC_WEBACCESS_SETTINGS_JSON, webappsettings)
|
|
||||||
except Exception as e:
|
|
||||||
print '%s: Error Writing WebApp settings for user: %s' % (e, user.name)
|
|
||||||
|
|
||||||
|
|
||||||
def main(options):
|
|
||||||
with open(options.file, 'r') as sigfile:
|
|
||||||
signaturehtml = sigfile.read()
|
|
||||||
signatureid = '1'
|
|
||||||
signaturename = options.file.replace('template', 'default').replace('-', ' ').replace('.html', '').title().split('/')[-1].replace(' Nl', ' NL').replace(
|
|
||||||
' De', ' DE')
|
|
||||||
signaturecontent = dict(
|
|
||||||
{u'name': signaturename, u'content': signaturehtml, u'isHTML': True})
|
|
||||||
runusers = []
|
|
||||||
if options.allusers:
|
|
||||||
for ruser in server.users(remote=False):
|
|
||||||
runusers.append(ruser.name)
|
|
||||||
else:
|
|
||||||
runusers = options.users
|
|
||||||
|
|
||||||
for username in runusers:
|
|
||||||
try:
|
|
||||||
user = server.user(username)
|
|
||||||
webappsettings = read_settings(user)
|
|
||||||
except Exception as e:
|
|
||||||
print e
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not len(webappsettings['settings']['zarafa']['v1']['contexts']['mail']):
|
|
||||||
print "%s: Adding config tree." % user.name
|
|
||||||
webappsettings['settings']['zarafa'][
|
|
||||||
'v1']['contexts']['mail'] = dict({})
|
|
||||||
if 'signatures' not in list(webappsettings['settings']['zarafa']['v1']['contexts']['mail']):
|
|
||||||
print "%s: Adding Signature settings to config tree." % user.name
|
|
||||||
webappsettings['settings']['zarafa']['v1'][
|
|
||||||
'contexts']['mail']['signatures'] = dict({})
|
|
||||||
if 'all' not in list(webappsettings['settings']['zarafa']['v1']['contexts']['mail']['signatures']):
|
|
||||||
print "%s: Empty Signature settings detected." % user.name
|
|
||||||
webappsettings['settings']['zarafa']['v1']['contexts'][
|
|
||||||
'mail']['signatures'] = dict({'all': dict({})})
|
|
||||||
print '%s: Adding/Replacing Default Signature with %s' % (user.name, signaturename)
|
|
||||||
webappsettings['settings']['zarafa']['v1']['contexts']['mail']['signatures']['all'][
|
|
||||||
signatureid] = signaturecontent
|
|
||||||
webappsettings['settings']['zarafa']['v1']['contexts'][
|
|
||||||
'mail']['signatures']['new_message'] = signatureid
|
|
||||||
webappsettings['settings']['zarafa']['v1']['contexts']['mail']['signatures'][
|
|
||||||
'replyforward_message'] = signatureid
|
|
||||||
write_settings(user, json.dumps(webappsettings))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
parser = kopano.parser('uUPckpsC') # select common cmd-line options
|
|
||||||
parser.add_option('-a', dest='allusers', action='store_true',
|
|
||||||
default=None, help='run program for all local users')
|
|
||||||
parser.add_option('-f', dest='file', action='store',
|
|
||||||
default=None, help='signature filename')
|
|
||||||
options, args = parser.parse_args()
|
|
||||||
server = kopano.Server(options=options)
|
|
||||||
if (options.users or options.allusers) and options.file:
|
|
||||||
main(options)
|
|
@ -12,6 +12,9 @@ Reset WebApp settings
|
|||||||
Change free/busy to 36 months
|
Change free/busy to 36 months
|
||||||
> python3 webapp_admin -u john --free-busy=36
|
> python3 webapp_admin -u john --free-busy=36
|
||||||
|
|
||||||
|
If you want to make a change for all users don't pass the user parameter. Example:
|
||||||
|
> python3 webapp_admin --icons Breeze
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
|
||||||
- python3
|
- python3
|
||||||
|
@ -42,10 +42,10 @@ def opt_args(print_help=None):
|
|||||||
|
|
||||||
# Common option group
|
# Common option group
|
||||||
group = OptionGroup(parser, "Common", "")
|
group = OptionGroup(parser, "Common", "")
|
||||||
|
group.add_option("--all-users", dest="all_users", action="store_true", help="Run for all users")
|
||||||
group.add_option("--location", dest="location", action="store", help="Change location where scripts saves the files")
|
group.add_option("--location", dest="location", action="store", help="Change location where scripts saves the files")
|
||||||
group.add_option("--file", dest="file", action="store", help="Use specific file")
|
group.add_option("--file", dest="file", action="store", help="Use specific file")
|
||||||
group.add_option("--backup", dest="backup", action="store_true", help="Backup Webapp settings")
|
group.add_option("--backup", dest="backup", action="store_true", help="Backup Webapp settings")
|
||||||
group.add_option("--change-locale", dest="change_locale", action="store", help="Set new locale (e.g. en_GB or nl_NL)")
|
|
||||||
group.add_option("--restore", dest="restore", action="store_true", help="Restore Webapp settings")
|
group.add_option("--restore", dest="restore", action="store_true", help="Restore Webapp settings")
|
||||||
group.add_option("--reset", dest="reset", action="store_true", help="Reset WebApp settings")
|
group.add_option("--reset", dest="reset", action="store_true", help="Reset WebApp settings")
|
||||||
parser.add_option_group(group)
|
parser.add_option_group(group)
|
||||||
@ -75,9 +75,11 @@ def opt_args(print_help=None):
|
|||||||
|
|
||||||
# WebApp setting option group
|
# WebApp setting option group
|
||||||
group = OptionGroup(parser, "webapp-settings", "")
|
group = OptionGroup(parser, "webapp-settings", "")
|
||||||
|
group.add_option("--language", dest="language", action="store", help="Set new language (e.g. en_GB or nl_NL)")
|
||||||
group.add_option("--theme", dest="theme", action="store", help="Change theme (e.g. dark)")
|
group.add_option("--theme", dest="theme", action="store", help="Change theme (e.g. dark)")
|
||||||
group.add_option("--free-busy", dest="freebusy", action="store", help="Change free/busy time span in months")
|
group.add_option("--free-busy", dest="freebusy", action="store", help="Change free/busy time span in months")
|
||||||
group.add_option("--icons", dest="icons", action="store", help="Change icons (e.g. breeze)")
|
group.add_option("--icons", dest="icons", action="store", help="Change icons (e.g. breeze)")
|
||||||
|
group.add_option("--htmleditor", dest="htmleditor", action="store", help="Change the HTML editor (e.g. full_tinymce)")
|
||||||
parser.add_option_group(group)
|
parser.add_option_group(group)
|
||||||
|
|
||||||
# Advanced option group
|
# Advanced option group
|
||||||
@ -173,14 +175,22 @@ def restore(user, filename=None):
|
|||||||
Change the language
|
Change the language
|
||||||
|
|
||||||
:param user: The user
|
:param user: The user
|
||||||
:param locale: The language that should be used. Format e.g. "en_GB"
|
:param language: The language that should be used. Format e.g. "en_GB"
|
||||||
"""
|
"""
|
||||||
def change_locale(user, locale):
|
def language(user, language):
|
||||||
settings = read_settings(user)
|
settings = read_settings(user)
|
||||||
|
# Get language from PR_LANGUAGE
|
||||||
|
if language == 'userdefined':
|
||||||
|
try:
|
||||||
|
language = user.prop(PR_LANGUAGE).value
|
||||||
|
except:
|
||||||
|
print('User language is not defined using en_GB as fallback'
|
||||||
|
language = 'en_GB'
|
||||||
|
|
||||||
if not settings['settings']['zarafa']['v1'].get('main'):
|
if not settings['settings']['zarafa']['v1'].get('main'):
|
||||||
settings['settings']['zarafa']['v1']['main'] = {}
|
settings['settings']['zarafa']['v1']['main'] = {}
|
||||||
settings['settings']['zarafa']['v1']['main']['language'] = locale
|
settings['settings']['zarafa']['v1']['main']['language'] = language
|
||||||
print('Setting locale to: {}'.format(locale))
|
print('Setting locale to: {}'.format(language))
|
||||||
write_settings(user, json.dumps(settings))
|
write_settings(user, json.dumps(settings))
|
||||||
|
|
||||||
|
|
||||||
@ -332,15 +342,15 @@ def export_smime(user, location=None, public=None):
|
|||||||
return
|
return
|
||||||
|
|
||||||
for cert in certificates:
|
for cert in certificates:
|
||||||
if public and cert.prop(PR_MESSAGE_CLASS).value == 'WebApp.Security.Public':
|
if public and cert.prop(PR_MESSAGE_CLASS_w).value == 'WebApp.Security.Public':
|
||||||
extension = 'pub'
|
extension = 'pub'
|
||||||
body = cert.body.text
|
body = cert.text
|
||||||
else:
|
else:
|
||||||
extension = 'pfx'
|
extension = 'pfx'
|
||||||
body = base64.b64decode(cert.body.text)
|
body = base64.b64decode(cert.text)
|
||||||
|
|
||||||
print('found {} certificate {} (serial: {})'.format(cert.prop(PR_MESSAGE_CLASS).value, cert.subject, cert.prop(PR_SENDER_NAME).value))
|
print('found {} certificate {} (serial: {})'.format(cert.prop(PR_MESSAGE_CLASS_W).value, cert.subject, cert.prop(PR_SENDER_NAME_W).value))
|
||||||
with open("%s/%s-%s.%s" % (backup_location, cert.subject, cert.prop(PR_SENDER_NAME).value, extension), "w") as text_file:
|
with open("%s/%s-%s.%s" % (backup_location, cert.subject, cert.prop(PR_SENDER_NAME_W).value, extension), "wb") as text_file:
|
||||||
text_file.write(body)
|
text_file.write(body)
|
||||||
|
|
||||||
|
|
||||||
@ -360,7 +370,7 @@ def import_smime(user, cert_file, passwd, ask_password=None, public=None):
|
|||||||
passwd = ''
|
passwd = ''
|
||||||
|
|
||||||
assoc = user.store.root.associated
|
assoc = user.store.root.associated
|
||||||
with open(cert_file) as f:
|
with open(cert_file, 'rb') as f:
|
||||||
cert = f.read()
|
cert = f.read()
|
||||||
if not public:
|
if not public:
|
||||||
messageclass = 'WebApp.Security.Private'
|
messageclass = 'WebApp.Security.Private'
|
||||||
@ -370,13 +380,13 @@ def import_smime(user, cert_file, passwd, ask_password=None, public=None):
|
|||||||
print(e)
|
print(e)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e.message)
|
print(e)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
certificate = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, p12.get_certificate())
|
certificate = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, p12.get_certificate())
|
||||||
cert_data = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, certificate)
|
cert_data = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, certificate)
|
||||||
date_before = MAPI.Time.unixtime(mktime(datetime.strptime(cert_data.get_notBefore(), "%Y%m%d%H%M%SZ" ).timetuple()))
|
date_before = MAPI.Time.unixtime(mktime(datetime.strptime(cert_data.get_notBefore().decode('utf-8'), "%Y%m%d%H%M%SZ" ).timetuple()))
|
||||||
date_after = MAPI.Time.unixtime(mktime(datetime.strptime(cert_data.get_notAfter(), "%Y%m%d%H%M%SZ" ).timetuple()))
|
date_after = MAPI.Time.unixtime(mktime(datetime.strptime(cert_data.get_notAfter().decode('utf-8'), "%Y%m%d%H%M%SZ" ).timetuple()))
|
||||||
|
|
||||||
issued_by = ""
|
issued_by = ""
|
||||||
dict_issued_by = dict(cert_data.get_issuer().get_components())
|
dict_issued_by = dict(cert_data.get_issuer().get_components())
|
||||||
@ -386,48 +396,69 @@ def import_smime(user, cert_file, passwd, ask_password=None, public=None):
|
|||||||
issued_to = ""
|
issued_to = ""
|
||||||
dict_issued_to = dict(cert_data.get_subject().get_components())
|
dict_issued_to = dict(cert_data.get_subject().get_components())
|
||||||
for key in dict_issued_to:
|
for key in dict_issued_to:
|
||||||
if key == 'emailAddress':
|
if key == b'emailAddress':
|
||||||
email = dict_issued_to[key]
|
email = dict_issued_to[key].decode('utf-8')
|
||||||
else:
|
else:
|
||||||
issued_to += "%s=%s\n" % (key, dict_issued_to[key])
|
issued_to += "%s=%s\n" % (key, dict_issued_to[key])
|
||||||
|
|
||||||
if str(user.email) == email:
|
if user.email == email:
|
||||||
item = assoc.mapiobj.CreateMessage(None, MAPI_ASSOCIATED)
|
item = assoc.mapiobj.CreateMessage(None, MAPI_ASSOCIATED)
|
||||||
item.SetProps([SPropValue(PR_SUBJECT, email),
|
|
||||||
SPropValue(PR_MESSAGE_CLASS, messageclass),
|
item.SetProps([SPropValue(PR_SUBJECT, email.encode('utf-8')),
|
||||||
SPropValue(PR_MESSAGE_DELIVERY_TIME, date_after),
|
SPropValue(PR_MESSAGE_CLASS, messageclass.encode('utf-8')),
|
||||||
SPropValue(PR_CLIENT_SUBMIT_TIME, date_before),
|
SPropValue(PR_MESSAGE_DELIVERY_TIME, date_after),
|
||||||
SPropValue(PR_SENDER_NAME, str(int(cert_data.get_serial_number()))),
|
SPropValue(PR_CLIENT_SUBMIT_TIME, date_before),
|
||||||
SPropValue(PR_SENDER_EMAIL_ADDRESS, issued_by),
|
SPropValue(PR_SENDER_NAME, str(cert_data.get_serial_number()).encode('utf-8')),
|
||||||
SPropValue(PR_SUBJECT_PREFIX, issued_to),
|
SPropValue(PR_SENDER_EMAIL_ADDRESS, issued_by.encode('utf-8')),
|
||||||
SPropValue(PR_RECEIVED_BY_NAME, str(cert_data.digest("sha1"))),
|
SPropValue(PR_SUBJECT_PREFIX, issued_to.encode('utf-8')),
|
||||||
SPropValue(PR_INTERNET_MESSAGE_ID, str(cert_data.digest("md5"))),
|
SPropValue(PR_RECEIVED_BY_NAME, cert_data.digest("sha1")),
|
||||||
SPropValue(PR_BODY, str(base64.b64encode(p12)))])
|
SPropValue(PR_INTERNET_MESSAGE_ID, cert_data.digest("md5")),
|
||||||
|
SPropValue(PR_BODY, base64.b64encode(p12.export()))])
|
||||||
item.SaveChanges(KEEP_OPEN_READWRITE)
|
item.SaveChanges(KEEP_OPEN_READWRITE)
|
||||||
print('Imported private certificate')
|
print('Imported private certificate')
|
||||||
else:
|
else:
|
||||||
print('Email address doesn\'t match')
|
print('Email address doesn\'t match')
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Custom function to merge two dictionaries.
|
||||||
|
Previously we used the internal dotty function for this,
|
||||||
|
but this function caused undesired behavior
|
||||||
|
|
||||||
|
:param dict1: The first dictionary
|
||||||
|
:param dict2: The second dictionary
|
||||||
|
"""
|
||||||
|
def mergedicts(dict1, dict2):
|
||||||
|
for k in set(dict1.keys()).union(dict2.keys()):
|
||||||
|
if k in dict1 and k in dict2:
|
||||||
|
if isinstance(dict1[k], dict) and isinstance(dict2[k], dict):
|
||||||
|
yield (k, dict(mergedicts(dict1[k], dict2[k])))
|
||||||
|
else:
|
||||||
|
yield (k, dict2[k])
|
||||||
|
elif k in dict1:
|
||||||
|
yield (k, dict1[k])
|
||||||
|
else:
|
||||||
|
yield (k, dict2[k])
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Inject webapp settings into the users store
|
Inject webapp settings into the users store
|
||||||
|
|
||||||
:param user: The user
|
:param user: The user
|
||||||
:param data: The webapp setting
|
:param data: The webapp setting
|
||||||
:param removed: Remove old setting and write new setting
|
|
||||||
"""
|
"""
|
||||||
def advanced_inject(user, data, removed=None):
|
def advanced_inject(user, data):
|
||||||
settings = read_settings(user)
|
settings = read_settings(user)
|
||||||
split_data = data.split('=')
|
split_data = data.split('=')
|
||||||
|
|
||||||
value = split_data[1].lstrip().rstrip()
|
value = split_data[1].lstrip().rstrip()
|
||||||
dot = dotty(settings)
|
dot = dotty()
|
||||||
if removed:
|
dot[split_data[0].rstrip()] = value
|
||||||
del dot[split_data[0].rstrip()]
|
|
||||||
else:
|
|
||||||
dot[split_data[0].rstrip()] = value
|
|
||||||
new_data = dot.to_dict()
|
new_data = dot.to_dict()
|
||||||
write_settings(user, json.dumps(new_data))
|
new_settings = dict(mergedicts(settings, new_data))
|
||||||
|
|
||||||
|
write_settings(user, json.dumps(new_settings))
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -438,6 +469,13 @@ def main():
|
|||||||
opt_args(True)
|
opt_args(True)
|
||||||
options, args = opt_args()
|
options, args = opt_args()
|
||||||
|
|
||||||
|
# Always first!
|
||||||
|
# If the script should execute for all users
|
||||||
|
# The admin should pass the '--all-users' parameter
|
||||||
|
if not options.users and not options.all_users:
|
||||||
|
print('There are no users specified. Use "--all-users" to run for all users')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
for user in kopano.Server(options).users(options.users):
|
for user in kopano.Server(options).users(options.users):
|
||||||
# Backup and restore
|
# Backup and restore
|
||||||
if options.backup:
|
if options.backup:
|
||||||
@ -446,8 +484,8 @@ def main():
|
|||||||
restore(user, options.file)
|
restore(user, options.file)
|
||||||
|
|
||||||
# Language
|
# Language
|
||||||
if options.change_locale:
|
if options.language:
|
||||||
change_locale(user, options.change_locale)
|
language(user, options.language)
|
||||||
|
|
||||||
#Categories
|
#Categories
|
||||||
if options.export_categories:
|
if options.export_categories:
|
||||||
@ -474,7 +512,7 @@ def main():
|
|||||||
if options.theme:
|
if options.theme:
|
||||||
setting = 'settings.zarafa.v1.main.active_theme = {}'.format(options.theme)
|
setting = 'settings.zarafa.v1.main.active_theme = {}'.format(options.theme)
|
||||||
advanced_inject(user, setting)
|
advanced_inject(user, setting)
|
||||||
print('Theme changed to {}'.format(options.icons))
|
print('Theme changed to {}'.format(options.theme))
|
||||||
|
|
||||||
# Free busy publishing
|
# Free busy publishing
|
||||||
if options.freebusy:
|
if options.freebusy:
|
||||||
@ -490,10 +528,24 @@ def main():
|
|||||||
|
|
||||||
# Icon set
|
# Icon set
|
||||||
if options.icons:
|
if options.icons:
|
||||||
|
accepted_icons = {'Breeze', 'Classic'}
|
||||||
|
if not options.icons in accepted_icons:
|
||||||
|
print('Valid syntax: Breeze or Classic')
|
||||||
|
sys.exit(1)
|
||||||
setting = 'settings.zarafa.v1.main.active_iconset = {}'.format(options.icons)
|
setting = 'settings.zarafa.v1.main.active_iconset = {}'.format(options.icons)
|
||||||
advanced_inject(user, setting)
|
advanced_inject(user, setting)
|
||||||
print('icon set changed to {}'.format(options.icons))
|
print('icon set changed to {}'.format(options.icons))
|
||||||
|
|
||||||
|
# Editor
|
||||||
|
if options.htmleditor:
|
||||||
|
accepted_editors = {'htmleditor-minimaltiny', 'full_tinymce'}
|
||||||
|
if not options.htmleditor in accepted_editors:
|
||||||
|
print('Valid syntax: htmleditor-minimaltiny or full_tinymce')
|
||||||
|
sys.exit(1)
|
||||||
|
setting = 'settings.zarafa.v1.contexts.mail.html_editor = {}'.format(options.htmleditor)
|
||||||
|
advanced_inject(user, setting)
|
||||||
|
print('Editor changed to {}'.format(options.htmleditor))
|
||||||
|
|
||||||
# Always at last!!!
|
# Always at last!!!
|
||||||
if options.reset:
|
if options.reset:
|
||||||
reset_settings(user)
|
reset_settings(user)
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
|
|
||||||
webapp_settings.py
|
|
||||||
==================
|
|
||||||
|
|
||||||
#### Usage:
|
|
||||||
|
|
||||||
|
|
||||||
###### Backup
|
|
||||||
|
|
||||||
```python
|
|
||||||
python webapp_settings.py --user user --backup
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
###### Restore
|
|
||||||
|
|
||||||
```python
|
|
||||||
python webapp_settings.py --user user --restore
|
|
||||||
```
|
|
@ -1,52 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
#encoding: utf-8
|
|
||||||
|
|
||||||
from MAPI import *
|
|
||||||
from MAPI.Util import *
|
|
||||||
import sys
|
|
||||||
try:
|
|
||||||
import kopano
|
|
||||||
except ImportError:
|
|
||||||
import zarafa as kopano
|
|
||||||
try:
|
|
||||||
import json
|
|
||||||
except ImportError:
|
|
||||||
import simplejson as json
|
|
||||||
|
|
||||||
def opt_args():
|
|
||||||
parser = kopano.parser('skpcfm')
|
|
||||||
parser.add_option("--user", dest="user", action="store", help="Run script for user")
|
|
||||||
parser.add_option("--backup", dest="backup", action="store_true", help="Backup webapp setting ")
|
|
||||||
parser.add_option("--restore", dest="restore", action="store_true", help="Restore webapp settings")
|
|
||||||
parser.add_option("--remove", dest="remove", action="store_true", help="Remove webapp settings")
|
|
||||||
|
|
||||||
return parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
options, args = opt_args()
|
|
||||||
|
|
||||||
if not options.user or (not options.backup and not options.restore and not options.remove):
|
|
||||||
print 'Please use:\n %s --user <username> (--backup or --restore) ' % (sys.argv[0])
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
user = kopano.Server(options).user(options.user)
|
|
||||||
if options.backup:
|
|
||||||
webapp = json.loads(user.store.prop(PR_EC_WEBACCESS_SETTINGS_JSON).value)
|
|
||||||
f = open('%s.json' % user.name,'w')
|
|
||||||
|
|
||||||
f.write(json.dumps(webapp, sort_keys=True,
|
|
||||||
indent=4, separators=(',', ': ')))
|
|
||||||
f.close()
|
|
||||||
if options.restore:
|
|
||||||
with open('%s.json' % user.name) as data_file:
|
|
||||||
data = json.load(data_file)
|
|
||||||
|
|
||||||
print data
|
|
||||||
user.store.create_prop(PR_EC_WEBACCESS_SETTINGS_JSON, json.dumps(data))
|
|
||||||
|
|
||||||
if options.remove:
|
|
||||||
user.store.delete(user.store.prop('PR_EC_WEBACCESS_SETTINGS_JSON'))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@ -1,17 +0,0 @@
|
|||||||
|
|
||||||
webapp_switch_locale.py
|
|
||||||
=========================
|
|
||||||
List or change the locale currently set in the user's WebApp settings.
|
|
||||||
|
|
||||||
#### Usage:
|
|
||||||
###### List locale
|
|
||||||
```
|
|
||||||
python switchlocale.py --user user1
|
|
||||||
Original locale: nl_NL.UTF-8
|
|
||||||
```
|
|
||||||
###### Change locale
|
|
||||||
```
|
|
||||||
python switchlocale.py --user user1 --locale de_DE.UTF-8
|
|
||||||
Original locale: nl_NL.UTF-8
|
|
||||||
Setting locale to: de_DE.UTF-8
|
|
||||||
```
|
|
@ -1,35 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# encoding: utf-8
|
|
||||||
import json
|
|
||||||
import kopano
|
|
||||||
from MAPI.Util import *
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def opt_args():
|
|
||||||
parser = kopano.parser('skpcfm')
|
|
||||||
parser.add_option("--user", dest="user", action="store", help="Run script for user")
|
|
||||||
parser.add_option("--locale", dest="locale", action="store", help="Set new locale")
|
|
||||||
return parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
options, args = opt_args()
|
|
||||||
|
|
||||||
if not options.user:
|
|
||||||
print 'Please use:\n %s --user <username> [--locale]' % (sys.argv[0])
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
user = kopano.Server(options).user(options.user)
|
|
||||||
settings = json.loads(user.store.prop(PR_EC_WEBACCESS_SETTINGS_JSON).value)
|
|
||||||
current = settings['settings']['zarafa']['v1']['main']['language']
|
|
||||||
print 'Original locale: %s' % current
|
|
||||||
|
|
||||||
if options.locale:
|
|
||||||
print 'Setting locale to: %s' % options.locale
|
|
||||||
settings['settings']['zarafa']['v1']['main']['language'] = options.locale
|
|
||||||
user.store.create_prop(PR_EC_WEBACCESS_SETTINGS_JSON, json.dumps(settings))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
Loading…
Reference in New Issue
Block a user