jabber4r 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +8 -0
- data/LICENSE.txt +12 -0
- data/README +180 -0
- data/Rakefile.rb +143 -0
- data/lib/jabber4r/jabber4r.rb +22 -0
- data/lib/jabber4r/jid.rb +93 -0
- data/lib/jabber4r/protocol.rb +1384 -0
- data/lib/jabber4r/rexml_1.8_patch.rb +16 -0
- data/lib/jabber4r/roster.rb +322 -0
- data/lib/jabber4r/session.rb +615 -0
- data/lib/jabber4r/vcard.rb +42 -0
- metadata +55 -0
data/CHANGES
ADDED
data/LICENSE.txt
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
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
Jabber4R is copyrighted free software by Rich Kilmer <rich@infoether.com>
|
2
|
+
Please see LICENSE.txt for licensing information.
|
3
|
+
Version: 0.8.0
|
4
|
+
Date: August 15, 2005
|
5
|
+
|
6
|
+
==== Overview
|
7
|
+
|
8
|
+
The purpose of this library is to allow Ruby applications to talk to a Jabber IM system.
|
9
|
+
Jabber is an open-source instant messaging service, which can be learned about here.
|
10
|
+
|
11
|
+
http://www.jabber.org
|
12
|
+
|
13
|
+
An interesting facet of Jabber is its ability to represent multiple resources connecting
|
14
|
+
to a single account at the same time. One could connect to the account
|
15
|
+
account@jabber.org from home and from work and from a pda all at the same time.
|
16
|
+
Each connection is viewed as a resource. Messages can be sent to an account (and the
|
17
|
+
server will decide which resource gets it based on the resource�s priority) or to an
|
18
|
+
account+resource. The fully qualified account and resource name is:
|
19
|
+
|
20
|
+
account@host/resource
|
21
|
+
|
22
|
+
This library was created to allow a Ruby application to connect to an existing Jabber
|
23
|
+
account as an additional resource. This is not meant to be a library to create a complete
|
24
|
+
Ruby-based Jabber IM client. It currently does not support creation of accounts and
|
25
|
+
managing presence subscriptions (do that with one of the other 30 Jabber clients out
|
26
|
+
there). It was written for ease of use, not completeness. It does support:
|
27
|
+
|
28
|
+
* Account registration
|
29
|
+
* Connection to an account (digest/plain text)
|
30
|
+
* Access to Roster (buddy list)
|
31
|
+
* Tracking of presence of resources in the Roster (including local account resources)
|
32
|
+
* Sending and receiving messages
|
33
|
+
* Requesting VCards
|
34
|
+
* Managing subscriptions
|
35
|
+
|
36
|
+
What can you do with this? You could write a Ruby application that allows you to query
|
37
|
+
it by IM for status, control, etc. You could use this as a communications channel
|
38
|
+
backbone for a Ruby application (which is my intent).
|
39
|
+
|
40
|
+
==== Release Notes
|
41
|
+
|
42
|
+
* Now have rake-based building and install.
|
43
|
+
|
44
|
+
==== Usage
|
45
|
+
|
46
|
+
require 'jabber4r/jabber4r'
|
47
|
+
session = Jabber::Session.bind_digest("rich@jabber.com", "secret")
|
48
|
+
session.new_message("bob@jabber.com").set_body("ruby speak!").send
|
49
|
+
session.release
|
50
|
+
|
51
|
+
You can send and receive messages. I make use of chaining on messages so you can do this
|
52
|
+
|
53
|
+
session.add_message_listener do |message|
|
54
|
+
message.reply.set_body(�Echo: #{message.body}�).send
|
55
|
+
end
|
56
|
+
|
57
|
+
If you want to send and wait for a reply message do:
|
58
|
+
|
59
|
+
answer=session.new_chat_message("rich@jabber.com").set_body("Hello there").send(true)
|
60
|
+
|
61
|
+
Then execute:
|
62
|
+
puts answer.body
|
63
|
+
answer.reply.set_body("Thanks for the reply").send
|
64
|
+
|
65
|
+
The examples below demonstrate many features.
|
66
|
+
|
67
|
+
Please look at the doc directory (RDoc format) for detailed info on Jabber4R. The
|
68
|
+
Jabber::Session class is kind of the main thing to focus on.
|
69
|
+
|
70
|
+
I have a test directory with a single unit test file (for testing the JID class).
|
71
|
+
I will work on many more. There is also a fun echo.rb file there that you can run
|
72
|
+
to echo and messages back to the sender...and when they send 'shutdown' the session
|
73
|
+
releases.
|
74
|
+
|
75
|
+
ruby echo.rb <jabberid> <password>
|
76
|
+
|
77
|
+
You can observe roster changes, but cannot manage subscriptions (the framework is there
|
78
|
+
to do this, but it needs some work). You also cannot add an account (you must already
|
79
|
+
have one). That's in the works as well.
|
80
|
+
|
81
|
+
Have fun!
|
82
|
+
|
83
|
+
|
84
|
+
== Installation
|
85
|
+
|
86
|
+
To install, execute the following command:
|
87
|
+
|
88
|
+
> gem install jabber4r
|
89
|
+
|
90
|
+
That's it!
|
91
|
+
|
92
|
+
==== Examples
|
93
|
+
|
94
|
+
NOTE: Remember to change your account@host/resource and password to YOURs.
|
95
|
+
|
96
|
+
Connecting to an account, sending a message, and disconnecting:
|
97
|
+
|
98
|
+
require 'jabber4r/jabber4r'
|
99
|
+
begin
|
100
|
+
session = Jabber::Session.bind('account@host/resource', 'password')
|
101
|
+
session.new_message('rich_kilmer@jabber.org').set_subject('hello').set_body('This is really cool').send
|
102
|
+
rescue Exception=>error
|
103
|
+
puts error
|
104
|
+
ensure
|
105
|
+
session.release if session
|
106
|
+
end
|
107
|
+
|
108
|
+
-----------------
|
109
|
+
|
110
|
+
Connecting to an account, sending a message, waiting for a reply, and disconnecting:
|
111
|
+
|
112
|
+
require 'jabber4r/jabber4r'
|
113
|
+
begin
|
114
|
+
session = Jabber::Session.bind('account@host/resource', 'password')
|
115
|
+
#NOTE: send the first message and wait for a reply (i.e. send(true) )
|
116
|
+
message = session.new_chat_message('rich_kilmer@jabber.org').set_body('hey').send(true)
|
117
|
+
#NOTE: reply to the reply with an echo of the message, but don't wait
|
118
|
+
message.reply.set_body("You said #{message.body}").send
|
119
|
+
rescue Exception=>error
|
120
|
+
puts error
|
121
|
+
ensure
|
122
|
+
session.release if session
|
123
|
+
end
|
124
|
+
|
125
|
+
-----------------
|
126
|
+
|
127
|
+
Connecting to an account, echoing back each received message, and disconnecting
|
128
|
+
when a shutdown message is received:
|
129
|
+
|
130
|
+
|
131
|
+
require "jabber4r/jabber4r"
|
132
|
+
begin
|
133
|
+
session = Jabber::Session.bind("account@host/resource", "password")
|
134
|
+
myThread = Thread.current
|
135
|
+
mlid = session.add_message_listener do |message|
|
136
|
+
message.reply.set_body("Echo: #{message.body}").send
|
137
|
+
myThread.wakeup if message.body=="shutdown"
|
138
|
+
end
|
139
|
+
Thread.stop
|
140
|
+
session.delete_message_listener(mlid)
|
141
|
+
rescue Exception=>error
|
142
|
+
puts error
|
143
|
+
ensure
|
144
|
+
session.release if session
|
145
|
+
end
|
146
|
+
|
147
|
+
-----------------
|
148
|
+
|
149
|
+
Connecting to an account, outputting roster changes, and disconnecting when a
|
150
|
+
shutdown message is received:
|
151
|
+
|
152
|
+
require "jabber4r/jabber4r"
|
153
|
+
begin
|
154
|
+
session = Jabber::Session.bind("account@host/resource", "password")
|
155
|
+
myThread = Thread.current
|
156
|
+
#NOTE: Just like before, a 'shutdown' message stops the session
|
157
|
+
mlid = session.add_message_listener do |message|
|
158
|
+
myThread.wakeup if message.body=="shutdown"
|
159
|
+
end
|
160
|
+
listenerid = session.add_roster_listener do |event, object|
|
161
|
+
case event
|
162
|
+
when Jabber::Roster::ITEM_ADDED
|
163
|
+
puts "Added item: #{object.to_s}"
|
164
|
+
when Jabber::Roster::ITEM_DELETED
|
165
|
+
puts "Deleted item: #{object.to_s}"
|
166
|
+
when Jabber::Roster::RESOURCE_ADDED
|
167
|
+
puts "Added resource: #{object.to_s}"
|
168
|
+
when Jabber::Roster::RESOURCE_DELETED
|
169
|
+
puts "Deleted resource: #{object.to_s}"
|
170
|
+
when Jabber::Roster::RESOURCE_UPDATED
|
171
|
+
puts "Updated resource: #{object.to_s}"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
Thread.stop
|
175
|
+
rescue Exception=>error
|
176
|
+
puts error
|
177
|
+
ensure
|
178
|
+
session.release if session
|
179
|
+
end
|
180
|
+
|
data/Rakefile.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
$:.unshift('lib')
|
2
|
+
require 'rubygems'
|
3
|
+
begin
|
4
|
+
require 'xforge'
|
5
|
+
rescue LoadError
|
6
|
+
puts "**** Warning. XForge not installed. Release tasks won't work ****"
|
7
|
+
end
|
8
|
+
require 'rake/gempackagetask'
|
9
|
+
require 'rake/contrib/rubyforgepublisher'
|
10
|
+
require 'rake/clean'
|
11
|
+
require 'rake/testtask'
|
12
|
+
require 'rake/rdoctask'
|
13
|
+
|
14
|
+
PKG_NAME = "jabber4r"
|
15
|
+
|
16
|
+
PKG_VERSION = "0.8.0"
|
17
|
+
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
18
|
+
PKG_FILES = FileList[
|
19
|
+
'[A-Z]*',
|
20
|
+
'lib/**/*.rb'
|
21
|
+
]
|
22
|
+
|
23
|
+
task :default => [:gem]
|
24
|
+
|
25
|
+
Rake::TestTask.new do |t|
|
26
|
+
t.libs << "test"
|
27
|
+
t.test_files = FileList['**/*test*.rb']
|
28
|
+
t.verbose = true
|
29
|
+
end
|
30
|
+
|
31
|
+
# Create a task to build the RDOC documentation tree.
|
32
|
+
rd = Rake::RDocTask.new("rdoc") do |rdoc|
|
33
|
+
rdoc.rdoc_dir = 'html'
|
34
|
+
rdoc.title = "Jabber4r"
|
35
|
+
rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README'
|
36
|
+
rdoc.rdoc_files.include('README')
|
37
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
38
|
+
end
|
39
|
+
|
40
|
+
# ====================================================================
|
41
|
+
# Create a task that will package the Rake software into distributable
|
42
|
+
# tar, zip and gem files.
|
43
|
+
|
44
|
+
spec = Gem::Specification.new do |s|
|
45
|
+
|
46
|
+
#### Basic information.
|
47
|
+
|
48
|
+
s.name = PKG_NAME
|
49
|
+
s.version = PKG_VERSION
|
50
|
+
s.summary = "Jabber4r is a pure-Ruby Jabber client library"
|
51
|
+
s.description = <<-EOF
|
52
|
+
The purpose of this library is to allow Ruby applications to
|
53
|
+
talk to a Jabber IM system. Jabber is an open-source instant
|
54
|
+
messaging service, which can be learned about at http://www.jabber.org
|
55
|
+
EOF
|
56
|
+
|
57
|
+
s.files = PKG_FILES.to_a
|
58
|
+
s.require_path = 'lib'
|
59
|
+
|
60
|
+
#### Documentation and testing.
|
61
|
+
|
62
|
+
s.has_rdoc = true
|
63
|
+
s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$/ }.to_a
|
64
|
+
s.rdoc_options <<
|
65
|
+
'--title' << 'Jabber4r' <<
|
66
|
+
'--main' << 'README' <<
|
67
|
+
'--line-numbers'
|
68
|
+
|
69
|
+
#### Author and project details.
|
70
|
+
|
71
|
+
s.author = "Richard Kilmer"
|
72
|
+
s.email = "rich@infoether.com"
|
73
|
+
s.rubyforge_project = "jabber4r"
|
74
|
+
s.homepage = "http://jabber4r.rubyforge.org"
|
75
|
+
end
|
76
|
+
|
77
|
+
desc "Build Gem"
|
78
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
79
|
+
pkg.need_zip = true
|
80
|
+
pkg.need_tar = true
|
81
|
+
end
|
82
|
+
task :gem => [:test]
|
83
|
+
|
84
|
+
# Support Tasks ------------------------------------------------------
|
85
|
+
|
86
|
+
def egrep(pattern)
|
87
|
+
Dir['**/*.rb'].each do |fn|
|
88
|
+
count = 0
|
89
|
+
open(fn) do |f|
|
90
|
+
while line = f.gets
|
91
|
+
count += 1
|
92
|
+
if line =~ pattern
|
93
|
+
puts "#{fn}:#{count}:#{line}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
desc "Look for TODO and FIXME tags in the code"
|
101
|
+
task :todo do
|
102
|
+
egrep /#.*(FIXME|TODO|TBD)/
|
103
|
+
end
|
104
|
+
|
105
|
+
task :release => [:verify_env_vars, :release_files, :publish_doc, :publish_news]
|
106
|
+
|
107
|
+
task :verify_env_vars do
|
108
|
+
raise "RUBYFORGE_USER environment variable not set!" unless ENV['RUBYFORGE_USER']
|
109
|
+
raise "RUBYFORGE_PASSWORD environment variable not set!" unless ENV['RUBYFORGE_PASSWORD']
|
110
|
+
end
|
111
|
+
|
112
|
+
task :publish_doc => [:rdoc] do
|
113
|
+
publisher = Rake::RubyForgePublisher.new(PKG_NAME, ENV['RUBYFORGE_USER'])
|
114
|
+
publisher.upload
|
115
|
+
end
|
116
|
+
|
117
|
+
desc "Release gem to RubyForge. MAKE SURE PKG_VERSION is aligned with the CHANGELOG file"
|
118
|
+
task :release_files => [:gem] do
|
119
|
+
release_files = FileList[
|
120
|
+
"pkg/#{PKG_FILE_NAME}.gem"
|
121
|
+
]
|
122
|
+
|
123
|
+
Rake::XForge::Release.new(PKG_NAME) do |xf|
|
124
|
+
# Never hardcode user name and password in the Rakefile!
|
125
|
+
xf.user_name = ENV['RUBYFORGE_USER']
|
126
|
+
xf.password = ENV['RUBYFORGE_PASSWORD']
|
127
|
+
xf.files = release_files.to_a
|
128
|
+
xf.release_name = "Jabber4r #{PKG_VERSION}"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
desc "Publish news on RubyForge"
|
133
|
+
task :publish_news => [:gem] do
|
134
|
+
release_files = FileList[
|
135
|
+
"pkg/#{PKG_FILE_NAME}.gem"
|
136
|
+
]
|
137
|
+
|
138
|
+
Rake::XForge::NewsPublisher.new(PKG_NAME) do |news|
|
139
|
+
# Never hardcode user name and password in the Rakefile!
|
140
|
+
news.user_name = ENV['RUBYFORGE_USER']
|
141
|
+
news.password = ENV['RUBYFORGE_PASSWORD']
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# License: see LICENSE.txt
|
2
|
+
# Jabber4R - Jabber Instant Messaging Library for Ruby
|
3
|
+
# Copyright (C) 2002 Rich Kilmer <rich@infoether.com>
|
4
|
+
#
|
5
|
+
|
6
|
+
##
|
7
|
+
# The Jabber module is the main namespace for all Jabber modules
|
8
|
+
# and classes.
|
9
|
+
#
|
10
|
+
module Jabber
|
11
|
+
VERSION_MAJOR = 0
|
12
|
+
VERSION_MINOR = 6
|
13
|
+
RELEASE = 0
|
14
|
+
DEBUG = false
|
15
|
+
end
|
16
|
+
|
17
|
+
require "jabber4r/session"
|
18
|
+
require "jabber4r/protocol"
|
19
|
+
require "jabber4r/roster"
|
20
|
+
require "jabber4r/jid"
|
21
|
+
require "jabber4r/vcard"
|
22
|
+
|
data/lib/jabber4r/jid.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# License: see LICENSE.txt
|
2
|
+
# Jabber4R - Jabber Instant Messaging Library for Ruby
|
3
|
+
# Copyright (C) 2002 Rich Kilmer <rich@infoether.com>
|
4
|
+
#
|
5
|
+
|
6
|
+
module Jabber
|
7
|
+
|
8
|
+
##
|
9
|
+
# The Jabber ID class is used to hold a parsed jabber identifier (account+host+resource)
|
10
|
+
#
|
11
|
+
class JID
|
12
|
+
|
13
|
+
# The node (account)
|
14
|
+
attr_accessor :node
|
15
|
+
|
16
|
+
# The resource id
|
17
|
+
attr_accessor :resource
|
18
|
+
|
19
|
+
# The host name (or IP address)
|
20
|
+
attr_accessor :host
|
21
|
+
|
22
|
+
def JID.to_jid(id)
|
23
|
+
return id if id.kind_of? JID
|
24
|
+
return JID.new(id)
|
25
|
+
end
|
26
|
+
|
27
|
+
#@@Pattern = /([^@""'\s:]+)\@([-.\w]+)\/?(.*)/
|
28
|
+
|
29
|
+
##
|
30
|
+
# Constructs a JID from the supplied string of the format:
|
31
|
+
# node@host[/resource] (e.g. "rich_kilmer@jabber.com/laptop")
|
32
|
+
#
|
33
|
+
# id:: [String] The jabber id string to parse
|
34
|
+
#
|
35
|
+
def initialize(id)
|
36
|
+
at_loc = id.index('@')
|
37
|
+
slash_loc = id.index('/')
|
38
|
+
if at_loc.nil? and slash_loc.nil?
|
39
|
+
@host = id
|
40
|
+
end
|
41
|
+
if at_loc
|
42
|
+
@node = id[0,at_loc]
|
43
|
+
host_end = slash_loc ? slash_loc-(at_loc+1) : id.size-(at_loc+1)
|
44
|
+
@host = id[at_loc+1,host_end]
|
45
|
+
@resource = id[slash_loc+1, id.size] if slash_loc
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Evalutes whether the node, resource and host are the same
|
51
|
+
#
|
52
|
+
# other:: [Jabber::JID] The other jabber id
|
53
|
+
# return:: [Boolean] True if they match
|
54
|
+
def ==(other)
|
55
|
+
return true if other.node==@node and other.resource==@resource and other.host==@host
|
56
|
+
return false
|
57
|
+
end
|
58
|
+
|
59
|
+
def same_account?(other)
|
60
|
+
other = JID.to_jid(other)
|
61
|
+
return true if other.node==@node and other.host==@host
|
62
|
+
return false
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Removes the resource from this JID
|
67
|
+
#
|
68
|
+
def strip_resource
|
69
|
+
@resource=nil
|
70
|
+
return self
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Returns the string ("node@host/resource") representation of this JID
|
75
|
+
#
|
76
|
+
# return:: [String] String form of JID
|
77
|
+
#
|
78
|
+
def to_s
|
79
|
+
result = (@node.to_s+"@"+@host.to_s)
|
80
|
+
result += ("/"+@resource) if @resource
|
81
|
+
return result
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# Override #hash to hash based on the to_s method
|
86
|
+
#
|
87
|
+
def hash
|
88
|
+
return to_s.hash
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|