lib/tap/mechanize/capture.rb in tap-mechanize-0.5.1 vs lib/tap/mechanize/capture.rb in tap-mechanize-0.6.0

- old
+ new

@@ -1,71 +1,72 @@ require 'tap/controller' require 'tap/mechanize/utils' require 'tap/ubiquity/utils' +require 'uri' module Tap module Mechanize # :startdoc::controller # :startdoc::ubiquity class Capture < Tap::Controller include Tap::Mechanize::Utils include Tap::Ubiquity::Utils PREFIX = '__redirect_http_' - REDIRECT_PARAMETER = '__redirect_http_original_action' # Brings up the tutorial. def index - render 'index.erb', :locals => {:captures => persistence.index } + render 'index.erb', :locals => {:captures => data.index(:data) } end - def create(id, keep_content=true) - persistence.create(id) do |io| - io << YAML.dump([parse_request(keep_content)]) + def create(id) + data.create(:data, id) do |io| + io << YAML.dump([parse_request]) end download(id) end def show(id) response['Content-Type'] = "text/plain" - persistence.read(id) + data.read(:data, id) end def download(id) - path = persistence.path(id) + path = data.path(:data, id) filename = id filename += ".yml" if File.extname(id) == "" response['Content-Type'] = "text/plain" response['Content-Disposition'] = "attachment; filename=#{filename};" - persistence.read(id) + data.read(:data, id) end - def update(id="request", keep_content=true) - path = persistence.path(id) + def update(id="request") + path = data.path(:data, id) requests = File.exists?(path) ? YAML.load_file(path) : [] - requests << parse_request(keep_content) + requests << parse_request - persistence.update(id) do |io| + data.create_or_update(:data, id) do |io| io << YAML.dump(requests) end download(id) end def destroy(id) - persistence.destroy(id) + data.destroy(:data, id) redirect uri(:index) end # Brings up a tutorial teaching how to capture and resubmit forms. def tutorial - serve js_injection(:redirect_http) do |link| - content = render 'tutorial.erb' - content + link - end + render 'tutorial.erb' end + def command + serve js_injection(:redirect_http) + end + def test render 'test.erb' end # Say is the target of the tutorial. @@ -73,19 +74,30 @@ "<pre>#{request.params['words']}</pre>" end # Returns the redirection script. def redirect_http + + # note configs are formatted into the javascript; keys MUST be valid + # names, but values can be anything that converts to json + configs = [ + [:submit_request, false], + [:keep_content, false], + [:keep_headers, false], + [:name, 'request'] + ] + css = render 'redirect.css' script = render 'redirect.js', :locals => { - :redirect_parameter => REDIRECT_PARAMETER, :redirect_action => uri(:update), + :configs => configs } content = render 'redirect_http.erb', :locals => { :css => css, - :script => script + :script => script, + :configs => configs } if request.get? response['Content-Type'] = 'text/plain' %Q{ @@ -135,38 +147,85 @@ # :locals => {:prefix => PREFIX} def prefix # :nodoc: PREFIX end - def capture_overloaded_parameters # :nodoc: - # perform the actions of Rack::Request::POST, but capture - # overloaded parameter names + def data + server.data + end + + def uri(*args) + "http://#{server.host}:#{server.port}#{super}" + end + + # Returns the data recieved in the query string. + def get_params env = request.env - env["rack.request.form_input"] = env["rack.input"] - unless env["rack.request.form_hash"] = parse_multipart(env) - env["rack.request.form_vars"] = env["rack.input"].read - env["rack.request.form_hash"] = Rack::Utils.parse_query(env["rack.request.form_vars"]) - env["rack.input"].rewind if env["rack.input"].respond_to?(:rewind) + if env["rack.request.query_string"] == request.query_string + env["rack.request.query_hash"] + else + env["rack.request.query_string"] = request.query_string + env["rack.request.query_hash"] = + parse_query(request.query_string) end end + # Returns the data recieved in the request body. + # + # This method support both application/x-www-form-urlencoded and + # multipart/form-data. + def post_params + env = request.env + if env["rack.request.form_input"].eql? env["rack.input"] + env["rack.request.form_hash"] + elsif request.form_data? + env["rack.request.form_input"] = env["rack.input"] + unless env["rack.request.form_hash"] = + Rack::Utils::Multipart.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"] = parse_query(form_vars) + + begin + env["rack.input"].rewind if env["rack.input"].respond_to?(:rewind) + rescue Errno::ESPIPE + # Handles exceptions raised by input streams that cannot be rewound + # such as when using plain CGI under Apache + end + end + env["rack.request.form_hash"] + else + {} + end + end + + def capture_parameters # :nodoc: + get_params.update(post_params) + end + # helper to parse the request into a request hash for # use by a Tap::Mechanize::Submit task - def parse_request(keep_content=true) # :nodoc: - if keep_content.kind_of?(String) - keep_content = keep_content =~ /true/i + def parse_request + params = capture_parameters + capture_params = {} + params.each_key do |key| + if key =~ /#{prefix}/ + normalize_params(capture_params, key, params.delete(key)) + end end + capture_params = capture_params[prefix] - capture_overloaded_parameters - hash = {} - parse_rack_request(request, keep_content).each_pair do |key, value| + parse_rack_request(request, params, capture_params['keep_content'] == "true").each_pair do |key, value| hash[key.to_s] = value end - action = hash['params'].delete(REDIRECT_PARAMETER) - + action = capture_params['original_action'] hash['uri'] = case action when /^http/ # action is an href already action when /^\// @@ -180,11 +239,13 @@ # make action relative to Referer base = File.dirname(hash['headers']['Referer'].to_s) File.join(base, action) end - # remove extranous data - hash.delete('headers') + # remove extra data + unless capture_params['keep_headers'] == 'true' + hash.delete('headers') + end hash.delete('version') hash end \ No newline at end of file