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.
- data/COPYING +340 -0
- data/ChangeLog +28 -0
- data/LICENSE +59 -0
- data/README +20 -0
- data/Rakefile +103 -0
- data/UPDATING +40 -0
- data/data/doc/xmpp4r/examples/advanced/adventure/README +57 -0
- data/data/doc/xmpp4r/examples/advanced/adventure/adventure.rb +23 -0
- data/data/doc/xmpp4r/examples/advanced/adventure/adventuremuc.rb +136 -0
- data/data/doc/xmpp4r/examples/advanced/adventure/cube.xml +15 -0
- data/data/doc/xmpp4r/examples/advanced/adventure/tower.xml +69 -0
- data/data/doc/xmpp4r/examples/advanced/adventure/world.rb +425 -0
- data/data/doc/xmpp4r/examples/advanced/fileserve.conf +11 -0
- data/data/doc/xmpp4r/examples/advanced/fileserve.rb +344 -0
- data/data/doc/xmpp4r/examples/advanced/getonline.rb +56 -0
- data/data/doc/xmpp4r/examples/advanced/gtkmucclient.rb +315 -0
- data/data/doc/xmpp4r/examples/advanced/migrate.rb +89 -0
- data/data/doc/xmpp4r/examples/advanced/minimuc.rb +266 -0
- data/data/doc/xmpp4r/examples/advanced/recvfile.rb +83 -0
- data/data/doc/xmpp4r/examples/advanced/rosterdiscovery.rb +130 -0
- data/data/doc/xmpp4r/examples/advanced/sendfile.conf +10 -0
- data/data/doc/xmpp4r/examples/advanced/sendfile.rb +72 -0
- data/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr.rb +51 -0
- data/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr_jabber.rb +43 -0
- data/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr_test.rb +10 -0
- data/data/doc/xmpp4r/examples/advanced/versionpoll.rb +90 -0
- data/data/doc/xmpp4r/examples/advanced/xmpping.rb +134 -0
- data/data/doc/xmpp4r/examples/advanced/xmppingrc.sample +9 -0
- data/data/doc/xmpp4r/examples/basic/change_password.rb +41 -0
- data/data/doc/xmpp4r/examples/basic/client.rb +68 -0
- data/data/doc/xmpp4r/examples/basic/component.rb +11 -0
- data/data/doc/xmpp4r/examples/basic/echo_nonthreaded.rb +32 -0
- data/data/doc/xmpp4r/examples/basic/echo_threaded.rb +32 -0
- data/data/doc/xmpp4r/examples/basic/jabbersend.rb +41 -0
- data/data/doc/xmpp4r/examples/basic/mass_sender.rb +67 -0
- data/data/doc/xmpp4r/examples/basic/mucinfo.rb +39 -0
- data/data/doc/xmpp4r/examples/basic/mucsimplebot.rb +83 -0
- data/data/doc/xmpp4r/examples/basic/register.rb +25 -0
- data/data/doc/xmpp4r/examples/basic/remove_registration.rb +18 -0
- data/data/doc/xmpp4r/examples/basic/roster.rb +42 -0
- data/data/doc/xmpp4r/examples/basic/rosterprint.rb +50 -0
- data/data/doc/xmpp4r/examples/basic/rosterrename.rb +34 -0
- data/data/doc/xmpp4r/examples/basic/rosterwatch.rb +172 -0
- data/data/doc/xmpp4r/examples/basic/send_vcard.rb +68 -0
- data/data/doc/xmpp4r/examples/basic/versionbot.rb +75 -0
- data/data/doc/xmpp4r/examples/buggy/jabber2jabber/jabber2jabber.rb +18 -0
- data/data/doc/xmpp4r/examples/buggy/miniedgarr_cgi.rb +192 -0
- data/data/doc/xmpp4r/examples/buggy/miniedgarr_watch.rb +82 -0
- data/lib/callbacks.rb +122 -0
- data/lib/xmpp4r/authenticationfailure.rb +13 -0
- data/lib/xmpp4r/bytestreams/helper/filetransfer.rb +315 -0
- data/lib/xmpp4r/bytestreams/helper/ibb/base.rb +256 -0
- data/lib/xmpp4r/bytestreams/helper/ibb/initiator.rb +30 -0
- data/lib/xmpp4r/bytestreams/helper/ibb/target.rb +46 -0
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb +151 -0
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/initiator.rb +85 -0
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb +178 -0
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/socks5.rb +56 -0
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb +61 -0
- data/lib/xmpp4r/bytestreams/iq/bytestreams.rb +177 -0
- data/lib/xmpp4r/bytestreams/iq/si.rb +221 -0
- data/lib/xmpp4r/bytestreams.rb +11 -0
- data/lib/xmpp4r/client.rb +249 -0
- data/lib/xmpp4r/component.rb +103 -0
- data/lib/xmpp4r/connection.rb +166 -0
- data/lib/xmpp4r/dataforms/x/data.rb +248 -0
- data/lib/xmpp4r/dataforms.rb +1 -0
- data/lib/xmpp4r/debuglog.rb +34 -0
- data/lib/xmpp4r/delay/x/delay.rb +100 -0
- data/lib/xmpp4r/delay.rb +1 -0
- data/lib/xmpp4r/discovery/iq/discoinfo.rb +225 -0
- data/lib/xmpp4r/discovery/iq/discoitems.rb +162 -0
- data/lib/xmpp4r/discovery.rb +2 -0
- data/lib/xmpp4r/error.rb +230 -0
- data/lib/xmpp4r/errorexception.rb +32 -0
- data/lib/xmpp4r/feature_negotiation/iq/feature.rb +42 -0
- data/lib/xmpp4r/feature_negotiation.rb +1 -0
- data/lib/xmpp4r/idgenerator.rb +37 -0
- data/lib/xmpp4r/iq.rb +229 -0
- data/lib/xmpp4r/jid.rb +167 -0
- data/lib/xmpp4r/message.rb +171 -0
- data/lib/xmpp4r/muc/helper/mucbrowser.rb +107 -0
- data/lib/xmpp4r/muc/helper/mucclient.rb +382 -0
- data/lib/xmpp4r/muc/helper/simplemucclient.rb +222 -0
- data/lib/xmpp4r/muc/x/muc.rb +98 -0
- data/lib/xmpp4r/muc/x/mucuserinvite.rb +58 -0
- data/lib/xmpp4r/muc/x/mucuseritem.rb +148 -0
- data/lib/xmpp4r/muc.rb +6 -0
- data/lib/xmpp4r/presence.rb +255 -0
- data/lib/xmpp4r/query.rb +43 -0
- data/lib/xmpp4r/rexmladdons.rb +826 -0
- data/lib/xmpp4r/roster/helper/roster.rb +514 -0
- data/lib/xmpp4r/roster/iq/roster.rb +244 -0
- data/lib/xmpp4r/roster/x/roster.rb +155 -0
- data/lib/xmpp4r/roster.rb +4 -0
- data/lib/xmpp4r/sasl.rb +167 -0
- data/lib/xmpp4r/stream.rb +543 -0
- data/lib/xmpp4r/streamparser.rb +77 -0
- data/lib/xmpp4r/vcard/helper/vcard.rb +86 -0
- data/lib/xmpp4r/vcard/iq/vcard.rb +102 -0
- data/lib/xmpp4r/vcard.rb +3 -0
- data/lib/xmpp4r/version/helper/responder.rb +71 -0
- data/lib/xmpp4r/version/helper/simpleresponder.rb +44 -0
- data/lib/xmpp4r/version/iq/version.rb +118 -0
- data/lib/xmpp4r/version.rb +3 -0
- data/lib/xmpp4r/x.rb +43 -0
- data/lib/xmpp4r/xmlstanza.rb +174 -0
- data/lib/xmpp4r/xmpp4r.rb +16 -0
- data/lib/xmpp4r.rb +122 -0
- data/setup.rb +1360 -0
- data/test/bytestreams/tc_ibb.rb +186 -0
- data/test/bytestreams/tc_socks5bytestreams.rb +57 -0
- data/test/delay/tc_xdelay.rb +51 -0
- data/test/lib/clienttester.rb +110 -0
- data/test/muc/tc_muc_mucclient.rb +569 -0
- data/test/muc/tc_muc_simplemucclient.rb +72 -0
- data/test/roster/.tc_helper.rb.swp +0 -0
- data/test/roster/tc_helper.rb +389 -0
- data/test/roster/tc_iqqueryroster.rb +140 -0
- data/test/roster/tc_xroster.rb +70 -0
- data/test/tc_callbacks.rb +128 -0
- data/test/tc_class_names.rb +129 -0
- data/test/tc_client.rb +30 -0
- data/test/tc_error.rb +103 -0
- data/test/tc_idgenerator.rb +30 -0
- data/test/tc_iq.rb +109 -0
- data/test/tc_iqquery.rb +31 -0
- data/test/tc_jid.rb +202 -0
- data/test/tc_message.rb +114 -0
- data/test/tc_presence.rb +148 -0
- data/test/tc_stream.rb +182 -0
- data/test/tc_streamError.rb +87 -0
- data/test/tc_streamSend.rb +59 -0
- data/test/tc_streamThreaded.rb +168 -0
- data/test/tc_xmlstanza.rb +76 -0
- data/test/ts_xmpp4r.rb +34 -0
- data/test/vcard/tc_iqvcard.rb +52 -0
- data/test/version/tc_helper.rb +46 -0
- data/test/version/tc_iqqueryversion.rb +96 -0
- data/tools/doctoweb.bash +30 -0
- data/tools/gen_requires.bash +10 -0
- 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,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
|