import xmpp, os, hashlib, time, brathuhn import socket, subprocess, random, s5b, util import config from threading import Thread from datetime import datetime GET_IP_CMD = ["dig", "myip.opendns.com", "@resolver1.opendns.com", "+short"] PROXY = config.S5B_PROXY ID=random.randint(0,1000000) BSTREAM_NS = "http://jabber.org/protocol/bytestreams" SI_NS = 'http://jabber.org/protocol/si' FILE_NS = 'http://jabber.org/protocol/si/profile/file-transfer' FEATURE_NS = 'http://jabber.org/protocol/feature-neg' X_DATA_NS = 'jabber:x:data' JABBER_NS = 'jabber:client' BYTESTREAM = 'http://jabber.org/protocol/bytestreams' IBB = 'http://jabber.org/protocol/ibb' transfer_ids = dict() queries = dict() LOCAL_IP = util.get_local_ip() def create_init_message(mfrom,to,name,size,fd): global ID global transfer_ids ID+=1 transfer_ids[unicode("si_%d"%ID)]=[fd,ID,size] iq=xmpp.Iq(xmlns=JABBER_NS, attrs={'from':unicode(mfrom),'to':to,'id':"si_%d" % ID,'type':'set'}) si=iq.addChild(name="si",namespace=SI_NS, attrs={'id':"si_%d" % ID, 'profile':FILE_NS}) si.addChild(name="file", namespace=FILE_NS, attrs={'name':name,'size':size}) fr=si.addChild(name="feature", namespace=FEATURE_NS) x=fr.addChild(name="x", namespace=X_DATA_NS, attrs={'type':'form'}) fd=x.addChild(name="field",attrs={'type':'list-single','var':'stream-method'}) opt=fd.addChild(name="option") val=opt.addChild(name="value") val.addData(BYTESTREAM) opt=fd.addChild(name="option") val=opt.addChild(name="value") val.addData(IBB) return iq def create_bytestream_query_message(mfrom,to,port,cid): global queries sid = "si_%d" % cid queries[sid] = cid iq=xmpp.Iq(xmlns=JABBER_NS, attrs={'from':unicode(mfrom),'to':to,'id':sid,'type':'set'}) q = iq.addChild(name="query",namespace=BSTREAM_NS, attrs={'sid':sid}) hosts = [] p=subprocess.Popen(GET_IP_CMD,stdout=subprocess.PIPE) p.wait() hosts.append(p.stdout.read()) hosts.append(LOCAL_IP) for host in hosts: q.addChild(name="streamhost",attrs={'jid':unicode(mfrom),'port':str(port),'host':host}) #print "\n",q return iq def start_ibb(cid,mfrom,fd): print "IBB" stream = xmpp.filetransfer.IBB() stream.PlugIn(brathuhn.cl) stream.OpenStream("si_%d" % cid, mfrom, fd, blocksize=4096) def ft_query(conn,msg): global queries global transfer_ids sid = msg.attrs['id'] cid = queries[sid] assert sid in transfer_ids fd = transfer_ids[ sid ][0] if msg.attrs['type']=='error': start_ibb(cid, unicode(msg.getFrom()), fd) del transfer_ids[ sid ] del queries[ sid ] def ft_init(conn,msg): global ID sid = msg.attrs['id'] if msg.attrs['type']=='result': fd = transfer_ids[ sid ][0] size = transfer_ids[ sid ][2] current_id = transfer_ids[ sid ][1] else: del transfer_ids[ sid ] return si=msg.getChildren()[0] # check if cancel message if si.name!='si': return fr=si.getChildren()[0] # some clients send a profile name # we will ignore it i.e take the next child if fr.name=='file': fr=si.getChildren()[1] if fr.name!='feature': return x=fr.getChildren()[0] if x.name!='x' and x.attrs['type']!='submit': return fi=x.getChildren()[0] if fi.name!='field': return val=fi.getChildren()[0] if val.name!='value': return if val.data[0]==BYTESTREAM: print "BYTESTREAM" s,port=s5b.s5b_prepare() q = create_bytestream_query_message(brathuhn.room_nick,msg.getFrom(),port,current_id) brathuhn.cl.send(q) def __run(): s5b.s5b_write_file(s,fd,size) Thread(target=__run()).start() ID += 1 elif val.data[0]==IBB: start_ibb(current_id, unicode(msg.getFrom()), fd) def ft_listener(conn,msg): global transfer_ids global queries assert msg.name=='iq' sid = msg.attrs['id'] if sid in transfer_ids and not sid in queries: print "init" ft_init(conn,msg) return if sid in queries: ft_query(conn,msg) return