jabber4r-revive 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.rspec +3 -0
- data/.travis.yml +8 -0
- data/CHANGELOG +45 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +45 -0
- data/LICENSE +12 -0
- data/README.md +29 -0
- data/Rakefile +71 -0
- data/jabber4r-revive.gemspec +25 -0
- data/lib/jabber4r/bosh_session.rb +224 -0
- data/lib/jabber4r/connection.rb +258 -0
- data/lib/jabber4r/debugger.rb +61 -0
- data/lib/jabber4r/jid.rb +125 -0
- data/lib/jabber4r/protocol/iq.rb +260 -0
- data/lib/jabber4r/protocol/message.rb +246 -0
- data/lib/jabber4r/protocol/parsed_xml_element.rb +208 -0
- data/lib/jabber4r/protocol/presence.rb +160 -0
- data/lib/jabber4r/protocol/xml_element.rb +144 -0
- data/lib/jabber4r/protocol.rb +257 -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
- data/lib/jabber4r/version.rb +3 -0
- data/lib/jabber4r.rb +33 -0
- data/spec/lib/jabber4r/bosh_session_spec.rb +150 -0
- data/spec/lib/jabber4r/connection_spec.rb +174 -0
- data/spec/lib/jabber4r/debugger_spec.rb +36 -0
- data/spec/lib/jabber4r/jid_spec.rb +198 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/support/mocks/tcp_socket_mock.rb +8 -0
- metadata +151 -0
@@ -0,0 +1,160 @@
|
|
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
|
+
|
7
|
+
module Jabber::Protocol
|
8
|
+
##
|
9
|
+
# The presence class is used to construct presence messages to
|
10
|
+
# send to the Jabber service.
|
11
|
+
#
|
12
|
+
class Presence
|
13
|
+
attr_accessor :to, :from, :id, :type
|
14
|
+
|
15
|
+
# The state to show (chat, xa, dnd, away)
|
16
|
+
attr_accessor :show
|
17
|
+
|
18
|
+
# The status message
|
19
|
+
attr_accessor :status
|
20
|
+
attr_accessor :priority
|
21
|
+
|
22
|
+
##
|
23
|
+
# Constructs a Presence object w/the supplied id
|
24
|
+
#
|
25
|
+
# id:: [String] The message ID
|
26
|
+
# show:: [String] The state to show
|
27
|
+
# status:: [String] The status message
|
28
|
+
#
|
29
|
+
def initialize(id, show=nil, status=nil)
|
30
|
+
@id = id
|
31
|
+
@show = show if show
|
32
|
+
@status = status if status
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Generate a presence object for initial presence notification
|
37
|
+
#
|
38
|
+
# id:: [String] The message ID
|
39
|
+
# show:: [String] The state to show
|
40
|
+
# status:: [String] The status message
|
41
|
+
# return:: [Jabber::Protocol::Presence] The newly created Presence object
|
42
|
+
#
|
43
|
+
def self.gen_initial(id, show=nil, status=nil)
|
44
|
+
Presence.new(id, show, status)
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Generate a presence object w/show="normal" (normal availability)
|
49
|
+
#
|
50
|
+
# id:: [String] The message ID
|
51
|
+
# status:: [String=nil] The status message
|
52
|
+
# return:: [Jabber::Protocol::Presence] The newly created Presence object
|
53
|
+
#
|
54
|
+
def self.gen_normal(id, status=nil)
|
55
|
+
Presence.new(id, "normal", status)
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# Generate a presence object w/show="chat" (free for chat)
|
60
|
+
#
|
61
|
+
# id:: [String] The message ID
|
62
|
+
# status:: [String=nil] The status message
|
63
|
+
# return:: [Jabber::Protocol::Presence] The newly created Presence object
|
64
|
+
#
|
65
|
+
def self.gen_chat(id, status=nil)
|
66
|
+
Presence.new(id, "chat", status)
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Generate a presence object w/show="xa" (extended away)
|
71
|
+
#
|
72
|
+
# id:: [String] The message ID
|
73
|
+
# status:: [String=nil] The status message
|
74
|
+
# return:: [Jabber::Protocol::Presence] The newly created Presence object
|
75
|
+
#
|
76
|
+
def self.gen_xa(id, status=nil)
|
77
|
+
Presence.new(id, "xa", status)
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Generate a presence object w/show="dnd" (do not disturb)
|
82
|
+
#
|
83
|
+
# id:: [String] The message ID
|
84
|
+
# status:: [String=nil] The status message
|
85
|
+
# return:: [Jabber::Protocol::Presence] The newly created Presence object
|
86
|
+
#
|
87
|
+
def self.gen_dnd(id, status=nil)
|
88
|
+
Presence.new(id, "dnd", status)
|
89
|
+
end
|
90
|
+
|
91
|
+
##
|
92
|
+
# Generate a presence object w/show="away" (away from resource)
|
93
|
+
#
|
94
|
+
# id:: [String] The message ID
|
95
|
+
# status:: [String=nil] The status message
|
96
|
+
# return:: [Jabber::Protocol::Presence] The newly created Presence object
|
97
|
+
#
|
98
|
+
def self.gen_away(id, status=nil)
|
99
|
+
Presence.new(id, "away", status)
|
100
|
+
end
|
101
|
+
|
102
|
+
##
|
103
|
+
# Generate a presence object w/show="unavailable" (not free for chat)
|
104
|
+
#
|
105
|
+
# id:: [String] The message ID
|
106
|
+
# status:: [String=nil] The status message
|
107
|
+
# return:: [Jabber::Protocol::Presence] The newly created Presence object
|
108
|
+
#
|
109
|
+
def self.gen_unavailable(id, status=nil)
|
110
|
+
p = Presence.new(id)
|
111
|
+
p.type="unavailable"
|
112
|
+
p
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.gen_new_subscription(to)
|
116
|
+
p = Presence.new(Jabber.gen_random_id)
|
117
|
+
p.type = "subscribe"
|
118
|
+
p.to = to
|
119
|
+
p
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.gen_accept_subscription(id, jid)
|
123
|
+
p = Presence.new(id)
|
124
|
+
p.type = "subscribed"
|
125
|
+
p.to = jid
|
126
|
+
p
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.gen_accept_unsubscription(id, jid)
|
130
|
+
p = Presence.new(id)
|
131
|
+
p.type = "unsubscribed"
|
132
|
+
p.to = jid
|
133
|
+
p
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# Generates the xml representation of this Presence object
|
138
|
+
#
|
139
|
+
# return:: [String] The presence XML message to send the Jabber service
|
140
|
+
#
|
141
|
+
def to_xml
|
142
|
+
e = XMLElement.new("presence")
|
143
|
+
e.add_attribute("id", @id) if @id
|
144
|
+
e.add_attribute("from", @from) if @from
|
145
|
+
e.add_attribute("to", @to) if @to
|
146
|
+
e.add_attribute("type", @type) if @type
|
147
|
+
e.add_child("show").add_data(@show) if @show
|
148
|
+
e.add_child("status").add_data(@status) if @status
|
149
|
+
e.add_child("priority") if @priority
|
150
|
+
e.to_s
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# see _to_xml
|
155
|
+
#
|
156
|
+
def to_s
|
157
|
+
to_xml
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,144 @@
|
|
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
|
+
|
7
|
+
module Jabber::Protocol
|
8
|
+
##
|
9
|
+
# Utility class to create valid XML strings
|
10
|
+
#
|
11
|
+
class XMLElement
|
12
|
+
|
13
|
+
# The parent XMLElement
|
14
|
+
attr_accessor :parent
|
15
|
+
|
16
|
+
##
|
17
|
+
# Construct an XMLElement for the supplied tag and attributes
|
18
|
+
#
|
19
|
+
# tag:: [String] XML tag
|
20
|
+
# attributes:: [Hash = {}] The attribute hash[attribute]=value
|
21
|
+
def initialize(tag, attributes={})
|
22
|
+
@tag = tag
|
23
|
+
@elements = []
|
24
|
+
@attributes = attributes
|
25
|
+
@data = ""
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Adds an attribute to this element
|
30
|
+
#
|
31
|
+
# attrib:: [String] The attribute name
|
32
|
+
# value:: [String] The attribute value
|
33
|
+
# return:: [Jabber::Protocol::XMLElement] self for chaining
|
34
|
+
#
|
35
|
+
def add_attribute(attrib, value)
|
36
|
+
@attributes[attrib]=value
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Adds data to this element
|
42
|
+
#
|
43
|
+
# data:: [String] The data to add
|
44
|
+
# return:: [Jabber::Protocol::XMLElement] self for chaining
|
45
|
+
#
|
46
|
+
def add_data(data)
|
47
|
+
@data += data.to_s
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Sets the namespace for this tag
|
53
|
+
#
|
54
|
+
# ns:: [String] The namespace
|
55
|
+
# return:: [Jabber::Protocol::XMLElement] self for chaining
|
56
|
+
#
|
57
|
+
def set_namespace(ns)
|
58
|
+
@tag+=":#{ns}"
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# Adds cdata to this element
|
64
|
+
#
|
65
|
+
# cdata:: [String] The cdata to add
|
66
|
+
# return:: [Jabber::Protocol::XMLElement] self for chaining
|
67
|
+
#
|
68
|
+
def add_cdata(cdata)
|
69
|
+
@data += "<![CDATA[#{cdata.to_s}]]>"
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Returns the parent element
|
75
|
+
#
|
76
|
+
# return:: [Jabber::Protocol::XMLElement] The parent XMLElement
|
77
|
+
#
|
78
|
+
def to_parent
|
79
|
+
@parent
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Adds a child to this element of the supplied tag
|
84
|
+
#
|
85
|
+
# tag:: [String] The element tag
|
86
|
+
# attributes:: [Hash = {}] The attributes hash[attribute]=value
|
87
|
+
# return:: [Jabber::Protocol::XMLElement] newly created child element
|
88
|
+
#
|
89
|
+
def add_child(tag, attributes={})
|
90
|
+
child = XMLElement.new(tag, attributes)
|
91
|
+
child.parent = self
|
92
|
+
@elements << child
|
93
|
+
return child
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Adds arbitrary XML data to this object
|
98
|
+
#
|
99
|
+
# xml:: [String] the xml to add
|
100
|
+
#
|
101
|
+
def add_xml(xml)
|
102
|
+
@xml = xml
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
# Recursively builds the XML string by traversing this element's
|
107
|
+
# children.
|
108
|
+
#
|
109
|
+
# format:: [Boolean] True to pretty-print (format) the output string
|
110
|
+
# indent:: [Integer = 0] The indent level (recursively more)
|
111
|
+
#
|
112
|
+
def to_xml(format, indent=0)
|
113
|
+
result = ""
|
114
|
+
result += " "*indent if format
|
115
|
+
result += "<#{@tag}"
|
116
|
+
@attributes.each {|attrib, value| result += (' '+attrib.to_s+'="'+value.to_s+'"') }
|
117
|
+
if @data=="" and @elements.size==0
|
118
|
+
result +="/>"
|
119
|
+
result +="\n" if format
|
120
|
+
return result
|
121
|
+
end
|
122
|
+
result += ">"
|
123
|
+
result += "\n" if format and @data==""
|
124
|
+
result += @data if @data!=""
|
125
|
+
@elements.each {|element| result+=element.to_xml(format, indent+4)}
|
126
|
+
result += @xml if not @xml.nil?
|
127
|
+
result += " "*indent if format and @data==""
|
128
|
+
result+="</#{@tag}>"
|
129
|
+
result+="\n" if format
|
130
|
+
return result
|
131
|
+
end
|
132
|
+
|
133
|
+
##
|
134
|
+
# Climbs to the top of this elements parent tree and then returns
|
135
|
+
# the to_xml XML string.
|
136
|
+
#
|
137
|
+
# return:: [String] The XML string of this element (from the topmost parent).
|
138
|
+
#
|
139
|
+
def to_s
|
140
|
+
return @parent.to_s if @parent
|
141
|
+
return to_xml(true)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,257 @@
|
|
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
|
+
|
7
|
+
require "singleton"
|
8
|
+
require "socket"
|
9
|
+
|
10
|
+
module Jabber
|
11
|
+
class JabberConnectionException < RuntimeError
|
12
|
+
attr_reader :data
|
13
|
+
|
14
|
+
def initialize(writing, data)
|
15
|
+
@writing = writing
|
16
|
+
@data = data
|
17
|
+
end
|
18
|
+
|
19
|
+
def writing?
|
20
|
+
@writing
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# The Protocol module contains helper methods for constructing
|
26
|
+
# Jabber protocol elements and classes that implement protocol
|
27
|
+
# elements.
|
28
|
+
#
|
29
|
+
module Protocol
|
30
|
+
|
31
|
+
USE_PARSER = :rexml # either :rexml or :xmlparser
|
32
|
+
|
33
|
+
##
|
34
|
+
# The parser to use for stream processing. The current
|
35
|
+
# available parsers are:
|
36
|
+
#
|
37
|
+
# * Jabber::Protocol::ExpatJabberParser uses XMLParser
|
38
|
+
# * Jabber::Protocol::REXMLJabberParser uses REXML
|
39
|
+
#
|
40
|
+
# return:: [Class] The parser class
|
41
|
+
#
|
42
|
+
def Protocol.Parser
|
43
|
+
if USE_PARSER==:xmlparser
|
44
|
+
Jabber::Protocol::ExpatJabberParser
|
45
|
+
else
|
46
|
+
Jabber::Protocol::REXMLJabberParser
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Generates an open stream XML element
|
52
|
+
#
|
53
|
+
# host:: [String] The host being connected to
|
54
|
+
# return:: [String] The XML data to send
|
55
|
+
#
|
56
|
+
def self.gen_open_stream(host)
|
57
|
+
return ('<?xml version="1.0" encoding="UTF-8" ?><stream:stream to="'+host+'" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams">')
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Generates an close stream XML element
|
62
|
+
#
|
63
|
+
# return:: [String] The XML data to send
|
64
|
+
#
|
65
|
+
def self.gen_close_stream
|
66
|
+
return "</stream:stream>"
|
67
|
+
end
|
68
|
+
|
69
|
+
if USE_PARSER == :xmlparser
|
70
|
+
require 'xmlparser'
|
71
|
+
##
|
72
|
+
# The ExpatJabberParser uses XMLParser (expat) to parse the incoming XML stream
|
73
|
+
# of the Jabber protocol and fires ParsedXMLElements at the Connection
|
74
|
+
# instance.
|
75
|
+
#
|
76
|
+
class ExpatJabberParser
|
77
|
+
|
78
|
+
# status if the parser is started
|
79
|
+
attr_reader :started
|
80
|
+
|
81
|
+
##
|
82
|
+
# Constructs a parser for the supplied stream (socket input)
|
83
|
+
#
|
84
|
+
# stream:: [IO] Socket input stream
|
85
|
+
# listener:: [#receive(ParsedXMLElement)] The listener (usually a Jabber::Protocol::Connection instance
|
86
|
+
#
|
87
|
+
def initialize(stream, listener)
|
88
|
+
@stream = stream
|
89
|
+
def @stream.gets
|
90
|
+
super(">")
|
91
|
+
end
|
92
|
+
@listener = listener
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
# Begins parsing the XML stream and does not return until
|
97
|
+
# the stream closes.
|
98
|
+
#
|
99
|
+
def parse
|
100
|
+
@started = false
|
101
|
+
|
102
|
+
parser = XMLParser.new("UTF-8")
|
103
|
+
def parser.unknownEncoding(e)
|
104
|
+
raise "Unknown encoding #{e.to_s}"
|
105
|
+
end
|
106
|
+
def parser.default
|
107
|
+
end
|
108
|
+
|
109
|
+
begin
|
110
|
+
parser.parse(@stream) do |type, name, data|
|
111
|
+
begin
|
112
|
+
case type
|
113
|
+
when XMLParser::START_ELEM
|
114
|
+
case name
|
115
|
+
when "stream:stream"
|
116
|
+
openstream = ParsedXMLElement.new(name)
|
117
|
+
data.each {|key, value| openstream.add_attribute(key, value)}
|
118
|
+
@listener.receive(openstream)
|
119
|
+
@started = true
|
120
|
+
else
|
121
|
+
if @current.nil?
|
122
|
+
@current = ParsedXMLElement.new(name.clone)
|
123
|
+
else
|
124
|
+
@current = @current.add_child(name.clone)
|
125
|
+
end
|
126
|
+
data.each {|key, value| @current.add_attribute(key.clone, value.clone)}
|
127
|
+
end
|
128
|
+
when XMLParser::CDATA
|
129
|
+
@current.append_data(data.clone) if @current
|
130
|
+
when XMLParser::END_ELEM
|
131
|
+
case name
|
132
|
+
when "stream:stream"
|
133
|
+
@started = false
|
134
|
+
else
|
135
|
+
@listener.receive(@current) unless @current.element_parent
|
136
|
+
@current = @current.element_parent
|
137
|
+
end
|
138
|
+
end
|
139
|
+
rescue
|
140
|
+
puts "Error #{$!}"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
rescue XMLParserError
|
144
|
+
line = parser.line
|
145
|
+
print "XML Parsing error(#{line}): #{$!}\n"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
else # USE REXML
|
150
|
+
require 'rexml/document'
|
151
|
+
require 'rexml/parsers/sax2parser'
|
152
|
+
require 'rexml/source'
|
153
|
+
|
154
|
+
##
|
155
|
+
# The REXMLJabberParser uses REXML to parse the incoming XML stream
|
156
|
+
# of the Jabber protocol and fires ParsedXMLElements at the Connection
|
157
|
+
# instance.
|
158
|
+
#
|
159
|
+
class REXMLJabberParser
|
160
|
+
# status if the parser is started
|
161
|
+
attr_reader :started
|
162
|
+
|
163
|
+
##
|
164
|
+
# Constructs a parser for the supplied stream (socket input)
|
165
|
+
#
|
166
|
+
# stream:: [IO] Socket input stream
|
167
|
+
# listener:: [Object.receive(ParsedXMLElement)] The listener (usually a Jabber::Protocol::Connection instance
|
168
|
+
#
|
169
|
+
def initialize(stream, listener)
|
170
|
+
@stream = stream
|
171
|
+
|
172
|
+
# this hack fixes REXML version "2.7.3" and "2.7.4"
|
173
|
+
if REXML::Version=="2.7.3" || REXML::Version=="2.7.4"
|
174
|
+
def @stream.read(len=nil)
|
175
|
+
len = 100 unless len
|
176
|
+
super(len)
|
177
|
+
end
|
178
|
+
def @stream.gets(char=nil)
|
179
|
+
super(">")
|
180
|
+
end
|
181
|
+
def @stream.readline(char=nil)
|
182
|
+
super(">")
|
183
|
+
end
|
184
|
+
def @stream.readlines(char=nil)
|
185
|
+
super(">")
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
@listener = listener
|
190
|
+
@current = nil
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# Begins parsing the XML stream and does not return until
|
195
|
+
# the stream closes.
|
196
|
+
#
|
197
|
+
def parse
|
198
|
+
#puts "PARSE"
|
199
|
+
@started = false
|
200
|
+
begin
|
201
|
+
parser = REXML::Parsers::SAX2Parser.new @stream
|
202
|
+
|
203
|
+
parser.listen(:end_document) do
|
204
|
+
raise Jabber::ConnectionForceCloseError
|
205
|
+
end
|
206
|
+
|
207
|
+
parser.listen( :start_element ) do |uri, localname, qname, attributes|
|
208
|
+
puts "START ELEMENT"
|
209
|
+
case qname
|
210
|
+
when "stream:stream"
|
211
|
+
openstream = ParsedXMLElement.new(qname)
|
212
|
+
attributes.each { |attr, value| openstream.add_attribute(attr, value) }
|
213
|
+
@listener.receive(openstream)
|
214
|
+
@started = true
|
215
|
+
else
|
216
|
+
if @current.nil?
|
217
|
+
@current = ParsedXMLElement.new(qname)
|
218
|
+
else
|
219
|
+
@current = @current.add_child(qname)
|
220
|
+
end
|
221
|
+
attributes.each { |attr, value| @current.add_attribute(attr, value) }
|
222
|
+
end
|
223
|
+
end
|
224
|
+
parser.listen( :end_element ) do |uri, localname, qname|
|
225
|
+
puts "END ELEMENT"
|
226
|
+
case qname
|
227
|
+
when "stream:stream"
|
228
|
+
@started = false
|
229
|
+
else
|
230
|
+
@listener.receive(@current) unless @current.element_parent
|
231
|
+
@current = @current.element_parent
|
232
|
+
end
|
233
|
+
end
|
234
|
+
parser.listen( :characters ) do | text |
|
235
|
+
puts "CHARACTERS"
|
236
|
+
@current.append_data(text) if @current
|
237
|
+
end
|
238
|
+
parser.listen( :cdata ) do | text |
|
239
|
+
puts "CDATA"
|
240
|
+
@current.append_data(text) if @current
|
241
|
+
end
|
242
|
+
parser.parse
|
243
|
+
rescue REXML::ParseException => e
|
244
|
+
puts "FAIL"
|
245
|
+
|
246
|
+
puts e.backtrace.join "\n"
|
247
|
+
puts e.message
|
248
|
+
@listener.parse_failure
|
249
|
+
rescue Jabber::ConnectionForceCloseError => e
|
250
|
+
@listener.parse_failure(e)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end # USE_PARSER
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|