riddl 0.99.105
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.
- data/AUTHORS +1 -0
- data/COPYING +165 -0
- data/INSTALL +24 -0
- data/README.rdoc +2 -0
- data/Rakefile +17 -0
- data/TODO +17 -0
- data/contrib/riddl.jpg +0 -0
- data/contrib/riddl.png +0 -0
- data/contrib/riddl.svg +138 -0
- data/lib/riddl/client.rb +423 -0
- data/lib/riddl/commonlogger.rb +16 -0
- data/lib/riddl/constants.rb +5 -0
- data/lib/riddl/error.rb +8 -0
- data/lib/riddl/handlers.rb +14 -0
- data/lib/riddl/handlers/oauth.rb +19 -0
- data/lib/riddl/handlers/plain-type.rb +21 -0
- data/lib/riddl/handlers/relaxng.rb +16 -0
- data/lib/riddl/handlers/xmlschema.rb +16 -0
- data/lib/riddl/header.rb +9 -0
- data/lib/riddl/implementation.rb +57 -0
- data/lib/riddl/ns/common-patterns/addon-security/request.xml +25 -0
- data/lib/riddl/ns/common-patterns/addon-security/response.xml +25 -0
- data/lib/riddl/ns/common-patterns/downloadify/1.0/downloadify.xml +18 -0
- data/lib/riddl/ns/common-patterns/notifications-consumer/1.0/consumer.xml +100 -0
- data/lib/riddl/ns/common-patterns/notifications-producer/1.0/producer.xml +204 -0
- data/lib/riddl/ns/common-patterns/properties/1.0/properties.schema.schema +140 -0
- data/lib/riddl/ns/common-patterns/properties/1.0/properties.schema.xsl +89 -0
- data/lib/riddl/ns/common-patterns/properties/1.0/properties.xml +150 -0
- data/lib/riddl/ns/common/datatypes-1_0.rng +79 -0
- data/lib/riddl/ns/common/relaxng-modular.rng +330 -0
- data/lib/riddl/ns/common/relaxng.rng +10 -0
- data/lib/riddl/ns/declaration/1.0/declaration.rng +114 -0
- data/lib/riddl/ns/description/1.0/description.rng +302 -0
- data/lib/riddl/option.rb +9 -0
- data/lib/riddl/parameter.rb +54 -0
- data/lib/riddl/protocols/http/generator.rb +121 -0
- data/lib/riddl/protocols/http/parser.rb +199 -0
- data/lib/riddl/protocols/websocket.rb +103 -0
- data/lib/riddl/protocols/xmpp/generator.rb +176 -0
- data/lib/riddl/protocols/xmpp/parser.rb +118 -0
- data/lib/riddl/roles.rb +15 -0
- data/lib/riddl/roles/http%3A%2F%2Foauth.net%2F1.0%2Faccess_token.rb +30 -0
- data/lib/riddl/roles/http%3A%2F%2Foauth.net%2F1.0%2Fon_behalf.rb +22 -0
- data/lib/riddl/roles/http%3A%2F%2Foauth.net%2F1.0%2Frequest_token.rb +30 -0
- data/lib/riddl/roles/http%3A%2F%2Foauth.net%2F1.0/base.rb +67 -0
- data/lib/riddl/server.rb +519 -0
- data/lib/riddl/utils/description.rb +29 -0
- data/lib/riddl/utils/downloadify.rb +14 -0
- data/lib/riddl/utils/erbserve.rb +23 -0
- data/lib/riddl/utils/fileserve.rb +31 -0
- data/lib/riddl/utils/notifications_producer.rb +310 -0
- data/lib/riddl/utils/properties.rb +474 -0
- data/lib/riddl/utils/xsloverlay.rb +21 -0
- data/lib/riddl/wrapper.rb +280 -0
- data/lib/riddl/wrapper/declaration.rb +103 -0
- data/lib/riddl/wrapper/declaration/facade.rb +94 -0
- data/lib/riddl/wrapper/declaration/interface.rb +34 -0
- data/lib/riddl/wrapper/declaration/tile.rb +107 -0
- data/lib/riddl/wrapper/description.rb +69 -0
- data/lib/riddl/wrapper/description/access.rb +108 -0
- data/lib/riddl/wrapper/description/message_and_transformation.rb +131 -0
- data/lib/riddl/wrapper/description/resource.rb +271 -0
- data/lib/riddl/wrapper/layerchecker.rb +33 -0
- data/lib/riddl/wrapper/messageparser.rb +221 -0
- data/lib/riddl/wrapper/resourcechecker.rb +98 -0
- data/ns/common-patterns/addon-security/request.xml +25 -0
- data/ns/common-patterns/addon-security/response.xml +25 -0
- data/ns/common-patterns/downloadify/1.0/downloadify.xml +18 -0
- data/ns/common-patterns/notifications-consumer/1.0/consumer.xml +100 -0
- data/ns/common-patterns/notifications-producer/1.0/producer.xml +204 -0
- data/ns/common-patterns/properties/1.0/properties.schema.schema +140 -0
- data/ns/common-patterns/properties/1.0/properties.schema.xsl +89 -0
- data/ns/common-patterns/properties/1.0/properties.xml +150 -0
- data/ns/common/datatypes-1_0.rng +79 -0
- data/ns/common/relaxng-modular.rng +330 -0
- data/ns/common/relaxng.rng +10 -0
- data/ns/declaration/1.0/declaration.rng +114 -0
- data/ns/description/1.0/description.rng +302 -0
- data/riddl.gemspec +33 -0
- data/test/smartrunner.rb +48 -0
- data/test/tc_declaration-distributed.rb +79 -0
- data/test/tc_declaration-hybrid.rb +71 -0
- data/test/tc_declaration-local.rb +47 -0
- data/test/tc_helloworld.rb +17 -0
- data/test/tc_producer.rb +54 -0
- data/test/tc_properties.rb +72 -0
- data/tools/flash-policy-server.rb +12 -0
- data/tools/riddlcheck +36 -0
- data/tools/riddlcheck-1_0 +36 -0
- data/tools/riddlprocess +51 -0
- data/tools/riddlprocess-1_0 +51 -0
- metadata +291 -0
@@ -0,0 +1,199 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../constants')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../parameter')
|
3
|
+
|
4
|
+
module Riddl
|
5
|
+
module Protocols
|
6
|
+
module HTTP
|
7
|
+
class Parser
|
8
|
+
MULTIPART_CONTENT_TYPES = [
|
9
|
+
#{{{
|
10
|
+
'multipart/form-data',
|
11
|
+
'multipart/related',
|
12
|
+
'multipart/mixed'
|
13
|
+
#}}}
|
14
|
+
].freeze
|
15
|
+
FORM_CONTENT_TYPES = [
|
16
|
+
#{{{
|
17
|
+
nil,
|
18
|
+
'application/x-www-form-urlencoded'
|
19
|
+
#}}}
|
20
|
+
].freeze
|
21
|
+
|
22
|
+
def self::unescape(s)
|
23
|
+
#{{{
|
24
|
+
return s if s.nil?
|
25
|
+
s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){
|
26
|
+
[$1.delete('%')].pack('H*')
|
27
|
+
}
|
28
|
+
#}}}
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse_content(input,ctype,content_length,content_disposition,content_id,riddl_type)
|
32
|
+
#{{{
|
33
|
+
# fixing for chunked?
|
34
|
+
|
35
|
+
ctype = nil if riddl_type == 'simple'
|
36
|
+
filename = content_disposition[/ filename="?([^\";]*)"?/ni, 1]
|
37
|
+
name = content_disposition[/ name="?([^\";]*)"?/ni, 1] || content_id
|
38
|
+
|
39
|
+
if ctype || filename
|
40
|
+
body = Parameter::Tempfile.new("RiddlMultipart")
|
41
|
+
body.binmode if body.respond_to?(:binmode)
|
42
|
+
else
|
43
|
+
body = ''
|
44
|
+
end
|
45
|
+
|
46
|
+
if content_length == 0 && name == ''
|
47
|
+
body << input.read
|
48
|
+
end
|
49
|
+
|
50
|
+
bufsize = 16384
|
51
|
+
until content_length <= 0
|
52
|
+
c = input.read(bufsize < content_length ? bufsize : content_length)
|
53
|
+
raise EOFError, "bad content body" if c.nil? || c.empty?
|
54
|
+
body << c
|
55
|
+
content_length -= c.size
|
56
|
+
end
|
57
|
+
body.rewind if body.respond_to?(:binmode)
|
58
|
+
|
59
|
+
add_to_params(name,body,filename,ctype,nil)
|
60
|
+
#}}}
|
61
|
+
end
|
62
|
+
private :parse_content
|
63
|
+
|
64
|
+
def parse_multipart(input,content_type,content_length)
|
65
|
+
#{{{
|
66
|
+
content_type =~ %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|n
|
67
|
+
boundary = "--#{$1}"
|
68
|
+
|
69
|
+
boundary_size = boundary.size + EOL.size
|
70
|
+
content_length -= boundary_size
|
71
|
+
status = input.read(boundary_size)
|
72
|
+
raise EOFError, "bad content body" unless status == boundary + EOL
|
73
|
+
|
74
|
+
rx = /(?:#{EOL})?#{Regexp.quote boundary}(#{EOL}|--)/n
|
75
|
+
|
76
|
+
buf = ""
|
77
|
+
bufsize = 16384
|
78
|
+
loop do
|
79
|
+
head = nil
|
80
|
+
body = ''
|
81
|
+
filename = ctype = name = nil
|
82
|
+
|
83
|
+
until head && buf =~ rx
|
84
|
+
if !head && i = buf.index(EOL+EOL)
|
85
|
+
head = buf.slice!(0, i+2) # First \r\n
|
86
|
+
buf.slice!(0, 2) # Second \r\n
|
87
|
+
|
88
|
+
filename = head[/Content-Disposition:.* filename="?([^\";]*)"?/ni, 1]
|
89
|
+
ctype = head[/Content-Type: (.*)#{EOL}/ni, 1]
|
90
|
+
name = head[/Content-Disposition:.*\s+name="?([^\";]*)"?/ni, 1] || head[/Content-ID:\s*([^#{EOL}]*)/ni, 1]
|
91
|
+
|
92
|
+
if ctype || filename
|
93
|
+
body = Parameter::Tempfile.new("RiddlMultipart")
|
94
|
+
body.binmode if body.respond_to?(:binmode)
|
95
|
+
end
|
96
|
+
|
97
|
+
next
|
98
|
+
end
|
99
|
+
|
100
|
+
# Save the read body part.
|
101
|
+
if head && (boundary_size+4 < buf.size)
|
102
|
+
body << buf.slice!(0, buf.size - (boundary_size+4))
|
103
|
+
end
|
104
|
+
|
105
|
+
c = input.read(bufsize < content_length ? bufsize : content_length)
|
106
|
+
raise EOFError, "bad content body" if c.nil? || c.empty?
|
107
|
+
content_length -= c.size
|
108
|
+
buf << c
|
109
|
+
end
|
110
|
+
|
111
|
+
# Save the rest.
|
112
|
+
if i = buf.index(rx)
|
113
|
+
body << buf.slice!(0, i)
|
114
|
+
buf.slice!(0, boundary_size+2)
|
115
|
+
content_length = -1 if $1 == "--"
|
116
|
+
end
|
117
|
+
|
118
|
+
add_to_params(name,body,filename,ctype,head)
|
119
|
+
|
120
|
+
break if buf.empty? || content_length == -1
|
121
|
+
end
|
122
|
+
#}}}
|
123
|
+
end
|
124
|
+
private :parse_multipart
|
125
|
+
|
126
|
+
def add_to_params(name,body,filename,ctype,head)
|
127
|
+
#{{{
|
128
|
+
if filename == ""
|
129
|
+
# filename is blank which means no file has been selected
|
130
|
+
elsif filename && ctype
|
131
|
+
body.rewind
|
132
|
+
|
133
|
+
# Take the basename of the upload's original filename.
|
134
|
+
# This handles the full Windows paths given by Internet Explorer
|
135
|
+
# (and perhaps other broken user agents) without affecting
|
136
|
+
# those which give the lone filename.
|
137
|
+
filename =~ /^(?:.*[:\\\/])?(.*)/m
|
138
|
+
filename = $1
|
139
|
+
|
140
|
+
@params << Parameter::Complex.new(name, ctype, body, filename, head)
|
141
|
+
elsif !filename && ctype
|
142
|
+
body.rewind
|
143
|
+
|
144
|
+
# Generic multipart cases, not coming from a form
|
145
|
+
@params << Parameter::Complex.new(name, ctype, body, nil, head)
|
146
|
+
else
|
147
|
+
@params << Parameter::Simple.new(name, body, :body)
|
148
|
+
end
|
149
|
+
#}}}
|
150
|
+
end
|
151
|
+
private :add_to_params
|
152
|
+
|
153
|
+
def parse_nested_query(qs, type)
|
154
|
+
#{{{
|
155
|
+
(qs || '').split(/[#{D}] */n).each do |p|
|
156
|
+
k, v = self.class::unescape(p).split('=', 2)
|
157
|
+
@params << Parameter::Simple.new(k,v,type)
|
158
|
+
end
|
159
|
+
#}}}
|
160
|
+
end
|
161
|
+
private :parse_nested_query
|
162
|
+
|
163
|
+
def initialize(query_string,input,content_type,content_length,content_disposition,content_id,riddl_type)
|
164
|
+
#{{{
|
165
|
+
# rewind because in some cases it is not at start (when multipart without length)
|
166
|
+
|
167
|
+
begin
|
168
|
+
input.rewind if input.respond_to?(:rewind)
|
169
|
+
rescue Errno::ESPIPE
|
170
|
+
# Handles exceptions raised by input streams that cannot be rewound
|
171
|
+
# such as when using plain CGI under Apache
|
172
|
+
end
|
173
|
+
|
174
|
+
media_type = content_type && content_type.split(/\s*[;,]\s*/, 2).first.downcase
|
175
|
+
@params = Riddl::Parameter::Array.new
|
176
|
+
parse_nested_query(query_string,:query)
|
177
|
+
if MULTIPART_CONTENT_TYPES.include?(media_type)
|
178
|
+
parse_multipart(input,content_type,content_length.to_i)
|
179
|
+
elsif FORM_CONTENT_TYPES.include?(media_type)
|
180
|
+
# sub is a fix for Safari Ajax postings that always append \0
|
181
|
+
parse_nested_query(input.read.sub(/\0\z/, ''),:body)
|
182
|
+
else
|
183
|
+
parse_content(input,content_type,content_length.to_i,content_disposition||'',content_id||'',riddl_type||'')
|
184
|
+
end
|
185
|
+
|
186
|
+
begin
|
187
|
+
input.rewind if input.respond_to?(:rewind)
|
188
|
+
rescue Errno::ESPIPE
|
189
|
+
# Handles exceptions raised by input streams that cannot be rewound
|
190
|
+
# such as when using plain CGI under Apache
|
191
|
+
end
|
192
|
+
#}}}
|
193
|
+
end
|
194
|
+
|
195
|
+
attr_reader :params
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
gem 'em-websocket', '>= 0.4.0'
|
2
|
+
require 'em-websocket'
|
3
|
+
require 'thin'
|
4
|
+
|
5
|
+
module Thin #{{{
|
6
|
+
class Connection
|
7
|
+
attr_accessor :websocket
|
8
|
+
def websocket?
|
9
|
+
!self.websocket.nil?
|
10
|
+
end
|
11
|
+
|
12
|
+
def pre_process_with_websocket
|
13
|
+
@request.env['thin.connection'] = self
|
14
|
+
pre_process_without_websocket
|
15
|
+
end
|
16
|
+
alias :pre_process_without_websocket :pre_process
|
17
|
+
alias :pre_process :pre_process_with_websocket
|
18
|
+
|
19
|
+
def receive_data_with_websocket(data)
|
20
|
+
if self.websocket?
|
21
|
+
self.websocket.receive_data(data)
|
22
|
+
else
|
23
|
+
receive_data_without_websocket(data)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
alias :receive_data_without_websocket :receive_data
|
27
|
+
alias :receive_data :receive_data_with_websocket
|
28
|
+
|
29
|
+
def unbind_with_websocket
|
30
|
+
if self.websocket?
|
31
|
+
self.websocket.unbind
|
32
|
+
else
|
33
|
+
unbind_without_websocket
|
34
|
+
end
|
35
|
+
end
|
36
|
+
alias :unbind_without_websocket :unbind
|
37
|
+
alias :unbind :unbind_with_websocket
|
38
|
+
end
|
39
|
+
end #}}}
|
40
|
+
|
41
|
+
class WebSocketParserData
|
42
|
+
attr_accessor :headers, :request_path, :query_string, :http_method, :body, :request_url
|
43
|
+
def match(what)
|
44
|
+
@body =~ what
|
45
|
+
end
|
46
|
+
def upgrade?
|
47
|
+
true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module EventMachine
|
52
|
+
module WebSocket
|
53
|
+
class Handshake
|
54
|
+
def receive_data(data)
|
55
|
+
@parser = data
|
56
|
+
@headers = data.headers
|
57
|
+
process(@headers, data.body)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
module Riddl
|
64
|
+
class WebSocket < ::EventMachine::WebSocket::Connection
|
65
|
+
class Error < RuntimeError; end
|
66
|
+
|
67
|
+
def self.new(*args)
|
68
|
+
instance = allocate
|
69
|
+
instance.__send__(:initialize, *args)
|
70
|
+
instance
|
71
|
+
end
|
72
|
+
|
73
|
+
def send_data(*args)
|
74
|
+
EM.next_tick do
|
75
|
+
@socket.send_data(*args)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def close_connection(*args)
|
80
|
+
EM.next_tick do
|
81
|
+
@socket.close_connection(*args)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def trigger_on_message(msg); @app.onmessage(msg); end
|
86
|
+
def trigger_on_open(handshake); @closed = false; @app.onopen; end
|
87
|
+
def trigger_on_close; @closed = true; @app.onclose; end
|
88
|
+
def trigger_on_error(error); @closed = true; @app.onerror(error); true; end
|
89
|
+
|
90
|
+
def initialize(app, socket)
|
91
|
+
@app = app
|
92
|
+
@socket = socket
|
93
|
+
@ssl = socket.backend.respond_to?(:ssl?) && socket.backend.ssl?
|
94
|
+
@closed = true
|
95
|
+
socket.websocket = self
|
96
|
+
socket.comm_inactivity_timeout = 0
|
97
|
+
end
|
98
|
+
|
99
|
+
def closed?
|
100
|
+
@closed
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../constants')
|
2
|
+
require 'blather/client/client'
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
module Riddl
|
6
|
+
module Protocols
|
7
|
+
module XMPP
|
8
|
+
XR_NS = 'http://www.fp7-adventure.eu/ns/xmpp-rest'.freeze
|
9
|
+
|
10
|
+
class Stanza < Blather::Stanza
|
11
|
+
def self.new
|
12
|
+
node = super :message
|
13
|
+
node.type = :normal
|
14
|
+
node.id = SecureRandom.uuid
|
15
|
+
node
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Error
|
20
|
+
MAPPING = {
|
21
|
+
302 => ['redirect' , 'modify' , '302 Redirect' ],
|
22
|
+
400 => ['bad-request' , 'modify' , '400 Bad Request' ],
|
23
|
+
401 => ['not-authorized' , 'auth' , '401 Not Authorized ' ],
|
24
|
+
402 => ['payment-required' , 'auth' , '402 Payment Required' ],
|
25
|
+
403 => ['forbidden' , 'auth' , '403 Forbidden' ],
|
26
|
+
404 => ['item-not-found' , 'cancel' , '404 Not Found' ],
|
27
|
+
405 => ['not-allowed' , 'cancel' , '405 Not Allowed' ],
|
28
|
+
406 => ['not-acceptable' , 'modify' , '406 Not Acceptable' ],
|
29
|
+
407 => ['registration-required' , 'auth' , '407 Registration Required' ],
|
30
|
+
408 => ['remote-server-timeout' , 'wait' , '408 Request Timeout' ],
|
31
|
+
409 => ['conflict' , 'cancel' , '409 Conflict' ],
|
32
|
+
500 => ['internal-server-error' , 'wait' , '500 Internal Server Error' ],
|
33
|
+
501 => ['feature-not-implemented' , 'cancel' , '501 Not Implemented' ],
|
34
|
+
502 => ['service-unavailable' , 'wait' , '502 Remote Server Error' ],
|
35
|
+
503 => ['service-unavailable' , 'cancel' , '503 Service Unavailable' ],
|
36
|
+
504 => ['remote-server-timeout' , 'wait' , '504 Remote Server Timeout' ],
|
37
|
+
510 => ['service-unavailable' , 'cancel' , '510 Disconnected' ]
|
38
|
+
}.freeze
|
39
|
+
UNDEFINED = [
|
40
|
+
'undefined-condition', 'modify'
|
41
|
+
].freeze
|
42
|
+
|
43
|
+
def initialize(err)
|
44
|
+
m = Stanza.new
|
45
|
+
@stanza = if MAPPING[err]
|
46
|
+
Blather::StanzaError.new(m,*MAPPING[err]).to_node
|
47
|
+
else
|
48
|
+
Blather::StanzaError.new(m,*UNDEFINED,'#{err} see http://www.iana.org/assignments/http-status-codes/http-status-codes.xml').to_node
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def generate
|
53
|
+
@stanza
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class Generator
|
58
|
+
def initialize(what,params,headers)
|
59
|
+
@params = params
|
60
|
+
@stanza = Stanza.new
|
61
|
+
@node = XML::Smart::Dom::Element.new(@stanza)
|
62
|
+
if what.is_a?(Fixnum)
|
63
|
+
@node.add('ok').namespaces.add(nil,XR_NS)
|
64
|
+
else
|
65
|
+
@node.add('operation',what).namespaces.add(nil,XR_NS)
|
66
|
+
end
|
67
|
+
headers.each do |k,v|
|
68
|
+
@node.add('header',v,:name => k).namespaces.add(nil,XR_NS)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Performs URI escaping so that you can construct proper
|
73
|
+
# query strings faster. Use this rather than the cgi.rb
|
74
|
+
# version since it's faster. (%20 instead of + for improved standards conformance).
|
75
|
+
def self.escape(s)
|
76
|
+
s.to_s.gsub(/([^a-zA-Z0-9_.-]+)/n) {
|
77
|
+
'%'+$1.unpack('H2'*$1.size).join('%').upcase
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
def generate(mode=:output)
|
82
|
+
if @params.is_a?(Array) && @params.length == 1
|
83
|
+
body(@params[0],mode)
|
84
|
+
elsif @params.class == Riddl::Parameter::Simple || @params.class == Riddl::Parameter::Complex
|
85
|
+
body(@params,mode)
|
86
|
+
elsif @params.is_a?(Array) && @params.length > 1
|
87
|
+
multipart(mode)
|
88
|
+
else
|
89
|
+
@stanza
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def body(r,mode)
|
94
|
+
case r
|
95
|
+
when Riddl::Parameter::Simple
|
96
|
+
if mode == :output
|
97
|
+
n = @node.add('part',r.value)
|
98
|
+
n.namespaces.add(nil,XR_NS)
|
99
|
+
n.attributes['content-type'] = 'text/plain'
|
100
|
+
n.attributes['content-id'] = r.name
|
101
|
+
n.attributes['RIDDL-TYPE'] = 'simple'
|
102
|
+
end
|
103
|
+
if mode == :input
|
104
|
+
n = @node.add('part')
|
105
|
+
n.namespaces.add(nil,XR_NS)
|
106
|
+
n.attributes['content-type'] = 'application/x-www-form-urlencoded'
|
107
|
+
n.text = self.class::escape(r.name) + '=' + self.class::escape(r.value)
|
108
|
+
end
|
109
|
+
when Riddl::Parameter::Complex
|
110
|
+
n = @node.add('part')
|
111
|
+
n.namespaces.add(nil,XR_NS)
|
112
|
+
n.text = (r.value.respond_to?(:read) ? r.value.read : r.value)
|
113
|
+
n.attributes['content-type'] = r.mimetype
|
114
|
+
n.attributes['RIDDL-TYPE'] = 'complex'
|
115
|
+
if r.filename.nil?
|
116
|
+
n.attributes['content-id'] = r.name
|
117
|
+
else
|
118
|
+
n.attributes['content-disposition'] = "riddl-data; name=\"#{r.name}\"; filename=\"#{r.filename}\""
|
119
|
+
end
|
120
|
+
end
|
121
|
+
@stanza
|
122
|
+
end
|
123
|
+
private :body
|
124
|
+
|
125
|
+
def multipart(mode)
|
126
|
+
scount = ccount = 0
|
127
|
+
@params.each do |r|
|
128
|
+
case r
|
129
|
+
when Riddl::Parameter::Simple
|
130
|
+
scount += 1
|
131
|
+
when Riddl::Parameter::Complex
|
132
|
+
ccount += 1
|
133
|
+
end
|
134
|
+
end
|
135
|
+
if scount > 0 && ccount == 0
|
136
|
+
n = @node.add('part')
|
137
|
+
n.namespaces.add(nil,XR_NS)
|
138
|
+
n.attributes['content-type'] = 'application/x-www-form-urlencoded'
|
139
|
+
res = []
|
140
|
+
@params.each do |r|
|
141
|
+
case r
|
142
|
+
when Riddl::Parameter::Simple
|
143
|
+
res << self.class::escape(r.name) + '=' + self.class::escape(r.value)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
n.text = res.join('&')
|
147
|
+
else
|
148
|
+
if scount + ccount > 0
|
149
|
+
@params.each do |r|
|
150
|
+
case r
|
151
|
+
when Riddl::Parameter::Simple
|
152
|
+
n = @node.add('part')
|
153
|
+
n.namespaces.add(nil,XR_NS)
|
154
|
+
n.attributes['RIDDL-TYPE'] = 'simple'
|
155
|
+
n.attributes['content-disposition'] = "#{mode == :input ? 'form-data' : 'riddl-data'}; name=\"#{r.name}\""
|
156
|
+
n.text = r.value
|
157
|
+
when Riddl::Parameter::Complex
|
158
|
+
n = @node.add('part')
|
159
|
+
n.namespaces.add(nil,XR_NS)
|
160
|
+
n.attributes['RIDDL-TYPE'] = 'complex'
|
161
|
+
n.attributes['content-disposition'] = "#{mode == :input ? 'form-data' : 'riddl-data'}; name=\"#{r.name}\"#{r.filename.nil? ? '' : "; filename=\"#{r.filename}\""}"
|
162
|
+
n.attributes['content-transfer-encoding'] = 'binary'
|
163
|
+
n.attributes['content-type'] = r.mimetype
|
164
|
+
n.text = (r.value.respond_to?(:read) ? r.value.read : r.value)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
@stanza
|
170
|
+
end
|
171
|
+
private :multipart
|
172
|
+
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|