import async import xmpp from mmptypes import * import utils import time import spool import core import glue import pool import mrim import forms import i18n import traceback import sys import os import socket import logging import gw import xml.parsers.expat conf = mrim.conf class XMPPTransport(gw.XMPPSocket): def __init__(self, name, disconame, server, port, password, logger): self.name = name self._id = '0' self.requests = {} self.disconame = disconame self.port = port self.server = server self.password = password self.logger = logger self.reconnectors = {} self.caps = {} self.last_version_time = time.strftime('%Y%m%d-%H%M') self.server_ids = { 'category':'gateway', 'type':'mrim', 'name':self.disconame } gw.XMPPSocket.__init__(self) def run(self): self.start(self.server, self.port, self.name, self.password) self.startup = time.time() self.RegisterDefaultHandler(lambda x,y: None) self.RegisterHandler('iq', self.process_iq) self.RegisterHandler('presence', self.process_presence) self.RegisterHandler('message', self.process_message) self.sform = forms.get_search_form() self.Features = forms.get_disco_features(self.server_ids, utils.server_features) if conf.probe: self.start_all_connections() async.loop(use_poll=True) def process_iq(self, conn, iq): if not self.check_access(iq): return ns = iq.getQueryNS() typ = iq.getType() if ns == xmpp.NS_REGISTER: self.iq_register_handler(iq) elif ns == xmpp.NS_GATEWAY: self.iq_gateway_handler(iq) elif ns == xmpp.NS_STATS: self.iq_stats_handler(iq) elif ns == xmpp.NS_TIME: self.iq_time_handler(iq, 'old') elif iq.getTag('time') and iq.getTag('time').getNamespace() == xmpp.NS_NEW_TIME: self.iq_time_handler(iq, 'new') elif ns == xmpp.NS_LAST: self.iq_last_handler(iq) elif ns == xmpp.NS_SEARCH: self.iq_search_handler(iq) elif ns == xmpp.NS_VERSION: self.iq_version_handler(iq) elif iq.getTag('vCard') and iq.getTag('vCard').getNamespace()==xmpp.NS_VCARD: self.iq_vcard_handler(iq) elif iq.getTag('command') and iq.getTag('command').getNamespace()==xmpp.NS_COMMANDS: self.iq_command_handler(iq) elif ns == xmpp.NS_DISCO_INFO: self.iq_disco_info_handler(iq) elif ns == xmpp.NS_DISCO_ITEMS: self.iq_disco_items_handler(iq) elif iq.getTag('ping') and iq.getTag('ping').getNamespace() == xmpp.NS_PING: self.iq_ping_handler(iq) else: self.send_not_implemented(iq) def process_presence(self, conn, presence): if not self.check_access(presence): return typ = presence.getType() if typ == 'unavailable': self.presence_unavailable_handler(presence) elif typ == 'subscribe': self.presence_subscribe_handler(presence) elif typ == 'subscribed': self.presence_subscribed_handler(presence) elif typ == 'unsubscribe': self.presence_unsubscribe_handler(presence) elif typ == 'unsubscribed': self.presence_unsubscribed_handler(presence) elif typ == 'probe': pass elif typ == 'error': self.presence_error_handler(presence) elif not typ: self.presence_available_handler(presence) def process_message(self, conn, message): if not self.check_access(message): return jid_to = message.getTo() jid_to_stripped = jid_to.getStripped() if message.getType() == 'error': self.message_error_handler(message) elif jid_to_stripped == self.name: self.message_server_handler(message) else: self.message_user_handler(message) def iq_disco_info_handler(self, iq): jid_from = iq.getFrom() jid_from_stripped = jid_from.getStripped() jid_to = iq.getTo() jid_to_stripped = jid_to.getStripped() typ = iq.getType() _id = iq.getAttr('id') node = iq.getTagAttr('query','node') if jid_to_stripped==self.name and typ=='get' and ((not node) or (node == '#'.join((utils.NODE, utils.SERVER_CAPS)))): #If node is empty or equal NODE#SERVER_CAPS then returm disco reply = iq.buildReply(typ='result') reply.setQueryPayload(self.Features) self.send(reply) elif jid_to_stripped==self.name and typ=='get' and node: self.iq_disco_node_info_handler(iq, node) elif utils.is_valid_email(utils.jid2mail(jid_to_stripped)) and typ=='get': if node and (node != '#'.join(('none', utils.CLIENT_CAPS))): self.iq_disco_user_node_info_handler(iq, node) else: #If node is empty or equal none#CLIENT_CAPS then returm disco ids = { 'category':'client', 'type':'pc', 'name':'mrim' } feats = forms.get_disco_features(ids, utils.client_features) reply = iq.buildReply(typ='result') reply.setQueryPayload(feats) self.send(reply) elif jid_to==self.name and typ=='result' and not node: if self.requests.has_key(_id): caps = self.requests[_id] del self.requests[_id] self.cache_features(caps, iq.getQueryChildren()) else: self.send_not_implemented(iq) def iq_disco_items_handler(self, iq): jid_from = iq.getFrom() jid_from_stripped = jid_from.getStripped() jid_to = iq.getTo() jid_to_stripped = jid_to.getStripped() jid_to_node = jid_to.getNode() typ = iq.getType() node = iq.getTagAttr('query','node') if jid_to_stripped==self.name and typ=='get' and node: self.iq_disco_node_items_handler(iq, node) elif jid_to_stripped==self.name and typ=='get' and not node: reply = iq.buildReply(typ='result') if jid_from_stripped in conf.admins: item = xmpp.Node('item',attrs={ 'jid':self.name, 'name':'online', 'node':'online' } ) reply.setQueryPayload([item]) command = xmpp.Node('item', attrs={ 'jid':self.name, 'name':'commands', 'node':xmpp.NS_COMMANDS } ) reply.getTag('query').addChild(node=command) self.send(reply) elif utils.is_valid_email(utils.jid2mail(jid_to_stripped)) and typ=='get': if node: self.iq_disco_user_node_items_handler(iq, node) else: reply = iq.buildReply(typ='result') command = xmpp.Node('item', attrs={ 'jid':jid_to, 'name':'commands', 'node':xmpp.NS_COMMANDS } ) reply.getTag('query').addChild(node=command) self.send(reply) else: self.send_not_implemented(iq) def iq_disco_node_info_handler(self, iq, node): jid_from = iq.getFrom() jid_from_stripped = jid_from.getStripped() jid_to = iq.getTo() jid_to_stripped = jid_to.getStripped() typ = iq.getType() if node=='online': if jid_from_stripped not in conf.admins: self.send_not_implemented(iq) return count = len(pool.getJids()) ids = { 'category':'directory', 'type':'user', 'name':'Users Online (%s)' % count } features = [ xmpp.NS_DISCO_INFO, xmpp.NS_DISCO_ITEMS ] reply = iq.buildReply(typ='result') reply.setQueryPayload(forms.get_disco_features(ids,features)) reply.setTagAttr('query','node','online') self.send(reply) elif node==xmpp.NS_COMMANDS: ids = { 'category':'automation', 'type':'command-list', 'name':'Service Commands' } features = [xmpp.NS_COMMANDS] reply = iq.buildReply(typ='result') reply.setQueryPayload(forms.get_disco_features(ids,features)) reply.setTagAttr('query','node',xmpp.NS_COMMANDS) self.send(reply) elif node in ['mail', 'sms']: if node=='mail': node_name = 'Mail Events' elif node=='sms': node_name = 'Send SMS' ids = { 'category':'automation', 'type':'command-node', 'name':node_name } features = [ xmpp.NS_COMMANDS, xmpp.NS_DATA ] reply = iq.buildReply(typ='result') reply.setQueryPayload(forms.get_disco_features(ids,features)) reply.setTagAttr('query','node',node) self.send(reply) else: self.send_not_implemented(iq) def iq_disco_user_node_info_handler(self, iq, node): jid_from = iq.getFrom() jid_from_stripped = jid_from.getStripped() jid_to = iq.getTo() jid_to_stripped = jid_to.getStripped() typ = iq.getType() if node==xmpp.NS_COMMANDS: ids = { 'category':'automation', 'type':'command-list', 'name':'User Commands' } features = [xmpp.NS_COMMANDS] reply = iq.buildReply(typ='result') reply.setQueryPayload(forms.get_disco_features(ids,features)) reply.setTagAttr('query','node',xmpp.NS_COMMANDS) self.send(reply) elif node in ['conf_sms', 'send_sms']: if node=='conf_sms': node_name = 'Configure SMS' elif node=='send_sms': node_name = 'Send SMS' ids = { 'category':'automation', 'type':'command-node', 'name':node_name } features = [ xmpp.NS_COMMANDS, xmpp.NS_DATA ] reply = iq.buildReply(typ='result') reply.setQueryPayload(forms.get_disco_features(ids,features)) reply.setTagAttr('query','node',node) self.send(reply) else: self.send_not_implemented(iq) def iq_disco_node_items_handler(self, iq, node): jid_from = iq.getFrom() jid_from_stripped = jid_from.getStripped() jid_to = iq.getTo() jid_to_stripped = jid_to.getStripped() typ = iq.getType() if node=='online': items = [] reply = iq.buildReply(typ='result') if jid_from_stripped in conf.admins: for jid in pool.getJids(): try: legacy_user = pool.get(jid).user item_attrs = { 'jid':jid, 'name':legacy_user, } item = xmpp.Node('item',attrs=item_attrs) items.append(item) except: pass reply.setQueryPayload(items) reply.setTagAttr('query','node','online') else: reply.setQueryPayload([]) self.send(reply) elif node==xmpp.NS_COMMANDS: mail_attrs = {'jid':self.name,'node':'mail','name':'Mail Events'} sms_attrs = {'jid':self.name,'node':'sms','name':'Send SMS'} mail = xmpp.Node('item',attrs=mail_attrs) sms = xmpp.Node('item',attrs=sms_attrs) reply = iq.buildReply(typ='result') reply.setTagAttr('query','node',xmpp.NS_COMMANDS) reply.setQueryPayload([mail, sms]) self.send(reply) elif node in ['mail', 'sms']: reply = iq.buildReply(typ='result') reply.setTagAttr('query','node',node) self.send(reply) else: self.send_not_implemented(iq) def iq_disco_user_node_items_handler(self, iq, node): jid_from = iq.getFrom() jid_from_stripped = jid_from.getStripped() jid_to = iq.getTo() jid_to_stripped = jid_to.getStripped() typ = iq.getType() if node==xmpp.NS_COMMANDS: mail_attrs = {'jid':jid_to,'node':'conf_sms','name':'Configure SMS'} sms_attrs = {'jid':jid_to,'node':'send_sms','name':'Send SMS'} mail = xmpp.Node('item',attrs=mail_attrs) sms = xmpp.Node('item',attrs=sms_attrs) reply = iq.buildReply(typ='result') reply.setTagAttr('query','node',xmpp.NS_COMMANDS) reply.setQueryPayload([mail, sms]) self.send(reply) elif node in ['conf_sms', 'send_sms']: reply = iq.buildReply(typ='result') reply.setTagAttr('query','node',node) self.send(reply) else: self.send_not_implemented(iq) def iq_register_handler(self, iq): jid_from = iq.getFrom() jid_from_stripped = jid_from.getStripped() jid_to = iq.getTo() jid_to_stripped = jid_to.getStripped() typ = iq.getType() iq_children = iq.getQueryChildren() if (typ=='get') and (jid_to_stripped==self.name) and (not iq_children): repl = iq.buildReply(typ='result') repl.setQueryPayload(self.get_register_form(jid_from_stripped)) self.send(repl) elif typ == 'set' and (jid_to_stripped==self.name) and iq_children: query_tag = iq.getTag('query') if query_tag.getTag('email') and query_tag.getTag('password'): user = query_tag.getTagData('email') password = query_tag.getTagData('password') error = xmpp.ERR_BAD_REQUEST if not user: text = i18n.NULL_EMAIL self.send_error(iq,error,text) return if not password: text = i18n.NULL_PASSWORD self.send_error(iq,error,text) return if not utils.is_valid_email(user): text = i18n.UNACCEPTABLE_EMAIL self.send_error(iq,error,text) return if not utils.is_valid_password(password): text = i18n.UNACCEPTABLE_PASSWORD self.send_error(iq,error,text) return mmp_conn = pool.get(jid_from) if mmp_conn: mmp_conn.exit() self.mrim_connection_start(jid_from, iq_register=iq) elif query_tag.getTag('remove'): account = spool.Profile(jid_from_stripped) if account.remove(): spool.Options(jid_from).remove() ok_iq = iq.buildReply(typ='result') ok_iq.setPayload([],add=0) self.send(ok_iq) unsub = xmpp.Presence(to=jid_from_stripped,frm=self.name) unsub.setType('unsubscribe') self.send(unsub) unsub.setType('unsubscribed') self.send(unsub) else: pass mmp_conn = pool.get(jid_from) if mmp_conn: mmp_conn.exit() else: tags_in_register_form = [child.getName() for child in query_tag.getChildren()] if ['username', 'password', 'nick', 'key'] == tags_in_register_form: pandion_suxx = "Please report to Pandion developers that their client doesn't really support forms and we know it ;)" pandion_error = xmpp.Error(iq,xmpp.ERR_NOT_ACCEPTABLE) pandion_error.getTag('error').setTagData('text', pandion_suxx) self.send(pandion_error) else: unknown_client_suxx = "Nice try =) Please report to developers that your client doesn't really support forms." self.send_error(iq,error=xmpp.ERR_NOT_ACCEPTABLE,text=unknown_client_suxx) else: self.send_not_implemented(iq) def iq_gateway_handler(self, iq): jid_to = iq.getTo() jid_to_stripped = jid_to.getStripped() iq_children = iq.getQueryChildren() typ = iq.getType() if (typ=='get') and (jid_to_stripped==self.name) and (not iq_children): repl = iq.buildReply(typ='result') query = xmpp.Node('query', attrs={'xmlns':xmpp.NS_GATEWAY}) query.setTagData('desc', i18n.ENTER_EMAIL) query.setTag('prompt') repl.setPayload([query]) self.send(repl) elif (typ=='set') and (jid_to_stripped==self.name) and iq_children: e_mail = [node.getData() for node in iq_children if node.getName()=='prompt'] if len(e_mail) == 1: prompt = xmpp.simplexml.Node('jid') prompt.setData(utils.mail2jid(e_mail[0])) repl = iq.buildReply(typ='result') repl.setQueryPayload([prompt]) self.send(repl) else: self.send_bad_request(iq) else: self.send_not_implemented(iq) def iq_search_handler(self, iq): jid_from = iq.getFrom() jid_to = iq.getTo() jid_to_stripped = jid_to.getStripped() typ = iq.getType() iq_children = iq.getQueryChildren() if (typ=='get') and (jid_to_stripped==self.name): if iq_children: self.send_bad_request(iq) else: mmp_conn = pool.get(jid_from) if mmp_conn: repl = iq.buildReply(typ='result') repl.setQueryPayload([self.sform]) self.send(repl) else: err = xmpp.ERR_REGISTRATION_REQUIRED txt = i18n.NOT_CONNECTED self.send_error(iq, err, txt) elif typ=='set' and (jid_to_stripped==self.name): if not iq_children: self.send_bad_request(iq) else: proto_dict = forms.workup_search_input(iq) mmp_conn = pool.get(jid_from) if mmp_conn: mmp_conn.search(proto_dict,iq) else: err = xmpp.ERR_REGISTRATION_REQUIRED txt = i18n.NOT_CONNECTED self.send_error(iq, err, txt) else: self.send_not_implemented(iq) def iq_version_handler(self, iq): jid_to = iq.getTo() jid_to_stripped = jid_to.getStripped() jid_from = iq.getFrom() jid_from_stripped = jid_from.getStripped() typ = iq.getType() iq_children = iq.getQueryChildren() if typ=='get' and (jid_to_stripped==self.name): if iq_children: self.send_bad_request(iq) else: repl = iq.buildReply(typ='result') query = repl.getTag('query') query.setTagData('name', conf.program) query.setTagData('version', conf.version) query.setTagData('os', conf.os) self.send(repl) elif typ=='result': query = iq.getTag('query') Name = query.getTagData('name') and query.getTagData('name').encode('utf-8', 'replace') Version = query.getTagData('version') and query.getTagData('version').encode('utf-8', 'replace') Os = query.getTagData('os') and query.getTagData('os').encode('utf-8', 'replace') resource = jid_from.getResource().encode('utf-8', 'replace') user = jid_from_stripped.encode('utf-8', 'replace')+'/'+resource fd = open( os.path.join(conf.profile_dir,'version_stats-'+self.last_version_time),'a+' ) fd.write("%s\t%s\t%s\t%s\n" % (user, Name, Version, Os)) fd.close() else: self.send_not_implemented(iq) def iq_time_handler(self, iq, ver): jid_to = iq.getTo() jid_to_stripped = jid_to.getStripped() typ = iq.getType() iq_children = iq.getQueryChildren() if typ=='get' and (jid_to_stripped==self.name): if iq_children: self.send_bad_request(iq) else: repl = iq.buildReply(typ='result') if ver=='old': query = xmpp.Node('query',attrs={'xmlns':xmpp.NS_TIME}) T = utils.gettime() query.setTagData('utc', T['utc']) query.setTagData('tz', T['tz']) query.setTagData('display', T['display']) repl.setPayload([query]) else: _time = xmpp.Node('time',attrs={'xmlns':xmpp.NS_NEW_TIME}) T = utils.xep_202_time() _time.setTagData('tzo', T[0]) _time.setTagData('utc', T[1]) repl.setPayload([_time]) self.send(repl) else: self.send_not_implemented(iq) def iq_last_handler(self, iq): jid_to = iq.getTo() jid_to_stripped = jid_to.getStripped() typ = iq.getType() iq_children = iq.getQueryChildren() if (jid_to_stripped==self.name) and typ=='get': if iq_children: self.send_bad_request(iq) else: repl = iq.buildReply(typ='result') repl.getTag('query').setAttr('seconds', int(time.time()-self.startup)) self.send(repl) else: self.send_not_implemented(iq) def iq_vcard_handler(self, iq): jid_from = iq.getFrom() jid_to = iq.getTo() jid_from_stripped = jid_from.getStripped() jid_to_stripped = jid_to.getStripped() typ = iq.getType() if jid_to_stripped!=self.name and typ=='get': mmp_conn = pool.get(jid_from) if mmp_conn: e_mail = utils.jid2mail(jid_to_stripped) mmp_conn.get_vcard(e_mail, iq) else: err = xmpp.ERR_REGISTRATION_REQUIRED txt = i18n.NOT_CONNECTED self.send_error(iq,err,txt) elif jid_to_stripped==self.name and typ=='get': vcard = xmpp.Node('vCard', attrs={'xmlns':xmpp.NS_VCARD}) vcard.setTagData('NICKNAME', conf.program) vcard.setTagData('DESC', 'XMPP to Mail.Ru-IM Transport\n'+conf.copyright) vcard.setTagData('URL', 'http://svn.xmpp.ru/repos/mrim') repl = iq.buildReply(typ='result') repl.setPayload([vcard]) self.send(repl) else: self.send_not_implemented(iq) def iq_stats_handler(self, iq): jid_to_stripped = iq.getTo() typ = iq.getType() iq_children = iq.getQueryChildren() if jid_to_stripped==self.name and typ=='get': payload = [] if not iq_children: total = xmpp.Node('stat', attrs={'name':'users/total'}) online = xmpp.Node('stat', attrs={'name':'users/online'}) payload = [total,online] else: for n in [child for child in iq_children if child.getName()=='stat']: if n.getAttr('name') == 'users/online': stat = xmpp.Node('stat', attrs={'units':'users'}) stat.setAttr('name','users/online') stat.setAttr('value',len(pool.getConnections())) payload.append(stat) elif n.getAttr('name') == 'users/total': stat = xmpp.Node('stat', attrs={'units':'users'}) stat.setAttr('name','users/total') users_total = len([ i for i in os.listdir(conf.profile_dir) if i.endswith('.xdb') ]) stat.setAttr('value',users_total) payload.append(stat) else: s = xmpp.Node('stat', attrs={'name':n.getAttr('name')}) err = xmpp.Node('error', attrs={'code':'404'}) err.setData('Not Found') s = xmpp.Node('stat', attrs={'name':n.getAttr('name')}) s.addChild(node=err) payload.append(s) if not payload: pass else: iq_repl = iq.buildReply(typ='result') iq_repl.setQueryPayload(payload) self.send(iq_repl) def iq_ping_handler(self, iq): jid_to = iq.getTo() jid_to_stripped = jid_to.getStripped() typ = iq.getType() iq_children = iq.getQueryChildren() if jid_to_stripped==self.name and typ=='get': repl = iq.buildReply(typ='result') repl.setPayload([]) self.send(repl) else: self.send_error(iq, xmpp.ERR_SERVICE_UNAVAILABLE) def iq_command_handler(self, iq): jid_from = iq.getFrom() jid_to = iq.getTo() jid_from_stripped = jid_from.getStripped() jid_to_stripped = jid_to.getStripped() typ = iq.getType() command = iq.getTag('command') sessionid = command.getAttr('sessionid') action = command.getAttr('action') node = command.getAttr('node') if not spool.is_registered(jid_from): err = xmpp.ERR_REGISTRATION_REQUIRED txt = i18n.NOT_REGISTERED self.send_error(iq,err,txt) return if typ=='set' and node=='mail' and jid_to_stripped==self.name: self.process_mail_cmd(iq, jid_from, command, sessionid, action) elif typ=='set' and node in ['sms', 'conf_sms', 'send_sms']: if pool.get(jid_from): if node=='sms' and jid_to_stripped==self.name: self.process_sms_cmd(iq, jid_from, command, sessionid, action) elif node=='conf_sms' and utils.is_valid_email(utils.jid2mail(jid_to_stripped)): self.process_conf_sms_cmd(iq, jid_from, command, sessionid, action) elif node=='send_sms' and utils.is_valid_email(utils.jid2mail(jid_to_stripped)): self.process_send_sms_cmd(iq, jid_from, command, sessionid, action) else: err = xmpp.ERR_REGISTRATION_REQUIRED txt = i18n.NOT_CONNECTED self.send_error(iq, err, txt) else: self.send_error(iq, xmpp.ERR_SERVICE_UNAVAILABLE) def process_mail_cmd(self, iq, jid, command, sessionid, action): if action=='execute' or (not action and not sessionid): response = forms.get_cmd_header('executing','mail') opts = spool.Options(jid) response.setPayload([ forms.get_mail_form(opts.getMboxStatus(),opts.getNewMail()) ]) reply = iq.buildReply(typ='result') reply.setPayload([response]) self.send(reply) elif action=='complete' or (not action and sessionid): response = forms.get_cmd_header('completed','mail',sessionid) xdata = iq.getTag('command').getTag('x') if forms.process_mail_command_xdata(jid, xdata): note = xmpp.Node('note', attrs={'type':'info'}) note.setData(i18n.COMMAND_SAVE_OK) response.setPayload([note]) reply = iq.buildReply(typ='result') reply.setPayload([response]) self.send(reply) else: self.send_bad_request(iq) elif action=='cancel': response = forms.get_cmd_header('canceled','mail',sessionid) reply = iq.buildReply(typ='result') reply.setPayload([response]) self.send(reply) else: self.send_bad_request(iq) def process_sms_cmd(self, iq, jid, command, sessionid, action): mmp_conn = pool.get(jid) if action=='execute' or (not action and not sessionid): response = forms.get_cmd_header('executing','sms') response.setPayload([forms.gate_sms_form()]) reply = iq.buildReply(typ='result') reply.setPayload([response]) self.send(reply) elif action=='cancel': response = forms.get_cmd_header('canceled','sms',sessionid) reply = iq.buildReply(typ='result') reply.setPayload([response]) self.send(reply) elif action=='complete' or (not action and sessionid): response = forms.get_cmd_header('completed','sms',sessionid) xdata = iq.getTag('command').getTag('x') code, result = forms.process_send_sms_xdata(xdata) if code: number, text = result mmp_conn.mmp_send_sms(to=number,body=text) note = xmpp.Node('note', attrs={'type':'info'}) note.setData(i18n.SMS_SEND_OK) response.setPayload([note]) reply = iq.buildReply(typ='result') reply.setPayload([response]) self.send(reply) else: self.send_error(iq, xmpp.ERR_BAD_REQUEST, result) else: self.send_bad_request(iq) def process_send_sms_cmd(self, iq, jid, command, sessionid, action): jid_to = iq.getTo().getStripped() mail = utils.jid2mail(jid_to) mmp_conn = pool.get(jid) if action=='execute' or (not action and not sessionid): err = xmpp.ERR_ITEM_NOT_FOUND if mail in mmp_conn.contact_list.getEmails(): nums = mmp_conn.contact_list.getPhones(mail) if nums: response = forms.get_cmd_header('executing','send_sms') response.setPayload([forms.user_sms_form(nums)]) reply = iq.buildReply(typ='result') reply.setPayload([response]) self.send(reply) else: txt = i18n.USER_HAS_NO_PHONES self.send_error(iq, err, txt) else: txt = i18n.USER_NOT_IN_CLIST self.send_error(iq, err, txt) elif action=='cancel': response = forms.get_cmd_header('canceled','send_sms',sessionid) reply = iq.buildReply(typ='result') reply.setPayload([response]) self.send(reply) elif action=='complete' or (not action and sessionid): response = forms.get_cmd_header('completed','send_sms',sessionid) xdata = iq.getTag('command').getTag('x') code, result = forms.process_send_sms_xdata(xdata) if code: number, text = result mmp_conn.mmp_send_sms(to=number,body=text) note = xmpp.Node('note', attrs={'type':'info'}) note.setData(i18n.SMS_SEND_OK) response.setPayload([note]) reply = iq.buildReply(typ='result') reply.setPayload([response]) self.send(reply) else: self.send_error(iq, xmpp.ERR_BAD_REQUEST, result) else: self.send_bad_request(iq) def process_conf_sms_cmd(self, iq, jid, command, sessionid, action): jid_to = iq.getTo().getStripped() mail = utils.jid2mail(jid_to) mmp_conn = pool.get(jid) if action=='execute' or (not action and not sessionid): if mail in mmp_conn.contact_list.getEmails(): nums = mmp_conn.contact_list.getPhones(mail) response = forms.get_cmd_header('executing','conf_sms') response.setPayload([forms.conf_sms_form(nums)]) reply = iq.buildReply(typ='result') reply.setPayload([response]) self.send(reply) else: err = xmpp.ERR_ITEM_NOT_FOUND txt = i18n.USER_NOT_IN_CLIST self.send_error(iq, err, txt) elif action=='complete' or (not action and sessionid): response = forms.get_cmd_header('completed','send_sms',sessionid) xdata = iq.getTag('command').getTag('x') code, result = forms.process_conf_sms_xdata(xdata) if code: if mail in mmp_conn.contact_list.getEmails(): mmp_conn.set_sms_phones(mail, result) mmp_conn.contact_list.setPhones(mail, result) note = xmpp.Node('note', attrs={'type':'info'}) note.setData(i18n.COMMAND_SAVE_OK) response.setPayload([note]) reply = iq.buildReply(typ='result') reply.setPayload([response]) self.send(reply) else: err = xmpp.ERR_ITEM_NOT_FOUND txt = i18n.USER_NOT_IN_CLIST self.send_error(iq, err, txt) else: self.send_error(iq, xmpp.ERR_BAD_REQUEST, result) elif action=='cancel': response = forms.get_cmd_header('canceled','conf_sms',sessionid) reply = iq.buildReply(typ='result') reply.setPayload([response]) self.send(reply) def presence_available_handler(self, presence): jid_from = presence.getFrom() jid_from_stripped = jid_from.getStripped() jid_to = presence.getTo() jid_to_stripped = jid_to.getStripped() show = presence.getShow() priority = presence.getPriority() if jid_to_stripped!=self.name: return mmp_conn = pool.get(jid_from, online=False) if mmp_conn: self.show_status(jid_from, priority, show, mmp_conn) else: c = presence.getTag('c', namespace=xmpp.NS_CAPS) caps = ("", "") if c: ver = c.getAttr('ver') or "" algo = c.getAttr('hash') or "sha-1" caps = (ver, algo) self.mrim_connection_start(jid_from, show, priority, caps) def presence_unavailable_handler(self, presence): jid_from = presence.getFrom() resource = jid_from.getResource() jid_from_stripped = jid_from.getStripped() jid_to = presence.getTo() jid_to_stripped = jid_to.getStripped() if jid_to_stripped!=self.name: return mmp_conn = pool.get(jid_from, online=False) offline = xmpp.Presence(to=jid_from, frm=self.name,typ='unavailable') if mmp_conn: if [jid_from.getResource()] != mmp_conn.getResources(): curshow = mmp_conn.getMaxShow() mmp_conn.broadcast_offline(jid_from) mmp_conn.delResource(resource) maxshow = mmp_conn.getMaxShow() if maxshow != curshow: prio = mmp_conn.getMaxPriority() res = mmp_conn.getMaxResource() jid_from.setResource(res) self.show_status(jid_from, prio, maxshow, mmp_conn, force=True) else: mmp_conn.exit() else: self.send(offline) def presence_subscribe_handler(self, presence): '''To be completely rewritten''' jid_from = presence.getFrom() jid_from_stripped = jid_from.getStripped() jid_to = presence.getTo() jid_to_stripped = jid_to.getStripped() if jid_to_stripped==self.name: self.send(xmpp.Presence(frm=self.name,to=jid_from_stripped,typ='subscribed')) self.send(xmpp.Presence(frm=self.name,to=jid_from)) else: e_mail = utils.jid2mail(jid_to_stripped) mmp_conn = pool.get(jid_from) if not mmp_conn: return if (e_mail in mmp_conn.contact_list.getEmails()) and \ mmp_conn.contact_list.isAuthorized(e_mail) and \ mmp_conn.contact_list.isValidUser(e_mail): subd = xmpp.Presence(frm=jid_to_stripped,to=jid_from_stripped,typ='subscribed') self.send(subd) pres = xmpp.Presence(frm=jid_to_stripped,to=jid_from) status = mmp_conn.contact_list.getUserStatus(e_mail) if status == STATUS_AWAY: pres.setShow('away') self.send(pres) elif status == STATUS_ONLINE: self.send(pres) else: mmp_conn.add_contact(e_mail) def presence_subscribed_handler(self, presence): jid_from = presence.getFrom() jid_from_stripped = jid_from.getStripped() jid_to = presence.getTo() jid_to_stripped = jid_to.getStripped() if jid_to_stripped==self.name: pass else: e_mail = utils.jid2mail(jid_to_stripped) mmp_conn = pool.get(jid_from) if mmp_conn: mmp_conn.mmp_send_subscribed(e_mail) def presence_unsubscribe_handler(self, presence): jid_from = presence.getFrom() jid_to = presence.getTo() jid_from_stripped = jid_from.getStripped() jid_to_stripped = jid_to.getStripped() if jid_to_stripped==self.name: return mmp_conn = pool.get(jid_from) if mmp_conn and mmp_conn._got_roster: e_mail = utils.jid2mail(jid_to_stripped) mmp_conn.del_contact(e_mail) def presence_unsubscribed_handler(self, presence): self.presence_unsubscribe_handler(presence) def presence_error_handler(self, presence): jid_from = presence.getFrom() mmp_conn = pool.get(jid_from) if mmp_conn: mmp_conn.exit(notify=False) def message_error_handler(self, message): jid_from = message.getFrom() mmp_conn = pool.get(jid_from) if mmp_conn: self.send_probe(jid_from.getStripped()) def message_server_handler(self, message): jid_from = message.getFrom() jid_from_stripped = jid_from.getStripped() body = message.getBody() if body: command = body.strip() if jid_from_stripped in conf.admins: if command=='version': self.collect_versions() def collect_versions(self): self.last_version_time = time.strftime('%Y%m%d-%H%M') version = xmpp.Iq(frm=conf.name,typ='get',queryNS=xmpp.NS_VERSION) for mmp_conn in pool.getConnections(): for resource in mmp_conn.getResources(): To = xmpp.JID(mmp_conn.jid) To.setResource(resource) version.setTo(To) self.send(version) def message_user_handler(self, message): jid_from = message.getFrom() jid_to = message.getTo() jid_to_stripped = jid_to.getStripped() mail_to = utils.jid2mail(jid_to_stripped) body = message.getBody() mmp_conn = pool.get(jid_from) if not mmp_conn: if body: err = xmpp.ERR_REGISTRATION_REQUIRED txt = i18n.NOT_CONNECTED self.send_error(message, err, txt) elif body: if len(body)<=65536: mmp_conn.cancel_composing(mail_to) mmp_conn.send_message(mail_to,body,message) else: err = xmpp.ERR_NOT_ACCEPTABLE txt = i18n.MESSAGE_TOO_BIG self.send_error(message, err, txt) else: x = message.getTag('x') c = message.getTag('composing') p = message.getTag('paused') HAVE_X_COMPOSING_START = x and x.getNamespace()=='jabber:x:event' \ and x.getTag('composing') and x.getTag('id') HAVE_X_COMPOSING_STOP = x and x.getNamespace()=='jabber:x:event' \ and (not x.getTag('composing')) and x.getTag('id') HAVE_COMPOSING = c and c.getNamespace()==xmpp.NS_CHATSTATES HAVE_PAUSED = p and p.getNamespace()==xmpp.NS_CHATSTATES if HAVE_X_COMPOSING_START or HAVE_COMPOSING: mmp_conn.mmp_send_typing_notify(mail_to) if HAVE_X_COMPOSING_STOP or HAVE_PAUSED: mmp_conn.cancel_composing(mail_to) def get_register_form(self, jid): user = spool.Profile(jid).getUsername() instr = xmpp.Node('instructions') instr.setData(i18n.ENTER_EMAIL_AND_PASSWORD) email = xmpp.Node('email') passwd = xmpp.Node('password') if user: reg = xmpp.Node('registered') email.setData(user) return [instr,reg,email,passwd] else: return [instr,email,passwd] def request_caps(self, caps, to): if self.caps.has_key(caps): return if utils.decode_caps_ver(caps): i = self.next_id() self.requests[i] = caps iq = xmpp.Iq(typ='get', queryNS=xmpp.NS_DISCO_INFO, frm=self.name, to=to) iq.setAttr('id', i) self.send(iq) def show_status(self, jid, priority, show, mmp_conn, force=False): resource = xmpp.JID(jid).getResource() HAVE_RESOURCE = mmp_conn.haveResource(resource) curshow = mmp_conn.getMaxShow() if HAVE_RESOURCE: mmp_conn.updatePriority(resource, priority, show) else: mmp_conn.addResource(resource, priority, show) maxshow = mmp_conn.getMaxShow() status = utils.show2status(maxshow) if (mmp_conn.current_status != status) or force: mmp_conn.current_status = status mmp_conn.mmp_change_status(status) if mmp_conn.state == 'session_established': if not HAVE_RESOURCE: self.send(xmpp.Presence(frm=self.name,to=jid)) mmp_conn.broadcast_online(jid) if (maxshow != curshow) or force: ricochet = xmpp.Presence(frm=self.name) utils.add_caps_s(ricochet) if maxshow in ['dnd', 'xa', 'away']: ricochet.setShow('away') for resource in mmp_conn.getResources(): To = xmpp.JID(jid) To.setResource(resource) ricochet.setTo(To) self.send(ricochet) def mrim_connection_start(self, jid, show=None, priority=None, caps=("", ""), iq_register=None): if iq_register: user = iq_register.getTag('query').getTagData('email') password = iq_register.getTag('query').getTagData('password') else: account = spool.Profile(xmpp.JID(jid).getStripped()) user = account.getUsername() password = account.getPassword() if not (user and password): return try: timer = self.reconnectors.pop(user) self.cancel_timer(timer) except: pass glue.MMPConnection(user,password,self,jid,priority,show,caps,iq_register).run() def send_not_implemented(self, iq): if iq.getType() in ['set','get']: self.send_error(iq) def send_bad_request(self, iq): if iq.getType() in ['set','get']: self.send_error(iq,xmpp.ERR_BAD_REQUEST) def send_error(self, stanza, error=xmpp.ERR_FEATURE_NOT_IMPLEMENTED, text='', reply=1): e = xmpp.Error(stanza,error,reply) if text: e.getTag('error').setTagData('text', text) e.getTag('error').getTag('text').setAttr('xml:lang','ru-RU') else: e.getTag('error').delChild('text') self.send(e) def send_probe(self, jid): probe = xmpp.Presence(frm=self.name,to=jid,typ='probe') self.send(probe) def stop(self, notify=True): for mmp_conn in pool.getConnections(online=False): mmp_conn.exit(notify) def start_all_connections(self): probe = xmpp.Presence(frm=conf.name,typ='probe') users = [f[:f.find('.xdb')] for f in os.listdir(conf.profile_dir) if f.endswith('.xdb')] for user in users: probe.setTo(user) self.send(probe) def reconnect_user(self, jid, mail, timeout): if conf.reconnect: self.logger.info("[%s] Reconnect over %s seconds" % (mail, timeout)) self.reconnectors[mail] = self.set_timer(timeout, ("reconnect", jid, mail)) def handle_timer(self, tref, (typ, jid, mail)): if typ=="reconnect": try: del self.reconnectors[mail] except: pass probe = xmpp.Presence(frm=self.name,to=jid,typ='probe') self.send(probe) def handle_close(self): self.close() self.stop(notify=False) self.logger.critical("Connection to server lost") def handle_error(self): if sys.exc_info()[0]==IOError: self.handle_close() elif sys.exc_info()[0]==xml.parsers.expat.ExpatError: self.handle_close() else: traceback.print_exc() def next_id(self): self._id = str(int(self._id) + 1) return self._id def cache_features(self, caps, payload): category, typ = '', '' features = [] ver, algo = caps for i in payload: if i.getName() == 'identity': category = i.getAttr('category') typ = i.getAttr('type') elif i.getName() == 'feature' and i.getAttr('var'): feature = i.getAttr('var') features.append(feature) if utils.encode_caps_ver(category, typ, features, algo) == ver: self.caps[caps] = features print self.caps def check_access(self, stanza): frm = stanza.getFrom() frm_domain = frm.getDomain() domains = conf.allow_domains if domains and (frm_domain not in domains): self.send_error(stanza, error=xmpp.ERR_PAYMENT_REQUIRED) return False else: return True