📄 htmlformelement.cpp
字号:
/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * (C) 2006 Alexey Proskuryakov (ap@nypop.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */#include "config.h"#include "HTMLFormElement.h"#include "CSSHelper.h"#include "ChromeClient.h"#include "Document.h"#include "Event.h"#include "EventNames.h"#include "FileList.h"#include "FileSystem.h"#include "FormData.h"#include "FormDataList.h"#include "Frame.h"#include "FrameLoader.h"#include "HTMLDocument.h"#include "HTMLFormCollection.h"#include "HTMLImageElement.h"#include "HTMLInputElement.h"#include "HTMLNames.h"#include "MIMETypeRegistry.h"#include "Page.h"#include "RenderTextControl.h"#include <wtf/RandomNumber.h>#include <limits>#if PLATFORM(WX)#include <wx/defs.h>#include <wx/filename.h>#endif#if PLATFORM(WIN_OS)#include <shlwapi.h>#endifnamespace WebCore {using namespace HTMLNames;HTMLFormElement::HTMLFormElement(const QualifiedName& tagName, Document* doc) : HTMLElement(tagName, doc) , m_elementAliases(0) , collectionInfo(0) , m_autocomplete(true) , m_insubmit(false) , m_doingsubmit(false) , m_inreset(false) , m_malformed(false){ ASSERT(hasTagName(formTag));}HTMLFormElement::~HTMLFormElement(){ if (!m_autocomplete) document()->unregisterForDocumentActivationCallbacks(this); delete m_elementAliases; delete collectionInfo; for (unsigned i = 0; i < formElements.size(); ++i) formElements[i]->formDestroyed(); for (unsigned i = 0; i < imgElements.size(); ++i) imgElements[i]->m_form = 0;}bool HTMLFormElement::formWouldHaveSecureSubmission(const String& url){ return document()->completeURL(url).protocolIs("https");}void HTMLFormElement::attach(){ HTMLElement::attach();}void HTMLFormElement::insertedIntoDocument(){ if (document()->isHTMLDocument()) static_cast<HTMLDocument*>(document())->addNamedItem(m_name); HTMLElement::insertedIntoDocument();}void HTMLFormElement::removedFromDocument(){ if (document()->isHTMLDocument()) static_cast<HTMLDocument*>(document())->removeNamedItem(m_name); HTMLElement::removedFromDocument();}void HTMLFormElement::handleLocalEvents(Event* event, bool useCapture){ Node* targetNode = event->target()->toNode(); if (!useCapture && targetNode && targetNode != this && (event->type() == eventNames().submitEvent || event->type() == eventNames().resetEvent)) { event->stopPropagation(); return; } HTMLElement::handleLocalEvents(event, useCapture);}unsigned HTMLFormElement::length() const{ int len = 0; for (unsigned i = 0; i < formElements.size(); ++i) if (formElements[i]->isEnumeratable()) ++len; return len;}Node* HTMLFormElement::item(unsigned index){ return elements()->item(index);}void HTMLFormElement::submitClick(Event* event){ bool submitFound = false; for (unsigned i = 0; i < formElements.size(); ++i) { if (formElements[i]->hasLocalName(inputTag)) { HTMLInputElement* element = static_cast<HTMLInputElement*>(formElements[i]); if (element->isSuccessfulSubmitButton() && element->renderer()) { submitFound = true; element->dispatchSimulatedClick(event); break; } } } if (!submitFound) // submit the form without a submit or image input prepareSubmit(event);}TextEncoding HTMLFormElement::dataEncoding() const{ if (isMailtoForm()) return UTF8Encoding(); return m_formDataBuilder.dataEncoding(document());}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; if (shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFileName)) 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()); return result;}bool HTMLFormElement::isMailtoForm() const{ return protocolIs(m_url, "mailto");}bool HTMLFormElement::prepareSubmit(Event* event){ Frame* frame = document()->frame(); if (m_insubmit || !frame) return m_insubmit; m_insubmit = true; m_doingsubmit = false; if (dispatchEventForType(eventNames().submitEvent, true, true) && !m_doingsubmit) m_doingsubmit = true; m_insubmit = false; if (m_doingsubmit) submit(event, true); return m_doingsubmit;}void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool lockHistory, bool lockBackForwardList){ FrameView* view = document()->view(); Frame* frame = document()->frame(); if (!view || !frame) return; if (m_insubmit) { m_doingsubmit = true; return; } m_insubmit = true; HTMLFormControlElement* firstSuccessfulSubmitButton = 0; bool needButtonActivation = activateSubmitButton; // do we need to activate a submit button? frame->loader()->clearRecordedFormValues(); frame->loader()->setFormAboutToBeSubmitted(this); for (unsigned i = 0; i < formElements.size(); ++i) { HTMLFormControlElement* control = formElements[i]; if (control->hasLocalName(inputTag)) { HTMLInputElement* input = static_cast<HTMLInputElement*>(control); if (input->isTextField()) { frame->loader()->recordFormValue(input->name(), input->value()); if (input->isSearchField()) input->addSearchResult(); } } if (needButtonActivation) { if (control->isActivatedSubmit()) needButtonActivation = false; else if (firstSuccessfulSubmitButton == 0 && control->isSuccessfulSubmitButton()) firstSuccessfulSubmitButton = control; } } if (needButtonActivation && firstSuccessfulSubmitButton) firstSuccessfulSubmitButton->setActivatedSubmit(true); if (m_url.isEmpty()) m_url = document()->url().string(); if (m_formDataBuilder.isPostMethod()) { if (m_formDataBuilder.isMultiPartForm() && isMailtoForm()) { setEnctype("application/x-www-form-urlencoded"); ASSERT(!m_formDataBuilder.isMultiPartForm()); } if (!m_formDataBuilder.isMultiPartForm()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -