⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 html_formimpl.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/*
 * 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)
 * Copyright (C) 2004 Apple Computer, Inc.
 *
 * 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.
 *
 */

#undef FORMS_DEBUG
//#define FORMS_DEBUG

#include "html/html_formimpl.h"

#include "khtmlview.h"
#include "khtml_part.h"
#include "html/html_documentimpl.h"
#include "html_imageimpl.h"
#include "khtml_settings.h"
#include "misc/htmlhashes.h"
#include "misc/formdata.h"

#include "css/cssstyleselector.h"
#include "css/cssproperties.h"
#include "css/csshelper.h"
#include "xml/dom_textimpl.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 <klocale.h>
#include <netaccess.h>
#include <kfileitem.h>
#include <qfile.h>
#include <qtextcodec.h>

// for keygen
#include <qstring.h>
#include <ksslkeygen.h>

#include <assert.h>

using namespace khtml;

namespace DOM {

struct FormDataListItem {
    FormDataListItem(const QCString &data) : m_data(data) { }
    FormDataListItem(const QString &path) : m_path(path) { }

    QString m_path;
    QCString m_data;
};

class FormDataList
OOM_MODIFIED
{
public:
    FormDataList(QTextCodec *);

    void appendData(const DOMString &key, const DOMString &value)
        { appendString(key.string()); appendString(value.string()); }
    void appendData(const DOMString &key, const QString &value)
        { appendString(key.string()); appendString(value); }
    void appendData(const DOMString &key, const QCString &value)
        { appendString(key.string()); appendString(value); }
    void appendData(const DOMString &key, int value)
        { appendString(key.string()); appendString(QString::number(value)); }
    void appendFile(const DOMString &key, const DOMString &filename);

    QValueListConstIterator<FormDataListItem> begin() const
        { return m_list.begin(); }
    QValueListConstIterator<FormDataListItem> end() const
        { return m_list.end(); }

private:
    void appendString(const QCString &s);
    void appendString(const QString &s);

    QTextCodec *m_codec;
    QValueList<FormDataListItem> m_list;
};

HTMLFormElementImpl::HTMLFormElementImpl(DocumentPtr *doc)
    : HTMLElementImpl(doc)
{
    collectionInfo = 0;
    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 = "----------0xKhTmLbOuNdArY";
    m_acceptcharset = "UNKNOWN";
    m_malformed = false;
}

HTMLFormElementImpl::~HTMLFormElementImpl()
{
    delete collectionInfo;

    for (unsigned i = 0; i < formElements.count(); ++i)
        formElements[i]->m_form = 0;
    for (unsigned i = 0; i < dormantFormElements.count(); ++i)
        dormantFormElements[i]->m_form = 0;
    for (unsigned i = 0; i < imgElements.count(); ++i)
        imgElements[i]->m_form = 0;
}

NodeImpl::Id HTMLFormElementImpl::id() const
{
    return ID_FORM;
}

#if APPLE_CHANGES

bool HTMLFormElementImpl::formWouldHaveSecureSubmission(const DOMString &url)
{
    if (url.isNull()) {
        return false;
    }
    return getDocument()->completeURL(url.string()).startsWith("https:", false);
}

#endif

void HTMLFormElementImpl::attach()
{
    HTMLElementImpl::attach();

    if (getDocument()->isHTMLDocument()) {
	HTMLDocumentImpl *document = static_cast<HTMLDocumentImpl *>(getDocument());
	document->addNamedImageOrForm(oldNameAttr);
	document->addNamedImageOrForm(oldIdAttr);
    }

#if APPLE_CHANGES
    // note we don't deal with calling secureFormRemoved() on detach, because the timing
    // was such that it cleared our state too early
    if (formWouldHaveSecureSubmission(m_url))
        getDocument()->secureFormAdded();
#endif
}

void HTMLFormElementImpl::detach()
{
    if (getDocument()->isHTMLDocument()) {
	HTMLDocumentImpl *document = static_cast<HTMLDocumentImpl *>(getDocument());
	document->removeNamedImageOrForm(oldNameAttr);
	document->removeNamedImageOrForm(oldIdAttr);
    }

    HTMLElementImpl::detach();
}

long HTMLFormElementImpl::length() const
{
    int len = 0;
    for (unsigned i = 0; i < formElements.count(); ++i)
	if (formElements[i]->isEnumeratable())
	    ++len;

    return len;
}

#if APPLE_CHANGES

void HTMLFormElementImpl::submitClick()
{
    bool submitFound = false;
    for (unsigned i = 0; i < formElements.count(); ++i) {
        if (formElements[i]->id() == ID_INPUT) {
            HTMLInputElementImpl *element = static_cast<HTMLInputElementImpl *>(formElements[i]);
            if (element->isSuccessfulSubmitButton() && element->renderer()) {
                submitFound = true;
                element->click(false);
                break;
            }
        }
    }
    if (!submitFound) // submit the form without a submit or image input
        prepareSubmit();
}

#endif // APPLE_CHANGES

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 = "-._*";
    int elen = e.length();
    QCString encoded(( elen+e.contains( '\n' ) )*3+1);
    int enclen = 0;

    //QCString orig(e.data(), e.size());

    for(int pos = 0; pos < elen; pos++) {
        unsigned char c = e[pos];

        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' || ( c == '\r' && e[pos+1] != '\n' ) )
        {
            encoded[enclen++] = '%';
            encoded[enclen++] = '0';
            encoded[enclen++] = 'D';
            encoded[enclen++] = '%';
            encoded[enclen++] = '0';
            encoded[enclen++] = 'A';
        }
        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;
}

// Change plain CR and plain LF to CRLF pairs.
static QCString fixLineBreaks(const QCString &s)
{
    // Compute the length.
    unsigned newLen = 0;
    const char *p = s.data();
    while (char c = *p++) {
        if (c == '\r') {
            // Safe to look ahead because of trailing '\0'.
            if (*p != '\n') {
                // Turn CR into CRLF.
                newLen += 2;
            }
        } else if (c == '\n') {
            // Turn LF into CRLF.
            newLen += 2;
        } else {
            // Leave other characters alone.
            newLen += 1;
        }
    }
    if (newLen == s.length()) {
        return s;
    }

    // Make a copy of the string.
    p = s.data();
    QCString result(newLen + 1);
    char *q = result.data();
    while (char c = *p++) {
        if (c == '\r') {
            // Safe to look ahead because of trailing '\0'.
            if (*p != '\n') {
                // Turn CR into CRLF.
                *q++ = '\r';
                *q++ = '\n';
            }
        } else if (c == '\n') {
            // Turn LF into CRLF.
            *q++ = '\r';
            *q++ = '\n';
        } else {
            // Leave other characters alone.
            *q++ = c;
        }
    }
    return result;
}

#if !APPLE_CHANGES

void HTMLFormElementImpl::i18nData()
{
    QString foo1 = i18n( "You're about to send data to the Internet "
                         "via an unencrypted connection. It might be possible "
                         "for others to see this information.\n"
                         "Do you want to continue?");
    QString foo2 = i18n("KDE Web browser");
    QString foo3 = i18n("When you send a password unencrypted to the Internet, "
                        "it might be possible for others to capture it as plain text.\n"
                        "Do you want to continue?");
    QString foo5 = i18n("Your data submission is redirected to "
                        "an insecure site. The data is sent unencrypted.\n"
                        "Do you want to continue?");
    QString foo6 = i18n("The page contents expired. You can repost the form"
                        "data by using <a href=\"javascript:go(0);\">Reload</a>");
}

#endif

bool HTMLFormElementImpl::formData(FormData &form_data) const
{
#ifdef FORMS_DEBUG
    kdDebug( 6030 ) << "form: formData()" << endl;
#endif

    QCString enc_string = ""; // used for non-multipart data

    // find out the QTextcodec to use
    QString str = m_acceptcharset.string();
    str.replace(',', ' ');
    QStringList charsets = QStringList::split(' ', str);
    QTextCodec* codec = 0;
    KHTMLPart *part = getDocument()->part();
    for ( QStringList::Iterator it = charsets.begin(); it != charsets.end(); ++it )
    {
        QString enc = (*it);
        if(enc.contains("UNKNOWN"))
        {
            // use standard document encoding
            enc = "ISO-8859-1";
            if (part)
                enc = part->encoding();
        }
        if((codec = KGlobal::charsets()->codecForName(enc.latin1())))
            break;
    }

    if(!codec)
        codec = QTextCodec::codecForLocale();

#if !APPLE_CHANGES
    QStringList fileUploads;
#endif

    for (unsigned i = 0; i < formElements.count(); ++i) {
        HTMLGenericFormElementImpl* current = formElements[i];
        FormDataList lst(codec);

        if (!current->disabled() && current->appendFormData(lst, m_multipart))
        {
            //kdDebug(6030) << "adding name " << current->name().string() << endl;
            for(QValueListConstIterator<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
                {
                    QCString hstr("--");
                    hstr += m_boundary.string().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->nodeType() == Node::ELEMENT_NODE && current->id() == ID_INPUT &&
                        static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::FILE)
                    {
                        QString path = static_cast<HTMLInputElementImpl*>(current)->value().string();
#if !APPLE_CHANGES
                        if (path.length()) fileUploads << path;
#endif

                        // 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 += codec->fromUnicode(path.mid(path.findRev('/') + 1));
                        hstr += "\"";

                        if(!static_cast<HTMLInputElementImpl*>(current)->value().isEmpty())
                        {
#if APPLE_CHANGES
                            QString mimeType = part ? KWQ(part)->mimeTypeForFileName(path) : QString();
#else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -