xrc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,37 @@
1
+ module Xrc
2
+ module Messages
3
+ class Base
4
+ # @return [REXML::Element] Raw element object
5
+ attr_reader :element
6
+
7
+ # @param [REXML::Element] element A message element
8
+ def initialize(element)
9
+ @element = element
10
+ end
11
+
12
+ # Returns a JID of message sender
13
+ # @return [String]
14
+ # @example
15
+ # message.from #=> "alice@example.com"
16
+ def from
17
+ @element.attribute("from").to_s
18
+ end
19
+
20
+ # Returns a JID of message address
21
+ # @return [String]
22
+ # @example
23
+ # message.to #=> "bob@example.com"
24
+ def to
25
+ @element.attribute("to").to_s
26
+ end
27
+
28
+ # Returns the type of the message
29
+ # @return [String]
30
+ # @example
31
+ # message.type #=> "groupchat"
32
+ def type
33
+ @element.attribute("type").to_s
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ module Xrc
2
+ module Messages
3
+ class Message < Base
4
+ # Returns the message body (e.g. Hello)
5
+ # @return [String]
6
+ # @example
7
+ # message.body #=> "Hello"
8
+ def body
9
+ @element.elements["body/text()"].to_s
10
+ end
11
+
12
+ # Returns this message in Hash format
13
+ # @return [Hash]
14
+ # @example
15
+ # message.to_hash #=> {
16
+ # :body => "bob@example.com",
17
+ # :from => "alice@example.com",
18
+ # :to => "bob@example.com",
19
+ # }
20
+ def to_hash
21
+ {
22
+ body: body,
23
+ from: from,
24
+ to: to,
25
+ }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,6 @@
1
+ module Xrc
2
+ module Messages
3
+ class Null < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Xrc
2
+ module Messages
3
+ class PrivateMessage < Message
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Xrc
2
+ module Messages
3
+ class RoomMessage < Message
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,29 @@
1
+ module Xrc
2
+ module Messages
3
+ class Subject < Base
4
+ # Returns the message subject (e.g. Room1)
5
+ # @return [String]
6
+ # @example
7
+ # message.subject #=> "Room1"
8
+ def subject
9
+ @element.elements["subject/text()"].to_s
10
+ end
11
+
12
+ # Returns this message in Hash format
13
+ # @return [Hash]
14
+ # @example
15
+ # message.to_hash #=> {
16
+ # :from => "alice@example.com",
17
+ # :subject => "Room1",
18
+ # :to => "bob@example.com",
19
+ # }
20
+ def to_hash
21
+ {
22
+ from: from,
23
+ to: to,
24
+ subject: subject,
25
+ }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ require "active_support/core_ext/module/aliasing"
2
+ require "active_support/logger"
3
+
4
+ module Xrc
5
+ module MethodLoggable
6
+ class << self
7
+ attr_writer :logger
8
+
9
+ def logger
10
+ @logger ||= ActiveSupport::Logger.new(STDOUT)
11
+ end
12
+ end
13
+
14
+ def log(method_name, &block)
15
+ define_method("#{method_name}_with_log") do |*args|
16
+ Xrc::MethodLoggable.logger.info(instance_exec(*args, &block))
17
+ __send__("#{method_name}_without_log", *args)
18
+ end
19
+ alias_method_chain method_name, :log
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ module Xrc
2
+ module Namespaces
3
+ BIND = "urn:ietf:params:xml:ns:xmpp-bind"
4
+ MUC = "http://jabber.org/protocol/muc"
5
+ PING = "urn:xmpp:ping"
6
+ ROSTER = "jabber:iq:roster"
7
+ SASL = "urn:ietf:params:xml:ns:xmpp-sasl"
8
+ SESSION = "urn:ietf:params:xml:ns:xmpp-session"
9
+ TLS = "urn:ietf:params:xml:ns:xmpp-tls"
10
+ end
11
+ end
data/lib/xrc/parser.rb ADDED
@@ -0,0 +1,89 @@
1
+ module Xrc
2
+ class Parser < REXML::Parsers::SAX2Parser
3
+ EVENTS = [
4
+ :cdata,
5
+ :characters,
6
+ :end_document,
7
+ :end_element,
8
+ :start_element,
9
+ ]
10
+
11
+ attr_accessor :current
12
+
13
+ attr_reader :block, :options
14
+
15
+ def initialize(options, &block)
16
+ super(options[:socket])
17
+ @block = block
18
+ bind
19
+ end
20
+
21
+ private
22
+
23
+ def bind
24
+ EVENTS.each do |event|
25
+ listen(event) do |*args|
26
+ send(event, *args)
27
+ end
28
+ end
29
+ end
30
+
31
+ def cdata(text)
32
+ if current
33
+ cdata = REXML::CData.new(text)
34
+ current.add(cdata)
35
+ end
36
+ end
37
+
38
+ def characters(text)
39
+ if current
40
+ text = REXML::Text.new(text, current.whitespace, nil, true)
41
+ current.add(text)
42
+ end
43
+ end
44
+
45
+ def end_document
46
+ end
47
+
48
+ def end_element(uri, localname, qname)
49
+ consume if has_current? && !has_parent?
50
+ pop
51
+ end
52
+
53
+ def start_element(uri, localname, qname, attributes)
54
+ element = REXML::Element.new(qname)
55
+ element.add_attributes(attributes)
56
+ if qname == "stream:stream"
57
+ consume(element)
58
+ else
59
+ push(element)
60
+ end
61
+ end
62
+
63
+ def push(element)
64
+ if current
65
+ self.current = current.add_element(element)
66
+ else
67
+ self.current = element
68
+ end
69
+ end
70
+
71
+ def pop
72
+ if current
73
+ self.current = current.parent
74
+ end
75
+ end
76
+
77
+ def consume(element = current)
78
+ block.call(element)
79
+ end
80
+
81
+ def has_current?
82
+ !!current
83
+ end
84
+
85
+ def has_parent?
86
+ !current.parent.nil?
87
+ end
88
+ end
89
+ end
data/lib/xrc/roster.rb ADDED
@@ -0,0 +1,28 @@
1
+ module Xrc
2
+ class Roster
3
+ # @param [REXML::Element] element An element of the response of roster requirement
4
+ def initialize(element)
5
+ @element = element
6
+ end
7
+
8
+ # Find a Xrc::User object from its JID
9
+ # @param [String] jid JID
10
+ # @return [Xrc::User]
11
+ # @return [nil]
12
+ def [](jid)
13
+ users.find {|user| user.jid == jid }
14
+ end
15
+
16
+ private
17
+
18
+ def users
19
+ @users ||= @element.elements.collect("query/item") do |item|
20
+ User.new(
21
+ jid: item.attribute("jid").to_s,
22
+ mention_name: item.attribute("mention_name").to_s,
23
+ name: item.attribute("name").to_s,
24
+ )
25
+ end
26
+ end
27
+ end
28
+ end
data/lib/xrc/socket.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Xrc
2
+ class Socket < OpenSSL::SSL::SSLSocket
3
+ def sysread(*args)
4
+ super.force_encoding(Encoding::UTF_8)
5
+ end
6
+ end
7
+ end
data/lib/xrc/user.rb ADDED
@@ -0,0 +1,27 @@
1
+ module Xrc
2
+ class User
3
+ # @option attributes [String] :jid JID
4
+ # @option attributes [String] :mention_name Mention name
5
+ # @option attributes [String] :name Full name
6
+ # @example
7
+ # Xrc::Client.new(jid: "alice@example.com", mention_name: "alice", name: "Alice Liddel")
8
+ def initialize(attributes)
9
+ @attributes = attributes
10
+ end
11
+
12
+ # @return [Xrc::Jid] JID represented in a Xrc::Jid object
13
+ def jid
14
+ @jid ||= Jid.new(@attributes[:jid])
15
+ end
16
+
17
+ # @return [String] Mention name
18
+ def mention_name
19
+ @attributes[:mention_name]
20
+ end
21
+
22
+ # @return [String] Full name
23
+ def name
24
+ @attributes[:name]
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module Xrc
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,9 @@
1
+ require "xrc"
2
+
3
+ RSpec.configure do |config|
4
+ config.treat_symbols_as_metadata_keys_with_true_values = true
5
+ config.run_all_when_everything_filtered = true
6
+ config.filter_run :focus
7
+ end
8
+
9
+ Xrc::MethodLoggable.logger.level = 2
@@ -0,0 +1,75 @@
1
+ require "spec_helper"
2
+ require "active_support/core_ext/string/strip"
3
+ require "stringio"
4
+
5
+ describe Xrc::Client do
6
+ after do
7
+ server.close
8
+ end
9
+
10
+ let!(:server) do
11
+ TCPServer.new(port)
12
+ end
13
+
14
+ let(:instance) do
15
+ described_class.new(*args)
16
+ end
17
+
18
+ let(:args) do
19
+ [options]
20
+ end
21
+
22
+ let(:options) do
23
+ {
24
+ jid: jid,
25
+ port: port,
26
+ }
27
+ end
28
+
29
+ let(:port) do
30
+ 5222
31
+ end
32
+
33
+ let(:jid) do
34
+ "#{node}@#{domain}/#{resource}"
35
+ end
36
+
37
+ let(:node) do
38
+ "alice"
39
+ end
40
+
41
+ let(:domain) do
42
+ "localhost"
43
+ end
44
+
45
+ let(:resource) do
46
+ "bot"
47
+ end
48
+
49
+ let(:socket) do
50
+ StringIO.new <<-EOS.strip_heredoc
51
+ <?xml version="1.0" encoding="UTF-8"?>
52
+ <stream:stream
53
+ from='#{domain}'
54
+ id='5d29a171a9472e73'
55
+ xmlns:stream='http://etherx.jabber.org/streams'
56
+ version='1.0'
57
+ xmlns='jabber:client'>
58
+ <stream:features>
59
+ <starttls xmlns='#{Namespaces::TLS}'/>
60
+ <required/>
61
+ </stream:features>
62
+ EOS
63
+ end
64
+
65
+ describe "#run" do
66
+ before do
67
+ pending
68
+ instance.stub(socket: socket)
69
+ end
70
+
71
+ it "parses received XML message" do
72
+ instance.run
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,35 @@
1
+ require "spec_helper"
2
+
3
+ describe Xrc::Jid do
4
+ let(:instance) do
5
+ described_class.new(*args)
6
+ end
7
+
8
+ let(:args) do
9
+ [jid]
10
+ end
11
+
12
+ let(:jid) do
13
+ "#{node}@#{domain}/#{resource}"
14
+ end
15
+
16
+ let(:node) do
17
+ "alice"
18
+ end
19
+
20
+ let(:domain) do
21
+ "example.com"
22
+ end
23
+
24
+ let(:resource) do
25
+ "bot"
26
+ end
27
+
28
+ describe "#initialize" do
29
+ it "parses node, domain, resource sections" do
30
+ instance.node.should == node
31
+ instance.domain.should == domain
32
+ instance.resource.should == resource
33
+ end
34
+ end
35
+ end