jabber4r-revive 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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