xmpp4r 0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. data/COPYING +340 -0
  2. data/ChangeLog +28 -0
  3. data/LICENSE +59 -0
  4. data/README +20 -0
  5. data/Rakefile +103 -0
  6. data/UPDATING +40 -0
  7. data/data/doc/xmpp4r/examples/advanced/adventure/README +57 -0
  8. data/data/doc/xmpp4r/examples/advanced/adventure/adventure.rb +23 -0
  9. data/data/doc/xmpp4r/examples/advanced/adventure/adventuremuc.rb +136 -0
  10. data/data/doc/xmpp4r/examples/advanced/adventure/cube.xml +15 -0
  11. data/data/doc/xmpp4r/examples/advanced/adventure/tower.xml +69 -0
  12. data/data/doc/xmpp4r/examples/advanced/adventure/world.rb +425 -0
  13. data/data/doc/xmpp4r/examples/advanced/fileserve.conf +11 -0
  14. data/data/doc/xmpp4r/examples/advanced/fileserve.rb +344 -0
  15. data/data/doc/xmpp4r/examples/advanced/getonline.rb +56 -0
  16. data/data/doc/xmpp4r/examples/advanced/gtkmucclient.rb +315 -0
  17. data/data/doc/xmpp4r/examples/advanced/migrate.rb +89 -0
  18. data/data/doc/xmpp4r/examples/advanced/minimuc.rb +266 -0
  19. data/data/doc/xmpp4r/examples/advanced/recvfile.rb +83 -0
  20. data/data/doc/xmpp4r/examples/advanced/rosterdiscovery.rb +130 -0
  21. data/data/doc/xmpp4r/examples/advanced/sendfile.conf +10 -0
  22. data/data/doc/xmpp4r/examples/advanced/sendfile.rb +72 -0
  23. data/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr.rb +51 -0
  24. data/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr_jabber.rb +43 -0
  25. data/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr_test.rb +10 -0
  26. data/data/doc/xmpp4r/examples/advanced/versionpoll.rb +90 -0
  27. data/data/doc/xmpp4r/examples/advanced/xmpping.rb +134 -0
  28. data/data/doc/xmpp4r/examples/advanced/xmppingrc.sample +9 -0
  29. data/data/doc/xmpp4r/examples/basic/change_password.rb +41 -0
  30. data/data/doc/xmpp4r/examples/basic/client.rb +68 -0
  31. data/data/doc/xmpp4r/examples/basic/component.rb +11 -0
  32. data/data/doc/xmpp4r/examples/basic/echo_nonthreaded.rb +32 -0
  33. data/data/doc/xmpp4r/examples/basic/echo_threaded.rb +32 -0
  34. data/data/doc/xmpp4r/examples/basic/jabbersend.rb +41 -0
  35. data/data/doc/xmpp4r/examples/basic/mass_sender.rb +67 -0
  36. data/data/doc/xmpp4r/examples/basic/mucinfo.rb +39 -0
  37. data/data/doc/xmpp4r/examples/basic/mucsimplebot.rb +83 -0
  38. data/data/doc/xmpp4r/examples/basic/register.rb +25 -0
  39. data/data/doc/xmpp4r/examples/basic/remove_registration.rb +18 -0
  40. data/data/doc/xmpp4r/examples/basic/roster.rb +42 -0
  41. data/data/doc/xmpp4r/examples/basic/rosterprint.rb +50 -0
  42. data/data/doc/xmpp4r/examples/basic/rosterrename.rb +34 -0
  43. data/data/doc/xmpp4r/examples/basic/rosterwatch.rb +172 -0
  44. data/data/doc/xmpp4r/examples/basic/send_vcard.rb +68 -0
  45. data/data/doc/xmpp4r/examples/basic/versionbot.rb +75 -0
  46. data/data/doc/xmpp4r/examples/buggy/jabber2jabber/jabber2jabber.rb +18 -0
  47. data/data/doc/xmpp4r/examples/buggy/miniedgarr_cgi.rb +192 -0
  48. data/data/doc/xmpp4r/examples/buggy/miniedgarr_watch.rb +82 -0
  49. data/lib/callbacks.rb +122 -0
  50. data/lib/xmpp4r/authenticationfailure.rb +13 -0
  51. data/lib/xmpp4r/bytestreams/helper/filetransfer.rb +315 -0
  52. data/lib/xmpp4r/bytestreams/helper/ibb/base.rb +256 -0
  53. data/lib/xmpp4r/bytestreams/helper/ibb/initiator.rb +30 -0
  54. data/lib/xmpp4r/bytestreams/helper/ibb/target.rb +46 -0
  55. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb +151 -0
  56. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/initiator.rb +85 -0
  57. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb +178 -0
  58. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/socks5.rb +56 -0
  59. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb +61 -0
  60. data/lib/xmpp4r/bytestreams/iq/bytestreams.rb +177 -0
  61. data/lib/xmpp4r/bytestreams/iq/si.rb +221 -0
  62. data/lib/xmpp4r/bytestreams.rb +11 -0
  63. data/lib/xmpp4r/client.rb +249 -0
  64. data/lib/xmpp4r/component.rb +103 -0
  65. data/lib/xmpp4r/connection.rb +166 -0
  66. data/lib/xmpp4r/dataforms/x/data.rb +248 -0
  67. data/lib/xmpp4r/dataforms.rb +1 -0
  68. data/lib/xmpp4r/debuglog.rb +34 -0
  69. data/lib/xmpp4r/delay/x/delay.rb +100 -0
  70. data/lib/xmpp4r/delay.rb +1 -0
  71. data/lib/xmpp4r/discovery/iq/discoinfo.rb +225 -0
  72. data/lib/xmpp4r/discovery/iq/discoitems.rb +162 -0
  73. data/lib/xmpp4r/discovery.rb +2 -0
  74. data/lib/xmpp4r/error.rb +230 -0
  75. data/lib/xmpp4r/errorexception.rb +32 -0
  76. data/lib/xmpp4r/feature_negotiation/iq/feature.rb +42 -0
  77. data/lib/xmpp4r/feature_negotiation.rb +1 -0
  78. data/lib/xmpp4r/idgenerator.rb +37 -0
  79. data/lib/xmpp4r/iq.rb +229 -0
  80. data/lib/xmpp4r/jid.rb +167 -0
  81. data/lib/xmpp4r/message.rb +171 -0
  82. data/lib/xmpp4r/muc/helper/mucbrowser.rb +107 -0
  83. data/lib/xmpp4r/muc/helper/mucclient.rb +382 -0
  84. data/lib/xmpp4r/muc/helper/simplemucclient.rb +222 -0
  85. data/lib/xmpp4r/muc/x/muc.rb +98 -0
  86. data/lib/xmpp4r/muc/x/mucuserinvite.rb +58 -0
  87. data/lib/xmpp4r/muc/x/mucuseritem.rb +148 -0
  88. data/lib/xmpp4r/muc.rb +6 -0
  89. data/lib/xmpp4r/presence.rb +255 -0
  90. data/lib/xmpp4r/query.rb +43 -0
  91. data/lib/xmpp4r/rexmladdons.rb +826 -0
  92. data/lib/xmpp4r/roster/helper/roster.rb +514 -0
  93. data/lib/xmpp4r/roster/iq/roster.rb +244 -0
  94. data/lib/xmpp4r/roster/x/roster.rb +155 -0
  95. data/lib/xmpp4r/roster.rb +4 -0
  96. data/lib/xmpp4r/sasl.rb +167 -0
  97. data/lib/xmpp4r/stream.rb +543 -0
  98. data/lib/xmpp4r/streamparser.rb +77 -0
  99. data/lib/xmpp4r/vcard/helper/vcard.rb +86 -0
  100. data/lib/xmpp4r/vcard/iq/vcard.rb +102 -0
  101. data/lib/xmpp4r/vcard.rb +3 -0
  102. data/lib/xmpp4r/version/helper/responder.rb +71 -0
  103. data/lib/xmpp4r/version/helper/simpleresponder.rb +44 -0
  104. data/lib/xmpp4r/version/iq/version.rb +118 -0
  105. data/lib/xmpp4r/version.rb +3 -0
  106. data/lib/xmpp4r/x.rb +43 -0
  107. data/lib/xmpp4r/xmlstanza.rb +174 -0
  108. data/lib/xmpp4r/xmpp4r.rb +16 -0
  109. data/lib/xmpp4r.rb +122 -0
  110. data/setup.rb +1360 -0
  111. data/test/bytestreams/tc_ibb.rb +186 -0
  112. data/test/bytestreams/tc_socks5bytestreams.rb +57 -0
  113. data/test/delay/tc_xdelay.rb +51 -0
  114. data/test/lib/clienttester.rb +110 -0
  115. data/test/muc/tc_muc_mucclient.rb +569 -0
  116. data/test/muc/tc_muc_simplemucclient.rb +72 -0
  117. data/test/roster/.tc_helper.rb.swp +0 -0
  118. data/test/roster/tc_helper.rb +389 -0
  119. data/test/roster/tc_iqqueryroster.rb +140 -0
  120. data/test/roster/tc_xroster.rb +70 -0
  121. data/test/tc_callbacks.rb +128 -0
  122. data/test/tc_class_names.rb +129 -0
  123. data/test/tc_client.rb +30 -0
  124. data/test/tc_error.rb +103 -0
  125. data/test/tc_idgenerator.rb +30 -0
  126. data/test/tc_iq.rb +109 -0
  127. data/test/tc_iqquery.rb +31 -0
  128. data/test/tc_jid.rb +202 -0
  129. data/test/tc_message.rb +114 -0
  130. data/test/tc_presence.rb +148 -0
  131. data/test/tc_stream.rb +182 -0
  132. data/test/tc_streamError.rb +87 -0
  133. data/test/tc_streamSend.rb +59 -0
  134. data/test/tc_streamThreaded.rb +168 -0
  135. data/test/tc_xmlstanza.rb +76 -0
  136. data/test/ts_xmpp4r.rb +34 -0
  137. data/test/vcard/tc_iqvcard.rb +52 -0
  138. data/test/version/tc_helper.rb +46 -0
  139. data/test/version/tc_iqqueryversion.rb +96 -0
  140. data/tools/doctoweb.bash +30 -0
  141. data/tools/gen_requires.bash +10 -0
  142. metadata +232 -0
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This script can be used to migrate from one jabber account to another
4
+
5
+ $:.unshift '../lib'
6
+
7
+ require 'optparse'
8
+ require 'xmpp4r'
9
+ include Jabber
10
+
11
+ jidfrom = JID::new('lucas@linux.ensimag.fr/JabberMigrate')
12
+ pwfrom = 'z'
13
+ jidto = JID::new('lucas@nussbaum.fr/JabberMigrate')
14
+ pwto = 'z'
15
+
16
+ BOTHOLD = "Hi, you are subscribed to my presence. I just changed my JID. The new one is #{jidto.strip}. You might want to update your roster. Thank you, and sorry for the inconvenience !"
17
+ BOTHNEW = "Hi, you are subscribed to the presence of my previous JID : #{jidfrom.strip}. I just changed my JID, and this is the new one. You might want to update your roster. Thank you, and sorry for the inconvenience !"
18
+
19
+ clfrom = Client::new(jidfrom, false)
20
+ clfrom.connect
21
+ clfrom.auth(pwfrom)
22
+ clto = Client::new(jidto, false)
23
+ clto.connect
24
+ clto.auth(pwto)
25
+ #clfrom.send(Presence::new)
26
+ #clto.send(Presence::new)
27
+ clfrom.send(Iq::new_rosterget)
28
+ exit = false
29
+ clfrom.add_iq_callback { |i|
30
+ if i.type == :result and i.queryns == 'jabber:iq:roster'
31
+ i.query.each_element do |e|
32
+ e.text = ''
33
+ jid = e.attribute('jid')
34
+ name = e.attribute('name')
35
+ subscription = e.attribute('subscription')
36
+ ask = e.attribute('ask')
37
+ jid &&= jid.value
38
+ next if jid =~ /@(icq|msn|aim|yahoo).blop.info/
39
+ # next if jid !~ /lucas@im.apinc.org/
40
+ puts "Processing #{e.to_s}"
41
+ # Jabber::debug = true
42
+ name &&= name.value
43
+ subscription &&= subscription.value
44
+ ask &&= ask.value
45
+ puts subscription
46
+ case subscription
47
+ when 'from'
48
+ # il veut me voir, je veux pas le voir.
49
+ # envoi unsubscribed
50
+ clfrom.send(Presence::new.set_to(jid).set_type(:unsubscribed))
51
+ # envoi message d'info OLD & NEW
52
+ clfrom.send(Message::new(jid, BOTHOLD).set_type(:chat))
53
+ clto.send(Message::new(jid, BOTHNEW).set_type(:chat))
54
+ when 'to'
55
+ # je veux le voir, il veut pas me voir
56
+ # envoi unsubscribe
57
+ clfrom.send(Presence::new.set_to(jid).set_type(:unsubscribe))
58
+ # envoi subscribe avec message
59
+ pres = Presence::new.set_to(jid).set_type(:subscribe)
60
+ pres.add(Element::new('status').add_text("Hi, I was previously subscribed to your presence with my JID #{jidfrom.strip}. Can I re-subscribe to your presence ? Thank you."))
61
+ clto.send(pres)
62
+ when 'both'
63
+ # envoi unsubscribed
64
+ clfrom.send(Presence::new.set_to(jid).set_type(:unsubscribed))
65
+ # envoi unsubscribe
66
+ clfrom.send(Presence::new.set_to(jid).set_type(:unsubscribe))
67
+ # update roster
68
+ iq = Iq::new_rosterset
69
+ e.delete_attribute('ask')
70
+ e.delete_attribute('subscription')
71
+ iq.query.add_element(e)
72
+ clto.send(iq)
73
+ # envoi message d'info OLD & NEW
74
+ clfrom.send(Message::new(jid, BOTHOLD).set_type(:chat))
75
+ pres = Presence::new.set_to(jid).set_type(:subscribe)
76
+ pres.add(Element::new('status').add_text("Hi, I was previously subscribed to your presence with my JID #{jidfrom.strip}. Can I re-subscribe to your presence ? Thank you."))
77
+ clto.send(pres)
78
+ clto.send(Message::new(jid, BOTHNEW).set_type(:chat))
79
+ end
80
+ end
81
+ end
82
+ }
83
+ while not exit
84
+ clfrom.process
85
+ clto.process
86
+ end
87
+ clfrom.close
88
+ clto.close
89
+
@@ -0,0 +1,266 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $:.unshift '../../../../../lib'
4
+
5
+ require 'xmpp4r'
6
+ require 'xmpp4r/iq/query/discoinfo'
7
+ require 'xmpp4r/iq/query/discoitems'
8
+ require 'xmpp4r/x/muc'
9
+
10
+
11
+ #Jabber::debug = true
12
+
13
+ class Room
14
+ class RoomException < Exception
15
+ attr_reader :error
16
+ def initialize(error, msg)
17
+ @error = Jabber::Error.new(error, msg)
18
+ end
19
+ end
20
+
21
+ def initialize(stream, name)
22
+ @users = {} # nick => jid
23
+ @stream = stream
24
+ @name = name
25
+ end
26
+
27
+ def num_users
28
+ @users.size
29
+ end
30
+
31
+ def each_user(&block)
32
+ @users.each { |n,j| yield(n, j) }
33
+ end
34
+
35
+ def handle_message(msg)
36
+ origin = msg.from
37
+ msg.from = nil
38
+ @users.each { |nick,jid|
39
+ if jid == origin
40
+ msg.from = Jabber::JID::new(@name.node, @name.domain, nick)
41
+ end
42
+ }
43
+ unless msg.from.nil?
44
+ broadcast(msg)
45
+ end
46
+
47
+ true
48
+ end
49
+
50
+ def handle_presence(pres)
51
+ reason = nil
52
+
53
+ # Check if nick already registered
54
+ @users.each { |nick,jid|
55
+ if pres.from != jid && pres.to.resource == nick
56
+ puts "#{pres.from} tried to use already active #{pres.to}"
57
+ raise RoomException.new('conflict', "Nick already used")
58
+ end
59
+ }
60
+ # New user?
61
+ unless @users.has_key?(pres.to.resource)
62
+ # Check nick length
63
+ if pres.to.resource.size < 1
64
+ puts "#{pres.from} tried to use empty nick"
65
+ raise RoomException.new('not-acceptable', "Nick must contain characters")
66
+ end
67
+
68
+ # Push user-list
69
+ userinfo = Jabber::Presence.import(pres)
70
+ userinfo.to = pres.from
71
+ userinfo.add(Jabber::XMucUser.new).add(Jabber::XMucUserItem.new(:none, :participant))
72
+ print "Sending all users for #{pres.to} to #{pres.from}:"
73
+ @users.each { |nick,jid|
74
+ userinfo.from = Jabber::JID::new(@name.node, @name.domain, nick)
75
+ print " #{nick} (#{jid})"
76
+ @stream.send(userinfo)
77
+ }
78
+ puts " Ok"
79
+
80
+ # Add the new user
81
+ puts "Adding #{pres.from} as #{pres.to}"
82
+ @users[pres.to.resource] = pres.from
83
+
84
+ send_message("#{pres.to.resource} joins #{@name.node}")
85
+ reason = "#{pres.to.resource} joins #{@name.node}"
86
+ end
87
+
88
+ # Remove dead rats
89
+ if pres.type == :error || pres.type == :unavailable
90
+ was_nick = nil
91
+ @users.delete_if { |nick,jid|
92
+ was_nick = nick
93
+ jid == pres.from
94
+ }
95
+ unless was_nick.nil?
96
+ send_message("#{was_nick} has left #{@name.node}")
97
+ reason = "#{was_nick} has left #{@name.node}"
98
+ end
99
+ end
100
+
101
+ # Advertise users presence to all
102
+ puts "Advertising user to all"
103
+ x = Jabber::XMucUserItem.new(:none, :participant, pres.from)
104
+ x.reason = reason
105
+ pres.add(Jabber::XMucUser.new).add(x)
106
+ pres.from = pres.to
107
+ broadcast(pres)
108
+ end
109
+
110
+ def send_message(body)
111
+ msg = Jabber::Message::new
112
+ msg.from = Jabber::JID::new(@name.node, @name.domain, "")
113
+ msg.type = :groupchat
114
+ msg.body = body
115
+ broadcast(msg)
116
+ end
117
+
118
+ def broadcast(stanza)
119
+ x = stanza.class::import(stanza)
120
+ @users.each { |nick,jid|
121
+ x.to = jid
122
+ @stream.send(x)
123
+ }
124
+ end
125
+ end
126
+
127
+ class MUC
128
+ def initialize(jid, secret, addr, port=5347)
129
+ @rooms = {}
130
+
131
+ @component = Jabber::Component::new(jid, addr, port)
132
+ @component.connect
133
+ @component.auth(secret)
134
+
135
+ @component.add_iq_callback { |iq|
136
+ handle_iq(iq)
137
+ }
138
+ @component.add_presence_callback { |pres|
139
+ handle_presence(pres)
140
+ }
141
+ @component.add_message_callback { |msg|
142
+ handle_message(msg)
143
+ }
144
+ end
145
+
146
+ def handle_iq(iq)
147
+ puts "#{iq.from} #{iq.queryns} to #{iq.to}"
148
+ if iq.query.kind_of?(Jabber::IqQueryDiscoInfo)
149
+ handle_disco_info(iq)
150
+ true
151
+ elsif iq.query.kind_of?(Jabber::IqQueryDiscoItems)
152
+ handle_disco_items(iq)
153
+ true
154
+ else
155
+ false
156
+ end
157
+ end
158
+
159
+ def handle_presence(pres)
160
+ room = nil
161
+ @rooms.each { |name,r|
162
+ room = r if name == pres.to.strip
163
+ }
164
+
165
+ if room.nil? && pres.type.nil? && (pres.to.node.to_s != '')
166
+ room = Room.new(@component, pres.to.strip)
167
+ @rooms[pres.to.strip] = room
168
+ elsif room.nil? && pres.type != :error
169
+ pres.to, pres.from = pres.from, pres.to
170
+ pres.type = :error
171
+ pres.add(Jabber::Error.new('item-not-found'))
172
+ @component.send(pres)
173
+ return(true)
174
+ end
175
+
176
+ begin
177
+ room.handle_presence(pres)
178
+ rescue Room::RoomException => e
179
+ pres.to, pres.from = pres.from, pres.to
180
+ pres.type = :error
181
+ pres.add(e.error)
182
+ @component.send(pres)
183
+ return(true)
184
+ end
185
+ return(false)
186
+ end
187
+
188
+ def handle_message(msg)
189
+ puts "Message from #{msg.from} to #{msg.to} (#{msg.type}): #{msg.body.inspect}"
190
+ return if msg.type == :error
191
+
192
+ room = @rooms[msg.to]
193
+ unless room.nil?
194
+ room.handle_message(msg)
195
+ else
196
+ msg.to, msg.from = msg.from, msg.to
197
+ msg.type = :error
198
+ msg.add(Jabber::Error.new('item-not-found', 'The chatroom you are trying to reach is currently not available.'))
199
+ @component.send(msg)
200
+ end
201
+ end
202
+
203
+ def handle_disco_info(iq)
204
+ if (iq.type == :get)
205
+ iq.type = :result
206
+ iq.query = Jabber::IqQueryDiscoInfo.new
207
+ if iq.to.node == nil
208
+ iq.query.add(Jabber::DiscoIdentity.new('conference', 'Minimal Multi-User Chat', 'text'))
209
+ else
210
+ room = @rooms[iq.to]
211
+ if room.nil?
212
+ iq.type = :error
213
+ iq.add_element(Jabber::Error.new('item-not-found'))
214
+ else
215
+ iq.query.add(Jabber::DiscoIdentity.new('conference', "#{iq.to.node} (#{room.num_users})", 'text'))
216
+ end
217
+ end
218
+ [Jabber::IqQueryDiscoInfo.new.namespace,
219
+ Jabber::IqQueryDiscoItems.new.namespace,
220
+ Jabber::XMuc.new.namespace,
221
+ Jabber::XMucUser.new.namespace].each { |ns|
222
+ iq.query.add(Jabber::DiscoFeature.new(ns))
223
+ }
224
+ else
225
+ iq.type = :error
226
+ iq.add_element(Jabber::Error.new('bad-request'))
227
+ end
228
+ iq.to, iq.from = iq.from, iq.to
229
+ @component.send(iq)
230
+ end
231
+
232
+ def handle_disco_items(iq)
233
+ if (iq.type == :get)
234
+ iq.type = :result
235
+ if iq.to.node == nil
236
+ @rooms.each { |name,room|
237
+ iq.query.add(Jabber::DiscoItem::new(Jabber::JID::new(name, @component.jid.domain), name))
238
+ }
239
+ elsif iq.to.resource == nil
240
+ room = @rooms[iq.to.strip]
241
+ unless room.nil?
242
+ room.each_user { |nick,jid|
243
+ iq.query.add(Jabber::DiscoItem::new(jid, nick))
244
+ }
245
+ else
246
+ iq.type = :error
247
+ iq.add_element(Jabber::Error.new('item-not-found'))
248
+ end
249
+ end
250
+ else
251
+ iq.type = :error
252
+ iq.add_element(Jabber::Error.new('bad-request'))
253
+ end
254
+ iq.to, iq.from = iq.from, iq.to
255
+ @component.send(iq)
256
+ end
257
+ end
258
+
259
+ if ARGV.size != 3
260
+ puts "Syntax: ./minimuc.rb <JID> <Password> <Host>"
261
+ puts "Example: ./minimuc.rb conference.xmpp4r.mil minimuc localhost"
262
+ exit
263
+ end
264
+
265
+ muc = MUC::new(Jabber::JID::new(ARGV[0]), ARGV[1], ARGV[2])
266
+ Thread.stop
@@ -0,0 +1,83 @@
1
+ require 'xmpp4r'
2
+ require 'xmpp4r/helpers/filetransfer'
3
+
4
+
5
+ if ARGV.size != 3
6
+ puts "Usage: #{$0} <jid> <password> <incoming-directory>"
7
+ exit
8
+ end
9
+
10
+
11
+ #Jabber::debug = true
12
+
13
+ cl = Jabber::Client.new(Jabber::JID.new(ARGV[0]))
14
+ puts "Connecting Jabber client..."
15
+ cl.connect
16
+ puts "Authenticating..."
17
+ cl.auth ARGV[1]
18
+
19
+ ft = Jabber::Helpers::FileTransfer.new(cl)
20
+ ft.add_incoming_callback { |iq,file|
21
+ puts "Incoming file transfer from #{iq.from}: #{file.fname} (#{file.size / 1024} KB)"
22
+
23
+ filename = "#{ARGV[2]}/#{file.fname.split(/\//).last}"
24
+ offset = nil
25
+ if File::exist?(filename)
26
+ puts "#{filename} already exists"
27
+ if File::size(filename) < file.size and file.range
28
+ offset = File::size(filename)
29
+ puts "Peer supports <range/>, will retrieve #{file.fname} starting at #{offset}"
30
+ else
31
+ puts "#{file.fname} is already fully retrieved, declining file-transfer"
32
+ ft.decline(iq)
33
+ next
34
+ end
35
+ end
36
+
37
+ Thread.new {
38
+ begin
39
+ puts "Accepting #{file.fname}"
40
+ stream = ft.accept(iq, offset)
41
+ if stream.kind_of?(Jabber::Helpers::SOCKS5Bytestreams)
42
+ stream.connect_timeout = 5
43
+ stream.add_streamhost_callback { |streamhost,state,e|
44
+ case state
45
+ when :connecting
46
+ puts "Connecting to #{streamhost.jid} (#{streamhost.host}:#{streamhost.port})"
47
+ when :success
48
+ puts "Successfully using #{streamhost.jid} (#{streamhost.host}:#{streamhost.port})"
49
+ when :failure
50
+ puts "Error using #{streamhost.jid} (#{streamhost.host}:#{streamhost.port}): #{e}"
51
+ end
52
+ }
53
+ end
54
+
55
+ puts "Waiting for stream configuration"
56
+ if stream.accept
57
+ puts "Stream established"
58
+ outfile = File.new(filename, (offset ? 'a' : 'w'))
59
+ while buf = stream.read
60
+ outfile.write(buf)
61
+ print '.'
62
+ $stdout.flush
63
+ end
64
+ puts '!'
65
+ outfile.close
66
+ stream.close
67
+ else
68
+ puts "Stream failed"
69
+ end
70
+ rescue Exception => e
71
+ puts "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
72
+ end
73
+ }
74
+ }
75
+
76
+ cl.send(Jabber::Presence.new(:chat, 'Send me files!'))
77
+
78
+ puts "Waiting."
79
+
80
+ Thread.stop
81
+
82
+ cl.close
83
+
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # XMPP4R - XMPP Library for Ruby
4
+ # Copyright (C) 2005 Stephan Maka <stephan@spaceboyz.net>
5
+ # Released under Ruby's license (see the LICENSE file) or GPL, at your option
6
+ #
7
+ #
8
+ # Roster-Discovery example
9
+ #
10
+ # If you don't understand this code read JEP-0030 (Service Discovery) first:
11
+ # http://www.jabber.org/jeps/jep-0030.html
12
+ #
13
+ # This examples exposes your roster to Service Discovery and can be browsed
14
+ # by anyone. Please use with care if you want to keep your roster private!
15
+ #
16
+ # The Psi client has a very pretty Service Discovery dialog. But be sure
17
+ # to turn off "Auto-browse into objects" for big rosters.
18
+ #
19
+
20
+ $:.unshift '../../../../../lib'
21
+
22
+ require 'thread'
23
+
24
+ require 'xmpp4r'
25
+ require 'xmpp4r/helpers/roster'
26
+ require 'xmpp4r/iq/query/discoinfo'
27
+ require 'xmpp4r/iq/query/discoitems'
28
+
29
+ # Command line argument checking
30
+
31
+ if ARGV.size != 2
32
+ puts("Usage: ./rosterdiscovery.rb <jid> <password>")
33
+ exit
34
+ end
35
+
36
+ # Building up the connection
37
+
38
+ #Jabber::debug = true
39
+
40
+ jid = Jabber::JID.new(ARGV[0])
41
+
42
+ cl = Jabber::Client.new(jid)
43
+ cl.connect
44
+ cl.auth(ARGV[1])
45
+
46
+
47
+ # The roster instance
48
+ roster = Jabber::Helpers::Roster.new(cl)
49
+
50
+
51
+ cl.add_iq_callback { |iq|
52
+ if iq.query.kind_of?(Jabber::IqQueryDiscoInfo) || iq.query.kind_of?(Jabber::IqQueryDiscoItems)
53
+
54
+ # Prepare the <iq/> stanza for result
55
+ iq.from, iq.to = iq.to, iq.from
56
+ iq.type = :result
57
+
58
+
59
+ if iq.query.kind_of?(Jabber::IqQueryDiscoInfo)
60
+ # iq.to and iq.from are already switched here:
61
+ puts("#{iq.to} requests info of #{iq.from} node #{iq.query.node.inspect}")
62
+
63
+ if iq.query.node.nil?
64
+ iq.query.add(Jabber::DiscoIdentity.new('directory', 'Roster discovery', 'user'))
65
+ else
66
+ # Count contacts in group
67
+ in_group = 0
68
+ roster.items.each { |jid,item|
69
+ if item.groups.include?(iq.query.node)
70
+ in_group += 1
71
+ end
72
+ }
73
+
74
+ iq.query.add(Jabber::DiscoIdentity.new('directory', "#{iq.query.node} (#{in_group})", 'group'))
75
+ end
76
+
77
+ iq.query.add(Jabber::DiscoFeature.new(Jabber::IqQueryDiscoInfo.new.namespace))
78
+ iq.query.add(Jabber::DiscoFeature.new(Jabber::IqQueryDiscoItems.new.namespace))
79
+
80
+ elsif iq.query.kind_of?(Jabber::IqQueryDiscoItems)
81
+ # iq.to and iq.from are already switched here:
82
+ puts("#{iq.to} requests items of #{iq.from} node #{iq.query.node.inspect}")
83
+
84
+ if iq.query.node.nil?
85
+ # Make items from group names
86
+ groups = []
87
+
88
+ roster.items.each { |jid,item|
89
+ groups += item.groups
90
+ }
91
+
92
+ groups.uniq.each { |group|
93
+ iq.query.add(Jabber::DiscoItem.new(cl.jid, group, group))
94
+ }
95
+
96
+ # Collect all ungrouped roster items
97
+ roster.items.each { |jid,item|
98
+ if item.groups == []
99
+ iq.query.add(Jabber::DiscoItem.new(item.jid, item.iname.to_s == '' ? item.jid : item.iname))
100
+ end
101
+ }
102
+ else
103
+ # Add a discovery item for each roster item in that group
104
+ roster.items.each { |jid,item|
105
+ if item.groups.include?(iq.query.node)
106
+ iq.query.add(Jabber::DiscoItem.new(item.jid, item.iname.to_s == '' ? item.jid : item.iname))
107
+ end
108
+ }
109
+ end
110
+
111
+ end
112
+
113
+ cl.send(iq)
114
+
115
+ true
116
+ end
117
+ }
118
+
119
+ # Initial presence
120
+ cl.send(Jabber::Presence.new.set_status("Discover my roster at #{jid}"))
121
+
122
+ # Main loop:
123
+
124
+ loop do
125
+ cl.process
126
+ Thread.stop
127
+ end
128
+
129
+ cl.close
130
+
@@ -0,0 +1,10 @@
1
+ ---
2
+ jabber:
3
+ jid: user@server/resource
4
+ password: password
5
+ local:
6
+ port: 65010
7
+ addresses: [172.22.16.3]
8
+ proxies:
9
+ - proxy.jabber.org
10
+ - transfer.jabber.freenet.de
@@ -0,0 +1,72 @@
1
+ require 'xmpp4r'
2
+ require 'xmpp4r/bytestreams'
3
+ require 'yaml'
4
+
5
+ Jabber::debug = true
6
+
7
+ if ARGV.size != 3
8
+ puts "Usage: #{$0} <jid> <description> <file>"
9
+ exit
10
+ end
11
+
12
+ conf = YAML::load File.new('sendfile.conf')
13
+
14
+ cl = Jabber::Client.new(Jabber::JID.new(conf['jabber']['jid']))
15
+ puts "Connecting Jabber client..."
16
+ cl.connect
17
+ puts "Authenticating..."
18
+ cl.auth conf['jabber']['password']
19
+
20
+ puts "Starting local Bytestreams server"
21
+ bss = Jabber::Bytestreams::SOCKS5BytestreamsServer.new(conf['local']['port'])
22
+ conf['local']['addresses'].each { |address|
23
+ bss.add_address(address)
24
+ }
25
+ ft = Jabber::FileTransfer::Helper.new(cl)
26
+ #ft.allow_bytestreams = false
27
+ source = Jabber::FileTransfer::FileSource.new(ARGV[2])
28
+ puts "Offering #{source.filename} to #{ARGV[0]}"
29
+ stream = ft.offer(Jabber::JID.new(ARGV[0]), source, ARGV[1])
30
+
31
+ if stream
32
+ puts "Starting stream initialization (#{stream.class})"
33
+
34
+ if stream.kind_of? Jabber::Bytestreams::SOCKS5BytestreamsInitiator
35
+ stream.add_streamhost(bss)
36
+ (conf['proxies'] || []).each { |proxy|
37
+ puts "Querying proxy #{proxy}"
38
+ stream.add_streamhost proxy
39
+ }
40
+ puts "Offering streamhosts " + stream.streamhosts.collect { |sh| sh.jid }.join(' ')
41
+
42
+ stream.add_streamhost_callback { |streamhost,state,e|
43
+ case state
44
+ when :connecting
45
+ puts "Connecting to #{streamhost.jid} (#{streamhost.host}:#{streamhost.port})"
46
+ when :success
47
+ puts "Successfully using #{streamhost.jid} (#{streamhost.host}:#{streamhost.port})"
48
+ when :failure
49
+ puts "Error using #{streamhost.jid} (#{streamhost.host}:#{streamhost.port}): #{e}"
50
+ end
51
+ }
52
+ end
53
+
54
+ stream.open
55
+ if stream.kind_of? Jabber::Bytestreams::SOCKS5BytestreamsInitiator
56
+ puts "Using streamhost #{stream.streamhost_used.jid} (#{stream.streamhost_used.host}:#{stream.streamhost_used.port})"
57
+ end
58
+
59
+ while buf = source.read
60
+ print "."
61
+ $stdout.flush
62
+ stream.write buf
63
+ stream.flush
64
+ end
65
+ puts "!"
66
+ stream.close
67
+
68
+ else
69
+ puts "Peer declined"
70
+ end
71
+
72
+ cl.close
@@ -0,0 +1,51 @@
1
+ require 'thread'
2
+
3
+ class Shell
4
+
5
+ PROMPT = "_-=READY=-_"
6
+
7
+ def initialize(shell = "/bin/bash", delay = 1, &block)
8
+ @cb = block
9
+ @shell = shell
10
+ @delay = delay
11
+ @parent_to_child_read, @parent_to_child_write = IO.pipe
12
+ @child_to_parent_read, @child_to_parent_write = IO.pipe
13
+ @child_pid = fork do
14
+ @parent_to_child_write.close
15
+ @child_to_parent_read.close
16
+ $stdin.reopen(@parent_to_child_read)
17
+ $stdout.reopen(@child_to_parent_write)
18
+ $stderr.reopen(@child_to_parent_write)
19
+ exec("/bin/bash")
20
+ end
21
+ buffer = ""
22
+ semaphore = Mutex::new
23
+ Thread::new do
24
+ while true
25
+ c = @child_to_parent_read.read(1)
26
+ semaphore.synchronize { buffer += c }
27
+ end
28
+ end
29
+ Thread::new do
30
+ ch = ""
31
+ while true do
32
+ sleep @delay
33
+ semaphore.synchronize {
34
+ if buffer == ch and ch != ""
35
+ @cb.call buffer
36
+ buffer = ""
37
+ end
38
+ ch = buffer
39
+ }
40
+ end
41
+ end
42
+ end
43
+
44
+ def puts(str)
45
+ @parent_to_child_write.puts(str)
46
+ end
47
+
48
+ def kill
49
+ @child_pid.kill
50
+ end
51
+ end