Skip to content

Commit

Permalink
dealing with incorrect encoding strings
Browse files Browse the repository at this point in the history
  • Loading branch information
tenderlove committed Jun 23, 2009
1 parent aa81122 commit aba71da
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 24 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

=== HEAD

* Bug Fixes:

* Rescue errors from bogus encodings

=== 0.9.3

* Bug Fixes:

* Do not apply encoding if encoding equals 'none' Thanks Akinori MUSHA!
Expand Down
48 changes: 24 additions & 24 deletions lib/www/mechanize/form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ class Mechanize
# puts form['name']
class Form
attr_accessor :method, :action, :name

attr_reader :fields, :buttons, :file_uploads, :radiobuttons, :checkboxes
attr_accessor :enctype

alias :elements :fields

attr_reader :form_node
attr_reader :page

def initialize(node, mech=nil, page=nil)
@enctype = node['enctype'] || 'application/x-www-form-urlencoded'
@form_node = node
Expand Down Expand Up @@ -137,10 +137,10 @@ def click_button(button = buttons.first)
end

# This method is sub-method of build_query.
# It converts charset of query value of fields into excepted one.
# It converts charset of query value of fields into expected one.
def proc_query(field)
return unless field.query_value
field.query_value.map{|(name, val)|
field.query_value.map{|(name, val)|
[from_native_charset(name), from_native_charset(val.to_s)]
}
end
Expand All @@ -149,7 +149,7 @@ def proc_query(field)
def from_native_charset(str, enc=nil)
if page
enc ||= page.encoding
Util.from_native_charset(str,enc)
Util.from_native_charset(str,enc) rescue str
else
str
end
Expand All @@ -161,36 +161,36 @@ def from_native_charset(str, enc=nil)
# be used to create a query string for this form.
def build_query(buttons = [])
query = []

fields().each do |f|
qval = proc_query(f)
query.push(*qval)
end

checkboxes().each do |f|
if f.checked
qval = proc_query(f)
query.push(*qval)
end
end

radio_groups = {}
radiobuttons().each do |f|
fname = from_native_charset(f.name)
radio_groups[fname] ||= []
radio_groups[fname] << f
radio_groups[fname] << f
end

# take one radio button from each group
radio_groups.each_value do |g|
checked = g.select {|f| f.checked}

if checked.size == 1
f = checked.first
qval = proc_query(f)
query.push(*qval)
elsif checked.size > 1
raise "multiple radiobuttons are checked in the same group!"
elsif checked.size > 1
raise "multiple radiobuttons are checked in the same group!"
end
end

Expand All @@ -206,7 +206,7 @@ def build_query(buttons = [])
def add_button_to_query(button)
@clicked_buttons << button
end

# This method calculates the request data to be sent back to the server
# for this form, depending on if this is a regular post, get, or a
# multi-part post,
Expand All @@ -225,8 +225,8 @@ def request_data
WWW::Mechanize::Util.build_query_string(query_params)
end
end
# Removes all fields with name +field_name+.

# Removes all fields with name +field_name+.
def delete_field!(field_name)
@fields.delete_if{ |f| f.name == field_name}
end
Expand Down Expand Up @@ -255,15 +255,15 @@ def #{singular}_with criteria = {}
alias :#{singular} :#{singular}_with
eomethod
end

private
def parse
@fields = []
@buttons = []
@file_uploads = []
@radiobuttons = []
@checkboxes = []

# Find all input tags
form_node.search('input').each do |node|
type = (node['type'] || 'text').downcase
Expand All @@ -275,15 +275,15 @@ def parse
when 'checkbox'
@checkboxes << CheckBox.new(node['name'], node['value'], !!node['checked'], self)
when 'file'
@file_uploads << FileUpload.new(node['name'], nil)
@file_uploads << FileUpload.new(node['name'], nil)
when 'submit'
@buttons << Button.new(node['name'], node['value'])
when 'button'
@buttons << Button.new(node['name'], node['value'])
when 'image'
@buttons << ImageButton.new(node['name'], node['value'])
else
@fields << Field.new(node['name'], node['value'] || '')
@fields << Field.new(node['name'], node['value'] || '')
end
end

Expand Down Expand Up @@ -318,7 +318,7 @@ def rand_string(len = 10)
1.upto(len) { |i| string << chars[rand(chars.size-1)] }
string
end

def mime_value_quote(str)
str.gsub(/(["\r\\])/){|s| '\\' + s}
end
Expand All @@ -328,7 +328,7 @@ def param_to_multipart(name, value)
"#{mime_value_quote(name)}\"\r\n" +
"\r\n#{value}\r\n"
end

def file_to_multipart(file)
file_name = file.file_name ? ::File.basename(file.file_name) : ''
body = "Content-Disposition: form-data; name=\"" +
Expand All @@ -345,7 +345,7 @@ def file_to_multipart(file)
if file.mime_type != nil
body << "Content-Type: #{file.mime_type}\r\n"
end

body <<
if file.file_data.respond_to? :read
"\r\n#{file.file_data.read}\r\n"
Expand Down
52 changes: 52 additions & 0 deletions test/htdocs/test_bad_encoding.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8; charset=utf-8"/>
<title>Page Title</title>
</head>
<body>
<h1>Post Form 1</h1>
<form name="post_form1" method="post" action="/form_post?a=b&amp;b=c">
<table>
<tr>
<td>First Name</td>
<td><input type="text" name="first_name" /></td>
</tr>
</table><br />
<input type="submit" value="Submit" />
</form>

<h1>Post Form 2</h1>
<form name="post_form2" method="get" action="/form_post?a=b&amp;b=c">
<table>
<tr>
<td>First Name</td>
<td><input type="text" name="first_name" /></td>
</tr>
</table><br />
<input type="submit" value="Submit" />
</form>

<h1>Post Form 3</h1>
<form name="post_form3" method="post" action="/form_post?a=b&b=c">
<table>
<tr>
<td>First Name</td>
<td><input type="text" name="first_name" /></td>
</tr>
</table><br />
<input type="submit" value="Submit" />
</form>

<h1>Post Form 4</h1>
<form name="post_form4" method="post" action="/form_post#1">
<table>
<tr>
<td>First Name</td>
<td><input type="text" name="first_name" /></td>
</tr>
</table><br />
<input type="submit" value="Submit" />
</form>
</body>
</html>

8 changes: 8 additions & 0 deletions test/test_form_action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ def setup
@page = @agent.get("http://localhost/tc_form_action.html")
end

def test_post_with_bad_encoding_does_not_raise_exception
@page = @agent.get("http://localhost/test_bad_encoding.html")
form = @page.form(:name => 'post_form1') { |f|
f.first_name = "Aaron"
}
form.submit
end

def test_post_encoded_action
form = @page.form(:name => 'post_form1') { |f|
f.first_name = "Aaron"
Expand Down

0 comments on commit aba71da

Please sign in to comment.