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.
- 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
|