From a705709f9ad0ea5f3cdcd2a5f60580e0d3b20bc5 Mon Sep 17 00:00:00 2001
From: Jacques Distler
Date: Sat, 26 Dec 2009 14:00:18 -0600
Subject: [PATCH] Vendor Rack 1.1
Also clean up some View stuff.
---
app/views/admin/edit_web.rhtml | 2 +-
app/views/file/import.rhtml | 2 +-
app/views/wiki/rollback.rhtml | 2 -
public/stylesheets/instiki.css | 7 -
vendor/plugins/rack/KNOWN-ISSUES | 3 +
vendor/plugins/rack/README | 83 +-
vendor/plugins/rack/Rakefile | 76 +-
vendor/plugins/rack/bin/rackup | 178 +---
vendor/plugins/rack/lib/rack.rb | 16 +-
vendor/plugins/rack/lib/rack/builder.rb | 17 +
vendor/plugins/rack/lib/rack/cascade.rb | 29 +-
vendor/plugins/rack/lib/rack/chunked.rb | 4 +-
vendor/plugins/rack/lib/rack/commonlogger.rb | 74 +-
vendor/plugins/rack/lib/rack/config.rb | 15 +
vendor/plugins/rack/lib/rack/content_type.rb | 2 +-
vendor/plugins/rack/lib/rack/directory.rb | 8 +-
vendor/plugins/rack/lib/rack/etag.rb | 23 +
vendor/plugins/rack/lib/rack/file.rb | 6 +-
vendor/plugins/rack/lib/rack/handler.rb | 19 +
vendor/plugins/rack/lib/rack/handler/cgi.rb | 2 +-
.../plugins/rack/lib/rack/handler/fastcgi.rb | 5 +-
vendor/plugins/rack/lib/rack/handler/lsws.rb | 5 +-
.../plugins/rack/lib/rack/handler/mongrel.rb | 13 +-
vendor/plugins/rack/lib/rack/handler/scgi.rb | 8 +-
.../plugins/rack/lib/rack/handler/webrick.rb | 6 +-
vendor/plugins/rack/lib/rack/lint.rb | 59 +-
vendor/plugins/rack/lib/rack/logger.rb | 20 +
vendor/plugins/rack/lib/rack/mime.rb | 4 +-
vendor/plugins/rack/lib/rack/mock.rb | 34 +-
vendor/plugins/rack/lib/rack/nulllogger.rb | 18 +
vendor/plugins/rack/lib/rack/reloader.rb | 5 +-
vendor/plugins/rack/lib/rack/request.rb | 55 +-
vendor/plugins/rack/lib/rack/response.rb | 44 +-
.../plugins/rack/lib/rack/rewindable_input.rb | 20 +-
vendor/plugins/rack/lib/rack/runtime.rb | 27 +
vendor/plugins/rack/lib/rack/sendfile.rb | 142 +++
vendor/plugins/rack/lib/rack/server.rb | 212 +++++
.../rack/lib/rack/session/abstract/id.rb | 8 +-
.../plugins/rack/lib/rack/session/cookie.rb | 7 +-
.../plugins/rack/lib/rack/session/memcache.rb | 96 ++-
vendor/plugins/rack/lib/rack/session/pool.rb | 2 +-
vendor/plugins/rack/lib/rack/urlmap.rb | 17 +-
vendor/plugins/rack/lib/rack/utils.rb | 241 +++++-
vendor/plugins/rack/rack.gemspec | 38 +
vendor/plugins/rack/test/cgi/test.ru | 3 +-
vendor/plugins/rack/test/multipart/bad_robots | 259 ++++++
.../rack/test/multipart/fail_16384_nofile | 814 ++++++++++++++++++
vendor/plugins/rack/test/multipart/file1.txt | 1 +
vendor/plugins/rack/test/rackup/.gitignore | 1 +
vendor/plugins/rack/test/rackup/config.ru | 31 +
vendor/plugins/rack/test/spec_rack_cascade.rb | 8 +-
vendor/plugins/rack/test/spec_rack_cgi.rb | 6 +-
.../rack/test/spec_rack_commonlogger.rb | 49 +-
vendor/plugins/rack/test/spec_rack_config.rb | 24 +
.../plugins/rack/test/spec_rack_directory.rb | 2 +-
vendor/plugins/rack/test/spec_rack_etag.rb | 17 +
vendor/plugins/rack/test/spec_rack_fastcgi.rb | 4 +-
vendor/plugins/rack/test/spec_rack_file.rb | 2 +-
vendor/plugins/rack/test/spec_rack_lint.rb | 45 +-
vendor/plugins/rack/test/spec_rack_logger.rb | 21 +
vendor/plugins/rack/test/spec_rack_mock.rb | 88 +-
vendor/plugins/rack/test/spec_rack_mongrel.rb | 8 +-
.../plugins/rack/test/spec_rack_nulllogger.rb | 13 +
vendor/plugins/rack/test/spec_rack_request.rb | 53 +-
.../plugins/rack/test/spec_rack_response.rb | 3 +
vendor/plugins/rack/test/spec_rack_runtime.rb | 35 +
.../plugins/rack/test/spec_rack_sendfile.rb | 86 ++
.../rack/test/spec_rack_session_memcache.rb | 73 +-
vendor/plugins/rack/test/spec_rack_urlmap.rb | 30 +
vendor/plugins/rack/test/spec_rack_utils.rb | 177 +++-
vendor/plugins/rack/test/spec_rack_webrick.rb | 8 +-
vendor/plugins/rack/test/spec_rackup.rb | 154 ++++
vendor/plugins/rack/test/testrequest.rb | 17 +-
.../rails/actionpack/lib/action_controller.rb | 2 +-
74 files changed, 3080 insertions(+), 608 deletions(-)
create mode 100644 vendor/plugins/rack/lib/rack/config.rb
create mode 100644 vendor/plugins/rack/lib/rack/etag.rb
create mode 100644 vendor/plugins/rack/lib/rack/logger.rb
create mode 100644 vendor/plugins/rack/lib/rack/nulllogger.rb
create mode 100644 vendor/plugins/rack/lib/rack/runtime.rb
create mode 100644 vendor/plugins/rack/lib/rack/sendfile.rb
create mode 100644 vendor/plugins/rack/lib/rack/server.rb
create mode 100644 vendor/plugins/rack/rack.gemspec
create mode 100644 vendor/plugins/rack/test/multipart/bad_robots
create mode 100644 vendor/plugins/rack/test/multipart/fail_16384_nofile
create mode 100644 vendor/plugins/rack/test/multipart/file1.txt
create mode 100644 vendor/plugins/rack/test/rackup/.gitignore
create mode 100644 vendor/plugins/rack/test/rackup/config.ru
create mode 100644 vendor/plugins/rack/test/spec_rack_config.rb
create mode 100644 vendor/plugins/rack/test/spec_rack_etag.rb
create mode 100644 vendor/plugins/rack/test/spec_rack_logger.rb
create mode 100644 vendor/plugins/rack/test/spec_rack_nulllogger.rb
create mode 100644 vendor/plugins/rack/test/spec_rack_runtime.rb
create mode 100644 vendor/plugins/rack/test/spec_rack_sendfile.rb
create mode 100644 vendor/plugins/rack/test/spec_rackup.rb
diff --git a/app/views/admin/edit_web.rhtml b/app/views/admin/edit_web.rhtml
index 83ca3ee2..0cd2acb6 100644
--- a/app/views/admin/edit_web.rhtml
+++ b/app/views/admin/edit_web.rhtml
@@ -18,7 +18,7 @@
onchange="proposeAddress();" />
- (Letters and digits only)
+ (Letters and digits only)
Specialize
diff --git a/app/views/file/import.rhtml b/app/views/file/import.rhtml
index 413c4c84..7e3a3e6f 100644
--- a/app/views/file/import.rhtml
+++ b/app/views/file/import.rhtml
@@ -15,7 +15,7 @@
<%- if @page -%>
- | <%= link_to 'Cancel', :web => @web.address, :action => 'file'%> (unlocks page)
+ | <%= link_to 'Cancel', :web => @web.address, :action => 'file'%> (unlocks page)
<%- end -%>
diff --git a/app/views/wiki/rollback.rhtml b/app/views/wiki/rollback.rhtml
index 0f4b5bad..7d3a14aa 100644
--- a/app/views/wiki/rollback.rhtml
+++ b/app/views/wiki/rollback.rhtml
@@ -4,8 +4,6 @@
@hide_navigation = true
-%>
-<%= "Please correct the error that caused this error in rendering:
#{params["msg"]}
" if params["msg"] %>
-
<%= render(:file => "#{@web.markup}_help") -%>
<%= render(:file => 'wiki_words_help') unless @web.brackets_only? -%>
diff --git a/public/stylesheets/instiki.css b/public/stylesheets/instiki.css
index cf6c4902..ade66ed8 100644
--- a/public/stylesheets/instiki.css
+++ b/public/stylesheets/instiki.css
@@ -61,13 +61,6 @@ margin:0.2em 0 0.2em 0;
padding:0;
}
-h1#pageName small {
-color:#444;
-font-size:35%;
-line-height:1em;
-padding:0;
-}
-
#svg_logo {
float:left;
margin:.5em .25em 0 -.625em;
diff --git a/vendor/plugins/rack/KNOWN-ISSUES b/vendor/plugins/rack/KNOWN-ISSUES
index 790199bd..a1af5dc1 100644
--- a/vendor/plugins/rack/KNOWN-ISSUES
+++ b/vendor/plugins/rack/KNOWN-ISSUES
@@ -16,3 +16,6 @@
end
Of course, use this only when your app runs at "/".
+
+ Since lighttpd 1.4.23, you also can use the "fix-root-scriptname" flag
+ in fastcgi.server.
diff --git a/vendor/plugins/rack/README b/vendor/plugins/rack/README
index c58009ff..70d3673a 100644
--- a/vendor/plugins/rack/README
+++ b/vendor/plugins/rack/README
@@ -11,21 +11,13 @@ which all Rack applications should conform to.
== Specification changes in this release
-With Rack 1.0, the Rack specification (found in SPEC) changed in the
-following backward-incompatible ways. This was done to properly
-support Ruby 1.9 and to deprecate some problematic techniques:
+With Rack 1.1, the Rack specification (found in SPEC) changed in the
+following backward-incompatible ways.
-* Rack::VERSION has been pushed to [1,0].
-* Header values must be Strings now, split on "\n".
-* rack.input must be rewindable and support reading into a buffer,
- wrap with Rack::RewindableInput if it isn't.
-* Content-Length can be missing, in this case chunked transfer
- encoding is used.
-* Bodies can now additionally respond to #to_path with a filename to
- be served.
-* String bodies are deprecated and will not work with Ruby 1.9, use an
- Array with a single String instead.
-* rack.session is now specified.
+* Rack::VERSION has been pushed to [1,1].
+* rack.logger is now specified.
+* The SPEC now allows subclasses of the required types.
+* rack.input has to be opened in binary mode.
== Supported web servers
@@ -43,8 +35,11 @@ The included *handlers* connect all kinds of web servers to Rack:
These web servers include Rack handlers in their distributions:
* Ebb
* Fuzed
+* Glassfish v3
* Phusion Passenger (which is mod_rack for Apache and for nginx)
+* Rainbows!
* Unicorn
+* Zbatery
Any valid Rack app will run the same on all these handlers, without
changing anything.
@@ -70,6 +65,7 @@ These frameworks include Rack adapters in their distributions:
* Vintage
* Waves
* Wee
+* ... and many others.
Current links to these projects can be found at
http://wiki.ramaze.net/Home#other-frameworks
@@ -130,13 +126,13 @@ Either with the embedded WEBrick starter:
Or with rackup:
- bin/rackup -Ilib example/lobster.ru
+ bin/rackup -Ilib example/lobster.ru
By default, the lobster is found at http://localhost:9292.
== Installing with RubyGems
-A Gem of Rack is available. You can install it with:
+A Gem of Rack is available at gemcutter.org. You can install it with:
gem install rack
@@ -165,7 +161,6 @@ To run the test suite completely, you need:
* fcgi
* memcache-client
* mongrel
- * ruby-openid
* thin
The full set of tests test FCGI access with lighttpd (on port
@@ -283,16 +278,49 @@ run on port 11211) and memcache-client installed.
* Make sure WEBrick respects the :Host option
* Many Ruby 1.9 fixes.
+* December ??th, 2009: Ninth public release 1.1.0.
+ * Moved Auth::OpenID to rack-contrib.
+ * SPEC change that relaxes Lint slightly to allow subclasses of the
+ required types
+ * SPEC change to document rack.input binary mode in greator detail
+ * SPEC define optional rack.logger specification
+ * File servers support X-Cascade header
+ * Imported Config middleware
+ * Imported ETag middleware
+ * Imported Runtime middleware
+ * Imported Sendfile middleware
+ * New Logger and NullLogger middlewares
+ * Added mime type for .ogv and .manifest.
+ * Don't squeeze PATH_INFO slashes
+ * Use Content-Type to determine POST params parsing
+ * Update Rack::Utils::HTTP_STATUS_CODES hash
+ * Add status code lookup utility
+ * Response should call #to_i on the status
+ * Add Request#user_agent
+ * Request#host knows about forwared host
+ * Return an empty string for Request#host if HTTP_HOST and
+ SERVER_NAME are both missing
+ * Allow MockRequest to accept hash params
+ * Optimizations to HeaderHash
+ * Refactored rackup into Rack::Server
+ * Added Utils.build_nested_query to complement Utils.parse_nested_query
+ * Added Utils::Multipart.build_multipart to complement
+ Utils::Multipart.parse_multipart
+ * Extracted set and delete cookie helpers into Utils so they can be
+ used outside Response
+ * Extract parse_query and parse_multipart in Request so subclasses
+ can change their behavior
+ * Enforce binary encoding in RewindableInput
+ * Set correct external_encoding for handlers that don't use RewindableInput
+
== Contact
-Please mail bugs, suggestions and patches to
-.
+Please post bugs, suggestions and patches to
+the bug tracker at .
Mailing list archives are available at
.
-There is a bug tracker at .
-
Git repository (send Git patches to the mailing list):
* http://github.com/rack/rack
* http://git.vuxu.org/cgi-bin/gitweb.cgi?p=rack.git
@@ -318,8 +346,14 @@ would like to thank:
* Luc Heinrich for the Cookie sessions, the static file handler and bugfixes.
* Armin Ronacher, for the logo and racktools.
* Aredridel, Ben Alpert, Dan Kubb, Daniel Roethlisberger, Matt Todd,
- Tom Robinson, Phil Hagelberg, and S. Brent Faulkner for bug fixing
- and other improvements.
+ Tom Robinson, Phil Hagelberg, S. Brent Faulkner, Bosko Milekic,
+ Daniel RodrÃguez Troitiño, Genki Takiuchi, Geoffrey Grosenbach,
+ Julien Sanchez, Kamal Fariz Mahyuddin, Masayoshi Takahashi, Patrick
+ Aljordm, Mig, and Kazuhiro Nishiyama for bug fixing and other
+ improvements.
+* Eric Wong, Hongli Lai, Jeremy Kemper for their continuous support
+ and API improvements.
+* Yehuda Katz and Carl Lerche for refactoring rackup.
* Brian Candler, for Rack::ContentType.
* Graham Batty, for improved handler loading.
* Stephen Bannasch, for bug reports and documentation.
@@ -349,7 +383,7 @@ all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -358,6 +392,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Rack::
Rack's Rubyforge project::
Official Rack repositories::
+Rack Lighthouse Bug Tracking::
rack-devel mailing list::
Christian Neukirchen::
diff --git a/vendor/plugins/rack/Rakefile b/vendor/plugins/rack/Rakefile
index c88f7aff..e22f060a 100644
--- a/vendor/plugins/rack/Rakefile
+++ b/vendor/plugins/rack/Rakefile
@@ -6,9 +6,8 @@ require 'rake/testtask'
desc "Run all the tests"
task :default => [:test]
-
desc "Make an archive as .tar.gz"
-task :dist => [:chmod, :changelog, :rdoc, "SPEC", "rack.gemspec"] do
+task :dist => [:chmod, :changelog, :rdoc, "SPEC"] do
FileUtils.touch("RDOX")
sh "git archive --format=tar --prefix=#{release}/ HEAD^{tree} >#{release}.tar"
sh "pax -waf #{release}.tar -s ':^:#{release}/:' RDOX SPEC ChangeLog doc rack.gemspec"
@@ -28,21 +27,11 @@ task :officialrelease_really => [:fulltest, "RDOX", "SPEC", :dist, :gem] do
sh "sha1sum #{release}.tar.gz #{release}.gem"
end
-
-def version
- abort "You need to pass VERSION=... to build packages." unless ENV["VERSION"]
- ENV["VERSION"]
-end
-
def release
- "rack-#{version}"
+ require File.dirname(__FILE__) + "/lib/rack"
+ "rack-#{Rack.release}"
end
-def manifest
- `git ls-files`.split("\n")
-end
-
-
desc "Make binaries executable"
task :chmod do
Dir["bin/*"].each { |binary| File.chmod(0775, binary) }
@@ -86,7 +75,7 @@ end
desc "Run all the fast tests"
task :test do
- sh "specrb -Ilib:test -w #{ENV['TEST'] || '-a'} #{ENV['TESTOPTS'] || '-t "^(?!Rack::Handler|Rack::Adapter|Rack::Session::Memcache|Rack::Auth::OpenID)"'}"
+ sh "specrb -Ilib:test -w #{ENV['TEST'] || '-a'} #{ENV['TESTOPTS'] || '-t "^(?!Rack::Handler|Rack::Adapter|Rack::Session::Memcache|rackup)"'}"
end
desc "Run all the tests"
@@ -94,63 +83,14 @@ task :fulltest => [:chmod] do
sh "specrb -Ilib:test -w #{ENV['TEST'] || '-a'} #{ENV['TESTOPTS']}"
end
-begin
- require 'rubygems'
-rescue LoadError
- # Too bad.
-else
- task "rack.gemspec" do
- spec = Gem::Specification.new do |s|
- s.name = "rack"
- s.version = version
- s.platform = Gem::Platform::RUBY
- s.summary = "a modular Ruby webserver interface"
-
- s.description = <<-EOF
-Rack provides minimal, modular and adaptable interface for developing
-web applications in Ruby. By wrapping HTTP requests and responses in
-the simplest way possible, it unifies and distills the API for web
-servers, web frameworks, and software in between (the so-called
-middleware) into a single method call.
-
-Also see http://rack.rubyforge.org.
- EOF
-
- s.files = manifest + %w(SPEC RDOX rack.gemspec)
- s.bindir = 'bin'
- s.executables << 'rackup'
- s.require_path = 'lib'
- s.has_rdoc = true
- s.extra_rdoc_files = ['README', 'SPEC', 'RDOX', 'KNOWN-ISSUES']
- s.test_files = Dir['test/{test,spec}_*.rb']
-
- s.author = 'Christian Neukirchen'
- s.email = 'chneukirchen@gmail.com'
- s.homepage = 'http://rack.rubyforge.org'
- s.rubyforge_project = 'rack'
-
- s.add_development_dependency 'test-spec'
-
- s.add_development_dependency 'camping'
- s.add_development_dependency 'fcgi'
- s.add_development_dependency 'memcache-client'
- s.add_development_dependency 'mongrel'
- s.add_development_dependency 'ruby-openid', '~> 2.0.0'
- s.add_development_dependency 'thin'
- end
-
- File.open("rack.gemspec", "w") { |f| f << spec.to_ruby }
- end
-
- task :gem => ["rack.gemspec", "SPEC"] do
- FileUtils.touch("RDOX")
- sh "gem build rack.gemspec"
- end
+task :gem => ["SPEC"] do
+ FileUtils.touch("RDOX")
+ sh "gem build rack.gemspec"
end
desc "Generate RDoc documentation"
task :rdoc do
- sh(*%w{rdoc --line-numbers --main README
+ sh(*%w{rdoc --line-numbers --main README
--title 'Rack\ Documentation' --charset utf-8 -U -o doc} +
%w{README KNOWN-ISSUES SPEC RDOX} +
Dir["lib/**/*.rb"])
diff --git a/vendor/plugins/rack/bin/rackup b/vendor/plugins/rack/bin/rackup
index 8e4df15e..a6f98913 100755
--- a/vendor/plugins/rack/bin/rackup
+++ b/vendor/plugins/rack/bin/rackup
@@ -1,176 +1,2 @@
-#!/usr/bin/env ruby
-# -*- ruby -*-
-
-$LOAD_PATH.unshift File.expand_path("#{__FILE__}/../../lib")
-autoload :Rack, 'rack'
-
-require 'optparse'
-
-automatic = false
-server = nil
-env = "development"
-daemonize = false
-pid = nil
-options = {:Port => 9292, :Host => "0.0.0.0", :AccessLog => []}
-
-# Don't evaluate CGI ISINDEX parameters.
-# http://hoohoo.ncsa.uiuc.edu/cgi/cl.html
-ARGV.clear if ENV.include?("REQUEST_METHOD")
-
-opts = OptionParser.new("", 24, ' ') { |opts|
- opts.banner = "Usage: rackup [ruby options] [rack options] [rackup config]"
-
- opts.separator ""
- opts.separator "Ruby options:"
-
- lineno = 1
- opts.on("-e", "--eval LINE", "evaluate a LINE of code") { |line|
- eval line, TOPLEVEL_BINDING, "-e", lineno
- lineno += 1
- }
-
- opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") {
- $DEBUG = true
- }
- opts.on("-w", "--warn", "turn warnings on for your script") {
- $-w = true
- }
-
- opts.on("-I", "--include PATH",
- "specify $LOAD_PATH (may be used more than once)") { |path|
- $LOAD_PATH.unshift(*path.split(":"))
- }
-
- opts.on("-r", "--require LIBRARY",
- "require the library, before executing your script") { |library|
- require library
- }
-
- opts.separator ""
- opts.separator "Rack options:"
- opts.on("-s", "--server SERVER", "serve using SERVER (webrick/mongrel)") { |s|
- server = s
- }
-
- opts.on("-o", "--host HOST", "listen on HOST (default: 0.0.0.0)") { |host|
- options[:Host] = host
- }
-
- opts.on("-p", "--port PORT", "use PORT (default: 9292)") { |port|
- options[:Port] = port
- }
-
- opts.on("-E", "--env ENVIRONMENT", "use ENVIRONMENT for defaults (default: development)") { |e|
- env = e
- }
-
- opts.on("-D", "--daemonize", "run daemonized in the background") { |d|
- daemonize = d ? true : false
- }
-
- opts.on("-P", "--pid FILE", "file to store PID (default: rack.pid)") { |f|
- pid = File.expand_path(f)
- }
-
- opts.separator ""
- opts.separator "Common options:"
-
- opts.on_tail("-h", "--help", "Show this message") do
- puts opts
- exit
- end
-
- opts.on_tail("--version", "Show version") do
- puts "Rack #{Rack.version}"
- exit
- end
-
- opts.parse! ARGV
-}
-
-require 'pp' if $DEBUG
-
-config = ARGV[0] || "config.ru"
-if !File.exist? config
- abort "configuration #{config} not found"
-end
-
-if config =~ /\.ru$/
- cfgfile = File.read(config)
- if cfgfile[/^#\\(.*)/]
- opts.parse! $1.split(/\s+/)
- end
- inner_app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app",
- nil, config
-else
- require config
- inner_app = Object.const_get(File.basename(config, '.rb').capitalize)
-end
-
-unless server = Rack::Handler.get(server)
- # Guess.
- if ENV.include?("PHP_FCGI_CHILDREN")
- server = Rack::Handler::FastCGI
-
- # We already speak FastCGI
- options.delete :File
- options.delete :Port
- elsif ENV.include?("REQUEST_METHOD")
- server = Rack::Handler::CGI
- else
- begin
- server = Rack::Handler::Mongrel
- rescue LoadError => e
- server = Rack::Handler::WEBrick
- end
- end
-end
-
-p server if $DEBUG
-
-case env
-when "development"
- app = Rack::Builder.new {
- use Rack::CommonLogger, $stderr unless server.name =~ /CGI/
- use Rack::ShowExceptions
- use Rack::Lint
- run inner_app
- }.to_app
-
-when "deployment"
- app = Rack::Builder.new {
- use Rack::CommonLogger, $stderr unless server.name =~ /CGI/
- run inner_app
- }.to_app
-
-when "none"
- app = inner_app
-
-end
-
-if $DEBUG
- pp app
- pp inner_app
-end
-
-if daemonize
- if RUBY_VERSION < "1.9"
- exit if fork
- Process.setsid
- exit if fork
- Dir.chdir "/"
- File.umask 0000
- STDIN.reopen "/dev/null"
- STDOUT.reopen "/dev/null", "a"
- STDERR.reopen "/dev/null", "a"
- else
- Process.daemon
- end
-
- if pid
- File.open(pid, 'w'){ |f| f.write("#{Process.pid}") }
- at_exit { File.delete(pid) if File.exist?(pid) }
- end
-end
-
-server.run app, options
+require "rack"
+Rack::Server.start
diff --git a/vendor/plugins/rack/lib/rack.rb b/vendor/plugins/rack/lib/rack.rb
index 371d0156..ecc238ee 100644
--- a/vendor/plugins/rack/lib/rack.rb
+++ b/vendor/plugins/rack/lib/rack.rb
@@ -3,10 +3,6 @@
# Rack is freely distributable under the terms of an MIT-style license.
# See COPYING or http://www.opensource.org/licenses/mit-license.php.
-path = File.expand_path(File.dirname(__FILE__))
-$:.unshift(path) unless $:.include?(path)
-
-
# The Rack main module, serving as a namespace for all core Rack
# modules and classes.
#
@@ -15,7 +11,7 @@ $:.unshift(path) unless $:.include?(path)
module Rack
# The Rack protocol version number implemented.
- VERSION = [1,0]
+ VERSION = [1,1]
# Return the Rack protocol version as a dotted string.
def self.version
@@ -24,7 +20,7 @@ module Rack
# Return the Rack release as a dotted string.
def self.release
- "1.0"
+ "1.1"
end
autoload :Builder, "rack/builder"
@@ -32,8 +28,10 @@ module Rack
autoload :Chunked, "rack/chunked"
autoload :CommonLogger, "rack/commonlogger"
autoload :ConditionalGet, "rack/conditionalget"
+ autoload :Config, "rack/config"
autoload :ContentLength, "rack/content_length"
autoload :ContentType, "rack/content_type"
+ autoload :ETag, "rack/etag"
autoload :File, "rack/file"
autoload :Deflater, "rack/deflater"
autoload :Directory, "rack/directory"
@@ -42,10 +40,15 @@ module Rack
autoload :Head, "rack/head"
autoload :Lint, "rack/lint"
autoload :Lock, "rack/lock"
+ autoload :Logger, "rack/logger"
autoload :MethodOverride, "rack/methodoverride"
autoload :Mime, "rack/mime"
+ autoload :NullLogger, "rack/nulllogger"
autoload :Recursive, "rack/recursive"
autoload :Reloader, "rack/reloader"
+ autoload :Runtime, "rack/runtime"
+ autoload :Sendfile, "rack/sendfile"
+ autoload :Server, "rack/server"
autoload :ShowExceptions, "rack/showexceptions"
autoload :ShowStatus, "rack/showstatus"
autoload :Static, "rack/static"
@@ -62,7 +65,6 @@ module Rack
autoload :Basic, "rack/auth/basic"
autoload :AbstractRequest, "rack/auth/abstract/request"
autoload :AbstractHandler, "rack/auth/abstract/handler"
- autoload :OpenID, "rack/auth/openid"
module Digest
autoload :MD5, "rack/auth/digest/md5"
autoload :Nonce, "rack/auth/digest/nonce"
diff --git a/vendor/plugins/rack/lib/rack/builder.rb b/vendor/plugins/rack/lib/rack/builder.rb
index 295235e5..530f0aaf 100644
--- a/vendor/plugins/rack/lib/rack/builder.rb
+++ b/vendor/plugins/rack/lib/rack/builder.rb
@@ -24,6 +24,23 @@ module Rack
# You can use +map+ to construct a Rack::URLMap in a convenient way.
class Builder
+ def self.parse_file(config, opts = Server::Options.new)
+ options = {}
+ if config =~ /\.ru$/
+ cfgfile = ::File.read(config)
+ if cfgfile[/^#\\(.*)/] && opts
+ options = opts.parse! $1.split(/\s+/)
+ end
+ cfgfile.sub!(/^__END__\n.*/, '')
+ app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app",
+ TOPLEVEL_BINDING, config
+ else
+ require config
+ app = Object.const_get(::File.basename(config, '.rb').capitalize)
+ end
+ return app, options
+ end
+
def initialize(&block)
@ins = []
instance_eval(&block) if block_given?
diff --git a/vendor/plugins/rack/lib/rack/cascade.rb b/vendor/plugins/rack/lib/rack/cascade.rb
index a038aa11..14c3e54d 100644
--- a/vendor/plugins/rack/lib/rack/cascade.rb
+++ b/vendor/plugins/rack/lib/rack/cascade.rb
@@ -4,31 +4,36 @@ module Rack
# status codes).
class Cascade
+ NotFound = [404, {}, []]
+
attr_reader :apps
def initialize(apps, catch=404)
- @apps = apps
- @catch = [*catch]
+ @apps = []; @has_app = {}
+ apps.each { |app| add app }
+
+ @catch = {}
+ [*catch].each { |status| @catch[status] = true }
end
def call(env)
- status = headers = body = nil
- raise ArgumentError, "empty cascade" if @apps.empty?
- @apps.each { |app|
- begin
- status, headers, body = app.call(env)
- break unless @catch.include?(status.to_i)
- end
- }
- [status, headers, body]
+ result = NotFound
+
+ @apps.each do |app|
+ result = app.call(env)
+ break unless @catch.include?(result[0].to_i)
+ end
+
+ result
end
def add app
+ @has_app[app] = true
@apps << app
end
def include? app
- @apps.include? app
+ @has_app.include? app
end
alias_method :<<, :add
diff --git a/vendor/plugins/rack/lib/rack/chunked.rb b/vendor/plugins/rack/lib/rack/chunked.rb
index 280d89dd..dddf9694 100644
--- a/vendor/plugins/rack/lib/rack/chunked.rb
+++ b/vendor/plugins/rack/lib/rack/chunked.rb
@@ -19,7 +19,7 @@ module Rack
STATUS_WITH_NO_ENTITY_BODY.include?(status) ||
headers['Content-Length'] ||
headers['Transfer-Encoding']
- [status, headers.to_hash, body]
+ [status, headers, body]
else
dup.chunk(status, headers, body)
end
@@ -29,7 +29,7 @@ module Rack
@body = body
headers.delete('Content-Length')
headers['Transfer-Encoding'] = 'chunked'
- [status, headers.to_hash, self]
+ [status, headers, self]
end
def each
diff --git a/vendor/plugins/rack/lib/rack/commonlogger.rb b/vendor/plugins/rack/lib/rack/commonlogger.rb
index 5e68ac62..1edc9b83 100644
--- a/vendor/plugins/rack/lib/rack/commonlogger.rb
+++ b/vendor/plugins/rack/lib/rack/commonlogger.rb
@@ -2,60 +2,48 @@ module Rack
# Rack::CommonLogger forwards every request to an +app+ given, and
# logs a line in the Apache common log format to the +logger+, or
# rack.errors by default.
-
class CommonLogger
+ # Common Log Format: http://httpd.apache.org/docs/1.3/logs.html#common
+ # lilith.local - - [07/Aug/2006 23:58:02] "GET / HTTP/1.1" 500 -
+ # %{%s - %s [%s] "%s %s%s %s" %d %s\n} %
+ FORMAT = %{%s - %s [%s] "%s %s%s %s" %d %s %0.4f\n}
+
def initialize(app, logger=nil)
@app = app
@logger = logger
end
def call(env)
- dup._call(env)
+ began_at = Time.now
+ status, header, body = @app.call(env)
+ header = Utils::HeaderHash.new(header)
+ log(env, status, header, began_at)
+ [status, header, body]
end
- def _call(env)
- @env = env
- @logger ||= self
- @time = Time.now
- @status, @header, @body = @app.call(env)
- [@status, @header, self]
+ private
+
+ def log(env, status, header, began_at)
+ now = Time.now
+ length = extract_content_length(header)
+
+ logger = @logger || env['rack.errors']
+ logger.write FORMAT % [
+ env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-",
+ env["REMOTE_USER"] || "-",
+ now.strftime("%d/%b/%Y %H:%M:%S"),
+ env["REQUEST_METHOD"],
+ env["PATH_INFO"],
+ env["QUERY_STRING"].empty? ? "" : "?"+env["QUERY_STRING"],
+ env["HTTP_VERSION"],
+ status.to_s[0..3],
+ length,
+ now - began_at ]
end
- def close
- @body.close if @body.respond_to? :close
- end
-
- # By default, log to rack.errors.
- def <<(str)
- @env["rack.errors"].write(str)
- @env["rack.errors"].flush
- end
-
- def each
- length = 0
- @body.each { |part|
- length += part.size
- yield part
- }
-
- @now = Time.now
-
- # Common Log Format: http://httpd.apache.org/docs/1.3/logs.html#common
- # lilith.local - - [07/Aug/2006 23:58:02] "GET / HTTP/1.1" 500 -
- # %{%s - %s [%s] "%s %s%s %s" %d %s\n} %
- @logger << %{%s - %s [%s] "%s %s%s %s" %d %s %0.4f\n} %
- [
- @env['HTTP_X_FORWARDED_FOR'] || @env["REMOTE_ADDR"] || "-",
- @env["REMOTE_USER"] || "-",
- @now.strftime("%d/%b/%Y %H:%M:%S"),
- @env["REQUEST_METHOD"],
- @env["PATH_INFO"],
- @env["QUERY_STRING"].empty? ? "" : "?"+@env["QUERY_STRING"],
- @env["HTTP_VERSION"],
- @status.to_s[0..3],
- (length.zero? ? "-" : length.to_s),
- @now - @time
- ]
+ def extract_content_length(headers)
+ value = headers['Content-Length'] or return '-'
+ value.to_s == '0' ? '-' : value
end
end
end
diff --git a/vendor/plugins/rack/lib/rack/config.rb b/vendor/plugins/rack/lib/rack/config.rb
new file mode 100644
index 00000000..c6d446c0
--- /dev/null
+++ b/vendor/plugins/rack/lib/rack/config.rb
@@ -0,0 +1,15 @@
+module Rack
+ # Rack::Config modifies the environment using the block given during
+ # initialization.
+ class Config
+ def initialize(app, &block)
+ @app = app
+ @block = block
+ end
+
+ def call(env)
+ @block.call(env)
+ @app.call(env)
+ end
+ end
+end
diff --git a/vendor/plugins/rack/lib/rack/content_type.rb b/vendor/plugins/rack/lib/rack/content_type.rb
index 0c1e1ca3..874c28cd 100644
--- a/vendor/plugins/rack/lib/rack/content_type.rb
+++ b/vendor/plugins/rack/lib/rack/content_type.rb
@@ -17,7 +17,7 @@ module Rack
status, headers, body = @app.call(env)
headers = Utils::HeaderHash.new(headers)
headers['Content-Type'] ||= @content_type
- [status, headers.to_hash, body]
+ [status, headers, body]
end
end
end
diff --git a/vendor/plugins/rack/lib/rack/directory.rb b/vendor/plugins/rack/lib/rack/directory.rb
index acdd3029..927ac0c9 100644
--- a/vendor/plugins/rack/lib/rack/directory.rb
+++ b/vendor/plugins/rack/lib/rack/directory.rb
@@ -71,7 +71,9 @@ table { width:100%%; }
body = "Forbidden\n"
size = Rack::Utils.bytesize(body)
- return [403, {"Content-Type" => "text/plain","Content-Length" => size.to_s}, [body]]
+ return [403, {"Content-Type" => "text/plain",
+ "Content-Length" => size.to_s,
+ "X-Cascade" => "pass"}, [body]]
end
def list_directory
@@ -123,7 +125,9 @@ table { width:100%%; }
def entity_not_found
body = "Entity not found: #{@path_info}\n"
size = Rack::Utils.bytesize(body)
- return [404, {"Content-Type" => "text/plain", "Content-Length" => size.to_s}, [body]]
+ return [404, {"Content-Type" => "text/plain",
+ "Content-Length" => size.to_s,
+ "X-Cascade" => "pass"}, [body]]
end
def each
diff --git a/vendor/plugins/rack/lib/rack/etag.rb b/vendor/plugins/rack/lib/rack/etag.rb
new file mode 100644
index 00000000..06dbc6aa
--- /dev/null
+++ b/vendor/plugins/rack/lib/rack/etag.rb
@@ -0,0 +1,23 @@
+require 'digest/md5'
+
+module Rack
+ # Automatically sets the ETag header on all String bodies
+ class ETag
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ status, headers, body = @app.call(env)
+
+ if !headers.has_key?('ETag')
+ parts = []
+ body.each { |part| parts << part.to_s }
+ headers['ETag'] = %("#{Digest::MD5.hexdigest(parts.join(""))}")
+ [status, headers, parts]
+ else
+ [status, headers, body]
+ end
+ end
+ end
+end
diff --git a/vendor/plugins/rack/lib/rack/file.rb b/vendor/plugins/rack/lib/rack/file.rb
index fe62bd6b..14af7b3b 100644
--- a/vendor/plugins/rack/lib/rack/file.rb
+++ b/vendor/plugins/rack/lib/rack/file.rb
@@ -45,7 +45,8 @@ module Rack
def forbidden
body = "Forbidden\n"
[403, {"Content-Type" => "text/plain",
- "Content-Length" => body.size.to_s},
+ "Content-Length" => body.size.to_s,
+ "X-Cascade" => "pass"},
[body]]
end
@@ -73,7 +74,8 @@ module Rack
def not_found
body = "File not found: #{@path_info}\n"
[404, {"Content-Type" => "text/plain",
- "Content-Length" => body.size.to_s},
+ "Content-Length" => body.size.to_s,
+ "X-Cascade" => "pass"},
[body]]
end
diff --git a/vendor/plugins/rack/lib/rack/handler.rb b/vendor/plugins/rack/lib/rack/handler.rb
index 5624a1e7..3c09883e 100644
--- a/vendor/plugins/rack/lib/rack/handler.rb
+++ b/vendor/plugins/rack/lib/rack/handler.rb
@@ -22,6 +22,25 @@ module Rack
end
end
+ def self.default(options = {})
+ # Guess.
+ if ENV.include?("PHP_FCGI_CHILDREN")
+ # We already speak FastCGI
+ options.delete :File
+ options.delete :Port
+
+ Rack::Handler::FastCGI
+ elsif ENV.include?("REQUEST_METHOD")
+ Rack::Handler::CGI
+ else
+ begin
+ Rack::Handler::Mongrel
+ rescue LoadError => e
+ Rack::Handler::WEBrick
+ end
+ end
+ end
+
# Transforms server-name constants to their canonical form as filenames,
# then tries to require them but silences the LoadError if not found
#
diff --git a/vendor/plugins/rack/lib/rack/handler/cgi.rb b/vendor/plugins/rack/lib/rack/handler/cgi.rb
index f45f3d73..c6903f15 100644
--- a/vendor/plugins/rack/lib/rack/handler/cgi.rb
+++ b/vendor/plugins/rack/lib/rack/handler/cgi.rb
@@ -15,7 +15,7 @@ module Rack
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
- env.update({"rack.version" => [1,0],
+ env.update({"rack.version" => [1,1],
"rack.input" => $stdin,
"rack.errors" => $stderr,
diff --git a/vendor/plugins/rack/lib/rack/handler/fastcgi.rb b/vendor/plugins/rack/lib/rack/handler/fastcgi.rb
index 1739d659..b992a5f4 100644
--- a/vendor/plugins/rack/lib/rack/handler/fastcgi.rb
+++ b/vendor/plugins/rack/lib/rack/handler/fastcgi.rb
@@ -33,10 +33,10 @@ module Rack
env.delete "HTTP_CONTENT_LENGTH"
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
-
+
rack_input = RewindableInput.new(request.in)
- env.update({"rack.version" => [1,0],
+ env.update({"rack.version" => [1,1],
"rack.input" => rack_input,
"rack.errors" => request.err,
@@ -50,7 +50,6 @@ module Rack
env["QUERY_STRING"] ||= ""
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
env["REQUEST_PATH"] ||= "/"
- env.delete "PATH_INFO" if env["PATH_INFO"] == ""
env.delete "CONTENT_TYPE" if env["CONTENT_TYPE"] == ""
env.delete "CONTENT_LENGTH" if env["CONTENT_LENGTH"] == ""
diff --git a/vendor/plugins/rack/lib/rack/handler/lsws.rb b/vendor/plugins/rack/lib/rack/handler/lsws.rb
index b4ddf4bb..eabc0bc9 100644
--- a/vendor/plugins/rack/lib/rack/handler/lsws.rb
+++ b/vendor/plugins/rack/lib/rack/handler/lsws.rb
@@ -1,5 +1,6 @@
require 'lsapi'
require 'rack/content_length'
+require 'rack/rewindable_input'
module Rack
module Handler
@@ -19,7 +20,7 @@ module Rack
rack_input = RewindableInput.new($stdin.read.to_s)
env.update(
- "rack.version" => [1,0],
+ "rack.version" => [1,1],
"rack.input" => rack_input,
"rack.errors" => $stderr,
"rack.multithread" => false,
@@ -38,6 +39,8 @@ module Rack
ensure
body.close if body.respond_to? :close
end
+ ensure
+ rack_input.close
end
def self.send_headers(status, headers)
print "Status: #{status}\r\n"
diff --git a/vendor/plugins/rack/lib/rack/handler/mongrel.rb b/vendor/plugins/rack/lib/rack/handler/mongrel.rb
index 7b448261..b6b775ea 100644
--- a/vendor/plugins/rack/lib/rack/handler/mongrel.rb
+++ b/vendor/plugins/rack/lib/rack/handler/mongrel.rb
@@ -7,10 +7,14 @@ module Rack
module Handler
class Mongrel < ::Mongrel::HttpHandler
def self.run(app, options={})
- server = ::Mongrel::HttpServer.new(options[:Host] || '0.0.0.0',
- options[:Port] || 8080)
+ server = ::Mongrel::HttpServer.new(
+ options[:Host] || '0.0.0.0',
+ options[:Port] || 8080,
+ options[:num_processors] || 950,
+ options[:throttle] || 0,
+ options[:timeout] || 60)
# Acts like Rack::URLMap, utilizing Mongrel's own path finding methods.
- # Use is similar to #run, replacing the app argument with a hash of
+ # Use is similar to #run, replacing the app argument with a hash of
# { path=>app, ... } or an instance of Rack::URLMap.
if options[:map]
if app.is_a? Hash
@@ -48,7 +52,7 @@ module Rack
rack_input = request.body || StringIO.new('')
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
- env.update({"rack.version" => [1,0],
+ env.update({"rack.version" => [1,1],
"rack.input" => rack_input,
"rack.errors" => $stderr,
@@ -59,7 +63,6 @@ module Rack
"rack.url_scheme" => "http",
})
env["QUERY_STRING"] ||= ""
- env.delete "PATH_INFO" if env["PATH_INFO"] == ""
status, headers, body = @app.call(env)
diff --git a/vendor/plugins/rack/lib/rack/handler/scgi.rb b/vendor/plugins/rack/lib/rack/handler/scgi.rb
index bd860a5d..79a6b2bd 100644
--- a/vendor/plugins/rack/lib/rack/handler/scgi.rb
+++ b/vendor/plugins/rack/lib/rack/handler/scgi.rb
@@ -7,14 +7,14 @@ module Rack
module Handler
class SCGI < ::SCGI::Processor
attr_accessor :app
-
+
def self.run(app, options=nil)
new(options.merge(:app=>app,
:host=>options[:Host],
:port=>options[:Port],
:socket=>options[:Socket])).listen
end
-
+
def initialize(settings = {})
@app = Rack::Chunked.new(Rack::ContentLength.new(settings[:app]))
@log = Object.new
@@ -22,7 +22,7 @@ module Rack
def @log.error(*args); end
super(settings)
end
-
+
def process_request(request, input_body, socket)
env = {}.replace(request)
env.delete "HTTP_CONTENT_TYPE"
@@ -36,7 +36,7 @@ module Rack
rack_input = StringIO.new(input_body)
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
- env.update({"rack.version" => [1,0],
+ env.update({"rack.version" => [1,1],
"rack.input" => rack_input,
"rack.errors" => $stderr,
"rack.multithread" => true,
diff --git a/vendor/plugins/rack/lib/rack/handler/webrick.rb b/vendor/plugins/rack/lib/rack/handler/webrick.rb
index 1ef1b8de..2240b8d3 100644
--- a/vendor/plugins/rack/lib/rack/handler/webrick.rb
+++ b/vendor/plugins/rack/lib/rack/handler/webrick.rb
@@ -27,7 +27,7 @@ module Rack
rack_input = StringIO.new(req.body.to_s)
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
- env.update({"rack.version" => [1,0],
+ env.update({"rack.version" => [1,1],
"rack.input" => rack_input,
"rack.errors" => $stderr,
@@ -41,9 +41,7 @@ module Rack
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
env["QUERY_STRING"] ||= ""
env["REQUEST_PATH"] ||= "/"
- if env["PATH_INFO"] == ""
- env.delete "PATH_INFO"
- else
+ unless env["PATH_INFO"] == ""
path, n = req.request_uri.path, env["SCRIPT_NAME"].length
env["PATH_INFO"] = path[n, path.length-n]
end
diff --git a/vendor/plugins/rack/lib/rack/lint.rb b/vendor/plugins/rack/lib/rack/lint.rb
index 796807a0..534375b9 100644
--- a/vendor/plugins/rack/lib/rack/lint.rb
+++ b/vendor/plugins/rack/lib/rack/lint.rb
@@ -61,7 +61,7 @@ module Rack
## subclassing allowed) that includes CGI-like headers.
## The application is free to modify the environment.
assert("env #{env.inspect} is not a Hash, but #{env.class}") {
- env.instance_of? Hash
+ env.kind_of? Hash
}
##
@@ -111,7 +111,7 @@ module Rack
## In addition to this, the Rack environment must include these
## Rack-specific variables:
- ## rack.version:: The Array [1,0], representing this version of Rack.
+ ## rack.version:: The Array [1,1], representing this version of Rack.
## rack.url_scheme:: +http+ or +https+, depending on the request URL.
## rack.input:: See below, the input stream.
## rack.errors:: See below, the error stream.
@@ -148,6 +148,35 @@ module Rack
}
end
+ ## rack.logger:: A common object interface for logging messages.
+ ## The object must implement:
+ if logger = env['rack.logger']
+ ## info(message, &block)
+ assert("logger #{logger.inspect} must respond to info") {
+ logger.respond_to?(:info)
+ }
+
+ ## debug(message, &block)
+ assert("logger #{logger.inspect} must respond to debug") {
+ logger.respond_to?(:debug)
+ }
+
+ ## warn(message, &block)
+ assert("logger #{logger.inspect} must respond to warn") {
+ logger.respond_to?(:warn)
+ }
+
+ ## error(message, &block)
+ assert("logger #{logger.inspect} must respond to error") {
+ logger.respond_to?(:error)
+ }
+
+ ## fatal(message, &block)
+ assert("logger #{logger.inspect} must respond to fatal") {
+ logger.respond_to?(:fatal)
+ }
+ end
+
## The server or the application can store their own data in the
## environment, too. The keys must contain at least one dot,
## and should be prefixed uniquely. The prefix rack.
@@ -175,7 +204,7 @@ module Rack
env.each { |key, value|
next if key.include? "." # Skip extensions
assert("env variable #{key} has non-string value #{value.inspect}") {
- value.instance_of? String
+ value.kind_of? String
}
}
@@ -184,7 +213,7 @@ module Rack
## * rack.version must be an array of Integers.
assert("rack.version must be an Array, was #{env["rack.version"].class}") {
- env["rack.version"].instance_of? Array
+ env["rack.version"].kind_of? Array
}
## * rack.url_scheme must either be +http+ or +https+.
assert("rack.url_scheme unknown: #{env["rack.url_scheme"].inspect}") {
@@ -243,7 +272,7 @@ module Rack
assert("rack.input #{input} is not opened in binary mode") {
input.binmode?
} if input.respond_to?(:binmode?)
-
+
## The input stream must respond to +gets+, +each+, +read+ and +rewind+.
[:gets, :each, :read, :rewind].each { |method|
assert("rack.input #{input} does not respond to ##{method}") {
@@ -269,7 +298,7 @@ module Rack
assert("rack.input#gets called with arguments") { args.size == 0 }
v = @input.gets
assert("rack.input#gets didn't return a String") {
- v.nil? or v.instance_of? String
+ v.nil? or v.kind_of? String
}
v
end
@@ -300,18 +329,18 @@ module Rack
args[1].kind_of?(String)
}
end
-
+
v = @input.read(*args)
-
+
assert("rack.input#read didn't return nil or a String") {
- v.nil? or v.instance_of? String
+ v.nil? or v.kind_of? String
}
if args[0].nil?
assert("rack.input#read(nil) returned nil on EOF") {
!v.nil?
}
end
-
+
v
end
@@ -320,12 +349,12 @@ module Rack
assert("rack.input#each called with arguments") { args.size == 0 }
@input.each { |line|
assert("rack.input#each didn't yield a String") {
- line.instance_of? String
+ line.kind_of? String
}
yield line
}
end
-
+
## * +rewind+ must be called without arguments. It rewinds the input
## stream back to the beginning. It must not raise Errno::ESPIPE:
## that is, it may not be a pipe or a socket. Therefore, handler
@@ -373,7 +402,7 @@ module Rack
## * +write+ must be called with a single argument that is a String.
def write(str)
- assert("rack.errors#write not called with a String") { str.instance_of? String }
+ assert("rack.errors#write not called with a String") { str.kind_of? String }
@error.write str
end
@@ -407,7 +436,7 @@ module Rack
header.each { |key, value|
## The header keys must be Strings.
assert("header key must be a string, was #{key.class}") {
- key.instance_of? String
+ key.kind_of? String
}
## The header must not contain a +Status+ key,
assert("header must not contain Status") { key.downcase != "status" }
@@ -499,7 +528,7 @@ module Rack
@body.each { |part|
## and must only yield String values.
assert("Body yielded non-string value #{part.inspect}") {
- part.instance_of? String
+ part.kind_of? String
}
yield part
}
diff --git a/vendor/plugins/rack/lib/rack/logger.rb b/vendor/plugins/rack/lib/rack/logger.rb
new file mode 100644
index 00000000..d67d8ce2
--- /dev/null
+++ b/vendor/plugins/rack/lib/rack/logger.rb
@@ -0,0 +1,20 @@
+require 'logger'
+
+module Rack
+ # Sets up rack.logger to write to rack.errors stream
+ class Logger
+ def initialize(app, level = ::Logger::INFO)
+ @app, @level = app, level
+ end
+
+ def call(env)
+ logger = ::Logger.new(env['rack.errors'])
+ logger.level = @level
+
+ env['rack.logger'] = logger
+ @app.call(env)
+ ensure
+ logger.close
+ end
+ end
+end
diff --git a/vendor/plugins/rack/lib/rack/mime.rb b/vendor/plugins/rack/lib/rack/mime.rb
index 5a6a73a9..1414d19a 100644
--- a/vendor/plugins/rack/lib/rack/mime.rb
+++ b/vendor/plugins/rack/lib/rack/mime.rb
@@ -14,7 +14,7 @@ module Rack
# Rack::Mime::MIME_TYPES.fetch('.foo', 'application/octet-stream')
def mime_type(ext, fallback='application/octet-stream')
- MIME_TYPES.fetch(ext, fallback)
+ MIME_TYPES.fetch(ext.to_s.downcase, fallback)
end
module_function :mime_type
@@ -105,6 +105,7 @@ module Rack
".m3u" => "audio/x-mpegurl",
".m4v" => "video/mp4",
".man" => "text/troff",
+ ".manifest"=> "text/cache-manifest",
".mathml" => "application/mathml+xml",
".mbox" => "application/mbox",
".mdoc" => "text/troff",
@@ -126,6 +127,7 @@ module Rack
".ods" => "application/vnd.oasis.opendocument.spreadsheet",
".odt" => "application/vnd.oasis.opendocument.text",
".ogg" => "application/ogg",
+ ".ogv" => "video/ogg",
".p" => "text/x-pascal",
".pas" => "text/x-pascal",
".pbm" => "image/x-portable-bitmap",
diff --git a/vendor/plugins/rack/lib/rack/mock.rb b/vendor/plugins/rack/lib/rack/mock.rb
index c34a2d7a..23ecba17 100644
--- a/vendor/plugins/rack/lib/rack/mock.rb
+++ b/vendor/plugins/rack/lib/rack/mock.rb
@@ -40,7 +40,7 @@ module Rack
end
DEFAULT_ENV = {
- "rack.version" => [1,0],
+ "rack.version" => [1,1],
"rack.input" => StringIO.new,
"rack.errors" => StringIO.new,
"rack.multithread" => true,
@@ -73,14 +73,17 @@ module Rack
# Return the Rack environment used for a request to +uri+.
def self.env_for(uri="", opts={})
uri = URI(uri)
+ uri.path = "/#{uri.path}" unless uri.path[0] == ?/
+
env = DEFAULT_ENV.dup
- env["REQUEST_METHOD"] = opts[:method] || "GET"
+ env["REQUEST_METHOD"] = opts[:method] ? opts[:method].to_s.upcase : "GET"
env["SERVER_NAME"] = uri.host || "example.org"
env["SERVER_PORT"] = uri.port ? uri.port.to_s : "80"
env["QUERY_STRING"] = uri.query.to_s
env["PATH_INFO"] = (!uri.path || uri.path.empty?) ? "/" : uri.path
env["rack.url_scheme"] = uri.scheme || "http"
+ env["HTTPS"] = env["rack.url_scheme"] == "https" ? "on" : "off"
env["SCRIPT_NAME"] = opts[:script_name] || ""
@@ -90,7 +93,30 @@ module Rack
env["rack.errors"] = StringIO.new
end
- opts[:input] ||= ""
+ if params = opts[:params]
+ if env["REQUEST_METHOD"] == "GET"
+ params = Utils.parse_nested_query(params) if params.is_a?(String)
+ params.update(Utils.parse_nested_query(env["QUERY_STRING"]))
+ env["QUERY_STRING"] = Utils.build_nested_query(params)
+ elsif !opts.has_key?(:input)
+ opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
+ if params.is_a?(Hash)
+ if data = Utils::Multipart.build_multipart(params)
+ opts[:input] = data
+ opts["CONTENT_LENGTH"] ||= data.length.to_s
+ opts["CONTENT_TYPE"] = "multipart/form-data; boundary=#{Utils::Multipart::MULTIPART_BOUNDARY}"
+ else
+ opts[:input] = Utils.build_nested_query(params)
+ end
+ else
+ opts[:input] = params
+ end
+ end
+ end
+
+ empty_str = ""
+ empty_str.force_encoding("ASCII-8BIT") if empty_str.respond_to? :force_encoding
+ opts[:input] ||= empty_str
if String === opts[:input]
rack_input = StringIO.new(opts[:input])
else
@@ -128,7 +154,7 @@ module Rack
@body = ""
body.each { |part| @body << part }
- @errors = errors.string
+ @errors = errors.string if errors.respond_to?(:string)
end
# Status
diff --git a/vendor/plugins/rack/lib/rack/nulllogger.rb b/vendor/plugins/rack/lib/rack/nulllogger.rb
new file mode 100644
index 00000000..77fb637d
--- /dev/null
+++ b/vendor/plugins/rack/lib/rack/nulllogger.rb
@@ -0,0 +1,18 @@
+module Rack
+ class NullLogger
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ env['rack.logger'] = self
+ @app.call(env)
+ end
+
+ def info(progname = nil, &block); end
+ def debug(progname = nil, &block); end
+ def warn(progname = nil, &block); end
+ def error(progname = nil, &block); end
+ def fatal(progname = nil, &block); end
+ end
+end
diff --git a/vendor/plugins/rack/lib/rack/reloader.rb b/vendor/plugins/rack/lib/rack/reloader.rb
index a9c566f7..a06de23a 100644
--- a/vendor/plugins/rack/lib/rack/reloader.rb
+++ b/vendor/plugins/rack/lib/rack/reloader.rb
@@ -1,5 +1,6 @@
# Copyright (c) 2009 Michael Fellinger m.fellinger@gmail.com
-# All files in this distribution are subject to the terms of the Ruby license.
+# Rack::Reloader is subject to the terms of an MIT-style license.
+# See COPYING or http://www.opensource.org/licenses/mit-license.php.
require 'pathname'
@@ -92,6 +93,8 @@ module Rack
found, stat = safe_stat(path)
return ::File.expand_path(found), stat if found
end
+
+ return false, false
end
def safe_stat(file)
diff --git a/vendor/plugins/rack/lib/rack/request.rb b/vendor/plugins/rack/lib/rack/request.rb
index 2f64bd6c..b3de1ce4 100644
--- a/vendor/plugins/rack/lib/rack/request.rb
+++ b/vendor/plugins/rack/lib/rack/request.rb
@@ -32,6 +32,7 @@ module Rack
def content_type; @env['CONTENT_TYPE'] end
def session; @env['rack.session'] ||= {} end
def session_options; @env['rack.session.options'] ||= {} end
+ def logger; @env['rack.logger'] end
# The media type (type/subtype) portion of the CONTENT_TYPE header
# without any media type parameters. e.g., when CONTENT_TYPE is
@@ -63,9 +64,17 @@ module Rack
media_type_params['charset']
end
+ def host_with_port
+ if forwarded = @env["HTTP_X_FORWARDED_HOST"]
+ forwarded.split(/,\s?/).last
+ else
+ @env['HTTP_HOST'] || "#{@env['SERVER_NAME'] || @env['SERVER_ADDR']}:#{@env['SERVER_PORT']}"
+ end
+ end
+
def host
# Remove port number.
- (@env["HTTP_HOST"] || @env["SERVER_NAME"]).to_s.gsub(/:\d+\z/, '')
+ host_with_port.to_s.gsub(/:\d+\z/, '')
end
def script_name=(s); @env["SCRIPT_NAME"] = s.to_s end
@@ -81,7 +90,6 @@ module Rack
# one of the media types presents in this list will not be eligible
# for form-data / param parsing.
FORM_DATA_MEDIA_TYPES = [
- nil,
'application/x-www-form-urlencoded',
'multipart/form-data'
]
@@ -92,15 +100,20 @@ module Rack
PARSEABLE_DATA_MEDIA_TYPES = [
'multipart/related',
'multipart/mixed'
- ]
+ ]
# Determine whether the request body contains form-data by checking
- # the request media_type against registered form-data media-types:
- # "application/x-www-form-urlencoded" and "multipart/form-data". The
+ # the request Content-Type for one of the media-types:
+ # "application/x-www-form-urlencoded" or "multipart/form-data". The
# list of form-data media types can be modified through the
# +FORM_DATA_MEDIA_TYPES+ array.
+ #
+ # A request body is also assumed to contain form-data when no
+ # Content-Type header is provided and the request_method is POST.
def form_data?
- FORM_DATA_MEDIA_TYPES.include?(media_type)
+ type = media_type
+ meth = env["rack.methodoverride.original_method"] || env['REQUEST_METHOD']
+ (meth == 'POST' && type.nil?) || FORM_DATA_MEDIA_TYPES.include?(type)
end
# Determine whether the request body contains data by checking
@@ -115,8 +128,7 @@ module Rack
@env["rack.request.query_hash"]
else
@env["rack.request.query_string"] = query_string
- @env["rack.request.query_hash"] =
- Utils.parse_nested_query(query_string)
+ @env["rack.request.query_hash"] = parse_query(query_string)
end
end
@@ -125,19 +137,20 @@ module Rack
# This method support both application/x-www-form-urlencoded and
# multipart/form-data.
def POST
- if @env["rack.request.form_input"].eql? @env["rack.input"]
+ if @env["rack.input"].nil?
+ raise "Missing rack.input"
+ elsif @env["rack.request.form_input"].eql? @env["rack.input"]
@env["rack.request.form_hash"]
elsif form_data? || parseable_data?
@env["rack.request.form_input"] = @env["rack.input"]
- unless @env["rack.request.form_hash"] =
- Utils::Multipart.parse_multipart(env)
+ unless @env["rack.request.form_hash"] = parse_multipart(env)
form_vars = @env["rack.input"].read
# Fix for Safari Ajax postings that always append \0
form_vars.sub!(/\0\z/, '')
@env["rack.request.form_vars"] = form_vars
- @env["rack.request.form_hash"] = Utils.parse_nested_query(form_vars)
+ @env["rack.request.form_hash"] = parse_query(form_vars)
@env["rack.input"].rewind
end
@@ -149,7 +162,7 @@ module Rack
# The union of GET and POST data.
def params
- self.put? ? self.GET : self.GET.update(self.POST)
+ self.GET.update(self.POST)
rescue EOFError => e
self.GET
end
@@ -175,6 +188,9 @@ module Rack
end
alias referrer referer
+ def user_agent
+ @env['HTTP_USER_AGENT']
+ end
def cookies
return {} unless @env["HTTP_COOKIE"]
@@ -214,11 +230,11 @@ module Rack
url
end
-
+
def path
script_name + path_info
end
-
+
def fullpath
query_string.empty? ? path : "#{path}?#{query_string}"
end
@@ -242,5 +258,14 @@ module Rack
@env['REMOTE_ADDR']
end
end
+
+ protected
+ def parse_query(qs)
+ Utils.parse_nested_query(qs)
+ end
+
+ def parse_multipart(env)
+ Utils::Multipart.parse_multipart(env)
+ end
end
end
diff --git a/vendor/plugins/rack/lib/rack/response.rb b/vendor/plugins/rack/lib/rack/response.rb
index 28b4d830..a7f9bf2b 100644
--- a/vendor/plugins/rack/lib/rack/response.rb
+++ b/vendor/plugins/rack/lib/rack/response.rb
@@ -19,7 +19,7 @@ module Rack
attr_accessor :length
def initialize(body=[], status=200, header={}, &block)
- @status = status
+ @status = status.to_i
@header = Utils::HeaderHash.new({"Content-Type" => "text/html"}.
merge(header))
@@ -54,45 +54,11 @@ module Rack
end
def set_cookie(key, value)
- case value
- when Hash
- domain = "; domain=" + value[:domain] if value[:domain]
- path = "; path=" + value[:path] if value[:path]
- # According to RFC 2109, we need dashes here.
- # N.B.: cgi.rb uses spaces...
- expires = "; expires=" + value[:expires].clone.gmtime.
- strftime("%a, %d-%b-%Y %H:%M:%S GMT") if value[:expires]
- secure = "; secure" if value[:secure]
- httponly = "; HttpOnly" if value[:httponly]
- value = value[:value]
- end
- value = [value] unless Array === value
- cookie = Utils.escape(key) + "=" +
- value.map { |v| Utils.escape v }.join("&") +
- "#{domain}#{path}#{expires}#{secure}#{httponly}"
-
- case self["Set-Cookie"]
- when Array
- self["Set-Cookie"] << cookie
- when String
- self["Set-Cookie"] = [self["Set-Cookie"], cookie]
- when nil
- self["Set-Cookie"] = cookie
- end
+ Utils.set_cookie_header!(header, key, value)
end
def delete_cookie(key, value={})
- unless Array === self["Set-Cookie"]
- self["Set-Cookie"] = [self["Set-Cookie"]].compact
- end
-
- self["Set-Cookie"].reject! { |cookie|
- cookie =~ /\A#{Utils.escape(key)}=/
- }
-
- set_cookie(key,
- {:value => '', :path => nil, :domain => nil,
- :expires => Time.at(0) }.merge(value))
+ Utils.delete_cookie_header!(header, key, value)
end
def redirect(target, status=302)
@@ -105,9 +71,9 @@ module Rack
if [204, 304].include?(status.to_i)
header.delete "Content-Type"
- [status.to_i, header.to_hash, []]
+ [status.to_i, header, []]
else
- [status.to_i, header.to_hash, self]
+ [status.to_i, header, self]
end
end
alias to_a finish # For *response
diff --git a/vendor/plugins/rack/lib/rack/rewindable_input.rb b/vendor/plugins/rack/lib/rack/rewindable_input.rb
index 2864d510..08764bee 100644
--- a/vendor/plugins/rack/lib/rack/rewindable_input.rb
+++ b/vendor/plugins/rack/lib/rack/rewindable_input.rb
@@ -16,27 +16,27 @@ module Rack
@rewindable_io = nil
@unlinked = false
end
-
+
def gets
make_rewindable unless @rewindable_io
@rewindable_io.gets
end
-
+
def read(*args)
make_rewindable unless @rewindable_io
@rewindable_io.read(*args)
end
-
+
def each(&block)
make_rewindable unless @rewindable_io
@rewindable_io.each(&block)
end
-
+
def rewind
make_rewindable unless @rewindable_io
@rewindable_io.rewind
end
-
+
# Closes this RewindableInput object without closing the originally
# wrapped IO oject. Cleans up any temporary resources that this RewindableInput
# has created.
@@ -52,9 +52,9 @@ module Rack
@rewindable_io = nil
end
end
-
+
private
-
+
# Ruby's Tempfile class has a bug. Subclass it and fix it.
class Tempfile < ::Tempfile
def _close
@@ -72,11 +72,13 @@ module Rack
# access it because we have the file handle open.
@rewindable_io = Tempfile.new('RackRewindableInput')
@rewindable_io.chmod(0000)
+ @rewindable_io.set_encoding(Encoding::BINARY) if @rewindable_io.respond_to?(:set_encoding)
+ @rewindable_io.binmode
if filesystem_has_posix_semantics? && !tempfile_unlink_contains_bug?
@rewindable_io.unlink
@unlinked = true
end
-
+
buffer = ""
while @io.read(1024 * 4, buffer)
entire_buffer_written_out = false
@@ -90,7 +92,7 @@ module Rack
end
@rewindable_io.rewind
end
-
+
def filesystem_has_posix_semantics?
RUBY_PLATFORM !~ /(mswin|mingw|cygwin|java)/
end
diff --git a/vendor/plugins/rack/lib/rack/runtime.rb b/vendor/plugins/rack/lib/rack/runtime.rb
new file mode 100644
index 00000000..1bd411fd
--- /dev/null
+++ b/vendor/plugins/rack/lib/rack/runtime.rb
@@ -0,0 +1,27 @@
+module Rack
+ # Sets an "X-Runtime" response header, indicating the response
+ # time of the request, in seconds
+ #
+ # You can put it right before the application to see the processing
+ # time, or before all the other middlewares to include time for them,
+ # too.
+ class Runtime
+ def initialize(app, name = nil)
+ @app = app
+ @header_name = "X-Runtime"
+ @header_name << "-#{name}" if name
+ end
+
+ def call(env)
+ start_time = Time.now
+ status, headers, body = @app.call(env)
+ request_time = Time.now - start_time
+
+ if !headers.has_key?(@header_name)
+ headers[@header_name] = "%0.6f" % request_time
+ end
+
+ [status, headers, body]
+ end
+ end
+end
diff --git a/vendor/plugins/rack/lib/rack/sendfile.rb b/vendor/plugins/rack/lib/rack/sendfile.rb
new file mode 100644
index 00000000..4fa82946
--- /dev/null
+++ b/vendor/plugins/rack/lib/rack/sendfile.rb
@@ -0,0 +1,142 @@
+require 'rack/file'
+
+module Rack
+ class File #:nodoc:
+ alias :to_path :path
+ end
+
+ # = Sendfile
+ #
+ # The Sendfile middleware intercepts responses whose body is being
+ # served from a file and replaces it with a server specific X-Sendfile
+ # header. The web server is then responsible for writing the file contents
+ # to the client. This can dramatically reduce the amount of work required
+ # by the Ruby backend and takes advantage of the web servers optimized file
+ # delivery code.
+ #
+ # In order to take advantage of this middleware, the response body must
+ # respond to +to_path+ and the request must include an X-Sendfile-Type
+ # header. Rack::File and other components implement +to_path+ so there's
+ # rarely anything you need to do in your application. The X-Sendfile-Type
+ # header is typically set in your web servers configuration. The following
+ # sections attempt to document
+ #
+ # === Nginx
+ #
+ # Nginx supports the X-Accel-Redirect header. This is similar to X-Sendfile
+ # but requires parts of the filesystem to be mapped into a private URL
+ # hierarachy.
+ #
+ # The following example shows the Nginx configuration required to create
+ # a private "/files/" area, enable X-Accel-Redirect, and pass the special
+ # X-Sendfile-Type and X-Accel-Mapping headers to the backend:
+ #
+ # location /files/ {
+ # internal;
+ # alias /var/www/;
+ # }
+ #
+ # location / {
+ # proxy_redirect false;
+ #
+ # proxy_set_header Host $host;
+ # proxy_set_header X-Real-IP $remote_addr;
+ # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ #
+ # proxy_set_header X-Sendfile-Type X-Accel-Redirect
+ # proxy_set_header X-Accel-Mapping /files/=/var/www/;
+ #
+ # proxy_pass http://127.0.0.1:8080/;
+ # }
+ #
+ # Note that the X-Sendfile-Type header must be set exactly as shown above. The
+ # X-Accel-Mapping header should specify the name of the private URL pattern,
+ # followed by an equals sign (=), followed by the location on the file system
+ # that it maps to. The middleware performs a simple substitution on the
+ # resulting path.
+ #
+ # See Also: http://wiki.codemongers.com/NginxXSendfile
+ #
+ # === lighttpd
+ #
+ # Lighttpd has supported some variation of the X-Sendfile header for some
+ # time, although only recent version support X-Sendfile in a reverse proxy
+ # configuration.
+ #
+ # $HTTP["host"] == "example.com" {
+ # proxy-core.protocol = "http"
+ # proxy-core.balancer = "round-robin"
+ # proxy-core.backends = (
+ # "127.0.0.1:8000",
+ # "127.0.0.1:8001",
+ # ...
+ # )
+ #
+ # proxy-core.allow-x-sendfile = "enable"
+ # proxy-core.rewrite-request = (
+ # "X-Sendfile-Type" => (".*" => "X-Sendfile")
+ # )
+ # }
+ #
+ # See Also: http://redmine.lighttpd.net/wiki/lighttpd/Docs:ModProxyCore
+ #
+ # === Apache
+ #
+ # X-Sendfile is supported under Apache 2.x using a separate module:
+ #
+ # http://tn123.ath.cx/mod_xsendfile/
+ #
+ # Once the module is compiled and installed, you can enable it using
+ # XSendFile config directive:
+ #
+ # RequestHeader Set X-Sendfile-Type X-Sendfile
+ # ProxyPassReverse / http://localhost:8001/
+ # XSendFile on
+
+ class Sendfile
+ F = ::File
+
+ def initialize(app, variation=nil)
+ @app = app
+ @variation = variation
+ end
+
+ def call(env)
+ status, headers, body = @app.call(env)
+ if body.respond_to?(:to_path)
+ case type = variation(env)
+ when 'X-Accel-Redirect'
+ path = F.expand_path(body.to_path)
+ if url = map_accel_path(env, path)
+ headers[type] = url
+ body = []
+ else
+ env['rack.errors'] << "X-Accel-Mapping header missing"
+ end
+ when 'X-Sendfile', 'X-Lighttpd-Send-File'
+ path = F.expand_path(body.to_path)
+ headers[type] = path
+ body = []
+ when '', nil
+ else
+ env['rack.errors'] << "Unknown x-sendfile variation: '#{variation}'.\n"
+ end
+ end
+ [status, headers, body]
+ end
+
+ private
+ def variation(env)
+ @variation ||
+ env['sendfile.type'] ||
+ env['HTTP_X_SENDFILE_TYPE']
+ end
+
+ def map_accel_path(env, file)
+ if mapping = env['HTTP_X_ACCEL_MAPPING']
+ internal, external = mapping.split('=', 2).map{ |p| p.strip }
+ file.sub(/^#{internal}/i, external)
+ end
+ end
+ end
+end
diff --git a/vendor/plugins/rack/lib/rack/server.rb b/vendor/plugins/rack/lib/rack/server.rb
new file mode 100644
index 00000000..7d0705ad
--- /dev/null
+++ b/vendor/plugins/rack/lib/rack/server.rb
@@ -0,0 +1,212 @@
+require 'optparse'
+
+module Rack
+ class Server
+ class Options
+ def parse!(args)
+ options = {}
+ opt_parser = OptionParser.new("", 24, ' ') do |opts|
+ opts.banner = "Usage: rackup [ruby options] [rack options] [rackup config]"
+
+ opts.separator ""
+ opts.separator "Ruby options:"
+
+ lineno = 1
+ opts.on("-e", "--eval LINE", "evaluate a LINE of code") { |line|
+ eval line, TOPLEVEL_BINDING, "-e", lineno
+ lineno += 1
+ }
+
+ opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") {
+ options[:debug] = true
+ }
+ opts.on("-w", "--warn", "turn warnings on for your script") {
+ options[:warn] = true
+ }
+
+ opts.on("-I", "--include PATH",
+ "specify $LOAD_PATH (may be used more than once)") { |path|
+ options[:include] = path.split(":")
+ }
+
+ opts.on("-r", "--require LIBRARY",
+ "require the library, before executing your script") { |library|
+ options[:require] = library
+ }
+
+ opts.separator ""
+ opts.separator "Rack options:"
+ opts.on("-s", "--server SERVER", "serve using SERVER (webrick/mongrel)") { |s|
+ options[:server] = s
+ }
+
+ opts.on("-o", "--host HOST", "listen on HOST (default: 0.0.0.0)") { |host|
+ options[:Host] = host
+ }
+
+ opts.on("-p", "--port PORT", "use PORT (default: 9292)") { |port|
+ options[:Port] = port
+ }
+
+ opts.on("-E", "--env ENVIRONMENT", "use ENVIRONMENT for defaults (default: development)") { |e|
+ options[:environment] = e
+ }
+
+ opts.on("-D", "--daemonize", "run daemonized in the background") { |d|
+ options[:daemonize] = d ? true : false
+ }
+
+ opts.on("-P", "--pid FILE", "file to store PID (default: rack.pid)") { |f|
+ options[:pid] = ::File.expand_path(f)
+ }
+
+ opts.separator ""
+ opts.separator "Common options:"
+
+ opts.on_tail("-h", "--help", "Show this message") do
+ puts opts
+ exit
+ end
+
+ opts.on_tail("--version", "Show version") do
+ puts "Rack #{Rack.version}"
+ exit
+ end
+ end
+ opt_parser.parse! args
+ options[:rack_file] = args.last if args.last
+ options
+ end
+ end
+
+ def self.start
+ new.start
+ end
+
+ attr_accessor :options
+
+ def initialize(options = nil)
+ @options = options
+ end
+
+ def options
+ @options ||= parse_options(ARGV)
+ end
+
+ def default_options
+ {
+ :environment => "development",
+ :pid => nil,
+ :Port => 9292,
+ :Host => "0.0.0.0",
+ :AccessLog => [],
+ :rack_file => ::File.expand_path("config.ru")
+ }
+ end
+
+ def app
+ @app ||= begin
+ if !::File.exist? options[:rack_file]
+ abort "configuration #{options[:rack_file]} not found"
+ end
+
+ app, options = Rack::Builder.parse_file(self.options[:rack_file], opt_parser)
+ self.options.merge! options
+ app
+ end
+ end
+
+ def self.middleware
+ @middleware ||= begin
+ m = Hash.new {|h,k| h[k] = []}
+ m["deployment"].concat [lambda {|server| server.server =~ /CGI/ ? nil : [Rack::CommonLogger, $stderr] }]
+ m["development"].concat m["deployment"] + [[Rack::ShowExceptions], [Rack::Lint]]
+ m
+ end
+ end
+
+ def middleware
+ self.class.middleware
+ end
+
+ def start
+ if options[:debug]
+ $DEBUG = true
+ require 'pp'
+ p options[:server]
+ pp wrapped_app
+ pp app
+ end
+
+ if options[:warn]
+ $-w = true
+ end
+
+ if includes = options[:include]
+ $LOAD_PATH.unshift *includes
+ end
+
+ if library = options[:require]
+ require library
+ end
+
+ daemonize_app if options[:daemonize]
+ write_pid if options[:pid]
+ server.run wrapped_app, options
+ end
+
+ def server
+ @_server ||= Rack::Handler.get(options[:server]) || Rack::Handler.default
+ end
+
+ private
+ def parse_options(args)
+ options = default_options
+
+ # Don't evaluate CGI ISINDEX parameters.
+ # http://hoohoo.ncsa.uiuc.edu/cgi/cl.html
+ args.clear if ENV.include?("REQUEST_METHOD")
+
+ options.merge! opt_parser.parse! args
+ options
+ end
+
+ def opt_parser
+ Options.new
+ end
+
+ def build_app(app)
+ middleware[options[:environment]].reverse_each do |middleware|
+ middleware = middleware.call(self) if middleware.respond_to?(:call)
+ next unless middleware
+ klass = middleware.shift
+ app = klass.new(app, *middleware)
+ end
+ app
+ end
+
+ def wrapped_app
+ @wrapped_app ||= build_app app
+ end
+
+ def daemonize_app
+ if RUBY_VERSION < "1.9"
+ exit if fork
+ Process.setsid
+ exit if fork
+ Dir.chdir "/"
+ ::File.umask 0000
+ STDIN.reopen "/dev/null"
+ STDOUT.reopen "/dev/null", "a"
+ STDERR.reopen "/dev/null", "a"
+ else
+ Process.daemon
+ end
+ end
+
+ def write_pid
+ ::File.open(options[:pid], 'w'){ |f| f.write("#{Process.pid}") }
+ at_exit { ::File.delete(options[:pid]) if ::File.exist?(options[:pid]) }
+ end
+ end
+end
diff --git a/vendor/plugins/rack/lib/rack/session/abstract/id.rb b/vendor/plugins/rack/lib/rack/session/abstract/id.rb
index 218144c1..98746705 100644
--- a/vendor/plugins/rack/lib/rack/session/abstract/id.rb
+++ b/vendor/plugins/rack/lib/rack/session/abstract/id.rb
@@ -107,18 +107,16 @@ module Rack
if not session_id = set_session(env, session_id, session, options)
env["rack.errors"].puts("Warning! #{self.class.name} failed to save session. Content dropped.")
- [status, headers, body]
elsif options[:defer] and not options[:renew]
env["rack.errors"].puts("Defering cookie for #{session_id}") if $VERBOSE
- [status, headers, body]
else
cookie = Hash.new
cookie[:value] = session_id
cookie[:expires] = Time.now + options[:expire_after] unless options[:expire_after].nil?
- response = Rack::Response.new(body, status, headers)
- response.set_cookie(@key, cookie.merge(options))
- response.to_a
+ Utils.set_cookie_header!(headers, @key, cookie.merge(options))
end
+
+ [status, headers, body]
end
# All thread safety and session retrival proceedures should occur here.
diff --git a/vendor/plugins/rack/lib/rack/session/cookie.rb b/vendor/plugins/rack/lib/rack/session/cookie.rb
index eace9bd0..240e6c8d 100644
--- a/vendor/plugins/rack/lib/rack/session/cookie.rb
+++ b/vendor/plugins/rack/lib/rack/session/cookie.rb
@@ -70,16 +70,15 @@ module Rack
if session_data.size > (4096 - @key.size)
env["rack.errors"].puts("Warning! Rack::Session::Cookie data size exceeds 4K. Content dropped.")
- [status, headers, body]
else
options = env["rack.session.options"]
cookie = Hash.new
cookie[:value] = session_data
cookie[:expires] = Time.now + options[:expire_after] unless options[:expire_after].nil?
- response = Rack::Response.new(body, status, headers)
- response.set_cookie(@key, cookie.merge(options))
- response.to_a
+ Utils.set_cookie_header!(headers, @key, cookie.merge(options))
end
+
+ [status, headers, body]
end
def generate_hmac(data)
diff --git a/vendor/plugins/rack/lib/rack/session/memcache.rb b/vendor/plugins/rack/lib/rack/session/memcache.rb
index 4a65cbf3..44629da3 100644
--- a/vendor/plugins/rack/lib/rack/session/memcache.rb
+++ b/vendor/plugins/rack/lib/rack/session/memcache.rb
@@ -29,9 +29,13 @@ module Rack
super
@mutex = Mutex.new
- @pool = MemCache.
- new @default_options[:memcache_server], @default_options
- raise 'No memcache servers' unless @pool.servers.any?{|s|s.alive?}
+ mserv = @default_options[:memcache_server]
+ mopts = @default_options.
+ reject{|k,v| MemCache::DEFAULT_OPTIONS.include? k }
+ @pool = MemCache.new mserv, mopts
+ unless @pool.active? and @pool.servers.any?{|c| c.alive? }
+ raise 'No memcache servers'
+ end
end
def generate_sid
@@ -41,24 +45,23 @@ module Rack
end
end
- def get_session(env, sid)
- session = @pool.get(sid) if sid
+ def get_session(env, session_id)
@mutex.lock if env['rack.multithread']
- unless sid and session
- env['rack.errors'].puts("Session '#{sid.inspect}' not found, initializing...") if $VERBOSE and not sid.nil?
- session = {}
- sid = generate_sid
- ret = @pool.add sid, session
- raise "Session collision on '#{sid.inspect}'" unless /^STORED/ =~ ret
+ unless session_id and session = @pool.get(session_id)
+ session_id, session = generate_sid, {}
+ unless /^STORED/ =~ @pool.add(session_id, session)
+ raise "Session collision on '#{session_id.inspect}'"
+ end
end
- session.instance_variable_set('@old', {}.merge(session))
- return [sid, session]
- rescue MemCache::MemCacheError, Errno::ECONNREFUSED # MemCache server cannot be contacted
- warn "#{self} is unable to find server."
+ session.instance_variable_set '@old', @pool.get(session_id, true)
+ return [session_id, session]
+ rescue MemCache::MemCacheError, Errno::ECONNREFUSED
+ # MemCache server cannot be contacted
+ warn "#{self} is unable to find memcached server."
warn $!.inspect
return [ nil, {} ]
ensure
- @mutex.unlock if env['rack.multithread']
+ @mutex.unlock if @mutex.locked?
end
def set_session(env, session_id, new_session, options)
@@ -66,43 +69,50 @@ module Rack
expiry = expiry.nil? ? 0 : expiry + 1
@mutex.lock if env['rack.multithread']
- session = @pool.get(session_id) || {}
if options[:renew] or options[:drop]
@pool.delete session_id
return false if options[:drop]
session_id = generate_sid
- @pool.add session_id, 0 # so we don't worry about cache miss on #set
+ @pool.add session_id, {} # so we don't worry about cache miss on #set
end
- old_session = new_session.instance_variable_get('@old') || {}
- session = merge_sessions session_id, old_session, new_session, session
+
+ session = @pool.get(session_id) || {}
+ old_session = new_session.instance_variable_get '@old'
+ old_session = old_session ? Marshal.load(old_session) : {}
+
+ unless Hash === old_session and Hash === new_session
+ env['rack.errors'].
+ puts 'Bad old_session or new_session sessions provided.'
+ else # merge sessions
+ # alterations are either update or delete, making as few changes as
+ # possible to prevent possible issues.
+
+ # removed keys
+ delete = old_session.keys - new_session.keys
+ if $VERBOSE and not delete.empty?
+ env['rack.errors'].
+ puts "//@#{session_id}: delete #{delete*','}"
+ end
+ delete.each{|k| session.delete k }
+
+ # added or altered keys
+ update = new_session.keys.
+ select{|k| new_session[k] != old_session[k] }
+ if $VERBOSE and not update.empty?
+ env['rack.errors'].puts "//@#{session_id}: update #{update*','}"
+ end
+ update.each{|k| session[k] = new_session[k] }
+ end
+
@pool.set session_id, session, expiry
return session_id
- rescue MemCache::MemCacheError, Errno::ECONNREFUSED # MemCache server cannot be contacted
- warn "#{self} is unable to find server."
+ rescue MemCache::MemCacheError, Errno::ECONNREFUSED
+ # MemCache server cannot be contacted
+ warn "#{self} is unable to find memcached server."
warn $!.inspect
return false
ensure
- @mutex.unlock if env['rack.multithread']
- end
-
- private
-
- def merge_sessions sid, old, new, cur=nil
- cur ||= {}
- unless Hash === old and Hash === new
- warn 'Bad old or new sessions provided.'
- return cur
- end
-
- delete = old.keys - new.keys
- warn "//@#{sid}: delete #{delete*','}" if $VERBOSE and not delete.empty?
- delete.each{|k| cur.delete k }
-
- update = new.keys.select{|k| new[k] != old[k] }
- warn "//@#{sid}: update #{update*','}" if $VERBOSE and not update.empty?
- update.each{|k| cur[k] = new[k] }
-
- cur
+ @mutex.unlock if @mutex.locked?
end
end
end
diff --git a/vendor/plugins/rack/lib/rack/session/pool.rb b/vendor/plugins/rack/lib/rack/session/pool.rb
index f6f87408..b3f8bd72 100644
--- a/vendor/plugins/rack/lib/rack/session/pool.rb
+++ b/vendor/plugins/rack/lib/rack/session/pool.rb
@@ -13,7 +13,7 @@ module Rack
# In the context of a multithreaded environment, sessions being
# committed to the pool is done in a merging manner.
#
- # The :drop option is available in rack.session.options if you with to
+ # The :drop option is available in rack.session.options if you wish to
# explicitly remove the session from the session cache.
#
# Example:
diff --git a/vendor/plugins/rack/lib/rack/urlmap.rb b/vendor/plugins/rack/lib/rack/urlmap.rb
index fcf6616c..b699d35b 100644
--- a/vendor/plugins/rack/lib/rack/urlmap.rb
+++ b/vendor/plugins/rack/lib/rack/urlmap.rb
@@ -28,27 +28,28 @@ module Rack
raise ArgumentError, "paths need to start with /"
end
location = location.chomp('/')
+ match = Regexp.new("^#{Regexp.quote(location).gsub('/', '/+')}(.*)", nil, 'n')
- [host, location, app]
- }.sort_by { |(h, l, a)| [h ? -h.size : (-1.0 / 0.0), -l.size] } # Longest path first
+ [host, location, match, app]
+ }.sort_by { |(h, l, m, a)| [h ? -h.size : (-1.0 / 0.0), -l.size] } # Longest path first
end
def call(env)
- path = env["PATH_INFO"].to_s.squeeze("/")
+ path = env["PATH_INFO"].to_s
script_name = env['SCRIPT_NAME']
hHost, sName, sPort = env.values_at('HTTP_HOST','SERVER_NAME','SERVER_PORT')
- @mapping.each { |host, location, app|
+ @mapping.each { |host, location, match, app|
next unless (hHost == host || sName == host \
|| (host.nil? && (hHost == sName || hHost == sName+':'+sPort)))
- next unless location == path[0, location.size]
- next unless path[location.size] == nil || path[location.size] == ?/
+ next unless path =~ match && rest = $1
+ next unless rest.empty? || rest[0] == ?/
return app.call(
env.merge(
'SCRIPT_NAME' => (script_name + location),
- 'PATH_INFO' => path[location.size..-1]))
+ 'PATH_INFO' => rest))
}
- [404, {"Content-Type" => "text/plain"}, ["Not Found: #{path}"]]
+ [404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"}, ["Not Found: #{path}"]]
end
end
end
diff --git a/vendor/plugins/rack/lib/rack/utils.rb b/vendor/plugins/rack/lib/rack/utils.rb
index d54c928c..68fd6ace 100644
--- a/vendor/plugins/rack/lib/rack/utils.rb
+++ b/vendor/plugins/rack/lib/rack/utils.rb
@@ -27,7 +27,7 @@ module Rack
module_function :unescape
DEFAULT_SEP = /[&;] */n
-
+
# Stolen from Mongrel, with some small modifications:
# Parses a query string by breaking it up at the '&'
# and ';' characters. You can also use this to parse
@@ -38,7 +38,9 @@ module Rack
(qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p|
k, v = p.split('=', 2).map { |x| unescape(x) }
-
+ if v =~ /^("|')(.*)\1$/
+ v = $2.gsub('\\'+$1, $1)
+ end
if cur = params[k]
if cur.class == Array
params[k] << v
@@ -67,6 +69,9 @@ module Rack
module_function :parse_nested_query
def normalize_params(params, name, v = nil)
+ if v and v =~ /^("|')(.*)\1$/
+ v = $2.gsub('\\'+$1, $1)
+ end
name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
k = $1 || ''
after = $' || ''
@@ -109,6 +114,25 @@ module Rack
end
module_function :build_query
+ def build_nested_query(value, prefix = nil)
+ case value
+ when Array
+ value.map { |v|
+ build_nested_query(v, "#{prefix}[]")
+ }.join("&")
+ when Hash
+ value.map { |k, v|
+ build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
+ }.join("&")
+ when String
+ raise ArgumentError, "value must be a Hash" if prefix.nil?
+ "#{prefix}=#{escape(value)}"
+ else
+ prefix
+ end
+ end
+ module_function :build_nested_query
+
# Escape ampersands, brackets and quotes to their HTML/XML entities.
def escape_html(string)
string.to_s.gsub("&", "&").
@@ -149,6 +173,54 @@ module Rack
end
module_function :select_best_encoding
+ def set_cookie_header!(header, key, value)
+ case value
+ when Hash
+ domain = "; domain=" + value[:domain] if value[:domain]
+ path = "; path=" + value[:path] if value[:path]
+ # According to RFC 2109, we need dashes here.
+ # N.B.: cgi.rb uses spaces...
+ expires = "; expires=" + value[:expires].clone.gmtime.
+ strftime("%a, %d-%b-%Y %H:%M:%S GMT") if value[:expires]
+ secure = "; secure" if value[:secure]
+ httponly = "; HttpOnly" if value[:httponly]
+ value = value[:value]
+ end
+ value = [value] unless Array === value
+ cookie = escape(key) + "=" +
+ value.map { |v| escape v }.join("&") +
+ "#{domain}#{path}#{expires}#{secure}#{httponly}"
+
+ case header["Set-Cookie"]
+ when Array
+ header["Set-Cookie"] << cookie
+ when String
+ header["Set-Cookie"] = [header["Set-Cookie"], cookie]
+ when nil
+ header["Set-Cookie"] = cookie
+ end
+
+ nil
+ end
+ module_function :set_cookie_header!
+
+ def delete_cookie_header!(header, key, value = {})
+ unless Array === header["Set-Cookie"]
+ header["Set-Cookie"] = [header["Set-Cookie"]].compact
+ end
+
+ header["Set-Cookie"].reject! { |cookie|
+ cookie =~ /\A#{escape(key)}=/
+ }
+
+ set_cookie_header!(header, key,
+ {:value => '', :path => nil, :domain => nil,
+ :expires => Time.at(0) }.merge(value))
+
+ nil
+ end
+ module_function :delete_cookie_header!
+
# Return the bytesize of String; uses String#length under Ruby 1.8 and
# String#bytesize under 1.9.
if ''.respond_to?(:bytesize)
@@ -191,11 +263,22 @@ module Rack
# A case-insensitive Hash that preserves the original case of a
# header when set.
class HeaderHash < Hash
+ def self.new(hash={})
+ HeaderHash === hash ? hash : super(hash)
+ end
+
def initialize(hash={})
+ super()
@names = {}
hash.each { |k, v| self[k] = v }
end
+ def each
+ super do |k, v|
+ yield(k, v.respond_to?(:to_ary) ? v.to_ary.join("\n") : v)
+ end
+ end
+
def to_hash
inject({}) do |hash, (k,v)|
if v.respond_to? :to_ary
@@ -208,21 +291,24 @@ module Rack
end
def [](k)
- super @names[k.downcase]
+ super(@names[k] ||= @names[k.downcase])
end
def []=(k, v)
delete k
- @names[k.downcase] = k
+ @names[k] = @names[k.downcase] = k
super k, v
end
def delete(k)
- super @names.delete(k.downcase)
+ canonical = k.downcase
+ result = super @names.delete(canonical)
+ @names.delete_if { |name,| name.downcase == canonical }
+ result
end
def include?(k)
- @names.has_key? k.downcase
+ @names.include?(k) || @names.include?(k.downcase)
end
alias_method :has_key?, :include?
@@ -238,13 +324,23 @@ module Rack
hash = dup
hash.merge! other
end
+
+ def replace(other)
+ clear
+ other.each { |k, v| self[k] = v }
+ self
+ end
end
# Every standard HTTP code mapped to the appropriate message.
- # Stolen from Mongrel.
+ # Generated with:
+ # curl -s http://www.iana.org/assignments/http-status-codes | \
+ # ruby -ane 'm = /^(\d{3}) +(\S[^\[(]+)/.match($_) and
+ # puts " #{m[1]} => \x27#{m[2].strip}x27,"'
HTTP_STATUS_CODES = {
100 => 'Continue',
101 => 'Switching Protocols',
+ 102 => 'Processing',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
@@ -252,12 +348,15 @@ module Rack
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
+ 207 => 'Multi-Status',
+ 226 => 'IM Used',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
+ 306 => 'Reserved',
307 => 'Temporary Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
@@ -273,27 +372,76 @@ module Rack
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
- 414 => 'Request-URI Too Large',
+ 414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
+ 422 => 'Unprocessable Entity',
+ 423 => 'Locked',
+ 424 => 'Failed Dependency',
+ 426 => 'Upgrade Required',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
- 505 => 'HTTP Version Not Supported'
+ 505 => 'HTTP Version Not Supported',
+ 506 => 'Variant Also Negotiates',
+ 507 => 'Insufficient Storage',
+ 510 => 'Not Extended',
}
# Responses with HTTP status codes that should not have an entity body
STATUS_WITH_NO_ENTITY_BODY = Set.new((100..199).to_a << 204 << 304)
+ SYMBOL_TO_STATUS_CODE = HTTP_STATUS_CODES.inject({}) { |hash, (code, message)|
+ hash[message.downcase.gsub(/\s|-/, '_').to_sym] = code
+ hash
+ }
+
+ def status_code(status)
+ if status.is_a?(Symbol)
+ SYMBOL_TO_STATUS_CODE[status] || 500
+ else
+ status.to_i
+ end
+ end
+ module_function :status_code
+
# A multipart form data parser, adapted from IOWA.
#
# Usually, Rack::Request#POST takes care of calling this.
module Multipart
+ class UploadedFile
+ # The filename, *not* including the path, of the "uploaded" file
+ attr_reader :original_filename
+
+ # The content type of the "uploaded" file
+ attr_accessor :content_type
+
+ def initialize(path, content_type = "text/plain", binary = false)
+ raise "#{path} file does not exist" unless ::File.exist?(path)
+ @content_type = content_type
+ @original_filename = ::File.basename(path)
+ @tempfile = Tempfile.new(@original_filename)
+ @tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
+ @tempfile.binmode if binary
+ FileUtils.copy_file(path, @tempfile.path)
+ end
+
+ def path
+ @tempfile.path
+ end
+ alias_method :local_path, :path
+
+ def method_missing(method_name, *args, &block) #:nodoc:
+ @tempfile.__send__(method_name, *args, &block)
+ end
+ end
+
EOL = "\r\n"
+ MULTIPART_BOUNDARY = "AaB03x"
def self.parse_multipart(env)
unless env['CONTENT_TYPE'] =~
@@ -378,7 +526,7 @@ module Rack
:name => name, :tempfile => body, :head => head}
elsif !filename && content_type
body.rewind
-
+
# Generic multipart cases, not coming from a form
data = {:type => content_type,
:name => name, :tempfile => body, :head => head}
@@ -388,7 +536,8 @@ module Rack
Utils.normalize_params(params, name, data) unless data.nil?
- break if buf.empty? || content_length == -1
+ # break if we're at the end of a buffer, but not if it is the end of a field
+ break if (buf.empty? && $1 != EOL) || content_length == -1
}
input.rewind
@@ -396,6 +545,76 @@ module Rack
params
end
end
+
+ def self.build_multipart(params, first = true)
+ if first
+ unless params.is_a?(Hash)
+ raise ArgumentError, "value must be a Hash"
+ end
+
+ multipart = false
+ query = lambda { |value|
+ case value
+ when Array
+ value.each(&query)
+ when Hash
+ value.values.each(&query)
+ when UploadedFile
+ multipart = true
+ end
+ }
+ params.values.each(&query)
+ return nil unless multipart
+ end
+
+ flattened_params = Hash.new
+
+ params.each do |key, value|
+ k = first ? key.to_s : "[#{key}]"
+
+ case value
+ when Array
+ value.map { |v|
+ build_multipart(v, false).each { |subkey, subvalue|
+ flattened_params["#{k}[]#{subkey}"] = subvalue
+ }
+ }
+ when Hash
+ build_multipart(value, false).each { |subkey, subvalue|
+ flattened_params[k + subkey] = subvalue
+ }
+ else
+ flattened_params[k] = value
+ end
+ end
+
+ if first
+ flattened_params.map { |name, file|
+ if file.respond_to?(:original_filename)
+ ::File.open(file.path, "rb") do |f|
+ f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
+<<-EOF
+--#{MULTIPART_BOUNDARY}\r
+Content-Disposition: form-data; name="#{name}"; filename="#{Utils.escape(file.original_filename)}"\r
+Content-Type: #{file.content_type}\r
+Content-Length: #{::File.stat(file.path).size}\r
+\r
+#{f.read}\r
+EOF
+ end
+ else
+<<-EOF
+--#{MULTIPART_BOUNDARY}\r
+Content-Disposition: form-data; name="#{name}"\r
+\r
+#{file}\r
+EOF
+ end
+ }.join + "--#{MULTIPART_BOUNDARY}--\r"
+ else
+ flattened_params
+ end
+ end
end
end
end
diff --git a/vendor/plugins/rack/rack.gemspec b/vendor/plugins/rack/rack.gemspec
new file mode 100644
index 00000000..e28b9bb2
--- /dev/null
+++ b/vendor/plugins/rack/rack.gemspec
@@ -0,0 +1,38 @@
+Gem::Specification.new do |s|
+ s.name = "rack"
+ s.version = "1.1.0"
+ s.platform = Gem::Platform::RUBY
+ s.summary = "a modular Ruby webserver interface"
+
+ s.description = <<-EOF
+Rack provides minimal, modular and adaptable interface for developing
+web applications in Ruby. By wrapping HTTP requests and responses in
+the simplest way possible, it unifies and distills the API for web
+servers, web frameworks, and software in between (the so-called
+middleware) into a single method call.
+
+Also see http://rack.rubyforge.org.
+EOF
+
+ s.files = Dir['{bin/*,contrib/*,example/*,lib/**/*}'] +
+ %w(COPYING KNOWN-ISSUES rack.gemspec RDOX README SPEC)
+ s.bindir = 'bin'
+ s.executables << 'rackup'
+ s.require_path = 'lib'
+ s.has_rdoc = true
+ s.extra_rdoc_files = ['README', 'SPEC', 'KNOWN-ISSUES']
+ s.test_files = Dir['test/{test,spec}_*.rb']
+
+ s.author = 'Christian Neukirchen'
+ s.email = 'chneukirchen@gmail.com'
+ s.homepage = 'http://rack.rubyforge.org'
+ s.rubyforge_project = 'rack'
+
+ s.add_development_dependency 'test-spec'
+
+ s.add_development_dependency 'camping'
+ s.add_development_dependency 'fcgi'
+ s.add_development_dependency 'memcache-client'
+ s.add_development_dependency 'mongrel'
+ s.add_development_dependency 'thin'
+end
diff --git a/vendor/plugins/rack/test/cgi/test.ru b/vendor/plugins/rack/test/cgi/test.ru
index 4054b886..fc9b6ffc 100755
--- a/vendor/plugins/rack/test/cgi/test.ru
+++ b/vendor/plugins/rack/test/cgi/test.ru
@@ -1,5 +1,4 @@
-#!/usr/bin/env ../../bin/rackup
-#\ -E deployment -I ../../lib
+#!/usr/bin/env ruby -I ../../lib ../../bin/rackup -E deployment -I ../../lib
# -*- ruby -*-
require '../testrequest'
diff --git a/vendor/plugins/rack/test/multipart/bad_robots b/vendor/plugins/rack/test/multipart/bad_robots
new file mode 100644
index 00000000..7e5bd418
--- /dev/null
+++ b/vendor/plugins/rack/test/multipart/bad_robots
@@ -0,0 +1,259 @@
+--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon
+Content-Disposition: form-data; name="bbbbbbbbbbbbbbb"
+
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaa
+
+--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon
+Content-Disposition: form-data; name="ccccccc"
+
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon
+Content-Disposition: form-data; name="file.name"
+
+INPUTMSG.gz
+--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon
+Content-Disposition: form-data; name="file.content_type"
+
+application/octet-stream
+--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon
+Content-Disposition: form-data; name="file.path"
+
+/var/tmp/uploads/4/0001728414
+--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon
+Content-Disposition: form-data; name="file.md5"
+
+aa73198feb4b4c1c3186f5e7466cbbcc
+--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon
+Content-Disposition: form-data; name="file.size"
+
+13212
+--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon
+Content-Disposition: form-data; name="size"
+
+80892
+--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon
+Content-Disposition: form-data; name="mail_server_id"
+
+<1111111111.22222222.3333333333333.JavaMail.app@ffff-aaaa.dddd>
+
+--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon
+Content-Disposition: form-data; name="addresses"
+
+{"campsy_programmer@pinkedum.com":{"domain":"pinkedum.com","name":"Campsy Programmer","type":["env_sender"],"mailbox":"campsy_programmer"},"tex@rapidcity.com":{"domain":"rapidcity.com","name":"Big Tex","type":["env_recipients","to"],"mailbox":"tex"},"group-digests@linkedin.com":{"domain":"linkedin.com","name":"Group Members","type":["from"],"mailbox":"group-digests"}}
+--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon
+Content-Disposition: form-data; name="received_on"
+
+2009-11-15T14:21:11Z
+--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon
+Content-Disposition: form-data; name="id"
+
+dbfd9804d26d11deab24e3037639bf77
+--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon
+Content-Disposition: form-data; name="ip_address"
+
+127.0.0.1
+--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon--
diff --git a/vendor/plugins/rack/test/multipart/fail_16384_nofile b/vendor/plugins/rack/test/multipart/fail_16384_nofile
new file mode 100644
index 00000000..bdcd3320
--- /dev/null
+++ b/vendor/plugins/rack/test/multipart/fail_16384_nofile
@@ -0,0 +1,814 @@
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="_method"
+
+put
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="authenticity_token"
+
+XCUgSyYsZ+iHQunq/yCSKFzjeVmsXV/WcphHQ0J+05I=
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[SESE]"
+
+BooBar
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[BBBBBBBBB]"
+
+18
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[CCCCCCCCCCCCCCCCCCC]"
+
+0
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[STARTFOO]"
+
+2009-11-04
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[ENDFOO]"
+
+2009-12-01
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[DDDDDDDD]"
+
+0
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[DDDDDDDD]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[EEEEEEEEEE]"
+
+10000
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[FFFFFFFFF]"
+
+boskoizcool
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[GGGGGGGGGGG]"
+
+0
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[GGGGGGGGGGG]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[YYYYYYYYYYYYYYY]"
+
+5.00
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[ZZZZZZZZZZZZZ]"
+
+mille
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[XXXXXXXXXXXXXXXXXXXXX]"
+
+0
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][9]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][10]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][11]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][12]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][13]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][14]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][15]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][16]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][17]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][18]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][19]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][20]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][21]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][22]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][23]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][0]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][1]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][2]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][3]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][4]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][5]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][6]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][7]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][8]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][9]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][10]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][11]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][12]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][13]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][14]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][15]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][16]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][17]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][18]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][19]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][20]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][21]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][22]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][23]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][0]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][1]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][2]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][3]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][4]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][5]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][6]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][7]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][8]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][9]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][10]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][11]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][12]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][13]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][14]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][15]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][16]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][17]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][18]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][19]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][20]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][21]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][22]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][23]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][0]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][1]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][2]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][3]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][4]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][5]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][6]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][7]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][8]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][9]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][10]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][11]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][12]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][13]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][14]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][15]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][16]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][17]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][18]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][19]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][20]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][21]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][22]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][23]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][0]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][1]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][2]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][3]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][4]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][5]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][6]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][7]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][8]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][9]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][10]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][11]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][12]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][13]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][14]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][15]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][16]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][17]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][18]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][19]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][20]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][21]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][22]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][23]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][0]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][1]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][2]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][3]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][4]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][5]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][6]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][7]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][8]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][9]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][10]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][11]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][12]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][13]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][14]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][15]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][16]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][17]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][18]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][19]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][20]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][21]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][22]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][23]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][0]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][1]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][2]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][3]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][4]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][5]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][6]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][7]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][8]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][9]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][10]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][11]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][12]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][13]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][14]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][15]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][16]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][17]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][18]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][19]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][20]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][21]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][22]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][23]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][0]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][1]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][2]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][3]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][4]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][5]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][6]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][7]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][8]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[WWWWWWWWWWWWWWWWWWWWWWWWW][678][ZEZE]"
+
+PLAPLAPLAINCINCINC
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[WWWWWWWWWWWWWWWWWWWWWWWWW][678][123412341234e]"
+
+SITE
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[WWWWWWWWWWWWWWWWWWWWWWWWW][678][12345678901]"
+
+56
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_type]"
+
+none
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][has_hashashas_has]"
+
+0
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][frefrefre_fre_freee]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][frefrefre_fre_frefre]"
+
+forever
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][self_block]"
+
+0
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][GGG_RULES][][COUCOUN]"
+
+
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][GGG_RULES][][REGREG]"
+
+
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][GGG_RULES][][c1c1]"
+
+
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA_TARTARTAR_wizard_rule"
+
+
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_rule]"
+
+
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[selection_selection]"
+
+R
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[PLAPLAPLA_MEMMEMMEMM_ATTRATTRER][new][-1][selection_selection]"
+
+1
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[PLAPLAPLA_MEMMEMMEMM_ATTRATTRER][new][-1][ba_unit_id]"
+
+1015
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[PLAPLAPLA_MEMMEMMEMM_ATTRATTRER][new][-2][selection_selection]"
+
+2
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[PLAPLAPLA_MEMMEMMEMM_ATTRATTRER][new][-2][ba_unit_id]"
+
+1017
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo
+Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[tile_name]"
+
+
+------WebKitFormBoundaryWsY0GnpbI5U7ztzo--
+
diff --git a/vendor/plugins/rack/test/multipart/file1.txt b/vendor/plugins/rack/test/multipart/file1.txt
new file mode 100644
index 00000000..0839b2e9
--- /dev/null
+++ b/vendor/plugins/rack/test/multipart/file1.txt
@@ -0,0 +1 @@
+contents
\ No newline at end of file
diff --git a/vendor/plugins/rack/test/rackup/.gitignore b/vendor/plugins/rack/test/rackup/.gitignore
new file mode 100644
index 00000000..2f9d279a
--- /dev/null
+++ b/vendor/plugins/rack/test/rackup/.gitignore
@@ -0,0 +1 @@
+log_output
diff --git a/vendor/plugins/rack/test/rackup/config.ru b/vendor/plugins/rack/test/rackup/config.ru
new file mode 100644
index 00000000..f1e2e1f3
--- /dev/null
+++ b/vendor/plugins/rack/test/rackup/config.ru
@@ -0,0 +1,31 @@
+require "#{File.dirname(__FILE__)}/../testrequest"
+
+$stderr = File.open("#{File.dirname(__FILE__)}/log_output", "w")
+
+class EnvMiddleware
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ # provides a way to test that lint is present
+ if env["PATH_INFO"] == "/broken_lint"
+ return [200, {}, ["Broken Lint"]]
+ # provides a way to kill the process without knowing the pid
+ elsif env["PATH_INFO"] == "/die"
+ exit!
+ end
+
+ env["test.$DEBUG"] = $DEBUG
+ env["test.$EVAL"] = BUKKIT if defined?(BUKKIT)
+ env["test.$VERBOSE"] = $VERBOSE
+ env["test.$LOAD_PATH"] = $LOAD_PATH
+ env["test.stderr"] = File.expand_path($stderr.path)
+ env["test.Ping"] = defined?(Ping)
+ env["test.pid"] = Process.pid
+ @app.call(env)
+ end
+end
+
+use EnvMiddleware
+run TestRequest.new
diff --git a/vendor/plugins/rack/test/spec_rack_cascade.rb b/vendor/plugins/rack/test/spec_rack_cascade.rb
index 3c0f3be3..cf3c29b4 100644
--- a/vendor/plugins/rack/test/spec_rack_cascade.rb
+++ b/vendor/plugins/rack/test/spec_rack_cascade.rb
@@ -28,15 +28,13 @@ context "Rack::Cascade" do
Rack::MockRequest.new(cascade).get("/cgi/../bla").should.be.not_found
end
- specify "should fail if empty" do
- lambda { Rack::MockRequest.new(Rack::Cascade.new([])).get("/") }.
- should.raise(ArgumentError)
+ specify "should return 404 if empty" do
+ Rack::MockRequest.new(Rack::Cascade.new([])).get('/').should.be.not_found
end
specify "should append new app" do
cascade = Rack::Cascade.new([], [404, 403])
- lambda { Rack::MockRequest.new(cascade).get('/cgi/test') }.
- should.raise(ArgumentError)
+ Rack::MockRequest.new(cascade).get('/').should.be.not_found
cascade << app2
Rack::MockRequest.new(cascade).get('/cgi/test').should.be.not_found
Rack::MockRequest.new(cascade).get('/cgi/../bla').should.be.not_found
diff --git a/vendor/plugins/rack/test/spec_rack_cgi.rb b/vendor/plugins/rack/test/spec_rack_cgi.rb
index 818fabdf..59500cd7 100644
--- a/vendor/plugins/rack/test/spec_rack_cgi.rb
+++ b/vendor/plugins/rack/test/spec_rack_cgi.rb
@@ -3,7 +3,7 @@ require 'testrequest'
context "Rack::Handler::CGI" do
include TestRequest::Helpers
-
+
setup do
@host = '0.0.0.0'
@port = 9203
@@ -36,7 +36,7 @@ context "Rack::Handler::CGI" do
specify "should have rack headers" do
GET("/test")
- response["rack.version"].should.equal [1,0]
+ response["rack.version"].should.equal [1,1]
response["rack.multithread"].should.be false
response["rack.multiprocess"].should.be true
response["rack.run_once"].should.be true
@@ -47,7 +47,7 @@ context "Rack::Handler::CGI" do
response["REQUEST_METHOD"].should.equal "GET"
response["SCRIPT_NAME"].should.equal "/test"
response["REQUEST_PATH"].should.equal "/"
- response["PATH_INFO"].should.be.nil
+ response["PATH_INFO"].should.equal ""
response["QUERY_STRING"].should.equal ""
response["test.postdata"].should.equal ""
diff --git a/vendor/plugins/rack/test/spec_rack_commonlogger.rb b/vendor/plugins/rack/test/spec_rack_commonlogger.rb
index ba03b78a..46a72e86 100644
--- a/vendor/plugins/rack/test/spec_rack_commonlogger.rb
+++ b/vendor/plugins/rack/test/spec_rack_commonlogger.rb
@@ -7,26 +7,55 @@ require 'rack/mock'
context "Rack::CommonLogger" do
app = lambda { |env|
+ [200,
+ {"Content-Type" => "text/html", "Content-Length" => length.to_s},
+ [obj]]}
+ app_without_length = lambda { |env|
[200,
{"Content-Type" => "text/html"},
- ["foo"]]}
+ []]}
+ app_with_zero_length = lambda { |env|
+ [200,
+ {"Content-Type" => "text/html", "Content-Length" => "0"},
+ []]}
specify "should log to rack.errors by default" do
- log = StringIO.new
res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/")
res.errors.should.not.be.empty
- res.errors.should =~ /GET /
- res.errors.should =~ / 200 / # status
- res.errors.should =~ / 3 / # length
+ res.errors.should =~ /"GET \/ " 200 #{length} /
end
- specify "should log to anything with <<" do
- log = ""
+ specify "should log to anything with +write+" do
+ log = StringIO.new
res = Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
- log.should =~ /GET /
- log.should =~ / 200 / # status
- log.should =~ / 3 / # length
+ log.string.should =~ /"GET \/ " 200 #{length} /
+ end
+
+ specify "should log - content length if header is missing" do
+ res = Rack::MockRequest.new(Rack::CommonLogger.new(app_without_length)).get("/")
+
+ res.errors.should.not.be.empty
+ res.errors.should =~ /"GET \/ " 200 - /
+ end
+
+ specify "should log - content length if header is zero" do
+ res = Rack::MockRequest.new(Rack::CommonLogger.new(app_with_zero_length)).get("/")
+
+ res.errors.should.not.be.empty
+ res.errors.should =~ /"GET \/ " 200 - /
+ end
+
+ def length
+ self.class.length
+ end
+
+ def self.length
+ 123
+ end
+
+ def self.obj
+ "hello world"
end
end
diff --git a/vendor/plugins/rack/test/spec_rack_config.rb b/vendor/plugins/rack/test/spec_rack_config.rb
new file mode 100644
index 00000000..a508ea4b
--- /dev/null
+++ b/vendor/plugins/rack/test/spec_rack_config.rb
@@ -0,0 +1,24 @@
+require 'test/spec'
+require 'rack/mock'
+require 'rack/builder'
+require 'rack/content_length'
+require 'rack/config'
+
+context "Rack::Config" do
+
+ specify "should accept a block that modifies the environment" do
+ app = Rack::Builder.new do
+ use Rack::Lint
+ use Rack::ContentLength
+ use Rack::Config do |env|
+ env['greeting'] = 'hello'
+ end
+ run lambda { |env|
+ [200, {'Content-Type' => 'text/plain'}, [env['greeting'] || '']]
+ }
+ end
+ response = Rack::MockRequest.new(app).get('/')
+ response.body.should.equal('hello')
+ end
+
+end
diff --git a/vendor/plugins/rack/test/spec_rack_directory.rb b/vendor/plugins/rack/test/spec_rack_directory.rb
index 540c728d..d255c91d 100644
--- a/vendor/plugins/rack/test/spec_rack_directory.rb
+++ b/vendor/plugins/rack/test/spec_rack_directory.rb
@@ -6,7 +6,7 @@ require 'rack/lint'
require 'rack/mock'
context "Rack::Directory" do
- DOCROOT = File.expand_path(File.dirname(__FILE__))
+ DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT
FILE_CATCH = proc{|env| [200, {'Content-Type'=>'text/plain', "Content-Length" => "7"}, ['passed!']] }
app = Rack::Directory.new DOCROOT, FILE_CATCH
diff --git a/vendor/plugins/rack/test/spec_rack_etag.rb b/vendor/plugins/rack/test/spec_rack_etag.rb
new file mode 100644
index 00000000..73cd31ac
--- /dev/null
+++ b/vendor/plugins/rack/test/spec_rack_etag.rb
@@ -0,0 +1,17 @@
+require 'test/spec'
+require 'rack/mock'
+require 'rack/etag'
+
+context "Rack::ETag" do
+ specify "sets ETag if none is set" do
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
+ response = Rack::ETag.new(app).call({})
+ response[1]['ETag'].should.equal "\"65a8e27d8879283831b664bd8b7f0ad4\""
+ end
+
+ specify "does not change ETag if it is already set" do
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'ETag' => '"abc"'}, ["Hello, World!"]] }
+ response = Rack::ETag.new(app).call({})
+ response[1]['ETag'].should.equal "\"abc\""
+ end
+end
diff --git a/vendor/plugins/rack/test/spec_rack_fastcgi.rb b/vendor/plugins/rack/test/spec_rack_fastcgi.rb
index 69478de5..1ae55ace 100644
--- a/vendor/plugins/rack/test/spec_rack_fastcgi.rb
+++ b/vendor/plugins/rack/test/spec_rack_fastcgi.rb
@@ -36,7 +36,7 @@ context "Rack::Handler::FastCGI" do
specify "should have rack headers" do
GET("/test.fcgi")
- response["rack.version"].should.equal [1,0]
+ response["rack.version"].should.equal [1,1]
response["rack.multithread"].should.be false
response["rack.multiprocess"].should.be true
response["rack.run_once"].should.be false
@@ -47,7 +47,7 @@ context "Rack::Handler::FastCGI" do
response["REQUEST_METHOD"].should.equal "GET"
response["SCRIPT_NAME"].should.equal "/test.fcgi"
response["REQUEST_PATH"].should.equal "/"
- response["PATH_INFO"].should.be.nil
+ response["PATH_INFO"].should.equal ""
response["QUERY_STRING"].should.equal ""
response["test.postdata"].should.equal ""
diff --git a/vendor/plugins/rack/test/spec_rack_file.rb b/vendor/plugins/rack/test/spec_rack_file.rb
index 1e6771ab..0a2f8ee8 100644
--- a/vendor/plugins/rack/test/spec_rack_file.rb
+++ b/vendor/plugins/rack/test/spec_rack_file.rb
@@ -6,7 +6,7 @@ require 'rack/lint'
require 'rack/mock'
context "Rack::File" do
- DOCROOT = File.expand_path(File.dirname(__FILE__))
+ DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT
specify "serves files" do
res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
diff --git a/vendor/plugins/rack/test/spec_rack_lint.rb b/vendor/plugins/rack/test/spec_rack_lint.rb
index 880a07ee..bbf75c17 100644
--- a/vendor/plugins/rack/test/spec_rack_lint.rb
+++ b/vendor/plugins/rack/test/spec_rack_lint.rb
@@ -71,6 +71,11 @@ context "Rack::Lint" do
}.should.raise(Rack::Lint::LintError).
message.should.equal("session [] must respond to store and []=")
+ lambda {
+ Rack::Lint.new(nil).call(env("rack.logger" => []))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.equal("logger [] must respond to info")
+
lambda {
Rack::Lint.new(nil).call(env("REQUEST_METHOD" => "FUCKUP?"))
}.should.raise(Rack::Lint::LintError).
@@ -110,7 +115,7 @@ context "Rack::Lint" do
Rack::Lint.new(nil).call(env("rack.input" => ""))
}.should.raise(Rack::Lint::LintError).
message.should.match(/does not respond to #gets/)
-
+
lambda {
input = Object.new
def input.binmode?
@@ -119,7 +124,7 @@ context "Rack::Lint" do
Rack::Lint.new(nil).call(env("rack.input" => input))
}.should.raise(Rack::Lint::LintError).
message.should.match(/is not opened in binary mode/)
-
+
lambda {
input = Object.new
def input.external_encoding
@@ -347,25 +352,25 @@ context "Rack::Lint" do
yield 23
yield 42
end
-
+
def rewind
raise Errno::ESPIPE, "Errno::ESPIPE"
end
end
-
+
eof_weirdio = Object.new
class << eof_weirdio
def gets
nil
end
-
+
def read(*args)
nil
end
-
+
def each
end
-
+
def rewind
end
end
@@ -452,48 +457,50 @@ context "Rack::Lint" do
}.should.raise(Rack::Lint::LintError).
message.should.match(/body was given for HEAD/)
end
-
+
specify "passes valid read calls" do
+ hello_str = "hello world"
+ hello_str.force_encoding("ASCII-8BIT") if hello_str.respond_to? :force_encoding
lambda {
Rack::Lint.new(lambda { |env|
env["rack.input"].read
[201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
- }).call(env({"rack.input" => StringIO.new("hello world")}))
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
}.should.not.raise(Rack::Lint::LintError)
-
+
lambda {
Rack::Lint.new(lambda { |env|
env["rack.input"].read(0)
[201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
- }).call(env({"rack.input" => StringIO.new("hello world")}))
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
}.should.not.raise(Rack::Lint::LintError)
-
+
lambda {
Rack::Lint.new(lambda { |env|
env["rack.input"].read(1)
[201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
- }).call(env({"rack.input" => StringIO.new("hello world")}))
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
}.should.not.raise(Rack::Lint::LintError)
-
+
lambda {
Rack::Lint.new(lambda { |env|
env["rack.input"].read(nil)
[201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
- }).call(env({"rack.input" => StringIO.new("hello world")}))
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
}.should.not.raise(Rack::Lint::LintError)
-
+
lambda {
Rack::Lint.new(lambda { |env|
env["rack.input"].read(nil, '')
[201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
- }).call(env({"rack.input" => StringIO.new("hello world")}))
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
}.should.not.raise(Rack::Lint::LintError)
-
+
lambda {
Rack::Lint.new(lambda { |env|
env["rack.input"].read(1, '')
[201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
- }).call(env({"rack.input" => StringIO.new("hello world")}))
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
}.should.not.raise(Rack::Lint::LintError)
end
end
diff --git a/vendor/plugins/rack/test/spec_rack_logger.rb b/vendor/plugins/rack/test/spec_rack_logger.rb
new file mode 100644
index 00000000..d55b9c77
--- /dev/null
+++ b/vendor/plugins/rack/test/spec_rack_logger.rb
@@ -0,0 +1,21 @@
+require 'rack/logger'
+require 'rack/lint'
+require 'stringio'
+
+context "Rack::Logger" do
+ specify "logs to rack.errors" do
+ app = lambda { |env|
+ log = env['rack.logger']
+ log.debug("Created logger")
+ log.info("Program started")
+ log.warn("Nothing to do!")
+
+ [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]]
+ }
+
+ errors = StringIO.new
+ Rack::Logger.new(app).call({'rack.errors' => errors})
+ errors.string.should.match "INFO -- : Program started"
+ errors.string.should.match "WARN -- : Nothing to do"
+ end
+end
diff --git a/vendor/plugins/rack/test/spec_rack_mock.rb b/vendor/plugins/rack/test/spec_rack_mock.rb
index 9c392a28..a03bedc2 100644
--- a/vendor/plugins/rack/test/spec_rack_mock.rb
+++ b/vendor/plugins/rack/test/spec_rack_mock.rb
@@ -93,6 +93,92 @@ context "Rack::MockRequest" do
env["rack.url_scheme"].should.equal "https"
end
+ specify "should set SSL port and HTTP flag on when using https" do
+ res = Rack::MockRequest.new(app).
+ get("https://example.org/foo")
+ res.should.be.kind_of Rack::MockResponse
+
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "GET"
+ env["SERVER_NAME"].should.equal "example.org"
+ env["SERVER_PORT"].should.equal "443"
+ env["QUERY_STRING"].should.equal ""
+ env["PATH_INFO"].should.equal "/foo"
+ env["rack.url_scheme"].should.equal "https"
+ env["HTTPS"].should.equal "on"
+ end
+
+ specify "should prepend slash to uri path" do
+ res = Rack::MockRequest.new(app).
+ get("foo")
+ res.should.be.kind_of Rack::MockResponse
+
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "GET"
+ env["SERVER_NAME"].should.equal "example.org"
+ env["SERVER_PORT"].should.equal "80"
+ env["QUERY_STRING"].should.equal ""
+ env["PATH_INFO"].should.equal "/foo"
+ env["rack.url_scheme"].should.equal "http"
+ end
+
+ specify "should properly convert method name to an uppercase string" do
+ res = Rack::MockRequest.new(app).request(:get)
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "GET"
+ end
+
+ specify "should accept params and build query string for GET requests" do
+ res = Rack::MockRequest.new(app).get("/foo?baz=2", :params => {:foo => {:bar => "1"}})
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "GET"
+ env["QUERY_STRING"].should.match "baz=2"
+ env["QUERY_STRING"].should.match "foo[bar]=1"
+ env["PATH_INFO"].should.equal "/foo"
+ env["mock.postdata"].should.equal ""
+ end
+
+ specify "should accept raw input in params for GET requests" do
+ res = Rack::MockRequest.new(app).get("/foo?baz=2", :params => "foo[bar]=1")
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "GET"
+ env["QUERY_STRING"].should.match "baz=2"
+ env["QUERY_STRING"].should.match "foo[bar]=1"
+ env["PATH_INFO"].should.equal "/foo"
+ env["mock.postdata"].should.equal ""
+ end
+
+ specify "should accept params and build url encoded params for POST requests" do
+ res = Rack::MockRequest.new(app).post("/foo", :params => {:foo => {:bar => "1"}})
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "POST"
+ env["QUERY_STRING"].should.equal ""
+ env["PATH_INFO"].should.equal "/foo"
+ env["CONTENT_TYPE"].should.equal "application/x-www-form-urlencoded"
+ env["mock.postdata"].should.equal "foo[bar]=1"
+ end
+
+ specify "should accept raw input in params for POST requests" do
+ res = Rack::MockRequest.new(app).post("/foo", :params => "foo[bar]=1")
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "POST"
+ env["QUERY_STRING"].should.equal ""
+ env["PATH_INFO"].should.equal "/foo"
+ env["CONTENT_TYPE"].should.equal "application/x-www-form-urlencoded"
+ env["mock.postdata"].should.equal "foo[bar]=1"
+ end
+
+ specify "should accept params and build multipart encoded params for POST requests" do
+ files = Rack::Utils::Multipart::UploadedFile.new(File.join(File.dirname(__FILE__), "multipart", "file1.txt"))
+ res = Rack::MockRequest.new(app).post("/foo", :params => { "submit-name" => "Larry", "files" => files })
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "POST"
+ env["QUERY_STRING"].should.equal ""
+ env["PATH_INFO"].should.equal "/foo"
+ env["CONTENT_TYPE"].should.equal "multipart/form-data; boundary=AaB03x"
+ env["mock.postdata"].length.should.equal 206
+ end
+
specify "should behave valid according to the Rack spec" do
lambda {
res = Rack::MockRequest.new(app).
@@ -130,7 +216,7 @@ context "Rack::MockResponse" do
res.original_headers["Content-Type"].should.equal "text/yaml"
res["Content-Type"].should.equal "text/yaml"
res.content_type.should.equal "text/yaml"
- res.content_length.should.be 401 # needs change often.
+ res.content_length.should.be 414 # needs change often.
res.location.should.be.nil
end
diff --git a/vendor/plugins/rack/test/spec_rack_mongrel.rb b/vendor/plugins/rack/test/spec_rack_mongrel.rb
index d73e884c..4b386891 100644
--- a/vendor/plugins/rack/test/spec_rack_mongrel.rb
+++ b/vendor/plugins/rack/test/spec_rack_mongrel.rb
@@ -6,14 +6,14 @@ require 'rack/urlmap'
require 'rack/lint'
require 'testrequest'
require 'timeout'
-
+
Thread.abort_on_exception = true
$tcp_defer_accept_opts = nil
$tcp_cork_opts = nil
context "Rack::Handler::Mongrel" do
include TestRequest::Helpers
-
+
setup do
server = Mongrel::HttpServer.new(@host='0.0.0.0', @port=9201)
server.register('/test',
@@ -41,7 +41,7 @@ context "Rack::Handler::Mongrel" do
specify "should have rack headers" do
GET("/test")
- response["rack.version"].should.equal [1,0]
+ response["rack.version"].should.equal [1,1]
response["rack.multithread"].should.be true
response["rack.multiprocess"].should.be false
response["rack.run_once"].should.be false
@@ -52,7 +52,7 @@ context "Rack::Handler::Mongrel" do
response["REQUEST_METHOD"].should.equal "GET"
response["SCRIPT_NAME"].should.equal "/test"
response["REQUEST_PATH"].should.equal "/test"
- response["PATH_INFO"].should.be.nil
+ response["PATH_INFO"].should.be.equal ""
response["QUERY_STRING"].should.equal ""
response["test.postdata"].should.equal ""
diff --git a/vendor/plugins/rack/test/spec_rack_nulllogger.rb b/vendor/plugins/rack/test/spec_rack_nulllogger.rb
new file mode 100644
index 00000000..b3c2bc9c
--- /dev/null
+++ b/vendor/plugins/rack/test/spec_rack_nulllogger.rb
@@ -0,0 +1,13 @@
+require 'rack/nulllogger'
+require 'rack/lint'
+require 'rack/mock'
+
+context "Rack::NullLogger" do
+ specify "acks as a nop logger" do
+ app = lambda { |env|
+ env['rack.logger'].warn "b00m"
+ [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]]
+ }
+ Rack::NullLogger.new(app).call({})
+ end
+end
diff --git a/vendor/plugins/rack/test/spec_rack_request.rb b/vendor/plugins/rack/test/spec_rack_request.rb
index 74e2f00a..fcdeb484 100644
--- a/vendor/plugins/rack/test/spec_rack_request.rb
+++ b/vendor/plugins/rack/test/spec_rack_request.rb
@@ -35,9 +35,18 @@ context "Rack::Request" do
req.host.should.equal "www2.example.org"
req = Rack::Request.new \
- Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org:9292")
+ Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292")
req.host.should.equal "example.org"
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292")
+ req.host.should.equal "example.org"
+
+ env = Rack::MockRequest.env_for("/", "SERVER_ADDR" => "192.168.1.1", "SERVER_PORT" => "9292")
+ env.delete("SERVER_NAME")
+ req = Rack::Request.new(env)
+ req.host.should.equal "192.168.1.1"
+
env = Rack::MockRequest.env_for("/")
env.delete("SERVER_NAME")
req = Rack::Request.new(env)
@@ -52,9 +61,16 @@ context "Rack::Request" do
req.params.should.equal "foo" => "bar", "quux" => "bla"
end
- specify "can parse POST data" do
+ specify "raises if rack.input is missing" do
+ req = Rack::Request.new({})
+ lambda { req.POST }.should.raise(RuntimeError)
+ end
+
+ specify "can parse POST data when method is POST and no Content-Type given" do
req = Rack::Request.new \
- Rack::MockRequest.env_for("/?foo=quux", :input => "foo=bar&quux=bla")
+ Rack::MockRequest.env_for("/?foo=quux",
+ "REQUEST_METHOD" => 'POST',
+ :input => "foo=bar&quux=bla")
req.content_type.should.be.nil
req.media_type.should.be.nil
req.query_string.should.equal "foo=quux"
@@ -63,7 +79,7 @@ context "Rack::Request" do
req.params.should.equal "foo" => "bar", "quux" => "bla"
end
- specify "can parse POST data with explicit content type" do
+ specify "can parse POST data with explicit content type regardless of method" do
req = Rack::Request.new \
Rack::MockRequest.env_for("/",
"CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
@@ -78,6 +94,7 @@ context "Rack::Request" do
specify "does not parse POST data when media type is not form-data" do
req = Rack::Request.new \
Rack::MockRequest.env_for("/?foo=quux",
+ "REQUEST_METHOD" => 'POST',
"CONTENT_TYPE" => 'text/plain;charset=utf-8',
:input => "foo=bar&quux=bla")
req.content_type.should.equal 'text/plain;charset=utf-8'
@@ -88,6 +105,16 @@ context "Rack::Request" do
req.body.read.should.equal "foo=bar&quux=bla"
end
+ specify "can parse POST data on PUT when media type is form-data" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/?foo=quux",
+ "REQUEST_METHOD" => 'PUT',
+ "CONTENT_TYPE" => 'application/x-www-form-urlencoded',
+ :input => "foo=bar&quux=bla")
+ req.POST.should.equal "foo" => "bar", "quux" => "bla"
+ req.body.read.should.equal "foo=bar&quux=bla"
+ end
+
specify "rewinds input after parsing POST data" do
input = StringIO.new("foo=bar&quux=bla")
req = Rack::Request.new \
@@ -100,7 +127,8 @@ context "Rack::Request" do
specify "cleans up Safari's ajax POST body" do
req = Rack::Request.new \
- Rack::MockRequest.env_for("/", :input => "foo=bar&quux=bla\0")
+ Rack::MockRequest.env_for("/",
+ 'REQUEST_METHOD' => 'POST', :input => "foo=bar&quux=bla\0")
req.POST.should.equal "foo" => "bar", "quux" => "bla"
end
@@ -147,9 +175,21 @@ context "Rack::Request" do
req.referer.should.equal "/"
end
+ specify "user agent should be extracted correct" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/", "HTTP_USER_AGENT" => "Mozilla/4.0 (compatible)")
+ req.user_agent.should.equal "Mozilla/4.0 (compatible)"
+
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/")
+ req.user_agent.should.equal nil
+ end
+
specify "can cache, but invalidates the cache" do
req = Rack::Request.new \
- Rack::MockRequest.env_for("/?foo=quux", :input => "foo=bar&quux=bla")
+ Rack::MockRequest.env_for("/?foo=quux",
+ "CONTENT_TYPE" => "application/x-www-form-urlencoded",
+ :input => "foo=bar&quux=bla")
req.GET.should.equal "foo" => "quux"
req.GET.should.equal "foo" => "quux"
req.env["QUERY_STRING"] = "bla=foo"
@@ -424,6 +464,7 @@ Content-Transfer-Encoding: base64\r
/9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
--AaB03x--\r
EOF
+ input.force_encoding("ASCII-8BIT") if input.respond_to? :force_encoding
res = Rack::MockRequest.new(Rack::Lint.new(app)).get "/",
"CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
"CONTENT_LENGTH" => input.size.to_s, "rack.input" => StringIO.new(input)
diff --git a/vendor/plugins/rack/test/spec_rack_response.rb b/vendor/plugins/rack/test/spec_rack_response.rb
index eb59b5c2..7989013d 100644
--- a/vendor/plugins/rack/test/spec_rack_response.rb
+++ b/vendor/plugins/rack/test/spec_rack_response.rb
@@ -118,6 +118,9 @@ context "Rack::Response" do
r = Rack::Response.new([], 500)
r.status.should.equal 500
+
+ r = Rack::Response.new([], "200 OK")
+ r.status.should.equal 200
end
specify "has a constructor that can take a block" do
diff --git a/vendor/plugins/rack/test/spec_rack_runtime.rb b/vendor/plugins/rack/test/spec_rack_runtime.rb
new file mode 100644
index 00000000..62d80956
--- /dev/null
+++ b/vendor/plugins/rack/test/spec_rack_runtime.rb
@@ -0,0 +1,35 @@
+require 'test/spec'
+require 'rack/mock'
+require 'rack/runtime'
+
+context "Rack::Runtime" do
+ specify "sets X-Runtime is none is set" do
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
+ response = Rack::Runtime.new(app).call({})
+ response[1]['X-Runtime'].should =~ /[\d\.]+/
+ end
+
+ specify "does not set the X-Runtime if it is already set" do
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain', "X-Runtime" => "foobar"}, "Hello, World!"] }
+ response = Rack::Runtime.new(app).call({})
+ response[1]['X-Runtime'].should == "foobar"
+ end
+
+ specify "should allow a suffix to be set" do
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
+ response = Rack::Runtime.new(app, "Test").call({})
+ response[1]['X-Runtime-Test'].should =~ /[\d\.]+/
+ end
+
+ specify "should allow multiple timers to be set" do
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
+ runtime1 = Rack::Runtime.new(app, "App")
+ runtime2 = Rack::Runtime.new(runtime1, "All")
+ response = runtime2.call({})
+
+ response[1]['X-Runtime-App'].should =~ /[\d\.]+/
+ response[1]['X-Runtime-All'].should =~ /[\d\.]+/
+
+ Float(response[1]['X-Runtime-All']).should > Float(response[1]['X-Runtime-App'])
+ end
+end
diff --git a/vendor/plugins/rack/test/spec_rack_sendfile.rb b/vendor/plugins/rack/test/spec_rack_sendfile.rb
new file mode 100644
index 00000000..8cfe2017
--- /dev/null
+++ b/vendor/plugins/rack/test/spec_rack_sendfile.rb
@@ -0,0 +1,86 @@
+require 'test/spec'
+require 'rack/mock'
+require 'rack/sendfile'
+
+context "Rack::File" do
+ specify "should respond to #to_path" do
+ Rack::File.new(Dir.pwd).should.respond_to :to_path
+ end
+end
+
+context "Rack::Sendfile" do
+ def sendfile_body
+ res = ['Hello World']
+ def res.to_path ; "/tmp/hello.txt" ; end
+ res
+ end
+
+ def simple_app(body=sendfile_body)
+ lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
+ end
+
+ def sendfile_app(body=sendfile_body)
+ Rack::Sendfile.new(simple_app(body))
+ end
+
+ setup do
+ @request = Rack::MockRequest.new(sendfile_app)
+ end
+
+ def request(headers={})
+ yield @request.get('/', headers)
+ end
+
+ specify "does nothing when no X-Sendfile-Type header present" do
+ request do |response|
+ response.should.be.ok
+ response.body.should.equal 'Hello World'
+ response.headers.should.not.include 'X-Sendfile'
+ end
+ end
+
+ specify "sets X-Sendfile response header and discards body" do
+ request 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' do |response|
+ response.should.be.ok
+ response.body.should.be.empty
+ response.headers['X-Sendfile'].should.equal '/tmp/hello.txt'
+ end
+ end
+
+ specify "sets X-Lighttpd-Send-File response header and discards body" do
+ request 'HTTP_X_SENDFILE_TYPE' => 'X-Lighttpd-Send-File' do |response|
+ response.should.be.ok
+ response.body.should.be.empty
+ response.headers['X-Lighttpd-Send-File'].should.equal '/tmp/hello.txt'
+ end
+ end
+
+ specify "sets X-Accel-Redirect response header and discards body" do
+ headers = {
+ 'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect',
+ 'HTTP_X_ACCEL_MAPPING' => '/tmp/=/foo/bar/'
+ }
+ request headers do |response|
+ response.should.be.ok
+ response.body.should.be.empty
+ response.headers['X-Accel-Redirect'].should.equal '/foo/bar/hello.txt'
+ end
+ end
+
+ specify 'writes to rack.error when no X-Accel-Mapping is specified' do
+ request 'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect' do |response|
+ response.should.be.ok
+ response.body.should.equal 'Hello World'
+ response.headers.should.not.include 'X-Accel-Redirect'
+ response.errors.should.include 'X-Accel-Mapping'
+ end
+ end
+
+ specify 'does nothing when body does not respond to #to_path' do
+ @request = Rack::MockRequest.new(sendfile_app(['Not a file...']))
+ request 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' do |response|
+ response.body.should.equal 'Not a file...'
+ response.headers.should.not.include 'X-Sendfile'
+ end
+ end
+end
diff --git a/vendor/plugins/rack/test/spec_rack_session_memcache.rb b/vendor/plugins/rack/test/spec_rack_session_memcache.rb
index 37c3d895..faac796e 100644
--- a/vendor/plugins/rack/test/spec_rack_session_memcache.rb
+++ b/vendor/plugins/rack/test/spec_rack_session_memcache.rb
@@ -8,7 +8,7 @@ begin
context "Rack::Session::Memcache" do
session_key = Rack::Session::Memcache::DEFAULT_OPTIONS[:key]
- session_match = /#{session_key}=[0-9a-fA-F]+;/
+ session_match = /#{session_key}=([0-9a-fA-F]+);/
incrementor = lambda do |env|
env["rack.session"]["counter"] ||= 0
env["rack.session"]["counter"] += 1
@@ -27,14 +27,20 @@ begin
incrementor.call(env)
end
- specify "MemCache can connect to existing server" do
- test_pool = MemCache.new :namespace => 'test:rack:session'
+ specify "faults on no connection" do
+ if RUBY_VERSION < "1.9"
+ lambda do
+ Rack::Session::Memcache.new incrementor, :memcache_server => 'nosuchserver'
+ end.should.raise
+ else
+ lambda do
+ Rack::Session::Memcache.new incrementor, :memcache_server => 'nosuchserver'
+ end.should.raise ArgumentError
+ end
end
- specify "faults on no connection" do
- lambda do
- Rack::Session::Memcache.new(incrementor, :memcache_server => '')
- end.should.raise
+ specify "connect to existing server" do
+ test_pool = MemCache.new incrementor, :namespace => 'test:rack:session'
end
specify "creates a new cookie" do
@@ -151,6 +157,31 @@ begin
res3.body.should.equal '{"counter"=>4}'
end
+ specify "deep hashes are correctly updated" do
+ store = nil
+ hash_check = proc do |env|
+ session = env['rack.session']
+ unless session.include? 'test'
+ session.update :a => :b, :c => { :d => :e },
+ :f => { :g => { :h => :i} }, 'test' => true
+ else
+ session[:f][:g][:h] = :j
+ end
+ [200, {}, session.inspect]
+ end
+ pool = Rack::Session::Memcache.new(hash_check)
+ req = Rack::MockRequest.new(pool)
+
+ res0 = req.get("/")
+ session_id = (cookie = res0["Set-Cookie"])[session_match, 1]
+ ses0 = pool.pool.get(session_id, true)
+
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
+ ses1 = pool.pool.get(session_id, true)
+
+ ses1.should.not.equal ses0
+ end
+
# anyone know how to do this better?
specify "multithread: should cleanly merge sessions" do
next unless $DEBUG
@@ -161,7 +192,7 @@ begin
res = req.get('/')
res.body.should.equal '{"counter"=>1}'
cookie = res["Set-Cookie"]
- sess_id = cookie[/#{pool.key}=([^,;]+)/,1]
+ session_id = cookie[session_match, 1]
delta_incrementor = lambda do |env|
# emulate disconjoinment of threading
@@ -178,12 +209,12 @@ begin
run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
end
end.reverse.map{|t| t.run.join.value }
- r.each do |res|
- res['Set-Cookie'].should.equal cookie
- res.body.should.include '"counter"=>2'
+ r.each do |request|
+ request['Set-Cookie'].should.equal cookie
+ request.body.should.include '"counter"=>2'
end
- session = pool.pool.get(sess_id)
+ session = pool.pool.get(session_id)
session.size.should.be tnum+1 # counter
session['counter'].should.be 2 # meeeh
@@ -202,12 +233,12 @@ begin
run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
end
end.reverse.map{|t| t.run.join.value }
- r.each do |res|
- res['Set-Cookie'].should.equal cookie
- res.body.should.include '"counter"=>3'
+ r.each do |request|
+ request['Set-Cookie'].should.equal cookie
+ request.body.should.include '"counter"=>3'
end
- session = pool.pool.get(sess_id)
+ session = pool.pool.get(session_id)
session.size.should.be tnum+1
session['counter'].should.be 3
@@ -224,17 +255,19 @@ begin
run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
end
end.reverse.map{|t| t.run.join.value }
- r.each do |res|
- res['Set-Cookie'].should.equal cookie
- res.body.should.include '"foo"=>"bar"'
+ r.each do |request|
+ request['Set-Cookie'].should.equal cookie
+ request.body.should.include '"foo"=>"bar"'
end
- session = pool.pool.get(sess_id)
+ session = pool.pool.get(session_id)
session.size.should.be r.size+1
session['counter'].should.be.nil?
session['foo'].should.equal 'bar'
end
end
+rescue RuntimeError
+ $stderr.puts "Skipping Rack::Session::Memcache tests. Start memcached and try again."
rescue LoadError
$stderr.puts "Skipping Rack::Session::Memcache tests (Memcache is required). `gem install memcache-client` and try again."
end
diff --git a/vendor/plugins/rack/test/spec_rack_urlmap.rb b/vendor/plugins/rack/test/spec_rack_urlmap.rb
index 6c4d72ac..3d8fe605 100644
--- a/vendor/plugins/rack/test/spec_rack_urlmap.rb
+++ b/vendor/plugins/rack/test/spec_rack_urlmap.rb
@@ -44,6 +44,12 @@ context "Rack::URLMap" do
res["X-ScriptName"].should.equal "/foo/bar"
res["X-PathInfo"].should.equal "/"
+ res = Rack::MockRequest.new(map).get("/foo///bar//quux")
+ res.status.should.equal 200
+ res.should.be.ok
+ res["X-ScriptName"].should.equal "/foo/bar"
+ res["X-PathInfo"].should.equal "//quux"
+
res = Rack::MockRequest.new(map).get("/foo/quux", "SCRIPT_NAME" => "/bleh")
res.should.be.ok
res["X-ScriptName"].should.equal "/bleh/foo"
@@ -182,4 +188,28 @@ context "Rack::URLMap" do
res["X-PathInfo"].should.equal "/"
res["X-ScriptName"].should.equal ""
end
+
+ specify "should not squeeze slashes" do
+ map = Rack::URLMap.new("/" => lambda { |env|
+ [200,
+ { "Content-Type" => "text/plain",
+ "X-Position" => "root",
+ "X-PathInfo" => env["PATH_INFO"],
+ "X-ScriptName" => env["SCRIPT_NAME"]
+ }, [""]]},
+ "/foo" => lambda { |env|
+ [200,
+ { "Content-Type" => "text/plain",
+ "X-Position" => "foo",
+ "X-PathInfo" => env["PATH_INFO"],
+ "X-ScriptName" => env["SCRIPT_NAME"]
+ }, [""]]}
+ )
+
+ res = Rack::MockRequest.new(map).get("/http://example.org/bar")
+ res.should.be.ok
+ res["X-Position"].should.equal "root"
+ res["X-PathInfo"].should.equal "/http://example.org/bar"
+ res["X-ScriptName"].should.equal ""
+ end
end
diff --git a/vendor/plugins/rack/test/spec_rack_utils.rb b/vendor/plugins/rack/test/spec_rack_utils.rb
index f270e87e..269a52bd 100644
--- a/vendor/plugins/rack/test/spec_rack_utils.rb
+++ b/vendor/plugins/rack/test/spec_rack_utils.rb
@@ -30,7 +30,10 @@ context "Rack::Utils" do
end
specify "should parse query strings correctly" do
- Rack::Utils.parse_query("foo=bar").should.equal "foo" => "bar"
+ Rack::Utils.parse_query("foo=bar").
+ should.equal "foo" => "bar"
+ Rack::Utils.parse_query("foo=\"bar\"").
+ should.equal "foo" => "bar"
Rack::Utils.parse_query("foo=bar&foo=quux").
should.equal "foo" => ["bar", "quux"]
Rack::Utils.parse_query("foo=1&bar=2").
@@ -47,6 +50,8 @@ context "Rack::Utils" do
should.equal "foo" => ""
Rack::Utils.parse_nested_query("foo=bar").
should.equal "foo" => "bar"
+ Rack::Utils.parse_nested_query("foo=\"bar\"").
+ should.equal "foo" => "bar"
Rack::Utils.parse_nested_query("foo=bar&foo=quux").
should.equal "foo" => "quux"
@@ -126,6 +131,53 @@ context "Rack::Utils" do
should.equal "my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F"
end
+ specify "should build nested query strings correctly" do
+ Rack::Utils.build_nested_query("foo" => nil).should.equal "foo"
+ Rack::Utils.build_nested_query("foo" => "").should.equal "foo="
+ Rack::Utils.build_nested_query("foo" => "bar").should.equal "foo=bar"
+
+ Rack::Utils.build_nested_query("foo" => "1", "bar" => "2").
+ should.equal "foo=1&bar=2"
+ Rack::Utils.build_nested_query("my weird field" => "q1!2\"'w$5&7/z8)?").
+ should.equal "my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F"
+
+ Rack::Utils.build_nested_query("foo" => [nil]).
+ should.equal "foo[]"
+ Rack::Utils.build_nested_query("foo" => [""]).
+ should.equal "foo[]="
+ Rack::Utils.build_nested_query("foo" => ["bar"]).
+ should.equal "foo[]=bar"
+
+ # The ordering of the output query string is unpredictable with 1.8's
+ # unordered hash. Test that build_nested_query performs the inverse
+ # function of parse_nested_query.
+ [{"foo" => nil, "bar" => ""},
+ {"foo" => "bar", "baz" => ""},
+ {"foo" => ["1", "2"]},
+ {"foo" => "bar", "baz" => ["1", "2", "3"]},
+ {"foo" => ["bar"], "baz" => ["1", "2", "3"]},
+ {"foo" => ["1", "2"]},
+ {"foo" => "bar", "baz" => ["1", "2", "3"]},
+ {"x" => {"y" => {"z" => "1"}}},
+ {"x" => {"y" => {"z" => ["1"]}}},
+ {"x" => {"y" => {"z" => ["1", "2"]}}},
+ {"x" => {"y" => [{"z" => "1"}]}},
+ {"x" => {"y" => [{"z" => ["1"]}]}},
+ {"x" => {"y" => [{"z" => "1", "w" => "2"}]}},
+ {"x" => {"y" => [{"v" => {"w" => "1"}}]}},
+ {"x" => {"y" => [{"z" => "1", "v" => {"w" => "2"}}]}},
+ {"x" => {"y" => [{"z" => "1"}, {"z" => "2"}]}},
+ {"x" => {"y" => [{"z" => "1", "w" => "a"}, {"z" => "2", "w" => "3"}]}}
+ ].each { |params|
+ qs = Rack::Utils.build_nested_query(params)
+ Rack::Utils.parse_nested_query(qs).should.equal params
+ }
+
+ lambda { Rack::Utils.build_nested_query("foo=bar") }.
+ should.raise(ArgumentError).
+ message.should.equal "value must be a Hash"
+ end
+
specify "should figure out which encodings are acceptable" do
helper = lambda do |a, b|
request = Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => a))
@@ -152,6 +204,18 @@ context "Rack::Utils" do
specify "should return the bytesize of String" do
Rack::Utils.bytesize("FOO\xE2\x82\xAC").should.equal 6
end
+
+ specify "should return status code for integer" do
+ Rack::Utils.status_code(200).should.equal 200
+ end
+
+ specify "should return status code for string" do
+ Rack::Utils.status_code("200").should.equal 200
+ end
+
+ specify "should return status code for symbol" do
+ Rack::Utils.status_code(:ok).should.equal 200
+ end
end
context "Rack::Utils::HeaderHash" do
@@ -190,30 +254,53 @@ context "Rack::Utils::HeaderHash" do
h = Rack::Utils::HeaderHash.new("foo" => ["bar", "baz"])
h.to_hash.should.equal({ "foo" => "bar\nbaz" })
end
-
+
+ specify "should replace hashes correctly" do
+ h = Rack::Utils::HeaderHash.new("Foo-Bar" => "baz")
+ j = {"foo" => "bar"}
+ h.replace(j)
+ h["foo"].should.equal "bar"
+ end
+
specify "should be able to delete the given key case-sensitively" do
h = Rack::Utils::HeaderHash.new("foo" => "bar")
h.delete("foo")
h["foo"].should.be.nil
h["FOO"].should.be.nil
end
-
+
specify "should be able to delete the given key case-insensitively" do
h = Rack::Utils::HeaderHash.new("foo" => "bar")
h.delete("FOO")
h["foo"].should.be.nil
h["FOO"].should.be.nil
end
-
+
specify "should return the deleted value when #delete is called on an existing key" do
h = Rack::Utils::HeaderHash.new("foo" => "bar")
h.delete("Foo").should.equal("bar")
end
-
+
specify "should return nil when #delete is called on a non-existant key" do
h = Rack::Utils::HeaderHash.new("foo" => "bar")
h.delete("Hello").should.be.nil
end
+
+ specify "should avoid unnecessary object creation if possible" do
+ a = Rack::Utils::HeaderHash.new("foo" => "bar")
+ b = Rack::Utils::HeaderHash.new(a)
+ b.object_id.should.equal(a.object_id)
+ b.should.equal(a)
+ end
+
+ specify "should convert Array values to Strings when responding to #each" do
+ h = Rack::Utils::HeaderHash.new("foo" => ["bar", "baz"])
+ h.each do |k,v|
+ k.should.equal("foo")
+ v.should.equal("bar\nbaz")
+ end
+ end
+
end
context "Rack::Utils::Context" do
@@ -372,9 +459,83 @@ context "Rack::Utils::Multipart" do
input.read.length.should.equal 197
end
+ specify "builds multipart body" do
+ files = Rack::Utils::Multipart::UploadedFile.new(multipart_file("file1.txt"))
+ data = Rack::Utils::Multipart.build_multipart("submit-name" => "Larry", "files" => files)
+
+ options = {
+ "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
+ "CONTENT_LENGTH" => data.length.to_s,
+ :input => StringIO.new(data)
+ }
+ env = Rack::MockRequest.env_for("/", options)
+ params = Rack::Utils::Multipart.parse_multipart(env)
+ params["submit-name"].should.equal "Larry"
+ params["files"][:filename].should.equal "file1.txt"
+ params["files"][:tempfile].read.should.equal "contents"
+ end
+
+ specify "builds nested multipart body" do
+ files = Rack::Utils::Multipart::UploadedFile.new(multipart_file("file1.txt"))
+ data = Rack::Utils::Multipart.build_multipart("people" => [{"submit-name" => "Larry", "files" => files}])
+
+ options = {
+ "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
+ "CONTENT_LENGTH" => data.length.to_s,
+ :input => StringIO.new(data)
+ }
+ env = Rack::MockRequest.env_for("/", options)
+ params = Rack::Utils::Multipart.parse_multipart(env)
+ params["people"][0]["submit-name"].should.equal "Larry"
+ params["people"][0]["files"][:filename].should.equal "file1.txt"
+ params["people"][0]["files"][:tempfile].read.should.equal "contents"
+ end
+
+ specify "can parse fields that end at the end of the buffer" do
+ input = File.read(multipart_file("bad_robots"))
+
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
+ "CONTENT_TYPE" => "multipart/form-data, boundary=1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon",
+ "CONTENT_LENGTH" => input.size,
+ :input => input)
+
+ req.POST['file.path'].should.equal "/var/tmp/uploads/4/0001728414"
+ req.POST['addresses'].should.not.equal nil
+ end
+
+ specify "builds complete params with the chunk size of 16384 slicing exactly on boundary" do
+ data = File.open(multipart_file("fail_16384_nofile")) { |f| f.read }.gsub(/\n/, "\r\n")
+ options = {
+ "CONTENT_TYPE" => "multipart/form-data; boundary=----WebKitFormBoundaryWsY0GnpbI5U7ztzo",
+ "CONTENT_LENGTH" => data.length.to_s,
+ :input => StringIO.new(data)
+ }
+ env = Rack::MockRequest.env_for("/", options)
+ params = Rack::Utils::Multipart.parse_multipart(env)
+
+ params.should.not.equal nil
+ params.keys.should.include "AAAAAAAAAAAAAAAAAAA"
+ params["AAAAAAAAAAAAAAAAAAA"].keys.should.include "PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"
+ params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"].keys.should.include "new"
+ params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"].keys.should.include "-2"
+ params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"]["-2"].keys.should.include "ba_unit_id"
+ params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"]["-2"]["ba_unit_id"].should.equal "1017"
+ end
+
+ specify "should return nil if no UploadedFiles were used" do
+ data = Rack::Utils::Multipart.build_multipart("people" => [{"submit-name" => "Larry", "files" => "contents"}])
+ data.should.equal nil
+ end
+
+ specify "should raise ArgumentError if params is not a Hash" do
+ lambda { Rack::Utils::Multipart.build_multipart("foo=bar") }.
+ should.raise(ArgumentError).
+ message.should.equal "value must be a Hash"
+ end
+
private
def multipart_fixture(name)
- file = File.join(File.dirname(__FILE__), "multipart", name.to_s)
+ file = multipart_file(name)
data = File.open(file, 'rb') { |io| io.read }
type = "multipart/form-data; boundary=AaB03x"
@@ -384,4 +545,8 @@ context "Rack::Utils::Multipart" do
"CONTENT_LENGTH" => length.to_s,
:input => StringIO.new(data) }
end
+
+ def multipart_file(name)
+ File.join(File.dirname(__FILE__), "multipart", name.to_s)
+ end
end
diff --git a/vendor/plugins/rack/test/spec_rack_webrick.rb b/vendor/plugins/rack/test/spec_rack_webrick.rb
index 3e63ea63..599425c4 100644
--- a/vendor/plugins/rack/test/spec_rack_webrick.rb
+++ b/vendor/plugins/rack/test/spec_rack_webrick.rb
@@ -9,7 +9,7 @@ Thread.abort_on_exception = true
context "Rack::Handler::WEBrick" do
include TestRequest::Helpers
-
+
setup do
@server = WEBrick::HTTPServer.new(:Host => @host='0.0.0.0',
:Port => @port=9202,
@@ -39,7 +39,7 @@ context "Rack::Handler::WEBrick" do
specify "should have rack headers" do
GET("/test")
- response["rack.version"].should.equal [1,0]
+ response["rack.version"].should.equal [1,1]
response["rack.multithread"].should.be true
response["rack.multiprocess"].should.be false
response["rack.run_once"].should.be false
@@ -50,7 +50,7 @@ context "Rack::Handler::WEBrick" do
response["REQUEST_METHOD"].should.equal "GET"
response["SCRIPT_NAME"].should.equal "/test"
response["REQUEST_PATH"].should.equal "/"
- response["PATH_INFO"].should.be.nil
+ response["PATH_INFO"].should.be.equal ""
response["QUERY_STRING"].should.equal ""
response["test.postdata"].should.equal ""
@@ -60,7 +60,7 @@ context "Rack::Handler::WEBrick" do
response["REQUEST_PATH"].should.equal "/"
response["PATH_INFO"].should.equal "/foo"
response["QUERY_STRING"].should.equal "quux=1"
-
+
GET("/test/foo%25encoding?quux=1")
response["REQUEST_METHOD"].should.equal "GET"
response["SCRIPT_NAME"].should.equal "/test"
diff --git a/vendor/plugins/rack/test/spec_rackup.rb b/vendor/plugins/rack/test/spec_rackup.rb
new file mode 100644
index 00000000..d9926fda
--- /dev/null
+++ b/vendor/plugins/rack/test/spec_rackup.rb
@@ -0,0 +1,154 @@
+require 'test/spec'
+require 'testrequest'
+require 'rack/server'
+require 'open3'
+
+begin
+require "mongrel"
+
+context "rackup" do
+ include TestRequest::Helpers
+
+ def run_rackup(*args)
+ options = args.last.is_a?(Hash) ? args.pop : {}
+ flags = args.first
+ @host = options[:host] || "0.0.0.0"
+ @port = options[:port] || 9292
+
+ Dir.chdir("#{root}/test/rackup") do
+ @in, @rackup, @err = Open3.popen3("#{Gem.ruby} -S #{rackup} #{flags}")
+ end
+
+ return if options[:port] == false
+
+ # Wait until the server is available
+ begin
+ GET("/")
+ rescue
+ sleep 0.05
+ retry
+ end
+ end
+
+ def output
+ @rackup.read
+ end
+
+ after do
+ # This doesn't actually return a response, so we rescue
+ GET "/die" rescue nil
+
+ Dir["#{root}/**/*.pid"].each do |file|
+ File.delete(file)
+ end
+
+ File.delete("#{root}/log_output") if File.exist?("#{root}/log_output")
+ end
+
+ specify "rackup" do
+ run_rackup
+ response["PATH_INFO"].should.equal '/'
+ response["test.$DEBUG"].should.be false
+ response["test.$EVAL"].should.be nil
+ response["test.$VERBOSE"].should.be false
+ response["test.Ping"].should.be nil
+ response["SERVER_SOFTWARE"].should.not =~ /webrick/
+ end
+
+ specify "rackup --help" do
+ run_rackup "--help", :port => false
+ output.should.match /--port/
+ end
+
+ specify "rackup --port" do
+ run_rackup "--port 9000", :port => 9000
+ response["SERVER_PORT"].should.equal "9000"
+ end
+
+ specify "rackup --debug" do
+ run_rackup "--debug"
+ response["test.$DEBUG"].should.be true
+ end
+
+ specify "rackup --eval" do
+ run_rackup %{--eval "BUKKIT = 'BUKKIT'"}
+ response["test.$EVAL"].should.equal "BUKKIT"
+ end
+
+ specify "rackup --warn" do
+ run_rackup %{--warn}
+ response["test.$VERBOSE"].should.be true
+ end
+
+ specify "rackup --include" do
+ run_rackup %{--include /foo/bar}
+ response["test.$LOAD_PATH"].should.include "/foo/bar"
+ end
+
+ specify "rackup --require" do
+ run_rackup %{--require ping}
+ response["test.Ping"].should.equal "constant"
+ end
+
+ specify "rackup --server" do
+ run_rackup %{--server webrick}
+ response["SERVER_SOFTWARE"].should =~ /webrick/i
+ end
+
+ specify "rackup --host" do
+ run_rackup %{--host 127.0.0.1}, :host => "127.0.0.1"
+ response["REMOTE_ADDR"].should.equal "127.0.0.1"
+ end
+
+ specify "rackup --daemonize --pid" do
+ run_rackup %{--daemonize --pid testing.pid}
+ status.should.be 200
+ @rackup.should.be.eof?
+ Dir["#{root}/**/testing.pid"].should.not.be.empty?
+ end
+
+ specify "rackup --pid" do
+ run_rackup %{--pid testing.pid}
+ status.should.be 200
+ Dir["#{root}/**/testing.pid"].should.not.be.empty?
+ end
+
+ specify "rackup --version" do
+ run_rackup %{--version}, :port => false
+ output.should =~ /1.0/
+ end
+
+ specify "rackup --env development includes lint" do
+ run_rackup
+ GET("/broken_lint")
+ status.should.be 500
+ end
+
+ specify "rackup --env deployment does not include lint" do
+ run_rackup %{--env deployment}
+ GET("/broken_lint")
+ status.should.be 200
+ end
+
+ specify "rackup --env none does not include lint" do
+ run_rackup %{--env none}
+ GET("/broken_lint")
+ status.should.be 200
+ end
+
+ specify "rackup --env deployment does log" do
+ run_rackup %{--env deployment}
+ log = File.read(response["test.stderr"])
+ log.should.be.empty?
+ end
+
+ specify "rackup --env none does not log" do
+ run_rackup %{--env none}
+ GET("/")
+ log = File.read(response["test.stderr"])
+ log.should.be.empty?
+ end
+end
+rescue LoadError
+ $stderr.puts "Skipping rackup --server tests (mongrel is required). `gem install thin` and try again."
+end
\ No newline at end of file
diff --git a/vendor/plugins/rack/test/testrequest.rb b/vendor/plugins/rack/test/testrequest.rb
index 7b7190cb..0da2b126 100644
--- a/vendor/plugins/rack/test/testrequest.rb
+++ b/vendor/plugins/rack/test/testrequest.rb
@@ -13,6 +13,17 @@ class TestRequest
module Helpers
attr_reader :status, :response
+ ROOT = File.expand_path(File.dirname(__FILE__) + "/..")
+ ENV["RUBYOPT"] = "-I#{ROOT}/lib -rubygems"
+
+ def root
+ ROOT
+ end
+
+ def rackup
+ "#{ROOT}/bin/rackup"
+ end
+
def GET(path, header={})
Net::HTTP.start(@host, @port) { |http|
user = header.delete(:user)
@@ -22,7 +33,11 @@ class TestRequest
get.basic_auth user, passwd if user && passwd
http.request(get) { |response|
@status = response.code.to_i
- @response = YAML.load(response.body)
+ begin
+ @response = YAML.load(response.body)
+ rescue ArgumentError
+ @response = nil
+ end
}
}
end
diff --git a/vendor/rails/actionpack/lib/action_controller.rb b/vendor/rails/actionpack/lib/action_controller.rb
index dbf13ae0..c18303b0 100644
--- a/vendor/rails/actionpack/lib/action_controller.rb
+++ b/vendor/rails/actionpack/lib/action_controller.rb
@@ -32,7 +32,7 @@ rescue LoadError
end
begin
- gem 'rack', '~> 1.1.0'
+ gem 'rack', '~> 1.1.1'
require 'rack'
rescue Gem::LoadError
$:.unshift "#{File.dirname(__FILE__)}/../../../plugins/rack/lib"