From a0f2b1d95d3785de92ae271fd7ea23e91c0cadc6 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 27 Jan 2009 18:17:39 -0600 Subject: Reorganize ActionController folder structure --- actionpack/lib/action_controller/cgi/ext.rb | 15 +++ actionpack/lib/action_controller/cgi/ext/cookie.rb | 112 +++++++++++++++++++++ .../action_controller/cgi/ext/query_extension.rb | 22 ++++ .../lib/action_controller/cgi/ext/stdinput.rb | 24 +++++ actionpack/lib/action_controller/cgi/process.rb | 70 +++++++++++++ 5 files changed, 243 insertions(+) create mode 100644 actionpack/lib/action_controller/cgi/ext.rb create mode 100644 actionpack/lib/action_controller/cgi/ext/cookie.rb create mode 100644 actionpack/lib/action_controller/cgi/ext/query_extension.rb create mode 100644 actionpack/lib/action_controller/cgi/ext/stdinput.rb create mode 100644 actionpack/lib/action_controller/cgi/process.rb (limited to 'actionpack/lib/action_controller/cgi') diff --git a/actionpack/lib/action_controller/cgi/ext.rb b/actionpack/lib/action_controller/cgi/ext.rb new file mode 100644 index 0000000000..558748f4bd --- /dev/null +++ b/actionpack/lib/action_controller/cgi/ext.rb @@ -0,0 +1,15 @@ +require 'action_controller/cgi/ext/stdinput' +require 'action_controller/cgi/ext/query_extension' +require 'action_controller/cgi/ext/cookie' + +class CGI #:nodoc: + include ActionController::CgiExt::Stdinput + + class << self + alias :escapeHTML_fail_on_nil :escapeHTML + + def escapeHTML(string) + escapeHTML_fail_on_nil(string) unless string.nil? + end + end +end diff --git a/actionpack/lib/action_controller/cgi/ext/cookie.rb b/actionpack/lib/action_controller/cgi/ext/cookie.rb new file mode 100644 index 0000000000..9cd19bb12d --- /dev/null +++ b/actionpack/lib/action_controller/cgi/ext/cookie.rb @@ -0,0 +1,112 @@ +require 'delegate' + +CGI.module_eval { remove_const "Cookie" } + +# TODO: document how this differs from stdlib CGI::Cookie +class CGI #:nodoc: + class Cookie < DelegateClass(Array) + attr_accessor :name, :value, :path, :domain, :expires + attr_reader :secure, :http_only + + # Creates a new CGI::Cookie object. + # + # The contents of the cookie can be specified as a +name+ and one + # or more +value+ arguments. Alternatively, the contents can + # be specified as a single hash argument. The possible keywords of + # this hash are as follows: + # + # * :name - The name of the cookie. Required. + # * :value - The cookie's value or list of values. + # * :path - The path for which this cookie applies. Defaults to the + # base directory of the CGI script. + # * :domain - The domain for which this cookie applies. + # * :expires - The time at which this cookie expires, as a Time object. + # * :secure - Whether this cookie is a secure cookie or not (defaults to + # +false+). Secure cookies are only transmitted to HTTPS servers. + # * :http_only - Whether this cookie can be accessed by client side scripts (e.g. document.cookie) or only over HTTP. + # More details in http://msdn2.microsoft.com/en-us/library/system.web.httpcookie.httponly.aspx. Defaults to +false+. + # + # These keywords correspond to attributes of the cookie object. + def initialize(name = '', *value) + if name.kind_of?(String) + @name = name + @value = Array(value) + @domain = nil + @expires = nil + @secure = false + @http_only = false + @path = nil + else + @name = name['name'] + @value = (name['value'].kind_of?(String) ? [name['value']] : Array(name['value'])).delete_if(&:blank?) + @domain = name['domain'] + @expires = name['expires'] + @secure = name['secure'] || false + @http_only = name['http_only'] || false + @path = name['path'] + end + + raise ArgumentError, "`name' required" unless @name + + # simple support for IE + unless @path + %r|^(.*/)|.match(ENV['SCRIPT_NAME']) + @path = ($1 or '') + end + + super(@value) + end + + # Sets whether the Cookie is a secure cookie or not. + def secure=(val) + @secure = val == true + end + + # Sets whether the Cookie is an HTTP only cookie or not. + def http_only=(val) + @http_only = val == true + end + + # Converts the Cookie to its string representation. + def to_s + buf = '' + buf << @name << '=' + buf << (@value.kind_of?(String) ? CGI::escape(@value) : @value.collect{|v| CGI::escape(v) }.join("&")) + buf << '; domain=' << @domain if @domain + buf << '; path=' << @path if @path + buf << '; expires=' << CGI::rfc1123_date(@expires) if @expires + buf << '; secure' if @secure + buf << '; HttpOnly' if @http_only + buf + end + + # FIXME: work around broken 1.8.7 DelegateClass#respond_to? + def respond_to?(method, include_private = false) + return true if super(method) + return __getobj__.respond_to?(method, include_private) + end + + # Parses a raw cookie string into a hash of cookie-name => cookie-object + # pairs. + # + # cookies = CGI::Cookie::parse("raw_cookie_string") + # # => { "name1" => cookie1, "name2" => cookie2, ... } + # + def self.parse(raw_cookie) + cookies = Hash.new([]) + + if raw_cookie + raw_cookie.split(/;\s?/).each do |pairs| + name, value = pairs.split('=',2) + next unless name and value + name = CGI::unescape(name) + unless cookies.has_key?(name) + cookies[name] = new(name, CGI::unescape(value)) + end + end + end + + cookies + end + end # class Cookie +end diff --git a/actionpack/lib/action_controller/cgi/ext/query_extension.rb b/actionpack/lib/action_controller/cgi/ext/query_extension.rb new file mode 100644 index 0000000000..9620fd2873 --- /dev/null +++ b/actionpack/lib/action_controller/cgi/ext/query_extension.rb @@ -0,0 +1,22 @@ +require 'cgi' + +class CGI #:nodoc: + module QueryExtension + # Remove the old initialize_query method before redefining it. + remove_method :initialize_query + + # Neuter CGI parameter parsing. + def initialize_query + # Fix some strange request environments. + env_table['REQUEST_METHOD'] ||= 'GET' + + # POST assumes missing Content-Type is application/x-www-form-urlencoded. + if env_table['CONTENT_TYPE'].blank? && env_table['REQUEST_METHOD'] == 'POST' + env_table['CONTENT_TYPE'] = 'application/x-www-form-urlencoded' + end + + @cookies = CGI::Cookie::parse(env_table['HTTP_COOKIE'] || env_table['COOKIE']) + @params = {} + end + end +end diff --git a/actionpack/lib/action_controller/cgi/ext/stdinput.rb b/actionpack/lib/action_controller/cgi/ext/stdinput.rb new file mode 100644 index 0000000000..5e9b6784af --- /dev/null +++ b/actionpack/lib/action_controller/cgi/ext/stdinput.rb @@ -0,0 +1,24 @@ +require 'cgi' + +module ActionController + module CgiExt + # Publicize the CGI's internal input stream so we can lazy-read + # request.body. Make it writable so we don't have to play $stdin games. + module Stdinput + def self.included(base) + base.class_eval do + remove_method :stdinput + attr_accessor :stdinput + end + + base.alias_method_chain :initialize, :stdinput + end + + def initialize_with_stdinput(type = nil, stdinput = $stdin) + @stdinput = stdinput + @stdinput.set_encoding(Encoding::BINARY) if @stdinput.respond_to?(:set_encoding) + initialize_without_stdinput(type || 'query') + end + end + end +end diff --git a/actionpack/lib/action_controller/cgi/process.rb b/actionpack/lib/action_controller/cgi/process.rb new file mode 100644 index 0000000000..ffcad5666a --- /dev/null +++ b/actionpack/lib/action_controller/cgi/process.rb @@ -0,0 +1,70 @@ +module ActionController #:nodoc: + class CGIHandler + module ProperStream + def each + while line = gets + yield line + end + end + + def read(*args) + if args.empty? + super || "" + else + super + end + end + end + + def self.dispatch_cgi(app, cgi, out = $stdout) + env = cgi.__send__(:env_table) + env.delete "HTTP_CONTENT_LENGTH" + + cgi.stdinput.extend ProperStream + + env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" + + env.update({ + "rack.version" => [0,1], + "rack.input" => cgi.stdinput, + "rack.errors" => $stderr, + "rack.multithread" => false, + "rack.multiprocess" => true, + "rack.run_once" => false, + "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http" + }) + + env["QUERY_STRING"] ||= "" + env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] + env["REQUEST_PATH"] ||= "/" + env.delete "PATH_INFO" if env["PATH_INFO"] == "" + + status, headers, body = app.call(env) + begin + out.binmode if out.respond_to?(:binmode) + out.sync = false if out.respond_to?(:sync=) + + headers['Status'] = status.to_s + out.write(cgi.header(headers)) + + body.each { |part| + out.write part + out.flush if out.respond_to?(:flush) + } + ensure + body.close if body.respond_to?(:close) + end + end + end + + class CgiRequest #:nodoc: + DEFAULT_SESSION_OPTIONS = { + :database_manager => nil, + :prefix => "ruby_sess.", + :session_path => "/", + :session_key => "_session_id", + :cookie_only => true, + :session_http_only => true + } + end +end -- cgit v1.2.3