jabber4r-revive 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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