Class Jabber::FileTransfer::Helper
In: lib/xmpp4r/bytestreams/helper/filetransfer.rb
Parent: Object
Message Presence XMPPStanza Iq XMPPElement X IqQuery Error Singleton IdGenerator Connection Client Component Client Comparable JID RuntimeError ErrorException AuthenticationFailure NoNameXmlnsRegistered SOCKS5Error REXML::Element Stream SOCKS5Bytestreams SOCKS5BytestreamsTarget SOCKS5BytestreamsInitiator XMPPElement StreamHost IqSiFileRange IqSiFile StreamHostUsed IqSi IqFeature XRosterItem RosterItem XMUCUserItem XMUCUserInvite IqPubSub Items Subscription IqPubSubOwner Item Event Feature Identity Item XDataField XDataReported XDataTitle XDataInstructions IqVcard SOCKS5BytestreamsServerStreamHost TCPSocket SOCKS5Socket IqQuery IqQueryBytestreams IqQueryVersion IqQueryRoster IqQueryRPC IqQueryMUCOwner IqQueryDiscoItems IqQueryDiscoInfo IBB IBBTarget IBBInitiator Responder SimpleResponder Iq IqCommand RosterXItem XRoster RosterX X XMUCUser XMUC XDelay XData XMLRPC::ParserWriterChooseMixin Client Server XMLRPC::ParseContentType XMLRPC::BasicServer XParent MUCClient SimpleMUCClient Base DigestMD5 Plain FileSource ServiceHelper NodeHelper CallbackList Callback Semaphore StreamParser SOCKS5BytestreamsPeer SOCKS5BytestreamsServer IBBQueueItem Responder Helper MUCBrowser Helper NodeBrowser Helper lib/xmpp4r/authenticationfailure.rb lib/xmpp4r/xmppstanza.rb lib/xmpp4r/callbacks.rb lib/xmpp4r/idgenerator.rb lib/xmpp4r/connection.rb lib/xmpp4r/iq.rb lib/xmpp4r/jid.rb lib/xmpp4r/errorexception.rb lib/xmpp4r/semaphore.rb lib/xmpp4r/client.rb lib/xmpp4r/stream.rb lib/xmpp4r/x.rb lib/xmpp4r/streamparser.rb lib/xmpp4r/error.rb lib/xmpp4r/component.rb lib/xmpp4r/query.rb lib/xmpp4r/xmppelement.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/server.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.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 XParent lib/xmpp4r/version/iq/version.rb lib/xmpp4r/version/helper/responder.rb lib/xmpp4r/version/helper/simpleresponder.rb Version lib/xmpp4r/command/iq/command.rb lib/xmpp4r/command/helper/responder.rb Command lib/xmpp4r/feature_negotiation/iq/feature.rb FeatureNegotiation lib/xmpp4r/roster/helper/roster.rb lib/xmpp4r/roster/iq/roster.rb lib/xmpp4r/roster/x/roster.rb Roster lib/xmpp4r/rpc/helper/server.rb lib/xmpp4r/rpc/helper/client.rb lib/xmpp4r/rpc/iq/rpc.rb RPC 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/iq/mucowner.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/pubsub/stanzas/subscription.rb lib/xmpp4r/pubsub/helper/servicehelper.rb lib/xmpp4r/pubsub/stanzas/item.rb lib/xmpp4r/pubsub/helper/nodehelper.rb lib/xmpp4r/pubsub/iq/pubsub.rb lib/xmpp4r/pubsub/stanzas/event.rb lib/xmpp4r/pubsub/helper/nodebrowser.rb lib/xmpp4r/pubsub/stanzas/items.rb PubSub lib/xmpp4r/httpbinding/client.rb HTTPBinding lib/xmpp4r/discovery/iq/discoinfo.rb lib/xmpp4r/discovery/iq/discoitems.rb Discovery lib/xmpp4r/dataforms/x/data.rb Dataforms lib/xmpp4r/vcard/helper/vcard.rb lib/xmpp4r/vcard/iq/vcard.rb Vcard Jabber dot/m_81_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 139
139:       def initialize(stream)
140:         @stream = stream
141:         @my_jid = nil
142:         @allow_bytestreams = true
143:         @allow_ibb = true
144: 
145:         @incoming_cbs = CallbackList.new
146: 
147:         @stream.add_iq_callback(150, self) { |iq|
148:           if iq.type == :set
149:             file = iq.first_element('si/file')
150:             field = nil
151:             iq.each_element('si/feature/x') { |e| field = e.field('stream-method') }
152: 
153:             if file and field
154:               @incoming_cbs.process(iq, file)
155:               true
156:             else
157:               false
158:             end
159:           else
160:             false
161:           end
162:         }
163:       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 186
186:       def accept(iq, offset=nil, length=nil)
187:         oldsi = iq.first_element('si')
188: 
189:         answer = iq.answer(false)
190:         answer.type = :result
191: 
192:         si = answer.add(Bytestreams::IqSi.new)
193:         if (offset or length) and oldsi.file.range
194:           si.add(Bytestreams::IqSiFile.new)
195:           si.file.add(Bytestreams::IqSiFileRange.new(offset, length))
196:         end
197:         si.add(FeatureNegotiation::IqFeature.new.import(oldsi.feature))
198:         si.feature.x.type = :submit
199:         stream_method = si.feature.x.field('stream-method')
200: 
201:         if stream_method.options.keys.include?(Bytestreams::NS_BYTESTREAMS) and @allow_bytestreams
202:           stream_method.values = [Bytestreams::NS_BYTESTREAMS]
203:           stream_method.options = []
204:           @stream.send(answer)
205: 
206:           Bytestreams::SOCKS5BytestreamsTarget.new(@stream, oldsi.id, iq.from, iq.to)
207:         elsif stream_method.options.keys.include?(Bytestreams::IBB::NS_IBB) and @allow_ibb
208:           stream_method.values = [Bytestreams::IBB::NS_IBB]
209:           stream_method.options = []
210:           @stream.send(answer)
211: 
212:           Bytestreams::IBBTarget.new(@stream, oldsi.id, iq.from, iq.to)
213:         else
214:           eanswer = iq.answer(false)
215:           eanswer.type = :error
216:           eanswer.add(Error.new('bad-request')).type = :cancel
217:           eanswer.error.add(REXML::Element.new('no-valid-streams')).add_namespace('http://jabber.org/protocol/si')
218:           @stream.send(eanswer)
219: 
220:           nil
221:         end
222:       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 172
172:       def add_incoming_callback(priority = 0, ref = nil, &block)
173:         @incoming_cbs.add(priority, ref, block)
174:       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 228
228:       def decline(iq)
229:         answer = iq.answer(false)
230:         answer.type = :error
231:         error = answer.add(Error.new('forbidden', 'Offer declined'))
232:         error.type = :cancel
233:         @stream.send(answer)
234:       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
from:[String] or [nil] Optional jid for components
result:[Bytestreams::SOCKS5BytestreamsInitiator] or [Bytestreams::IBBInitiator] or [nil]

[Source]

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

[Validate]