📄 html_formimpl.cpp
字号:
/* * This file is part of the DOM implementation for KDE. * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) * * 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. * */#undef FORMS_DEBUG//#define FORMS_DEBUG#include "html/html_formimpl.h"#include "khtmlview.h"#include "khtml_part.h"#include "html/html_documentimpl.h"#include "khtml_settings.h"#include "misc/htmlhashes.h"#include "css/cssstyleselector.h"#include "css/cssproperties.h"#include "css/cssvalues.h"#include "css/csshelper.h"#include "xml/dom_textimpl.h"#include "xml/dom_docimpl.h"#include "xml/dom2_eventsimpl.h"#include "khtml_ext.h"#include "rendering/render_form.h"#include <kcharsets.h>#include <kglobal.h>#include <kdebug.h>#include <kmimetype.h>#include <kmessagebox.h>#include <kapplication.h>#include <klocale.h>#ifndef KHTML_NO_WALLET#include <kwallet.h>#endif#include <netaccess.h>#include <kfileitem.h>#include <qfile.h>#include <qdir.h>#include <qtextcodec.h>// for keygen#include <qstring.h>#include <ksslkeygen.h>#include <assert.h>using namespace DOM;using namespace khtml;HTMLFormElementImpl::HTMLFormElementImpl(DocumentPtr *doc, bool implicit) : HTMLElementImpl(doc){ m_implicit = implicit; m_post = false; m_multipart = false; m_autocomplete = true; m_insubmit = false; m_doingsubmit = false; m_inreset = false; m_enctype = "application/x-www-form-urlencoded"; m_boundary = "----------" + KApplication::randomString( 42 + 13 ); m_acceptcharset = "UNKNOWN"; m_malformed = false;}HTMLFormElementImpl::~HTMLFormElementImpl(){ if (getDocument() && getDocument()->view() && getDocument()->view()->part()) { getDocument()->view()->part()->dequeueWallet(this); } QPtrListIterator<HTMLGenericFormElementImpl> it(formElements); for (; it.current(); ++it) it.current()->m_form = 0; QPtrListIterator<HTMLImageElementImpl> it2(imgElements); for (; it2.current(); ++it2) it2.current()->m_form = 0;}NodeImpl::Id HTMLFormElementImpl::id() const{ return ID_FORM;}long HTMLFormElementImpl::length() const{ int len = 0; QPtrListIterator<HTMLGenericFormElementImpl> it(formElements); for (; it.current(); ++it) if (it.current()->isEnumeratable()) ++len; return len;}static QCString encodeCString(const QCString& e){ // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1 // safe characters like NS handles them for compatibility static const char *safe = "-._*"; QCString encoded(( e.length()+e.contains( '\n' ) )*3 +e.contains('\r') * 3 + 1); int enclen = 0; bool crmissing = false; unsigned char oldc; unsigned char c ='\0'; //QCString orig(e.data(), e.size()); unsigned len = e.length(); for(unsigned pos = 0; pos < len; pos++) { oldc = c; c = e[pos]; if (crmissing && c != '\n') { encoded[enclen++] = '%'; encoded[enclen++] = '0'; encoded[enclen++] = 'D'; crmissing = false; } if ( (( c >= 'A') && ( c <= 'Z')) || (( c >= 'a') && ( c <= 'z')) || (( c >= '0') && ( c <= '9')) || (strchr(safe, c)) ) encoded[enclen++] = c; else if ( c == ' ' ) encoded[enclen++] = '+'; else if ( c == '\n' ) { encoded[enclen++] = '%'; encoded[enclen++] = '0'; encoded[enclen++] = 'D'; encoded[enclen++] = '%'; encoded[enclen++] = '0'; encoded[enclen++] = 'A'; crmissing = false; } else if (c == '\r' && oldc != '\n') { crmissing = true; } else if ( c != '\r' ) { encoded[enclen++] = '%'; unsigned int h = c / 16; h += (h > 9) ? ('A' - 10) : '0'; encoded[enclen++] = h; unsigned int l = c % 16; l += (l > 9) ? ('A' - 10) : '0'; encoded[enclen++] = l; } } encoded[enclen++] = '\0'; encoded.truncate(enclen); return encoded;}// ### This function only encodes to numeric ampersand escapes,// ### we could use standard ampersand values as well.inline static QString escapeUnencodeable(const QTextCodec* codec, const QString& s) { QString enc_string; const int len = s.length(); for(int i=0; i <len; ++i) { const QChar c = s[i]; if (codec->canEncode(c)) enc_string.append(c); else { QString ampersandEscape; ampersandEscape.sprintf("&#%u;", c.unicode()); enc_string.append(ampersandEscape); } } return enc_string;}inline static QCString fixUpfromUnicode(const QTextCodec* codec, const QString& s){ QCString str = codec->fromUnicode(escapeUnencodeable(codec,s)); str.truncate(str.length()); return str;}QByteArray HTMLFormElementImpl::formData(bool& ok){#ifdef FORMS_DEBUG kdDebug( 6030 ) << "form: formData()" << endl;#endif QByteArray form_data(0); QCString enc_string = ""; // used for non-multipart data // find out the QTextcodec to use const QString str = m_acceptcharset.string(); const QChar space(' '); const unsigned int strLength = str.length(); for(unsigned int i=0; i < strLength; ++i) if(str[i].latin1() == ',') str[i] = space; const QStringList charsets = QStringList::split(' ', str); QTextCodec* codec = 0; KHTMLView *view = getDocument()->view(); { QStringList::ConstIterator it = charsets.begin(); const QStringList::ConstIterator itEnd = charsets.end(); for ( ; it != itEnd; ++it ) { QString enc = (*it); if(enc.contains("UNKNOWN")) { // use standard document encoding enc = "ISO 8859-1"; if(view && view->part()) enc = view->part()->encoding(); } if((codec = KGlobal::charsets()->codecForName(enc.latin1()))) break; } } if(!codec) codec = QTextCodec::codecForLocale(); // we need to map visual hebrew to logical hebrew, as the web // server alsways expects responses in logical ordering if ( codec->mibEnum() == 11 ) codec = QTextCodec::codecForMib( 85 ); m_encCharset = codec->name(); const unsigned int m_encCharsetLength = m_encCharset.length(); for(unsigned int i=0; i < m_encCharsetLength; ++i) m_encCharset[i] = m_encCharset[i].latin1() == ' ' ? QChar('-') : m_encCharset[i].lower(); QStringList fileUploads, fileNotUploads; for (QPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) { HTMLGenericFormElementImpl* const current = it.current(); khtml::encodingList lst; if (!current->disabled() && current->encoding(codec, lst, m_multipart)) { //kdDebug(6030) << "adding name '" << current->name().string() << "'" << endl; khtml::encodingList::ConstIterator it = lst.begin(); const khtml::encodingList::ConstIterator itEnd = lst.end(); for( it = lst.begin(); it != itEnd; ++it ) { if (!m_multipart) { // handle ISINDEX / <input name=isindex> special // but only if its the first entry if ( enc_string.isEmpty() && *it == "isindex" ) { ++it; enc_string += encodeCString( *it ); } else { if(!enc_string.isEmpty()) enc_string += '&'; enc_string += encodeCString(*it); enc_string += "="; ++it; enc_string += encodeCString(*it); } } else { QCString hstr("--"); hstr += m_boundary.latin1(); hstr += "\r\n"; hstr += "Content-Disposition: form-data; name=\""; hstr += (*it).data(); hstr += "\""; // if the current type is FILE, then we also need to // include the filename if (current->id() == ID_INPUT && static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::FILE && current->renderer()) { KURL path; QString val = static_cast<HTMLInputElementImpl*>(current)->value().string().stripWhiteSpace(); if (!val.isEmpty() && QDir::isRelativePath(val) && QFile::exists(KGlobalSettings::documentPath() + val)) { path.setPath(KGlobalSettings::documentPath() + val); } else { path = KURL::fromPathOrURL(val); } hstr += fixUpfromUnicode(codec, "; filename=\"" + path.fileName() + "\""); if (path.isValid()) { fileUploads << path.prettyURL(0, KURL::StripFileProtocol); const KMimeType::Ptr ptr = KMimeType::findByURL(path); if (!ptr->name().isEmpty()) { hstr += "\r\nContent-Type: "; hstr += ptr->name().ascii(); } } else if (!val.isEmpty()) { fileNotUploads << path.prettyURL(0, KURL::StripFileProtocol); } } hstr += "\r\n\r\n"; ++it; // append body const unsigned int old_size = form_data.size(); form_data.resize( old_size + hstr.length() + (*it).size() + 1); memcpy(form_data.data() + old_size, hstr.data(), hstr.length()); memcpy(form_data.data() + old_size + hstr.length(), *it, (*it).size()); form_data[form_data.size()-2] = '\r'; form_data[form_data.size()-1] = '\n'; // reset unsubmittedFormChange flag if (current->id() == ID_INPUT && static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::TEXT) static_cast<HTMLInputElementImpl*>(current)->setUnsubmittedFormChange(false); if (current->id() == ID_TEXTAREA) static_cast<HTMLTextAreaElementImpl*>(current)->setUnsubmittedFormChange(false); } } } } if (fileNotUploads.count()) { const int result = KMessageBox::warningContinueCancelList( 0, i18n("The following files will not be uploaded" " because they could not be found.\n" "Do you want to continue?"), fileNotUploads, i18n("Submit Confirmation"),KGuiItem(i18n("&Submit Anyway"))); if (result == KMessageBox::Cancel) { ok = false; return QByteArray(); } } if (fileUploads.count()) { const int result = KMessageBox::warningContinueCancelList( 0, i18n("You're about to transfer the following files from " "your local computer to the Internet.\n" "Do you really want to continue?"), fileUploads, i18n("Send Confirmation"),KGuiItem(i18n("&Send Files"))); if (result == KMessageBox::Cancel) { ok = false; return QByteArray(); } } if (m_multipart) enc_string = ("--" + m_boundary + "--\r\n").ascii(); const int old_size = form_data.size(); form_data.resize( form_data.size() + enc_string.length() ); memcpy(form_data.data() + old_size, enc_string.data(), enc_string.length() ); ok = true; return form_data;}void HTMLFormElementImpl::setEnctype( const DOMString& type ){ if(type.string().find("multipart", 0, false) != -1 || type.string().find("form-data", 0, false) != -1) { m_enctype = "multipart/form-data"; m_multipart = true; m_post = true; } else if (type.string().find("text", 0, false) != -1 || type.string().find("plain", 0, false) != -1) { m_enctype = "text/plain"; m_multipart = false; } else { m_enctype = "application/x-www-form-urlencoded"; m_multipart = false; } m_encCharset = QString::null;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -