summaryrefslogtreecommitdiff
path: root/sleekxmpp/componentxmpp.py
blob: 49aa83eab9c9e8f5f3061e4d52994c85ffe5ef9f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/usr/bin/python2.5

"""
    SleekXMPP: The Sleek XMPP Library
    Copyright (C) 2007  Nathanael C. Fritz
    This file is part of SleekXMPP.

    SleekXMPP 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 2 of the License, or
    (at your option) any later version.

    SleekXMPP 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 SleekXMPP; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
"""
from __future__ import absolute_import
from . basexmpp import basexmpp
from xml.etree import cElementTree as ET

# some servers use different namespaces for components -- this is a hack, but is there for compatibility
from . import xmlstream.matcher.xmlmask
from . import xmlstream.matcher.xpath
xmlstream.matcher.xmlmask.ignore_ns = True
xmlstream.matcher.xpath.ignore_ns = True
# ----------

from . xmlstream.xmlstream import XMLStream
from . xmlstream.xmlstream import RestartStream
from . xmlstream.matcher.xmlmask import MatchXMLMask
from . xmlstream.matcher.xpath import MatchXPath
from . xmlstream.matcher.many import MatchMany
from . xmlstream.handler.callback import Callback
from . xmlstream.stanzabase import StanzaBase
from . xmlstream import xmlstream as xmlstreammod
import time
import logging
import base64
import sys
import random
import copy
from . import plugins
from . import stanza
import sha
srvsupport = True
try:
	import dns.resolver
except ImportError:
	srvsupport = False


class ComponentXMPP(basexmpp, XMLStream):
	"""SleekXMPP's client class.  Use only for good, not evil."""

	def __init__(self, jid, secret, host, port, plugin_config = {}, plugin_whitelist=[]):
		XMLStream.__init__(self)
		self.default_ns = 'jabber:component:accept'
		basexmpp.__init__(self)
		self.auto_authorize = None
		self.stream_header = "<stream:stream xmlns='jabber:component:accept' xmlns:stream='http://etherx.jabber.org/streams' to='%s'>" % jid
		self.stream_footer = "</stream:stream>"
		self.server_host = host
		self.server_port = port
		self.set_jid(jid)
		self.secret = secret
		self.registerHandler(Callback('PresenceProbe', MatchXMLMask("<presence xmlns='%s' type='probe'/>" % self.default_ns), self._handlePresenceProbe))
		self.registerHandler(Callback('Handshake', MatchXPath('{jabber:component:accept}handshake'), self._handleHandshake))
		self.registerHandler(Callback('PresenceSubscription', MatchMany(\
			(MatchXMLMask("<presence xmlns='%s' type='subscribe'/>" % self.default_ns), \
			 MatchXMLMask("<presence xmlns='%s' type='subscribed'/>" % self.default_ns), \
			 MatchXMLMask("<presence xmlns='%s' type='unsubscribe'/>" % self.default_ns), \
			 MatchXMLMask("<presence xmlns='%s' type='unsubscribed'/>" % self.default_ns) \
			 )), self._handlePresenceSubscription))

	def _handlePresenceProbe(self, stanza):
		xml = stanza.xml
		self.event("got_presence_probe", ({
				'from': xml.attrib['from'],
				'to': xml.attrib['to']
			}))

	def _handlePresenceSubscription(self, presence):
		xml = presence.xml
		self.event("changed_subscription", {
				'type' : xml.attrib['type'],
				'from': xml.attrib['from'],
				'to': xml.attrib['to'] 
			})
	
	def start_stream_handler(self, xml):
		sid = xml.get('id', '')
		handshake = ET.Element('{jabber:component:accept}handshake')
		handshake.text = sha.new(u"%s%s" % (sid, self.secret)).hexdigest().lower()
		self.send(handshake)
	
	def _handleHandshake(self, xml):
		self.event("session_start")
	
	def connect(self):
		logging.debug("Connecting to %s:%s" % (self.server_host, self.server_port))
		return xmlstreammod.XMLStream.connect(self, self.server_host, self.server_port)