📄 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) * * 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., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * $Id: html_formimpl.cpp,v 1.3 2002/03/07 07:21:55 ymwei Exp $ */#undef FORMS_DEBUG#include "render_interface.h"#include "mghtmlview.h"#include "mghtml_part.h"#include "html_documentimpl.h"#include "htmlhashes.h"#include "cssstyleselector.h"#include "cssproperties.h"#include "dom_textimpl.h"#include "html_formimpl.h"#include "render_form.h"#include "kdebug.h"#include "qfile.h"#define DEBUG_BY_XHTANG 1using namespace DOM;using namespace khtml;//template class QList<khtml::RenderFormElement>;HTMLFormElementImpl::HTMLFormElementImpl(DocumentImpl *doc) : HTMLElementImpl(doc){ m_post = false; m_multipart = false; m_enctype = "application/x-www-form-urlencoded"; m_boundary = "----------0xKhTmLbOuNdArY";}HTMLFormElementImpl::~HTMLFormElementImpl(){ QListIterator<HTMLGenericFormElementImpl> it(formElements); for (; it.current(); ++it) it.current()->setForm(0);}ushort HTMLFormElementImpl::id() const{ return ID_FORM;}long HTMLFormElementImpl::length() const{ return formElements.count();}QCString HTMLFormElementImpl::encodeByteArray(const QByteArray& 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 = "-._*"; unsigned pos = 0; QCString encoded; while ( pos < e.size() ) { unsigned char c = e[pos]; if ( (( c >= 'A') && ( c <= 'Z')) || (( c >= 'a') && ( c <= 'z')) || (( c >= '0') && ( c <= '9')) || (strchr(safe, c)) ) encoded += c; else if ( c == ' ' ) encoded += '+'; else if ( c == '\n' ) encoded += "%0D%0A"; else if ( c != '\r' ) { encoded += '%'; unsigned int h = c / 16; h += (h > 9) ? ('A' - 10) : '0'; encoded += h; unsigned int l = c % 16; l += (l > 9) ? ('A' - 10) : '0'; encoded += l; } pos++; } return encoded;}QByteArray HTMLFormElementImpl::formData(){#ifdef FORMS_DEBUG kdDebug( 6030 ) << "form: formData()" << endl;#endif QByteArray form_data(0); bool first = true; QCString enc_string = ""; // used for non-multipart data HTMLGenericFormElementImpl *current = formElements.first(); for( ; current; current = formElements.next() ) { khtml::encodingList lst;#ifdef FORMS_DEBUG kdDebug(6030) << "checking " << current->name().string() << endl;#endif if (!current->disabled() && current->encoding(lst)) {#ifdef FORMS_DEBUG kdDebug(6030) << "adding name " << current->name().string() << endl;#endif khtml::encodingList::Iterator it; for( it = lst.begin(); it != lst.end(); ++it ) { QByteArray enc(*it);#ifdef FORMS_DEBUG kdDebug(6030) << "found data!" << endl;#endif if (!m_multipart) { if(!first) enc_string += '&'; // HACK HACK HACK HACK // ### encoding functions need to be able to submit more than // one name part as well for this case if(current->id() == ID_INPUT && static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::IMAGE) { HTMLInputElementImpl* i = static_cast<HTMLInputElementImpl*>(current); if(i->clickX() != -1) { QCString aStr; enc_string += HTMLFormElementImpl::encodeByteArray(QString(current->name().string() + ".x").local8Bit()); aStr.setNum(i->clickX()); enc_string += "="; enc_string += aStr; enc_string += "&"; enc_string += HTMLFormElementImpl::encodeByteArray(QString(current->name().string() + ".y").local8Bit()); enc_string += "="; aStr.setNum(i->clickY()); enc_string += aStr; } } else { enc_string += HTMLFormElementImpl::encodeByteArray(current->name().string().local8Bit()); enc_string += "="; enc_string += HTMLFormElementImpl::encodeByteArray(enc); } first = false; } else { QCString str(("--" + m_boundary.string() + "\r\n").ascii()); str += "Content-Disposition: form-data; "; str += ("name=\"" + current->name().string() + "\"").ascii(); // if the current type is FILE, then we also need to // include the filename *and* the file type if (current->nodeType() == Node::ELEMENT_NODE && current->id() == ID_INPUT && static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::FILE) { QString path = static_cast<HTMLInputElementImpl*>(current)->filename().string(); QString onlyfilename = path.mid(path.findRev('/')+1); str += ("; filename=\"" + onlyfilename + "\"\r\n").ascii(); if(!static_cast<HTMLInputElementImpl*>(current)->filename().isEmpty()) { str += "Content-Type: "; str += "text/plain";#if 0 KMimeType::Ptr ptr = KMimeType::findByURL(KURL(path)); str += ptr->name().ascii();#endif } } str += "\r\n\r\n"; // this is where it gets ugly.. we have to memcpy the // text part to the form.. then memcpy the (possibly // binary) data. yuck! unsigned int old_size = form_data.size(); form_data.resize( old_size + str.size() + enc.size()); memcpy(form_data.data() + old_size, str.data(), str.length()); memcpy(form_data.data() + old_size + str.length(), enc, enc.size()); form_data[form_data.size()-2] = '\r'; form_data[form_data.size()-1] = '\n'; } } } } if (m_multipart) enc_string = ("--" + m_boundary.string() + "--\r\n").ascii(); 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() ); return form_data;}void HTMLFormElementImpl::setEnctype( const DOMString& type ){ m_enctype = type; if ( strcasecmp( type, "multipart/form-data" ) == 0 ) m_multipart = true;}void HTMLFormElementImpl::setBoundary( const DOMString& bound ){ m_boundary = bound;}void HTMLFormElementImpl::prepareSubmit(){ if(!view) return; //del#if 0 DOMString script = getAttribute(ATTR_ONSUBMIT); if (!script.isNull() && view->part()->jScriptEnabled()) {#if 0 QVariant ret = view->part()->executeScript(Node(this), script.string()); if (ret.type() == QVariant::Bool && ret.toBool() == false) return; // don't submit if script returns false#else return;#endif }#endif#ifdef JAVASCRIPT_ENABLE DOMString script = getAttribute(ATTR_ONSUBMIT); if (!script.isNull() && view->part()->jScriptEnabled()) { bool ret = view->part()->executeScript(this, script.string()); if (ret == false) return; // don't submit if script returns false }#endif submit();}void HTMLFormElementImpl::submit(){#if DEBUG_BY_XHTANG// fprintf(stderr,"HTMLFormElementImpl::submit m_post:%d view:%p.\n",m_post,view);#endif#ifdef FORMS_DEBUG kdDebug( 6030 ) << "submit pressed!" << endl;#endif if(!view) return; QByteArray form_data = formData(); // formdata is not null-terminated, so this will cause Insure++ to scream // kdDebug( 6030 ) << "formdata = " << form_data.data() << endl << "m_post = " << m_post << endl << "multipart = " << m_multipart << endl; /* if(m_post) { view->part()->submitForm( "post", url.string(), form_data, target.string(), enctype().string(), boundary().string() ); } else view->part()->submitForm( "get", url.string(), form_data, target.string() ); */ if(m_post) { view->part()->submitForm( "post", url.string(), form_data, target.string(), enctype().string(), boundary().string() ); } else// view->part()->submitForm( "get", url.string(), form_data,target.string() );// following is changed view->part()->submitForm( "get", url.string(), form_data,target.string(), (QString)"", (QString)"");}void HTMLFormElementImpl::reset( ){#ifdef FORMS_DEBUG kdDebug( 6030 ) << "reset pressed!" << endl;#endif #ifdef JAVASCRIPT_ENABLE DOMString script = getAttribute(ATTR_ONRESET); if (!script.isNull() && view->part()->jScriptEnabled()) // view->part()->executeScript(Node(this), script.string()); view->part()->executeScript((HTMLElementImpl*)this, script.string());#endif HTMLGenericFormElementImpl *current = formElements.first(); while(current) { current->reset(); current = formElements.next(); } if (document->isHTMLDocument()) static_cast<HTMLDocumentImpl*>(document)->updateRendering();}void HTMLFormElementImpl::parseAttribute(AttrImpl *attr){ switch(attr->attrId) { case ATTR_ACTION: url = attr->value(); break; case ATTR_TARGET: target = attr->value(); break; case ATTR_METHOD: if ( strcasecmp( attr->value(), "post" ) == 0 ) m_post = true; break; case ATTR_ENCTYPE: setEnctype( attr->value() ); break; case ATTR_ACCEPT_CHARSET: case ATTR_ACCEPT: // ignore these for the moment... break; default: HTMLElementImpl::parseAttribute(attr); }}void HTMLFormElementImpl::attach(MGHTMLView *_view){ view = _view; HTMLElementImpl::attach(_view);}void HTMLFormElementImpl::detach(){ view = 0; HTMLElementImpl::detach();}void HTMLFormElementImpl::radioClicked( HTMLGenericFormElementImpl *caller ){ HTMLGenericFormElementImpl *current; for (current = formElements.first(); current; current = formElements.next()) { if (current->id() == ID_INPUT && static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::RADIO && current != caller && current->name() == caller->name()) { static_cast<HTMLInputElementImpl*>(current)->setChecked(false); } }}void HTMLFormElementImpl::maybeSubmit(){ if(!view) return; int le = 0; int total = 0; // count number of LineEdits / total number HTMLGenericFormElementImpl *current; for (current = formElements.first(); current; current = formElements.next()) { if (!current->disabled() && !current->readOnly()) { if (current->id() == ID_INPUT && (static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::TEXT || static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::PASSWORD)) le++; // we're not counting hidden input's here, as they're not enabled (### check this) total++; } } // if there's only one lineedit or only one possibly successful one, submit if (le < 2 || total < 2) prepareSubmit();}void HTMLFormElementImpl::registerFormElement(HTMLGenericFormElementImpl *e){ formElements.append(e);}void HTMLFormElementImpl::removeFormElement(HTMLGenericFormElementImpl *e){ // ### make sure this get's called, when formElements get removed from // the document tree formElements.remove(e);}// -------------------------------------------------------------------------HTMLGenericFormElementImpl::HTMLGenericFormElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f) : HTMLElementImpl(doc){ _form = f; if (_form) _form->registerFormElement(this); view = 0; m_disabled = m_readOnly = false;}HTMLGenericFormElementImpl::HTMLGenericFormElementImpl(DocumentImpl *doc) : HTMLElementImpl(doc){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -