gmcmillan-xmpp4r 0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG +91 -0
- data/COPYING +340 -0
- data/LICENSE +59 -0
- data/README.rdoc +122 -0
- data/README_ruby19.txt +43 -0
- data/Rakefile +258 -0
- data/data/doc/xmpp4r/examples/advanced/adventure/README +56 -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 +424 -0
- data/data/doc/xmpp4r/examples/advanced/fileserve.conf +11 -0
- data/data/doc/xmpp4r/examples/advanced/fileserve.rb +346 -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 +88 -0
- data/data/doc/xmpp4r/examples/advanced/minimuc.rb +266 -0
- data/data/doc/xmpp4r/examples/advanced/pep-aggregator/index.xsl +235 -0
- data/data/doc/xmpp4r/examples/advanced/pep-aggregator/pep-aggregator.rb +147 -0
- data/data/doc/xmpp4r/examples/advanced/recvfile.rb +85 -0
- data/data/doc/xmpp4r/examples/advanced/rosterdiscovery.rb +129 -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 +109 -0
- data/data/doc/xmpp4r/examples/advanced/xmpping.rb +146 -0
- data/data/doc/xmpp4r/examples/advanced/xmppingrc.sample +14 -0
- data/data/doc/xmpp4r/examples/basic/change_password.rb +41 -0
- data/data/doc/xmpp4r/examples/basic/client.rb +70 -0
- data/data/doc/xmpp4r/examples/basic/component.rb +11 -0
- data/data/doc/xmpp4r/examples/basic/echo.rb +37 -0
- data/data/doc/xmpp4r/examples/basic/jabbersend.rb +41 -0
- data/data/doc/xmpp4r/examples/basic/mass_sender.rb +68 -0
- data/data/doc/xmpp4r/examples/basic/muc_owner_config.rb +12 -0
- data/data/doc/xmpp4r/examples/basic/mucinfo.rb +41 -0
- data/data/doc/xmpp4r/examples/basic/mucsimplebot.rb +82 -0
- data/data/doc/xmpp4r/examples/basic/register.rb +42 -0
- data/data/doc/xmpp4r/examples/basic/remove_registration.rb +18 -0
- data/data/doc/xmpp4r/examples/basic/roster.rb +44 -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 +171 -0
- data/data/doc/xmpp4r/examples/basic/send_vcard.rb +67 -0
- data/data/doc/xmpp4r/examples/basic/tune_client.rb +56 -0
- data/data/doc/xmpp4r/examples/basic/tune_server.rb +58 -0
- data/data/doc/xmpp4r/examples/basic/versionbot.rb +75 -0
- data/lib/xmpp4r.rb +118 -0
- data/lib/xmpp4r/base64.rb +32 -0
- data/lib/xmpp4r/bytestreams.rb +15 -0
- data/lib/xmpp4r/bytestreams/helper/filetransfer.rb +321 -0
- data/lib/xmpp4r/bytestreams/helper/ibb/base.rb +257 -0
- data/lib/xmpp4r/bytestreams/helper/ibb/initiator.rb +31 -0
- data/lib/xmpp4r/bytestreams/helper/ibb/target.rb +54 -0
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb +153 -0
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/initiator.rb +86 -0
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb +198 -0
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/socks5.rb +65 -0
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb +82 -0
- data/lib/xmpp4r/bytestreams/iq/bytestreams.rb +170 -0
- data/lib/xmpp4r/bytestreams/iq/si.rb +206 -0
- data/lib/xmpp4r/callbacks.rb +133 -0
- data/lib/xmpp4r/caps.rb +1 -0
- data/lib/xmpp4r/caps/c.rb +67 -0
- data/lib/xmpp4r/caps/helper/generator.rb +160 -0
- data/lib/xmpp4r/caps/helper/helper.rb +84 -0
- data/lib/xmpp4r/client.rb +345 -0
- data/lib/xmpp4r/command/helper/responder.rb +53 -0
- data/lib/xmpp4r/command/iq/command.rb +154 -0
- data/lib/xmpp4r/component.rb +103 -0
- data/lib/xmpp4r/connection.rb +231 -0
- data/lib/xmpp4r/dataforms.rb +5 -0
- data/lib/xmpp4r/dataforms/x/data.rb +297 -0
- data/lib/xmpp4r/debuglog.rb +63 -0
- data/lib/xmpp4r/delay.rb +5 -0
- data/lib/xmpp4r/delay/x/delay.rb +99 -0
- data/lib/xmpp4r/discovery.rb +8 -0
- data/lib/xmpp4r/discovery/helper/helper.rb +58 -0
- data/lib/xmpp4r/discovery/helper/responder.rb +165 -0
- data/lib/xmpp4r/discovery/iq/discoinfo.rb +211 -0
- data/lib/xmpp4r/discovery/iq/discoitems.rb +147 -0
- data/lib/xmpp4r/entity_time.rb +6 -0
- data/lib/xmpp4r/entity_time/iq.rb +45 -0
- data/lib/xmpp4r/entity_time/responder.rb +57 -0
- data/lib/xmpp4r/errors.rb +284 -0
- data/lib/xmpp4r/feature_negotiation.rb +5 -0
- data/lib/xmpp4r/feature_negotiation/iq/feature.rb +28 -0
- data/lib/xmpp4r/framework/base.rb +55 -0
- data/lib/xmpp4r/framework/bot.rb +148 -0
- data/lib/xmpp4r/httpbinding.rb +5 -0
- data/lib/xmpp4r/httpbinding/client.rb +275 -0
- data/lib/xmpp4r/idgenerator.rb +37 -0
- data/lib/xmpp4r/iq.rb +221 -0
- data/lib/xmpp4r/jid.rb +167 -0
- data/lib/xmpp4r/last.rb +2 -0
- data/lib/xmpp4r/last/helper/helper.rb +37 -0
- data/lib/xmpp4r/last/iq/last.rb +67 -0
- data/lib/xmpp4r/location.rb +2 -0
- data/lib/xmpp4r/location/helper/helper.rb +56 -0
- data/lib/xmpp4r/location/location.rb +179 -0
- data/lib/xmpp4r/message.rb +226 -0
- data/lib/xmpp4r/muc.rb +14 -0
- data/lib/xmpp4r/muc/helper/mucbrowser.rb +92 -0
- data/lib/xmpp4r/muc/helper/mucclient.rb +469 -0
- data/lib/xmpp4r/muc/helper/simplemucclient.rb +332 -0
- data/lib/xmpp4r/muc/iq/mucadmin.rb +23 -0
- data/lib/xmpp4r/muc/iq/mucadminitem.rb +20 -0
- data/lib/xmpp4r/muc/iq/mucowner.rb +15 -0
- data/lib/xmpp4r/muc/item.rb +143 -0
- data/lib/xmpp4r/muc/x/muc.rb +70 -0
- data/lib/xmpp4r/muc/x/mucuserinvite.rb +60 -0
- data/lib/xmpp4r/muc/x/mucuseritem.rb +36 -0
- data/lib/xmpp4r/presence.rb +232 -0
- data/lib/xmpp4r/pubsub.rb +8 -0
- data/lib/xmpp4r/pubsub/children/configuration.rb +86 -0
- data/lib/xmpp4r/pubsub/children/event.rb +49 -0
- data/lib/xmpp4r/pubsub/children/item.rb +35 -0
- data/lib/xmpp4r/pubsub/children/items.rb +53 -0
- data/lib/xmpp4r/pubsub/children/node_config.rb +48 -0
- data/lib/xmpp4r/pubsub/children/publish.rb +38 -0
- data/lib/xmpp4r/pubsub/children/retract.rb +41 -0
- data/lib/xmpp4r/pubsub/children/subscription.rb +62 -0
- data/lib/xmpp4r/pubsub/children/subscription_config.rb +67 -0
- data/lib/xmpp4r/pubsub/children/unsubscribe.rb +63 -0
- data/lib/xmpp4r/pubsub/helper/nodebrowser.rb +129 -0
- data/lib/xmpp4r/pubsub/helper/nodehelper.rb +156 -0
- data/lib/xmpp4r/pubsub/helper/oauth_service_helper.rb +90 -0
- data/lib/xmpp4r/pubsub/helper/servicehelper.rb +490 -0
- data/lib/xmpp4r/pubsub/iq/pubsub.rb +19 -0
- data/lib/xmpp4r/query.rb +15 -0
- data/lib/xmpp4r/reliable.rb +168 -0
- data/lib/xmpp4r/rexmladdons.rb +197 -0
- data/lib/xmpp4r/roster.rb +7 -0
- data/lib/xmpp4r/roster/helper/roster.rb +532 -0
- data/lib/xmpp4r/roster/iq/roster.rb +215 -0
- data/lib/xmpp4r/roster/x/roster.rb +138 -0
- data/lib/xmpp4r/rpc.rb +2 -0
- data/lib/xmpp4r/rpc/helper/client.rb +123 -0
- data/lib/xmpp4r/rpc/helper/server.rb +74 -0
- data/lib/xmpp4r/rpc/helper/xmlrpcaddons.rb +67 -0
- data/lib/xmpp4r/rpc/iq/rpc.rb +23 -0
- data/lib/xmpp4r/sasl.rb +259 -0
- data/lib/xmpp4r/semaphore.rb +38 -0
- data/lib/xmpp4r/stream.rb +611 -0
- data/lib/xmpp4r/streamparser.rb +66 -0
- data/lib/xmpp4r/test/listener_mocker.rb +118 -0
- data/lib/xmpp4r/tune.rb +2 -0
- data/lib/xmpp4r/tune/helper/helper.rb +58 -0
- data/lib/xmpp4r/tune/tune.rb +113 -0
- data/lib/xmpp4r/vcard.rb +6 -0
- data/lib/xmpp4r/vcard/helper/vcard.rb +84 -0
- data/lib/xmpp4r/vcard/iq/vcard.rb +109 -0
- data/lib/xmpp4r/version.rb +7 -0
- data/lib/xmpp4r/version/helper/responder.rb +72 -0
- data/lib/xmpp4r/version/helper/simpleresponder.rb +44 -0
- data/lib/xmpp4r/version/iq/version.rb +105 -0
- data/lib/xmpp4r/x.rb +37 -0
- data/lib/xmpp4r/xhtml.rb +1 -0
- data/lib/xmpp4r/xhtml/html.rb +115 -0
- data/lib/xmpp4r/xmpp4r.rb +20 -0
- data/lib/xmpp4r/xmppelement.rb +168 -0
- data/lib/xmpp4r/xmppstanza.rb +162 -0
- data/setup.rb +1586 -0
- data/test/bytestreams/tc_ibb.rb +188 -0
- data/test/bytestreams/tc_socks5bytestreams.rb +114 -0
- data/test/caps/tc_helper.rb +158 -0
- data/test/dataforms/tc_data.rb +81 -0
- data/test/delay/tc_xdelay.rb +51 -0
- data/test/discovery/tc_responder.rb +91 -0
- data/test/entity_time/tc_responder.rb +65 -0
- data/test/last/tc_helper.rb +75 -0
- data/test/lib/assert_equal_xml.rb +14 -0
- data/test/lib/clienttester.rb +149 -0
- data/test/muc/tc_muc_mucclient.rb +834 -0
- data/test/muc/tc_muc_simplemucclient.rb +114 -0
- data/test/muc/tc_mucowner.rb +50 -0
- data/test/pubsub/tc_helper.rb +785 -0
- data/test/pubsub/tc_nodeconfig.rb +61 -0
- data/test/pubsub/tc_subscriptionconfig.rb +41 -0
- data/test/roster/tc_helper.rb +523 -0
- data/test/roster/tc_iqqueryroster.rb +173 -0
- data/test/roster/tc_xroster.rb +73 -0
- data/test/rpc/tc_helper.rb +96 -0
- data/test/tc_callbacks.rb +129 -0
- data/test/tc_class_names.rb +146 -0
- data/test/tc_client.rb +30 -0
- data/test/tc_errors.rb +146 -0
- data/test/tc_idgenerator.rb +30 -0
- data/test/tc_iq.rb +113 -0
- data/test/tc_iqquery.rb +31 -0
- data/test/tc_jid.rb +204 -0
- data/test/tc_presence.rb +150 -0
- data/test/tc_rexml.rb +139 -0
- data/test/tc_stream.rb +193 -0
- data/test/tc_streamComponent.rb +105 -0
- data/test/tc_streamError.rb +129 -0
- data/test/tc_streamSend.rb +59 -0
- data/test/tc_streamparser.rb +137 -0
- data/test/tc_xmppstanza.rb +135 -0
- data/test/ts_xmpp4r.rb +44 -0
- data/test/tune/tc_helper_recv.rb +82 -0
- data/test/tune/tc_helper_send.rb +74 -0
- data/test/tune/tc_tune.rb +79 -0
- data/test/vcard/tc_helper.rb +49 -0
- data/test/vcard/tc_iqvcard.rb +62 -0
- data/test/version/tc_helper.rb +60 -0
- data/test/version/tc_iqqueryversion.rb +97 -0
- data/test/xhtml/tc_html.rb +41 -0
- data/tools/gen_requires.bash +31 -0
- data/tools/xmpp4r-gemspec-test.rb +11 -0
- data/xmpp4r.gemspec +249 -0
- metadata +299 -0
@@ -0,0 +1,346 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'xmpp4r'
|
5
|
+
require 'xmpp4r/bytestreams'
|
6
|
+
require 'xmpp4r/roster'
|
7
|
+
require 'xmpp4r/version'
|
8
|
+
|
9
|
+
Jabber::debug = true
|
10
|
+
|
11
|
+
def human_readable(num)
|
12
|
+
unit = ''
|
13
|
+
units = %w(K M G T P E)
|
14
|
+
while num > 10240 and units.size > 0
|
15
|
+
num /= 1024
|
16
|
+
unit = units.shift
|
17
|
+
end
|
18
|
+
"#{num} #{unit}B"
|
19
|
+
end
|
20
|
+
|
21
|
+
class Transfer
|
22
|
+
attr_reader :peer, :filename, :bytes, :filesize
|
23
|
+
|
24
|
+
def initialize(filetransfer, peer, filename, filesize, msgblock)
|
25
|
+
@filetransfer = filetransfer
|
26
|
+
@peer = peer
|
27
|
+
@filename = filename
|
28
|
+
@filesize = filesize
|
29
|
+
@msgblock = msgblock
|
30
|
+
|
31
|
+
@done = false
|
32
|
+
@bytes = 0
|
33
|
+
@stats = [0]
|
34
|
+
@stats_lock = Mutex.new
|
35
|
+
@stats_thread = Thread.new { stats_loop }
|
36
|
+
|
37
|
+
|
38
|
+
@streamhost_cb = lambda { |streamhost,state,e|
|
39
|
+
case state
|
40
|
+
when :connecting
|
41
|
+
say "Connecting to #{streamhost.jid} (#{streamhost.host}:#{streamhost.port})"
|
42
|
+
when :success
|
43
|
+
say "Successfully using #{streamhost.jid} (#{streamhost.host}:#{streamhost.port})"
|
44
|
+
when :failure
|
45
|
+
say "Error using #{streamhost.jid} (#{streamhost.host}:#{streamhost.port}): #{e}"
|
46
|
+
end
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def done?
|
51
|
+
@stats_thread.kill if @done
|
52
|
+
@done
|
53
|
+
end
|
54
|
+
|
55
|
+
def stats_loop
|
56
|
+
loop {
|
57
|
+
sleep 1
|
58
|
+
@stats_lock.synchronize {
|
59
|
+
@stats.push @bytes
|
60
|
+
@stats.shift if @stats.size > 5
|
61
|
+
}
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def stats
|
66
|
+
@stats_lock.synchronize {
|
67
|
+
if @stats.first >= @stats.last
|
68
|
+
0
|
69
|
+
else
|
70
|
+
(@stats.last - @stats.first) / (@stats.size - 1)
|
71
|
+
end
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def say(text)
|
76
|
+
@msgblock.call(text)
|
77
|
+
end
|
78
|
+
|
79
|
+
def transfer(from, to)
|
80
|
+
while buf = from.read
|
81
|
+
@bytes += to.write buf
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class Upload < Transfer
|
87
|
+
def initialize(filetransfer, iq, filename, filesize, can_range, msgblock)
|
88
|
+
super(filetransfer, iq.from, filename, filesize, msgblock)
|
89
|
+
|
90
|
+
if filename.size < 1
|
91
|
+
say "What is this file for?"
|
92
|
+
@done = true
|
93
|
+
return
|
94
|
+
end
|
95
|
+
|
96
|
+
offset = nil
|
97
|
+
if File::exist?(filename)
|
98
|
+
if File::size(filename) < filesize and can_range
|
99
|
+
@bytes = offset = File::size(filename)
|
100
|
+
say "Will retrieve #{filename} starting at #{offset}"
|
101
|
+
else
|
102
|
+
say "#{filename} already exists"
|
103
|
+
filetransfer.decline(iq)
|
104
|
+
@done = true
|
105
|
+
return
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
Thread.new {
|
110
|
+
begin
|
111
|
+
stream = filetransfer.accept(iq, offset)
|
112
|
+
if stream.kind_of?(Jabber::Bytestreams::SOCKS5Bytestreams)
|
113
|
+
stream.connect_timeout = 5
|
114
|
+
stream.add_streamhost_callback(nil, nil, &@streamhost_cb)
|
115
|
+
end
|
116
|
+
|
117
|
+
if stream.accept
|
118
|
+
outfile = File.new(filename, (offset ? 'a' : 'w'))
|
119
|
+
|
120
|
+
transfer(stream, outfile)
|
121
|
+
|
122
|
+
outfile.close
|
123
|
+
stream.close
|
124
|
+
@done = true
|
125
|
+
else
|
126
|
+
say "Stream failed"
|
127
|
+
@done = true
|
128
|
+
end
|
129
|
+
rescue
|
130
|
+
puts $!.backtrace.first
|
131
|
+
say "Error: #{$!}"
|
132
|
+
@done = true
|
133
|
+
end
|
134
|
+
}
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class Download < Transfer
|
139
|
+
def initialize(filetransfer, peer, filename, msgblock, socksconf)
|
140
|
+
begin
|
141
|
+
filesize = File.size(filename)
|
142
|
+
rescue
|
143
|
+
filesize = 0
|
144
|
+
end
|
145
|
+
|
146
|
+
super(filetransfer, peer, filename, filesize, msgblock)
|
147
|
+
|
148
|
+
Thread.new {
|
149
|
+
begin
|
150
|
+
raise "No regular file" unless File.file?(filename)
|
151
|
+
|
152
|
+
source = Jabber::FileTransfer::FileSource.new(filename)
|
153
|
+
stream = filetransfer.offer(peer, source)
|
154
|
+
unless stream
|
155
|
+
raise "Well, you should accept what you request..."
|
156
|
+
@done = true
|
157
|
+
end
|
158
|
+
|
159
|
+
if stream.kind_of?(Jabber::Bytestreams::SOCKS5Bytestreams)
|
160
|
+
socksconf.call(stream)
|
161
|
+
stream.add_streamhost_callback(nil, nil, &@streamhost_cb)
|
162
|
+
end
|
163
|
+
|
164
|
+
stream.open
|
165
|
+
transfer(source, stream)
|
166
|
+
stream.close
|
167
|
+
@done = true
|
168
|
+
rescue
|
169
|
+
say "Error: #{$!}"
|
170
|
+
@done = true
|
171
|
+
end
|
172
|
+
}
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
class FileServe
|
177
|
+
def initialize(conf)
|
178
|
+
@uploads = 0
|
179
|
+
@downloads = 0
|
180
|
+
|
181
|
+
@transfers = []
|
182
|
+
@transfers_lock = Mutex.new
|
183
|
+
|
184
|
+
@client = Jabber::Client.new Jabber::JID.new(conf['jabber']['jid'])
|
185
|
+
@client.connect
|
186
|
+
@client.auth(conf['jabber']['password'])
|
187
|
+
|
188
|
+
@ft = Jabber::FileTransfer::Helper.new(@client)
|
189
|
+
Jabber::Version::SimpleResponder.new(@client,
|
190
|
+
"XMPP4R FileServe example",
|
191
|
+
Jabber::XMPP4R_VERSION,
|
192
|
+
IO.popen('uname -sr').readlines.to_s.strip)
|
193
|
+
register_handlers
|
194
|
+
|
195
|
+
@directory = conf['directory']
|
196
|
+
@directory.gsub!(/\/+$/, '')
|
197
|
+
|
198
|
+
@socksserver = Jabber::Bytestreams::SOCKS5BytestreamsServer.new(conf['socks']['port'])
|
199
|
+
|
200
|
+
conf['socks']['addresses'].each { |addr| @socksserver.add_address(addr) }
|
201
|
+
|
202
|
+
@proxies = []
|
203
|
+
conf['socks']['proxies'].collect { |jid|
|
204
|
+
puts "Querying proxy #{jid}..."
|
205
|
+
begin
|
206
|
+
@proxies.push(Jabber::Bytestreams::SOCKS5Bytestreams::query_streamhost(@client, jid))
|
207
|
+
rescue
|
208
|
+
puts "Error: #{$!}"
|
209
|
+
end
|
210
|
+
}
|
211
|
+
|
212
|
+
Thread.new { presence }
|
213
|
+
Thread.new { cleaner }
|
214
|
+
|
215
|
+
# Panic reboot ;-)
|
216
|
+
@client.on_exception { initialize(conf) }
|
217
|
+
end
|
218
|
+
|
219
|
+
def presence
|
220
|
+
rate_upload = 0
|
221
|
+
rate_download = 0
|
222
|
+
|
223
|
+
old_status = nil
|
224
|
+
loop {
|
225
|
+
# Update the @rate_* variables
|
226
|
+
@transfers_lock.synchronize {
|
227
|
+
@transfers.each { |t|
|
228
|
+
if t.kind_of?(Upload) and t.stats > rate_upload
|
229
|
+
rate_upload = t.stats
|
230
|
+
elsif t.kind_of?(Download) and t.stats > rate_download
|
231
|
+
rate_download = t.stats
|
232
|
+
end
|
233
|
+
}
|
234
|
+
}
|
235
|
+
status = "Attempted #{@downloads} downloads (max. #{human_readable rate_download}/s) and #{@uploads} uploads (max. #{human_readable rate_upload}/s)"
|
236
|
+
|
237
|
+
@client.send(Jabber::Presence.new(:chat, status)) if status != old_status
|
238
|
+
old_status = status
|
239
|
+
|
240
|
+
sleep 1
|
241
|
+
|
242
|
+
}
|
243
|
+
end
|
244
|
+
|
245
|
+
def register_handlers
|
246
|
+
@client.add_message_callback { |msg|
|
247
|
+
if msg.type == :chat and msg.body and msg.from != 'pentabarf@pentabarf.org/rails'
|
248
|
+
puts "<#{msg.from}> #{msg.body.strip}"
|
249
|
+
cmd, arg = msg.body.split(/ /, 2)
|
250
|
+
|
251
|
+
command(msg.from, cmd, arg)
|
252
|
+
end
|
253
|
+
}
|
254
|
+
|
255
|
+
@ft.add_incoming_callback { |iq,file|
|
256
|
+
|
257
|
+
say = lambda { |text|
|
258
|
+
say(iq.from, text)
|
259
|
+
}
|
260
|
+
|
261
|
+
puts "Incoming file transfer from #{iq.from}: #{file.fname} (#{file.size / 1024} KB)"
|
262
|
+
filename = file.fname.split(/\//).last
|
263
|
+
filename.gsub!(/^\.+/, '')
|
264
|
+
|
265
|
+
puts "Range: #{file.range != nil}"
|
266
|
+
transfer = Upload.new(@ft, iq, "#{@directory}/#{filename}", file.size, file.range != nil, say)
|
267
|
+
@uploads += 1
|
268
|
+
|
269
|
+
@transfers_lock.synchronize {
|
270
|
+
@transfers.push(transfer)
|
271
|
+
}
|
272
|
+
|
273
|
+
}
|
274
|
+
|
275
|
+
roster = Jabber::Roster::Helper.new(@client)
|
276
|
+
|
277
|
+
roster.add_subscription_request_callback { |item,presence|
|
278
|
+
roster.accept_subscription(presence.from)
|
279
|
+
}
|
280
|
+
|
281
|
+
end
|
282
|
+
|
283
|
+
def command(from, cmd, arg)
|
284
|
+
say = lambda { |text|
|
285
|
+
say(from, text)
|
286
|
+
}
|
287
|
+
socksconf = lambda { |stream|
|
288
|
+
stream.add_streamhost(@socksserver)
|
289
|
+
@proxies.each { |sh|
|
290
|
+
stream.add_streamhost(sh)
|
291
|
+
}
|
292
|
+
}
|
293
|
+
|
294
|
+
case cmd
|
295
|
+
when 'get'
|
296
|
+
arg.gsub!(/\//, '')
|
297
|
+
arg.gsub!(/^\.+/, '')
|
298
|
+
transfer = Download.new(@ft, from, "#{@directory}/#{arg}", say, socksconf)
|
299
|
+
@downloads += 1
|
300
|
+
@transfers_lock.synchronize {
|
301
|
+
@transfers.push(transfer)
|
302
|
+
}
|
303
|
+
when 'ls'
|
304
|
+
text = ""
|
305
|
+
Dir.foreach(@directory) { |file|
|
306
|
+
next if file =~ /^\./
|
307
|
+
path = "#{@directory}/#{file}"
|
308
|
+
text += "#{file} (#{human_readable File.size(path)})\n" if File.file?(path)
|
309
|
+
}
|
310
|
+
say.call(text.strip)
|
311
|
+
when 'stat'
|
312
|
+
@transfers_lock.synchronize {
|
313
|
+
text = "#{@transfers.size} transfers:\n"
|
314
|
+
@transfers.each { |t|
|
315
|
+
text += "#{t.filename} (#{t.peer}): #{(t.bytes * 100) / t.filesize}% (#{human_readable t.stats}/s)\n"
|
316
|
+
}
|
317
|
+
}
|
318
|
+
say.call(text.strip)
|
319
|
+
when 'help'
|
320
|
+
say.call "Download a file: get <filename>\nList directory contents: ls\nLook who is currently wasting bandwidth: stat\nUpload a file, simply send this file"
|
321
|
+
else
|
322
|
+
say.call "Unknown command: #{cmd}, try help"
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
def say(to, text)
|
327
|
+
puts ">#{to}< #{text.strip}"
|
328
|
+
@client.send(Jabber::Message.new(to, text).set_type(:chat))
|
329
|
+
end
|
330
|
+
|
331
|
+
def cleaner
|
332
|
+
loop {
|
333
|
+
|
334
|
+
@transfers_lock.synchronize {
|
335
|
+
@transfers.delete_if { |t| t.done? }
|
336
|
+
}
|
337
|
+
|
338
|
+
sleep 1
|
339
|
+
}
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
|
344
|
+
FileServe.new(YAML::load(File.new('fileserve.conf')))
|
345
|
+
puts "Up and running!"
|
346
|
+
Thread.stop
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# This script can get all roster entries
|
4
|
+
|
5
|
+
require 'optparse'
|
6
|
+
require 'xmpp4r'
|
7
|
+
include Jabber
|
8
|
+
|
9
|
+
get = true
|
10
|
+
jid = JID.new('lucastest@linux.ensimag.fr/rosterget')
|
11
|
+
password = 'lucastest'
|
12
|
+
domains = []
|
13
|
+
|
14
|
+
OptionParser.new do |opts|
|
15
|
+
opts.banner = 'Usage: roster.rb -j jid -p password -d domain'
|
16
|
+
opts.separator ''
|
17
|
+
opts.on('-j', '--jid JID', 'sets the jid') { |j| jid = JID.new(j) }
|
18
|
+
opts.on('-p', '--password PASSWORD', 'sets the password') { |p| password = p }
|
19
|
+
opts.on('-d', '--domain DOMAIN', 'sets the domain') { |d| domains << d }
|
20
|
+
opts.on_tail('-h', '--help', 'Show this message') {
|
21
|
+
puts opts
|
22
|
+
exit
|
23
|
+
}
|
24
|
+
opts.parse!(ARGV)
|
25
|
+
end
|
26
|
+
|
27
|
+
cl = Client.new(jid)
|
28
|
+
cl.connect
|
29
|
+
cl.auth(password)
|
30
|
+
exit = false
|
31
|
+
nb = 0
|
32
|
+
cl.add_iq_callback { |i|
|
33
|
+
fjid = JID.new(i.from)
|
34
|
+
if i.type == :result and fjid.resource == "admin"
|
35
|
+
domain = fjid.domain
|
36
|
+
items = nil
|
37
|
+
i.each_element('item') { |e| items = e }
|
38
|
+
raise "items nil" if items.nil?
|
39
|
+
puts "--- Online users for #{domain} (seconds, sent, received)"
|
40
|
+
c = 0
|
41
|
+
items.each_element('user') do |e|
|
42
|
+
puts "#{e.attribute('jid')} #{e.attribute('name')}"
|
43
|
+
c += 1
|
44
|
+
end
|
45
|
+
puts "--- #{domain} : #{c} online users"
|
46
|
+
nb -= 1
|
47
|
+
end
|
48
|
+
}
|
49
|
+
for d in domains do
|
50
|
+
cl.send(Iq.new_browseget.set_to("#{d}/admin"))
|
51
|
+
nb += 1
|
52
|
+
end
|
53
|
+
while nb > 0
|
54
|
+
cl.process(1)
|
55
|
+
end
|
56
|
+
cl.close
|
@@ -0,0 +1,315 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'gtk2'
|
4
|
+
|
5
|
+
$:.unshift '../../../../../lib'
|
6
|
+
require 'xmpp4r'
|
7
|
+
require 'xmpp4r/muc/helper/simplemucclient'
|
8
|
+
require 'xmpp4r/version/helper/simpleresponder'
|
9
|
+
|
10
|
+
#Jabber::debug = true
|
11
|
+
|
12
|
+
class Gtk::Label
|
13
|
+
def self.new_show(str = nil, mnemonic = false)
|
14
|
+
label = new(str, mnemonic)
|
15
|
+
label.show
|
16
|
+
label
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class SetupWindow < Gtk::Window
|
21
|
+
def initialize
|
22
|
+
super(Gtk::Window::TOPLEVEL)
|
23
|
+
self.title = "GtkMUCClient setup"
|
24
|
+
signal_connect("delete_event") { cancel }
|
25
|
+
|
26
|
+
vbox = Gtk::VBox.new
|
27
|
+
vbox.set_border_width(4)
|
28
|
+
add(vbox)
|
29
|
+
vbox.show
|
30
|
+
|
31
|
+
frame1 = Gtk::Frame.new('Jabber Account Settings')
|
32
|
+
frame1.set_border_width(4)
|
33
|
+
frame1.show
|
34
|
+
vbox.add(frame1)
|
35
|
+
|
36
|
+
layout1 = Gtk::Table.new(4, 2)
|
37
|
+
layout1.row_spacings = 4
|
38
|
+
layout1.column_spacings = 8
|
39
|
+
layout1.show
|
40
|
+
frame1.add(layout1)
|
41
|
+
|
42
|
+
layout1.attach(Gtk::Label.new_show('Jabber ID:'), 0, 1, 1, 2)
|
43
|
+
@entry_jid = Gtk::Entry.new
|
44
|
+
@entry_jid.text = 'collector@jabber.ccc.de'
|
45
|
+
@entry_jid.show
|
46
|
+
layout1.attach(@entry_jid, 1, 2, 1, 2)
|
47
|
+
|
48
|
+
layout1.attach(Gtk::Label.new_show('Password:'), 0, 1, 2, 3)
|
49
|
+
@entry_password = Gtk::Entry.new
|
50
|
+
@entry_password.visibility = false
|
51
|
+
@entry_password.show
|
52
|
+
layout1.attach(@entry_password, 1, 2, 2, 3)
|
53
|
+
|
54
|
+
layout1.attach(Gtk::Label.new_show('Resource:'), 0, 1, 3, 4)
|
55
|
+
@entry_resource = Gtk::Entry.new
|
56
|
+
@entry_resource.text = 'gtkmucclient'
|
57
|
+
@entry_resource.show
|
58
|
+
layout1.attach(@entry_resource, 1, 2, 3, 4)
|
59
|
+
|
60
|
+
|
61
|
+
frame2 = Gtk::Frame.new('Multi-User Chat Settings')
|
62
|
+
frame2.set_border_width(4)
|
63
|
+
frame2.show
|
64
|
+
vbox.add(frame2)
|
65
|
+
|
66
|
+
layout2 = Gtk::Table.new(3, 2)
|
67
|
+
layout2.row_spacings = 4
|
68
|
+
layout2.column_spacings = 8
|
69
|
+
layout2.show
|
70
|
+
frame2.add(layout2)
|
71
|
+
|
72
|
+
layout2.attach(Gtk::Label.new_show('Room:'), 0, 1, 1, 2)
|
73
|
+
@entry_room = Gtk::Entry.new
|
74
|
+
@entry_room.text = 'test@conference.jabber.org'
|
75
|
+
@entry_room.show
|
76
|
+
layout2.attach(@entry_room, 1, 2, 1, 2)
|
77
|
+
|
78
|
+
layout2.attach(Gtk::Label.new_show('Nick:'), 0, 1, 2, 3)
|
79
|
+
@entry_nick = Gtk::Entry.new
|
80
|
+
@entry_nick.text = 'XMPP4R-Fan'
|
81
|
+
@entry_nick.show
|
82
|
+
layout2.attach(@entry_nick, 1, 2, 2, 3)
|
83
|
+
|
84
|
+
|
85
|
+
hbox = Gtk::HBox.new
|
86
|
+
hbox.show
|
87
|
+
vbox.add(hbox)
|
88
|
+
|
89
|
+
button_ok = Gtk::Button.new("Ok")
|
90
|
+
button_ok.set_border_width(4)
|
91
|
+
hbox.add(button_ok)
|
92
|
+
button_ok.signal_connect("clicked") { ok }
|
93
|
+
button_ok.can_default = true
|
94
|
+
button_ok.grab_default
|
95
|
+
button_ok.show
|
96
|
+
button_cancel = Gtk::Button.new("Cancel")
|
97
|
+
button_cancel.set_border_width(4)
|
98
|
+
hbox.add(button_cancel)
|
99
|
+
button_cancel.signal_connect("clicked") { cancel }
|
100
|
+
button_cancel.show
|
101
|
+
end
|
102
|
+
|
103
|
+
def error_dialog(msg)
|
104
|
+
dialog = Gtk::MessageDialog.new(self, Gtk::Dialog::MODAL, Gtk::MessageDialog::ERROR, Gtk::MessageDialog::BUTTONS_OK, msg)
|
105
|
+
dialog.signal_connect("response") { dialog.destroy }
|
106
|
+
dialog.run
|
107
|
+
end
|
108
|
+
|
109
|
+
def ok
|
110
|
+
jid = Jabber::JID.new(@entry_jid.text)
|
111
|
+
mucjid = Jabber::JID.new(@entry_room.text)
|
112
|
+
|
113
|
+
if jid.node.nil?
|
114
|
+
error_dialog("Your Jabber ID must contain a user name and therefore contain one @ character.")
|
115
|
+
elsif jid.resource
|
116
|
+
error_dialog("If you intend to set a custom resource, put that in the right text field. Remove the slash!")
|
117
|
+
elsif @entry_resource.text.empty?
|
118
|
+
error_dialog("Please set a resource. This is a somewhat unimportant setting...")
|
119
|
+
elsif mucjid.node.nil?
|
120
|
+
error_dialog("Please set a room name, e.g. myroom@conference.jabber.org")
|
121
|
+
elsif mucjid.resource
|
122
|
+
error_dialog("The MUC room must not contain a resource. Remove the slash!")
|
123
|
+
elsif @entry_nick.text.empty?
|
124
|
+
error_dialog("Please set a nick for MUC.")
|
125
|
+
else
|
126
|
+
jid.resource = @entry_resource.text
|
127
|
+
mucjid.resource = @entry_nick.text
|
128
|
+
password = @entry_password.text
|
129
|
+
|
130
|
+
destroy
|
131
|
+
|
132
|
+
ChatWindow.new(jid, password, mucjid).show
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def cancel
|
137
|
+
destroy
|
138
|
+
Gtk.main_quit
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
class ChatWindow < Gtk::Window
|
143
|
+
def initialize(jid, password, mucjid)
|
144
|
+
super(Gtk::Window::TOPLEVEL)
|
145
|
+
self.title = "GtkMUCClient: #{mucjid.resource} in #{mucjid.strip}"
|
146
|
+
signal_connect("delete_event") { destroy; Gtk.main_quit }
|
147
|
+
|
148
|
+
layout = Gtk::VBox.new
|
149
|
+
|
150
|
+
@topic = Gtk::Entry.new
|
151
|
+
@topic.editable = false
|
152
|
+
@topic.show
|
153
|
+
layout.pack_start(@topic, false, false, 2)
|
154
|
+
|
155
|
+
layout_mid = Gtk::HPaned.new
|
156
|
+
layout_mid.position = 500
|
157
|
+
layout_mid.show
|
158
|
+
layout.pack_start(layout_mid)
|
159
|
+
|
160
|
+
@buffer_scroll = Gtk::ScrolledWindow.new
|
161
|
+
@buffer_scroll.show
|
162
|
+
@buffer_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
|
163
|
+
layout_mid.pack1(@buffer_scroll, true, true)
|
164
|
+
|
165
|
+
@buffer_view = Gtk::TextView.new
|
166
|
+
@buffer_view.editable = false
|
167
|
+
@buffer_view.cursor_visible = false
|
168
|
+
@buffer_view.wrap_mode = Gtk::TextTag::WRAP_WORD
|
169
|
+
@buffer_view.modify_font(Pango::FontDescription.new('monospace 12'))
|
170
|
+
@buffer_view.show
|
171
|
+
@buffer_scroll.add_with_viewport(@buffer_view)
|
172
|
+
|
173
|
+
roster_scroll = Gtk::ScrolledWindow.new
|
174
|
+
roster_scroll.show
|
175
|
+
roster_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
|
176
|
+
layout_mid.pack2(roster_scroll, true, true)
|
177
|
+
|
178
|
+
@roster = Gtk::ListStore.new(String)
|
179
|
+
@roster.set_sort_column_id(0)
|
180
|
+
roster_view = Gtk::TreeView.new(@roster)
|
181
|
+
roster_view.append_column Gtk::TreeViewColumn.new("Participant", Gtk::CellRendererText.new, {:text => 0})
|
182
|
+
roster_view.show
|
183
|
+
roster_scroll.add_with_viewport(roster_view)
|
184
|
+
|
185
|
+
@input = Gtk::Entry.new
|
186
|
+
@input.grab_focus
|
187
|
+
@input.signal_connect("activate") {
|
188
|
+
on_input(@input.text)
|
189
|
+
@input.text = ''
|
190
|
+
}
|
191
|
+
@input.show
|
192
|
+
layout.pack_start(@input, false, false, 2)
|
193
|
+
|
194
|
+
layout.show
|
195
|
+
add(layout)
|
196
|
+
|
197
|
+
print_buffer "Welcome to the XMPP4R sample GTK2 Multi-User Chat client"
|
198
|
+
print_buffer "Commands start with a slash, type \"/help\" for a list"
|
199
|
+
|
200
|
+
@client = Jabber::Client.new(jid)
|
201
|
+
Jabber::Version::SimpleResponder.new(@client, "XMPP4R example: GtkMUCClient", Jabber::XMPP4R_VERSION, IO.popen("uname -sr").readlines.to_s.strip)
|
202
|
+
Thread.new {
|
203
|
+
begin
|
204
|
+
print_buffer "Connecting for domain #{jid.domain}..."
|
205
|
+
@client.connect
|
206
|
+
print_buffer "Authenticating for #{jid.strip}..."
|
207
|
+
@client.auth(password)
|
208
|
+
print_buffer "Attempting to join #{mucjid.strip} as #{mucjid.resource}..."
|
209
|
+
@muc = Jabber::MUC::SimpleMUCClient.new(@client)
|
210
|
+
register_handlers
|
211
|
+
@muc.join(mucjid)
|
212
|
+
rescue Exception => e
|
213
|
+
puts "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
|
214
|
+
print_buffer("Error: #{e}")
|
215
|
+
end
|
216
|
+
}
|
217
|
+
|
218
|
+
set_size_request(600, 400)
|
219
|
+
end
|
220
|
+
|
221
|
+
def print_buffer(s, time=nil)
|
222
|
+
@buffer_view.buffer.insert(@buffer_view.buffer.end_iter, "[#{(time || Time.new).getlocal.strftime('%I:%M')}] #{s}\n")
|
223
|
+
va = @buffer_scroll.vadjustment
|
224
|
+
va.value = va.upper
|
225
|
+
end
|
226
|
+
|
227
|
+
def register_handlers
|
228
|
+
@muc.on_room_message { |time,text|
|
229
|
+
print_buffer("*** #{text}", time)
|
230
|
+
}
|
231
|
+
@muc.on_message { |time,nick,text|
|
232
|
+
if text =~ /^\/me (.+)$/
|
233
|
+
print_buffer("*#{nick} #{$1}", time)
|
234
|
+
else
|
235
|
+
print_buffer("<#{nick}> #{text}", time)
|
236
|
+
end
|
237
|
+
}
|
238
|
+
@muc.on_private_message { |time,nick,text|
|
239
|
+
print_buffer("<-(#{nick}) #{text}", time)
|
240
|
+
}
|
241
|
+
@muc.on_join { |time,nick|
|
242
|
+
@roster.append[0] = nick
|
243
|
+
}
|
244
|
+
@muc.on_self_leave { |time|
|
245
|
+
print_buffer("You have exited the room", time)
|
246
|
+
}
|
247
|
+
@muc.on_leave { |time,nick|
|
248
|
+
del_iter = nil
|
249
|
+
@roster.each { |m,p,iter|
|
250
|
+
del_iter = iter if iter[0] == nick
|
251
|
+
}
|
252
|
+
@roster.remove(del_iter) if del_iter
|
253
|
+
}
|
254
|
+
@muc.on_subject { |time,nick,subject|
|
255
|
+
@topic.text = subject
|
256
|
+
}
|
257
|
+
end
|
258
|
+
|
259
|
+
def on_input(line)
|
260
|
+
commands = {
|
261
|
+
'help' => [
|
262
|
+
'Display this help',
|
263
|
+
lambda {
|
264
|
+
commands.each { |cmd,a|
|
265
|
+
print_buffer "/#{cmd.ljust(10)} - #{a[0]}"
|
266
|
+
}
|
267
|
+
}
|
268
|
+
],
|
269
|
+
'msg' => [
|
270
|
+
'Send a private message to a user',
|
271
|
+
lambda { |args|
|
272
|
+
# Limitation: it is not possible to send private messages
|
273
|
+
# to a user with a space in his nickname
|
274
|
+
to = args.shift
|
275
|
+
text = args.join(' ')
|
276
|
+
@muc.say(text, to)
|
277
|
+
print_buffer "->(#{to}) #{text}"
|
278
|
+
}
|
279
|
+
],
|
280
|
+
'subject' => [
|
281
|
+
'Change the room\'s subject',
|
282
|
+
lambda { |args|
|
283
|
+
@muc.subject = args.join(' ')
|
284
|
+
}
|
285
|
+
],
|
286
|
+
'quit' => [
|
287
|
+
'Leave room with optional message, then disconnect client and shut down',
|
288
|
+
lambda { |args|
|
289
|
+
@muc.exit(args.join(' ')) if @muc.active?
|
290
|
+
@client.close
|
291
|
+
Gtk.main_quit
|
292
|
+
}
|
293
|
+
]
|
294
|
+
}
|
295
|
+
|
296
|
+
if line =~ /^\//
|
297
|
+
args = line.split(/ /)
|
298
|
+
cmd = args.shift[1..-1].downcase
|
299
|
+
|
300
|
+
command = commands[cmd]
|
301
|
+
if command
|
302
|
+
help, func = command
|
303
|
+
func.call(args)
|
304
|
+
else
|
305
|
+
print_buffer "Unknown command: #{cmd}, use \"/help\""
|
306
|
+
end
|
307
|
+
else
|
308
|
+
@muc.say(line)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
Gtk.init
|
314
|
+
SetupWindow.new.show
|
315
|
+
Gtk.main
|