jabber4r-revive 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .rvmrc
2
+
3
+ tmp/
4
+ pkg/
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format progress
3
+ --order random
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ branches:
6
+ only:
7
+ - master
8
+ script: bundle exec rspec
data/CHANGELOG ADDED
@@ -0,0 +1,45 @@
1
+
2
+ v0.9.0
3
+ - 2013/06/26: feature(changelog) added changelog file (Strech (aka Sergey Fedorov))
4
+ - 2013/06/26: Jabber::BoshSession : Modified to_json method (Strech (aka Sergey Fedorov))
5
+ - 2013/06/25: Jabber::BoshSession : XMPP over BOSH (XEP-0206) (Strech (aka Sergey Fedorov))
6
+ - 2013/06/20: Jabber::Connection : Change method parse_failure (Strech (aka Sergey Fedorov))
7
+ - 2013/06/20: Jabber::Connection : Refactoring (Strech (aka Sergey Fedorov))
8
+ - 2013/06/20: Rspec : Socket mock changed. Jabber::Connection : Specs for #send (Strech (aka Sergey Fedorov))
9
+ - 2013/06/20: Rspec : Change rspec dummy text (Strech (aka Sergey Fedorov))
10
+ - 2013/06/20: Jabber::Debugger : Added (Strech (aka Sergey Fedorov))
11
+ - 2013/06/20: Jabber : Moved up on one level (Strech (aka Sergey Fedorov))
12
+ - 2013/06/20: Jabber::Connection : add_filter and remove_filter refactoring (Strech (aka Sergey Fedorov))
13
+ - 2013/06/20: F (Strech (aka Sergey Fedorov))
14
+ - 2013/06/20: F (Strech (aka Sergey Fedorov))
15
+ - 2013/06/19: Jabber::Connection : New method force_close! added (Strech (aka Sergey Fedorov))
16
+ - 2013/06/19: Jabber::Connection : Added :end_document listener (Strech (aka Sergey Fedorov))
17
+ - 2013/06/07: Jabber::Protocol::Connection : Fix misstype (Strech (aka Sergey Fedorov))
18
+ - 2013/06/07: Jabber : Added missing requires (Strech (aka Sergey Fedorov))
19
+ - 2013/06/07: Jabber::JID : Specs for same?, ::to_jid methods (Strech (aka Sergey Fedorov))
20
+ - 2013/06/07: Jabber::JID : Specs for hash, ==, strip! methods (Strech (aka Sergey Fedorov))
21
+ - 2013/06/07: Jabber::JID : Specs for to_s method. Jid regexp (Strech (aka Sergey Fedorov))
22
+ - 2013/06/07: CI : TravisCI config updated (Strech (aka Sergey Fedorov))
23
+ - 2013/06/07: CI : TravisCI config updated (Strech (aka Sergey Fedorov))
24
+ - 2013/06/07: CI : TravisCI config updated (Strech (aka Sergey Fedorov))
25
+ - 2013/06/07: CI : TravisCI config added (Strech (aka Sergey Fedorov))
26
+ - 2013/06/07: Update README.md (Sergey Fedorov)
27
+ - 2013/06/07: Jabber::Protocol : Methods send and receive sync by mutex. Some part of refactoring (Strech (aka Sergey Fedorov))
28
+ - 2013/06/07: Jabber::Protocol : Class methods refactoring. Split subclasses (Strech (aka Sergey Fedorov))
29
+ - 2013/06/06: Jabber::Protocol : Class refactoring (Strech (aka Sergey Fedorov))
30
+ - 2013/06/04: Jabber::JID : Strip method added (Strech (aka Sergey Fedorov))
31
+ - 2013/06/04: Jabber::Protocol::Iq : Class method from_element refactoring (Strech (aka Sergey Fedorov))
32
+ - 2013/06/04: Jabber::Protocol::Iq : Replace class name to self (Strech (aka Sergey Fedorov))
33
+ - 2013/06/04: Update README.md (Sergey Fedorov)
34
+ - 2013/06/04: Update README.md (Sergey Fedorov)
35
+ - 2013/06/04: Jabber::Protocol::Iq : Send method refactoring (Strech (aka Sergey Fedorov))
36
+ - 2013/06/04: Jabber::JID : Tomdoc (Strech (aka Sergey Fedorov))
37
+ - 2013/06/04: Jabber::JID : Rspec specs added. Refactoring (Strech (aka Sergey Fedorov))
38
+ - 2013/06/04: Gem: Rspec gem dependency added (Strech (aka Sergey Fedorov))
39
+ - 2013/06/03: Update .gitignore (Strech (aka Sergey Fedorov))
40
+ - 2013/06/03: Jabber::Protocol::Iq : Misstype fixed. Trailing spaces removed (Strech (aka Sergey Fedorov))
41
+ - 2013/06/03: Rename LICENSE.txt to LICENSE (Sergey Fedorov)
42
+ - 2013/06/03: Update README.md (Sergey Fedorov)
43
+
44
+ v0.8.0
45
+ - 2013/06/03: Initial commit (Strech (aka Sergey Fedorov))
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,45 @@
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
data/LICENSE ADDED
@@ -0,0 +1,12 @@
1
+ Copyright (c) 2002, Rich Kilmer (rich@infoether.com)
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
+
6
+ Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7
+
8
+ Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9
+
10
+ The name Rich Kilmer may not be used to endorse or promote products derived from this software without specific prior written permission.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Jabber4r (revive)
2
+
3
+ Original [README](http://rubydoc.info/gems/jabber4r/file/README) and original [jabber4r web-site](http://jabber4r.rubyforge.org/)
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'jabber4r-revive'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install jabber4r-revive
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,71 @@
1
+ # coding: utf-8
2
+
3
+ require "bundler/gem_tasks"
4
+ require "pty"
5
+
6
+ # ============================== Support =======================================
7
+
8
+ ROOT_PATH = File.expand_path("..", __FILE__)
9
+ VERSION_PATH = File.join(ROOT_PATH, "lib", "jabber4r", "version.rb")
10
+ CHANGELOG_PATH = File.join(ROOT_PATH, "CHANGELOG")
11
+
12
+ # get current version from version.rb file
13
+ def current_version
14
+ version = File.read(VERSION_PATH).gsub(/[^\d\.]+/, "").strip.chomp
15
+ end
16
+
17
+ # get released version from git
18
+ def released_version
19
+ /\Av([\d\.]+)\z/ === `git describe --tags --abbrev=0 2>/dev/null || echo 'v0.0.0'`.chomp.strip
20
+
21
+ $1
22
+ end
23
+
24
+ # run +cmd+ in subprocess, redirect its stdout to parent's stdout
25
+ def spawn(cmd, stdout = STDOUT)
26
+ puts ">> #{cmd}"
27
+
28
+ cmd += ' 2>&1'
29
+ PTY.spawn cmd do |r, w, pid|
30
+ begin
31
+ r.sync
32
+ r.each_char { |chr| stdout.write(chr) }
33
+ rescue Errno::EIO => e
34
+ # simply ignoring this
35
+ ensure
36
+ ::Process.wait pid
37
+ end
38
+ end
39
+ abort "#{cmd} failed" unless $? && $?.exitstatus == 0
40
+ end
41
+
42
+ # =============================== Tasks ========================================
43
+
44
+ namespace :version do
45
+ task :current do
46
+ puts current_version
47
+ end
48
+
49
+ desc "Release new version"
50
+ task release: [:changelog, :commit, :tag]
51
+
52
+ desc "Add new version to git repo"
53
+ task :commit do
54
+ spawn "git add '#{VERSION_PATH}'"
55
+ spawn "git diff --cached --exit-code > /dev/null || git commit -m \"Release #{current_version}\" || echo -n"
56
+ end
57
+
58
+ desc "Add git tag for new version"
59
+ task :tag do
60
+ spawn "git tag v#{current_version}"
61
+ end
62
+
63
+ desc "Generate file CHANGELOG"
64
+ task :changelog do
65
+ spawn "changelogger changelog '#{ROOT_PATH}' --top_version='v#{current_version}' > '#{CHANGELOG_PATH}'"
66
+ spawn "git add '#{CHANGELOG_PATH}'"
67
+ end
68
+ end
69
+
70
+ desc "Show current version"
71
+ task version: "version:current"
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "jabber4r/version"
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "jabber4r-revive"
8
+ gem.version = Jabber::VERSION
9
+ gem.authors = ["Richard Kilmer", "Sergey Fedorov"]
10
+ gem.email = ["rich@infoether.com", "strech_ftf@mail.ru"]
11
+ gem.description = "The purpose of this library is to allow Ruby applications to talk to a Jabber IM system. Jabber is an open-source instant messaging service, which can be learned about at http://www.jabber.org"
12
+ gem.summary = "Read more http://jabber4r.rubyforge.org"
13
+ gem.homepage = "https://github.com/Strech/jabber4r-revive"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency "ox"
21
+
22
+ gem.add_development_dependency "rspec"
23
+ gem.add_development_dependency "webmock"
24
+ gem.add_development_dependency "changelogger"
25
+ end
@@ -0,0 +1,224 @@
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