File automx-1.1.3pre.patch of Package automx1

diff --git a/CHANGES b/CHANGES
index 3575762..b520894 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+* Version 1.1.2
+---------------------------------
+- Added support for cal/carddav
+- Added support for eMClient for OX
+
 * Version 1.1.1
 ---------------------------------
 - Added service_domain_required option for Outlook
diff --git a/INSTALL b/INSTALL
index 2c61b4f..c4ed76f 100644
--- a/INSTALL
+++ b/INSTALL
@@ -115,7 +115,8 @@ If you install automx on an existing host, which has it's own domain-name, then
 it is also possible to use above entries as nicknames:
 
 somehost.example.com. IN A 192.168.2.1
-    autoconfig IN CNAME somehost autodiscover IN CNAME somehost
+autoconfig            IN CNAME somehost.example.com.
+autodiscover          IN CNAME somehost.example.com.
 
 Web Server Configuration
 
diff --git a/README.md b/README.md
index 2e9c454..d8821fd 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ various autoconfiguration techniques in one webservice.
 
 ## Mailclients
 automx can provision Outlook, Thunderbird, iOS devices and other clients that
-support either Microsofts autodiscover mechanism or Mozillas autoconfig.
+support either Microsoft's autodiscover mechanism or Mozilla's autoconfig.
 
 ## Backends
 automx can either statically or dynamically generate email account information
diff --git a/src/automx-test b/src/automx-test
index d62f8d0..079731c 100755
--- a/src/automx-test
+++ b/src/automx-test
@@ -31,7 +31,7 @@ function clean_exit() {
 # We need a mail address
 if [[ $1 ]]; then
 	PROFILE="$1"
-else 
+else
 	echo "Provide the mail address for which configuration settings should be retrieved."
 	read -ep "Mail address: " PROFILE
 fi
@@ -43,17 +43,32 @@ MBREQUEST="$(mktemp /tmp/${PROGRAM_NAME}.XXXXXX)"
 MBCRESPONSE="$(mktemp /tmp/${PROGRAM_NAME}.XXXXXX)"
 
 # Test Mozilla schema
+MOZFOUND=0
 AUTOCONF="autoconfig.$DOMAIN"
-if [[ $(dig +short $AUTOCONF) ]]; then
+WELL_KNOWN="$DOMAIN/.well-known/autoconfig"
+if [[ ! $(dig +short $AUTOCONF) ]]; then
+	echo
+	echo "Autodiscovery domain for Mozilla Thunderbird not found ($AUTOCONF)"
+	echo
+else
 	CON="http://$AUTOCONF/mail/config-v1.1.xml?emailaddress=$PROFILE"
 	echo
 	echo "Testing Autoconfig ..."
 	echo "Connecting to $CON ..."
 	echo
-	wget -S -O - -q --no-check-certificate $CON
-else
+	wget -S -O - -q --no-check-certificate $CON && MOZFOUND=1
+fi
+if [ $MOZFOUND -ne 1 ]; then
+	# some error happened; try fallback URL
+	echo "Trying fallback URL ..."
+	CON="http://$WELL_KNOWN/mail/config-v1.1.xml?emailaddress=$PROFILE"
+	echo "Connecting to $CON ..."
 	echo
-	echo "Autodiscovery domain for Mozilla Thunderbird not found ($AUTOCONF)"
+	wget -S -O - -q --no-check-certificate $CON && MOZFOUND=1
+fi
+if [ $MOZFOUND -eq 0 ]; then
+	# no supported autoconfig information
+	echo "No autoconfig endpoint found."
 	echo
 fi
 
@@ -78,14 +93,14 @@ if [[ $AUTODISC ]]; then
 		  </Request>
 		</Autodiscover>
 	REQ
-	
+
 	echo
 	echo "Testing Autodiscover (Microsoft Outlook(tm)) ..."
 	echo "Connecting to $CON ..."
 	echo
 	wget -S -O - -q --post-file=$OLREQUEST --no-check-certificate $CON
 	rm $OLREQUEST
-	
+
 	# Test Microsoft Mobile schema
 	cat <<-REQ >$MBREQUEST
 		<?xml version="1.0" encoding="utf-8"?>
@@ -96,7 +111,7 @@ if [[ $AUTODISC ]]; then
 		  </Request>
 		</Autodiscover>
 	REQ
-	
+
 	echo
 	echo "Testing Autodiscover (mobilesync) ..."
 	echo "Connecting to $CON ..."
diff --git a/src/automx/config.py b/src/automx/config.py
index 9c78b94..0c4b83b 100644
--- a/src/automx/config.py
+++ b/src/automx/config.py
@@ -15,13 +15,24 @@ 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 __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
 import os
 import sys
 import shlex
 import re
 import logging
+# noinspection PyCompatibility
 import ipaddress
-import configparser
+
+try:
+    import configparser
+except ImportError:
+    # noinspection PyPep8Naming
+    import ConfigParser as configparser
 
 try:
     # noinspection PyUnresolvedReferences
@@ -31,9 +42,12 @@ try:
 except ImportError:
     use_memcache = False
 
+# noinspection PyCompatibility
 from configparser import NoOptionError, NoSectionError
 from dateutil import parser
 from collections import OrderedDict
+# noinspection PyCompatibility
+from builtins import dict, int, str
 
 
 __version__ = '1.1.1'
@@ -58,47 +72,47 @@ class Config(configparser.RawConfigParser):
     independend from the view. It may query different backends to gather all
     required information needed to generate XML output later on in the view
     class.
-    
+
     It uses a OrderdDict to guarentee the correct service order that is needed
     in the XML output. This said means that it is a difference, if a service
     like IMAP is configured before POP3 or upside down, because a MUA follows
     this order.
-    
-    The class currently support smtp, pop and imap services.
-    
+
+    The class currently support smtp, pop, imap, carddav, caldav and ox services.
+
     The class currently supports the following backends:
-    
+
     -> global - This backend tells automx to use the global section
-    
+
     -> static - all kind of service information that can be sent directly to
                 the MUA
-                
+
     -> filter - This backend can execute commands and collects results from
                 stdout. The result may be "", which means we skip further
                 searching. It may return data, which should point to a section
                 that we try to follow.
-                
+
     -> ldap   - Read all kind of information from LDAP servers. The result
                 attributes are stored in an internal dictionary and if options
                 later on in this backend section (is read as static backend)
                 do contain variables in the form ${attributename}, these are
                 expanded to the collected data.
-                
+
     -> sql    - Read all kind of information from SQL servers. The result
                 attributes are stored in an internal dictionary. See ldpa
-                
+
     -> script - Execute a script and split a result into attributes, which are
                 stored in an internal dictionary, See ldap
-                
+
     -> file   - Provide static files. If present, all collected data are
                 discarded and only the static file is sent to the remote
                 client. This may change in future releases.
-    
+
     Note: There may exist a DEFAULT section that is appended to _all_ sections
     in the configuration file. That said you can do really complex
     configurations that on the other hand make life easier. This section also
     may contain variables, which, if found in the vars-dictionary, are used.
-    
+
     """
 
     def __init__(self, environ):
@@ -245,6 +259,12 @@ class Config(configparser.RawConfigParser):
                         service = self.__service(section, "imap")
                     elif opt == "pop":
                         service = self.__service(section, "pop")
+                    elif opt == "carddav":
+                        service = self.__service(section, "carddav")
+                    elif opt == "caldav":
+                        service = self.__service(section, "caldav")
+                    elif opt == "ox":
+                        service = self.__service(section, "ox")
                     elif opt == "sign_mobileconfig":
                         try:
                             settings[opt] = self.getboolean(section, opt)
@@ -260,7 +280,7 @@ class Config(configparser.RawConfigParser):
                     else:
                         pass
 
-                    if opt in ("smtp", "imap", "pop"):
+                    if opt in ("smtp", "imap", "pop", "caldav", "carddav", "ox"):
                         if backend == "static_append":
                             if opt in settings:
                                 if self.debug:
@@ -636,7 +656,7 @@ class Config(configparser.RawConfigParser):
 
                             got_data = True
 
-                            # we replace our search_domain 
+                            # we replace our search_domain
                             self.__search_domain = special_opt
                             self.__emailaddress = new_emailaddress
 
@@ -973,7 +993,10 @@ class Memcache(object):
         else:
             networks = ("127.0.0.1", "::1/128")
 
-        a = ipaddress.ip_address(self.__client)
+        if sys.version_info < (3,):
+            a = ipaddress.ip_address(self.__client.decode("utf-8"))
+        else:
+            a = ipaddress.ip_address(self.__client)
         for network in iter(networks):
             n = ipaddress.ip_network(network)
             if a in n:
diff --git a/src/automx/view.py b/src/automx/view.py
index 823fc18..d83aa10 100644
--- a/src/automx/view.py
+++ b/src/automx/view.py
@@ -15,6 +15,11 @@ 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 __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
 import sys
 import uuid
 import logging
@@ -22,7 +27,13 @@ import logging
 from lxml import etree
 from lxml.etree import XMLSyntaxError
 from xml.parsers.expat import ExpatError
-from plistlib import load, dumps, FMT_XML
+
+try:
+    # noinspection PyUnresolvedReferences
+    from plistlib import load, dumps, FMT_XML
+except ImportError:
+    # noinspection PyPep8Naming
+    from plistlib import readPlist, writePlistToString
 
 
 __version__ = '1.1.1'
@@ -38,7 +49,7 @@ class View(object):
     is used in Mozilla Thunderbird and several other open-source MUAs. It also
     supports .mobileconfig profile support as found on iOS devices. These
     profiles can also be used on Mac OS X Mail.app
-        
+
     """
 
     def __init__(self, model, schema, subschema):
@@ -64,7 +75,10 @@ class View(object):
             elif self.__schema == "mobileconfig":
                 path = self.__model.domain[self.__schema]
                 try:
-                    plist_tmp = load(path)
+                    if sys.version_info < (3,):
+                        plist_tmp = readPlist(path)
+                    else:
+                        plist_tmp = load(path)
                     plist = plist_tmp.copy()
                     self.__plist = plist
                 except ExpatError:
@@ -119,7 +133,7 @@ class View(object):
                     raise Exception("Missing attribute <action>")
 
                 for key, value in self.__model.domain.items():
-                    if key in ("smtp", "imap", "pop"):
+                    if key in ("smtp", "imap", "pop", "caldav", "carddav", "ox"):
                         if len(value) != 0:
                             protocol = etree.SubElement(account, "Protocol")
                             self.__service(key, protocol)
@@ -291,6 +305,12 @@ class View(object):
                 s_type = service.upper()
             elif service in "pop":
                 s_type = "POP3"
+            elif service in "caldav":
+                s_type = "CalDAV"
+            elif service in "carddav":
+                s_type = "CardDAV"
+            elif service in "ox":
+                s_type = "X-OX-APPSUITE"
 
             c.text = s_type
 
@@ -450,19 +470,19 @@ class View(object):
             if service + "_server" in elem:
                 if service in ("imap", "pop"):
                     proto["in_server"] = elem[service + "_server"]
-                else:
+                elif service == "smtp":
                     proto["out_server"] = elem[service + "_server"]
 
             if service + "_port" in elem:
                 if service in ("imap", "pop"):
                     proto["in_port"] = int(elem[service + "_port"])
-                else:
+                elif service == "smtp":
                     proto["out_port"] = int(elem[service + "_port"])
 
             if service + "_auth_identity" in elem:
                 if service in ("imap", "pop"):
                     proto["in_username"] = elem[service + "_auth_identity"]
-                else:
+                elif service == "smtp":
                     proto["out_username"] = elem[service + "_auth_identity"]
 
             if service + "_auth" in elem:
@@ -490,7 +510,7 @@ class View(object):
 
                 if service in ("imap", "pop"):
                     proto["in_auth"] = result
-                else:
+                elif service == "smtp":
                     proto["out_auth"] = result
 
             if service + "_encryption" in elem:
@@ -499,12 +519,12 @@ class View(object):
                 if value in ("ssl", "starttls"):
                     if service in ("imap", "pop"):
                         proto["in_encryption"] = True
-                    else:
+                    elif service == "smtp":
                         proto["out_encryption"] = True
                 else:
                     if service in ("imap", "pop"):
                         proto["in_encryption"] = False
-                    else:
+                    elif service == "smtp":
                         proto["out_encryption"] = False
 
     def render(self):
@@ -520,7 +540,11 @@ class View(object):
                                   pretty_print=True)
 
         elif self.__plist is not None:
-            plist_unsigned = dumps(self.__plist, fmt=FMT_XML)
+            if sys.version_info < (3,):
+                plist_unsigned = writePlistToString(self.__plist)
+            else:
+                # noinspection PyArgumentList
+                plist_unsigned = dumps(self.__plist, fmt=FMT_XML)
 
             # Old M2Crypto that is not ported yet to Python3
             """
@@ -566,7 +590,7 @@ class View(object):
 
                     sign_cert = self.__model.domain["sign_cert"]
                     sign_key = self.__model.domain["sign_key"]
-                    
+
                     if "sign_more_certs" in self.__model.domain:
                         extra = " -certfile " + self.__model.domain[
                             "sign_more_certs"]
diff --git a/src/automx_wsgi.py b/src/automx_wsgi.py
index f38b3be..ea80a7f 100755
--- a/src/automx_wsgi.py
+++ b/src/automx_wsgi.py
@@ -15,20 +15,37 @@ 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 __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
 import os
 import sys
 import traceback
 import logging
 
+# noinspection PyCompatibility
 from html import escape
 from io import StringIO
 from lxml import etree
 from lxml.etree import XMLSyntaxError
+# noinspection PyCompatibility
 from builtins import int, str
 
-from urllib.parse import urlparse, urlencode, parse_qs, unquote
-from urllib.request import urlopen, Request
-from urllib.error import HTTPError
+try:
+    # noinspection PyCompatibility
+    from urllib.parse import urlparse, urlencode, parse_qs, unquote
+    # noinspection PyCompatibility
+    from urllib.request import urlopen, Request
+    # noinspection PyCompatibility
+    from urllib.error import HTTPError
+except ImportError:
+    # noinspection PyCompatibility
+    from urlparse import urlparse, parse_qs
+    from urllib import urlencode, unquote
+    # noinspection PyCompatibility
+    from urllib2 import urlopen, Request, HTTPError
 
 from automx.config import Config
 from automx.config import DataNotFoundException
@@ -262,25 +279,43 @@ def application(environ, start_response):
                     data.domain["sign_mobileconfig"] is True):
                 logging.debug("No debugging output for signed mobileconfig!")
             else:
-                logging.debug(str("Response:\n%s" % response_body))
+                if sys.version_info < (3,):
+                    logging.debug("Response:\n" + response_body.decode('utf-8'))
+                else:
+                    logging.debug(str("Response:\n%s" % response_body))
 
     body_len = str(len(response_body))
 
+    def aenc(key, value):
+        """Auto-enocde to ascii; Make headers compatible for Py2/Py3
+
+        :param key: header key
+        :param value: header value
+        :return: auto encoded tuple
+        """
+        if sys.version_info < (3,):
+            return key.encode("ascii"), value.encode("ascii")
+        else:
+            return key, value
+
     if schema in ('autoconfig', "autodiscover"):
-        response_headers = [('Content-Type', 'text/xml'),
-                            ('Content-Length', body_len)]
+        response_headers = [aenc('Content-Type', 'text/xml'),
+                            aenc('Content-Length', body_len)]
     elif schema == "mobileconfig":
-        response_headers = [('Content-Type',
-                             'application/x-apple-aspen-config'
-                             '; charset=utf-8'),
-                            ('Content-Disposition',
-                             'attachment; '
-                             'filename="company.mobileconfig'),
-                            ('Content-Length', body_len)]
+        response_headers = [aenc('Content-Type',
+                                 'application/x-apple-aspen-config'
+                                 '; charset=utf-8'),
+                            aenc('Content-Disposition',
+                                 'attachment; '
+                                 'filename="company.mobileconfig'),
+                            aenc('Content-Length', body_len)]
     else:
         # Failure?
-        response_headers = [('Content-Type', 'text/html'),
-                            ('Content-Length', body_len)]
+        response_headers = [aenc('Content-Type', 'text/html'),
+                            aenc('Content-Length', body_len)]
+
+    if sys.version_info < (3,):
+        status = status.encode("ascii")
 
     start_response(status, response_headers)
 
diff --git a/src/doc/automx.conf.5.rst b/src/doc/automx.conf.5.rst
index 35a0893..e9271c1 100644
--- a/src/doc/automx.conf.5.rst
+++ b/src/doc/automx.conf.5.rst
@@ -67,6 +67,28 @@ smtp
 	protocol to connect to this server is SMTP. Specifying this name is
 	only applicable for account_type = email.
 
+caldav
+	This name specifies a CalDAV service as defined in RFC 4791. The
+	protocol to connect to this server is HTTP. The server definition expects
+	a URL like https://caldav.example.com/. Specifying this name is only
+	applicable for account_type = email currently.
+	This service only affects autodiscover view.
+
+carddav
+	This name specifies a CardDAV service as defined in RFC 6352. The
+	protocol to connect to this server is HTTP. The server definition expects
+	a URL like https://carddav.example.com/. Specifying this name is only
+	applicable for account_type = email currently.
+	This service only affects autodiscover view.
+
+ox
+	This name specifies an existing OX App Suite service. Some clients
+	need to know where to access the OX App Suite HTTP API. The server
+	definition expects a URL like https://ox.example.com/. Specifying
+	this name is only applicable for account_type = email currently.
+	This service only affects autodiscover view.
+
+
 Parameters
 ''''''''''
 
@@ -74,7 +96,7 @@ autoconfig (no default)
 	Specifies a path to a file that contains static autoconfiguration
 	options following to the Mozilla schema.
 
-		.. NOTE:: 
+		.. NOTE::
 
 			This parameter is valid only if backend = file has been specified.
 
@@ -194,7 +216,7 @@ mobileconfig (no default)
 	Specifies a path to a file that contains static mobileconfiguration
 	options following to the Mozilla schema.
 
-		.. NOTE:: 
+		.. NOTE::
 
 			This parameter is valid only if backend = file has been specified.
 
@@ -390,5 +412,3 @@ See also
 .. _automx_sql(5): automx_sql.5.html
 .. _automx_script(5): automx_script.5.html
 .. _automx-test(1): automx-test.1.html
-
-
diff --git a/src/html/index.html.de b/src/html/index.html.de
index 4954fd9..030e4a5 100644
--- a/src/html/index.html.de
+++ b/src/html/index.html.de
@@ -42,11 +42,11 @@
   </div>
 
   <div id="footer-desktop" class="hide-for-small">
-    <a class="right automx-powered" href="http://automx.org" target="_blank">Powered by <img src="img/automx-banner.png" width="126" height="20" alt="automx banner" /></a>
+    <a class="right automx-powered" href="https://automx.org" target="_blank">Powered by <img src="img/automx-banner.png" width="126" height="20" alt="automx banner" /></a>
   </div>
   <div id="footer-mobile" class="show-for-small row">
     <div class="small-12 columns">
-      <a class="right automx-powered" href="http://automx.org" target="_blank">Powered by <img src="img/automx-banner.png" width="126" height="20" alt="automx banner" /></a>
+      <a class="right automx-powered" href="https://automx.org" target="_blank">Powered by <img src="img/automx-banner.png" width="126" height="20" alt="automx banner" /></a>
     </div>
   </div>
 
diff --git a/src/html/index.html.en b/src/html/index.html.en
index a88f043..1acb53a 100644
--- a/src/html/index.html.en
+++ b/src/html/index.html.en
@@ -43,11 +43,11 @@
   </div>
 
   <div id="footer-desktop" class="hide-for-small">
-    <a class="right automx-powered" href="http://automx.org" target="_blank">Powered by <img src="img/automx-banner.png" width="126" height="20" alt="automx banner" /></a>
+    <a class="right automx-powered" href="https://automx.org" target="_blank">Powered by <img src="img/automx-banner.png" width="126" height="20" alt="automx banner" /></a>
   </div>
   <div id="footer-mobile" class="show-for-small row">
     <div class="small-12 columns">
-      <a class="right automx-powered" href="http://automx.org" target="_blank">Powered by <img src="img/automx-banner.png" width="126" height="20" alt="automx banner" /></a>
+      <a class="right automx-powered" href="https://automx.org" target="_blank">Powered by <img src="img/automx-banner.png" width="126" height="20" alt="automx banner" /></a>
     </div>
   </div>
 
openSUSE Build Service is sponsored by