1"""
2    Slixmpp: The Slick XMPP Library
3    Copyright (C) 2015 Emmanuel Gil Peyrot
4    This file is part of Slixmpp.
5
6    See the file LICENSE for copying permission.
7"""
8
9import asyncio
10import logging
11from uuid import uuid4
12
13from slixmpp.plugins import BasePlugin, register_plugin
14from slixmpp import future_wrapper, Iq, Message
15from slixmpp.exceptions import XMPPError, IqError, IqTimeout
16from slixmpp.jid import JID
17from slixmpp.xmlstream import JID, register_stanza_plugin
18from slixmpp.xmlstream.handler import Callback
19from slixmpp.xmlstream.matcher import StanzaPath
20from slixmpp.plugins.xep_0070 import stanza, Confirm
21
22
23log = logging.getLogger(__name__)
24
25
26class XEP_0070(BasePlugin):
27
28    """
29    XEP-0070 Verifying HTTP Requests via XMPP
30    """
31
32    name = 'xep_0070'
33    description = 'XEP-0070: Verifying HTTP Requests via XMPP'
34    dependencies = {'xep_0030'}
35    stanza = stanza
36
37    def plugin_init(self):
38        register_stanza_plugin(Iq, Confirm)
39        register_stanza_plugin(Message, Confirm)
40
41        self.xmpp.register_handler(
42            Callback('Confirm',
43                 StanzaPath('iq@type=get/confirm'),
44                 self._handle_iq_confirm))
45
46        self.xmpp.register_handler(
47            Callback('Confirm',
48                 StanzaPath('message/confirm'),
49                 self._handle_message_confirm))
50
51    def plugin_end(self):
52        self.xmpp.remove_handler('Confirm')
53        self.xmpp['xep_0030'].del_feature(feature='http://jabber.org/protocol/http-auth')
54
55    def session_bind(self, jid):
56        self.xmpp['xep_0030'].add_feature('http://jabber.org/protocol/http-auth')
57
58    @future_wrapper
59    def ask_confirm(self, jid, id, url, method, *, ifrom=None, message=None):
60        jid = JID(jid)
61        if jid.resource:
62            stanza = self.xmpp.Iq()
63            stanza['type'] = 'get'
64        else:
65            stanza = self.xmpp.Message()
66            stanza['thread'] = uuid4().hex
67        stanza['from'] = ifrom
68        stanza['to'] = jid
69        stanza['confirm']['id'] = id
70        stanza['confirm']['url'] = url
71        stanza['confirm']['method'] = method
72        if not jid.resource:
73            if message is not None:
74                stanza['body'] = message.format(id=id, url=url, method=method)
75            stanza.send()
76            return stanza
77        else:
78            return stanza.send()
79
80    def _handle_iq_confirm(self, iq):
81        self.xmpp.event('http_confirm_iq', iq)
82        self.xmpp.event('http_confirm', iq)
83
84    def _handle_message_confirm(self, message):
85        self.xmpp.event('http_confirm_message', message)
86        self.xmpp.event('http_confirm', message)
87