diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/loader/FormSubmission.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/loader/FormSubmission.cpp')
-rw-r--r-- | Source/WebCore/loader/FormSubmission.cpp | 144 |
1 files changed, 79 insertions, 65 deletions
diff --git a/Source/WebCore/loader/FormSubmission.cpp b/Source/WebCore/loader/FormSubmission.cpp index 4d1a6e85b..1d742ea33 100644 --- a/Source/WebCore/loader/FormSubmission.cpp +++ b/Source/WebCore/loader/FormSubmission.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,6 +32,7 @@ #include "config.h" #include "FormSubmission.h" +#include "ContentSecurityPolicy.h" #include "DOMFormData.h" #include "Document.h" #include "Event.h" @@ -45,9 +47,9 @@ #include "HTMLInputElement.h" #include "HTMLNames.h" #include "HTMLParserIdioms.h" +#include "NoEventDispatchAssertion.h" #include "TextEncoding.h" #include <wtf/CurrentTime.h> -#include <wtf/RandomNumber.h> namespace WebCore { @@ -65,7 +67,7 @@ static void appendMailtoPostFormDataToURL(URL& url, const FormData& data, const { String body = data.flattenToString(); - if (equalIgnoringCase(encodingType, "text/plain")) { + if (equalLettersIgnoringASCIICase(encodingType, "text/plain")) { // Convention seems to be to decode, and s/&/\r\n/. Also, spaces are encoded as %20. body = decodeURLEscapeSequences(body.replaceWithLiteral('&', "\r\n").replace('+', ' ') + "\r\n"); } @@ -76,10 +78,10 @@ static void appendMailtoPostFormDataToURL(URL& url, const FormData& data, const body = String(bodyData.data(), bodyData.size()).replaceWithLiteral('+', "%20"); String query = url.query(); - if (!query.isEmpty()) - query.append('&'); - query.append(body); - url.setQuery(query); + if (query.isEmpty()) + url.setQuery(body); + else + url.setQuery(query + '&' + body); } void FormSubmission::Attributes::parseAction(const String& action) @@ -90,11 +92,11 @@ void FormSubmission::Attributes::parseAction(const String& action) String FormSubmission::Attributes::parseEncodingType(const String& type) { - if (equalIgnoringCase(type, "multipart/form-data")) - return "multipart/form-data"; - if (equalIgnoringCase(type, "text/plain")) - return "text/plain"; - return "application/x-www-form-urlencoded"; + if (equalLettersIgnoringASCIICase(type, "multipart/form-data")) + return ASCIILiteral("multipart/form-data"); + if (equalLettersIgnoringASCIICase(type, "text/plain")) + return ASCIILiteral("text/plain"); + return ASCIILiteral("application/x-www-form-urlencoded"); } void FormSubmission::Attributes::updateEncodingType(const String& type) @@ -105,7 +107,7 @@ void FormSubmission::Attributes::updateEncodingType(const String& type) FormSubmission::Method FormSubmission::Attributes::parseMethodType(const String& type) { - return equalIgnoringCase(type, "post") ? FormSubmission::PostMethod : FormSubmission::GetMethod; + return equalLettersIgnoringASCIICase(type, "post") ? FormSubmission::Method::Post : FormSubmission::Method::Get; } void FormSubmission::Attributes::updateMethodType(const String& type) @@ -113,65 +115,70 @@ void FormSubmission::Attributes::updateMethodType(const String& type) m_method = parseMethodType(type); } -void FormSubmission::Attributes::copyFrom(const Attributes& other) -{ - m_method = other.m_method; - m_isMultiPartForm = other.m_isMultiPartForm; - - m_action = other.m_action; - m_target = other.m_target; - m_encodingType = other.m_encodingType; - m_acceptCharset = other.m_acceptCharset; -} - -inline FormSubmission::FormSubmission(Method method, const URL& action, const String& target, const String& contentType, PassRefPtr<FormState> state, PassRefPtr<FormData> data, const String& boundary, bool lockHistory, PassRefPtr<Event> event) +inline FormSubmission::FormSubmission(Method method, const URL& action, const String& target, const String& contentType, Ref<FormState>&& state, Ref<FormData>&& data, const String& boundary, LockHistory lockHistory, Event* event) : m_method(method) , m_action(action) , m_target(target) , m_contentType(contentType) - , m_formState(state) - , m_formData(data) + , m_formState(WTFMove(state)) + , m_formData(WTFMove(data)) , m_boundary(boundary) , m_lockHistory(lockHistory) , m_event(event) { } -PassRefPtr<FormSubmission> FormSubmission::create(HTMLFormElement* form, const Attributes& attributes, PassRefPtr<Event> event, bool lockHistory, FormSubmissionTrigger trigger) +static TextEncoding encodingFromAcceptCharset(const String& acceptCharset, Document& document) { - ASSERT(form); + String normalizedAcceptCharset = acceptCharset; + normalizedAcceptCharset.replace(',', ' '); + + Vector<String> charsets; + normalizedAcceptCharset.split(' ', charsets); + + for (auto& charset : charsets) { + TextEncoding encoding(charset); + if (encoding.isValid()) + return encoding; + } - HTMLFormControlElement* submitButton = 0; + return document.textEncoding(); +} + +Ref<FormSubmission> FormSubmission::create(HTMLFormElement& form, const Attributes& attributes, Event* event, LockHistory lockHistory, FormSubmissionTrigger trigger) +{ + HTMLFormControlElement* submitButton = nullptr; if (event && event->target()) { for (Node* node = event->target()->toNode(); node; node = node->parentNode()) { - if (node->isElementNode() && toElement(node)->isFormControlElement()) { - submitButton = toHTMLFormControlElement(node); + if (is<HTMLFormControlElement>(*node)) { + submitButton = downcast<HTMLFormControlElement>(node); break; } } } - FormSubmission::Attributes copiedAttributes; - copiedAttributes.copyFrom(attributes); + auto copiedAttributes = attributes; if (submitButton) { - String attributeValue; - if (!(attributeValue = submitButton->getAttribute(formactionAttr)).isNull()) + AtomicString attributeValue; + if (!(attributeValue = submitButton->attributeWithoutSynchronization(formactionAttr)).isNull()) copiedAttributes.parseAction(attributeValue); - if (!(attributeValue = submitButton->getAttribute(formenctypeAttr)).isNull()) + if (!(attributeValue = submitButton->attributeWithoutSynchronization(formenctypeAttr)).isNull()) copiedAttributes.updateEncodingType(attributeValue); - if (!(attributeValue = submitButton->getAttribute(formmethodAttr)).isNull()) + if (!(attributeValue = submitButton->attributeWithoutSynchronization(formmethodAttr)).isNull()) copiedAttributes.updateMethodType(attributeValue); - if (!(attributeValue = submitButton->getAttribute(formtargetAttr)).isNull()) + if (!(attributeValue = submitButton->attributeWithoutSynchronization(formtargetAttr)).isNull()) copiedAttributes.setTarget(attributeValue); } - Document& document = form->document(); - URL actionURL = document.completeURL(copiedAttributes.action().isEmpty() ? document.url().string() : copiedAttributes.action()); + auto& document = form.document(); + auto actionURL = document.completeURL(copiedAttributes.action().isEmpty() ? document.url().string() : copiedAttributes.action()); bool isMailtoForm = actionURL.protocolIs("mailto"); bool isMultiPartForm = false; - String encodingType = copiedAttributes.encodingType(); + auto encodingType = copiedAttributes.encodingType(); + + document.contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(actionURL, ContentSecurityPolicy::InsecureRequestType::FormSubmission); - if (copiedAttributes.method() == PostMethod) { + if (copiedAttributes.method() == Method::Post) { isMultiPartForm = copiedAttributes.isMultiPartForm(); if (isMultiPartForm && isMailtoForm) { encodingType = "application/x-www-form-urlencoded"; @@ -179,24 +186,27 @@ PassRefPtr<FormSubmission> FormSubmission::create(HTMLFormElement* form, const A } } - TextEncoding dataEncoding = isMailtoForm ? UTF8Encoding() : FormDataBuilder::encodingFromAcceptCharset(copiedAttributes.acceptCharset(), document); - RefPtr<DOMFormData> domFormData = DOMFormData::create(dataEncoding.encodingForFormSubmission()); - Vector<std::pair<String, String>> formValues; + auto dataEncoding = isMailtoForm ? UTF8Encoding() : encodingFromAcceptCharset(copiedAttributes.acceptCharset(), document); + auto domFormData = DOMFormData::create(dataEncoding.encodingForFormSubmission()); + StringPairVector formValues; bool containsPasswordData = false; - for (unsigned i = 0; i < form->associatedElements().size(); ++i) { - FormAssociatedElement& control = *form->associatedElements()[i]; - HTMLElement& element = control.asHTMLElement(); - if (!element.isDisabledFormControl()) - control.appendFormData(*domFormData, isMultiPartForm); - if (isHTMLInputElement(element)) { - HTMLInputElement& input = toHTMLInputElement(element); - if (input.isTextField()) { - formValues.append(std::pair<String, String>(input.name().string(), input.value())); - input.addSearchResult(); + { + NoEventDispatchAssertion noEventDispatchAssertion; + + for (auto& control : form.associatedElements()) { + auto& element = control->asHTMLElement(); + if (!element.isDisabledFormControl()) + control->appendFormData(domFormData, isMultiPartForm); + if (is<HTMLInputElement>(element)) { + auto& input = downcast<HTMLInputElement>(element); + if (input.isTextField()) { + formValues.append({ input.name().string(), input.value() }); + input.addSearchResult(); + } + if (input.isPasswordField() && !input.value().isEmpty()) + containsPasswordData = true; } - if (input.isPasswordField() && !input.value().isEmpty()) - containsPasswordData = true; } } @@ -204,11 +214,11 @@ PassRefPtr<FormSubmission> FormSubmission::create(HTMLFormElement* form, const A String boundary; if (isMultiPartForm) { - formData = FormData::createMultiPart(*(static_cast<FormDataList*>(domFormData.get())), domFormData->encoding(), &document); + formData = FormData::createMultiPart(domFormData, domFormData->encoding(), &document); boundary = formData->boundary().data(); } else { - formData = FormData::create(*(static_cast<FormDataList*>(domFormData.get())), domFormData->encoding(), attributes.method() == GetMethod ? FormData::FormURLEncoded : FormData::parseEncodingType(encodingType)); - if (copiedAttributes.method() == PostMethod && isMailtoForm) { + formData = FormData::create(domFormData, domFormData->encoding(), attributes.method() == Method::Get ? FormData::FormURLEncoded : FormData::parseEncodingType(encodingType)); + if (copiedAttributes.method() == Method::Post && isMailtoForm) { // Convert the form data into a string that we put into the URL. appendMailtoPostFormDataToURL(actionURL, *formData, encodingType); formData = FormData::create(); @@ -217,14 +227,17 @@ PassRefPtr<FormSubmission> FormSubmission::create(HTMLFormElement* form, const A formData->setIdentifier(generateFormDataIdentifier()); formData->setContainsPasswordData(containsPasswordData); + String targetOrBaseTarget = copiedAttributes.target().isEmpty() ? document.baseTarget() : copiedAttributes.target(); - RefPtr<FormState> formState = FormState::create(form, formValues, &document, trigger); - return adoptRef(new FormSubmission(copiedAttributes.method(), actionURL, targetOrBaseTarget, encodingType, formState.release(), formData.release(), boundary, lockHistory, event)); + + auto formState = FormState::create(form, WTFMove(formValues), document, trigger); + + return adoptRef(*new FormSubmission(copiedAttributes.method(), actionURL, targetOrBaseTarget, encodingType, WTFMove(formState), formData.releaseNonNull(), boundary, lockHistory, event)); } URL FormSubmission::requestURL() const { - if (m_method == FormSubmission::PostMethod) + if (m_method == Method::Post) return m_action; URL requestURL(m_action); @@ -240,9 +253,9 @@ void FormSubmission::populateFrameLoadRequest(FrameLoadRequest& frameRequest) if (!m_referrer.isEmpty()) frameRequest.resourceRequest().setHTTPReferrer(m_referrer); - if (m_method == FormSubmission::PostMethod) { + if (m_method == Method::Post) { frameRequest.resourceRequest().setHTTPMethod("POST"); - frameRequest.resourceRequest().setHTTPBody(m_formData); + frameRequest.resourceRequest().setHTTPBody(m_formData.copyRef()); // construct some user headers if necessary if (m_boundary.isEmpty()) @@ -253,6 +266,7 @@ void FormSubmission::populateFrameLoadRequest(FrameLoadRequest& frameRequest) frameRequest.resourceRequest().setURL(requestURL()); FrameLoader::addHTTPOriginIfNeeded(frameRequest.resourceRequest(), m_origin); + FrameLoader::addHTTPUpgradeInsecureRequestsIfNeeded(frameRequest.resourceRequest()); } } |