annotate plugins/plugin_xep_0065.py @ 178:bd24f2aed80c

Plugin XEP-0065: dest_file is now propertly closed after copy, and data dict in getProgress is not filled in case of file access error (file closed)
author Goffi <goffi@goffi.org>
date Mon, 16 Aug 2010 21:08:19 +0800
parents 55d3ef84f01f
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
goffi@necton2
parents:
diff changeset
1 #!/usr/bin/python
goffi@necton2
parents:
diff changeset
2 #-*- coding: utf-8 -*-
goffi@necton2
parents:
diff changeset
3 """
goffi@necton2
parents:
diff changeset
4 SAT plugin for managing xep-0065
goffi@necton2
parents:
diff changeset
5
goffi@necton2
parents:
diff changeset
6 Copyright (C)
goffi@necton2
parents:
diff changeset
7 2002-2004 Dave Smith (dizzyd@jabber.org)
goffi@necton2
parents:
diff changeset
8 2007-2008 Fabio Forno (xmpp:ff@jabber.bluendo.com)
57
a5b5fb5fc9fd updated README and copyright note
Goffi <goffi@goffi.org>
parents: 48
diff changeset
9 2009, 2010 Jérôme Poisson (goffi@goffi.org)
0
goffi@necton2
parents:
diff changeset
10
goffi@necton2
parents:
diff changeset
11 This program is free software: you can redistribute it and/or modify
goffi@necton2
parents:
diff changeset
12 it under the terms of the GNU General Public License as published by
goffi@necton2
parents:
diff changeset
13 the Free Software Foundation, either version 3 of the License, or
goffi@necton2
parents:
diff changeset
14 (at your option) any later version.
goffi@necton2
parents:
diff changeset
15
goffi@necton2
parents:
diff changeset
16 This program is distributed in the hope that it will be useful,
goffi@necton2
parents:
diff changeset
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
goffi@necton2
parents:
diff changeset
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
goffi@necton2
parents:
diff changeset
19 GNU General Public License for more details.
goffi@necton2
parents:
diff changeset
20
goffi@necton2
parents:
diff changeset
21 You should have received a copy of the GNU General Public License
goffi@necton2
parents:
diff changeset
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
goffi@necton2
parents:
diff changeset
23
goffi@necton2
parents:
diff changeset
24 --
goffi@necton2
parents:
diff changeset
25
goffi@necton2
parents:
diff changeset
26 This program is based on proxy65 (http://code.google.com/p/proxy65),
goffi@necton2
parents:
diff changeset
27 originaly written by David Smith and modified by Fabio Forno.
goffi@necton2
parents:
diff changeset
28 It is sublicensed under GPL v3 (or any later version) as allowed by the original
goffi@necton2
parents:
diff changeset
29 license.
goffi@necton2
parents:
diff changeset
30
goffi@necton2
parents:
diff changeset
31 --
goffi@necton2
parents:
diff changeset
32
goffi@necton2
parents:
diff changeset
33 Here is a copy of the original license:
goffi@necton2
parents:
diff changeset
34
goffi@necton2
parents:
diff changeset
35 Copyright (C)
goffi@necton2
parents:
diff changeset
36 2002-2004 Dave Smith (dizzyd@jabber.org)
goffi@necton2
parents:
diff changeset
37 2007-2008 Fabio Forno (xmpp:ff@jabber.bluendo.com)
goffi@necton2
parents:
diff changeset
38
goffi@necton2
parents:
diff changeset
39 Permission is hereby granted, free of charge, to any person obtaining a copy
goffi@necton2
parents:
diff changeset
40 of this software and associated documentation files (the "Software"), to deal
goffi@necton2
parents:
diff changeset
41 in the Software without restriction, including without limitation the rights
goffi@necton2
parents:
diff changeset
42 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
goffi@necton2
parents:
diff changeset
43 copies of the Software, and to permit persons to whom the Software is
goffi@necton2
parents:
diff changeset
44 furnished to do so, subject to the following conditions:
goffi@necton2
parents:
diff changeset
45
goffi@necton2
parents:
diff changeset
46 The above copyright notice and this permission notice shall be included in
goffi@necton2
parents:
diff changeset
47 all copies or substantial portions of the Software.
goffi@necton2
parents:
diff changeset
48
goffi@necton2
parents:
diff changeset
49 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
goffi@necton2
parents:
diff changeset
50 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
goffi@necton2
parents:
diff changeset
51 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
goffi@necton2
parents:
diff changeset
52 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
goffi@necton2
parents:
diff changeset
53 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
goffi@necton2
parents:
diff changeset
54 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
goffi@necton2
parents:
diff changeset
55 THE SOFTWARE.
goffi@necton2
parents:
diff changeset
56 """
goffi@necton2
parents:
diff changeset
57
goffi@necton2
parents:
diff changeset
58 from logging import debug, info, error
goffi@necton2
parents:
diff changeset
59 from twisted.internet import protocol, reactor
goffi@necton2
parents:
diff changeset
60 from twisted.protocols.basic import FileSender
goffi@necton2
parents:
diff changeset
61 from twisted.words.xish import domish
20
fc8c202cda87 refactoring: using xml params part IV (default values)
Goffi <goffi@goffi.org>
parents: 19
diff changeset
62 from twisted.web.client import getPage
0
goffi@necton2
parents:
diff changeset
63 import struct
20
fc8c202cda87 refactoring: using xml params part IV (default values)
Goffi <goffi@goffi.org>
parents: 19
diff changeset
64 import urllib
0
goffi@necton2
parents:
diff changeset
65 import hashlib, pdb
goffi@necton2
parents:
diff changeset
66
15
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
67 from zope.interface import implements
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
68
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
69 try:
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
70 from twisted.words.protocols.xmlstream import XMPPHandler
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
71 except ImportError:
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
72 from wokkel.subprotocols import XMPPHandler
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
73
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
74 from wokkel import disco, iwokkel
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
75
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
76 IQ_SET = '/iq[@type="set"]'
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
77 NS_BS = 'http://jabber.org/protocol/bytestreams'
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
78 BS_REQUEST = IQ_SET + '/query[@xmlns="' + NS_BS + '"]'
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
79
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
80
0
goffi@necton2
parents:
diff changeset
81
goffi@necton2
parents:
diff changeset
82 PLUGIN_INFO = {
goffi@necton2
parents:
diff changeset
83 "name": "XEP 0065 Plugin",
goffi@necton2
parents:
diff changeset
84 "import_name": "XEP_0065",
goffi@necton2
parents:
diff changeset
85 "type": "XEP",
48
4392f1fdb064 plugins improvement
Goffi <goffi@goffi.org>
parents: 38
diff changeset
86 "protocols": ["XEP-0065"],
0
goffi@necton2
parents:
diff changeset
87 "main": "XEP_0065",
64
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
88 "handler": "yes",
69
86f1f7f6d332 i18n first draft
Goffi <goffi@goffi.org>
parents: 64
diff changeset
89 "description": _("""Implementation of SOCKS5 Bytestreams""")
0
goffi@necton2
parents:
diff changeset
90 }
goffi@necton2
parents:
diff changeset
91
goffi@necton2
parents:
diff changeset
92 STATE_INITIAL = 0
goffi@necton2
parents:
diff changeset
93 STATE_AUTH = 1
goffi@necton2
parents:
diff changeset
94 STATE_REQUEST = 2
goffi@necton2
parents:
diff changeset
95 STATE_READY = 3
goffi@necton2
parents:
diff changeset
96 STATE_AUTH_USERPASS = 4
goffi@necton2
parents:
diff changeset
97 STATE_TARGET_INITIAL = 5
goffi@necton2
parents:
diff changeset
98 STATE_TARGET_AUTH = 6
goffi@necton2
parents:
diff changeset
99 STATE_TARGET_REQUEST = 7
goffi@necton2
parents:
diff changeset
100 STATE_TARGET_READY = 8
goffi@necton2
parents:
diff changeset
101 STATE_LAST = 9
goffi@necton2
parents:
diff changeset
102
goffi@necton2
parents:
diff changeset
103 STATE_CONNECT_PENDING = STATE_LAST + 1
goffi@necton2
parents:
diff changeset
104
goffi@necton2
parents:
diff changeset
105 SOCKS5_VER = 0x05
goffi@necton2
parents:
diff changeset
106
goffi@necton2
parents:
diff changeset
107 ADDR_IPV4 = 0x01
goffi@necton2
parents:
diff changeset
108 ADDR_DOMAINNAME = 0x03
goffi@necton2
parents:
diff changeset
109 ADDR_IPV6 = 0x04
goffi@necton2
parents:
diff changeset
110
goffi@necton2
parents:
diff changeset
111 CMD_CONNECT = 0x01
goffi@necton2
parents:
diff changeset
112 CMD_BIND = 0x02
goffi@necton2
parents:
diff changeset
113 CMD_UDPASSOC = 0x03
goffi@necton2
parents:
diff changeset
114
goffi@necton2
parents:
diff changeset
115 AUTHMECH_ANON = 0x00
goffi@necton2
parents:
diff changeset
116 AUTHMECH_USERPASS = 0x02
goffi@necton2
parents:
diff changeset
117 AUTHMECH_INVALID = 0xFF
goffi@necton2
parents:
diff changeset
118
goffi@necton2
parents:
diff changeset
119 REPLY_SUCCESS = 0x00
goffi@necton2
parents:
diff changeset
120 REPLY_GENERAL_FAILUR = 0x01
goffi@necton2
parents:
diff changeset
121 REPLY_CONN_NOT_ALLOWED = 0x02
goffi@necton2
parents:
diff changeset
122 REPLY_NETWORK_UNREACHABLE = 0x03
goffi@necton2
parents:
diff changeset
123 REPLY_HOST_UNREACHABLE = 0x04
goffi@necton2
parents:
diff changeset
124 REPLY_CONN_REFUSED = 0x05
goffi@necton2
parents:
diff changeset
125 REPLY_TTL_EXPIRED = 0x06
goffi@necton2
parents:
diff changeset
126 REPLY_CMD_NOT_SUPPORTED = 0x07
goffi@necton2
parents:
diff changeset
127 REPLY_ADDR_NOT_SUPPORTED = 0x08
goffi@necton2
parents:
diff changeset
128
goffi@necton2
parents:
diff changeset
129
goffi@necton2
parents:
diff changeset
130
goffi@necton2
parents:
diff changeset
131
goffi@necton2
parents:
diff changeset
132
goffi@necton2
parents:
diff changeset
133 class SOCKSv5(protocol.Protocol, FileSender):
goffi@necton2
parents:
diff changeset
134 def __init__(self):
69
86f1f7f6d332 i18n first draft
Goffi <goffi@goffi.org>
parents: 64
diff changeset
135 debug(_("Protocol init"))
0
goffi@necton2
parents:
diff changeset
136 self.state = STATE_INITIAL
goffi@necton2
parents:
diff changeset
137 self.buf = ""
goffi@necton2
parents:
diff changeset
138 self.supportedAuthMechs = [ AUTHMECH_ANON ]
goffi@necton2
parents:
diff changeset
139 self.supportedAddrs = [ ADDR_DOMAINNAME ]
goffi@necton2
parents:
diff changeset
140 self.enabledCommands = [ CMD_CONNECT ]
goffi@necton2
parents:
diff changeset
141 self.peersock = None
goffi@necton2
parents:
diff changeset
142 self.addressType = 0
goffi@necton2
parents:
diff changeset
143 self.requestType = 0
goffi@necton2
parents:
diff changeset
144 self.activeConns = {}
goffi@necton2
parents:
diff changeset
145 self.pendingConns = {}
goffi@necton2
parents:
diff changeset
146 self.transfered = 0 #nb of bytes already copied
goffi@necton2
parents:
diff changeset
147
goffi@necton2
parents:
diff changeset
148 def _startNegotiation(self):
goffi@necton2
parents:
diff changeset
149 debug("_startNegotiation")
goffi@necton2
parents:
diff changeset
150 self.state = STATE_TARGET_AUTH
goffi@necton2
parents:
diff changeset
151 self.transport.write(struct.pack('!3B', SOCKS5_VER, 1, AUTHMECH_ANON))
goffi@necton2
parents:
diff changeset
152
goffi@necton2
parents:
diff changeset
153 def _parseNegotiation(self):
goffi@necton2
parents:
diff changeset
154 debug("_parseNegotiation")
goffi@necton2
parents:
diff changeset
155 try:
goffi@necton2
parents:
diff changeset
156 # Parse out data
goffi@necton2
parents:
diff changeset
157 ver, nmethod = struct.unpack('!BB', self.buf[:2])
goffi@necton2
parents:
diff changeset
158 methods = struct.unpack('%dB' % nmethod, self.buf[2:nmethod+2])
goffi@necton2
parents:
diff changeset
159
goffi@necton2
parents:
diff changeset
160 # Ensure version is correct
goffi@necton2
parents:
diff changeset
161 if ver != 5:
goffi@necton2
parents:
diff changeset
162 self.transport.write(struct.pack('!BB', SOCKS5_VER, AUTHMECH_INVALID))
goffi@necton2
parents:
diff changeset
163 self.transport.loseConnection()
goffi@necton2
parents:
diff changeset
164 return
goffi@necton2
parents:
diff changeset
165
goffi@necton2
parents:
diff changeset
166 # Trim off front of the buffer
goffi@necton2
parents:
diff changeset
167 self.buf = self.buf[nmethod+2:]
goffi@necton2
parents:
diff changeset
168
goffi@necton2
parents:
diff changeset
169 # Check for supported auth mechs
goffi@necton2
parents:
diff changeset
170 for m in self.supportedAuthMechs:
goffi@necton2
parents:
diff changeset
171 if m in methods:
goffi@necton2
parents:
diff changeset
172 # Update internal state, according to selected method
goffi@necton2
parents:
diff changeset
173 if m == AUTHMECH_ANON:
goffi@necton2
parents:
diff changeset
174 self.state = STATE_REQUEST
goffi@necton2
parents:
diff changeset
175 elif m == AUTHMECH_USERPASS:
goffi@necton2
parents:
diff changeset
176 self.state = STATE_AUTH_USERPASS
goffi@necton2
parents:
diff changeset
177 # Complete negotiation w/ this method
goffi@necton2
parents:
diff changeset
178 self.transport.write(struct.pack('!BB', SOCKS5_VER, m))
goffi@necton2
parents:
diff changeset
179 return
goffi@necton2
parents:
diff changeset
180
goffi@necton2
parents:
diff changeset
181 # No supported mechs found, notify client and close the connection
goffi@necton2
parents:
diff changeset
182 self.transport.write(struct.pack('!BB', SOCKS5_VER, AUTHMECH_INVALID))
goffi@necton2
parents:
diff changeset
183 self.transport.loseConnection()
goffi@necton2
parents:
diff changeset
184 except struct.error:
goffi@necton2
parents:
diff changeset
185 pass
goffi@necton2
parents:
diff changeset
186
goffi@necton2
parents:
diff changeset
187 def _parseUserPass(self):
goffi@necton2
parents:
diff changeset
188 debug("_parseUserPass")
goffi@necton2
parents:
diff changeset
189 try:
goffi@necton2
parents:
diff changeset
190 # Parse out data
goffi@necton2
parents:
diff changeset
191 ver, ulen = struct.unpack('BB', self.buf[:2])
goffi@necton2
parents:
diff changeset
192 uname, = struct.unpack('%ds' % ulen, self.buf[2:ulen + 2])
goffi@necton2
parents:
diff changeset
193 plen, = struct.unpack('B', self.buf[ulen + 2])
goffi@necton2
parents:
diff changeset
194 password, = struct.unpack('%ds' % plen, self.buf[ulen + 3:ulen + 3 + plen])
goffi@necton2
parents:
diff changeset
195 # Trim off fron of the buffer
goffi@necton2
parents:
diff changeset
196 self.buf = self.buf[3 + ulen + plen:]
goffi@necton2
parents:
diff changeset
197 # Fire event to authenticate user
goffi@necton2
parents:
diff changeset
198 if self.authenticateUserPass(uname, password):
goffi@necton2
parents:
diff changeset
199 # Signal success
goffi@necton2
parents:
diff changeset
200 self.state = STATE_REQUEST
goffi@necton2
parents:
diff changeset
201 self.transport.write(struct.pack('!BB', SOCKS5_VER, 0x00))
goffi@necton2
parents:
diff changeset
202 else:
goffi@necton2
parents:
diff changeset
203 # Signal failure
goffi@necton2
parents:
diff changeset
204 self.transport.write(struct.pack('!BB', SOCKS5_VER, 0x01))
goffi@necton2
parents:
diff changeset
205 self.transport.loseConnection()
goffi@necton2
parents:
diff changeset
206 except struct.error:
goffi@necton2
parents:
diff changeset
207 pass
goffi@necton2
parents:
diff changeset
208
goffi@necton2
parents:
diff changeset
209 def sendErrorReply(self, errorcode):
goffi@necton2
parents:
diff changeset
210 debug("sendErrorReply")
goffi@necton2
parents:
diff changeset
211 # Any other address types are not supported
goffi@necton2
parents:
diff changeset
212 result = struct.pack('!BBBBIH', SOCKS5_VER, errorcode, 0, 1, 0, 0)
goffi@necton2
parents:
diff changeset
213 self.transport.write(result)
goffi@necton2
parents:
diff changeset
214 self.transport.loseConnection()
goffi@necton2
parents:
diff changeset
215
goffi@necton2
parents:
diff changeset
216 def addConnection(self, address, connection):
69
86f1f7f6d332 i18n first draft
Goffi <goffi@goffi.org>
parents: 64
diff changeset
217 info(_("Adding connection: %(address)s, %(connection)s") % {'address':address, 'connection':connection})
0
goffi@necton2
parents:
diff changeset
218 olist = self.pendingConns.get(address, [])
goffi@necton2
parents:
diff changeset
219 if len(olist) <= 1:
goffi@necton2
parents:
diff changeset
220 olist.append(connection)
goffi@necton2
parents:
diff changeset
221 self.pendingConns[address] = olist
goffi@necton2
parents:
diff changeset
222 return True
goffi@necton2
parents:
diff changeset
223 else:
goffi@necton2
parents:
diff changeset
224 return False
goffi@necton2
parents:
diff changeset
225
goffi@necton2
parents:
diff changeset
226 def removePendingConnection(self, address, connection):
goffi@necton2
parents:
diff changeset
227 olist = self.pendingConns[address]
goffi@necton2
parents:
diff changeset
228 if len(olist) == 1:
goffi@necton2
parents:
diff changeset
229 del self.pendingConns[address]
goffi@necton2
parents:
diff changeset
230 else:
goffi@necton2
parents:
diff changeset
231 olist.remove(connection)
goffi@necton2
parents:
diff changeset
232 self.pendingConns[address] = olist
goffi@necton2
parents:
diff changeset
233
goffi@necton2
parents:
diff changeset
234 def removeActiveConnection(self, address):
goffi@necton2
parents:
diff changeset
235 del self.activeConns[address]
goffi@necton2
parents:
diff changeset
236
goffi@necton2
parents:
diff changeset
237 def _parseRequest(self):
goffi@necton2
parents:
diff changeset
238 debug("_parseRequest")
goffi@necton2
parents:
diff changeset
239 try:
goffi@necton2
parents:
diff changeset
240 # Parse out data and trim buffer accordingly
goffi@necton2
parents:
diff changeset
241 ver, cmd, rsvd, self.addressType = struct.unpack('!BBBB', self.buf[:4])
goffi@necton2
parents:
diff changeset
242
goffi@necton2
parents:
diff changeset
243 # Ensure we actually support the requested address type
goffi@necton2
parents:
diff changeset
244 if self.addressType not in self.supportedAddrs:
goffi@necton2
parents:
diff changeset
245 self.sendErrorReply(REPLY_ADDR_NOT_SUPPORTED)
goffi@necton2
parents:
diff changeset
246 return
goffi@necton2
parents:
diff changeset
247
goffi@necton2
parents:
diff changeset
248 # Deal with addresses
goffi@necton2
parents:
diff changeset
249 if self.addressType == ADDR_IPV4:
goffi@necton2
parents:
diff changeset
250 addr, port = struct.unpack('!IH', self.buf[4:10])
goffi@necton2
parents:
diff changeset
251 self.buf = self.buf[10:]
goffi@necton2
parents:
diff changeset
252 elif self.addressType == ADDR_DOMAINNAME:
goffi@necton2
parents:
diff changeset
253 nlen = ord(self.buf[4])
goffi@necton2
parents:
diff changeset
254 addr, port = struct.unpack('!%dsH' % nlen, self.buf[5:])
goffi@necton2
parents:
diff changeset
255 self.buf = self.buf[7 + len(addr):]
goffi@necton2
parents:
diff changeset
256 else:
goffi@necton2
parents:
diff changeset
257 # Any other address types are not supported
goffi@necton2
parents:
diff changeset
258 self.sendErrorReply(REPLY_ADDR_NOT_SUPPORTED)
goffi@necton2
parents:
diff changeset
259 return
goffi@necton2
parents:
diff changeset
260
goffi@necton2
parents:
diff changeset
261 # Ensure command is supported
goffi@necton2
parents:
diff changeset
262 if cmd not in self.enabledCommands:
goffi@necton2
parents:
diff changeset
263 # Send a not supported error
goffi@necton2
parents:
diff changeset
264 self.sendErrorReply(REPLY_CMD_NOT_SUPPORTED)
goffi@necton2
parents:
diff changeset
265 return
goffi@necton2
parents:
diff changeset
266
goffi@necton2
parents:
diff changeset
267 # Process the command
goffi@necton2
parents:
diff changeset
268 if cmd == CMD_CONNECT:
goffi@necton2
parents:
diff changeset
269 self.connectRequested(addr, port)
goffi@necton2
parents:
diff changeset
270 elif cmd == CMD_BIND:
goffi@necton2
parents:
diff changeset
271 self.bindRequested(addr, port)
goffi@necton2
parents:
diff changeset
272 else:
goffi@necton2
parents:
diff changeset
273 # Any other command is not supported
goffi@necton2
parents:
diff changeset
274 self.sendErrorReply(REPLY_CMD_NOT_SUPPORTED)
goffi@necton2
parents:
diff changeset
275
goffi@necton2
parents:
diff changeset
276 except struct.error, why:
goffi@necton2
parents:
diff changeset
277 return None
goffi@necton2
parents:
diff changeset
278
goffi@necton2
parents:
diff changeset
279 def _makeRequest(self):
goffi@necton2
parents:
diff changeset
280 debug("_makeRequest")
goffi@necton2
parents:
diff changeset
281 self.state = STATE_TARGET_REQUEST
goffi@necton2
parents:
diff changeset
282 sha1 = hashlib.sha1(self.sid + self.initiator_jid + self.target_jid).hexdigest()
goffi@necton2
parents:
diff changeset
283 request = struct.pack('!5B%dsH' % len(sha1), SOCKS5_VER, CMD_CONNECT, 0, ADDR_DOMAINNAME, len(sha1), sha1, 0)
goffi@necton2
parents:
diff changeset
284 self.transport.write(request)
goffi@necton2
parents:
diff changeset
285
goffi@necton2
parents:
diff changeset
286 def _parseRequestReply(self):
goffi@necton2
parents:
diff changeset
287 debug("_parseRequestReply")
goffi@necton2
parents:
diff changeset
288 try:
goffi@necton2
parents:
diff changeset
289 ver, rep, rsvd, self.addressType = struct.unpack('!BBBB', self.buf[:4])
goffi@necton2
parents:
diff changeset
290 # Ensure we actually support the requested address type
goffi@necton2
parents:
diff changeset
291 if self.addressType not in self.supportedAddrs:
goffi@necton2
parents:
diff changeset
292 self.sendErrorReply(REPLY_ADDR_NOT_SUPPORTED)
goffi@necton2
parents:
diff changeset
293 return
goffi@necton2
parents:
diff changeset
294
goffi@necton2
parents:
diff changeset
295 # Deal with addresses
goffi@necton2
parents:
diff changeset
296 if self.addressType == ADDR_IPV4:
goffi@necton2
parents:
diff changeset
297 addr, port = struct.unpack('!IH', self.buf[4:10])
goffi@necton2
parents:
diff changeset
298 self.buf = self.buf[10:]
goffi@necton2
parents:
diff changeset
299 elif self.addressType == ADDR_DOMAINNAME:
goffi@necton2
parents:
diff changeset
300 nlen = ord(self.buf[4])
goffi@necton2
parents:
diff changeset
301 addr, port = struct.unpack('!%dsH' % nlen, self.buf[5:])
goffi@necton2
parents:
diff changeset
302 self.buf = self.buf[7 + len(addr):]
goffi@necton2
parents:
diff changeset
303 else:
goffi@necton2
parents:
diff changeset
304 # Any other address types are not supported
goffi@necton2
parents:
diff changeset
305 self.sendErrorReply(REPLY_ADDR_NOT_SUPPORTED)
goffi@necton2
parents:
diff changeset
306 return
goffi@necton2
parents:
diff changeset
307
goffi@necton2
parents:
diff changeset
308 # Ensure reply is OK
goffi@necton2
parents:
diff changeset
309 if rep != REPLY_SUCCESS:
goffi@necton2
parents:
diff changeset
310 self.loseConnection()
goffi@necton2
parents:
diff changeset
311 return
goffi@necton2
parents:
diff changeset
312
69
86f1f7f6d332 i18n first draft
Goffi <goffi@goffi.org>
parents: 64
diff changeset
313 debug(_("Saving file in %s."), self.data["dest_path"])
0
goffi@necton2
parents:
diff changeset
314 self.dest_file = open(self.data["dest_path"], 'w')
goffi@necton2
parents:
diff changeset
315 self.state = STATE_TARGET_READY
64
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
316 self.activateCB(self.target_jid, self.initiator_jid, self.sid, self.IQ_id, self.xmlstream)
0
goffi@necton2
parents:
diff changeset
317
goffi@necton2
parents:
diff changeset
318
goffi@necton2
parents:
diff changeset
319 except struct.error, why:
goffi@necton2
parents:
diff changeset
320 return None
goffi@necton2
parents:
diff changeset
321
goffi@necton2
parents:
diff changeset
322 def connectionMade(self):
goffi@necton2
parents:
diff changeset
323 debug("connectionMade (mode = %s)" % self.mode)
goffi@necton2
parents:
diff changeset
324 self.host.registerProgressCB(self.transfert_id, self.getProgress)
goffi@necton2
parents:
diff changeset
325
goffi@necton2
parents:
diff changeset
326 if self.mode == "target":
goffi@necton2
parents:
diff changeset
327 self.state = STATE_TARGET_INITIAL
goffi@necton2
parents:
diff changeset
328 self._startNegotiation()
goffi@necton2
parents:
diff changeset
329
goffi@necton2
parents:
diff changeset
330 def connectRequested(self, addr, port):
69
86f1f7f6d332 i18n first draft
Goffi <goffi@goffi.org>
parents: 64
diff changeset
331 debug("connectRequested")
0
goffi@necton2
parents:
diff changeset
332 # Check for special connect to the namespace -- this signifies that the client
goffi@necton2
parents:
diff changeset
333 # is just checking to ensure it can connect to the streamhost
goffi@necton2
parents:
diff changeset
334 if addr == "http://jabber.org/protocol/bytestreams":
goffi@necton2
parents:
diff changeset
335 self.connectCompleted(addr, 0)
goffi@necton2
parents:
diff changeset
336 self.transport.loseConnection()
goffi@necton2
parents:
diff changeset
337 return
goffi@necton2
parents:
diff changeset
338
goffi@necton2
parents:
diff changeset
339 # Save addr, for cleanup
goffi@necton2
parents:
diff changeset
340 self.addr = addr
goffi@necton2
parents:
diff changeset
341
goffi@necton2
parents:
diff changeset
342 # Check to see if the requested address is already
goffi@necton2
parents:
diff changeset
343 # activated -- send an error if so
goffi@necton2
parents:
diff changeset
344 if addr in self.activeConns:
goffi@necton2
parents:
diff changeset
345 self.sendErrorReply(socks5.REPLY_CONN_NOT_ALLOWED)
goffi@necton2
parents:
diff changeset
346 return
goffi@necton2
parents:
diff changeset
347
goffi@necton2
parents:
diff changeset
348 # Add this address to the pending connections
goffi@necton2
parents:
diff changeset
349 if self.addConnection(addr, self):
goffi@necton2
parents:
diff changeset
350 self.connectCompleted(addr, 0)
goffi@necton2
parents:
diff changeset
351 self.transport.stopReading()
goffi@necton2
parents:
diff changeset
352 else:
goffi@necton2
parents:
diff changeset
353 self.sendErrorReply(socks5.REPLY_CONN_REFUSED)
goffi@necton2
parents:
diff changeset
354
goffi@necton2
parents:
diff changeset
355 def getProgress(self, data):
goffi@necton2
parents:
diff changeset
356 """Fill data with position of current transfert"""
goffi@necton2
parents:
diff changeset
357 try:
goffi@necton2
parents:
diff changeset
358 data["position"] = str(self.dest_file.tell())
178
bd24f2aed80c Plugin XEP-0065: dest_file is now propertly closed after copy, and data dict in getProgress is not filled in case of file access error (file closed)
Goffi <goffi@goffi.org>
parents: 127
diff changeset
359 data["size"] = self.filesize
0
goffi@necton2
parents:
diff changeset
360 except (ValueError, AttributeError):
178
bd24f2aed80c Plugin XEP-0065: dest_file is now propertly closed after copy, and data dict in getProgress is not filled in case of file access error (file closed)
Goffi <goffi@goffi.org>
parents: 127
diff changeset
361 pass
0
goffi@necton2
parents:
diff changeset
362
goffi@necton2
parents:
diff changeset
363 def fileTransfered(self, d):
69
86f1f7f6d332 i18n first draft
Goffi <goffi@goffi.org>
parents: 64
diff changeset
364 info(_("File transfer completed, closing connection"))
0
goffi@necton2
parents:
diff changeset
365 self.transport.loseConnection()
178
bd24f2aed80c Plugin XEP-0065: dest_file is now propertly closed after copy, and data dict in getProgress is not filled in case of file access error (file closed)
Goffi <goffi@goffi.org>
parents: 127
diff changeset
366 try:
bd24f2aed80c Plugin XEP-0065: dest_file is now propertly closed after copy, and data dict in getProgress is not filled in case of file access error (file closed)
Goffi <goffi@goffi.org>
parents: 127
diff changeset
367 self.dest_file.close()
bd24f2aed80c Plugin XEP-0065: dest_file is now propertly closed after copy, and data dict in getProgress is not filled in case of file access error (file closed)
Goffi <goffi@goffi.org>
parents: 127
diff changeset
368 except:
bd24f2aed80c Plugin XEP-0065: dest_file is now propertly closed after copy, and data dict in getProgress is not filled in case of file access error (file closed)
Goffi <goffi@goffi.org>
parents: 127
diff changeset
369 pass
0
goffi@necton2
parents:
diff changeset
370
goffi@necton2
parents:
diff changeset
371 def updateTransfered(self, data):
goffi@necton2
parents:
diff changeset
372 self.transfered+=len(data)
goffi@necton2
parents:
diff changeset
373 return data
goffi@necton2
parents:
diff changeset
374
goffi@necton2
parents:
diff changeset
375 def connectCompleted(self, remotehost, remoteport):
goffi@necton2
parents:
diff changeset
376 debug("connectCompleted")
goffi@necton2
parents:
diff changeset
377 if self.addressType == ADDR_IPV4:
goffi@necton2
parents:
diff changeset
378 result = struct.pack('!BBBBIH', SOCKS5_VER, REPLY_SUCCESS, 0, 1, remotehost, remoteport)
goffi@necton2
parents:
diff changeset
379 elif self.addressType == ADDR_DOMAINNAME:
goffi@necton2
parents:
diff changeset
380 result = struct.pack('!BBBBB%dsH' % len(remotehost), SOCKS5_VER, REPLY_SUCCESS, 0,
goffi@necton2
parents:
diff changeset
381 ADDR_DOMAINNAME, len(remotehost), remotehost, remoteport)
goffi@necton2
parents:
diff changeset
382 self.transport.write(result)
goffi@necton2
parents:
diff changeset
383 self.state = STATE_READY
goffi@necton2
parents:
diff changeset
384 self.dest_file=open(self.filepath)
goffi@necton2
parents:
diff changeset
385 d=self.beginFileTransfer(self.dest_file, self.transport, self.updateTransfered)
goffi@necton2
parents:
diff changeset
386 d.addCallback(self.fileTransfered)
goffi@necton2
parents:
diff changeset
387
goffi@necton2
parents:
diff changeset
388 def bindRequested(self, addr, port):
goffi@necton2
parents:
diff changeset
389 pass
goffi@necton2
parents:
diff changeset
390
goffi@necton2
parents:
diff changeset
391 def authenticateUserPass(self, user, passwd):
goffi@necton2
parents:
diff changeset
392 debug("User/pass: %s/%s", user, passwd)
goffi@necton2
parents:
diff changeset
393 return True
goffi@necton2
parents:
diff changeset
394
goffi@necton2
parents:
diff changeset
395 def dataReceived(self, buf):
goffi@necton2
parents:
diff changeset
396 if self.state == STATE_TARGET_READY:
goffi@necton2
parents:
diff changeset
397 self.dest_file.write(buf)
goffi@necton2
parents:
diff changeset
398 self.transfered+=len(buf)
goffi@necton2
parents:
diff changeset
399 return
goffi@necton2
parents:
diff changeset
400
goffi@necton2
parents:
diff changeset
401 self.buf = self.buf + buf
goffi@necton2
parents:
diff changeset
402 if self.state == STATE_INITIAL:
goffi@necton2
parents:
diff changeset
403 self._parseNegotiation()
goffi@necton2
parents:
diff changeset
404 if self.state == STATE_AUTH_USERPASS:
goffi@necton2
parents:
diff changeset
405 self._parseUserPass()
goffi@necton2
parents:
diff changeset
406 if self.state == STATE_REQUEST:
goffi@necton2
parents:
diff changeset
407 self._parseRequest()
goffi@necton2
parents:
diff changeset
408 if self.state == STATE_TARGET_AUTH:
goffi@necton2
parents:
diff changeset
409 ver, method = struct.unpack('!BB', buf)
goffi@necton2
parents:
diff changeset
410 self.buf = self.buf[2:]
goffi@necton2
parents:
diff changeset
411 if ver!=SOCKS5_VER or method!=AUTHMECH_ANON:
goffi@necton2
parents:
diff changeset
412 self.transport.loseConnection()
goffi@necton2
parents:
diff changeset
413 else:
goffi@necton2
parents:
diff changeset
414 self._makeRequest()
goffi@necton2
parents:
diff changeset
415 if self.state == STATE_TARGET_REQUEST:
goffi@necton2
parents:
diff changeset
416 self._parseRequestReply()
goffi@necton2
parents:
diff changeset
417
goffi@necton2
parents:
diff changeset
418
goffi@necton2
parents:
diff changeset
419 def clientConnectionLost(self, reason):
goffi@necton2
parents:
diff changeset
420 debug("clientConnectionLost")
goffi@necton2
parents:
diff changeset
421 self.transport.loseConnection()
goffi@necton2
parents:
diff changeset
422
goffi@necton2
parents:
diff changeset
423 def connectionLost(self, reason):
goffi@necton2
parents:
diff changeset
424 debug("connectionLost")
goffi@necton2
parents:
diff changeset
425 self.host.removeProgressCB(self.transfert_id)
goffi@necton2
parents:
diff changeset
426 if self.state == STATE_CONNECT_PENDING:
goffi@necton2
parents:
diff changeset
427 self.removePendingConnection(self.addr, self)
goffi@necton2
parents:
diff changeset
428 else:
goffi@necton2
parents:
diff changeset
429 self.transport.unregisterProducer()
goffi@necton2
parents:
diff changeset
430 if self.peersock != None:
goffi@necton2
parents:
diff changeset
431 self.peersock.peersock = None
goffi@necton2
parents:
diff changeset
432 self.peersock.transport.unregisterProducer()
goffi@necton2
parents:
diff changeset
433 self.peersock = None
goffi@necton2
parents:
diff changeset
434 self.removeActiveConnection(self.addr)
goffi@necton2
parents:
diff changeset
435
goffi@necton2
parents:
diff changeset
436 class Socks5ServerFactory(protocol.ServerFactory):
goffi@necton2
parents:
diff changeset
437 protocol = SOCKSv5
goffi@necton2
parents:
diff changeset
438 protocol.mode = "initiator" #FIXME: Q&D way, fix it
goffi@necton2
parents:
diff changeset
439
goffi@necton2
parents:
diff changeset
440
goffi@necton2
parents:
diff changeset
441 def startedConnecting(self, connector):
69
86f1f7f6d332 i18n first draft
Goffi <goffi@goffi.org>
parents: 64
diff changeset
442 debug (_("Socks 5 server connection started"))
0
goffi@necton2
parents:
diff changeset
443
goffi@necton2
parents:
diff changeset
444 def clientConnectionLost(self, connector, reason):
69
86f1f7f6d332 i18n first draft
Goffi <goffi@goffi.org>
parents: 64
diff changeset
445 debug (_("Socks 5 server connection lost (reason: %s)"), reason)
0
goffi@necton2
parents:
diff changeset
446
goffi@necton2
parents:
diff changeset
447 class Socks5ClientFactory(protocol.ClientFactory):
goffi@necton2
parents:
diff changeset
448 protocol = SOCKSv5
goffi@necton2
parents:
diff changeset
449 protocol.mode = "target" #FIXME: Q&D way, fix it
goffi@necton2
parents:
diff changeset
450
goffi@necton2
parents:
diff changeset
451 def startedConnecting(self, connector):
69
86f1f7f6d332 i18n first draft
Goffi <goffi@goffi.org>
parents: 64
diff changeset
452 debug (_("Socks 5 client connection started"))
0
goffi@necton2
parents:
diff changeset
453
goffi@necton2
parents:
diff changeset
454 def clientConnectionLost(self, connector, reason):
69
86f1f7f6d332 i18n first draft
Goffi <goffi@goffi.org>
parents: 64
diff changeset
455 debug (_("Socks 5 client connection lost (reason: %s)"), reason)
0
goffi@necton2
parents:
diff changeset
456
goffi@necton2
parents:
diff changeset
457
64
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
458 class XEP_0065():
15
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
459
19
f2a745ca0fbc refactoring: using xml params part III (parameters import)
Goffi <goffi@goffi.org>
parents: 15
diff changeset
460 params = """
f2a745ca0fbc refactoring: using xml params part III (parameters import)
Goffi <goffi@goffi.org>
parents: 15
diff changeset
461 <params>
60
9764e027ecc0 SàT: multi-profile parameters, first draft
Goffi <goffi@goffi.org>
parents: 57
diff changeset
462 <general>
19
f2a745ca0fbc refactoring: using xml params part III (parameters import)
Goffi <goffi@goffi.org>
parents: 15
diff changeset
463 <category name="File Transfert">
20
fc8c202cda87 refactoring: using xml params part IV (default values)
Goffi <goffi@goffi.org>
parents: 19
diff changeset
464 <param name="IP" value='0.0.0.0' default_cb='yes' type="string" />
19
f2a745ca0fbc refactoring: using xml params part III (parameters import)
Goffi <goffi@goffi.org>
parents: 15
diff changeset
465 <param name="Port" value="28915" type="string" />
f2a745ca0fbc refactoring: using xml params part III (parameters import)
Goffi <goffi@goffi.org>
parents: 15
diff changeset
466 </category>
60
9764e027ecc0 SàT: multi-profile parameters, first draft
Goffi <goffi@goffi.org>
parents: 57
diff changeset
467 </general>
19
f2a745ca0fbc refactoring: using xml params part III (parameters import)
Goffi <goffi@goffi.org>
parents: 15
diff changeset
468 </params>
f2a745ca0fbc refactoring: using xml params part III (parameters import)
Goffi <goffi@goffi.org>
parents: 15
diff changeset
469 """
20
fc8c202cda87 refactoring: using xml params part IV (default values)
Goffi <goffi@goffi.org>
parents: 19
diff changeset
470
0
goffi@necton2
parents:
diff changeset
471 def __init__(self, host):
69
86f1f7f6d332 i18n first draft
Goffi <goffi@goffi.org>
parents: 64
diff changeset
472 info(_("Plugin XEP_0065 initialization"))
0
goffi@necton2
parents:
diff changeset
473 self.host = host
69
86f1f7f6d332 i18n first draft
Goffi <goffi@goffi.org>
parents: 64
diff changeset
474 debug(_("registering"))
0
goffi@necton2
parents:
diff changeset
475 self.server_factory = Socks5ServerFactory()
goffi@necton2
parents:
diff changeset
476 self.server_factory.protocol.host = self.host #needed for progress CB
goffi@necton2
parents:
diff changeset
477 self.client_factory = Socks5ClientFactory()
21
633c5ed65701 parameters: new button type (not finished)
Goffi <goffi@goffi.org>
parents: 20
diff changeset
478
633c5ed65701 parameters: new button type (not finished)
Goffi <goffi@goffi.org>
parents: 20
diff changeset
479 #parameters
38
3e24753b9e0b Fixed parameters loading/saving
Goffi <goffi@goffi.org>
parents: 22
diff changeset
480 host.memory.importParams(XEP_0065.params)
20
fc8c202cda87 refactoring: using xml params part IV (default values)
Goffi <goffi@goffi.org>
parents: 19
diff changeset
481 host.memory.setDefault("IP", "File Transfert", self.getExternalIP)
21
633c5ed65701 parameters: new button type (not finished)
Goffi <goffi@goffi.org>
parents: 20
diff changeset
482
22
bb72c29f3432 added action cb mechanism for buttons. Tested with a temporary new user registration button.
Goffi <goffi@goffi.org>
parents: 21
diff changeset
483 port = int(self.host.memory.getParamA("Port", "File Transfert"))
69
86f1f7f6d332 i18n first draft
Goffi <goffi@goffi.org>
parents: 64
diff changeset
484 info(_("Launching Socks5 Stream server on port %d"), port)
0
goffi@necton2
parents:
diff changeset
485 reactor.listenTCP(port, self.server_factory)
15
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
486
72
f271fff3a713 MUC implementation: first draft
Goffi <goffi@goffi.org>
parents: 69
diff changeset
487 def getHandler(self, profile):
64
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
488 return XEP_0065_handler(self)
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
489
20
fc8c202cda87 refactoring: using xml params part IV (default values)
Goffi <goffi@goffi.org>
parents: 19
diff changeset
490 def getExternalIP(self):
fc8c202cda87 refactoring: using xml params part IV (default values)
Goffi <goffi@goffi.org>
parents: 19
diff changeset
491 """Return IP visible from outside, by asking to a website"""
fc8c202cda87 refactoring: using xml params part IV (default values)
Goffi <goffi@goffi.org>
parents: 19
diff changeset
492 return getPage("http://www.goffi.org/sat_tools/get_ip.php")
0
goffi@necton2
parents:
diff changeset
493
goffi@necton2
parents:
diff changeset
494 def setData(self, data, id):
goffi@necton2
parents:
diff changeset
495 self.data = data
goffi@necton2
parents:
diff changeset
496 self.transfert_id = id
goffi@necton2
parents:
diff changeset
497
goffi@necton2
parents:
diff changeset
498 def sendFile(self, id, filepath, size):
goffi@necton2
parents:
diff changeset
499 #lauching socks5 initiator
69
86f1f7f6d332 i18n first draft
Goffi <goffi@goffi.org>
parents: 64
diff changeset
500 debug(_("Launching socks5 initiator"))
0
goffi@necton2
parents:
diff changeset
501 self.server_factory.protocol.mode = "initiator"
goffi@necton2
parents:
diff changeset
502 self.server_factory.protocol.filepath = filepath
goffi@necton2
parents:
diff changeset
503 self.server_factory.protocol.filesize = size
goffi@necton2
parents:
diff changeset
504 self.server_factory.protocol.transfert_id = id
goffi@necton2
parents:
diff changeset
505
64
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
506 def getFile(self, iq, profile_key='@DEFAULT@'):
0
goffi@necton2
parents:
diff changeset
507 """Get file using byte stream"""
64
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
508 client = self.host.getClient(profile_key)
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
509 assert(client)
15
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
510 iq.handled = True
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
511 SI_elem = iq.firstChildElement()
218ec9984fa5 wokkel integration part III + memory saved again
Goffi <goffi@goffi.org>
parents: 9
diff changeset
512 IQ_id = iq['id']
0
goffi@necton2
parents:
diff changeset
513 for element in SI_elem.elements():
goffi@necton2
parents:
diff changeset
514 if element.name == "streamhost":
127
55d3ef84f01f Primitivus: mouse wheel changed to 'up' and 'down' key press
Goffi <goffi@goffi.org>
parents: 72
diff changeset
515 info (_("Stream proposed: host=[%(host)s] port=[%(port)s]") % {'host':element['host'], 'port':element['port']})
0
goffi@necton2
parents:
diff changeset
516 factory = self.client_factory
goffi@necton2
parents:
diff changeset
517 self.server_factory.protocol.mode = "target"
goffi@necton2
parents:
diff changeset
518 factory.protocol.host = self.host #needed for progress CB
64
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
519 factory.protocol.xmlstream = client.xmlstream
0
goffi@necton2
parents:
diff changeset
520 factory.protocol.data = self.data
goffi@necton2
parents:
diff changeset
521 factory.protocol.transfert_id = self.transfert_id
goffi@necton2
parents:
diff changeset
522 factory.protocol.filesize = self.data["size"]
goffi@necton2
parents:
diff changeset
523 factory.protocol.sid = SI_elem['sid']
goffi@necton2
parents:
diff changeset
524 factory.protocol.initiator_jid = element['jid']
64
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
525 factory.protocol.target_jid = client.jid.full()
0
goffi@necton2
parents:
diff changeset
526 factory.protocol.IQ_id = IQ_id
goffi@necton2
parents:
diff changeset
527 factory.protocol.activateCB = self.activateStream
goffi@necton2
parents:
diff changeset
528 reactor.connectTCP(element['host'], int(element['port']), factory)
goffi@necton2
parents:
diff changeset
529
64
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
530 def activateStream(self, from_jid, to_jid, sid, IQ_id, xmlstream):
69
86f1f7f6d332 i18n first draft
Goffi <goffi@goffi.org>
parents: 64
diff changeset
531 debug(_("activating stream"))
0
goffi@necton2
parents:
diff changeset
532 result = domish.Element(('', 'iq'))
goffi@necton2
parents:
diff changeset
533 result['type'] = 'result'
goffi@necton2
parents:
diff changeset
534 result['id'] = IQ_id
goffi@necton2
parents:
diff changeset
535 result['from'] = from_jid
goffi@necton2
parents:
diff changeset
536 result['to'] = to_jid
goffi@necton2
parents:
diff changeset
537 query = result.addElement('query', 'http://jabber.org/protocol/bytestreams')
goffi@necton2
parents:
diff changeset
538 query['sid'] = sid
goffi@necton2
parents:
diff changeset
539 streamhost = query.addElement('streamhost-used')
goffi@necton2
parents:
diff changeset
540 streamhost['jid'] = to_jid #FIXME: use real streamhost
64
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
541 xmlstream.send(result)
0
goffi@necton2
parents:
diff changeset
542
64
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
543 class XEP_0065_handler(XMPPHandler):
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
544 implements(iwokkel.IDisco)
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
545
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
546 def __init__(self, plugin_parent):
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
547 self.plugin_parent = plugin_parent
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
548 self.host = plugin_parent.host
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
549
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
550 def connectionInitialized(self):
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
551 self.xmlstream.addObserver(BS_REQUEST, self.plugin_parent.getFile)
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
552
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
553
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
554 def getDiscoInfo(self, requestor, target, nodeIdentifier=''):
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
555 return [disco.DiscoFeature(NS_BS)]
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
556
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
557 def getDiscoItems(self, requestor, target, nodeIdentifier=''):
d46f849664aa SàT: multi-profile, plugins updated
Goffi <goffi@goffi.org>
parents: 60
diff changeset
558 return []