cgialt 0.0.1

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,146 @@
1
+ require 'test/unit'
2
+ #require 'cgi'
3
+ require(ENV['CGI'] || 'cgi')
4
+
5
+
6
+ class CGIModrubyTest < Test::Unit::TestCase
7
+
8
+
9
+ def setup
10
+ @environ = {
11
+ 'SERVER_PROTOCOL' => 'HTTP/1.1',
12
+ 'REQUEST_METHOD' => 'GET',
13
+ #'QUERY_STRING' => 'a=foo&b=bar',
14
+ }
15
+ ENV.update(@environ)
16
+ CGI.class_eval { const_set(:MOD_RUBY, true) }
17
+ Apache._reset()
18
+ #@cgi = CGI.new
19
+ #@req = Apache.request
20
+ end
21
+
22
+
23
+ def teardown
24
+ @environ.each do |key, val| ENV.delete(key) end
25
+ CGI.class_eval { remove_const(:MOD_RUBY) }
26
+ end
27
+
28
+
29
+ def test_cgi_modruby_simple
30
+ req = Apache.request
31
+ cgi = CGI.new
32
+ assert(req._setup_cgi_env_invoked?)
33
+ assert(! req._send_http_header_invoked?)
34
+ actual = cgi.header
35
+ assert_equal('', actual)
36
+ assert_equal('text/html', req.content_type)
37
+ assert(req._send_http_header_invoked?)
38
+ end
39
+
40
+
41
+ def test_cgi_modruby_complex
42
+ req = Apache.request
43
+ cgi = CGI.new
44
+ options = {
45
+ 'status' => 'FORBIDDEN',
46
+ 'location' => 'http://www.example.com/',
47
+ 'type' => 'image/gif',
48
+ 'content-encoding' => 'deflate',
49
+ 'cookie' => [ CGI::Cookie.new('name1', 'abc', '123'),
50
+ CGI::Cookie.new('name'=>'name2', 'value'=>'value2', 'secure'=>true),
51
+ ],
52
+ }
53
+ assert(req._setup_cgi_env_invoked?)
54
+ assert(! req._send_http_header_invoked?)
55
+ actual = cgi.header(options)
56
+ assert_equal('', actual)
57
+ assert_equal('image/gif', req.content_type)
58
+ assert_equal('403 Forbidden', req.status_line)
59
+ assert_equal(403, req.status)
60
+ assert_equal('deflate', req.content_encoding)
61
+ assert_equal('http://www.example.com/', req.headers_out['location'])
62
+ assert_equal(["name1=abc&123; path=", "name2=value2; path=; secure"],
63
+ req.headers_out['Set-Cookie'])
64
+ assert(req._send_http_header_invoked?)
65
+ end
66
+
67
+
68
+ def test_cgi_modruby_location
69
+ req = Apache.request
70
+ cgi = CGI.new
71
+ options = {
72
+ 'status' => '200 OK',
73
+ 'location' => 'http://www.example.com/',
74
+ }
75
+ actual = cgi.header(options)
76
+ assert_equal('200 OK', req.status_line) # should be '302 Found' ?
77
+ assert_equal(302, req.status)
78
+ assert_equal('http://www.example.com/', req.headers_out['location'])
79
+ end
80
+
81
+
82
+ def test_cgi_modruby_requestparams
83
+ req = Apache.request
84
+ req.args = 'a=foo&b=bar'
85
+ cgi = CGI.new
86
+ assert_equal('foo', cgi['a'])
87
+ assert_equal('bar', cgi['b'])
88
+ end
89
+
90
+
91
+ instance_methods.each do |method|
92
+ private method if method =~ /^test_(.*)/ && $1 != ENV['TEST']
93
+ end if ENV['TEST']
94
+
95
+ end
96
+
97
+
98
+
99
+ ## dummy class for mod_ruby
100
+ class Apache #:nodoc:
101
+
102
+ def self._reset
103
+ @request = Request.new
104
+ end
105
+
106
+ def self.request
107
+ return @request
108
+ end
109
+
110
+ class Request
111
+
112
+ def initialize
113
+ hash = {}
114
+ def hash.add(name, value)
115
+ (self[name] ||= []) << value
116
+ end
117
+ @headers_out = hash
118
+ @status_line = nil
119
+ @status = nil
120
+ @content_type = nil
121
+ @content_encoding = nil
122
+ end
123
+ attr_accessor :headers_out, :status_line, :status, :content_type, :content_encoding
124
+
125
+ attr_accessor :args
126
+ #def args
127
+ # return ENV['QUERY_STRING']
128
+ #end
129
+
130
+ def send_http_header
131
+ @http_header = '*invoked*'
132
+ end
133
+ def _send_http_header_invoked?
134
+ @http_header ? true : false
135
+ end
136
+
137
+ def setup_cgi_env
138
+ @cgi_env = '*invoked*'
139
+ end
140
+ def _setup_cgi_env_invoked?
141
+ @cgi_env ? true : false
142
+ end
143
+
144
+ end
145
+
146
+ end
@@ -0,0 +1,295 @@
1
+ require 'test/unit'
2
+ #require 'cgi'
3
+ require(ENV['CGI'] || 'cgi')
4
+ require 'tempfile'
5
+ require 'stringio'
6
+
7
+
8
+ ##
9
+ ## usage:
10
+ ## boundary = 'foobar1234' # or nil
11
+ ## multipart = MultiPart.new(boundary)
12
+ ## multipart.append('name1', 'value1')
13
+ ## multipart.append('file1', File.read('file1.html'), 'file1.html')
14
+ ## str = multipart.close()
15
+ ## str.each_line {|line| p line }
16
+ ## ## output:
17
+ ## # "--foobar1234\r\n"
18
+ ## # "Content-Disposition: form-data: name=\"name1\"\r\n"
19
+ ## # "\r\n"
20
+ ## # "value1\r\n"
21
+ ## # "--foobar1234\r\n"
22
+ ## # "Content-Disposition: form-data: name=\"file1\"; filename=\"file1.html\"\r\n"
23
+ ## # "Content-Type: text/html\r\n"
24
+ ## # "\r\n"
25
+ ## # "<html>\n"
26
+ ## # "<body><p>Hello</p></body>\n"
27
+ ## # "</html>\n"
28
+ ## # "\r\n"
29
+ ## # "--foobar1234--\r\n"
30
+ ##
31
+ class MultiPart
32
+
33
+ def initialize(boundary=nil)
34
+ @boundary = boundary || create_boundary()
35
+ @buf = ''
36
+ end
37
+ attr_reader :boundary
38
+
39
+ def append(name, value, filename=nil, content_type=nil)
40
+ content_type = detect_content_type(filename) if filename && content_type.nil?
41
+ s = filename ? "; filename=\"#{filename}\"" : ''
42
+ buf = @buf
43
+ buf << "--#{boundary}\r\n"
44
+ buf << "Content-Disposition: form-data: name=\"#{name}\"#{s}\r\n"
45
+ buf << "Content-Type: #{content_type}\r\n" if content_type
46
+ buf << "\r\n"
47
+ buf << value
48
+ buf << "\r\n"
49
+ return self
50
+ end
51
+
52
+ def close
53
+ buf = @buf
54
+ @buf = ''
55
+ return buf << "--#{boundary}--\r\n"
56
+ end
57
+
58
+ def create_boundary() #:nodoc:
59
+ return "--boundary#{rand().to_s[2..-1]}"
60
+ end
61
+
62
+ def detect_content_type(filename) #:nodoc:
63
+ filename =~ /\.(\w+)\z/
64
+ return MIME_TYPES[$1] || 'application/octet-stream'
65
+ end
66
+
67
+ MIME_TYPES = {
68
+ 'gif' => 'image/gif',
69
+ 'jpg' => 'image/jpeg',
70
+ 'jpeg' => 'image/jpeg',
71
+ 'png' => 'image/png',
72
+ 'bmp' => 'image/bmp',
73
+ 'tif' => 'image/tiff',
74
+ 'tiff' => 'image/tiff',
75
+ 'htm' => 'text/html',
76
+ 'html' => 'text/html',
77
+ 'xml' => 'text/xml',
78
+ 'txt' => 'text/plain',
79
+ 'text' => 'text/plain',
80
+ 'css' => 'text/css',
81
+ 'mpg' => 'video/mpeg',
82
+ 'mpeg' => 'video/mpeg',
83
+ 'mov' => 'video/quicktime',
84
+ 'avi' => 'video/x-msvideo',
85
+ 'mp3' => 'audio/mpeg',
86
+ 'mid' => 'audio/midi',
87
+ 'wav' => 'audio/x-wav',
88
+ 'zip' => 'application/zip',
89
+ #'tar.gz' => 'application/gtar',
90
+ 'gz' => 'application/gzip',
91
+ 'bz2' => 'application/bzip2',
92
+ 'rtf' => 'application/rtf',
93
+ 'pdf' => 'application/pdf',
94
+ 'ps' => 'application/postscript',
95
+ 'js' => 'application/x-javascript',
96
+ 'xls' => 'application/vnd.ms-excel',
97
+ 'doc' => 'application/msword',
98
+ 'ppt' => 'application/vnd.ms-powerpoint',
99
+ }
100
+
101
+ end
102
+
103
+
104
+
105
+ class CGIMultipartTest < Test::Unit::TestCase
106
+
107
+ def setup
108
+ ENV['REQUEST_METHOD'] = 'POST'
109
+ end
110
+
111
+ def teardown
112
+ %[REQUEST_METHOD CONTENT_TYPE CONTENT_LENGTH REQUEST_METHOD].each do |name|
113
+ ENV.delete(name)
114
+ end
115
+ $stdin.close() if $stdin.is_a?(Tempfile)
116
+ $stdin = STDIN
117
+ end
118
+
119
+ def _prepare(data)
120
+ ## create multipart input
121
+ multipart = MultiPart.new(@boundary)
122
+ data.each do |hash|
123
+ multipart.append(hash[:name], hash[:value], hash[:filename])
124
+ end
125
+ input = multipart.close()
126
+ input = yield(input) if block_given?
127
+ #$stderr.puts "*** debug: input=\n#{input.collect{|line| line.inspect}.join("\n")}"
128
+ @boundary ||= multipart.boundary
129
+ ## set environment
130
+ ENV['CONTENT_TYPE'] = "multipart/form-data; boundary=#{@boundary}"
131
+ ENV['CONTENT_LENGTH'] = input.length.to_s
132
+ ENV['REQUEST_METHOD'] = 'POST'
133
+ ## set $stdin
134
+ tmpfile = Tempfile.new(self.name)
135
+ tmpfile << input
136
+ tmpfile.rewind()
137
+ $stdin = tmpfile
138
+ end
139
+
140
+ def _test_multipart
141
+ caller(0).find {|s| s =~ /in `test_(.*?)'/ }
142
+ testname = $1
143
+ #$stderr.puts "*** debug: testname=#{testname.inspect}"
144
+ _prepare(@data)
145
+ cgi = CGI.new
146
+ expected_names = @data.collect{|hash| hash[:name] }.sort
147
+ assert_equal(expected_names, cgi.params.keys.sort)
148
+ threshold = 1024*10
149
+ @data.each do |hash|
150
+ name = hash[:name]
151
+ expected = hash[:value]
152
+ expected_class = @expected_class || (hash[:value].length < threshold ? StringIO : Tempfile)
153
+ assert_kind_of(expected_class, cgi[name])
154
+ assert_equal(expected, cgi[name].read())
155
+ assert_equal(hash[:filename] || '', cgi[name].original_filename) #if hash[:filename]
156
+ assert_equal(hash[:content_type] || '', cgi[name].content_type) #if hash[:content_type]
157
+ end
158
+ end
159
+
160
+
161
+ def _read(basename)
162
+ filename = File.join(File.dirname(__FILE__), 'testdata', basename)
163
+ s = File.open(filename, 'rb') {|f| f.read() }
164
+ return s
165
+ end
166
+
167
+
168
+ def test_cgi_multipart_stringio
169
+ @boundary = '----WebKitFormBoundaryAAfvAII+YL9102cX'
170
+ @data = [
171
+ {:name=>'hidden1', :value=>'foobar'},
172
+ {:name=>'text1', :value=>"\202\240\202\242\202\244\202\246\202\250"},
173
+ {:name=>'file1', :value=>_read('file1.html'),
174
+ :filename=>'file1.html', :content_type=>'text/html'},
175
+ {:name=>'image1', :value=>_read('small.png'),
176
+ :filename=>'small.png', :content_type=>'image/png'}, # small image
177
+ ]
178
+ @expected_class = StringIO
179
+ _test_multipart()
180
+ end
181
+
182
+
183
+ def test_cgi_multipart_tempfile
184
+ @boundary = '----WebKitFormBoundaryAAfvAII+YL9102cX'
185
+ @data = [
186
+ {:name=>'hidden1', :value=>'foobar'},
187
+ {:name=>'text1', :value=>"\202\240\202\242\202\244\202\246\202\250"},
188
+ {:name=>'file1', :value=>_read('file1.html'),
189
+ :filename=>'file1.html', :content_type=>'text/html'},
190
+ {:name=>'image1', :value=>_read('large.png'),
191
+ :filename=>'large.png', :content_type=>'image/png'}, # large image
192
+ ]
193
+ @expected_class = Tempfile
194
+ _test_multipart()
195
+ end
196
+
197
+
198
+ def _set_const(klass, name, value)
199
+ old = nil
200
+ klass.class_eval do
201
+ old = const_get(name)
202
+ remove_const(name)
203
+ const_set(name, value)
204
+ end
205
+ return old
206
+ end
207
+
208
+
209
+ def test_cgi_multipart_maxmultipartlength
210
+ @data = [
211
+ {:name=>'image1', :value=>_read('large.png'),
212
+ :filename=>'large.png', :content_type=>'image/png'}, # large image
213
+ ]
214
+ original = _set_const(CGI, :MAX_MULTIPART_LENGTH, 2 * 1024)
215
+ begin
216
+ ex = assert_raise(StandardError) do
217
+ _test_multipart()
218
+ end
219
+ assert_equal("too large multipart data.", ex.message)
220
+ ensure
221
+ _set_const(CGI, :MAX_MULTIPART_LENGTH, original)
222
+ end
223
+ end if CGI.const_defined?(:MAX_MULTIPART_LENGTH)
224
+
225
+
226
+ def test_cgi_multipart_maxmultipartcount
227
+ @data = [
228
+ {:name=>'file1', :value=>_read('file1.html'),
229
+ :filename=>'file1.html', :content_type=>'text/html'},
230
+ ]
231
+ item = @data.first
232
+ 500.times { @data << item }
233
+ #original = _set_const(CGI, :MAX_MULTIPART_COUNT, 128)
234
+ begin
235
+ ex = assert_raise(StandardError) do
236
+ _test_multipart()
237
+ end
238
+ assert_equal("too many parameters.", ex.message)
239
+ ensure
240
+ #_set_const(CGI, :MAX_MULTIPART_COUNT, original)
241
+ end
242
+ end if CGI.const_defined?(:MAX_MULTIPART_COUNT)
243
+
244
+
245
+ def test_cgi_multipart_badbody ## [ruby-dev:28470]
246
+ @data = [
247
+ {:name=>'file1', :value=>_read('file1.html'),
248
+ :filename=>'file1.html', :content_type=>'text/html'},
249
+ ]
250
+ _prepare(@data) do |input|
251
+ input2 = input.sub(/--(\r\n)?\z/, "\r\n")
252
+ assert input2 != input
253
+ #p input2
254
+ input2
255
+ end
256
+ ex = assert_raise(EOFError) do
257
+ cgi = CGI.new
258
+ end
259
+ assert_equal("bad boundary end of body part", ex.message)
260
+ #
261
+ _prepare(@data) do |input|
262
+ input2 = input.sub(/--(\r\n)?\z/, "")
263
+ assert input2 != input
264
+ #p input2
265
+ input2
266
+ end
267
+ ex = assert_raise(EOFError) do
268
+ cgi = CGI.new
269
+ end
270
+ assert_equal("bad content body", ex.message)
271
+ end
272
+
273
+
274
+ def test_cgi_multipart_quoteboundary ## [JVN#84798830]
275
+ @boundary = '(.|\n)*'
276
+ @data = [
277
+ {:name=>'hidden1', :value=>'foobar'},
278
+ {:name=>'text1', :value=>"\202\240\202\242\202\244\202\246\202\250"},
279
+ {:name=>'file1', :value=>_read('file1.html'),
280
+ :filename=>'file1.html', :content_type=>'text/html'},
281
+ {:name=>'image1', :value=>_read('small.png'),
282
+ :filename=>'small.png', :content_type=>'image/png'}, # small image
283
+ ]
284
+ _prepare(@data)
285
+ cgi = CGI.new
286
+ assert_equal('file1.html', cgi['file1'].original_filename)
287
+ end
288
+
289
+ ###
290
+
291
+ self.instance_methods.each do |method|
292
+ private method if method =~ /^test_(.*)/ && $1 != ENV['TEST']
293
+ end if ENV['TEST']
294
+
295
+ end
@@ -0,0 +1,10 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
+ <html>
3
+ <head>
4
+ <title>ムスカ大佐のひとりごと</title>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF8">
6
+ </head>
7
+ <body>
8
+ <p>バカどもにはちょうどいい目くらましだ。</p>
9
+ </body>
10
+ </html>