aboutsummaryrefslogtreecommitdiffstats
path: root/server/xep_0077.py
diff options
context:
space:
mode:
authorGuillaume Horel <guillaume.horel@gmail.com>2011-04-27 01:04:03 -0400
committerGuillaume Horel <guillaume.horel@gmail.com>2011-04-27 01:04:03 -0400
commitb38e784e1aeb0b3f3db4a8a33799c4bd94a5d10a (patch)
tree6df5fa411b7db980869d259de4319f762baa705d /server/xep_0077.py
parentd045912cb5b4e49140514b7dbf2ca4bc5ca5098f (diff)
downloadalias-b38e784e1aeb0b3f3db4a8a33799c4bd94a5d10a.tar.gz
Preliminary work for in-band registration.
Diffstat (limited to 'server/xep_0077.py')
-rw-r--r--server/xep_0077.py158
1 files changed, 158 insertions, 0 deletions
diff --git a/server/xep_0077.py b/server/xep_0077.py
new file mode 100644
index 0000000..b07105b
--- /dev/null
+++ b/server/xep_0077.py
@@ -0,0 +1,158 @@
+"""
+Creating a SleekXMPP Plugin
+
+This is a minimal implementation of XEP-0077 to serve
+as a tutorial for creating SleekXMPP plugins.
+"""
+
+from sleekxmpp.plugins.base import base_plugin
+from sleekxmpp.xmlstream.handler.callback import Callback
+from sleekxmpp.xmlstream.matcher.xpath import MatchXPath
+from sleekxmpp.xmlstream import ElementBase, ET, register_stanza_plugin
+from sleekxmpp import Iq
+from user import UserHandler
+from config import config
+
+class Registration(ElementBase):
+ namespace = 'jabber:iq:register'
+ name = 'query'
+ plugin_attrib = 'register'
+ interfaces = set(('pubkey', 'privkey', 'salt'
+ 'registered', 'remove', 'instructions'))
+ sub_interfaces = interfaces
+
+ def getRegistered(self):
+ present = self.xml.find('{%s}registered' % self.namespace)
+ return present is not None
+
+ def getRemove(self):
+ present = self.xml.find('{%s}remove' % self.namespace)
+ return present is not None
+
+ def setRegistered(self, registered):
+ if registered:
+ self.addField('registered')
+ else:
+ del self['registered']
+
+ def setRemove(self, remove):
+ if remove:
+ self.addField('remove')
+ else:
+ del self['remove']
+
+ def addField(self, name):
+ itemXML = ET.Element('{%s}%s' % (self.namespace, name))
+ self.xml.append(itemXML)
+
+
+class UserStore(object):
+ def __init__(self):
+ self.users = {}
+
+ def __getitem__(self, jid):
+ return self.users.get(jid, None)
+
+ def register(self, jid, registration):
+ username = registration['username']
+
+ def filter_usernames(user):
+ return user != jid and self.users[user]['username'] == username
+
+ conflicts = filter(filter_usernames, self.users.keys())
+ if conflicts:
+ return False
+
+ self.users[jid] = registration
+ return True
+
+ def unregister(self, jid):
+ del self.users[jid]
+
+class xep_0077(base_plugin):
+ """
+ XEP-0077 In-Band Registration
+ """
+
+ def plugin_init(self):
+ self.description = "In-Band Registration"
+ self.xep = "0077"
+ self.form_fields = ()
+ self.form_instructions = ""
+ self.backend = UserHandler(config.root)
+
+ self.xmpp.registerHandler(
+ Callback('In-Band Registration',
+ MatchXPath('{%s}iq/{jabber:iq:register}query' % self.xmpp.default_ns),
+ self.__handleRegistration))
+ register_stanza_plugin(Iq, Registration)
+
+ def post_init(self):
+ base_plugin.post_init(self)
+ self.xmpp['xep_0030'].add_feature("jabber:iq:register")
+
+ def __handleRegistration(self, iq):
+ if iq['type'] == 'get':
+ # Registration form requested
+ self.sendRegistrationForm(iq, self.backend)
+ elif iq['type'] == 'set':
+ if iq['register']['remove']:
+ # Remove an account
+ self.backend.unregister(iq['from'].bare)
+ #self.xmpp.event('unregistered_user', iq)
+ iq.reply().send()
+ return
+
+ for field in self.form_fields:
+ if not iq['register'][field]:
+ # Incomplete Registration
+ self._sendError(iq, '406', 'modify', 'not-acceptable',
+ "Please fill in all fields.")
+ return
+
+ if self.backend.register(iq['from'].bare, iq['register']):
+ # Successful registration
+ #self.xmpp.event('registered_user', iq)
+ iq.reply().setPayload(iq['register'].xml)
+ iq.send()
+ else:
+ # Conflicting registration
+ self._sendError(iq, '409', 'cancel', 'conflict',
+ "That username is already taken.")
+
+ def setForm(self, *fields):
+ self.form_fields = fields
+
+ def setInstructions(self, instructions):
+ self.form_instructions = instructions
+
+ def sendRegistrationForm(self, iq, userHandler):
+ reg = iq['register']
+ if user
+ userData = {}
+ else:
+ reg['registered'] = True
+
+ if self.form_instructions:
+ reg['instructions'] = self.form_instructions
+
+ for field in self.form_fields:
+ data = userData.get(field, '')
+ if data:
+ # Add field with existing data
+ reg[field] = data
+ else:
+ # Add a blank field
+ reg.addField(field)
+
+ iq.reply().setPayload(reg.xml)
+ iq.send()
+
+ def _sendError(self, iq, code, error_type, name, text=''):
+ iq.reply().setPayload(iq['register'].xml)
+ iq.error()
+ iq['error']['code'] = code
+ iq['error']['type'] = error_type
+ iq['error']['condition'] = name
+ iq['error']['text'] = text
+ iq.send() \ No newline at end of file