You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
3.8 KiB
164 lines
3.8 KiB
|
|
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 "<!--out-->\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
|
|
|
|
|
|
|