]> code.delx.au - pymsnt/blob - src/ft.py
Still not working. *sigh*
[pymsnt] / src / ft.py
1 # Copyright 2005 James Bunton <james@delx.cjb.net>
2 # Licensed for distribution under the GPL version 2, check COPYING for details
3
4 import disco
5 from debug import LogEvent, INFO, WARN, ERROR
6 import config
7 import utils
8 if utils.checkTwisted():
9 from twisted.xish.domish import Element
10 else:
11 from tlib.domish import Element
12
13 import random
14 import sys
15
16 class FTReceive:
17 """ Manager for file transfers going from MSN to Jabber. """
18
19 """
20 Plan of action for this class:
21 * Determine the FT support of the Jabber client.
22 * If we support a common protocol with them, create an
23 FTReceive_Invite object of that type. Either OOB (JEP0066) or SI(JEP0095)
24 * Call doInvite() and wait on the Deferred to send an affirmative or
25 negative to the MSN contact.
26 * The InvitationReceive sends IQ packets to the Jabber user to see if they
27 accept. If they do it creates an appropriate FTReceive_Transport to send
28 the file. Returning a Deferred for success or failure.
29
30 """
31
32 def __init__(self, session, senderJID, legacyftp):
33 self.session = session
34 self.toJID = self.session.jabberID + "/" + self.session.highestResource()
35 self.senderJID = senderJID
36 self.legacyftp = legacyftp
37 LogEvent(INFO)
38 self.checkSupport()
39
40 def checkSupport(self):
41 def discoDone(features):
42 c1 = features.count(disco.FT)
43 c2 = features.count(disco.S5)
44 c3 = features.count(disco.IBB)
45 c4 = features.count(disco.IQOOB)
46 #if c1 > 0 and c2 > 0:
47 # self.socksMode()
48 #elif c1 > 0 and c3 > 0:
49 # self.ibbMode()
50 if c4 > 0:
51 self.oobMode()
52 else:
53 self.messageOobMode()
54
55 def discoFail(ignored=None):
56 self.messageOobMode()
57
58 d = disco.DiscoRequest(self.session.pytrans, self.toJID).doDisco()
59 d.addCallback(discoDone)
60 d.addErrback(discoFail)
61
62 def socksMode(self):
63 LogEvent(ERROR)
64
65 def ibbMode(self):
66 LogEvent(ERROR)
67
68 def oobMode(self):
69 LogEvent(ERROR)
70
71 def messageOobMode(self):
72 def messageOobModeCB(ignored=None):
73 global oobSite
74 filename = str(random.randint(0, sys.maxint))
75 oobSite.resource.putFile(self, filename)
76 m = Element((None, "message"))
77 m.attributes["to"] = self.session.jabberID
78 m.attributes["from"] = self.senderJID
79 m.addElement("body").addContent(config.ftOOBRoot + "/" + filename)
80 x = m.addElement("x")
81 x.attributes["xmlns"] = disco.XOOB
82 x.addElement("url").addContent(config.ftOOBRoot + "/" + filename)
83 self.session.pytrans.send(m)
84
85 d = self.legacyftp.accept()
86 d.addCallback(messageOobModeCB)
87 d.addErrback(self.error)
88
89
90 def error(self, ignored=None):
91 # FIXME
92 LogEvent(WARN)
93
94
95
96
97 # Put the files up for OOB download
98
99 from twisted.web import server, resource, error
100 from twisted.internet import reactor
101
102 from debug import LogEvent, INFO, WARN, ERROR
103
104 class Connector:
105 def __init__(self, ftReceive, ftHttpPush):
106 self.ftReceive, self.ftHttpPush = ftReceive, ftHttpPush
107 self.ftReceive.legacyftp.writeTo(self)
108
109 def write(self, data):
110 self.ftHttpPush.write(data)
111
112 def close(self):
113 self.ftHttpPush.finish()
114
115 def error(self):
116 self.ftHttpPush.finish()
117 self.ftReceive.error()
118
119 class FileTransfer(resource.Resource):
120 def __init__(self):
121 self.isLeaf = True
122 self.files = {}
123
124 def putFile(self, file, filename):
125 self.files[filename] = file
126
127 def render_GET(self, request):
128 filename = request.path[1:] # Remove the leading /
129 if self.files.has_key(filename):
130 file = self.files[filename]
131 Connector(file, request)
132 del self.files[filename]
133 return server.NOT_DONE_YET
134 else:
135 page = error.NoResource(message="404 File Not Found")
136 return page.render(request)
137
138 oobSite = server.Site(FileTransfer())
139 reactor.listenTCP(int(config.ftOOBPort), oobSite)
140
141