Class Jabber::FileTransfer::Helper
In: lib/xmpp4r/bytestreams/helper/filetransfer.rb
Parent: Object
XMLStanza Message Presence Iq REXML::Element X IqQuery Error StreamHost IqSiFileRange IqSiFile StreamHostUsed IqSi XRosterItem RosterItem IqFeature XMUCUserItem XMUCUserInvite XDataField XDataReported XDataTitle XDataInstructions Feature Identity Item IqVcard Singleton IdGenerator Connection Client Component Comparable JID RuntimeError AuthenticationFailure ErrorException SOCKS5Error Stream SOCKS5Bytestreams SOCKS5BytestreamsTarget SOCKS5BytestreamsInitiator SOCKS5BytestreamsServerStreamHost TCPSocket SOCKS5Socket IBB IBBTarget IBBInitiator IqQuery IqQueryBytestreams IqQueryVersion IqQueryRoster IqQueryDiscoItems IqQueryDiscoInfo Responder SimpleResponder X XRoster XMUCUser XMUC XDelay XData MUCClient SimpleMUCClient Base DigestMD5 Plain FileSource StreamParser SOCKS5BytestreamsPeer SOCKS5BytestreamsServer IBBQueueItem Helper MUCBrowser Helper Helper lib/xmpp4r/authenticationfailure.rb lib/xmpp4r/idgenerator.rb lib/xmpp4r/connection.rb lib/xmpp4r/iq.rb lib/xmpp4r/jid.rb lib/xmpp4r/xmlstanza.rb lib/xmpp4r/errorexception.rb lib/xmpp4r/stream.rb lib/xmpp4r/client.rb lib/xmpp4r/x.rb lib/xmpp4r/streamparser.rb lib/xmpp4r/error.rb lib/xmpp4r/component.rb lib/xmpp4r/query.rb lib/xmpp4r/message.rb lib/xmpp4r/presence.rb lib/xmpp4r/bytestreams/helper/ibb/initiator.rb lib/xmpp4r/bytestreams/iq/si.rb lib/xmpp4r/bytestreams/iq/bytestreams.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/socks5.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/initiator.rb lib/xmpp4r/bytestreams/helper/ibb/base.rb lib/xmpp4r/bytestreams/helper/ibb/target.rb Bytestreams lib/xmpp4r/version/iq/version.rb lib/xmpp4r/version/helper/responder.rb lib/xmpp4r/version/helper/simpleresponder.rb Version lib/xmpp4r/roster/helper/roster.rb lib/xmpp4r/roster/iq/roster.rb lib/xmpp4r/roster/x/roster.rb Roster lib/xmpp4r/feature_negotiation/iq/feature.rb FeatureNegotiation lib/xmpp4r/muc/x/muc.rb lib/xmpp4r/muc/helper/mucclient.rb lib/xmpp4r/muc/x/mucuseritem.rb lib/xmpp4r/muc/helper/mucbrowser.rb lib/xmpp4r/muc/x/mucuserinvite.rb lib/xmpp4r/muc/helper/simplemucclient.rb MUC lib/xmpp4r/sasl.rb SASL lib/xmpp4r/bytestreams/helper/filetransfer.rb TransferSource FileTransfer lib/xmpp4r/delay/x/delay.rb Delay lib/xmpp4r/dataforms/x/data.rb Dataforms lib/xmpp4r/discovery/iq/discoinfo.rb lib/xmpp4r/discovery/iq/discoitems.rb Discovery lib/xmpp4r/vcard/helper/vcard.rb lib/xmpp4r/vcard/iq/vcard.rb Vcard Jabber dot/m_60_0.png

The FileTransfer helper provides the ability to respond to incoming and to offer outgoing file-transfers.

Methods

Attributes

allow_bytestreams  [RW]  Set this to false if you don‘t want to use SOCKS5Bytestreams
allow_ibb  [RW]  Set this to false if you don‘t want to use IBB
my_jid  [RW]  Set this if you want to use this helper in a Component

Public Class methods

Create a new FileTransfer instance

[Source]

     # File lib/xmpp4r/bytestreams/helper/filetransfer.rb, line 136
136:       def initialize(stream)
137:         @stream = stream
138:         @my_jid = nil
139:         @allow_bytestreams = true
140:         @allow_ibb = true
141: 
142:         @incoming_cbs = CallbackList.new
143: 
144:         @stream.add_iq_callback(150, self) { |iq|
145:           if iq.type == :set
146:             file = iq.first_element('si/file')
147:             field = nil
148:             iq.each_element('si/feature/x') { |e| field = e.field('stream-method') }
149: 
150:             if file and field
151:               @incoming_cbs.process(iq, file)
152:               true
153:             else
154:               false
155:             end
156:           else
157:             false
158:           end
159:         }
160:       end

Public Instance methods

Accept an incoming file-transfer, to be used in a block given to add_incoming_callback

offset and length will be ignored if there is no ‘si/file/range’ in iq.

iq:[Iq] of file-transfer we want to accept
offset:[Fixnum] or [nil]
length:[Fixnum] or [nil]
result:[Bytestreams::SOCKS5BytestreamsTarget] or [Bytestreams::IBBTarget] or [nil] if no valid stream-method

[Source]

     # File lib/xmpp4r/bytestreams/helper/filetransfer.rb, line 183
183:       def accept(iq, offset=nil, length=nil)
184:         oldsi = iq.first_element('si')
185: 
186:         answer = iq.answer(false)
187:         answer.type = :result
188: 
189:         si = answer.add(Bytestreams::IqSi.new)
190:         if (offset or length) and oldsi.file.range
191:           si.add(Bytestreams::IqSiFile.new)
192:           si.file.add(Bytestreams::IqSiFileRange.new(offset, length))
193:         end
194:         si.add(FeatureNegotiation::IqFeature.new.import(oldsi.feature))
195:         si.feature.x.type = :submit
196:         stream_method = si.feature.x.field('stream-method')
197: 
198:         if stream_method.options.keys.include?(Bytestreams::IqQueryBytestreams::NS_BYTESTREAMS) and @allow_bytestreams
199:           stream_method.values = [Bytestreams::IqQueryBytestreams::NS_BYTESTREAMS]
200:           stream_method.options = []
201:           @stream.send(answer)
202: 
203:           Bytestreams::SOCKS5BytestreamsTarget.new(@stream, oldsi.id, iq.from, iq.to)
204:         elsif stream_method.options.keys.include?(Bytestreams::IBB::NS_IBB) and @allow_ibb
205:           stream_method.values = [Bytestreams::IBB::NS_IBB]
206:           stream_method.options = []
207:           @stream.send(answer)
208: 
209:           Bytestreams::IBBTarget.new(@stream, oldsi.id, iq.from, iq.to)
210:         else
211:           eanswer = iq.answer(false)
212:           eanswer.type = :error
213:           eanswer.add(Error.new('bad-request')).type = :cancel
214:           eanswer.error.add(REXML::Element.new('no-valid-streams')).add_namespace('http://jabber.org/protocol/si')
215:           @stream.send(eanswer)
216: 
217:           nil
218:         end
219:       end

Add a callback which will be invoked upon an incoming file-transfer

block takes two arguments:

You may then invoke accept or decline

[Source]

     # File lib/xmpp4r/bytestreams/helper/filetransfer.rb, line 169
169:       def add_incoming_callback(priority = 0, ref = nil, &block)
170:         @incoming_cbs.add(priority, ref, block)
171:       end

Decline an incoming file-transfer, to be used in a block given to add_incoming_callback

iq:[Iq] of file-transfer we want to decline

[Source]

     # File lib/xmpp4r/bytestreams/helper/filetransfer.rb, line 225
225:       def decline(iq)
226:         answer = iq.answer(false)
227:         answer.type = :error
228:         error = answer.add(Error.new('forbidden', 'Offer declined'))
229:         error.type = :cancel
230:         @stream.send(answer)
231:       end

Offer a file to somebody

Will wait for a response from the peer

The result is a stream which you can configure, or nil if the peer responded with an invalid stream-method.

May raise an ErrorException

jid:[JID] to send the file to
source:File-transfer source, implementing the FileSource interface
desc:[String] or [nil] Optional file description
result:[Bytestreams::SOCKS5BytestreamsInitiator] or [Bytestreams::IBBInitiator] or [nil]

[Source]

     # File lib/xmpp4r/bytestreams/helper/filetransfer.rb, line 246
246:       def offer(jid, source, desc=nil)
247:         session_id = Jabber::IdGenerator.instance.generate_id
248: 
249:         offered_methods = {}
250:         if @allow_bytestreams
251:           offered_methods[Bytestreams::IqQueryBytestreams::NS_BYTESTREAMS] = nil
252:         end
253:         if @allow_ibb
254:           offered_methods[Bytestreams::IBB::NS_IBB] = nil
255:         end
256: 
257:         iq = Iq::new(:set, jid)
258:         iq.from = @my_jid
259:         si = iq.add(Bytestreams::IqSi.new(session_id, Bytestreams::IqSi::PROFILE_FILETRANSFER, source.mime))
260: 
261:         file = si.add(Bytestreams::IqSiFile.new(source.filename, source.size))
262:         file.hash = source.md5
263:         file.date = source.date
264:         file.description = desc if desc
265:         file.add(Bytestreams::IqSiFileRange.new) if source.can_range?
266: 
267:         feature = si.add(REXML::Element.new('feature'))
268:         feature.add_namespace 'http://jabber.org/protocol/feature-neg'
269:         x = feature.add(Dataforms::XData.new(:form))
270:         stream_method_field = x.add(Dataforms::XDataField.new('stream-method', :list_single))
271:         stream_method_field.options = offered_methods
272: 
273:         begin
274:           stream_method = nil
275:           response = nil
276:           @stream.send_with_id(iq) { |r|
277:             response = r
278:             si = response.first_element('si')
279:             if response.type == :result and si and si.feature and si.feature.x
280:               stream_method = si.feature.x.field('stream-method').values.first
281: 
282:               if si.file and si.file.range
283:                 if source.can_range?
284:                   source.seek(si.file.range.offset) if si.file.range.offset
285:                   source.length = si.file.range.length if si.file.range.length
286:                 else
287:                   source.read(si.file.range.offset)
288:                 end
289:               end
290:             end
291:             true
292:           }
293:         rescue ErrorException => e
294:           if e.error.code == 403  # Declined
295:             return false
296:           else
297:             raise e
298:           end
299:         end
300: 
301:         if stream_method == Bytestreams::IqQueryBytestreams::NS_BYTESTREAMS and @allow_bytestreams
302:           Bytestreams::SOCKS5BytestreamsInitiator.new(@stream, session_id, @my_jid || @stream.jid, jid)
303:         elsif stream_method == Bytestreams::IBB::NS_IBB and @allow_ibb
304:           Bytestreams::IBBInitiator.new(@stream, session_id, @my_jid || @stream.jid, jid)
305:         else  # Target responded with a stream_method we didn't offer
306:           eanswer = response.answer
307:           eanswer.type = :error
308:           eanswer.add Error::new('bad-request')
309:           @stream.send(eanswer)
310:           nil
311:         end
312:       end

[Validate]