summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Boddie <paul@boddie.org.uk>2014-08-07 12:27:35 (GMT)
committerPaul Boddie <paul@boddie.org.uk>2014-08-07 12:27:35 (GMT)
commit62b1ad3a00c52ba370a4a5395bfc543c39e35ffe (patch)
tree0114afa984a70216a6ec5be93491f0d1cac0c574
parentcfed166d06e0976a6aa4655be702868061a6d033 (diff)
downloadpykolab-62b1ad3a00c52ba370a4a5395bfc543c39e35ffe.tar.gz
Added Converse support.
-rw-r--r--pykolab/setup/setup_converse.py299
1 files changed, 299 insertions, 0 deletions
diff --git a/pykolab/setup/setup_converse.py b/pykolab/setup/setup_converse.py
new file mode 100644
index 0000000..cf38008
--- /dev/null
+++ b/pykolab/setup/setup_converse.py
@@ -0,0 +1,299 @@
+# -*- coding: utf-8 -*-
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2014 Paul Boddie <paul@boddie.org.uk>
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# This program 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 3 of the License, or
+# (at your option) any later version.
+
+# This program 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. If not, see <http://www.gnu.org/licenses/>.
+#
+
+from os.path import join, isfile
+from shutil import copy
+import re
+import time
+
+import components
+
+import pykolab
+
+from pykolab import utils
+from pykolab.constants import *
+from pykolab.setup.services import *
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.setup')
+conf = pykolab.getConf()
+
+def __init__():
+ components.register(
+ 'converse',
+ execute,
+ description=description(),
+ after=['ldap', 'roundcube']
+ )
+
+def cli_options():
+ converse_group = conf.add_cli_parser_option_group(_("Converse Options"))
+
+ converse_group.add_option(
+ "--reset-converse-config",
+ dest = "reset_converse_config",
+ action = "store_true",
+ default = False,
+ help = _("Reset the Converse (and potentially Apache proxy) configuration.")
+ )
+
+def description():
+ return _("Setup Converse.")
+
+def execute(*args, **kw):
+
+ # Signal that interaction may occur. This will involve debconf and similar
+ # system-specific mechanisms if available.
+
+ start_interaction("kolab-conf/title-converse")
+ try:
+ _execute(*args, **kw)
+ finally:
+ stop_interaction()
+
+def _execute(*args, **kw):
+
+ prefix = get_roundcube_config()
+
+ if not prefix:
+ if conf.check_only:
+ utils.setup_status("converse", _("not installed"))
+ else:
+ log.error(_("Neither Roundcube nor Converse are installed on this system"))
+ return
+
+ config = join(prefix, "converse.inc.php")
+ backup = join(prefix, "converse.inc.php.orig")
+
+ if not isfile(config):
+ if conf.check_only:
+ utils.setup_status("converse", _("not installed"))
+ else:
+ log.error(_("Converse is not installed on this system"))
+ return
+ elif not isfile(backup):
+ copy(config, backup)
+
+ # Define the settings values.
+
+ proxy_uri = conf.get('xmpp', 'bind_proxy_uri')
+ bind_uri = conf.get('xmpp', 'bind_uri')
+ bind_uri_default = "http://%s:5280/http-bind" % hostname
+
+ if not bind_uri or conf.reset_converse_config:
+ if conf.check_only:
+ utils.setup_status("converse", _("needs setup"))
+ return
+
+ bind_uri = ask_question("kolab-conf/xmpp-bind-server",
+ _("""
+ Please indicate the location of the bind server providing
+ access to the XMPP server to be used by Converse.
+ """),
+ _("Select an XMPP server bind URI"),
+ default=(bind_uri or bind_uri_default)
+ )
+
+ if not proxy_uri or conf.reset_converse_config:
+ if conf.check_only:
+ utils.setup_status("converse", _("needs setup"))
+ return
+
+ proxy_uri = ask_question("kolab-conf/xmpp-proxy-server",
+ _("""
+ Please indicate the location of the proxy server providing
+ access to the XMPP server to be used by Converse.
+ You can leave this empty to insist that the bind URI is
+ reachable from Web applications served by this host.
+ """),
+ _("Select an XMPP server proxy URI"),
+ default=(proxy_uri != bind_uri and proxy_uri or "")
+ )
+
+ need_proxy = proxy_uri and proxy_uri != bind_uri or conf.reset_converse_config
+
+ # Each setting has a name, whether it should be provided as a function,
+ # whether it should be provided as an array, and a returned value.
+ # Using functions to provide settings permits dynamic values.
+
+ settings = [
+ ('converse_xmpp_bosh_prebind_url', True, False, "'%s'" % bind_uri),
+ ('converse_xmpp_hostname', True, False, "'%s'" % conf.get('kolab', 'primary_domain')),
+ ('converse_xmpp_username', True, False, "$_SESSION['kolab_uid']"),
+ ]
+
+ # Determine whether the configuration details are already present.
+
+ f = open(config)
+ try:
+ text = f.read()
+ finally:
+ f.close()
+
+ # Replace the top-level settings.
+
+ have_settings, text = replace_settings(settings, text)
+
+ if not conf.check_only and not have_settings:
+ f = open(config, "w")
+ try:
+ f.write(text)
+ finally:
+ f.close()
+
+ # Determine whether the plugin is enabled.
+
+ roundcube_config = join(prefix, 'config.inc.php')
+
+ f = open(roundcube_config)
+ try:
+ text = f.read()
+ finally:
+ f.close()
+
+ rc_settings = [
+ ("plugins", False, True, "'converse'"),
+ ]
+
+ have_plugin, text = replace_settings(rc_settings, text, "config")
+
+ if conf.check_only:
+ utils.setup_status("converse", have_settings and have_plugin and _("setup done") or _("needs setup"))
+ return
+
+ if not have_plugin:
+ f = open(roundcube_config, "w")
+ try:
+ f.write(text)
+ finally:
+ f.close()
+
+ # Add a section if necessary with the proxy URI being explicitly the same
+ # as the bind URI if no proxy is to be used.
+
+ if not conf.has_section('xmpp'):
+ conf.add_section('xmpp')
+
+ conf.command_set('xmpp', 'bind_uri', bind_uri)
+ conf.command_set('xmpp', 'bind_proxy_uri', proxy_uri or bind_uri)
+
+ # Update the configuration file.
+
+ fp = open(conf.defaults.config_file, "w+")
+ conf.cfg_parser.write(fp)
+ fp.close()
+
+ # Write any site files for the proxy.
+
+ if need_proxy:
+
+ web_settings = {
+ "bind_uri" : bind_uri,
+ "bind_proxy_host_and_port" : get_host_and_port_from_url(proxy_uri),
+ }
+
+ template_file = get_template_path('converse-proxy.tpl')
+ output_file = join(get_apache_site_dir(), 'converse-proxy')
+
+ if template_file is not None:
+ log.debug(_("Using template file %r") % (template_file), level=8)
+ instantiate_template(template_file, output_file, [web_settings])
+
+ # Enable the site.
+
+ enable_apache_site('converse-proxy')
+ enable_apache_module('proxy_http')
+
+ # Restart the Web server.
+
+ time.sleep(2)
+
+ apache = is_debian() and "apache2" or "httpd"
+ if not control_service(apache, 'restart'):
+ log.error(_("Could not start the webserver service."))
+
+ if not configure_service(apache, True):
+ log.error(_("Could not configure to start on boot, the " + \
+ "webserver service."))
+
+def replace_settings(settings, text, config_var="rcmail_config"):
+ have_settings = True
+ new_settings = []
+
+ for name, is_function, is_array, value in settings:
+ details = find_rcmail_setting(name, text, config_var)
+ setting_text = get_rcmail_setting(name, is_function, is_array, value, config_var)
+
+ if details is None:
+ have_settings = False
+ new_settings.append(setting_text)
+ else:
+ (start, end), name, start_def, start_array, _value, end_array, end_def = details
+
+ # For arrays, append the value to the end.
+
+ if is_array and value not in _value:
+ have_settings = False
+ setting_text = get_rcmail_setting(name, is_function, is_array, _value.rstrip().rstrip(",") + ",\n" + value, config_var)
+ text = text[:start] + setting_text + text[end:]
+
+ # For single values, insert the value.
+
+ elif not is_array and value != _value:
+ have_settings = False
+ text = text[:start] + setting_text + text[end:]
+
+ for setting_text in new_settings:
+ text += "\n%s" % setting_text
+
+ return have_settings, text
+
+def get_rcmail_setting(name, is_function, is_array, value, config_var="rcmail_config"):
+ return rcmail_setting % {
+ "config_var" : config_var,
+ "name" : name,
+ "start_def" : is_function and def_string or "",
+ "start_array" : is_array and array_string or "",
+ "value" : value,
+ "end_array" : is_array and end_array_string or "",
+ "end_def" : is_function and end_def_string or ""
+ }
+
+def find_rcmail_setting(name, text, config_var="rcmail_config"):
+ m = re.search(
+ r"\$" + config_var + r"\['(?P<name>" + name + r")'\]\s*=\s*"
+ r"(?P<start_def>function\(\$args\)\s*{.*?return\s+)?"
+ r"(?P<start_array>[Aa]rray\s*\(\s*)?"
+ r"(?P<value>.*?)"
+ r"(?P<end_array>\))?"
+ r"\s*;"
+ r"(?P<end_def>(?(start_def).*?}))", text, re.DOTALL)
+ if m:
+ return m.span(), m.group("name"), m.group("start_def"), m.group("start_array"), m.group("value"), m.group("end_array"), m.group("end_def")
+ else:
+ return None
+
+# Data used to construct settings.
+
+rcmail_setting = "$%(config_var)s['%(name)s'] = %(start_def)s%(start_array)s%(value)s%(end_array)s;%(end_def)s"
+def_string = "function($args) {\n\treturn "
+array_string = "array("
+end_array_string = ")"
+end_def_string = "\n};"