diff options
author | Adam Hodgen <ant1441@gmail.com> | 2022-02-17 23:05:46 +0000 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-02-18 01:48:51 +0100 |
commit | aa70422b4d076b07d2f0b0587ddd7d9ca692b24a (patch) | |
tree | 96dfdacbbee80dd4a1fb841d4e90857d4cdf3e32 | |
parent | 240068a48ccd136c0c54203e1a1b471309d4b5fc (diff) | |
download | serenity-aa70422b4d076b07d2f0b0587ddd7d9ca692b24a.zip |
LibWeb: Add <input> value sanitiztion algorithm
The value sanitiztion algorithm is defined for some states of the type
attribute, and sanitizes the value of the 'value' attribute
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp | 61 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/HTMLInputElement.h | 56 |
2 files changed, 90 insertions, 27 deletions
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 5f47009218..7a188cf903 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -152,11 +152,13 @@ String HTMLInputElement::value() const void HTMLInputElement::set_value(String value) { + auto sanitised_value = value_sanitization_algorithm(move(value)); + if (m_text_node) { - m_text_node->set_data(move(value)); + m_text_node->set_data(sanitised_value); return; } - set_attribute(HTML::AttributeNames::value, move(value)); + set_attribute(HTML::AttributeNames::value, sanitised_value); } void HTMLInputElement::create_shadow_tree_if_needed() @@ -232,8 +234,8 @@ String HTMLInputElement::type() const { auto value = attribute(HTML::AttributeNames::type); -#define __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(keyword) \ - if (value.equals_ignoring_case(#keyword)) \ +#define __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(keyword, _) \ + if (value.equals_ignoring_case(#keyword)) \ return #keyword; ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTES #undef __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE @@ -244,9 +246,60 @@ String HTMLInputElement::type() const return "text"; } +HTMLInputElement::TypeAttributeState HTMLInputElement::type_state() const +{ + auto value = attribute(HTML::AttributeNames::type); + +#define __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(keyword, state) \ + if (value.equals_ignoring_case(#keyword)) \ + return HTMLInputElement::TypeAttributeState::state; + ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTES +#undef __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE + + // The missing value default and the invalid value default are the Text state. + // https://html.spec.whatwg.org/multipage/input.html#the-input-element:missing-value-default + // https://html.spec.whatwg.org/multipage/input.html#the-input-element:invalid-value-default + return HTMLInputElement::TypeAttributeState::Text; +} + void HTMLInputElement::set_type(String const& type) { set_attribute(HTML::AttributeNames::type, type); } +// https://html.spec.whatwg.org/multipage/input.html#value-sanitization-algorithm +String HTMLInputElement::value_sanitization_algorithm(String value) const +{ + if (type_state() == HTMLInputElement::TypeAttributeState::Text || type_state() == HTMLInputElement::TypeAttributeState::Search || type_state() == HTMLInputElement::TypeAttributeState::Telephone || type_state() == HTMLInputElement::TypeAttributeState::Password) { + // Strip newlines from the value. + if (value.contains('\r') || value.contains('\n')) { + StringBuilder builder; + for (auto c : value) { + if (!(c == '\r' || c == '\n')) + builder.append(c); + } + return builder.to_string(); + } + } else if (type_state() == HTMLInputElement::TypeAttributeState::URL) { + // Strip newlines from the value, then strip leading and trailing ASCII whitespace from the value. + if (value.contains('\r') || value.contains('\n')) { + StringBuilder builder; + for (auto c : value) { + if (!(c == '\r' || c == '\n')) + builder.append(c); + } + return builder.to_string().trim_whitespace(); + } + } else if (type_state() == HTMLInputElement::TypeAttributeState::Number) { + // If the value of the element is not a valid floating-point number, then set it to the empty string instead. + char* end_ptr; + auto val = strtod(value.characters(), &end_ptr); + if (!isfinite(val) || *end_ptr) + return ""; + } + + // FIXME: Implement remaining value sanitation algorithms + return value; +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h index 9b8b2be17c..043877cb9d 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h @@ -13,29 +13,29 @@ namespace Web::HTML { // https://html.spec.whatwg.org/multipage/input.html#attr-input-type -#define ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTES \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(hidden) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(text) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(search) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(tel) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(url) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(email) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(password) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(date) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(month) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(week) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(time) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE("datetime-local") \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(number) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(range) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(color) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(checkbox) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(radio) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(file) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(submit) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(image) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(reset) \ - __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(button) +#define ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTES \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(hidden, Hidden) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(text, Text) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(search, Search) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(tel, Telephone) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(url, URL) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(email, Email) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(password, Password) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(date, Date) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(month, Month) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(week, Week) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(time, Time) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE("datetime-local", LocalDateAndTime) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(number, Number) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(range, Range) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(color, Color) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(checkbox, Checkbox) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(radio, RadioButton) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(file, FileUpload) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(submit, SubmitButton) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(image, ImageButton) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(reset, ResetButton) \ + __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(button, Button) class HTMLInputElement final : public FormAssociatedElement { public: @@ -46,7 +46,14 @@ public: virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override; + enum TypeAttributeState { +#define __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(_, state) state, + ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTES +#undef __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE + }; + String type() const; + TypeAttributeState type_state() const; void set_type(String const&); String default_value() const { return attribute(HTML::AttributeNames::value); } @@ -90,6 +97,9 @@ private: void create_shadow_tree_if_needed(); void run_input_activation_behavior(); + // https://html.spec.whatwg.org/multipage/input.html#value-sanitization-algorithm + String value_sanitization_algorithm(String) const; + RefPtr<DOM::Text> m_text_node; bool m_checked { false }; |