jabber4r-revive 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,246 @@
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
+ class Message
9
+ attr_accessor :to, :from, :id, :type, :body, :xhtml, :subject, :thread, :x, :oobData, :errorcode, :error
10
+ NORMAL = "normal"
11
+ ERROR="error"
12
+ CHAT="chat"
13
+ GROUPCHAT="groupchat"
14
+ HEADLINE="headline"
15
+
16
+ ##
17
+ # Factory to build a Message from an XMLElement
18
+ #
19
+ # session:: [Jabber::Session] The Jabber session instance
20
+ # element:: [Jabber::Protocol::ParsedXMLElement] The received XML object
21
+ # return:: [Jabber::Protocol::Message] The newly created Message object
22
+ #
23
+ def self.from_element(session, element)
24
+ message = Message.new(element.attr_to)
25
+ message.from = Jabber::JID.new(element.attr_from) if element.attr_from
26
+ message.type = element.attr_type
27
+ message.id = element.attr_id
28
+ message.thread = element.thread.element_data
29
+ message.body = element.body.element_data
30
+ message.xhtml = element.xhtml.element_data
31
+ message.subject = element.subject.element_data
32
+ message.oobData = element.x.element_data
33
+ message.session=session
34
+ return message
35
+ end
36
+
37
+ ##
38
+ # Creates a Message
39
+ #
40
+ # to:: [String | Jabber::JID] The jabber id to send this message to (or from)
41
+ # type:: [Integer=NORMAL] The type of message...Message::(NORMAL, CHAT, GROUPCHAT, HEADLINE)
42
+ #
43
+ def initialize(to, type=NORMAL)
44
+ return unless to
45
+ to = Jabber::JID.new(to) if to.kind_of? String
46
+ @to = to if to.kind_of? Jabber::JID
47
+ @type = type
48
+ end
49
+
50
+ ##
51
+ # Chaining method...sets the body of the message
52
+ #
53
+ # body:: [String] The message body
54
+ # return:: [Jabber::Protocol::Message] The current Message object
55
+ #
56
+ def set_body(body)
57
+ @body = body.gsub(/[&]/, '&amp;').gsub(/[<]/, '&lt;').gsub(/[']/, '&apos;')
58
+ self
59
+ end
60
+
61
+ ##
62
+ # Chaining method...sets the subject of the message
63
+ #
64
+ # subject:: [String] The message subject
65
+ # return:: [Jabber::Protocol::Message] The current Message object
66
+ #
67
+ def set_subject(subject)
68
+ @subject = subject.gsub(/[&]/, '&amp;').gsub(/[<]/, '&lt;').gsub(/[']/, '&apos;')
69
+ self
70
+ end
71
+
72
+ ##
73
+ # Chaining method...sets the XHTML body of the message
74
+ #
75
+ # body:: [String] The message body
76
+ # return:: [Jabber::Protocol::Message] The current message object
77
+ #
78
+ def set_xhtml(xhtml)
79
+ @xhtml=xhtml
80
+ self
81
+ end
82
+
83
+ ##
84
+ # Chaining method...sets the thread of the message
85
+ #
86
+ # thread:: [String] The message thread id
87
+ # return:: [Jabber::Protocol::Message] The current Message object
88
+ #
89
+ def set_thread(thread)
90
+ @thread = thread
91
+ self
92
+ end
93
+
94
+ ##
95
+ # Chaining method...sets the OOB data of the message
96
+ #
97
+ # data:: [String] The message OOB data
98
+ # return:: [Jabber::Protocol::Message] The current Message object
99
+ #
100
+ def set_outofband(data)
101
+ @oobData = data
102
+ self
103
+ end
104
+
105
+ ##
106
+ # Chaining method...sets the extended data of the message
107
+ #
108
+ # x:: [String] The message x data
109
+ # return:: [Jabber::Protocol::Message] The current Message object
110
+ #
111
+ def set_x(x)
112
+ @x = x
113
+ self
114
+ end
115
+
116
+ ##
117
+ # Sets an error code to be returned(chaining method)
118
+ #
119
+ # code:: [Integer] the jabber error code
120
+ # reason:: [String] Why the error was reported
121
+ # return:: [Jabber::Protocol::Message] The current Message object
122
+ #
123
+
124
+ def set_error(code,reason)
125
+ @errorcode=code
126
+ @error=reason
127
+ @type="error"
128
+ self
129
+ end
130
+
131
+ ##
132
+ # Convenience method for send(true)
133
+ #
134
+ # ttl:: [Integer = nil] The time (in seconds) to wait for a reply before assuming nil
135
+ # &block:: [Block] A block to process the message replies
136
+ #
137
+ def request(ttl=nil, &block)
138
+ send(true, ttl, &block)
139
+ end
140
+
141
+ ##
142
+ # Sends the message to the Jabber service for delivery
143
+ #
144
+ # wait:: [Boolean = false] Wait for reply before return?
145
+ # ttl:: [Integer = nil] The time (in seconds) to wait for a reply before assuming nil
146
+ # &block:: [Block] A block to process the message replies
147
+ #
148
+ def send(wait=false, ttl=nil, &block)
149
+ if wait
150
+ message = nil
151
+ blockedThread = Thread.current
152
+ timer_thread = nil
153
+ timeout = false
154
+ unless ttl.nil?
155
+ timer_thread = Thread.new {
156
+ sleep ttl
157
+ timeout = true
158
+ blockedThread.wakeup
159
+ }
160
+ end
161
+ @session.connection.send(self.to_s, block) do |je|
162
+ if je.element_tag == "message" and je.thread.element_data == @thread
163
+ je.consume_element
164
+ message = Message.from_element(@session, je)
165
+ blockedThread.wakeup unless timeout
166
+ unless timer_thread.nil?
167
+ timer_thread.kill
168
+ timer_thread = nil
169
+ end
170
+ end
171
+ end
172
+ Thread.stop
173
+ return message
174
+ else
175
+ @session.connection.send(self.to_s, block) if @session
176
+ end
177
+ end
178
+
179
+ ##
180
+ # Sets the session instance
181
+ #
182
+ # session:: [Jabber::Session] The session instance
183
+ # return:: [Jabber::Protocol::Message] The current Message object
184
+ #
185
+ def session=(session)
186
+ @session = session
187
+ self
188
+ end
189
+
190
+ ##
191
+ # Builds a reply to an existing message by setting:
192
+ # 1. to = from
193
+ # 2. id = id
194
+ # 3. thread = thread
195
+ # 4. type = type
196
+ # 5. session = session
197
+ #
198
+ # return:: [Jabber::Protocol::Message] The reply message
199
+ #
200
+ def reply
201
+ message = Message.new(nil)
202
+ message.to = @from
203
+ message.id = @id
204
+ message.thread = @thread
205
+ message.type = @type
206
+ message.session = @session
207
+ @is_reply = true
208
+ return message
209
+ end
210
+
211
+ ##
212
+ # Generates XML that complies with the Jabber protocol for
213
+ # sending the message through the Jabber service.
214
+ #
215
+ # return:: [String] The XML string.
216
+ #
217
+ def to_xml
218
+ @thread = Jabber.gen_random_thread if @thread.nil? and (not @is_reply)
219
+ elem = XMLElement.new("message", {"to"=>@to, "type"=>@type})
220
+ elem.add_attribute("id", @id) if @id
221
+ elem.add_child("thread").add_data(@thread) if @thread
222
+ elem.add_child("subject").add_data(@subject) if @subject
223
+ elem.add_child("body").add_data(@body) if @body
224
+ if @xhtml then
225
+ t=elem.add_child("xhtml").add_attribute("xmlns","http://www.w3.org/1999/xhtml")
226
+ t.add_child("body").add_data(@xhtml)
227
+ end
228
+ if @type=="error" then
229
+ e=elem.add_child("error");
230
+ e.add_attribute("code",@errorcode) if @errorcode
231
+ e.add_data(@error) if @error
232
+ end
233
+ elem.add_child("x").add_attribute("xmlns", "jabber:x:oob").add_data(@oobData) if @oobData
234
+ elem.add_xml(@x.to_s) if @x
235
+ return elem.to_s
236
+ end
237
+
238
+ ##
239
+ # see to_xml
240
+ #
241
+ def to_s
242
+ to_xml
243
+ end
244
+
245
+ end
246
+ end
@@ -0,0 +1,208 @@
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
+ # This class is constructed from XML data elements that are received from
10
+ # the Jabber service.
11
+ #
12
+ class ParsedXMLElement
13
+
14
+ ##
15
+ # This class is used to return nil element values to prevent errors (and
16
+ # reduce the number of checks.
17
+ #
18
+ class NilParsedXMLElement
19
+
20
+ ##
21
+ # Override to return nil
22
+ #
23
+ # return:: [nil]
24
+ #
25
+ def method_missing(methId, *args)
26
+ return nil
27
+ end
28
+
29
+ ##
30
+ # Evaluate as nil
31
+ #
32
+ # return:: [Boolean] true
33
+ #
34
+ def nil?
35
+ return true
36
+ end
37
+
38
+ ##
39
+ # Return a zero count
40
+ #
41
+ # return:: [Integer] 0
42
+ #
43
+ def count
44
+ 0
45
+ end
46
+
47
+ include Singleton
48
+ end
49
+
50
+ # The <tag> as String
51
+ attr_reader :element_tag
52
+
53
+ # The parent ParsedXMLElement
54
+ attr_reader :element_parent
55
+
56
+ # A hash of ParsedXMLElement children
57
+ attr_reader :element_children
58
+
59
+ # The data <tag>data</tag> for a tag
60
+ attr_reader :element_data
61
+
62
+ ##
63
+ # Construct an instance for the given tag
64
+ #
65
+ # tag:: [String] The tag
66
+ # parent:: [Jabber::Protocol::ParsedXMLElement = nil] The parent element
67
+ #
68
+ def initialize(tag, parent=nil)
69
+ @element_tag = tag
70
+ @element_parent = parent
71
+ @element_children = {}
72
+ @attributes = {}
73
+ @element_consumed = false
74
+ end
75
+
76
+ ##
77
+ # Add the attribute to the element
78
+ # <tag name="value">data</tag>
79
+ #
80
+ # name:: [String] The attribute name
81
+ # value:: [String] The attribute value
82
+ # return:: [Jabber::Protocol::ParsedXMLElement] self for chaining
83
+ #
84
+ def add_attribute(name, value)
85
+ @attributes[name]=value
86
+ self
87
+ end
88
+
89
+ ##
90
+ # Factory to build a child element from this element with the given tag
91
+ #
92
+ # tag:: [String] The tag name
93
+ # return:: [Jabber::Protocol::ParsedXMLElement] The newly created child element
94
+ #
95
+ def add_child(tag)
96
+ child = ParsedXMLElement.new(tag, self)
97
+ @element_children[tag] = Array.new if not @element_children.has_key? tag
98
+ @element_children[tag] << child
99
+ return child
100
+ end
101
+
102
+ ##
103
+ # When an xml is received from the Jabber service and a ParsedXMLElement is created,
104
+ # it is propogated to all filters and listeners. Any one of those can consume the element
105
+ # to prevent its propogation to other filters or listeners. This method marks the element
106
+ # as consumed.
107
+ #
108
+ def consume_element
109
+ @element_consumed = true
110
+ end
111
+
112
+ ##
113
+ # Checks if the element is consumed
114
+ #
115
+ # return:: [Boolean] True if the element is consumed
116
+ #
117
+ def element_consumed?
118
+ @element_consumed
119
+ end
120
+
121
+ ##
122
+ # Appends data to the element
123
+ #
124
+ # data:: [String] The data to append
125
+ # return:: [Jabber::Protocol::ParsedXMLElement] self for chaining
126
+ #
127
+ def append_data(data)
128
+ @element_data = "" unless @element_data
129
+ @element_data += data
130
+ self
131
+ end
132
+
133
+ ##
134
+ # Calls the parent's element_children (hash) index off of this elements
135
+ # tag and gets the supplied index. In this sense it gets its sibling based
136
+ # on offset.
137
+ #
138
+ # number:: [Integer] The number of the sibling to get
139
+ # return:: [Jabber::Protocol::ParsedXMLElement] The sibling element
140
+ #
141
+ def [](number)
142
+ return @element_parent.element_children[@element_tag][number] if @element_parent
143
+ end
144
+
145
+ ##
146
+ # Returns the count of siblings with this element's tag
147
+ #
148
+ # return:: [Integer] The number of sibling elements
149
+ #
150
+ def count
151
+ return @element_parent.element_children[@element_tag].size if @element_parent
152
+ return 0
153
+ end
154
+
155
+ ##
156
+ # see _count
157
+ #
158
+ def size
159
+ count
160
+ end
161
+
162
+ ##
163
+ # Overrides to allow for directly accessing child elements
164
+ # and attributes. If prefaced by attr_ it looks for an attribute
165
+ # that matches or checks for a child with a tag that matches
166
+ # the method name. If no match occurs, it returns a
167
+ # NilParsedXMLElement (singleton) instance.
168
+ #
169
+ # Example:: <alpha number="1"><beta number="2">Beta Data</beta></alpha>
170
+ #
171
+ # element.element_tag #=> alpha
172
+ # element.attr_number #=> 1
173
+ # element.beta.element_data #=> Beta Data
174
+ #
175
+ def method_missing(methId, *args)
176
+ tag = methId.id2name
177
+ if tag[0..4]=="attr_"
178
+ return @attributes[tag[5..-1]]
179
+ end
180
+ list = @element_children[tag]
181
+ return list[0] if list
182
+ return NilParsedXMLElement.instance
183
+ end
184
+
185
+ ##
186
+ # Returns the valid XML as a string
187
+ #
188
+ # return:: [String] XML string
189
+ def to_s
190
+ begin
191
+ result = "\n<#{@element_tag}"
192
+ @attributes.each {|key, value| result += (' '+key+'="'+value+'"') }
193
+ if @element_children.size>0 or @element_data
194
+ result += ">"
195
+ else
196
+ result += "/>"
197
+ end
198
+ result += @element_data if @element_data
199
+ @element_children.each_value {|array| array.each {|je| result += je.to_s} }
200
+ result += "\n" if @element_children.size>0
201
+ result += "</#{@element_tag}>" if @element_children.size>0 or @element_data
202
+ result
203
+ rescue => exception
204
+ puts exception.to_s
205
+ end
206
+ end
207
+ end
208
+ end