xmpp4r 0.3 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +10 -0
- data/README +12 -4
- data/Rakefile +1 -1
- data/data/doc/xmpp4r/examples/advanced/fileserve.rb +2 -0
- data/data/doc/xmpp4r/examples/advanced/recvfile.rb +2 -0
- data/data/doc/xmpp4r/examples/basic/client.rb +2 -2
- data/data/doc/xmpp4r/examples/basic/mass_sender.rb +1 -0
- data/data/doc/xmpp4r/examples/buggy/miniedgarr_cgi.rb +1 -1
- data/lib/xmpp4r/bytestreams.rb +4 -0
- data/lib/xmpp4r/bytestreams/helper/filetransfer.rb +10 -4
- data/lib/xmpp4r/bytestreams/helper/ibb/base.rb +4 -0
- data/lib/xmpp4r/bytestreams/helper/ibb/initiator.rb +5 -1
- data/lib/xmpp4r/bytestreams/helper/ibb/target.rb +5 -1
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb +5 -1
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/initiator.rb +4 -0
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb +20 -6
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/socks5.rb +4 -0
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb +4 -0
- data/lib/xmpp4r/bytestreams/iq/si.rb +4 -0
- data/lib/xmpp4r/component.rb +1 -1
- data/lib/xmpp4r/dataforms.rb +4 -0
- data/lib/xmpp4r/delay.rb +4 -0
- data/lib/xmpp4r/discovery.rb +4 -0
- data/lib/xmpp4r/feature_negotiation.rb +4 -0
- data/lib/xmpp4r/feature_negotiation/iq/feature.rb +4 -0
- data/lib/xmpp4r/iq.rb +1 -1
- data/lib/xmpp4r/message.rb +10 -3
- data/lib/xmpp4r/muc.rb +4 -0
- data/lib/xmpp4r/muc/helper/simplemucclient.rb +4 -0
- data/lib/xmpp4r/presence.rb +9 -5
- data/lib/xmpp4r/rexmladdons.rb +65 -3
- data/lib/xmpp4r/roster.rb +4 -0
- data/lib/xmpp4r/roster/helper/roster.rb +18 -3
- data/lib/xmpp4r/sasl.rb +59 -10
- data/lib/xmpp4r/stream.rb +22 -2
- data/lib/xmpp4r/vcard.rb +4 -0
- data/lib/xmpp4r/vcard/helper/vcard.rb +4 -4
- data/lib/xmpp4r/version.rb +4 -0
- data/lib/xmpp4r/xmpp4r.rb +1 -1
- data/setup.rb +800 -575
- data/test/bytestreams/tc_socks5bytestreams.rb +46 -0
- data/test/tc_iq.rb +1 -1
- data/test/tc_rexml.rb +60 -0
- data/test/ts_xmpp4r.rb +2 -1
- data/test/vcard/tc_helper.rb +49 -0
- metadata +96 -94
- data/test/roster/.tc_helper.rb.swp +0 -0
data/ChangeLog
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
XMPP4R 0.3.1 (23/04/2007)
|
2
|
+
=========================
|
3
|
+
* SASL fixes
|
4
|
+
* Message#x and Presence#x support element selection by namespace
|
5
|
+
* Proper XML entity escaping for REXML text nodes
|
6
|
+
* Improvements to FileTransfer::Helper and SOCKS5BytestreamsServer
|
7
|
+
* Vcard::Helper fixes
|
8
|
+
* Update Digest module usage to reflect recent Ruby versions
|
9
|
+
* More documentation
|
10
|
+
|
1
11
|
XMPP4R 0.3 (20/07/2006)
|
2
12
|
=======================
|
3
13
|
* SRV lookup capability in Client#connect
|
data/README
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
XMPP4R
|
2
2
|
----------
|
3
|
-
by
|
4
|
-
|
5
|
-
|
3
|
+
by:
|
4
|
+
Lucas Nussbaum <lucas@lucas-nussbaum.net>
|
5
|
+
Stephan Maka <stephan@spaceboyz.net>
|
6
|
+
Kirill A. Shutemov <k.shutemov@gmail.com>
|
7
|
+
Yuki Mitsui
|
8
|
+
Peter Schrammel
|
9
|
+
Olli
|
10
|
+
Vojtech Vobr
|
11
|
+
Andreas Wiese
|
6
12
|
|
7
13
|
Currently, all the information is provided on
|
8
14
|
|
@@ -13,7 +19,9 @@ The integrated HTML documentation can be built with
|
|
13
19
|
rake rdoc
|
14
20
|
|
15
21
|
If you need to ask questions, feel free to ask them on the
|
16
|
-
xmpp4r-devel@gna.org mailing list.
|
22
|
+
xmpp4r-devel@gna.org mailing list. When reporting problems,
|
23
|
+
please include a protocol dump which can be enabled with:
|
24
|
+
Jabber::debug = true
|
17
25
|
|
18
26
|
XMPP4R is released under the Ruby license (see the LICENSE file), which is
|
19
27
|
compatible with the GNU GPL (see the COPYING file) via an explicit
|
data/Rakefile
CHANGED
@@ -22,7 +22,7 @@ class BasicClient
|
|
22
22
|
quit = true if line.nil?
|
23
23
|
if not quit
|
24
24
|
command, args = line.split(' ', 2)
|
25
|
-
args.chomp
|
25
|
+
args = args.to_s.chomp
|
26
26
|
# main case
|
27
27
|
case command
|
28
28
|
when 'exit'
|
@@ -52,7 +52,7 @@ class BasicClient
|
|
52
52
|
##
|
53
53
|
# connect <jid> <password>
|
54
54
|
def do_connect(args)
|
55
|
-
@jid, @password = args.split(' ',
|
55
|
+
@jid, @password = args.split(' ', 2)
|
56
56
|
@jid = JID::new(@jid)
|
57
57
|
@cl = Client::new(@jid)
|
58
58
|
@cl.connect
|
@@ -34,7 +34,7 @@ doc.root.each_element { |e|
|
|
34
34
|
elsif e.name == 'presence'
|
35
35
|
pres = Jabber::Presence.new.import(e)
|
36
36
|
|
37
|
-
if (pres.from.strip == jid) || (Digest::MD5.
|
37
|
+
if (pres.from.strip == jid) || (Digest::MD5.hexdigest(pres.from.strip.to_s) == jidhash)
|
38
38
|
if (jid == '') && !jidhash.nil?
|
39
39
|
jid = pres.from.strip
|
40
40
|
end
|
data/lib/xmpp4r/bytestreams.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
# =XMPP4R - XMPP Library for Ruby
|
2
|
+
# License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
|
3
|
+
# Website::http://home.gna.org/xmpp4r/
|
4
|
+
|
1
5
|
require 'xmpp4r/bytestreams/iq/si.rb'
|
2
6
|
require 'xmpp4r/bytestreams/iq/bytestreams.rb'
|
3
7
|
require 'xmpp4r/bytestreams/helper/ibb/base.rb'
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# =XMPP4R - XMPP Library for Ruby
|
2
|
+
# License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
|
3
|
+
# Website::http://home.gna.org/xmpp4r/
|
4
|
+
|
1
5
|
require 'callbacks'
|
2
6
|
|
3
7
|
require 'xmpp4r/bytestreams/iq/si'
|
@@ -242,8 +246,10 @@ module Jabber
|
|
242
246
|
# jid:: [JID] to send the file to
|
243
247
|
# source:: File-transfer source, implementing the FileSource interface
|
244
248
|
# desc:: [String] or [nil] Optional file description
|
249
|
+
# from:: [String] or [nil] Optional jid for components
|
245
250
|
# result:: [Bytestreams::SOCKS5BytestreamsInitiator] or [Bytestreams::IBBInitiator] or [nil]
|
246
|
-
def offer(jid, source, desc=nil)
|
251
|
+
def offer(jid, source, desc=nil, from=nil)
|
252
|
+
from = from || @my_jid || @stream.jid
|
247
253
|
session_id = Jabber::IdGenerator.instance.generate_id
|
248
254
|
|
249
255
|
offered_methods = {}
|
@@ -255,7 +261,7 @@ module Jabber
|
|
255
261
|
end
|
256
262
|
|
257
263
|
iq = Iq::new(:set, jid)
|
258
|
-
iq.from =
|
264
|
+
iq.from = from
|
259
265
|
si = iq.add(Bytestreams::IqSi.new(session_id, Bytestreams::IqSi::PROFILE_FILETRANSFER, source.mime))
|
260
266
|
|
261
267
|
file = si.add(Bytestreams::IqSiFile.new(source.filename, source.size))
|
@@ -299,9 +305,9 @@ module Jabber
|
|
299
305
|
end
|
300
306
|
|
301
307
|
if stream_method == Bytestreams::IqQueryBytestreams::NS_BYTESTREAMS and @allow_bytestreams
|
302
|
-
Bytestreams::SOCKS5BytestreamsInitiator.new(@stream, session_id,
|
308
|
+
Bytestreams::SOCKS5BytestreamsInitiator.new(@stream, session_id, from, jid)
|
303
309
|
elsif stream_method == Bytestreams::IBB::NS_IBB and @allow_ibb
|
304
|
-
Bytestreams::IBBInitiator.new(@stream, session_id,
|
310
|
+
Bytestreams::IBBInitiator.new(@stream, session_id, from, jid)
|
305
311
|
else # Target responded with a stream_method we didn't offer
|
306
312
|
eanswer = response.answer
|
307
313
|
eanswer.type = :error
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# =XMPP4R - XMPP Library for Ruby
|
2
|
+
# License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
|
3
|
+
# Website::http://home.gna.org/xmpp4r/
|
4
|
+
|
1
5
|
module Jabber
|
2
6
|
module Bytestreams
|
3
7
|
##
|
@@ -5,7 +9,7 @@ module Jabber
|
|
5
9
|
class IBBInitiator < IBB
|
6
10
|
# You may set the block-size before open
|
7
11
|
attr_accessor :block_size
|
8
|
-
|
12
|
+
|
9
13
|
##
|
10
14
|
# Open the stream to the peer,
|
11
15
|
# waits for successful result
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# =XMPP4R - XMPP Library for Ruby
|
2
|
+
# License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
|
3
|
+
# Website::http://home.gna.org/xmpp4r/
|
4
|
+
|
1
5
|
module Jabber
|
2
6
|
module Bytestreams
|
3
7
|
##
|
@@ -28,7 +32,7 @@ module Jabber
|
|
28
32
|
reply = iq.answer(false)
|
29
33
|
reply.type = :result
|
30
34
|
@stream.send(reply)
|
31
|
-
|
35
|
+
|
32
36
|
connect_lock.unlock
|
33
37
|
true
|
34
38
|
else
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# =XMPP4R - XMPP Library for Ruby
|
2
|
+
# License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
|
3
|
+
# Website::http://home.gna.org/xmpp4r/
|
4
|
+
|
1
5
|
require 'socket'
|
2
6
|
require 'thread'
|
3
7
|
require 'timeout'
|
@@ -122,7 +126,7 @@ module Jabber
|
|
122
126
|
# initiator_jid and target_jid.
|
123
127
|
# result:: [String] SHA1 hash
|
124
128
|
def stream_address
|
125
|
-
Digest::SHA1.
|
129
|
+
Digest::SHA1.hexdigest("#{@session_id}#{@initiator_jid}#{@target_jid}")
|
126
130
|
end
|
127
131
|
|
128
132
|
##
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# =XMPP4R - XMPP Library for Ruby
|
2
|
+
# License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
|
3
|
+
# Website::http://home.gna.org/xmpp4r/
|
4
|
+
|
1
5
|
module Jabber
|
2
6
|
module Bytestreams
|
3
7
|
##
|
@@ -19,12 +23,17 @@ module Jabber
|
|
19
23
|
# Will start to listen on the given TCP port and
|
20
24
|
# accept new peers
|
21
25
|
# port:: [Fixnum] TCP port to listen on
|
22
|
-
|
26
|
+
# listen_on:: [String] Optional address for the server socket to listen on (i.e. '0.0.0.0' or '::')
|
27
|
+
def initialize(port, listen_on=nil)
|
23
28
|
@port = port
|
24
29
|
@addresses = []
|
25
30
|
@peers = []
|
26
31
|
@peers_lock = Mutex.new
|
27
|
-
|
32
|
+
if listen_on
|
33
|
+
socket = TCPServer.new(listen_on, port)
|
34
|
+
else
|
35
|
+
socket = TCPServer.new(port)
|
36
|
+
end
|
28
37
|
|
29
38
|
Thread.new {
|
30
39
|
loop {
|
@@ -45,6 +54,9 @@ module Jabber
|
|
45
54
|
|
46
55
|
##
|
47
56
|
# Find the socket a peer is associated to
|
57
|
+
#
|
58
|
+
# This method also performs some housekeeping, ie. removing
|
59
|
+
# peers with closed sockets.
|
48
60
|
# addr:: [String] Address like SOCKS5Bytestreams#stream_address
|
49
61
|
# result:: [TCPSocker] or [nil]
|
50
62
|
def peer_sock(addr)
|
@@ -58,11 +70,13 @@ module Jabber
|
|
58
70
|
removes << peer
|
59
71
|
elsif peer.address == addr and res.nil?
|
60
72
|
res = peer.socket
|
61
|
-
else
|
62
|
-
# If we sent multiple addresses of our own, clients may
|
63
|
-
# connect multiple times. Close these connections here.
|
64
|
-
removes << peer
|
65
73
|
end
|
74
|
+
|
75
|
+
# If we sent multiple addresses of our own, clients may
|
76
|
+
# connect multiple times. DO NOT close any other connections
|
77
|
+
# here. These may belong to other concurrent bytestreams,
|
78
|
+
# believe that the peer will close any unneeded sockets
|
79
|
+
# which will then be picked up by the next call to peer_sock.
|
66
80
|
}
|
67
81
|
|
68
82
|
# If we sent multiple addresses of our own, clients may
|
data/lib/xmpp4r/component.rb
CHANGED
@@ -83,7 +83,7 @@ module Jabber
|
|
83
83
|
# Throws AuthenticationFailure
|
84
84
|
# secret:: [String] the shared secret
|
85
85
|
def auth(secret)
|
86
|
-
hash = Digest::SHA1::
|
86
|
+
hash = Digest::SHA1::hexdigest(@streamid.to_s + secret)
|
87
87
|
authenticated = false
|
88
88
|
send("<handshake>#{hash}</handshake>") { |r|
|
89
89
|
if r.prefix == 'stream' and r.name == 'error'
|
data/lib/xmpp4r/dataforms.rb
CHANGED
data/lib/xmpp4r/delay.rb
CHANGED
data/lib/xmpp4r/discovery.rb
CHANGED
data/lib/xmpp4r/iq.rb
CHANGED
@@ -156,7 +156,7 @@ module Jabber
|
|
156
156
|
query = IqQuery::new
|
157
157
|
query.add_namespace('jabber:iq:auth')
|
158
158
|
query.add(REXML::Element::new('username').add_text(jid.node))
|
159
|
-
query.add(REXML::Element::new('digest').add_text(Digest::SHA1.
|
159
|
+
query.add(REXML::Element::new('digest').add_text(Digest::SHA1.hexdigest(session_id + password)))
|
160
160
|
query.add(REXML::Element::new('resource').add_text(jid.resource)) if not jid.resource.nil?
|
161
161
|
iq.add(query)
|
162
162
|
iq
|
data/lib/xmpp4r/message.rb
CHANGED
@@ -82,9 +82,16 @@ module Jabber
|
|
82
82
|
end
|
83
83
|
|
84
84
|
##
|
85
|
-
# Get the first <x/> element
|
86
|
-
|
87
|
-
|
85
|
+
# Get the first <x/> element in this stanza, or nil if none found.
|
86
|
+
# namespace:: [String] Optional, find the first <x/> element having this xmlns
|
87
|
+
# result:: [REXML::Element] or nil
|
88
|
+
def x(namespace=nil)
|
89
|
+
each_element('x') { |x|
|
90
|
+
if namespace.nil? or namespace == x.namespace
|
91
|
+
return x
|
92
|
+
end
|
93
|
+
}
|
94
|
+
nil
|
88
95
|
end
|
89
96
|
|
90
97
|
##
|
data/lib/xmpp4r/muc.rb
CHANGED
data/lib/xmpp4r/presence.rb
CHANGED
@@ -94,12 +94,16 @@ module Jabber
|
|
94
94
|
end
|
95
95
|
|
96
96
|
##
|
97
|
-
# Get the first <x/> element
|
97
|
+
# Get the first <x/> element in this stanza, or nil if none found.
|
98
|
+
# namespace:: [String] Optional, find the first <x/> element having this xmlns
|
98
99
|
# result:: [REXML::Element] or nil
|
99
|
-
def x
|
100
|
-
|
101
|
-
|
102
|
-
|
100
|
+
def x(namespace=nil)
|
101
|
+
each_element('x') { |x|
|
102
|
+
if namespace.nil? or namespace == x.namespace
|
103
|
+
return x
|
104
|
+
end
|
105
|
+
}
|
106
|
+
nil
|
103
107
|
end
|
104
108
|
|
105
109
|
##
|
data/lib/xmpp4r/rexmladdons.rb
CHANGED
@@ -10,8 +10,23 @@ require 'rexml/source'
|
|
10
10
|
oldverbose = $VERBOSE
|
11
11
|
$VERBOSE = false
|
12
12
|
|
13
|
-
# REXML module. This file only adds
|
14
|
-
# ease the coding
|
13
|
+
# REXML module. This file only adds the following methods to the REXML module, to
|
14
|
+
# ease the coding:
|
15
|
+
# * replace_element_text
|
16
|
+
# * first_element
|
17
|
+
# * first_element_text
|
18
|
+
# * typed_add
|
19
|
+
# * import
|
20
|
+
# * self.import
|
21
|
+
# * delete_elements
|
22
|
+
#
|
23
|
+
# Further definitions are just copied from REXML out of Ruby-1.8.4 to solve issues
|
24
|
+
# with REXML in Ruby-1.8.2.
|
25
|
+
#
|
26
|
+
# The redefinitions of Text::normalize and Attribute#initialize address an issue
|
27
|
+
# where entities in element texts and attributes were not escaped. This modifies
|
28
|
+
# the behavious of REXML a bit but Sean Russell intends a similar behaviour for
|
29
|
+
# the future of REXML.
|
15
30
|
module REXML
|
16
31
|
# this class adds a few helper methods to REXML::Element
|
17
32
|
class Element
|
@@ -116,7 +131,8 @@ module REXML
|
|
116
131
|
@variables = {}
|
117
132
|
end
|
118
133
|
|
119
|
-
def namespaces=( namespaces
|
134
|
+
def namespaces=( namespaces )
|
135
|
+
namespaces ||= {}
|
120
136
|
Functions::namespace_context = namespaces
|
121
137
|
@namespaces = namespaces
|
122
138
|
end
|
@@ -819,6 +835,52 @@ module REXML
|
|
819
835
|
|
820
836
|
|
821
837
|
############################################################################
|
838
|
+
|
839
|
+
class Text
|
840
|
+
# Escapes all possible entities
|
841
|
+
def Text::normalize( input, doctype=nil, entity_filter=nil )
|
842
|
+
copy = input
|
843
|
+
# Doing it like this rather than in a loop improves the speed
|
844
|
+
if doctype
|
845
|
+
# Replace all ampersands that aren't part of an entity
|
846
|
+
copy = copy.gsub( EREFERENCE, '&' )
|
847
|
+
doctype.entities.each_value do |entity|
|
848
|
+
copy = copy.gsub( entity.value,
|
849
|
+
"&#{entity.name};" ) if entity.value and
|
850
|
+
not( entity_filter and entity_filter.include?(entity) )
|
851
|
+
end
|
852
|
+
else
|
853
|
+
# Replace all ampersands
|
854
|
+
copy = copy.gsub( '&', '&' )
|
855
|
+
DocType::DEFAULT_ENTITIES.each_value do |entity|
|
856
|
+
copy = copy.gsub(entity.value, "&#{entity.name};" )
|
857
|
+
end
|
858
|
+
end
|
859
|
+
copy
|
860
|
+
end
|
861
|
+
end
|
862
|
+
|
863
|
+
class Attribute
|
864
|
+
def initialize( first, second=nil, parent=nil )
|
865
|
+
@normalized = @unnormalized = @element = nil
|
866
|
+
if first.kind_of? Attribute
|
867
|
+
self.name = first.expanded_name
|
868
|
+
@value = first.value
|
869
|
+
if second.kind_of? Element
|
870
|
+
@element = second
|
871
|
+
else
|
872
|
+
@element = first.element
|
873
|
+
end
|
874
|
+
elsif first.kind_of? String
|
875
|
+
@element = parent if parent.kind_of? Element
|
876
|
+
self.name = first
|
877
|
+
@value = Text::normalize(second.to_s)
|
878
|
+
else
|
879
|
+
raise "illegal argument #{first.class.name} to Attribute constructor"
|
880
|
+
end
|
881
|
+
end
|
882
|
+
end
|
883
|
+
|
822
884
|
end
|
823
885
|
|
824
886
|
# Restore the old $VERBOSE setting
|