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. --- AUTHORS | 1 + src/document/html/parser/forms.c | 4 +- src/document/html/parser/parse.c | 6 +- src/document/html/parser/parse.h | 5 ++ src/viewer/text/form.c | 30 +++++++++ src/viewer/text/form.h | 1 + src/viewer/text/textarea.c | 13 +---- test/server/crlf.conf | 2 + test/server/crlf.py | 121 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 168 insertions(+), 15 deletions(-) create mode 100644 test/server/crlf.conf create mode 100755 test/server/crlf.py
diff --git a/AUTHORS b/AUTHORS
index 866f0d7..18e8641 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -457,6 +457,7 @@ Peder Stray <[EMAIL PROTECTED]>
Fix handling of key presses turning up as key prefixes
Peter Collingbourne <[EMAIL PROTECTED]>
+ Fixed bug relating to newlines in hidden input fields
Fixed compiler errors and warnings in src/util/random.c where
CONFIG_SSL undefined
Peter Gervai <[EMAIL PROTECTED]>
diff --git a/src/document/html/parser/forms.c b/src/document/html/parser/forms.c
index c34459a..5f9dc47 100644
--- a/src/document/html/parser/forms.c
+++ b/src/document/html/parser/forms.c
@@ -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)
diff --git a/src/document/html/parser/parse.c b/src/document/html/parser/parse.c
index 128485e..399c4e6 100644
--- a/src/document/html/parser/parse.c
+++ b/src/document/html/parser/parse.c
@@ -179,9 +179,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, ' ');
diff --git a/src/document/html/parser/parse.h b/src/document/html/parser/parse.h
index 4eaa154..9498e43 100644
--- a/src/document/html/parser/parse.h
+++ b/src/document/html/parser/parse.h
@@ -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))
diff --git a/src/viewer/text/form.c b/src/viewer/text/form.c
index f2b7b9d..e64ae88 100644
--- a/src/viewer/text/form.c
+++ b/src/viewer/text/form.c
@@ -807,6 +807,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)
@@ -850,6 +874,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);
}
@@ -1120,6 +1146,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
diff --git a/src/viewer/text/form.h b/src/viewer/text/form.h
index 74a9991..79757ba 100644
--- a/src/viewer/text/form.h
+++ b/src/viewer/text/form.h
@@ -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);
diff --git a/src/viewer/text/textarea.c b/src/viewer/text/textarea.c
index 60a0c60..7749f7b 100644
--- a/src/viewer/text/textarea.c
+++ b/src/viewer/text/textarea.c
@@ -488,9 +488,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;
@@ -503,16 +501,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);
}
diff --git a/test/server/crlf.conf b/test/server/crlf.conf
new file mode 100644
index 0000000..33d61a2
--- /dev/null
+++ b/test/server/crlf.conf
@@ -0,0 +1,2 @@
+set document.browse.forms.confirm_submit = 0
+set ecmascript.enable = 1
diff --git a/test/server/crlf.py b/test/server/crlf.py
new file mode 100755
index 0000000..84b49fd
--- /dev/null
+++ b/test/server/crlf.py
@@ -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 "
"
+ if ch == C_LF:
+ if encoding == E_Raw:
+ return "\n"
+ if encoding == E_JavaScript:
+ return "\\n"
+ if encoding == E_Entity:
+ return "
"
+
+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()
--
1.5.6.5
--
Peter
signature.asc
Description: Digital signature
_______________________________________________ elinks-dev mailing list [email protected] http://linuxfromscratch.org/mailman/listinfo/elinks-dev
