From 149edfe3efa9f7d13702f164d921c35e8b5c3ef1 Mon Sep 17 00:00:00 2001
From: Yann Leboulanger <yann@leboulanger.org>
Date: Sun, 19 Nov 2017 22:35:45 +0100
Subject: [PATCH] implement XEP-0156. Fixes #5795

---
 gajim/common/connection.py | 29 +++++++++++++++++++++++++++++
 gajim/common/resolver.py   | 18 +++++++++++++++---
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/gajim/common/connection.py b/gajim/common/connection.py
index 692dd2c0db..4a89b59569 100644
--- a/gajim/common/connection.py
+++ b/gajim/common/connection.py
@@ -181,6 +181,11 @@ class CommonConnection:
 
         self.get_config_values_or_default()
 
+        h = app.config.get_per('accounts', self.name, 'hostname')
+        if h:
+            app.resolver.resolve('_xmppconnect.' + helpers.idn_to_ascii(h),
+                self._on_resolve_txt, type_='txt')
+
     def _compute_resource(self):
         resource = app.config.get_per('accounts', self.name, 'resource')
         # All valid resource substitution strings should be added to this hash.
@@ -1104,6 +1109,28 @@ class Connection(CommonConnection, ConnectionHandlers):
                 i['ssl_port'] = ssl_p
         self._connect_to_next_host()
 
+    def _on_resolve_txt(self, host, result_array):
+        for res in result_array:
+            if res.startswith('_xmpp-client-xbosh='):
+                url = res[19:]
+                found = False
+                proxies = app.config.get_per('proxies')
+                for p in proxies:
+                    if app.config.get_per('proxies', p, 'type') == 'bosh' \
+                    and app.config.get_per('proxies', p, 'bosh_uri') == url:
+                        found = True
+                        break
+                if not found:
+                    h = app.config.get_per('accounts', self.name, 'hostname')
+                    p = 'bosh_' + h
+                    i = 0
+                    while p in proxies:
+                        i += 1
+                        p = 'bosh_' + h + str(i)
+                    app.config.add_per('proxies', p)
+                    app.config.set_per('proxies', p, 'type', 'bosh')
+                    app.config.set_per('proxies', p, 'bosh_uri', url)
+
 
     def _connect_to_next_host(self, retry=False):
         log.debug('Connection to next host')
@@ -2212,6 +2239,8 @@ class Connection(CommonConnection, ConnectionHandlers):
         self.on_connect_success = self._on_new_account
         self.on_connect_failure = self._on_new_account
         self.connect(config)
+        app.resolver.resolve('_xmppconnect.' + helpers.idn_to_ascii(
+            self._hostname), self._on_resolve_txt, type_='txt')
 
     def _on_new_account(self, con=None, con_type=None):
         if not con_type:
diff --git a/gajim/common/resolver.py b/gajim/common/resolver.py
index 6723652d59..173cf97e53 100644
--- a/gajim/common/resolver.py
+++ b/gajim/common/resolver.py
@@ -94,9 +94,8 @@ class GioResolver(CommonResolver):
 
     def start_resolve(self, host, type_):
         if type_ == 'txt':
-            # TXT record resolution isn't used anywhere at the moment so
-            # implementing it here isn't urgent
-            raise NotImplementedError("Gio resolver does not currently implement TXT records")
+            callback = functools.partial(self._on_ready_txt, host)
+            type_ = Gio.ResolverRecordType.TXT
         else:
             callback = functools.partial(self._on_ready_srv, host)
             type_ = Gio.ResolverRecordType.SRV
@@ -125,6 +124,19 @@ class GioResolver(CommonResolver):
             ]
         super()._on_ready(host, 'srv', result_list)
 
+    def _on_ready_txt(self, host, source_object, result):
+        try:
+            variant_results = source_object.lookup_records_finish(result)
+        except GLib.Error as e:
+            if e.domain == 'g-resolver-error-quark':
+                result_list = []
+                log.warning("Could not resolve host: %s", e.message)
+            else:
+                raise
+        else:
+            result_list = [res[0][0] for res in variant_results]
+        super()._on_ready(host, 'txt', result_list)
+
 
 # below lines is on how to use API and assist in testing
 if __name__ == '__main__':
-- 
GitLab