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.
- data/.gitignore +5 -4
- data/.rspec +3 -3
- data/.travis.yml +7 -7
- data/CHANGELOG +11 -1
- data/Gemfile +3 -3
- data/README.md +29 -29
- data/Rakefile +70 -70
- data/jabber4r-revive.gemspec +25 -25
- data/lib/jabber4r.rb +38 -33
- data/lib/jabber4r/bosh.rb +21 -0
- data/lib/jabber4r/bosh/authentication.rb +13 -0
- data/lib/jabber4r/bosh/authentication/non_sasl.rb +219 -0
- data/lib/jabber4r/bosh/authentication/sasl.rb +239 -0
- data/lib/jabber4r/bosh/session.rb +144 -0
- data/lib/jabber4r/connection.rb +259 -258
- data/lib/jabber4r/debugger.rb +60 -60
- data/lib/jabber4r/jid.rb +20 -19
- data/lib/jabber4r/protocol.rb +249 -257
- data/lib/jabber4r/protocol/authentication.rb +14 -0
- data/lib/jabber4r/protocol/authentication/non_sasl.rb +138 -0
- data/lib/jabber4r/protocol/authentication/sasl.rb +88 -0
- data/lib/jabber4r/protocol/iq.rb +259 -259
- data/lib/jabber4r/protocol/message.rb +245 -245
- data/lib/jabber4r/protocol/parsed_xml_element.rb +207 -207
- data/lib/jabber4r/protocol/presence.rb +160 -160
- data/lib/jabber4r/protocol/xml_element.rb +143 -143
- data/lib/jabber4r/rexml_1.8_patch.rb +15 -15
- data/lib/jabber4r/roster.rb +38 -38
- data/lib/jabber4r/session.rb +615 -615
- data/lib/jabber4r/version.rb +10 -3
- data/spec/lib/jabber4r/bosh/authentication/non_sasl_spec.rb +79 -0
- data/spec/lib/jabber4r/bosh/authentication/sasl_spec.rb +42 -0
- data/spec/lib/jabber4r/bosh/session_spec.rb +406 -0
- data/spec/lib/jabber4r/bosh_spec.rb +0 -0
- data/spec/lib/jabber4r/connection_spec.rb +174 -174
- data/spec/lib/jabber4r/debugger_spec.rb +35 -35
- data/spec/lib/jabber4r/jid_spec.rb +197 -197
- data/spec/lib/jabber4r/protocol/authentication/non_sasl_spec.rb +79 -0
- data/spec/lib/jabber4r/protocol/authentication/sasl_spec.rb +42 -0
- data/spec/spec_helper.rb +11 -11
- data/spec/support/mocks/tcp_socket_mock.rb +8 -8
- metadata +61 -45
- data/Gemfile.lock +0 -45
- data/lib/jabber4r/bosh_session.rb +0 -224
- data/spec/lib/jabber4r/bosh_session_spec.rb +0 -150
@@ -0,0 +1,79 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe Jabber::Protocol::Authentication::NonSASL do
|
5
|
+
let(:jid) { Jabber::JID.new("strech@localhost/my-resource") }
|
6
|
+
|
7
|
+
describe "#initialize" do
|
8
|
+
context "when create plain non-sasl authentication" do
|
9
|
+
let(:auth) { described_class.new(jid, "my-password") }
|
10
|
+
|
11
|
+
it { expect(auth.stream_id).to be_nil }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when jid is a String" do
|
15
|
+
let(:auth) { described_class.new("hello@localhost/my-res", "my-password") }
|
16
|
+
|
17
|
+
it { expect { auth }.not_to raise_error TypeError }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when jid is not instance of Jabber::JID or String" do
|
21
|
+
let(:auth) { described_class.new(:hello, "my-password") }
|
22
|
+
|
23
|
+
it { expect { auth }.to raise_error TypeError }
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when mechanism doesn't exists" do
|
27
|
+
let(:auth) { described_class.new("hello@localhost/my-res", "my-password", mechanism: :unknown) }
|
28
|
+
|
29
|
+
it { expect { auth }.to raise_error ArgumentError }
|
30
|
+
end
|
31
|
+
|
32
|
+
context "when mechanism is digest and no stream_id is given" do
|
33
|
+
let(:auth) { described_class.new("hello@localhost/my-res", "my-password", mechanism: :digest) }
|
34
|
+
|
35
|
+
it { expect { auth }.to raise_error KeyError }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#plain" do
|
40
|
+
let(:auth) { described_class.new(jid, "my-password") }
|
41
|
+
let(:auth_xml) { auth.dump.strip.gsub(/[\r\n]+|\s{2,}/, "") }
|
42
|
+
let(:correct_xml) do
|
43
|
+
'<iq xmlns="jabber:client" type="set" id="auth2"><query xmlns="jabber:iq:auth">' +
|
44
|
+
'<username>strech</username><password>my-password</password>' +
|
45
|
+
'<resource>my-resource</resource></query></iq>'
|
46
|
+
end
|
47
|
+
|
48
|
+
before { Jabber.stub(:gen_random_id).and_return "auth2" }
|
49
|
+
|
50
|
+
it { expect(auth_xml).to eq correct_xml }
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#digest" do
|
54
|
+
let(:auth) { described_class.new(jid, "my-password", stream_id: 1, mechanism: :digest) }
|
55
|
+
let(:auth_xml) { auth.dump.strip.gsub(/[\r\n]+|\s{2,}/, "") }
|
56
|
+
let(:correct_xml) do
|
57
|
+
'<iq xmlns="jabber:client" type="set" id="auth2"><query xmlns="jabber:iq:auth">' +
|
58
|
+
'<username>strech</username><digest>0123456789</digest>' +
|
59
|
+
'<resource>my-resource</resource></query></iq>'
|
60
|
+
end
|
61
|
+
|
62
|
+
before { Jabber.stub(:gen_random_id).and_return "auth2" }
|
63
|
+
before { described_class.stub(:generate_digest).and_return "0123456789" }
|
64
|
+
|
65
|
+
it { expect(auth_xml).to eq correct_xml }
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#plain?" do
|
69
|
+
let(:auth) { described_class.new(jid, "my-password") }
|
70
|
+
|
71
|
+
it { expect(auth).to be_plain }
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#digest?" do
|
75
|
+
let(:auth) { described_class.new(jid, "my-password", mechanism: :digest, stream_id: 1) }
|
76
|
+
|
77
|
+
it { expect(auth).to be_digest }
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe Jabber::Protocol::Authentication::SASL do
|
5
|
+
let(:jid) { Jabber::JID.new("strech@localhost/my-resource") }
|
6
|
+
|
7
|
+
describe "#initialize" do
|
8
|
+
context "when jid is a String" do
|
9
|
+
let(:auth) { described_class.new("hello@localhost/my-res", "my-password") }
|
10
|
+
|
11
|
+
it { expect { auth }.not_to raise_error TypeError }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when jid is not instance of Jabber::JID or String" do
|
15
|
+
let(:auth) { described_class.new(:hello, "my-password") }
|
16
|
+
|
17
|
+
it { expect { auth }.to raise_error TypeError }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when mechanism doesn't exists" do
|
21
|
+
let(:auth) { described_class.new("hello@localhost/my-res", "my-password", mechanism: :unknown) }
|
22
|
+
|
23
|
+
it { expect { auth }.to raise_error ArgumentError }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#plain" do
|
28
|
+
let(:auth) { described_class.new(jid, "my-password") }
|
29
|
+
let(:auth_xml) { auth.dump.strip.gsub(/[\r\n]+|\s{2,}/, "") }
|
30
|
+
let(:correct_xml) { '<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">0123456789</auth>' }
|
31
|
+
|
32
|
+
before { described_class.stub(:generate_plain).and_return "0123456789" }
|
33
|
+
|
34
|
+
it { expect(auth_xml).to eq correct_xml }
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#plain?" do
|
38
|
+
let(:auth) { described_class.new(jid, "my-password") }
|
39
|
+
|
40
|
+
it { expect(auth).to be_plain }
|
41
|
+
end
|
42
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
$LOAD_PATH.unshift File.expand_path("../../", __FILE__)
|
3
|
-
|
4
|
-
require "webmock/rspec"
|
5
|
-
|
6
|
-
require "jabber4r"
|
7
|
-
Dir["spec/support/**/*.rb"].sort.each { |f| require f }
|
8
|
-
|
9
|
-
RSpec.configure do |config|
|
10
|
-
# ... rspec options
|
11
|
-
end
|
1
|
+
# coding: utf-8
|
2
|
+
$LOAD_PATH.unshift File.expand_path("../../", __FILE__)
|
3
|
+
|
4
|
+
require "webmock/rspec"
|
5
|
+
|
6
|
+
require "jabber4r"
|
7
|
+
Dir["spec/support/**/*.rb"].sort.each { |f| require f }
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
# ... rspec options
|
11
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
# Mock of TCPSocket
|
4
|
-
class TCPSocketMock < StringIO
|
5
|
-
def to_s
|
6
|
-
rewind; read
|
7
|
-
end
|
8
|
-
end
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
# Mock of TCPSocket
|
4
|
+
class TCPSocketMock < StringIO
|
5
|
+
def to_s
|
6
|
+
rewind; read
|
7
|
+
end
|
8
|
+
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: jabber4r-revive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.10.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Richard Kilmer
|
@@ -10,72 +10,72 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-
|
13
|
+
date: 2013-07-08 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
+
name: ox
|
16
17
|
version_requirements: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
17
19
|
requirements:
|
18
|
-
- -
|
20
|
+
- - ~>
|
19
21
|
- !ruby/object:Gem::Version
|
20
|
-
version:
|
21
|
-
none: false
|
22
|
-
name: ox
|
23
|
-
type: :runtime
|
24
|
-
prerelease: false
|
22
|
+
version: 2.0.4
|
25
23
|
requirement: !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
26
25
|
requirements:
|
27
|
-
- -
|
26
|
+
- - ~>
|
28
27
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
30
|
-
|
28
|
+
version: 2.0.4
|
29
|
+
type: :runtime
|
30
|
+
prerelease: false
|
31
31
|
- !ruby/object:Gem::Dependency
|
32
|
+
name: rspec
|
32
33
|
version_requirements: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
33
35
|
requirements:
|
34
|
-
- -
|
36
|
+
- - ~>
|
35
37
|
- !ruby/object:Gem::Version
|
36
|
-
version:
|
37
|
-
none: false
|
38
|
-
name: rspec
|
39
|
-
type: :development
|
40
|
-
prerelease: false
|
38
|
+
version: 2.13.0
|
41
39
|
requirement: !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
42
41
|
requirements:
|
43
|
-
- -
|
42
|
+
- - ~>
|
44
43
|
- !ruby/object:Gem::Version
|
45
|
-
version:
|
46
|
-
|
44
|
+
version: 2.13.0
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
|
+
name: webmock
|
48
49
|
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
49
51
|
requirements:
|
50
|
-
- -
|
52
|
+
- - ~>
|
51
53
|
- !ruby/object:Gem::Version
|
52
|
-
version:
|
53
|
-
none: false
|
54
|
-
name: webmock
|
55
|
-
type: :development
|
56
|
-
prerelease: false
|
54
|
+
version: 1.11.0
|
57
55
|
requirement: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
58
57
|
requirements:
|
59
|
-
- -
|
58
|
+
- - ~>
|
60
59
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
62
|
-
|
60
|
+
version: 1.11.0
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
63
|
- !ruby/object:Gem::Dependency
|
64
|
+
name: changelogger
|
64
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
65
67
|
requirements:
|
66
|
-
- -
|
68
|
+
- - ~>
|
67
69
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
69
|
-
none: false
|
70
|
-
name: changelogger
|
71
|
-
type: :development
|
72
|
-
prerelease: false
|
70
|
+
version: 0.0.3
|
73
71
|
requirement: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
74
73
|
requirements:
|
75
|
-
- -
|
74
|
+
- - ~>
|
76
75
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
78
|
-
|
76
|
+
version: 0.0.3
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
79
|
description: The purpose of this library is to allow Ruby applications to talk to
|
80
80
|
a Jabber IM system. Jabber is an open-source instant messaging service, which can
|
81
81
|
be learned about at http://www.jabber.org
|
@@ -91,17 +91,23 @@ files:
|
|
91
91
|
- .travis.yml
|
92
92
|
- CHANGELOG
|
93
93
|
- Gemfile
|
94
|
-
- Gemfile.lock
|
95
94
|
- LICENSE
|
96
95
|
- README.md
|
97
96
|
- Rakefile
|
98
97
|
- jabber4r-revive.gemspec
|
99
98
|
- lib/jabber4r.rb
|
100
|
-
- lib/jabber4r/
|
99
|
+
- lib/jabber4r/bosh.rb
|
100
|
+
- lib/jabber4r/bosh/authentication.rb
|
101
|
+
- lib/jabber4r/bosh/authentication/non_sasl.rb
|
102
|
+
- lib/jabber4r/bosh/authentication/sasl.rb
|
103
|
+
- lib/jabber4r/bosh/session.rb
|
101
104
|
- lib/jabber4r/connection.rb
|
102
105
|
- lib/jabber4r/debugger.rb
|
103
106
|
- lib/jabber4r/jid.rb
|
104
107
|
- lib/jabber4r/protocol.rb
|
108
|
+
- lib/jabber4r/protocol/authentication.rb
|
109
|
+
- lib/jabber4r/protocol/authentication/non_sasl.rb
|
110
|
+
- lib/jabber4r/protocol/authentication/sasl.rb
|
105
111
|
- lib/jabber4r/protocol/iq.rb
|
106
112
|
- lib/jabber4r/protocol/message.rb
|
107
113
|
- lib/jabber4r/protocol/parsed_xml_element.rb
|
@@ -112,10 +118,15 @@ files:
|
|
112
118
|
- lib/jabber4r/session.rb
|
113
119
|
- lib/jabber4r/vcard.rb
|
114
120
|
- lib/jabber4r/version.rb
|
115
|
-
- spec/lib/jabber4r/
|
121
|
+
- spec/lib/jabber4r/bosh/authentication/non_sasl_spec.rb
|
122
|
+
- spec/lib/jabber4r/bosh/authentication/sasl_spec.rb
|
123
|
+
- spec/lib/jabber4r/bosh/session_spec.rb
|
124
|
+
- spec/lib/jabber4r/bosh_spec.rb
|
116
125
|
- spec/lib/jabber4r/connection_spec.rb
|
117
126
|
- spec/lib/jabber4r/debugger_spec.rb
|
118
127
|
- spec/lib/jabber4r/jid_spec.rb
|
128
|
+
- spec/lib/jabber4r/protocol/authentication/non_sasl_spec.rb
|
129
|
+
- spec/lib/jabber4r/protocol/authentication/sasl_spec.rb
|
119
130
|
- spec/spec_helper.rb
|
120
131
|
- spec/support/mocks/tcp_socket_mock.rb
|
121
132
|
homepage: https://github.com/Strech/jabber4r-revive
|
@@ -125,27 +136,32 @@ rdoc_options: []
|
|
125
136
|
require_paths:
|
126
137
|
- lib
|
127
138
|
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
none: false
|
128
140
|
requirements:
|
129
141
|
- - ! '>='
|
130
142
|
- !ruby/object:Gem::Version
|
131
143
|
version: '0'
|
132
|
-
none: false
|
133
144
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
134
146
|
requirements:
|
135
147
|
- - ! '>='
|
136
148
|
- !ruby/object:Gem::Version
|
137
149
|
version: '0'
|
138
|
-
none: false
|
139
150
|
requirements: []
|
140
151
|
rubyforge_project:
|
141
|
-
rubygems_version: 1.8.
|
152
|
+
rubygems_version: 1.8.25
|
142
153
|
signing_key:
|
143
154
|
specification_version: 3
|
144
155
|
summary: Read more http://jabber4r.rubyforge.org
|
145
156
|
test_files:
|
146
|
-
- spec/lib/jabber4r/
|
157
|
+
- spec/lib/jabber4r/bosh/authentication/non_sasl_spec.rb
|
158
|
+
- spec/lib/jabber4r/bosh/authentication/sasl_spec.rb
|
159
|
+
- spec/lib/jabber4r/bosh/session_spec.rb
|
160
|
+
- spec/lib/jabber4r/bosh_spec.rb
|
147
161
|
- spec/lib/jabber4r/connection_spec.rb
|
148
162
|
- spec/lib/jabber4r/debugger_spec.rb
|
149
163
|
- spec/lib/jabber4r/jid_spec.rb
|
164
|
+
- spec/lib/jabber4r/protocol/authentication/non_sasl_spec.rb
|
165
|
+
- spec/lib/jabber4r/protocol/authentication/sasl_spec.rb
|
150
166
|
- spec/spec_helper.rb
|
151
167
|
- spec/support/mocks/tcp_socket_mock.rb
|
data/Gemfile.lock
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
jabber4r-revive (0.9.0)
|
5
|
-
ox
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: https://rubygems.org/
|
9
|
-
specs:
|
10
|
-
addressable (2.3.4)
|
11
|
-
changelogger (0.0.3)
|
12
|
-
grit (~> 2.5.0)
|
13
|
-
thor (~> 0.16.0)
|
14
|
-
crack (0.4.0)
|
15
|
-
safe_yaml (~> 0.9.0)
|
16
|
-
diff-lcs (1.2.4)
|
17
|
-
grit (2.5.0)
|
18
|
-
diff-lcs (~> 1.1)
|
19
|
-
mime-types (~> 1.15)
|
20
|
-
posix-spawn (~> 0.3.6)
|
21
|
-
mime-types (1.23)
|
22
|
-
ox (2.0.4)
|
23
|
-
posix-spawn (0.3.6)
|
24
|
-
rspec (2.13.0)
|
25
|
-
rspec-core (~> 2.13.0)
|
26
|
-
rspec-expectations (~> 2.13.0)
|
27
|
-
rspec-mocks (~> 2.13.0)
|
28
|
-
rspec-core (2.13.1)
|
29
|
-
rspec-expectations (2.13.0)
|
30
|
-
diff-lcs (>= 1.1.3, < 2.0)
|
31
|
-
rspec-mocks (2.13.1)
|
32
|
-
safe_yaml (0.9.3)
|
33
|
-
thor (0.16.0)
|
34
|
-
webmock (1.11.0)
|
35
|
-
addressable (>= 2.2.7)
|
36
|
-
crack (>= 0.3.2)
|
37
|
-
|
38
|
-
PLATFORMS
|
39
|
-
ruby
|
40
|
-
|
41
|
-
DEPENDENCIES
|
42
|
-
changelogger
|
43
|
-
jabber4r-revive!
|
44
|
-
rspec
|
45
|
-
webmock
|
@@ -1,224 +0,0 @@
|
|
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 "ox"
|
9
|
-
require "json"
|
10
|
-
require "net/http"
|
11
|
-
require "digest/sha1"
|
12
|
-
|
13
|
-
module Jabber
|
14
|
-
# XMPP Over BOSH class
|
15
|
-
# NOTE: http://xmpp.org/extensions/xep-0206.html
|
16
|
-
class BoshSession
|
17
|
-
# Public: Default connection options
|
18
|
-
DEFAULTS = {
|
19
|
-
host: "localhost",
|
20
|
-
port: 5280,
|
21
|
-
bind_uri: "/http-bind"
|
22
|
-
}.freeze
|
23
|
-
|
24
|
-
attr_reader :stream_id
|
25
|
-
attr_reader :jid, :rid, :sid
|
26
|
-
attr_reader :host, :port, :bind_uri
|
27
|
-
|
28
|
-
# Public: Create new BOSH-session and bind it to jabber http-bind service
|
29
|
-
#
|
30
|
-
# username - String the login of jabber server user
|
31
|
-
# password - String the password of jabber server user
|
32
|
-
# options - Hash the options for jabber http-bind service (default: Empty hash)
|
33
|
-
# :host - String the jabber server host
|
34
|
-
# :port - [String|Fixnum] the port of http-bind endpoint of jabber server
|
35
|
-
# :bind_uri - String the http-bind uri
|
36
|
-
#
|
37
|
-
#
|
38
|
-
# Examples
|
39
|
-
#
|
40
|
-
# Jabber::BoshSession.bind("strech@localhost/res-1", "secret-pass")
|
41
|
-
# Jabber::BoshSession.bind("strech@localhost/res-1", "secret-pass", )
|
42
|
-
#
|
43
|
-
# Raises Jabber::AuthenticationError
|
44
|
-
# Returns Jabber::BoshSession
|
45
|
-
def self.bind(username, password, options = {})
|
46
|
-
host, port, bind_uri = DEFAULTS.dup.merge!(options).values
|
47
|
-
|
48
|
-
session = new(host, port, bind_uri)
|
49
|
-
raise AuthenticationError, "Failed to login" unless session.authenticate(username, password)
|
50
|
-
|
51
|
-
session
|
52
|
-
end
|
53
|
-
|
54
|
-
# Public: Create new BOSH-session (not binded to http-bind service)
|
55
|
-
#
|
56
|
-
# host - String the jabber server host
|
57
|
-
# port - [String|Fixnum] the port of http-bind endpoint of jabber server
|
58
|
-
# bind_uri - String the http-bind uri
|
59
|
-
#
|
60
|
-
# Examples
|
61
|
-
#
|
62
|
-
# Jabber::BoshSession.new("localhost", 5280, "/http-bind")
|
63
|
-
#
|
64
|
-
# Returns Jabber::BoshSession
|
65
|
-
def initialize(host, port, bind_uri)
|
66
|
-
@host, @port, @bind_uri = host, port, bind_uri
|
67
|
-
@alive = false
|
68
|
-
end
|
69
|
-
|
70
|
-
# Public: Authenticate user in jabber server by his username and password
|
71
|
-
# NOTE: This authentication is Non-SASL http://xmpp.org/extensions/xep-0078.html
|
72
|
-
#
|
73
|
-
# Examples
|
74
|
-
#
|
75
|
-
# bosh = Jabber::BoshSession.new ...
|
76
|
-
# bosh.authenticate("strech@localhost/my-resource", "super-secret-password") # => true
|
77
|
-
# bosh.alive? # => true
|
78
|
-
#
|
79
|
-
# Returns boolean
|
80
|
-
def authenticate(username, password)
|
81
|
-
open_new_stream
|
82
|
-
|
83
|
-
@jid = username.is_a?(JID) ? username : JID.new(username)
|
84
|
-
@alive = login(jid, password)
|
85
|
-
end
|
86
|
-
|
87
|
-
# Public: Is BOSH-session active? (no polling consider)
|
88
|
-
#
|
89
|
-
# Returns boolean
|
90
|
-
def alive?
|
91
|
-
@alive
|
92
|
-
end
|
93
|
-
|
94
|
-
# Public: Represent BOSH-session as json object
|
95
|
-
#
|
96
|
-
# Returns String
|
97
|
-
def to_json
|
98
|
-
{jid: jid.to_s, rid: rid, sid: sid}.to_json
|
99
|
-
end
|
100
|
-
|
101
|
-
private
|
102
|
-
# Internal: Send open stream command to jabber server
|
103
|
-
#
|
104
|
-
# Raises XMLMalformedError
|
105
|
-
# Returns boolean
|
106
|
-
def open_new_stream
|
107
|
-
Jabber.debug("Open stream for bosh session")
|
108
|
-
|
109
|
-
body = Ox::Element.new("body").tap do |element|
|
110
|
-
element[:xmlns] = "http://jabber.org/protocol/httpbind"
|
111
|
-
element[:content] = "text/xml; charset=utf-8"
|
112
|
-
element[:rid] = generate_next_rid
|
113
|
-
element[:to] = host
|
114
|
-
element[:secure] = true
|
115
|
-
element[:wait] = 60
|
116
|
-
element[:hold] = 1
|
117
|
-
end
|
118
|
-
|
119
|
-
response = post(Ox.dump body)
|
120
|
-
xml = Ox.parse(response.body.tr("'", '"'))
|
121
|
-
|
122
|
-
[:sid, :authid].each do |m|
|
123
|
-
raise XMLMalformedError,
|
124
|
-
"Couldn't find <body /> attribute [#{m}]" if xml[m].nil?
|
125
|
-
end
|
126
|
-
|
127
|
-
@sid, @stream_id = xml.sid, xml.authid
|
128
|
-
|
129
|
-
true
|
130
|
-
end
|
131
|
-
|
132
|
-
# Internal: Send login request to jabber server
|
133
|
-
#
|
134
|
-
# jid - Jabber::JID the jid of jabber user
|
135
|
-
# password - String the password of jabber user
|
136
|
-
#
|
137
|
-
# Raises ArgumentError
|
138
|
-
# Raises XMLMalformedError
|
139
|
-
# Returns boolean
|
140
|
-
def login(jid, password)
|
141
|
-
raise ArgumentError,
|
142
|
-
"Jabber::JID expected, but #{jid.class} was given" unless jid.is_a?(JID)
|
143
|
-
|
144
|
-
query = Ox::Element.new("query").tap do |element|
|
145
|
-
element[:xmlns] = "jabber:iq:auth"
|
146
|
-
|
147
|
-
element << (Ox::Element.new("username") << jid.node)
|
148
|
-
element << (Ox::Element.new("digest") << generate_digest_for(stream_id, password))
|
149
|
-
element << (Ox::Element.new("resource") << jid.resource)
|
150
|
-
end
|
151
|
-
|
152
|
-
iq = Ox::Element.new("iq").tap do |element|
|
153
|
-
element[:xmlns] = "jabber:client"
|
154
|
-
element[:type] = "set"
|
155
|
-
element[:id] = Jabber.gen_random_id
|
156
|
-
|
157
|
-
element << query
|
158
|
-
end
|
159
|
-
|
160
|
-
body = Ox::Element.new("body").tap do |element|
|
161
|
-
element[:xmlns] = 'http://jabber.org/protocol/httpbind'
|
162
|
-
element[:content] = "text/xml; charset=utf-8"
|
163
|
-
element[:rid] = generate_next_rid
|
164
|
-
element[:sid] = sid
|
165
|
-
|
166
|
-
element << iq
|
167
|
-
end
|
168
|
-
|
169
|
-
response = post(Ox.dump body)
|
170
|
-
xml = Ox.parse(response.body.tr("'", '"'))
|
171
|
-
|
172
|
-
raise XMLMalformedError, "Couldn't find xml tag <iq/>" if xml.locate("iq").empty?
|
173
|
-
return false unless xml.iq[:type] == "result"
|
174
|
-
|
175
|
-
@rid = body.rid
|
176
|
-
|
177
|
-
true
|
178
|
-
end
|
179
|
-
|
180
|
-
# Internal: Send HTTP-post request on HTTP-bind uri
|
181
|
-
#
|
182
|
-
# body - String data, which will be sended
|
183
|
-
#
|
184
|
-
# Examples
|
185
|
-
#
|
186
|
-
# post(%Q[<body><iq id="1"/></body>]) # => Net::HTTPSuccess
|
187
|
-
#
|
188
|
-
# Raises Net::HTTPBadResponse
|
189
|
-
# Returns Net:HttpResponse
|
190
|
-
def post(body)
|
191
|
-
request = Net::HTTP::Post.new(bind_uri)
|
192
|
-
request.body = body
|
193
|
-
request.content_length = request.body.size
|
194
|
-
request["Content-Type"] = "text/xml; charset=utf-8"
|
195
|
-
|
196
|
-
Jabber.debug("Sending POST request - #{body.strip}")
|
197
|
-
|
198
|
-
response = Net::HTTP.new(host, port).start { |http| http.request(request) }
|
199
|
-
|
200
|
-
Jabber.debug("Receiving - #{response.code}: #{response.body.inspect}")
|
201
|
-
|
202
|
-
unless response.is_a?(Net::HTTPSuccess)
|
203
|
-
raise Net::HTTPBadResponse, "Net::HTTPSuccess expected, but #{response.class} was received"
|
204
|
-
end
|
205
|
-
|
206
|
-
response
|
207
|
-
end
|
208
|
-
|
209
|
-
# Internal: Generate hex string consist of concatination of all arguments
|
210
|
-
#
|
211
|
-
# Returns String
|
212
|
-
def generate_digest_for(*args)
|
213
|
-
Digest::SHA1.hexdigest(args.join)
|
214
|
-
end
|
215
|
-
|
216
|
-
# Internal: Generate next request id for http post request
|
217
|
-
#
|
218
|
-
# Returns Fixnum
|
219
|
-
def generate_next_rid
|
220
|
-
@rid ||= rand(1_000_000_000)
|
221
|
-
@rid += 1
|
222
|
-
end
|
223
|
-
end
|
224
|
-
end
|