1
0
Fork 0

Fixed bug relating to newlines in hidden input fields

This patch fixes an issue whereby a newline character appearing within
a hidden input field is incorrectly reinterpreted as a space character.
The patch handles almost all cases, and includes a test case.
15/18 tests pass, but the remainder currently fail due to the fact
that ELinks does not currently support textarea scripting.
This commit is contained in:
Peter Collingbourne 2008-11-03 21:56:49 +00:00 committed by Kalle Olavi Niemitalo
parent c56f3928ec
commit 658b9cc70f
9 changed files with 170 additions and 15 deletions

View File

@ -449,6 +449,9 @@ Pavol Babincak <scroolik@gmail.com>
Peder Stray <peder@ifi.uio.no>
Fix handling of key presses turning up as key prefixes
Peter Collingbourne <peter@peter.uk.to>
Fixed bug relating to newlines in hidden input fields
Peter Gervai <grin@tolna.net>
Manpage updates
Mailcap to links.cfg convertor

View File

@ -287,7 +287,9 @@ html_input(struct html_context *html_context, unsigned char *a,
mem_free(al);
}
if (fc->type != FC_FILE)
if (fc->type == FC_HIDDEN)
fc->default_value = get_lit_attr_val(a, "value", cp);
else if (fc->type != FC_FILE)
fc->default_value = get_attr_val(a, "value", cp);
if (!fc->default_value) {
if (fc->type == FC_CHECKBOX)

View File

@ -177,9 +177,11 @@ next_attr:
/* parse_quoted_value: */
while (*(++e) != quote) {
if (*e == ASCII_CR) continue;
if (!*e) goto parse_error;
if (*e != ASCII_TAB && *e != ASCII_LF)
if (flags & HTML_ATTR_LITERAL_NL)
add_chr(attr, attrlen, *e);
else if (*e == ASCII_CR) continue;
else if (*e != ASCII_TAB && *e != ASCII_LF)
add_chr(attr, attrlen, *e);
else if (!(flags & HTML_ATTR_EAT_NL))
add_chr(attr, attrlen, ' ');

View File

@ -25,6 +25,10 @@ enum html_attr_flags {
/* If HTML_ATTR_NO_CONV is set, then convert_string() is not called
* on value. Unused for now. */
/* HTML_ATTR_NO_CONV = 4, */
/* If HTML_ATTR_LITERAL_NL is set, carriage return, newline and tab
* characters are returned literally. */
HTML_ATTR_LITERAL_NL = 8,
};
/* Parses html element attributes.
@ -37,6 +41,7 @@ unsigned char *get_attr_value(register unsigned char *e, unsigned char *name, in
/* Wrappers for get_attr_value(). */
#define get_attr_val(e, name, cp) get_attr_value(e, name, cp, HTML_ATTR_NONE)
#define get_lit_attr_val(e, name, cp) get_attr_value(e, name, cp, HTML_ATTR_LITERAL_NL)
#define get_url_val(e, name, cp) get_attr_value(e, name, cp, HTML_ATTR_EAT_NL)
#define has_attr(e, name, cp) (!!get_attr_value(e, name, cp, HTML_ATTR_TEST))

View File

@ -795,6 +795,30 @@ get_successful_controls(struct document_view *doc_view,
sort_submitted_values(list);
}
unsigned char *
encode_crlf(struct submitted_value *sv)
{
struct string newtext;
int i;
assert(sv && sv->value);
if_assert_failed return NULL;
if (!init_string(&newtext)) return NULL;
for (i = 0; sv->value[i]; i++) {
if (sv->value[i] == '\r') {
if (sv->value[i+1] != '\n')
add_crlf_to_string(&newtext);
} else if (sv->value[i] == '\n')
add_crlf_to_string(&newtext);
else
add_char_to_string(&newtext, sv->value[i]);
}
return newtext.source;
}
static void
encode_controls(LIST_OF(struct submitted_value) *l, struct string *data,
int cp_from, int cp_to)
@ -838,6 +862,8 @@ encode_controls(LIST_OF(struct submitted_value) *l, struct string *data,
p2 = convert_string(convert_table, sv->value,
strlen(sv->value), -1, CSM_FORM, NULL, NULL, NULL);
} else if (sv->type == FC_HIDDEN) {
p2 = encode_crlf(sv);
} else {
p2 = stracpy(sv->value);
}
@ -1134,6 +1160,10 @@ encode_text_plain(LIST_OF(struct submitted_value) *l, struct string *data,
value = area51 = encode_textarea(sv);
if (!area51) break;
/* Fall through */
case FC_HIDDEN:
if (!area51) value = area51 = encode_crlf(sv);
if (!area51) break;
/* Fall through */
case FC_TEXT:
case FC_PASSWORD:
/* Convert back to original encoding (see

View File

@ -99,6 +99,7 @@ struct submitted_value {
struct submitted_value *init_submitted_value(unsigned char *name, unsigned char *value, enum form_type type, struct form_control *fc, int position);
void done_submitted_value(struct submitted_value *sv);
void done_submitted_value_list(LIST_OF(struct submitted_value) *list);
unsigned char *encode_crlf(struct submitted_value *sv);
struct uri *get_form_uri(struct session *ses, struct document_view *doc_view, struct form_control *fc);

View File

@ -490,9 +490,7 @@ unsigned char *
encode_textarea(struct submitted_value *sv)
{
struct form_control *fc;
struct string newtext;
void *blabla;
int i;
assert(sv && sv->value);
if_assert_failed return NULL;
@ -505,16 +503,7 @@ encode_textarea(struct submitted_value *sv)
blabla = format_text(sv->value, fc->cols, fc->wrap, 1);
mem_free_if(blabla);
if (!init_string(&newtext)) return NULL;
for (i = 0; sv->value[i]; i++) {
if (sv->value[i] != '\n')
add_char_to_string(&newtext, sv->value[i]);
else
add_crlf_to_string(&newtext);
}
return newtext.source;
return encode_crlf(sv);
}

2
test/server/crlf.conf Normal file
View File

@ -0,0 +1,2 @@
set document.browse.forms.confirm_submit = 0
set ecmascript.enable = 1

121
test/server/crlf.py Executable file
View File

@ -0,0 +1,121 @@
#!/usr/bin/env python
import os
from BaseHTTPServer import *
import tempfile
import signal
r, w = os.pipe()
C_CR = 0
C_LF = 1
C_CRLF = 2
E_Raw = 0
E_Entity = 1
E_JavaScript = 2
F_Hidden = 0
F_TextArea = 1
def encode(ch, encoding):
if ch == C_CRLF:
return encode(C_CR, encoding) + encode(C_LF, encoding)
if ch == C_CR:
if encoding == E_Raw:
return "\r"
if encoding == E_JavaScript:
return "\\r"
if encoding == E_Entity:
return "&#013;"
if ch == C_LF:
if encoding == E_Raw:
return "\n"
if encoding == E_JavaScript:
return "\\n"
if encoding == E_Entity:
return "&#010;"
def get_form(ch, encoding, field):
text = "foo" + encode(ch, encoding) + "bar"
if encoding == E_JavaScript:
text_initial = ""
else:
text_initial = text
s = """<html>
<head>
<title>Form Test</title>
</head>
<body>
<form id="form1" name="form1" action="http://127.0.0.1:8090/">
"""
if field == F_Hidden:
s += '<input type="hidden" id="field1" name="field1" value="' + text_initial + '">'
elif field == F_TextArea:
s += '<textarea id="field1" name="field1">' + text_initial + '</textarea>'
s += "\n</form>"
if encoding == E_JavaScript:
s += """
<script>
document.form1.field1.value = '%s';
</script>""" % (text)
s += "</body></html>"
return s
class forwarder(BaseHTTPRequestHandler):
def do_GET(self):
w.write(self.path + "\n")
w.flush()
self.send_response(200)
self.send_header("Content-Type", "text/plain")
self.end_headers()
self.wfile.write("Dummy response")
def runtest(r, *args):
form = get_form(*args)
tmpfile, tmpname = tempfile.mkstemp(".html")
tmpfile = os.fdopen(tmpfile, 'w')
tmpfile.write(form)
tmpfile.close()
linkspid = os.spawnlp(os.P_NOWAIT, 'elinks', 'elinks',
'-config-dir', os.getcwd(),
'-config-file', 'crlf.conf',
'-no-connect', '1',
'-auto-submit', '1',
tmpname)
path = r.readline()
os.kill(linkspid, signal.SIGINT)
os.waitpid(linkspid, 0)
os.unlink(tmpname)
return path
pid = os.fork()
if pid:
os.close(w)
r = os.fdopen(r)
paths = []
for c in [C_CR, C_LF, C_CRLF]:
for e in [E_Raw, E_Entity, E_JavaScript]:
for f in [F_Hidden, F_TextArea]:
paths.append(("%d %d %d " % (c, e, f)) + runtest(r, c, e, f))
for path in paths:
print path,
os.kill(pid, signal.SIGTERM)
os.waitpid(pid, 0)
else:
os.close(r)
w = os.fdopen(w, 'w')
server_address = ('127.0.0.1', 8090)
httpd = HTTPServer(server_address, forwarder)
httpd.serve_forever()