jabber4r-revive 0.9.0 → 0.10.0

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 (45) hide show
  1. data/.gitignore +5 -4
  2. data/.rspec +3 -3
  3. data/.travis.yml +7 -7
  4. data/CHANGELOG +11 -1
  5. data/Gemfile +3 -3
  6. data/README.md +29 -29
  7. data/Rakefile +70 -70
  8. data/jabber4r-revive.gemspec +25 -25
  9. data/lib/jabber4r.rb +38 -33
  10. data/lib/jabber4r/bosh.rb +21 -0
  11. data/lib/jabber4r/bosh/authentication.rb +13 -0
  12. data/lib/jabber4r/bosh/authentication/non_sasl.rb +219 -0
  13. data/lib/jabber4r/bosh/authentication/sasl.rb +239 -0
  14. data/lib/jabber4r/bosh/session.rb +144 -0
  15. data/lib/jabber4r/connection.rb +259 -258
  16. data/lib/jabber4r/debugger.rb +60 -60
  17. data/lib/jabber4r/jid.rb +20 -19
  18. data/lib/jabber4r/protocol.rb +249 -257
  19. data/lib/jabber4r/protocol/authentication.rb +14 -0
  20. data/lib/jabber4r/protocol/authentication/non_sasl.rb +138 -0
  21. data/lib/jabber4r/protocol/authentication/sasl.rb +88 -0
  22. data/lib/jabber4r/protocol/iq.rb +259 -259
  23. data/lib/jabber4r/protocol/message.rb +245 -245
  24. data/lib/jabber4r/protocol/parsed_xml_element.rb +207 -207
  25. data/lib/jabber4r/protocol/presence.rb +160 -160
  26. data/lib/jabber4r/protocol/xml_element.rb +143 -143
  27. data/lib/jabber4r/rexml_1.8_patch.rb +15 -15
  28. data/lib/jabber4r/roster.rb +38 -38
  29. data/lib/jabber4r/session.rb +615 -615
  30. data/lib/jabber4r/version.rb +10 -3
  31. data/spec/lib/jabber4r/bosh/authentication/non_sasl_spec.rb +79 -0
  32. data/spec/lib/jabber4r/bosh/authentication/sasl_spec.rb +42 -0
  33. data/spec/lib/jabber4r/bosh/session_spec.rb +406 -0
  34. data/spec/lib/jabber4r/bosh_spec.rb +0 -0
  35. data/spec/lib/jabber4r/connection_spec.rb +174 -174
  36. data/spec/lib/jabber4r/debugger_spec.rb +35 -35
  37. data/spec/lib/jabber4r/jid_spec.rb +197 -197
  38. data/spec/lib/jabber4r/protocol/authentication/non_sasl_spec.rb +79 -0
  39. data/spec/lib/jabber4r/protocol/authentication/sasl_spec.rb +42 -0
  40. data/spec/spec_helper.rb +11 -11
  41. data/spec/support/mocks/tcp_socket_mock.rb +8 -8
  42. metadata +61 -45
  43. data/Gemfile.lock +0 -45
  44. data/lib/jabber4r/bosh_session.rb +0 -224
  45. data/spec/lib/jabber4r/bosh_session_spec.rb +0 -150
@@ -0,0 +1,14 @@
1
+ # coding: utf-8
2
+
3
+ # License: see LICENSE
4
+ # Jabber4R - Jabber Instant Messaging Library for Ruby
5
+ # Copyright (C) 2002 Rich Kilmer <rich@infoether.com>
6
+ # Copyright (C) 2013 Sergey Fedorov <strech_ftf@mail.ru>
7
+
8
+ module Jabber::Protocol
9
+ # Public: This module provide authentication methods for xmpp protocol
10
+ module Authentication; end
11
+ end
12
+
13
+ require "jabber4r/protocol/authentication/non_sasl"
14
+ require "jabber4r/protocol/authentication/sasl"
@@ -0,0 +1,138 @@
1
+ # coding: utf-8
2
+
3
+ # License: see LICENSE
4
+ # Jabber4R - Jabber Instant Messaging Library for Ruby
5
+ # Copyright (C) 2002 Rich Kilmer <rich@infoether.com>
6
+ # Copyright (C) 2013 Sergey Fedorov <strech_ftf@mail.ru>
7
+
8
+ require "digest/sha1"
9
+
10
+ module Jabber::Protocol::Authentication
11
+ # Class provided Non-SASL authentication on jabber server
12
+ # http://xmpp.org/extensions/xep-0078.html
13
+ class NonSASL
14
+ MECHANISMS = [:plain, :digest].freeze
15
+
16
+ attr_reader :jid, :password
17
+ attr_reader :stream_id, :mechanism
18
+
19
+ # Public: Creates new Non-SASL authentication object
20
+ #
21
+ # jid - [Jabber::JID|String] the jid of jabber server user
22
+ # password - String the user password
23
+ # options - Hash the authentication options (default: Empty hash)
24
+ # :stream_id - String the stream identifier (authid)
25
+ # :mechanism - Symbol the name of mechnism to use
26
+ #
27
+ # Examples
28
+ #
29
+ # non_sasl = Jabber::Protocol::Authentication::NonSASL.new("strech@localhost/res-1", "my-pass-phrase")
30
+ # non_sasl.plain? # => true
31
+ # non_sasl.to_xml # =>
32
+ #
33
+ # <iq type="set" id="...">
34
+ # <query xmlns="jabber:iq:auth">
35
+ # <username>strech</username>
36
+ # <password>my-pass-phrase</password>
37
+ # <resource>res-1</resource>
38
+ # </query>
39
+ # </iq>
40
+ def initialize(jid, password, options = {})
41
+ raise TypeError,
42
+ "Class(Jabber::JID) or Class(String) expected," +
43
+ " but #{jid.class} was given" unless jid.is_a?(Jabber::JID) || jid.is_a?(String)
44
+
45
+ @jid = jid.is_a?(Jabber::JID) ? jid : Jabber::JID.new(jid)
46
+ @password = password
47
+
48
+ @mechanism = options.fetch(:mechanism, :plain)
49
+ @stream_id = options.fetch(:stream_id) if digest?
50
+
51
+ raise ArgumentError,
52
+ "Unknown authentication mechanism '#{mechanism}'," +
53
+ " available is [#{MECHANISMS * ", "}]" unless MECHANISMS.include?(mechanism)
54
+ end
55
+
56
+ # Public: Is NonSASL object is for plain authentication
57
+ #
58
+ # Returns boolean
59
+ def plain?
60
+ mechanism == :plain
61
+ end
62
+
63
+ # Public: Is NonSASL object is for digest authentication
64
+ #
65
+ # Returns boolean
66
+ def digest?
67
+ mechanism == :digest
68
+ end
69
+
70
+ # Public: Create XML string from NonSASL object
71
+ #
72
+ # Returns String
73
+ def dump
74
+ Ox.dump(send mechanism)
75
+ end
76
+ alias :to_xml :dump
77
+
78
+ # Public: Create Ox::Element from NonSASL object
79
+ #
80
+ # Returns Ox::Element
81
+ def to_ox
82
+ send(mechanism)
83
+ end
84
+
85
+ private
86
+ # Internal: Make xml object for plain authentication mechanism
87
+ #
88
+ # Returns Ox:Element
89
+ def plain
90
+ query = Ox::Element.new("query").tap do |element|
91
+ element[:xmlns] = "jabber:iq:auth"
92
+
93
+ element << (Ox::Element.new("username") << jid.node)
94
+ element << (Ox::Element.new("password") << password)
95
+ element << (Ox::Element.new("resource") << jid.resource)
96
+ end
97
+
98
+ build_iq(query)
99
+ end
100
+
101
+ # Internal: Make xml object for digest authentication mechanism
102
+ #
103
+ # Returns Ox:Element
104
+ def digest
105
+ query = Ox::Element.new("query").tap do |element|
106
+ element[:xmlns] = "jabber:iq:auth"
107
+
108
+ digest_password = self.class.generate_digest(stream_id, password)
109
+
110
+ element << (Ox::Element.new("username") << jid.node)
111
+ element << (Ox::Element.new("digest") << digest_password)
112
+ element << (Ox::Element.new("resource") << jid.resource)
113
+ end
114
+
115
+ build_iq(query)
116
+ end
117
+
118
+ # Internal: The root iq stanza for authentication
119
+ #
120
+ # Returns Ox:Element
121
+ def build_iq(query)
122
+ Ox::Element.new("iq").tap do |element|
123
+ element[:xmlns] = "jabber:client"
124
+ element[:type] = "set"
125
+ element[:id] = Jabber.gen_random_id
126
+
127
+ element << query
128
+ end
129
+ end
130
+
131
+ # Internal: Generate hex string consist of concatination stream_id and password
132
+ #
133
+ # Returns String
134
+ def self.generate_digest(stream_id, password)
135
+ Digest::SHA1.hexdigest([stream_id, password].join)
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,88 @@
1
+ # coding: utf-8
2
+
3
+ # License: see LICENSE
4
+ # Jabber4R - Jabber Instant Messaging Library for Ruby
5
+ # Copyright (C) 2002 Rich Kilmer <rich@infoether.com>
6
+ # Copyright (C) 2013 Sergey Fedorov <strech_ftf@mail.ru>
7
+
8
+ require 'base64'
9
+
10
+ module Jabber::Protocol::Authentication
11
+ # Class provided SASL authentication on jabber server
12
+ class SASL
13
+ # Full list of mechanisms
14
+ # http://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml
15
+ MECHANISMS = [:plain].freeze
16
+
17
+ attr_reader :jid, :password
18
+ attr_reader :mechanism
19
+
20
+ # Public: Creates new SASL authentication object
21
+ #
22
+ # jid - [Jabber::JID|String] the jid of jabber server user
23
+ # password - String the user password
24
+ # options - Hash the authentication options (default: Empty hash)
25
+ # :mechanism - Symbol the name of mechnism to use
26
+ #
27
+ # Examples
28
+ #
29
+ # non_sasl = Jabber::Protocol::Authentication::SASL.new("strech@localhost/res-1", "my-pass-phrase")
30
+ # non_sasl.plain? # => true
31
+ # non_sasl.to_xml # =>
32
+ #
33
+ # <auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">biwsbj1qdWxpZXQscj1vTXNUQUF3QUFBQU1BQUFBTlAwVEFBQUFBQUJQVTBBQQ==</auth>
34
+ def initialize(jid, password, options = {})
35
+ raise TypeError,
36
+ "Class(Jabber::JID) or Class(String) expected," +
37
+ " but #{jid.class} was given" unless jid.is_a?(Jabber::JID) || jid.is_a?(String)
38
+
39
+ @jid = jid.is_a?(Jabber::JID) ? jid : Jabber::JID.new(jid)
40
+ @password = password
41
+
42
+ @mechanism = options.fetch(:mechanism, :plain)
43
+
44
+ raise ArgumentError,
45
+ "Unknown authentication mechanism '#{mechanism}'," +
46
+ " available is [#{MECHANISMS * ", "}]" unless MECHANISMS.include?(mechanism)
47
+ end
48
+
49
+ # Public: Is SASL object is for plain authentication
50
+ #
51
+ # Returns boolean
52
+ def plain?
53
+ mechanism == :plain
54
+ end
55
+
56
+ # Public: Create XML string from SASL object
57
+ #
58
+ # Returns String
59
+ def dump
60
+ Ox.dump(send mechanism)
61
+ end
62
+ alias :to_xml :dump
63
+
64
+ # Public: Create Ox::Element from SASL object
65
+ #
66
+ # Returns Ox::Element
67
+ def to_ox
68
+ send(mechanism)
69
+ end
70
+
71
+ private
72
+ # Internal: Make xml object for plain authentication mechanism
73
+ #
74
+ # Returns Ox:Element
75
+ def plain
76
+ Ox::Element.new("auth").tap do |element|
77
+ element[:xmlns] = "urn:ietf:params:xml:ns:xmpp-sasl"
78
+ element[:mechanism] = "PLAIN"
79
+
80
+ element << self.class.generate_plain(jid, password)
81
+ end
82
+ end
83
+
84
+ def self.generate_plain(jid, password)
85
+ ["#{jid.strip}\x00#{jid.node}\x00#{password}"].pack("m").gsub(/\s/, "")
86
+ end
87
+ end
88
+ end
@@ -1,260 +1,260 @@
1
- # coding: utf-8
2
-
3
- # License: see LICENSE
4
- # Jabber4R - Jabber Instant Messaging Library for Ruby
5
- # Copyright (C) 2002 Rich Kilmer <rich@infoether.com>
6
-
7
- module Jabber::Protocol
8
- ##
9
- # A class used to build/parse IQ requests/responses
10
- #
11
- class Iq
12
- attr_accessor :session,:to, :from, :id, :type, :xmlns, :data,:error,:errorcode
13
- ERROR="error"
14
- GET="get"
15
- SET="set"
16
- RESULT="result"
17
-
18
- ##
19
- # Factory to build an IQ object from xml element
20
- #
21
- # session:: [Jabber::Session] The Jabber session instance
22
- # element:: [Jabber::Protocol::ParsedXMLElement] The received XML object
23
- # return:: [Jabber::Protocol::Iq] The newly created Iq object
24
- #
25
- def self.from_element(session, element)
26
- iq = new(session)
27
-
28
- iq.from = Jabber::JID.new(element.attr_from) if element.attr_from
29
- iq.to = Jabber::JID.new(element.attr_to) if element.attr_to
30
-
31
- iq.id = element.attr_id
32
- iq.type = element.attr_type
33
- iq.xmlns = element.query.attr_xmlns
34
- iq.data = element.query
35
- iq.session = session
36
-
37
- if element.attr_type = "error"
38
- iq.error = element.error
39
- iq.errorcode = element.error.attr_code
40
- end
41
-
42
- return iq
43
- end
44
-
45
- ##
46
- # Default constructor to build an Iq object
47
- # session:: [Jabber::Session] The Jabber session instance
48
- # id:: [String=nil] The (optional) id of the Iq object
49
- def initialize(session,id=nil)
50
- @session=session
51
- @id=id
52
- end
53
-
54
- ##
55
- # Return an IQ object that uses the jabber:iq:private namespace
56
- #
57
- def self.get_private(session,id,ename,ns)
58
- iq=Iq.new(session,id)
59
- iq.type="get"
60
- iq.xmlns="jabber:iq:private"
61
- iq.data=XMLElement.new(ename,{'xmlns' => ns});
62
- return iq
63
- end
64
-
65
-
66
- ##
67
- # Generates an IQ roster request XML element
68
- #
69
- # id:: [String] The message id
70
- # return:: [String] The XML data to send
71
- #
72
- def self.gen_roster(session, id)
73
- iq = Iq.new(session, id)
74
- iq.type = "get"
75
- iq.xmlns = "jabber:iq:roster"
76
- return iq
77
- #return XMLElement.new("iq", {"type"=>"get", "id"=>id}).add_child("query", {"xmlns"=>"jabber:iq:roster"}).to_s
78
- end
79
-
80
- ##
81
- # Generates an IQ authortization request XML element
82
- #
83
- # id:: [String] The message id
84
- # username:: [String] The username
85
- # password:: [String] The password
86
- # email:: [String] The email address of the account
87
- # name:: [String] The full name
88
- # return:: [String] The XML data to send
89
- #
90
- def self.gen_registration(session, id, username, password, email, name)
91
- iq = Iq.new(session, id)
92
- iq.type = "set"
93
- iq.xmlns = "jabber:iq:register"
94
- iq.data = XMLElement.new("username").add_data(username).to_s
95
- iq.data << XMLElement.new("password").add_data(password).to_s
96
- iq.data << XMLElement.new("email").add_data(email).to_s
97
- iq.data << XMLElement.new("name").add_data(name).to_s
98
- return iq
99
- end
100
-
101
- ##
102
- # Generates an IQ Roster Item add request XML element
103
- #
104
- # session:: [Session] The session
105
- # id:: [String] The message id
106
- # jid:: [JID] The Jabber ID to add to the roster
107
- # name:: [String] The full name
108
- # return:: [String] The XML data to send
109
- #
110
- def self.gen_add_rosteritem(session, id, jid, name)
111
- iq = Iq.new(session, id)
112
- iq.type = "set"
113
- iq.xmlns = "jabber:iq:roster"
114
- iq.data = XMLElement.new("item").add_attribute("jid", jid).add_attribute("name", name).to_s
115
- return iq
116
- end
117
-
118
- ##
119
- # Generates an IQ authortization request XML element
120
- #
121
- # id:: [String] The message id
122
- # username:: [String] The username
123
- # password:: [String] The password
124
- # resource:: [String] The resource to bind this session to
125
- # return:: [String] The XML data to send
126
- #
127
- def self.gen_auth(session, id, username, password, resource)
128
- iq = Iq.new(session, id)
129
- iq.type = "set"
130
- iq.xmlns = "jabber:iq:auth"
131
- iq.data = XMLElement.new("username").add_data(username).to_s
132
- iq.data << XMLElement.new("password").add_data(password).to_s
133
- iq.data << XMLElement.new("resource").add_data(resource).to_s
134
- return iq
135
- #element = XMLElement.new("iq", {"type"=>"set", "id"=>id}).add_child("query", {"xmlns"=>"jabber:iq:auth"}).add_child("username").add_data(username).to_parent.add_child("password").add_data(password).to_parent.add_child("resource").add_data(resource).to_parent.to_s
136
- end
137
-
138
- ##
139
- # Generates an IQ digest authortization request XML element
140
- #
141
- # id:: [String] The message id
142
- # username:: [String] The username
143
- # digest:: [String] The SHA-1 hash of the sessionid and the password
144
- # resource:: [String] The resource to bind this session to
145
- # return:: [String] The XML data to send
146
- #
147
- def self.gen_auth_digest(session, id, username, digest, resource)
148
- iq = Iq.new(session, id)
149
- iq.type = "set"
150
- iq.xmlns = "jabber:iq:auth"
151
- iq.data = XMLElement.new("username").add_data(username).to_s
152
- iq.data << XMLElement.new("digest").add_data(digest).to_s
153
- iq.data << XMLElement.new("resource").add_data(resource).to_s
154
- return iq
155
- #return XMLElement.new("iq", {"type"=>"set", "id"=>id}).add_child("query", {"xmlns"=>"jabber:iq:auth"}).add_child("username").add_data(username).to_parent.add_child("digest").add_data(digest).to_parent.add_child("resource").add_data(resource).to_parent.to_s
156
- end
157
-
158
- ##
159
- # Generates an IQ out of bounds XML element
160
- #
161
- # to:: [JID] The Jabber ID to send to
162
- # url:: [String] The data to send
163
- # desc:: [String=""] The description of the data
164
- # return:: [String] The XML data to send
165
- #
166
- def self.gen_oob(session, to, url, desc="")
167
- iq = Iq.new(session, nil)
168
- iq.type = "set"
169
- iq.xmlns = "jabber:iq:oob"
170
- iq.data = XMLElement.new("url").add_data(url).to_s
171
- iq.data << XMLElement.new("desc").add_data(desc).to_s
172
- return iq
173
- #return XMLElement.new("iq", {"type"=>"set"}).add_child("query", {"xmlns"=>"jabber:iq:oob"}).add_child("url").add_data(url).to_parent.add_child("desc").add_data(data).to_parent.to_s
174
- end
175
-
176
- ##
177
- # Generates an VCard request XML element
178
- #
179
- # id:: [String] The message ID
180
- # to:: [JID] The jabber id of the account to get the VCard for
181
- # return:: [String] The XML data to send
182
- #
183
- def self.gen_vcard(session, id, to)
184
- iq = Iq.new(session, id)
185
- iq.xmlns = "vcard-temp"
186
- iq.type = "get"
187
- iq.to = to
188
- return iq
189
- #return XMLElement.new("iq", {"type"=>"get", "id"=>id, "to"=>to}).add_child("query", {"xmlns"=>"vcard-temp"}).to_s
190
- end
191
-
192
-
193
-
194
-
195
- ##
196
- # Sends the IQ to the Jabber service for delivery
197
- #
198
- # wait:: [Boolean = false] Wait for reply before return?
199
- # &block:: [Block] A block to process the message replies
200
- #
201
- def send(wait=false, &block)
202
- if wait
203
- iq = nil
204
- blockedThread = Thread.current
205
- @session.connection.send(self.to_s, block) do |je|
206
- if je.element_tag == "iq" and je.attr_id == @id
207
- je.consume_element
208
- iq = self.class.from_element(@session, je)
209
- blockedThread.wakeup
210
- end
211
- end
212
- Thread.stop
213
- return iq
214
- else
215
- @session.connection.send(self.to_s, block) if @session
216
- end
217
- end
218
-
219
- ##
220
- # Builds a reply to an existing Iq
221
- #
222
- # return:: [Jabber::Protocol::Iq] The result Iq
223
- #
224
- def reply
225
- iq = Iq.new(@session,@id)
226
- iq.to = @from
227
- iq.id = @id
228
- iq.type = 'result'
229
- @is_reply = true
230
- return iq
231
- end
232
-
233
- ##
234
- # Generates XML that complies with the Jabber protocol for
235
- # sending the Iq through the Jabber service.
236
- #
237
- # return:: [String] The XML string.
238
- #
239
- def to_xml
240
- elem = XMLElement.new("iq", { "type"=>@type})
241
- elem.add_attribute("to" ,@to) if @to
242
- elem.add_attribute("id", @id) if @id
243
- elem.add_child("query").add_attribute("xmlns",@xmlns).add_data(@data.to_s)
244
- if @type=="error" then
245
- e=elem.add_child("error");
246
- e.add_attribute("code",@errorcode) if @errorcode
247
- e.add_data(@error) if @error
248
- end
249
- return elem.to_s
250
- end
251
-
252
- ##
253
- # see to_xml
254
- #
255
- def to_s
256
- to_xml
257
- end
258
-
259
- end
1
+ # coding: utf-8
2
+
3
+ # License: see LICENSE
4
+ # Jabber4R - Jabber Instant Messaging Library for Ruby
5
+ # Copyright (C) 2002 Rich Kilmer <rich@infoether.com>
6
+
7
+ module Jabber::Protocol
8
+ ##
9
+ # A class used to build/parse IQ requests/responses
10
+ #
11
+ class Iq
12
+ attr_accessor :session,:to, :from, :id, :type, :xmlns, :data,:error,:errorcode
13
+ ERROR="error"
14
+ GET="get"
15
+ SET="set"
16
+ RESULT="result"
17
+
18
+ ##
19
+ # Factory to build an IQ object from xml element
20
+ #
21
+ # session:: [Jabber::Session] The Jabber session instance
22
+ # element:: [Jabber::Protocol::ParsedXMLElement] The received XML object
23
+ # return:: [Jabber::Protocol::Iq] The newly created Iq object
24
+ #
25
+ def self.from_element(session, element)
26
+ iq = new(session)
27
+
28
+ iq.from = Jabber::JID.new(element.attr_from) if element.attr_from
29
+ iq.to = Jabber::JID.new(element.attr_to) if element.attr_to
30
+
31
+ iq.id = element.attr_id
32
+ iq.type = element.attr_type
33
+ iq.xmlns = element.query.attr_xmlns
34
+ iq.data = element.query
35
+ iq.session = session
36
+
37
+ if element.attr_type = "error"
38
+ iq.error = element.error
39
+ iq.errorcode = element.error.attr_code
40
+ end
41
+
42
+ return iq
43
+ end
44
+
45
+ ##
46
+ # Default constructor to build an Iq object
47
+ # session:: [Jabber::Session] The Jabber session instance
48
+ # id:: [String=nil] The (optional) id of the Iq object
49
+ def initialize(session,id=nil)
50
+ @session=session
51
+ @id=id
52
+ end
53
+
54
+ ##
55
+ # Return an IQ object that uses the jabber:iq:private namespace
56
+ #
57
+ def self.get_private(session,id,ename,ns)
58
+ iq=Iq.new(session,id)
59
+ iq.type="get"
60
+ iq.xmlns="jabber:iq:private"
61
+ iq.data=XMLElement.new(ename,{'xmlns' => ns});
62
+ return iq
63
+ end
64
+
65
+
66
+ ##
67
+ # Generates an IQ roster request XML element
68
+ #
69
+ # id:: [String] The message id
70
+ # return:: [String] The XML data to send
71
+ #
72
+ def self.gen_roster(session, id)
73
+ iq = Iq.new(session, id)
74
+ iq.type = "get"
75
+ iq.xmlns = "jabber:iq:roster"
76
+ return iq
77
+ #return XMLElement.new("iq", {"type"=>"get", "id"=>id}).add_child("query", {"xmlns"=>"jabber:iq:roster"}).to_s
78
+ end
79
+
80
+ ##
81
+ # Generates an IQ authortization request XML element
82
+ #
83
+ # id:: [String] The message id
84
+ # username:: [String] The username
85
+ # password:: [String] The password
86
+ # email:: [String] The email address of the account
87
+ # name:: [String] The full name
88
+ # return:: [String] The XML data to send
89
+ #
90
+ def self.gen_registration(session, id, username, password, email, name)
91
+ iq = Iq.new(session, id)
92
+ iq.type = "set"
93
+ iq.xmlns = "jabber:iq:register"
94
+ iq.data = XMLElement.new("username").add_data(username).to_s
95
+ iq.data << XMLElement.new("password").add_data(password).to_s
96
+ iq.data << XMLElement.new("email").add_data(email).to_s
97
+ iq.data << XMLElement.new("name").add_data(name).to_s
98
+ return iq
99
+ end
100
+
101
+ ##
102
+ # Generates an IQ Roster Item add request XML element
103
+ #
104
+ # session:: [Session] The session
105
+ # id:: [String] The message id
106
+ # jid:: [JID] The Jabber ID to add to the roster
107
+ # name:: [String] The full name
108
+ # return:: [String] The XML data to send
109
+ #
110
+ def self.gen_add_rosteritem(session, id, jid, name)
111
+ iq = Iq.new(session, id)
112
+ iq.type = "set"
113
+ iq.xmlns = "jabber:iq:roster"
114
+ iq.data = XMLElement.new("item").add_attribute("jid", jid).add_attribute("name", name).to_s
115
+ return iq
116
+ end
117
+
118
+ ##
119
+ # Generates an IQ authortization request XML element
120
+ #
121
+ # id:: [String] The message id
122
+ # username:: [String] The username
123
+ # password:: [String] The password
124
+ # resource:: [String] The resource to bind this session to
125
+ # return:: [String] The XML data to send
126
+ #
127
+ def self.gen_auth(session, id, username, password, resource)
128
+ iq = Iq.new(session, id)
129
+ iq.type = "set"
130
+ iq.xmlns = "jabber:iq:auth"
131
+ iq.data = XMLElement.new("username").add_data(username).to_s
132
+ iq.data << XMLElement.new("password").add_data(password).to_s
133
+ iq.data << XMLElement.new("resource").add_data(resource).to_s
134
+ return iq
135
+ #element = XMLElement.new("iq", {"type"=>"set", "id"=>id}).add_child("query", {"xmlns"=>"jabber:iq:auth"}).add_child("username").add_data(username).to_parent.add_child("password").add_data(password).to_parent.add_child("resource").add_data(resource).to_parent.to_s
136
+ end
137
+
138
+ ##
139
+ # Generates an IQ digest authortization request XML element
140
+ #
141
+ # id:: [String] The message id
142
+ # username:: [String] The username
143
+ # digest:: [String] The SHA-1 hash of the sessionid and the password
144
+ # resource:: [String] The resource to bind this session to
145
+ # return:: [String] The XML data to send
146
+ #
147
+ def self.gen_auth_digest(session, id, username, digest, resource)
148
+ iq = Iq.new(session, id)
149
+ iq.type = "set"
150
+ iq.xmlns = "jabber:iq:auth"
151
+ iq.data = XMLElement.new("username").add_data(username).to_s
152
+ iq.data << XMLElement.new("digest").add_data(digest).to_s
153
+ iq.data << XMLElement.new("resource").add_data(resource).to_s
154
+ return iq
155
+ #return XMLElement.new("iq", {"type"=>"set", "id"=>id}).add_child("query", {"xmlns"=>"jabber:iq:auth"}).add_child("username").add_data(username).to_parent.add_child("digest").add_data(digest).to_parent.add_child("resource").add_data(resource).to_parent.to_s
156
+ end
157
+
158
+ ##
159
+ # Generates an IQ out of bounds XML element
160
+ #
161
+ # to:: [JID] The Jabber ID to send to
162
+ # url:: [String] The data to send
163
+ # desc:: [String=""] The description of the data
164
+ # return:: [String] The XML data to send
165
+ #
166
+ def self.gen_oob(session, to, url, desc="")
167
+ iq = Iq.new(session, nil)
168
+ iq.type = "set"
169
+ iq.xmlns = "jabber:iq:oob"
170
+ iq.data = XMLElement.new("url").add_data(url).to_s
171
+ iq.data << XMLElement.new("desc").add_data(desc).to_s
172
+ return iq
173
+ #return XMLElement.new("iq", {"type"=>"set"}).add_child("query", {"xmlns"=>"jabber:iq:oob"}).add_child("url").add_data(url).to_parent.add_child("desc").add_data(data).to_parent.to_s
174
+ end
175
+
176
+ ##
177
+ # Generates an VCard request XML element
178
+ #
179
+ # id:: [String] The message ID
180
+ # to:: [JID] The jabber id of the account to get the VCard for
181
+ # return:: [String] The XML data to send
182
+ #
183
+ def self.gen_vcard(session, id, to)
184
+ iq = Iq.new(session, id)
185
+ iq.xmlns = "vcard-temp"
186
+ iq.type = "get"
187
+ iq.to = to
188
+ return iq
189
+ #return XMLElement.new("iq", {"type"=>"get", "id"=>id, "to"=>to}).add_child("query", {"xmlns"=>"vcard-temp"}).to_s
190
+ end
191
+
192
+
193
+
194
+
195
+ ##
196
+ # Sends the IQ to the Jabber service for delivery
197
+ #
198
+ # wait:: [Boolean = false] Wait for reply before return?
199
+ # &block:: [Block] A block to process the message replies
200
+ #
201
+ def send(wait=false, &block)
202
+ if wait
203
+ iq = nil
204
+ blockedThread = Thread.current
205
+ @session.connection.send(self.to_s, block) do |je|
206
+ if je.element_tag == "iq" and je.attr_id == @id
207
+ je.consume_element
208
+ iq = self.class.from_element(@session, je)
209
+ blockedThread.wakeup
210
+ end
211
+ end
212
+ Thread.stop
213
+ return iq
214
+ else
215
+ @session.connection.send(self.to_s, block) if @session
216
+ end
217
+ end
218
+
219
+ ##
220
+ # Builds a reply to an existing Iq
221
+ #
222
+ # return:: [Jabber::Protocol::Iq] The result Iq
223
+ #
224
+ def reply
225
+ iq = Iq.new(@session,@id)
226
+ iq.to = @from
227
+ iq.id = @id
228
+ iq.type = 'result'
229
+ @is_reply = true
230
+ return iq
231
+ end
232
+
233
+ ##
234
+ # Generates XML that complies with the Jabber protocol for
235
+ # sending the Iq through the Jabber service.
236
+ #
237
+ # return:: [String] The XML string.
238
+ #
239
+ def to_xml
240
+ elem = XMLElement.new("iq", { "type"=>@type})
241
+ elem.add_attribute("to" ,@to) if @to
242
+ elem.add_attribute("id", @id) if @id
243
+ elem.add_child("query").add_attribute("xmlns",@xmlns).add_data(@data.to_s)
244
+ if @type=="error" then
245
+ e=elem.add_child("error");
246
+ e.add_attribute("code",@errorcode) if @errorcode
247
+ e.add_data(@error) if @error
248
+ end
249
+ return elem.to_s
250
+ end
251
+
252
+ ##
253
+ # see to_xml
254
+ #
255
+ def to_s
256
+ to_xml
257
+ end
258
+
259
+ end
260
260
  end