riddl 0.99.255 → 0.99.256
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.
- checksums.yaml +4 -4
- data/examples/properties/server.properties.xml +1 -1
- data/lib/ruby/riddl/client.rb +7 -97
- data/lib/ruby/riddl/server.rb +11 -95
- data/riddl.gemspec +1 -2
- metadata +2 -18
- data/lib/ruby/riddl/protocols/xmpp/generator.rb +0 -169
- data/lib/ruby/riddl/protocols/xmpp/parser.rb +0 -110
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 234355d07a1365d8c3edad0985f8fbed5c1020b1
|
|
4
|
+
data.tar.gz: eeedfe05639e119ff574ecaef299e4fe792786aa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8746dda65d1ecfb226db477340b060ca803392ddf40d1228299c39a670afdd6fb004bb579ed1cfeab379c9d7dbfc2af06a4688405de26132d713eb4e149095fa
|
|
7
|
+
data.tar.gz: fccc19fdd4ca57f9673ece1c9a071c85d1188fc52a3b9c76461424232b3d08fe06590e5738d88fcf30c4bbc640ec7217d5241bb10874ed4b6fce1fb274bb552f
|
data/lib/ruby/riddl/client.rb
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
gem 'blather'
|
|
2
|
-
|
|
3
1
|
require File.expand_path(File.dirname(__FILE__) + '/wrapper')
|
|
4
2
|
require File.expand_path(File.dirname(__FILE__) + '/error')
|
|
5
3
|
require File.expand_path(File.dirname(__FILE__) + '/protocols/http/generator')
|
|
6
4
|
require File.expand_path(File.dirname(__FILE__) + '/protocols/http/parser')
|
|
7
|
-
require File.expand_path(File.dirname(__FILE__) + '/protocols/xmpp/generator')
|
|
8
|
-
require File.expand_path(File.dirname(__FILE__) + '/protocols/xmpp/parser')
|
|
9
5
|
require File.expand_path(File.dirname(__FILE__) + '/protocols/utils')
|
|
10
6
|
require File.expand_path(File.dirname(__FILE__) + '/header')
|
|
11
7
|
require File.expand_path(File.dirname(__FILE__) + '/option')
|
|
@@ -13,7 +9,6 @@ require File.expand_path(File.dirname(__FILE__) + '/option')
|
|
|
13
9
|
require 'net/https'
|
|
14
10
|
require 'eventmachine'
|
|
15
11
|
require 'em-websocket-client'
|
|
16
|
-
require 'blather/client/client'
|
|
17
12
|
require 'uri'
|
|
18
13
|
require 'openssl'
|
|
19
14
|
require 'digest/md5'
|
|
@@ -47,7 +42,7 @@ unless Module.constants.include?('CLIENT_INCLUDED')
|
|
|
47
42
|
\A
|
|
48
43
|
|
|
49
44
|
# protocol identifier
|
|
50
|
-
(?:(?:https?|
|
|
45
|
+
(?:(?:https?|[a-z]{4})://)
|
|
51
46
|
|
|
52
47
|
# user:pass authentication
|
|
53
48
|
(?:\S+(?::\S*)?@)?
|
|
@@ -93,26 +88,8 @@ unless Module.constants.include?('CLIENT_INCLUDED')
|
|
|
93
88
|
if @base !~ RIDDL_URL_PATTERN
|
|
94
89
|
raise ConnectionError, 'An RFC 3986 URI as target is required. Pro tip: (http|https|xmpp)://...'
|
|
95
90
|
end
|
|
96
|
-
if
|
|
97
|
-
|
|
98
|
-
end
|
|
99
|
-
if URI.parse(@base).scheme == 'xmpp' && @options[:jid] && @options[:pass]
|
|
100
|
-
sig = SignalWait.new
|
|
101
|
-
Thread::abort_on_exception = true
|
|
102
|
-
Thread.new do
|
|
103
|
-
begin
|
|
104
|
-
EM.send EM.reactor_running? ? :defer : :run do
|
|
105
|
-
client = Blather::Client.setup @options[:jid], @options[:pass]
|
|
106
|
-
client.register_handler(:ready) { sig.continue }
|
|
107
|
-
client.connect
|
|
108
|
-
@options[:xmpp] = client
|
|
109
|
-
sig.continue
|
|
110
|
-
end
|
|
111
|
-
rescue
|
|
112
|
-
raise ConnectionError, 'XMPP connection not successful.'
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
sig.wait 2
|
|
91
|
+
if @options[:custom_protocol]
|
|
92
|
+
@options[:custom_protocol] = @options[:custom_protocol].new(@base,@options)
|
|
116
93
|
end
|
|
117
94
|
unless riddl.nil?
|
|
118
95
|
@wrapper = (riddl.class == Riddl::Wrapper ? riddl : Riddl::Wrapper::new(riddl))
|
|
@@ -127,10 +104,6 @@ unless Module.constants.include?('CLIENT_INCLUDED')
|
|
|
127
104
|
end
|
|
128
105
|
attr_reader :base
|
|
129
106
|
|
|
130
|
-
def close_xmpp
|
|
131
|
-
@options[:xmpp].close if @options[:xmpp]
|
|
132
|
-
end
|
|
133
|
-
|
|
134
107
|
def self::location(base,options={})
|
|
135
108
|
new(base,nil,options)
|
|
136
109
|
end
|
|
@@ -409,56 +382,12 @@ unless Module.constants.include?('CLIENT_INCLUDED')
|
|
|
409
382
|
end
|
|
410
383
|
return res.code.to_i, response, response_headers
|
|
411
384
|
#}}}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
return req.simulate if simulate
|
|
416
|
-
|
|
417
|
-
sig = SignalWait.new
|
|
418
|
-
stanza = req.stanza
|
|
419
|
-
|
|
420
|
-
@options[:debug].puts(stanza) if @options[:debug]
|
|
421
|
-
|
|
422
|
-
status = 404
|
|
423
|
-
response = []
|
|
424
|
-
response_headers = {}
|
|
425
|
-
if ack
|
|
426
|
-
@options[:xmpp].write_with_handler(stanza) do |raw|
|
|
427
|
-
res = XML::Smart::Dom::Element.new(raw).parent
|
|
428
|
-
@options[:debug].puts(res.to_s) if @options[:debug]
|
|
429
|
-
res.register_namespace 'xr', Riddl::Protocols::XMPP::XR_NS
|
|
430
|
-
if res.find('/message/error').empty?
|
|
431
|
-
status = 200
|
|
432
|
-
response_headers = {}
|
|
433
|
-
res.find('/message/xr:header').each do |e|
|
|
434
|
-
response_headers[e.attributes['name']] = e.text
|
|
435
|
-
end
|
|
436
|
-
response = Protocols::XMPP::Parser.new('', res).params
|
|
437
|
-
else
|
|
438
|
-
res.register_namespace 'se', Blather::StanzaError::STANZA_ERR_NS
|
|
439
|
-
err = res.find('string(/message/error/se:text)')
|
|
440
|
-
status = (err.match(/\d+/)[0] || 209).to_i
|
|
441
|
-
end
|
|
442
|
-
sig.continue
|
|
443
|
-
end
|
|
444
|
-
sig.wait
|
|
445
|
-
else
|
|
446
|
-
status = 200
|
|
447
|
-
@options[:xmpp].write stanza
|
|
448
|
-
|
|
449
|
-
# xmpp writes in next_tick so we have to fucking wait also a tick
|
|
450
|
-
# to ensure that all shit has been written. fuck. not the best
|
|
451
|
-
# solution, but scripts may preemtively quit if we dont do it. if
|
|
452
|
-
# anybody knows a better solution, please tell me.
|
|
453
|
-
|
|
454
|
-
### UPDATE todo, we produce deadlocks here, rethink this mess
|
|
455
|
-
# EM.next_tick { sig.continue }
|
|
456
|
-
# sig.wait
|
|
385
|
+
else
|
|
386
|
+
if @options[:custom_protocol]
|
|
387
|
+
return @options[:custom_protocol].handle(url,riddl_method,parameters,headers,qs,simulate,ack)
|
|
457
388
|
end
|
|
458
|
-
return status, response, response_headers
|
|
459
|
-
#}}}
|
|
460
389
|
end
|
|
461
|
-
raise URIError, "not a valid URI (http, https,
|
|
390
|
+
raise URIError, "not a valid URI (http, https, ... are accepted)"
|
|
462
391
|
end #}}}
|
|
463
392
|
private :make_request
|
|
464
393
|
|
|
@@ -489,25 +418,6 @@ unless Module.constants.include?('CLIENT_INCLUDED')
|
|
|
489
418
|
end
|
|
490
419
|
end # }}}
|
|
491
420
|
|
|
492
|
-
class XMPPRequest #{{{
|
|
493
|
-
attr_reader :stanza
|
|
494
|
-
|
|
495
|
-
def initialize(method, to, path, parameters, headers, qs, ack)
|
|
496
|
-
path = (path.strip == '' ? '' : path)
|
|
497
|
-
path += "/?#{qs}" unless qs == ''
|
|
498
|
-
path.gsub!(/\/+/,'/')
|
|
499
|
-
@stanza = Protocols::XMPP::Generator.new(method,parameters,headers,ack).generate
|
|
500
|
-
@stanza.to = to + path
|
|
501
|
-
end
|
|
502
|
-
|
|
503
|
-
def simulate
|
|
504
|
-
sock = StringIO.new('')
|
|
505
|
-
sock.write @stanza.to_s
|
|
506
|
-
sock.rewind
|
|
507
|
-
[nil, sock, []]
|
|
508
|
-
end
|
|
509
|
-
end #}}}
|
|
510
|
-
|
|
511
421
|
end
|
|
512
422
|
|
|
513
423
|
end
|
data/lib/ruby/riddl/server.rb
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
gem 'blather'
|
|
2
|
-
|
|
3
1
|
require File.expand_path(File.dirname(__FILE__) + '/constants')
|
|
4
2
|
require File.expand_path(File.dirname(__FILE__) + '/implementation')
|
|
5
3
|
require File.expand_path(File.dirname(__FILE__) + '/protocols/http/parser')
|
|
6
4
|
require File.expand_path(File.dirname(__FILE__) + '/protocols/http/generator')
|
|
7
|
-
require File.expand_path(File.dirname(__FILE__) + '/protocols/xmpp/parser')
|
|
8
|
-
require File.expand_path(File.dirname(__FILE__) + '/protocols/xmpp/generator')
|
|
9
5
|
require File.expand_path(File.dirname(__FILE__) + '/protocols/utils')
|
|
10
6
|
require File.expand_path(File.dirname(__FILE__) + '/protocols/websocket')
|
|
11
7
|
require File.expand_path(File.dirname(__FILE__) + '/header')
|
|
@@ -20,7 +16,7 @@ require 'rack/content_length'
|
|
|
20
16
|
require 'rack/chunked'
|
|
21
17
|
require 'securerandom'
|
|
22
18
|
require 'psych.rb'
|
|
23
|
-
|
|
19
|
+
|
|
24
20
|
|
|
25
21
|
module Riddl
|
|
26
22
|
|
|
@@ -133,7 +129,10 @@ module Riddl
|
|
|
133
129
|
)
|
|
134
130
|
|
|
135
131
|
puts "Server (#{@riddl_opts[:url]}) started as PID:#{Process.pid}"
|
|
136
|
-
|
|
132
|
+
if @riddl_opts[:custom_protocol] && !@riddl_opts[:http_only]
|
|
133
|
+
@riddl_opts[:custom_protocol] = @riddl_opts[:custom_protocol].new(@riddl_opts)
|
|
134
|
+
puts @riddl_opts[:custom_protocol].support if @riddl_opts[:custom_protocol].support
|
|
135
|
+
end
|
|
137
136
|
Process.daemon(@riddl_opts[:basepath]) unless @riddl_opts[:verbose]
|
|
138
137
|
Dir.chdir(@riddl_opts[:basepath])
|
|
139
138
|
::Kernel::at_exit do
|
|
@@ -150,29 +149,8 @@ module Riddl
|
|
|
150
149
|
server.start
|
|
151
150
|
end
|
|
152
151
|
|
|
153
|
-
@riddl_opts[:
|
|
154
|
-
|
|
155
|
-
xmpp = Blather::Client.setup @riddl_xmpp_jid, @riddl_xmpp_pass
|
|
156
|
-
@riddl_opts[:xmpp] = xmpp
|
|
157
|
-
xmpp.register_handler(:message, '/message/ns:operation', :ns => 'http://riddl.org/ns/xmpp-rest') do |m|
|
|
158
|
-
began_at = Time.now
|
|
159
|
-
instance = dup
|
|
160
|
-
instance.__xmpp_call(xmpp,m)
|
|
161
|
-
now = Time.now
|
|
162
|
-
instance.riddl_log.write Rack::CommonLogger::FORMAT % [
|
|
163
|
-
@riddl_xmpp_jid || "-",
|
|
164
|
-
m.from || "-",
|
|
165
|
-
now.strftime("%d/%b/%Y %H:%M:%S"),
|
|
166
|
-
instance.riddl_method.upcase,
|
|
167
|
-
instance.riddl_pinfo,
|
|
168
|
-
'',
|
|
169
|
-
'XMPP',
|
|
170
|
-
instance.riddl_status,
|
|
171
|
-
'?',
|
|
172
|
-
now - began_at
|
|
173
|
-
]
|
|
174
|
-
end
|
|
175
|
-
xmpp.connect
|
|
152
|
+
if @riddl_opts[:custom_protocol] && !@riddl_opts[:http_only]
|
|
153
|
+
@riddl_opts[:custom_protocol].start
|
|
176
154
|
end
|
|
177
155
|
|
|
178
156
|
[:INT, :TERM].each do |signal|
|
|
@@ -184,11 +162,10 @@ module Riddl
|
|
|
184
162
|
end
|
|
185
163
|
|
|
186
164
|
rescue => e
|
|
187
|
-
if
|
|
188
|
-
|
|
189
|
-
else
|
|
190
|
-
puts "Server (#{@riddl_opts[:url]}) stopped due to connection error (PID:#{Process.pid})"
|
|
165
|
+
if @riddl_opts[:custom_protocol] && !@riddl_opts[:http_only]
|
|
166
|
+
@riddl_opts[:custom_protocol].error_handling(e)
|
|
191
167
|
end
|
|
168
|
+
puts "Server (#{@riddl_opts[:url]}) stopped due to connection error (PID:#{Process.pid})"
|
|
192
169
|
end
|
|
193
170
|
end #}}}
|
|
194
171
|
|
|
@@ -327,62 +304,6 @@ module Riddl
|
|
|
327
304
|
end
|
|
328
305
|
end #}}}
|
|
329
306
|
|
|
330
|
-
def __xmpp_call(env,raw) #{{{
|
|
331
|
-
@riddl_log = @riddl_logger || STDOUT
|
|
332
|
-
|
|
333
|
-
@riddl_env = XML::Smart::Dom::Element.new(raw).parent
|
|
334
|
-
@riddl_env.register_namespace 'xr', Riddl::Protocols::XMPP::XR_NS
|
|
335
|
-
@riddl_res = env
|
|
336
|
-
@riddl_status = 404
|
|
337
|
-
|
|
338
|
-
@riddl_pinfo = ('/' + @riddl_env.root.attributes['to'].sub(/^[^\/]+/,'')).gsub(/\/+/,'/')
|
|
339
|
-
@riddl_pinfo.gsub!(/\?(.*)/).each do
|
|
340
|
-
@riddl_query_string = $1; ''
|
|
341
|
-
end
|
|
342
|
-
@riddl_matching_path = @riddl_paths.find{ |e| @riddl_pinfo.match(e[1]).to_s.length == @riddl_pinfo.length }
|
|
343
|
-
|
|
344
|
-
if @riddl_matching_path
|
|
345
|
-
@riddl_method = @riddl_env.find('string(/message/xr:operation)').downcase
|
|
346
|
-
|
|
347
|
-
@riddl_headers = {}
|
|
348
|
-
@riddl_env.find('/message/xr:header').each do |e|
|
|
349
|
-
@riddl_headers[e.attributes['name']] = e.text
|
|
350
|
-
end
|
|
351
|
-
@riddl_parameters = Protocols::XMPP::Parser.new(
|
|
352
|
-
@riddl_query_string,
|
|
353
|
-
@riddl_env
|
|
354
|
-
).params
|
|
355
|
-
|
|
356
|
-
@riddl_path = '/'
|
|
357
|
-
@riddl_info = {
|
|
358
|
-
:h => @riddl_headers,
|
|
359
|
-
:p => @riddl_parameters,
|
|
360
|
-
:r => @riddl_pinfo.sub(/^\//,'').split('/').map{|e|Protocols::Utils::unescape(e)},
|
|
361
|
-
:s => @riddl_matching_path[0].sub(/\//,'').split('/'),
|
|
362
|
-
:m => @riddl_method,
|
|
363
|
-
:env => Hash[@riddl_env.root.attributes.map{|a| [a.qname.name, a.value] }].merge({ 'riddl.transport' => 'xmpp', 'xmpp' => @riddl_res }),
|
|
364
|
-
:match => []
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
__call
|
|
368
|
-
else
|
|
369
|
-
@riddl_log.write "404: this resource for sure does not exist.\n"
|
|
370
|
-
@riddl_status = 404 # client requests wrong path
|
|
371
|
-
end
|
|
372
|
-
|
|
373
|
-
stanza = if @riddl_exe && @riddl_status >= 200 && @riddl_status < 300
|
|
374
|
-
return if @riddl_message.out.nil?
|
|
375
|
-
Protocols::XMPP::Generator.new(@riddl_status,@riddl_exe.response,@riddl_exe.headers).generate
|
|
376
|
-
else
|
|
377
|
-
Protocols::XMPP::Error.new(@riddl_status).generate
|
|
378
|
-
end
|
|
379
|
-
|
|
380
|
-
stanza.from = raw.to
|
|
381
|
-
stanza.to = raw.from
|
|
382
|
-
stanza.id = raw.id
|
|
383
|
-
@riddl_res.write stanza
|
|
384
|
-
end #}}}
|
|
385
|
-
|
|
386
307
|
def __http_call(env) #{{{
|
|
387
308
|
@riddl_env = env
|
|
388
309
|
@riddl_env['rack.logger'] = @riddl_logger if @riddl_logger
|
|
@@ -419,7 +340,7 @@ module Riddl
|
|
|
419
340
|
:r => @riddl_pinfo.sub(/^\//,'').split('/').map{|e|Protocols::Utils::unescape(e)},
|
|
420
341
|
:s => @riddl_matching_path[0].sub(/\//,'').split('/'),
|
|
421
342
|
:m => @riddl_method,
|
|
422
|
-
:env => @riddl_env.reject{|k,v| k =~ /^rack\./}.merge({'riddl.transport' => 'http', '
|
|
343
|
+
:env => @riddl_env.reject{|k,v| k =~ /^rack\./}.merge({'riddl.transport' => 'http', 'custom_protocol' => @riddl_opts[:custom_protocol]}),
|
|
423
344
|
:match => []
|
|
424
345
|
}
|
|
425
346
|
|
|
@@ -464,11 +385,6 @@ module Riddl
|
|
|
464
385
|
def process_out(pout)# {{{
|
|
465
386
|
@riddl_process_out = pout
|
|
466
387
|
end# }}}
|
|
467
|
-
def xmpp(jid,pass)# {{{
|
|
468
|
-
@riddl_xmpp_jid = jid
|
|
469
|
-
@riddl_xmpp_pass = pass
|
|
470
|
-
@riddl_opts[:jid] = jid
|
|
471
|
-
end# }}}
|
|
472
388
|
def cross_site_xhr(csxhr)# {{{
|
|
473
389
|
@riddl_cross_site_xhr = csxhr
|
|
474
390
|
end# }}}
|
data/riddl.gemspec
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Gem::Specification.new do |s|
|
|
2
2
|
s.name = "riddl"
|
|
3
|
-
s.version = "0.99.
|
|
3
|
+
s.version = "0.99.256"
|
|
4
4
|
s.platform = Gem::Platform::RUBY
|
|
5
5
|
s.license = "LGPL-3.0"
|
|
6
6
|
s.summary = "restful interface description and declaration language: tools and client/server libs"
|
|
@@ -32,7 +32,6 @@ Gem::Specification.new do |s|
|
|
|
32
32
|
s.add_runtime_dependency 'em-websocket-client', '>= 0.1', '~>0'
|
|
33
33
|
s.add_runtime_dependency 'mime-types', '>= 2.4', '~>2'
|
|
34
34
|
s.add_runtime_dependency 'minitest', '>= 5.0.0', '~>5'
|
|
35
|
-
s.add_runtime_dependency 'blather', '~>1.2'
|
|
36
35
|
s.add_runtime_dependency 'charlock_holmes', '>= 0.7', '~>0'
|
|
37
36
|
s.add_runtime_dependency 'redis', '>= 3.3.0', '~>3.3'
|
|
38
37
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: riddl
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.99.
|
|
4
|
+
version: 0.99.256
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Juergen 'eTM' Mangler
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: tools
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date: 2017-
|
|
13
|
+
date: 2017-12-01 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: xml-smart
|
|
@@ -180,20 +180,6 @@ dependencies:
|
|
|
180
180
|
- - "~>"
|
|
181
181
|
- !ruby/object:Gem::Version
|
|
182
182
|
version: '5'
|
|
183
|
-
- !ruby/object:Gem::Dependency
|
|
184
|
-
name: blather
|
|
185
|
-
requirement: !ruby/object:Gem::Requirement
|
|
186
|
-
requirements:
|
|
187
|
-
- - "~>"
|
|
188
|
-
- !ruby/object:Gem::Version
|
|
189
|
-
version: '1.2'
|
|
190
|
-
type: :runtime
|
|
191
|
-
prerelease: false
|
|
192
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
193
|
-
requirements:
|
|
194
|
-
- - "~>"
|
|
195
|
-
- !ruby/object:Gem::Version
|
|
196
|
-
version: '1.2'
|
|
197
183
|
- !ruby/object:Gem::Dependency
|
|
198
184
|
name: charlock_holmes
|
|
199
185
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -441,8 +427,6 @@ files:
|
|
|
441
427
|
- lib/ruby/riddl/protocols/http/parser.rb
|
|
442
428
|
- lib/ruby/riddl/protocols/utils.rb
|
|
443
429
|
- lib/ruby/riddl/protocols/websocket.rb
|
|
444
|
-
- lib/ruby/riddl/protocols/xmpp/generator.rb
|
|
445
|
-
- lib/ruby/riddl/protocols/xmpp/parser.rb
|
|
446
430
|
- lib/ruby/riddl/roles.rb
|
|
447
431
|
- lib/ruby/riddl/roles/http%3A%2F%2Foauth.net%2F1.0%2Faccess_token.rb
|
|
448
432
|
- lib/ruby/riddl/roles/http%3A%2F%2Foauth.net%2F1.0%2Fon_behalf.rb
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../constants')
|
|
2
|
-
require File.expand_path(File.dirname(__FILE__) + '/../utils')
|
|
3
|
-
require 'blather/client/client'
|
|
4
|
-
require 'securerandom'
|
|
5
|
-
|
|
6
|
-
module Riddl
|
|
7
|
-
module Protocols
|
|
8
|
-
module XMPP
|
|
9
|
-
XR_NS = 'http://riddl.org/ns/xmpp-rest'.freeze
|
|
10
|
-
|
|
11
|
-
class Stanza < Blather::Stanza
|
|
12
|
-
def self.new
|
|
13
|
-
node = super :message
|
|
14
|
-
node.type = :normal
|
|
15
|
-
node.id = SecureRandom.uuid
|
|
16
|
-
node
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
class Error
|
|
21
|
-
MAPPING = {
|
|
22
|
-
302 => ['redirect' , 'modify' , '302 Redirect' ],
|
|
23
|
-
400 => ['bad-request' , 'modify' , '400 Bad Request' ],
|
|
24
|
-
401 => ['not-authorized' , 'auth' , '401 Not Authorized ' ],
|
|
25
|
-
402 => ['payment-required' , 'auth' , '402 Payment Required' ],
|
|
26
|
-
403 => ['forbidden' , 'auth' , '403 Forbidden' ],
|
|
27
|
-
404 => ['item-not-found' , 'cancel' , '404 Not Found' ],
|
|
28
|
-
405 => ['not-allowed' , 'cancel' , '405 Not Allowed' ],
|
|
29
|
-
406 => ['not-acceptable' , 'modify' , '406 Not Acceptable' ],
|
|
30
|
-
407 => ['registration-required' , 'auth' , '407 Registration Required' ],
|
|
31
|
-
408 => ['remote-server-timeout' , 'wait' , '408 Request Timeout' ],
|
|
32
|
-
409 => ['conflict' , 'cancel' , '409 Conflict' ],
|
|
33
|
-
500 => ['internal-server-error' , 'wait' , '500 Internal Server Error' ],
|
|
34
|
-
501 => ['feature-not-implemented' , 'cancel' , '501 Not Implemented' ],
|
|
35
|
-
502 => ['service-unavailable' , 'wait' , '502 Remote Server Error' ],
|
|
36
|
-
503 => ['service-unavailable' , 'cancel' , '503 Service Unavailable' ],
|
|
37
|
-
504 => ['remote-server-timeout' , 'wait' , '504 Remote Server Timeout' ],
|
|
38
|
-
510 => ['service-unavailable' , 'cancel' , '510 Disconnected' ]
|
|
39
|
-
}.freeze
|
|
40
|
-
UNDEFINED = [
|
|
41
|
-
'undefined-condition', 'modify'
|
|
42
|
-
].freeze
|
|
43
|
-
|
|
44
|
-
def initialize(err)
|
|
45
|
-
m = Stanza.new
|
|
46
|
-
@stanza = if MAPPING[err]
|
|
47
|
-
Blather::StanzaError.new(m,*MAPPING[err]).to_node
|
|
48
|
-
else
|
|
49
|
-
Blather::StanzaError.new(m,*UNDEFINED,'#{err} see http://www.iana.org/assignments/http-status-codes/http-status-codes.xml').to_node
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def generate
|
|
54
|
-
@stanza
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
class Generator
|
|
59
|
-
def initialize(what,params,headers,ack=false)
|
|
60
|
-
@params = params
|
|
61
|
-
@stanza = Stanza.new
|
|
62
|
-
@node = XML::Smart::Dom::Element.new(@stanza)
|
|
63
|
-
if what.is_a?(Fixnum)
|
|
64
|
-
@node.add('ok').namespaces.add(nil,XR_NS)
|
|
65
|
-
else
|
|
66
|
-
@node.add('operation',what,:ack=>ack).namespaces.add(nil,XR_NS)
|
|
67
|
-
end
|
|
68
|
-
headers.each do |k,v|
|
|
69
|
-
@node.add('header',v,:name => k).namespaces.add(nil,XR_NS)
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def generate(mode=:output)
|
|
74
|
-
if @params.is_a?(Array) && @params.length == 1
|
|
75
|
-
body(@params[0],mode)
|
|
76
|
-
elsif @params.class == Riddl::Parameter::Simple || @params.class == Riddl::Parameter::Complex
|
|
77
|
-
body(@params,mode)
|
|
78
|
-
elsif @params.is_a?(Array) && @params.length > 1
|
|
79
|
-
multipart(mode)
|
|
80
|
-
else
|
|
81
|
-
@stanza
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def body(r,mode)
|
|
86
|
-
case r
|
|
87
|
-
when Riddl::Parameter::Simple
|
|
88
|
-
if mode == :output
|
|
89
|
-
n = @node.add('part',r.value)
|
|
90
|
-
n.namespaces.add(nil,XR_NS)
|
|
91
|
-
n.attributes['content-type'] = 'text/plain'
|
|
92
|
-
n.attributes['content-id'] = r.name
|
|
93
|
-
n.attributes['RIDDL-TYPE'] = 'simple'
|
|
94
|
-
end
|
|
95
|
-
if mode == :input
|
|
96
|
-
n = @node.add('part')
|
|
97
|
-
n.namespaces.add(nil,XR_NS)
|
|
98
|
-
n.attributes['content-type'] = 'application/x-www-form-urlencoded'
|
|
99
|
-
n.text = Riddl::Protocols::Utils::escape(r.name) + '=' + Riddl::Protocols::Utils::escape(r.value)
|
|
100
|
-
end
|
|
101
|
-
when Riddl::Parameter::Complex
|
|
102
|
-
n = @node.add('part')
|
|
103
|
-
n.namespaces.add(nil,XR_NS)
|
|
104
|
-
n.text = (r.value.respond_to?(:read) ? r.value.read : r.value)
|
|
105
|
-
n.attributes['content-type'] = r.mimetype + r.mimextra
|
|
106
|
-
n.attributes['RIDDL-TYPE'] = 'complex'
|
|
107
|
-
if r.filename.nil?
|
|
108
|
-
n.attributes['content-id'] = r.name
|
|
109
|
-
else
|
|
110
|
-
n.attributes['content-disposition'] = "riddl-data; name=\"#{r.name}\"; filename=\"#{r.filename}\""
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
@stanza
|
|
114
|
-
end
|
|
115
|
-
private :body
|
|
116
|
-
|
|
117
|
-
def multipart(mode)
|
|
118
|
-
scount = ccount = 0
|
|
119
|
-
@params.each do |r|
|
|
120
|
-
case r
|
|
121
|
-
when Riddl::Parameter::Simple
|
|
122
|
-
scount += 1
|
|
123
|
-
when Riddl::Parameter::Complex
|
|
124
|
-
ccount += 1
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
if scount > 0 && ccount == 0
|
|
128
|
-
n = @node.add('part')
|
|
129
|
-
n.namespaces.add(nil,XR_NS)
|
|
130
|
-
n.attributes['content-type'] = 'application/x-www-form-urlencoded'
|
|
131
|
-
res = []
|
|
132
|
-
@params.each do |r|
|
|
133
|
-
case r
|
|
134
|
-
when Riddl::Parameter::Simple
|
|
135
|
-
res << Riddl::Protocols::Utils::escape(r.name) + '=' + Riddl::Protocols::Utils::escape(r.value)
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
n.text = res.join('&')
|
|
139
|
-
else
|
|
140
|
-
if scount + ccount > 0
|
|
141
|
-
@params.each do |r|
|
|
142
|
-
case r
|
|
143
|
-
when Riddl::Parameter::Simple
|
|
144
|
-
n = @node.add('part')
|
|
145
|
-
n.namespaces.add(nil,XR_NS)
|
|
146
|
-
n.attributes['RIDDL-TYPE'] = 'simple'
|
|
147
|
-
n.attributes['content-type'] = 'text/plain'
|
|
148
|
-
n.attributes['content-disposition'] = "#{mode == :input ? 'form-data' : 'riddl-data'}; name=\"#{r.name}\""
|
|
149
|
-
n.text = r.value
|
|
150
|
-
when Riddl::Parameter::Complex
|
|
151
|
-
n = @node.add('part')
|
|
152
|
-
n.namespaces.add(nil,XR_NS)
|
|
153
|
-
n.attributes['RIDDL-TYPE'] = 'complex'
|
|
154
|
-
n.attributes['content-disposition'] = "#{mode == :input ? 'form-data' : 'riddl-data'}; name=\"#{r.name}\"#{r.filename.nil? ? '' : "; filename=\"#{r.filename}\""}"
|
|
155
|
-
n.attributes['content-transfer-encoding'] = 'binary'
|
|
156
|
-
n.attributes['content-type'] = r.mimetype + r.mimextra
|
|
157
|
-
n.text = (r.value.respond_to?(:read) ? r.value.read : r.value)
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
end
|
|
162
|
-
@stanza
|
|
163
|
-
end
|
|
164
|
-
private :multipart
|
|
165
|
-
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
end
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../constants')
|
|
2
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../parameter')
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__) + '/../utils')
|
|
4
|
-
|
|
5
|
-
module Riddl
|
|
6
|
-
module Protocols
|
|
7
|
-
module XMPP
|
|
8
|
-
class Parser
|
|
9
|
-
FORM_CONTENT_TYPES = [
|
|
10
|
-
#{{{
|
|
11
|
-
'application/x-www-form-urlencoded'
|
|
12
|
-
#}}}
|
|
13
|
-
].freeze
|
|
14
|
-
|
|
15
|
-
STD_ATTRIBUTES = [
|
|
16
|
-
#{{{
|
|
17
|
-
'content-type',
|
|
18
|
-
'content-disposition',
|
|
19
|
-
'content-id',
|
|
20
|
-
'content-transfer-type',
|
|
21
|
-
'RIDDL-TYPE',
|
|
22
|
-
#}}}
|
|
23
|
-
].freeze
|
|
24
|
-
|
|
25
|
-
def parse_part(input,head,ctype,content_disposition,content_id,riddl_type)
|
|
26
|
-
#{{{
|
|
27
|
-
head = Hash[
|
|
28
|
-
head.map do |h|
|
|
29
|
-
STD_ATTRIBUTES.include?(h.qname.name) ? nil : [h.qname.name, h.value]
|
|
30
|
-
end.compact
|
|
31
|
-
]
|
|
32
|
-
ctype = nil if riddl_type == 'simple'
|
|
33
|
-
filename = content_disposition[/ filename="?([^\";]*)"?/ni, 1]
|
|
34
|
-
name = content_disposition[/ name="?([^\";]*)"?/ni, 1] || content_id
|
|
35
|
-
|
|
36
|
-
if ctype || filename
|
|
37
|
-
body = Parameter::Tempfile.new("RiddlMultipart")
|
|
38
|
-
body.binmode if body.respond_to?(:binmode)
|
|
39
|
-
else
|
|
40
|
-
body = ''
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
input.each { |i| body << i.dump }
|
|
44
|
-
body.rewind if body.respond_to?(:binmode)
|
|
45
|
-
|
|
46
|
-
add_to_params(name,body,filename,ctype,head)
|
|
47
|
-
#}}}
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def add_to_params(name,body,filename,ctype,head)
|
|
51
|
-
#{{{
|
|
52
|
-
if filename == ""
|
|
53
|
-
# filename is blank which means no file has been selected
|
|
54
|
-
elsif filename && ctype
|
|
55
|
-
body.rewind
|
|
56
|
-
|
|
57
|
-
# Take the basename of the upload's original filename.
|
|
58
|
-
# This handles the full Windows paths given by Internet Explorer
|
|
59
|
-
# (and perhaps other broken user agents) without affecting
|
|
60
|
-
# those which give the lone filename.
|
|
61
|
-
filename =~ /^(?:.*[:\\\/])?(.*)/m
|
|
62
|
-
filename = $1
|
|
63
|
-
|
|
64
|
-
@params << Parameter::Complex.new(name, ctype, body, filename, head)
|
|
65
|
-
elsif !filename && ctype
|
|
66
|
-
body.rewind
|
|
67
|
-
|
|
68
|
-
# Generic multipart cases, not coming from a form
|
|
69
|
-
@params << Parameter::Complex.new(name, ctype, body, nil, head)
|
|
70
|
-
else
|
|
71
|
-
@params << Parameter::Simple.new(name, body, :body)
|
|
72
|
-
end
|
|
73
|
-
#}}}
|
|
74
|
-
end
|
|
75
|
-
private :add_to_params
|
|
76
|
-
|
|
77
|
-
def parse_nested_query(qs, type)
|
|
78
|
-
#{{{
|
|
79
|
-
(qs || '').split(/[#{D}] */n).each do |p|
|
|
80
|
-
k, v = Riddl::Protocols::Utils::unescape(p).split('=', 2)
|
|
81
|
-
@params << Parameter::Simple.new(k,v,type)
|
|
82
|
-
end
|
|
83
|
-
#}}}
|
|
84
|
-
end
|
|
85
|
-
private :parse_nested_query
|
|
86
|
-
|
|
87
|
-
def initialize(query_string,input)
|
|
88
|
-
#{{{
|
|
89
|
-
@params = Riddl::Parameter::Array.new
|
|
90
|
-
|
|
91
|
-
parse_nested_query(query_string,:query)
|
|
92
|
-
|
|
93
|
-
input.find('/message/xr:part').each do |p|
|
|
94
|
-
content_type = p.attributes['content-type'] || nil
|
|
95
|
-
media_type = content_type && content_type.split(/\s*[;,]\s*/, 2).first.downcase
|
|
96
|
-
if FORM_CONTENT_TYPES.include?(media_type)
|
|
97
|
-
# sub is a fix for Safari Ajax postings that always append \0
|
|
98
|
-
parse_nested_query(p.text.sub(/\0\z/, ''),:body)
|
|
99
|
-
else
|
|
100
|
-
parse_part(p.children,p.attributes,content_type,p.attributes['content-disposition']||'',p.attributes['content-id']||'',p.attributes['RIDDL-TYPE']||'')
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
#}}}
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
attr_reader :params
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
end
|