TEST(FormDataTest, has) { FormData* fd = FormData::create(UTF8Encoding()); fd->append("name1", "value1"); EXPECT_TRUE(fd->has("name1")); EXPECT_EQ(1u, fd->size()); }
void ResourceRequest::doUpdatePlatformHTTPBody() { CFMutableURLRequestRef cfRequest; RetainPtr<CFURLRef> url = ResourceRequest::url().createCFURL(); RetainPtr<CFURLRef> firstPartyForCookies = ResourceRequest::firstPartyForCookies().createCFURL(); if (m_cfRequest) { cfRequest = CFURLRequestCreateMutableCopy(0, m_cfRequest.get()); CFURLRequestSetURL(cfRequest, url.get()); CFURLRequestSetMainDocumentURL(cfRequest, firstPartyForCookies.get()); CFURLRequestSetCachePolicy(cfRequest, (CFURLRequestCachePolicy)cachePolicy()); CFURLRequestSetTimeoutInterval(cfRequest, timeoutInterval()); } else cfRequest = CFURLRequestCreateMutable(0, url.get(), (CFURLRequestCachePolicy)cachePolicy(), timeoutInterval(), firstPartyForCookies.get()); FormData* formData = httpBody(); if (formData && !formData->isEmpty()) WebCore::setHTTPBody(cfRequest, formData); if (RetainPtr<CFReadStreamRef> bodyStream = adoptCF(CFURLRequestCopyHTTPRequestBodyStream(cfRequest))) { // For streams, provide a Content-Length to avoid using chunked encoding, and to get accurate total length in callbacks. if (RetainPtr<CFStringRef> lengthString = adoptCF(static_cast<CFStringRef>(CFReadStreamCopyProperty(bodyStream.get(), formDataStreamLengthPropertyName())))) { CFURLRequestSetHTTPHeaderFieldValue(cfRequest, CFSTR("Content-Length"), lengthString.get()); // Since resource request is already marked updated, we need to keep it up to date too. ASSERT(m_resourceRequestUpdated); m_httpHeaderFields.set(HTTPHeaderName::ContentLength, lengthString.get()); } } m_cfRequest = adoptCF(cfRequest); #if PLATFORM(COCOA) clearOrUpdateNSURLRequest(); #endif }
void HiddenInputType::appendToFormData(FormData& formData) const { if (equalIgnoringCase(element().name(), "_charset_")) { formData.append(element().name(), String(formData.encoding().name())); return; } InputType::appendToFormData(formData); }
// This static method is called to check to see if a POST response is in // the cache. bool ResourceHandle::willLoadFromCache(ResourceRequest& request, Frame*) { // set the cache policy correctly, copied from // network/mac/ResourceHandleMac.mm request.setCachePolicy(ReturnCacheDataDontLoad); FormData* formData = request.httpBody(); return ResourceLoaderAndroid::willLoadFromCache(request.url(), formData ? formData->identifier() : 0); }
// https://w3c.github.io/webappsec-credential-management/#passwordcredential-form-constructor PasswordCredential* PasswordCredential::create(HTMLFormElement* form, ExceptionState& exceptionState) { // Extract data from the form, then use the extracted |formData| object's // value to populate |data|. FormData* formData = FormData::create(form); PasswordCredentialData data; AtomicString idName; AtomicString passwordName; for (FormAssociatedElement* element : form->associatedElements()) { // If |element| isn't a "submittable element" with string data, then it // won't have a matching value in |formData|, and we can safely skip it. FileOrUSVString result; formData->get(element->name(), result); if (!result.isUSVString()) continue; AtomicString autocomplete = toHTMLElement(element)->fastGetAttribute(HTMLNames::autocompleteAttr); if (equalIgnoringCase(autocomplete, "current-password") || equalIgnoringCase(autocomplete, "new-password")) { data.setPassword(result.getAsUSVString()); passwordName = element->name(); } else if (equalIgnoringCase(autocomplete, "photo")) { data.setIconURL(result.getAsUSVString()); } else if (equalIgnoringCase(autocomplete, "name") || equalIgnoringCase(autocomplete, "nickname")) { data.setName(result.getAsUSVString()); } else if (equalIgnoringCase(autocomplete, "username")) { data.setId(result.getAsUSVString()); idName = element->name(); } } // Create a PasswordCredential using the data gathered above. PasswordCredential* credential = PasswordCredential::create(data, exceptionState); if (exceptionState.hadException()) return nullptr; ASSERT(credential); // After creating the Credential, populate its 'additionalData', 'idName', and 'passwordName' attributes. // If the form's 'enctype' is anything other than multipart, generate a URLSearchParams using the // data in |formData|. credential->setIdName(idName); credential->setPasswordName(passwordName); FormDataOrURLSearchParams additionalData; if (form->enctype() == "multipart/form-data") { additionalData.setFormData(formData); } else { URLSearchParams* params = URLSearchParams::create(URLSearchParamsInit()); for (const FormData::Entry* entry : formData->entries()) { if (entry->isString()) params->append(entry->name().data(), entry->value().data()); } additionalData.setURLSearchParams(params); } credential->setAdditionalData(additionalData); return credential; }
void XSSAuditor::init() { const size_t miniumLengthForSuffixTree = 512; // FIXME: Tune this parameter. const int suffixTreeDepth = 5; ASSERT(m_state == Uninitialized); m_state = Initial; if (!m_isEnabled) return; // In theory, the Document could have detached from the Frame after the // XSSAuditor was constructed. if (!m_parser->document()->frame()) { m_isEnabled = false; return; } const KURL& url = m_parser->document()->url(); if (url.isEmpty()) { // The URL can be empty when opening a new browser window or calling window.open(""). m_isEnabled = false; return; } if (url.protocolIsData()) { m_isEnabled = false; return; } TextResourceDecoder* decoder = m_parser->document()->decoder(); m_decodedURL = fullyDecodeString(url.string(), decoder); if (m_decodedURL.find(isRequiredForInjection, 0) == notFound) m_decodedURL = String(); if (DocumentLoader* documentLoader = m_parser->document()->frame()->loader()->documentLoader()) { DEFINE_STATIC_LOCAL(String, XSSProtectionHeader, ("X-XSS-Protection")); m_xssProtection = parseXSSProtectionHeader(documentLoader->response().httpHeaderField(XSSProtectionHeader)); FormData* httpBody = documentLoader->originalRequest().httpBody(); if (httpBody && !httpBody->isEmpty()) { String httpBodyAsString = httpBody->flattenToString(); if (!httpBodyAsString.isEmpty()) { m_decodedHTTPBody = fullyDecodeString(httpBodyAsString, decoder); if (m_decodedHTTPBody.find(isRequiredForInjection, 0) == notFound) m_decodedHTTPBody = String(); if (m_decodedHTTPBody.length() >= miniumLengthForSuffixTree) m_decodedHTTPBodySuffixTree = adoptPtr(new SuffixTree<ASCIICodebook>(m_decodedHTTPBody, suffixTreeDepth)); } } } if (m_decodedURL.isEmpty() && m_decodedHTTPBody.isEmpty()) m_isEnabled = false; }
/** * Test a POST form transfer */ static void TestNetworkPostTransfer() { // FIXME Setup a http server to serve the files TestManager::AssertTrue("No web server setup for the tests", false); return; const std::string aURL(TEST_WEB_SITE"testpostwithparam.php"); std::string aPath = TestManager::GetInstance().getPath() + "NetworkTests/Refs/testpostwithparam.html"; const std::string aRef(aPath); BIResourceHandleManager* aResourceHandleManager = getBIResourceHandleManager(); TestManager::AssertTrue("Transfer Job Manager obtained", aResourceHandleManager != NULL); std::string aFileName; GetTemporaryUnexistingFileName("/tmp/transfer", ".txt", aFileName); TestResourceHandleClient aTestResourceHandleClient(aFileName); FormData formData; DeprecatedString aParams; aParams = "param1=toto¶m2=kiki"; formData.appendData( static_cast<const void *> (aParams.ascii()), aParams.length() ); ResourceRequest aResourceRequest = ResourceRequest(static_cast<const KURL&> (aURL.c_str())); aResourceRequest.setHTTPMethod("POST"); aResourceRequest.setHTTPReferrer(TEST_WEB_SITE); aResourceRequest.setHTTPBody(formData.copy());; RefPtr<BIResourceHandle> aResourceHandle = BIResourceHandle::create(aResourceRequest, &aTestResourceHandleClient, 0, false, false, false); TestManager::AssertTrue("FormData flatten", aResourceRequest.httpBody()->flattenToString() == "param1=toto¶m2=kiki" ); TestManager::AssertTrue("Form data with correct element", aResourceRequest.httpBody()->elements().size() == 1 ); TestManager::AssertTrue("Correct Metadata", aResourceRequest.httpReferrer() == TEST_WEB_SITE ); TestManager::AssertTrue("Correct Method", aResourceHandle->method() == "POST"); gTransferFileCount = 1; // Wait for the end of the transfer. gTimeout = false; WebCore::Timer<NetworkTest> aTimeoutTimer(NULL,&NetworkTest::TimeoutCallback); aTimeoutTimer.startOneShot(20); // timeout in 20s BIEventLoop* aEventLoop = BAL::getBIEventLoop(); BIEvent* event; while( gTransferFileCount && !gTimeout ) { aEventLoop->WaitEvent(event); } TestManager::AssertTrue("Transfer done", !gTransferFileCount ); BALFileComparison aFileComparison; bool bEqual = aFileComparison.AreEqual( aFileName, aRef ); TestManager::AssertTrue("File as expected", bEqual ); unlink( aFileName.c_str() ); }
TEST(FormDataTest, getAll) { FormData* fd = FormData::create(UTF8Encoding()); fd->append("name1", "value1"); HeapVector<FormDataEntryValue> results = fd->getAll("name1"); EXPECT_EQ(1u, results.size()); EXPECT_TRUE(results[0].isUSVString()); EXPECT_EQ("value1", results[0].getAsUSVString()); EXPECT_EQ(1u, fd->size()); }
void FileInputType::appendToFormData(FormData& formData) const { FileList* fileList = element().files(); unsigned numFiles = fileList->length(); if (numFiles == 0) { formData.append(element().name(), File::create("")); return; } for (unsigned i = 0; i < numFiles; ++i) formData.append(element().name(), fileList->item(i)); }
TEST(FormDataTest, get) { FormData* fd = FormData::create(UTF8Encoding()); fd->append("name1", "value1"); FileOrUSVString result; fd->get("name1", result); EXPECT_TRUE(result.isUSVString()); EXPECT_EQ("value1", result.getAsUSVString()); const FormData::Entry& entry = *fd->entries()[0]; EXPECT_STREQ("name1", entry.name().data()); EXPECT_STREQ("value1", entry.value().data()); }
bool ResourceHandle::startHttp(String urlString) { if (!session) { session = soup_session_async_new(); soup_session_add_feature(session, SOUP_SESSION_FEATURE(getCookieJar())); const char* soup_debug = g_getenv("WEBKIT_SOUP_LOGGING"); if (soup_debug) { int soup_debug_level = atoi(soup_debug); SoupLogger* logger = soup_logger_new(static_cast<SoupLoggerLogLevel>(soup_debug_level), -1); soup_logger_attach(logger, session); g_object_unref(logger); } } SoupMessage* msg; msg = soup_message_new(request().httpMethod().utf8().data(), urlString.utf8().data()); g_signal_connect(msg, "restarted", G_CALLBACK(restartedCallback), this); g_signal_connect(msg, "got-headers", G_CALLBACK(gotHeadersCallback), this); g_signal_connect(msg, "got-chunk", G_CALLBACK(gotChunkCallback), this); HTTPHeaderMap customHeaders = d->m_request.httpHeaderFields(); if (!customHeaders.isEmpty()) { HTTPHeaderMap::const_iterator end = customHeaders.end(); for (HTTPHeaderMap::const_iterator it = customHeaders.begin(); it != end; ++it) soup_message_headers_append(msg->request_headers, it->first.utf8().data(), it->second.utf8().data()); } FormData* httpBody = d->m_request.httpBody(); if (httpBody && !httpBody->isEmpty()) { // Making a copy of the request body isn't the most efficient way to // serialize it, but by far the most simple. Dealing with individual // FormData elements and shared buffers should be more memory // efficient. // // This possibly isn't handling file uploads/attachments, for which // shared buffers or streaming should definitely be used. Vector<char> body; httpBody->flatten(body); soup_message_set_request(msg, d->m_request.httpContentType().utf8().data(), SOUP_MEMORY_COPY, body.data(), body.size()); } d->m_msg = static_cast<SoupMessage*>(g_object_ref(msg)); soup_session_queue_message(session, d->m_msg, finishedCallback, this); return true; }
void HTMLTextAreaElement::appendToFormData(FormData& formData) { if (name().isEmpty()) return; document().updateStyleAndLayout(); const String& text = (m_wrap == HardWrap) ? valueWithHardLineBreaks() : value(); formData.append(name(), text); const AtomicString& dirnameAttrValue = fastGetAttribute(dirnameAttr); if (!dirnameAttrValue.isNull()) formData.append(dirnameAttrValue, directionForFormData()); }
static HTTPBody toHTTPBody(const FormData& formData) { HTTPBody httpBody; for (const auto& formDataElement : formData.elements()) { HTTPBody::Element element; switch (formDataElement.m_type) { case FormDataElement::Type::Data: element.type = HTTPBody::Element::Type::Data; element.data = formDataElement.m_data; break; case FormDataElement::Type::EncodedFile: element.filePath = formDataElement.m_filename; element.fileStart = formDataElement.m_fileStart; if (formDataElement.m_fileLength != BlobDataItem::toEndOfFile) element.fileLength = formDataElement.m_fileLength; if (formDataElement.m_expectedFileModificationTime != invalidFileTime()) element.expectedFileModificationTime = formDataElement.m_expectedFileModificationTime; break; case FormDataElement::Type::EncodedBlob: element.blobURLString = formDataElement.m_url.string(); break; } httpBody.elements.append(WTF::move(element)); } return httpBody; }
void TextFieldInputType::appendToFormData(FormData& formData) const { InputType::appendToFormData(formData); const AtomicString& dirnameAttrValue = element().fastGetAttribute(dirnameAttr); if (!dirnameAttrValue.isNull()) formData.append(dirnameAttrValue, element().directionForFormData()); }
ResourceRequest ResourceHandleCFURLConnectionDelegate::createResourceRequest(CFURLRequestRef cfRequest, CFURLResponseRef redirectResponse) { ResourceRequest request; CFHTTPMessageRef httpMessage = CFURLResponseGetHTTPResponse(redirectResponse); if (httpMessage && CFHTTPMessageGetResponseStatusCode(httpMessage) == 307) { RetainPtr<CFStringRef> lastHTTPMethod = m_handle->lastHTTPMethod().createCFString(); RetainPtr<CFStringRef> newMethod = adoptCF(CFURLRequestCopyHTTPRequestMethod(cfRequest)); if (CFStringCompareWithOptions(lastHTTPMethod.get(), newMethod.get(), CFRangeMake(0, CFStringGetLength(lastHTTPMethod.get())), kCFCompareCaseInsensitive)) { RetainPtr<CFMutableURLRequestRef> mutableRequest = adoptCF(CFURLRequestCreateMutableCopy(0, cfRequest)); wkSetRequestStorageSession(m_handle->storageSession(), mutableRequest.get()); CFURLRequestSetHTTPRequestMethod(mutableRequest.get(), lastHTTPMethod.get()); FormData* body = m_handle->firstRequest().httpBody(); if (!equalIgnoringCase(m_handle->firstRequest().httpMethod(), "GET") && body && !body->isEmpty()) WebCore::setHTTPBody(mutableRequest.get(), body); String originalContentType = m_handle->firstRequest().httpContentType(); if (!originalContentType.isEmpty()) CFURLRequestSetHTTPHeaderFieldValue(mutableRequest.get(), CFSTR("Content-Type"), originalContentType.createCFString().get()); request = mutableRequest.get(); } } if (request.isNull()) request = cfRequest; if (!request.url().protocolIs("https") && protocolIs(request.httpReferrer(), "https") && m_handle->context()->shouldClearReferrerOnHTTPSToHTTPRedirect()) request.clearHTTPReferrer(); return request; }
void ArgumentCoder<ResourceRequest>::encode(ArgumentEncoder* encoder, const ResourceRequest& resourceRequest) { encoder->encode(resourceRequest.url().string()); encoder->encode(resourceRequest.httpMethod()); const HTTPHeaderMap& headers = resourceRequest.httpHeaderFields(); encoder->encode(headers); FormData* httpBody = resourceRequest.httpBody(); encoder->encode(static_cast<bool>(httpBody)); if (httpBody) encoder->encode(httpBody->flattenToString()); encoder->encode(resourceRequest.firstPartyForCookies().string()); encoder->encode(static_cast<uint32_t>(resourceRequest.soupMessageFlags())); }
static CFURLRequestRef willSendRequest(CFURLConnectionRef conn, CFURLRequestRef cfRequest, CFURLResponseRef cfRedirectResponse, const void* clientInfo) { #if LOG_DISABLED UNUSED_PARAM(conn); #endif ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); if (!cfRedirectResponse) { CFRetain(cfRequest); return cfRequest; } LOG(Network, "CFNet - willSendRequest(conn=%p, handle=%p) (%s)", conn, handle, handle->firstRequest().url().string().utf8().data()); ResourceRequest request; if (cfRedirectResponse) { CFHTTPMessageRef httpMessage = CFURLResponseGetHTTPResponse(cfRedirectResponse); if (httpMessage && CFHTTPMessageGetResponseStatusCode(httpMessage) == 307) { RetainPtr<CFStringRef> lastHTTPMethod(AdoptCF, handle->lastHTTPMethod().createCFString()); RetainPtr<CFStringRef> newMethod(AdoptCF, CFURLRequestCopyHTTPRequestMethod(cfRequest)); if (CFStringCompareWithOptions(lastHTTPMethod.get(), newMethod.get(), CFRangeMake(0, CFStringGetLength(lastHTTPMethod.get())), kCFCompareCaseInsensitive)) { RetainPtr<CFMutableURLRequestRef> mutableRequest(AdoptCF, CFURLRequestCreateMutableCopy(0, cfRequest)); #if USE(CFURLSTORAGESESSIONS) wkSetRequestStorageSession(ResourceHandle::currentStorageSession(), mutableRequest.get()); #endif CFURLRequestSetHTTPRequestMethod(mutableRequest.get(), lastHTTPMethod.get()); FormData* body = handle->firstRequest().httpBody(); if (!equalIgnoringCase(handle->firstRequest().httpMethod(), "GET") && body && !body->isEmpty()) WebCore::setHTTPBody(mutableRequest.get(), body); String originalContentType = handle->firstRequest().httpContentType(); RetainPtr<CFStringRef> originalContentTypeCF(AdoptCF, originalContentType.createCFString()); if (!originalContentType.isEmpty()) CFURLRequestSetHTTPHeaderFieldValue(mutableRequest.get(), CFSTR("Content-Type"), originalContentTypeCF.get()); request = mutableRequest.get(); } } } if (request.isNull()) request = cfRequest; // Should not set Referer after a redirect from a secure resource to non-secure one. if (!request.url().protocolIs("https") && protocolIs(request.httpReferrer(), "https")) request.clearHTTPReferrer(); handle->willSendRequest(request, cfRedirectResponse); if (request.isNull()) return 0; cfRequest = request.cfURLRequest(); CFRetain(cfRequest); return cfRequest; }
PassRefPtr<EncodedFormData> PasswordCredential::encodeFormData( String& contentType) const { if (m_additionalData.isURLSearchParams()) { // If |additionalData| is a 'URLSearchParams' object, build a urlencoded // response. URLSearchParams* params = URLSearchParams::create(URLSearchParamsInit()); URLSearchParams* additionalData = m_additionalData.getAsURLSearchParams(); for (const auto& param : additionalData->params()) { const String& name = param.first; if (name != idName() && name != passwordName()) params->append(name, param.second); } params->append(idName(), id()); params->append(passwordName(), password()); contentType = AtomicString("application/x-www-form-urlencoded;charset=UTF-8"); return params->toEncodedFormData(); } // Otherwise, we'll build a multipart response. FormData* formData = FormData::create(nullptr); if (m_additionalData.isFormData()) { FormData* additionalData = m_additionalData.getAsFormData(); for (const FormData::Entry* entry : additionalData->entries()) { const String& name = formData->decode(entry->name()); if (name == idName() || name == passwordName()) continue; if (entry->blob()) formData->append(name, entry->blob(), entry->filename()); else formData->append(name, formData->decode(entry->value())); } } formData->append(idName(), id()); formData->append(passwordName(), password()); RefPtr<EncodedFormData> encodedData = formData->encodeMultiPartFormData(); contentType = AtomicString("multipart/form-data; boundary=") + encodedData->boundary().data(); return encodedData.release(); }
void ArgumentCoder<ResourceRequest>::encode(ArgumentEncoder* encoder, const ResourceRequest& resourceRequest) { if (kShouldSerializeWebCoreData) { encoder->encode(resourceRequest.url().string()); encoder->encode(resourceRequest.httpMethod()); const HTTPHeaderMap& headers = resourceRequest.httpHeaderFields(); encoder->encode(headers); FormData* httpBody = resourceRequest.httpBody(); encoder->encode(static_cast<bool>(httpBody)); if (httpBody) encoder->encode(httpBody->flattenToString()); encoder->encode(resourceRequest.firstPartyForCookies().string()); } encodePlatformData(encoder, resourceRequest); }
CFArrayRef arrayFromFormData(const FormData& d) { size_t size = d.elements().size(); CFMutableArrayRef a = CFArrayCreateMutable(0, d.elements().size(), &kCFTypeArrayCallBacks); for (size_t i = 0; i < size; ++i) { const FormDataElement& e = d.elements()[i]; if (e.m_type == FormDataElement::data) { CFDataRef data = CFDataCreate(0, (const UInt8*)e.m_data.data(), e.m_data.size()); CFArrayAppendValue(a, data); CFRelease(data); } else { ASSERT(e.m_type == FormDataElement::encodedFile); CFStringRef filename = e.m_filename.createCFString(); CFArrayAppendValue(a, filename); CFRelease(filename); } } return a; }
void ArgumentCoder<ResourceRequest>::encodePlatformData(ArgumentEncoder& encoder, const ResourceRequest& resourceRequest) { encoder << resourceRequest.url().string(); encoder << resourceRequest.httpMethod(); encoder << resourceRequest.httpHeaderFields(); // FIXME: Do not encode HTTP message body. // 1. It can be large and thus costly to send across. // 2. It is misleading to provide a body with some requests, while others use body streams, which cannot be serialized at all. FormData* httpBody = resourceRequest.httpBody(); encoder << static_cast<bool>(httpBody); if (httpBody) encoder << httpBody->flattenToString(); encoder << resourceRequest.firstPartyForCookies().string(); encoder << static_cast<uint32_t>(resourceRequest.soupMessageFlags()); encoder << resourceRequest.initiatingPageID(); }
void HTMLObjectElement::appendToFormData(FormData& formData) { if (name().isEmpty()) return; Widget* widget = pluginWidget(); if (!widget || !widget->isPluginView()) return; String value; if (toPluginView(widget)->getFormValue(value)) formData.append(name(), value); }
void HTMLKeygenElement::appendToFormData(FormData& formData) { // Only RSA is supported at this time. const AtomicString& keyType = fastGetAttribute(keytypeAttr); if (!keyType.isNull() && !equalIgnoringCase(keyType, "rsa")) return; SecurityOrigin* topOrigin = document().frame()->tree().top()->securityContext()->getSecurityOrigin(); String value = Platform::current()->signedPublicKeyAndChallengeString( shadowSelect()->selectedIndex(), fastGetAttribute(challengeAttr), document().baseURL(), KURL(KURL(), topOrigin->toString())); if (!value.isNull()) formData.append(name(), value); }
static void* formCreate(CFReadStreamRef stream, void* context) { FormData* formData = static_cast<FormData*>(context); CFSetCallBacks runLoopAndModeCallBacks = { 0, pairRetain, pairRelease, NULL, pairEqual, pairHash }; FormStreamFields* newInfo = new FormStreamFields; newInfo->scheduledRunLoopPairs = CFSetCreateMutable(0, 0, &runLoopAndModeCallBacks); newInfo->currentStream = NULL; newInfo->currentData = 0; newInfo->formStream = stream; // Don't retain. That would create a reference cycle. // Append in reverse order since we remove elements from the end. size_t size = formData->elements().size(); newInfo->remainingElements.reserveCapacity(size); for (size_t i = 0; i < size; ++i) newInfo->remainingElements.append(formData->elements()[size - i - 1]); getStreamFormDatas().set(stream, adoptRef(formData)); return newInfo; }
void ArgumentCoder<ResourceRequest>::encode(ArgumentEncoder& encoder, const ResourceRequest& resourceRequest) { if (kShouldSerializeWebCoreData) { encoder << resourceRequest.url().string(); encoder << resourceRequest.httpMethod(); encoder << resourceRequest.httpHeaderFields(); // FIXME: Do not encode HTTP message body. // 1. It can be large and thus costly to send across. // 2. It is misleading to provide a body with some requests, while others use body streams, which cannot be serialized at all. FormData* httpBody = resourceRequest.httpBody(); encoder << static_cast<bool>(httpBody); if (httpBody) encoder << httpBody->flattenToString(); encoder << resourceRequest.firstPartyForCookies().string(); } #if ENABLE(CACHE_PARTITIONING) encoder << resourceRequest.cachePartition(); #endif encodePlatformData(encoder, resourceRequest); }
static void appendMailtoPostFormDataToURL(KURL& url, const FormData& data, const String& encodingType) { String body = data.flattenToString(); if (equalIgnoringCase(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"); } Vector<char> bodyData; bodyData.append("body=", 5); FormDataBuilder::encodeStringAsFormData(bodyData, body.utf8()); body = String(bodyData.data(), bodyData.size()).replaceWithLiteral('+', "%20"); String query = url.query(); if (!query.isEmpty()) query.append('&'); query.append(body); url.setQuery(query); }
bool XSSAuditor::findInRequest(Frame* frame, const FindTask& task) const { ASSERT(frame->document()); if (!frame->document()->decoder()) { // Note, JavaScript URLs do not have a charset. return false; } if (task.string.isEmpty()) return false; DocumentLoader *documentLoader = frame->loader()->documentLoader(); if (!documentLoader) return false; FormData* formDataObj = documentLoader->originalRequest().httpBody(); const bool hasFormData = formDataObj && !formDataObj->isEmpty(); String pageURL = frame->document()->url().string(); if (!hasFormData) { // We clear out our form data caches, in case we're holding onto a bunch of memory. m_formDataCache.clear(); m_formDataSuffixTree.clear(); } String canonicalizedString; if (!hasFormData && task.string.length() > 2 * pageURL.length()) { // Q: Why do we bother to do this check at all? // A: Canonicalizing large inline scripts can be expensive. We want to // reduce the size of the string before we call canonicalize below, // since it could result in an unneeded allocation and memcpy. // // Q: Why do we multiply by two here? // A: We attempt to detect reflected XSS even when the server // transforms the attacker's input with addSlashes. The best the // attacker can do get the server to inflate his/her input by a // factor of two by sending " characters, which the server // transforms to \". canonicalizedString = task.string.substring(0, 2 * pageURL.length()); } else canonicalizedString = task.string; if (frame->document()->url().protocolIs("data")) return false; canonicalizedString = canonicalize(canonicalizedString); if (canonicalizedString.isEmpty()) return false; if (!task.context.isEmpty()) canonicalizedString = task.context + canonicalizedString; String decodedPageURL = m_pageURLCache.canonicalizeURL(pageURL, frame->document()->decoder()->encoding(), task.decodeEntities, task.decodeURLEscapeSequencesTwice); if (task.allowRequestIfNoIllegalURICharacters && !hasFormData && decodedPageURL.find(&isIllegalURICharacter, 0) == -1) return false; // Injection is impossible because the request does not contain any illegal URI characters. if (decodedPageURL.find(canonicalizedString, 0, false) != -1) return true; // We've found the string in the GET data. if (hasFormData) { String decodedFormData = m_formDataCache.canonicalizeURL(formDataObj, frame->document()->decoder()->encoding(), task.decodeEntities, task.decodeURLEscapeSequencesTwice); if (m_generationOfSuffixTree != m_formDataCache.generation()) { m_formDataSuffixTree = new SuffixTree<ASCIICodebook>(decodedFormData, 5); m_generationOfSuffixTree = m_formDataCache.generation(); } // Try a fast-reject via the suffixTree. if (m_formDataSuffixTree && !m_formDataSuffixTree->mightContain(canonicalizedString)) return false; if (decodedFormData.find(canonicalizedString, 0, false) != -1) return true; // We found the string in the POST data. } return false; }
void SubmitInputType::appendToFormData(FormData& formData) const { if (element().isActivatedSubmit()) formData.append(element().name(), element().valueOrDefaultLabel()); }
void InputType::appendToFormData(FormData& formData) const { formData.append(element().name(), element().value()); }
bool HTMLFormElement::formData(FormData &form_data) const { DeprecatedCString enc_string = ""; // used for non-multipart data DeprecatedString str = m_acceptcharset.deprecatedString(); str.replace(',', ' '); DeprecatedStringList charsets = DeprecatedStringList::split(' ', str); TextEncoding encoding(InvalidEncoding); Frame *frame = document()->frame(); for (DeprecatedStringList::Iterator it = charsets.begin(); it != charsets.end(); ++it) { if ((encoding = TextEncoding((*it).latin1())).isValid()) break; } if (!encoding.isValid()) { if (frame) encoding = TextEncoding(frame->encoding().latin1()); else encoding = TextEncoding(Latin1Encoding); } for (unsigned i = 0; i < formElements.size(); ++i) { HTMLGenericFormElement* current = formElements[i]; FormDataList lst(encoding); if (!current->disabled() && current->appendFormData(lst, m_multipart)) { for (DeprecatedValueListConstIterator<FormDataListItem> it = lst.begin(); it != lst.end(); ++it) { if (!m_multipart) { // handle ISINDEX / <input name=isindex> special // but only if its the first entry if ( enc_string.isEmpty() && (*it).m_data == "isindex" ) { ++it; enc_string += encodeCString( (*it).m_data ); } else { if(!enc_string.isEmpty()) enc_string += '&'; enc_string += encodeCString((*it).m_data); enc_string += "="; ++it; enc_string += encodeCString((*it).m_data); } } else { DeprecatedCString hstr("--"); hstr += m_boundary.deprecatedString().latin1(); hstr += "\r\n"; hstr += "Content-Disposition: form-data; name=\""; hstr += (*it).m_data.data(); hstr += "\""; // if the current type is FILE, then we also need to // include the filename if (current->hasLocalName(inputTag) && static_cast<HTMLInputElement*>(current)->inputType() == HTMLInputElement::FILE) { DeprecatedString path = static_cast<HTMLInputElement*>(current)->value().deprecatedString(); // FIXME: This won't work if the filename includes a " mark, // or control characters like CR or LF. This also does strange // things if the filename includes characters you can't encode // in the website's character set. hstr += "; filename=\""; hstr += encoding.fromUnicode(path.mid(path.findRev('/') + 1), true); hstr += "\""; if (!static_cast<HTMLInputElement*>(current)->value().isEmpty()) { DeprecatedString mimeType = frame ? frame->mimeTypeForFileName(path).deprecatedString() : DeprecatedString(); if (!mimeType.isEmpty()) { hstr += "\r\nContent-Type: "; hstr += mimeType.ascii(); } } } hstr += "\r\n\r\n"; ++it; // append body form_data.appendData(hstr.data(), hstr.length()); const FormDataListItem &item = *it; size_t dataSize = item.m_data.size(); if (dataSize != 0) form_data.appendData(item.m_data, dataSize - 1); else if (!item.m_path.isEmpty()) form_data.appendFile(item.m_path); form_data.appendData("\r\n", 2); } } } } if (m_multipart) enc_string = ("--" + m_boundary.deprecatedString() + "--\r\n").ascii(); form_data.appendData(enc_string.data(), enc_string.length()); return true; }