PassRefPtr<FormSubmission> FormSubmission::create(HTMLFormElement* form, const Attributes& attributes, PassRefPtr<Event> event, bool lockHistory, FormSubmissionTrigger trigger) { ASSERT(form); Document* document = form->document(); KURL actionURL = document->completeURL(attributes.action().isEmpty() ? document->url().string() : attributes.action()); bool isMailtoForm = actionURL.protocolIs("mailto"); bool isMultiPartForm = false; String encodingType = attributes.encodingType(); if (attributes.method() == PostMethod) { isMultiPartForm = attributes.isMultiPartForm(); if (isMultiPartForm && isMailtoForm) { encodingType = "application/x-www-form-urlencoded"; isMultiPartForm = false; } } TextEncoding dataEncoding = isMailtoForm ? UTF8Encoding() : FormDataBuilder::encodingFromAcceptCharset(attributes.acceptCharset(), document); RefPtr<DOMFormData> domFormData = DOMFormData::create(dataEncoding.encodingForFormSubmission()); Vector<pair<String, String> > formValues; for (unsigned i = 0; i < form->associatedElements().size(); ++i) { HTMLFormControlElement* control = form->associatedElements()[i]; if (!control->disabled()) control->appendFormData(*domFormData, isMultiPartForm); if (control->hasLocalName(inputTag)) { HTMLInputElement* input = static_cast<HTMLInputElement*>(control); if (input->isTextField()) { formValues.append(pair<String, String>(input->name(), input->value())); if (input->isSearchField()) input->addSearchResult(); } } } RefPtr<FormData> formData; String boundary; if (isMultiPartForm) { formData = FormData::createMultiPart(*(static_cast<FormDataList*>(domFormData.get())), domFormData->encoding(), document); boundary = formData->boundary().data(); } else { formData = FormData::create(*(static_cast<FormDataList*>(domFormData.get())), domFormData->encoding()); if (attributes.method() == PostMethod && isMailtoForm) { // Convert the form data into a string that we put into the URL. appendMailtoPostFormDataToURL(actionURL, *formData, encodingType); formData = FormData::create(); } } formData->setIdentifier(generateFormDataIdentifier()); String targetOrBaseTarget = attributes.target().isEmpty() ? document->baseTarget() : attributes.target(); RefPtr<FormState> formState = FormState::create(form, formValues, document->frame(), trigger); return adoptRef(new FormSubmission(attributes.method(), actionURL, targetOrBaseTarget, encodingType, formState.release(), formData.release(), boundary, lockHistory, event)); }
PassRefPtr<FormData> HTMLFormElement::prepareFormData() { if (m_formDataBuilder.isPostMethod()) { if (m_formDataBuilder.isMultiPartForm() && isMailtoForm()) { // FIXME: This may fire a DOM Mutation Event. Do we really want this here? setEnctype("application/x-www-form-urlencoded"); ASSERT(!m_formDataBuilder.isMultiPartForm()); } } else m_formDataBuilder.setIsMultiPartForm(false); RefPtr<DOMFormData> domFormData = DOMFormData::create(dataEncoding().encodingForFormSubmission()); for (unsigned i = 0; i < m_associatedElements.size(); ++i) { HTMLFormControlElement* control = m_associatedElements[i]; if (!control->disabled()) control->appendFormData(*domFormData, m_formDataBuilder.isMultiPartForm()); } RefPtr<FormData> result; if (m_formDataBuilder.isMultiPartForm()) result = FormData::createMultiPart(domFormData->items(), domFormData->encoding(), document()); else { result = FormData::create(domFormData->items(), domFormData->encoding()); if (m_formDataBuilder.isPostMethod() && isMailtoForm()) { // Convert the form data into a string that we put into the URL. KURL url = document()->completeURL(m_url); appendMailtoPostFormDataToURL(url, *result, m_formDataBuilder.encodingType()); m_url = url.string(); result = FormData::create(); } } result->setIdentifier(generateFormDataIdentifier()); return result.release(); }
PassRefPtr<FormData> HTMLFormElement::createFormData(const CString& boundary) { Vector<char> encodedData; TextEncoding encoding = dataEncoding().encodingForFormSubmission(); RefPtr<FormData> result = FormData::create(); for (unsigned i = 0; i < formElements.size(); ++i) { HTMLFormControlElement* control = formElements[i]; FormDataList list(encoding); if (!control->disabled() && control->appendFormData(list, m_formDataBuilder.isMultiPartForm())) { size_t formDataListSize = list.list().size(); ASSERT(formDataListSize % 2 == 0); for (size_t j = 0; j < formDataListSize; j += 2) { const FormDataList::Item& key = list.list()[j]; const FormDataList::Item& value = list.list()[j + 1]; if (!m_formDataBuilder.isMultiPartForm()) { // Omit the name "isindex" if it's the first form data element. // FIXME: Why is this a good rule? Is this obsolete now? if (encodedData.isEmpty() && key.data() == "isindex") FormDataBuilder::encodeStringAsFormData(encodedData, value.data()); else m_formDataBuilder.addKeyValuePairAsFormData(encodedData, key.data(), value.data()); } else { Vector<char> header; m_formDataBuilder.beginMultiPartHeader(header, boundary, key.data()); bool shouldGenerateFile = false; // if the current type is FILE, then we also need to include the filename if (value.file()) { const String& path = value.file()->path(); String fileName = value.file()->fileName(); // Let the application specify a filename if it's going to generate a replacement file for the upload. if (!path.isEmpty()) { if (Page* page = document()->page()) { String generatedFileName; shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFileName); if (shouldGenerateFile) fileName = generatedFileName; } } // We have to include the filename=".." part in the header, even if the filename is empty m_formDataBuilder.addFilenameToMultiPartHeader(header, encoding, fileName); if (!fileName.isEmpty()) { // FIXME: The MIMETypeRegistry function's name makes it sound like it takes a path, // not just a basename. But filename is not the path. But note that it's not safe to // just use path instead since in the generated-file case it will not reflect the // MIME type of the generated file. String mimeType = MIMETypeRegistry::getMIMETypeForPath(fileName); if (!mimeType.isEmpty()) m_formDataBuilder.addContentTypeToMultiPartHeader(header, mimeType.latin1()); } } m_formDataBuilder.finishMultiPartHeader(header); // Append body result->appendData(header.data(), header.size()); if (size_t dataSize = value.data().length()) result->appendData(value.data().data(), dataSize); else if (value.file() && !value.file()->path().isEmpty()) result->appendFile(value.file()->path(), shouldGenerateFile); result->appendData("\r\n", 2); } } } } if (m_formDataBuilder.isMultiPartForm()) m_formDataBuilder.addBoundaryToMultiPartHeader(encodedData, boundary, true); result->appendData(encodedData.data(), encodedData.size()); result->setIdentifier(generateFormDataIdentifier()); return result; }