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