/*
    Copyright (C) 2006 Enrico Ros <enrico.ros@m31engineering.it>
    Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
    Copyright (C) 2007 Staikos Computing Services Inc.  <info@staikos.net>

    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 <qglobal.h>
#if QT_VERSION < 0x040400
#include "qwebframe.h"
#include "qwebnetworkinterface.h"
#include "qwebnetworkinterface_p.h"
#include "qwebpage.h"
#include "qcookiejar.h"
#include <qdebug.h>
#include <qfile.h>
#include <qnetworkproxy.h>
#include <qurl.h>
#include <QAuthenticator>
#include <QCoreApplication>
#include <QSslError>

#include "ResourceHandle.h"
#include "ResourceHandleClient.h"
#include "ResourceHandleInternal.h"
#include "MIMETypeRegistry.h"
#include "CookieJar.h"

#if 0
#define DEBUG qDebug
#else
#define DEBUG if (1) {} else qDebug
#endif

static QWebNetworkInterface *s_default_interface = 0;
static QWebNetworkManager *s_manager = 0;

using namespace WebCore;

uint qHash(const HostInfo &info)
{
    return qHash(info.host) + info.port;
}

static bool operator==(const HostInfo &i1, const HostInfo &i2)
{
    return i1.port == i2.port && i1.host == i2.host;
}

enum ParserState {
    State_Begin,
    State_FirstChar,
    State_SecondChar
};

/*
 * Decode URLs without doing any charset conversion.
 *
 * Most simple approach to do it without any lookahead.
 */
static QByteArray decodePercentEncoding(const QByteArray& input)
{
    int actualLength = 0;
    QByteArray tmpVal;
    QByteArray output;
    ParserState state = State_Begin;

    output.resize(input.length());
    tmpVal.resize(2);

    for (int i = 0; i < input.length(); ++i)
        if (state == State_Begin) {
            if (input.at(i) == '%') {
                state = State_FirstChar;
            } else {
                output[actualLength++] = input[i];
            }
        } else if (state == State_FirstChar) {
            state = State_SecondChar;
            tmpVal[0] = input[i];
        } else if (state == State_SecondChar) {
            state = State_Begin;
            tmpVal[1] = input[i];
            output[actualLength++] = tmpVal.toShort(0, 16);
        }

    output.resize(actualLength);
    return output;
}

void QWebNetworkRequestPrivate::init(const WebCore::ResourceRequest &resourceRequest)
{
    KURL url = resourceRequest.url();
    QUrl qurl = QString(url.string());
    init(resourceRequest.httpMethod(), qurl, &resourceRequest);
}

void QWebNetworkRequestPrivate::init(const QString &method, const QUrl &url, const WebCore::ResourceRequest *resourceRequest)
{
    httpHeader = QHttpRequestHeader(method, url.toString(QUrl::RemoveScheme|QUrl::RemoveAuthority));
    httpHeader.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive"));
    setURL(url);

    if (resourceRequest) {
        httpHeader.setValue(QLatin1String("User-Agent"), resourceRequest->httpUserAgent());
        const QString scheme = url.scheme().toLower();
        if (scheme == QLatin1String("http") || scheme == QLatin1String("https")) {
            QString cookies = QCookieJar::cookieJar()->cookies(resourceRequest->url());
            if (!cookies.isEmpty())
                httpHeader.setValue(QLatin1String("Cookie"), cookies);
        }


        const HTTPHeaderMap& loaderHeaders = resourceRequest->httpHeaderFields();
        HTTPHeaderMap::const_iterator end = loaderHeaders.end();
        for (HTTPHeaderMap::const_iterator it = loaderHeaders.begin(); it != end; ++it)
            httpHeader.setValue(it->first, it->second);

        // handle and perform a 'POST' request
        if (method == "POST") {
            Vector<char> data;
            resourceRequest->httpBody()->flatten(data);
            postData = QByteArray(data.data(), data.size());
            httpHeader.setValue(QLatin1String("content-length"), QString::number(postData.size()));
        }
    }
}

void QWebNetworkRequestPrivate::setURL(const QUrl &u)
{
    url = u;
    int port = url.port();
    const QString scheme = u.scheme();
    if (port > 0 && (port != 80 || scheme != "http") && (port != 443 || scheme != "https"))
        httpHeader.setValue(QLatin1String("Host"), url.host() + QLatin1Char(':') + QString::number(port));
    else
        httpHeader.setValue(QLatin1String("Host"), url.host());
}

/*!
  \class QWebNetworkRequest

  The QWebNetworkRequest class represents a request for data from the network with all the
  necessary information needed for retrieval. This includes the url, extra HTTP header fields
  as well as data for a HTTP POST request.
*/

QWebNetworkRequest::QWebNetworkRequest()
    : d(new QWebNetworkRequestPrivate)
{
}

QWebNetworkRequest::QWebNetworkRequest(const QUrl &url, Method method, const QByteArray &postData)
    : d(new QWebNetworkRequestPrivate)
{
    d->init(method == Get ? "GET" : "POST", url);
    d->postData = postData;
}

QWebNetworkRequest::QWebNetworkRequest(const QWebNetworkRequest &other)
    : d(new QWebNetworkRequestPrivate(*other.d))
{
}

QWebNetworkRequest &QWebNetworkRequest::operator=(const QWebNetworkRequest &other)
{
    *d = *other.d;
    return *this;
}

/*!
  \internal
*/
QWebNetworkRequest::QWebNetworkRequest(const QWebNetworkRequestPrivate &priv)
    : d(new QWebNetworkRequestPrivate(priv))
{
}

/*!
  \internal
*/
QWebNetworkRequest::QWebNetworkRequest(const WebCore::ResourceRequest &request)
    : d(new QWebNetworkRequestPrivate)
{
    d->init(request);
}

QWebNetworkRequest::~QWebNetworkRequest()
{
    delete d;
}

/*!
  The requested URL
*/
QUrl QWebNetworkRequest::url() const
{
    return d->url;
}

/*!
   Sets the URL to request.

   Note that setting the URL also sets the "Host" field in the HTTP header.
*/
void QWebNetworkRequest::setUrl(const QUrl &url)
{
    d->setURL(url);
}

/*!
   The http request header information.
*/
QHttpRequestHeader QWebNetworkRequest::httpHeader() const
{
    return d->httpHeader;
}

void QWebNetworkRequest::setHttpHeader(const QHttpRequestHeader &header) const
{
    d->httpHeader = header;
}

QString QWebNetworkRequest::httpHeaderField(const QString &key) const
{
    return d->httpHeader.value(key);
}

void QWebNetworkRequest::setHttpHeaderField(const QString &key, const QString &value)
{
    d->httpHeader.setValue(key, value);
}

/*!
    Post data sent with HTTP POST requests.
*/
QByteArray QWebNetworkRequest::postData() const
{
    return d->postData;
}

void QWebNetworkRequest::setPostData(const QByteArray &data)
{
    d->postData = data;
}

/*!
  \class QWebNetworkJob

  The QWebNetworkJob class represents a network job, that needs to be
  processed by the QWebNetworkInterface.

  This class is only required when implementing a new network layer (or
  support for a special protocol) using QWebNetworkInterface.

  QWebNetworkJob objects are created and owned by the QtWebKit library.
  Most of it's properties are read-only.

  The job is reference counted. This can be used to ensure that the job doesn't
  get deleted while it's still stored in some data structure.
*/

/*!
  \internal
*/
QWebNetworkJob::QWebNetworkJob()
    : d(new QWebNetworkJobPrivate)
{
}

/*!
  \internal
*/
QWebNetworkJob::~QWebNetworkJob()
{
    delete d;
    d = 0;
}

/*!
  The requested URL
*/
QUrl QWebNetworkJob::url() const
{
    return d->request.url;
}

/*!
  Post data associated with the job
*/
QByteArray QWebNetworkJob::postData() const
{
    return d->request.postData;
}

/*!
  The HTTP request header that should be used to download the job.
*/
QHttpRequestHeader QWebNetworkJob::httpHeader() const
{
    return d->request.httpHeader;
}

/*!
  The complete network request that should be used to download the job.
*/
QWebNetworkRequest QWebNetworkJob::request() const
{
    return QWebNetworkRequest(d->request);
}

/*!
  The HTTP response header received from the network.
*/
QHttpResponseHeader QWebNetworkJob::response() const
{
    return d->response;
}

/*!
  The last error of the Job.
*/
QString QWebNetworkJob::errorString() const
{
    return d->errorString;
}

/*!
  Sets the HTTP reponse header. The response header has to be called before
  emitting QWebNetworkInterface::started.
*/
void QWebNetworkJob::setResponse(const QHttpResponseHeader &response)
{
    d->response = response;
}

void QWebNetworkJob::setErrorString(const QString& errorString)
{
    d->errorString = errorString;
}

/*!
  returns true if the job has been cancelled by the WebKit framework
*/
bool QWebNetworkJob::cancelled() const
{
    return !d->resourceHandle;
}

/*!
  reference the job.
*/
void QWebNetworkJob::ref()
{
    ++d->ref;
}

/*!
  derefence the job.

  If the reference count drops to 0 this method also deletes the job.

  Returns false if the reference count has dropped to 0.
*/
bool QWebNetworkJob::deref()
{
    if (!--d->ref) {
        delete this;
        return false;
    }
    return true;
}

/*!
   Returns the network interface that is associated with this job.
*/
QWebNetworkInterface *QWebNetworkJob::networkInterface() const
{
    return d->interface;
}

/*!
   Returns the network interface that is associated with this job.
*/
QWebFrame *QWebNetworkJob::frame() const
{
    if (d->resourceHandle) {
        ResourceHandleInternal *rhi = d->resourceHandle->getInternal();
        if (rhi) {
            return rhi->m_frame;
        }
    }
    return 0;
}

QWebNetworkJob::JobStatus QWebNetworkJob::status() const
{
    return d->jobStatus;
}

void QWebNetworkJob::setStatus(const JobStatus& status)
{
    d->jobStatus = status;
}

/*!
  \class QWebNetworkManager
  \internal
*/
QWebNetworkManager::QWebNetworkManager()
    : QObject(0)
    , m_scheduledWork(false)
{
    connect(this, SIGNAL(scheduleWork()), SLOT(doWork()), Qt::QueuedConnection);
}

QWebNetworkManager *QWebNetworkManager::self()
{
    // ensure everything's constructed and connected
    QWebNetworkInterface::defaultInterface();

    return s_manager;
}

bool QWebNetworkManager::add(ResourceHandle *handle, QWebNetworkInterface *interface, JobMode jobMode)
{
    if (!interface)
        interface = s_default_interface;

    ASSERT(interface);

    QWebNetworkJob *job = new QWebNetworkJob();
    handle->getInternal()->m_job = job;
    job->d->resourceHandle = handle;
    job->d->interface = interface;

    job->d->request.init(handle->request());

    const QString method = handle->getInternal()->m_request.httpMethod();
    if (method != "POST" && method != "GET" && method != "HEAD") {
        qWarning("REQUEST: [%s]\n", qPrintable(job->d->request.httpHeader.toString()));
        return false;
    }

    DEBUG() << "QWebNetworkManager::add:" <<  job->d->request.httpHeader.toString();

    if (jobMode == SynchronousJob) {
        Q_ASSERT(!m_synchronousJobs.contains(job));
        m_synchronousJobs[job] = 1;
    }

    interface->addJob(job);

    return true;
}

void QWebNetworkManager::cancel(ResourceHandle *handle)
{
    QWebNetworkJob *job = handle->getInternal()->m_job;
    if (!job)
        return;
    DEBUG() << "QWebNetworkManager::cancel:" <<  job->d->request.httpHeader.toString();
    job->d->resourceHandle = 0;
    job->d->interface->cancelJob(job);
    handle->getInternal()->m_job = 0;
}

void QWebNetworkManager::started(QWebNetworkJob *job)
{
    Q_ASSERT(job->d);
    Q_ASSERT(job->status() == QWebNetworkJob::JobCreated ||
             job->status() == QWebNetworkJob::JobRecreated);

    job->setStatus(QWebNetworkJob::JobStarted);
    ResourceHandleClient* client = 0;
    if (job->d->resourceHandle) {
        client = job->d->resourceHandle->client();
        if (!client)
            return;
    } else {
        return;
    }

    DEBUG() << "ResourceHandleManager::receivedResponse:";
    DEBUG() << job->d->response.toString();

    QStringList cookies = job->d->response.allValues("Set-Cookie");
    KURL url(job->url());
    foreach (QString c, cookies) {
        QCookieJar::cookieJar()->setCookies(url, url, c);
    }
    QString contentType = job->d->response.value("Content-Type");
    QString encoding;
    int idx = contentType.indexOf(QLatin1Char(';'));
    if (idx > 0) {
        QString remainder = contentType.mid(idx + 1).toLower();
        contentType = contentType.left(idx).trimmed();

        idx = remainder.indexOf("charset");
        if (idx >= 0) {
            idx = remainder.indexOf(QLatin1Char('='), idx);
            if (idx >= 0)
                encoding = remainder.mid(idx + 1).trimmed();
        }
    }
    if (contentType.isEmpty()) {
        // let's try to guess from the extension
        QString extension = job->d->request.url.path();
        int index = extension.lastIndexOf(QLatin1Char('.'));
        if (index > 0) {
            extension = extension.mid(index + 1);
            contentType = MIMETypeRegistry::getMIMETypeForExtension(extension);
        }
    }
//     qDebug() << "Content-Type=" << contentType;
//     qDebug() << "Encoding=" << encoding;


    ResourceResponse response(url, contentType,
                              0 /* FIXME */,
                              encoding,
                              String() /* FIXME */);

    int statusCode = job->d->response.statusCode();
    if (job->url().scheme() != QLatin1String("file"))
        response.setHTTPStatusCode(statusCode);
    else if (statusCode == 404)
        response.setHTTPStatusCode(statusCode);

    /* Fill in the other fields */

    if (statusCode >= 300 && statusCode < 400) {
        // we're on a redirect page! if the 'Location:' field is valid, we redirect
        QString location = job->d->response.value("location");
        DEBUG() << "Redirection";
        if (!location.isEmpty()) {
            QUrl newUrl = job->d->request.url.resolved(location);
            if (job->d->resourceHandle) {
                ResourceRequest newRequest = job->d->resourceHandle->request();
                newRequest.setURL(KURL(newUrl));
                if (client)
                    client->willSendRequest(job->d->resourceHandle, newRequest, response);
            }

            QString method;
            if (statusCode == 302 || statusCode == 303) {
                // this is standard-correct for 303 and practically-correct (no standard-correct) for 302
                // also, it's required for Yahoo's login process for flickr.com which responds to a POST
                // with a 302 which must be GET'ed
                method = "GET";
                job->d->request.httpHeader.setContentLength(0);
            } else {
                method = job->d->request.httpHeader.method();
            }
            job->d->request.httpHeader.setRequest(method,
                                                  newUrl.toString(QUrl::RemoveScheme|QUrl::RemoveAuthority));
            job->d->request.setURL(newUrl);
            job->d->redirected = true;
            return;
        }
    }

    if (client)
        client->didReceiveResponse(job->d->resourceHandle, response);

}

void QWebNetworkManager::data(QWebNetworkJob *job, const QByteArray &data)
{
    Q_ASSERT(job->status() == QWebNetworkJob::JobStarted ||
             job->status() == QWebNetworkJob::JobReceivingData);

    job->setStatus(QWebNetworkJob::JobReceivingData);
    ResourceHandleClient* client = 0;
    if (job->d->resourceHandle) {
        client = job->d->resourceHandle->client();
        if (!client)
            return;
    } else {
        return;
    }

    if (job->d->redirected)
        return; // don't emit the "Document has moved here" type of HTML

    DEBUG() << "receivedData" << job->d->request.url.path();
    if (client)
        client->didReceiveData(job->d->resourceHandle, data.constData(), data.length(), data.length() /*FixMe*/);

}

void QWebNetworkManager::finished(QWebNetworkJob *job, int errorCode)
{
    Q_ASSERT(errorCode == 1 ||
             job->status() == QWebNetworkJob::JobStarted ||
             job->status() == QWebNetworkJob::JobReceivingData);

    if (m_synchronousJobs.contains(job))
        m_synchronousJobs.remove(job);

    job->setStatus(QWebNetworkJob::JobFinished);
    ResourceHandleClient* client = 0;
    if (job->d->resourceHandle) {
        client = job->d->resourceHandle->client();
        if (!client)
            return;
    } else {
        job->deref();
        return;
    }

    DEBUG() << "receivedFinished" << errorCode << job->url();

    if (job->d->redirected) {
        job->d->redirected = false;
        job->setStatus(QWebNetworkJob::JobRecreated);
        job->d->interface->addJob(job);
        return;
    }

    if (job->d->resourceHandle)
        job->d->resourceHandle->getInternal()->m_job = 0;

    if (client) {
        if (errorCode) {
            //FIXME: error setting error was removed from ResourceHandle
            client->didFail(job->d->resourceHandle,
                            ResourceError(job->d->request.url.host(), job->d->response.statusCode(),
                                          job->d->request.url.toString(), job->d->errorString));
        } else {
            client->didFinishLoading(job->d->resourceHandle);
        }
    }

    DEBUG() << "receivedFinished done" << job->d->request.url;

    job->deref();
}

void QWebNetworkManager::addHttpJob(QWebNetworkJob *job)
{
    HostInfo hostInfo(job->url());
    WebCoreHttp *httpConnection = m_hostMapping.value(hostInfo);
    if (!httpConnection) {
        // #### fix custom ports
        DEBUG() << "   new connection to" << hostInfo.host << hostInfo.port;
        httpConnection = new WebCoreHttp(this, hostInfo);
        QObject::connect(httpConnection, SIGNAL(connectionClosed(const WebCore::HostInfo&)),
                         this, SLOT(httpConnectionClosed(const WebCore::HostInfo&)));

        m_hostMapping[hostInfo] = httpConnection;
    }
    httpConnection->request(job);
}

void QWebNetworkManager::cancelHttpJob(QWebNetworkJob *job)
{
    WebCoreHttp *httpConnection = m_hostMapping.value(job->url());
    if (httpConnection)
        httpConnection->cancel(job);
}

void QWebNetworkManager::httpConnectionClosed(const WebCore::HostInfo &info)
{
    WebCoreHttp *connection = m_hostMapping.take(info);
    connection->deleteLater();
}

void QWebNetworkInterfacePrivate::sendFileData(QWebNetworkJob* job, int statusCode, const QByteArray &data)
{
    int error = statusCode >= 400 ? 1 : 0;
    if (!job->cancelled()) {
        QHttpResponseHeader response;
        response.setStatusLine(statusCode);
        response.setContentLength(data.length());
        job->setResponse(response);
        q->started(job);
        if (!data.isEmpty())
            q->data(job, data);
    }
    q->finished(job, error);
}

void QWebNetworkInterfacePrivate::parseDataUrl(QWebNetworkJob* job)
{
    QByteArray data = job->url().toString().toLatin1();
    //qDebug() << "handling data url:" << data;

    ASSERT(data.startsWith("data:"));

    // Here's the syntax of data URLs:
    // dataurl    := "data:" [ mediatype ] [ ";base64" ] "," data
    // mediatype  := [ type "/" subtype ] *( ";" parameter )
    // data       := *urlchar
    // parameter  := attribute "=" value
    QByteArray header;
    bool base64 = false;

    int index = data.indexOf(',');
    if (index != -1) {
        header = data.mid(5, index - 5).toLower();
        //qDebug() << "header=" << header;
        data = data.mid(index+1);
        //qDebug() << "data=" << data;

        if (header.endsWith(";base64")) {
            //qDebug() << "base64";
            base64 = true;
            header = header.left(header.length() - 7);
            //qDebug() << "mime=" << header;
        }
    } else {
        data = QByteArray();
    }

    if (base64) {
        data = QByteArray::fromBase64(data);
    } else {
        data = decodePercentEncoding(data);
    }

    if (header.isEmpty())
        header = "text/plain;charset=US-ASCII";
    int statusCode = 200;
    QHttpResponseHeader response;
    response.setContentType(header);
    response.setContentLength(data.size());
    job->setResponse(response);

    int error = statusCode >= 400 ? 1 : 0;
    q->started(job);
    if (!data.isEmpty())
        q->data(job, data);
    q->finished(job, error);
}

void QWebNetworkManager::queueStart(QWebNetworkJob* job)
{
    Q_ASSERT(job->d);

    QMutexLocker locker(&m_queueMutex);
    job->ref();
    m_pendingWork.append(new JobWork(job));
    doScheduleWork();
}

void QWebNetworkManager::queueData(QWebNetworkJob* job, const QByteArray& data)
{
    ASSERT(job->d);

    QMutexLocker locker(&m_queueMutex);
    job->ref();
    m_pendingWork.append(new JobWork(job, data));
    doScheduleWork();
}

void QWebNetworkManager::queueFinished(QWebNetworkJob* job, int errorCode)
{
    Q_ASSERT(job->d);

    QMutexLocker locker(&m_queueMutex);
    job->ref();
    m_pendingWork.append(new JobWork(job, errorCode));
    doScheduleWork();
}

void QWebNetworkManager::doScheduleWork()
{
    if (!m_scheduledWork) {
        m_scheduledWork = true;
        emit scheduleWork();
    }
}


/*
 * We will work on a copy of m_pendingWork. While dispatching m_pendingWork
 * new work will be added that will be handled at a later doWork call. doWork
 * will be called we set m_scheduledWork to false early in this method.
 */
void QWebNetworkManager::doWork()
{
    m_queueMutex.lock();
    m_scheduledWork = false;
    bool hasSyncJobs = m_synchronousJobs.size();
    const QHash<QWebNetworkJob*, int> syncJobs = m_synchronousJobs;
    m_queueMutex.unlock();

    foreach (JobWork* work, m_pendingWork) {
        if (hasSyncJobs && !syncJobs.contains(work->job))
            continue;

        if (work->workType == JobWork::JobStarted)
            started(work->job);
        else if (work->workType == JobWork::JobData) {
            // This job was not yet started
            if (static_cast<int>(work->job->status()) < QWebNetworkJob::JobStarted)
                continue;

            data(work->job, work->data);
        } else if (work->workType == JobWork::JobFinished) {
            // This job was not yet started... we have no idea if data comes by...
            // and it won't start in case of errors
            if (static_cast<int>(work->job->status()) < QWebNetworkJob::JobStarted && work->errorCode != 1)
                continue;

            finished(work->job, work->errorCode);
        }

        m_queueMutex.lock();
        m_pendingWork.removeAll(work);
        m_queueMutex.unlock();

        work->job->deref();
        delete work;
    }

    m_queueMutex.lock();
    if (hasSyncJobs && m_synchronousJobs.size() == 0)
        doScheduleWork();
    m_queueMutex.unlock();
}

/*!
  \class QWebNetworkInterface

  The QWebNetworkInterface class provides an abstraction layer for
  WebKit's network interface.  It allows to completely replace or
  extend the builtin network layer.

  QWebNetworkInterface contains two virtual methods, addJob and
  cancelJob that have to be reimplemented when implementing your own
  networking layer.

  QWebNetworkInterface can by default handle the http, https, file and
  data URI protocols.

*/

static bool gRoutineAdded = false;

static void gCleanupInterface()
{
    delete s_default_interface;
    s_default_interface = 0;
}

/*!
  Sets a new default interface that will be used by all of WebKit
  for downloading data from the internet.
*/
void QWebNetworkInterface::setDefaultInterface(QWebNetworkInterface *defaultInterface)
{
    if (s_default_interface == defaultInterface)
        return;
    if (s_default_interface)
        delete s_default_interface;
    s_default_interface = defaultInterface;
    if (!gRoutineAdded) {
        qAddPostRoutine(gCleanupInterface);
        gRoutineAdded = true;
    }
}

/*!
  Returns the default interface that will be used by WebKit. If no
  default interface has been set, QtWebkit will create an instance of
  QWebNetworkInterface to do the work.
*/
QWebNetworkInterface *QWebNetworkInterface::defaultInterface()
{
    if (!s_default_interface) {
        setDefaultInterface(new QWebNetworkInterface);
    }
    return s_default_interface;
}


/*!
  Constructs a QWebNetworkInterface object.
*/
QWebNetworkInterface::QWebNetworkInterface(QObject *parent)
    : QObject(parent)
{
    d = new QWebNetworkInterfacePrivate;
    d->q = this;

    if (!s_manager)
        s_manager = new QWebNetworkManager;
}

/*!
  Destructs the QWebNetworkInterface object.
*/
QWebNetworkInterface::~QWebNetworkInterface()
{
    delete d;
}

/*!
  This virtual method gets called whenever QtWebkit needs to add a
  new job to download.

  The QWebNetworkInterface should process this job, by first emitting
  the started signal, then emitting data repeatedly as new data for
  the Job is available, and finally ending the job with emitting a
  finished signal.

  After the finished signal has been emitted, the QWebNetworkInterface
  is not allowed to access the job anymore.
*/
void QWebNetworkInterface::addJob(QWebNetworkJob *job)
{
    QString protocol = job->url().scheme();
    if (protocol == QLatin1String("http") || protocol == QLatin1String("https")) {
        QWebNetworkManager::self()->addHttpJob(job);
        return;
    }

    // "file", "data" and all unhandled stuff go through here
    //DEBUG() << "fileRequest";
    DEBUG() << "FileLoader::request" << job->url();

    if (job->cancelled()) {
        d->sendFileData(job, 400, QByteArray());
        return;
    }

    QUrl url = job->url();
    if (protocol == QLatin1String("data")) {
        d->parseDataUrl(job);
        return;
    }

    int statusCode = 200;
    QByteArray data;
    QString path = url.path();
    if (protocol == QLatin1String("qrc")) {
        protocol = "file";
        path.prepend(QLatin1Char(':'));
    }

    if (!(protocol.isEmpty() || protocol == QLatin1String("file"))) {
        statusCode = 404;
    } else {
        // we simply ignore post data here.
        QFile f(path);
        DEBUG() << "opening" << QString(url.path());

        if (f.open(QIODevice::ReadOnly)) {
            QHttpResponseHeader response;
            response.setStatusLine(200);
            job->setResponse(response);
            data = f.readAll();
        } else {
            statusCode = 404;
        }
    }

    if (statusCode == 404) {
        QHttpResponseHeader response;
        response.setStatusLine(404);
        job->setResponse(response);
    }

    d->sendFileData(job, statusCode, data);
}

/*!
  This virtual method gets called whenever QtWebkit needs to cancel a
  new job.

  The QWebNetworkInterface acknowledge the canceling of the job, by
  emitting the finished signal with an error code of 1. After emitting
  the finished signal, the interface should not access the job
  anymore.
*/
void QWebNetworkInterface::cancelJob(QWebNetworkJob *job)
{
    QString protocol = job->url().scheme();
    if (protocol == QLatin1String("http") || protocol == QLatin1String("https"))
        QWebNetworkManager::self()->cancelHttpJob(job);
}

void QWebNetworkInterface::started(QWebNetworkJob* job)
{
    Q_ASSERT(s_manager);
    s_manager->queueStart(job);
}

void QWebNetworkInterface::data(QWebNetworkJob* job, const QByteArray& data)
{
    Q_ASSERT(s_manager);
    s_manager->queueData(job, data);
}

void QWebNetworkInterface::finished(QWebNetworkJob* job, int errorCode)
{
    Q_ASSERT(s_manager);
    s_manager->queueFinished(job, errorCode);
}

/////////////////////////////////////////////////////////////////////////////
WebCoreHttp::WebCoreHttp(QObject* parent, const HostInfo &hi)
    : QObject(parent), info(hi),
      m_inCancel(false)
{
    for (int i = 0; i < 2; ++i) {
        connection[i].http = new QHttp(info.host, (hi.protocol == QLatin1String("https")) ? QHttp::ConnectionModeHttps : QHttp::ConnectionModeHttp, info.port);
        connect(connection[i].http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader&)),
                this, SLOT(onResponseHeaderReceived(const QHttpResponseHeader&)));
        connect(connection[i].http, SIGNAL(readyRead(const QHttpResponseHeader&)),
                this, SLOT(onReadyRead()));
        connect(connection[i].http, SIGNAL(requestFinished(int, bool)),
                this, SLOT(onRequestFinished(int, bool)));
        connect(connection[i].http, SIGNAL(done(bool)),
                this, SLOT(onDone(bool)));
        connect(connection[i].http, SIGNAL(stateChanged(int)),
                this, SLOT(onStateChanged(int)));
        connect(connection[i].http, SIGNAL(authenticationRequired(const QString&, quint16, QAuthenticator*)),
                this, SLOT(onAuthenticationRequired(const QString&, quint16, QAuthenticator*)));
        connect(connection[i].http, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
                this, SLOT(onProxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)));
        connect(connection[i].http, SIGNAL(sslErrors(const QList<QSslError>&)),
                this, SLOT(onSslErrors(const QList<QSslError>&)));
    }
}

WebCoreHttp::~WebCoreHttp()
{
    connection[0].http->deleteLater();
    connection[1].http->deleteLater();
}

void WebCoreHttp::request(QWebNetworkJob *job)
{
    m_pendingRequests.append(job);
    scheduleNextRequest();
}

void WebCoreHttp::scheduleNextRequest()
{
    int c = 0;
    for (; c < 2; ++c) {
        if (!connection[c].current)
            break;
    }
    if (c >= 2)
        return;

    QWebNetworkJob *job = 0;
    while (!job && !m_pendingRequests.isEmpty()) {
        job = m_pendingRequests.takeFirst();
        if (job->cancelled()) {
            job->networkInterface()->finished(job, 1);
            job = 0;
        }
    }
    if (!job)
        return;

    QHttp *http = connection[c].http;

    connection[c].current = job;
    connection[c].id = -1;
#ifndef QT_NO_NETWORKPROXY
    int proxyId = http->setProxy(job->frame()->page()->networkProxy());
#endif

    QByteArray postData = job->postData();
    if (!postData.isEmpty())
        connection[c].id = http->request(job->httpHeader(), postData);
    else
        connection[c].id = http->request(job->httpHeader());

    DEBUG() << "WebCoreHttp::scheduleNextRequest: using connection" << c;
    DEBUG() << job->httpHeader().toString();
//     DEBUG() << job->request.toString();
}

int WebCoreHttp::getConnection()
{
    QObject *o = sender();
    int c;
    if (o == connection[0].http) {
        c = 0;
    } else {
        Q_ASSERT(o == connection[1].http);
        c = 1;
    }
    Q_ASSERT(connection[c].current);
    return c;
}

void WebCoreHttp::onResponseHeaderReceived(const QHttpResponseHeader &resp)
{
    QHttp *http = qobject_cast<QHttp*>(sender());
    if (http->currentId() == 0) {
        qDebug() << "ERROR!  Invalid job id.  Why?"; // foxnews.com triggers this
        return;
    }
    int c = getConnection();
    QWebNetworkJob *job = connection[c].current;
    DEBUG() << "WebCoreHttp::slotResponseHeaderReceived connection=" << c;
    DEBUG() << resp.toString();

    job->setResponse(resp);

    job->networkInterface()->started(job);
}

void WebCoreHttp::onReadyRead()
{
    QHttp *http = qobject_cast<QHttp*>(sender());
    if (http->currentId() == 0) {
        qDebug() << "ERROR!  Invalid job id.  Why?"; // foxnews.com triggers this
        return;
    }
    int c = getConnection();
    QWebNetworkJob *job = connection[c].current;
    Q_ASSERT(http == connection[c].http);
    //DEBUG() << "WebCoreHttp::slotReadyRead connection=" << c;

    QByteArray data;
    data.resize(http->bytesAvailable());
    http->read(data.data(), data.length());
    job->networkInterface()->data(job, data);
}

void WebCoreHttp::onRequestFinished(int id, bool error)
{
    int c = getConnection();
    if (connection[c].id != id) {
        return;
    }

    QWebNetworkJob *job = connection[c].current;
    if (!job) {
        scheduleNextRequest();
        return;
    }

    QHttp *http = connection[c].http;
    DEBUG() << "WebCoreHttp::slotFinished connection=" << c << error << job;
    if (error) {
        DEBUG() << "   error: " << http->errorString();
        job->setErrorString(http->errorString());
    }

    if (!error && http->bytesAvailable()) {
        QByteArray data;
        data.resize(http->bytesAvailable());
        http->read(data.data(), data.length());
        job->networkInterface()->data(job, data);
    }

    job->networkInterface()->finished(job, error ? 1 : 0);
    connection[c].current = 0;
    connection[c].id = -1;
    scheduleNextRequest();
}

void WebCoreHttp::onDone(bool error)
{
    DEBUG() << "WebCoreHttp::onDone" << error;
}

void WebCoreHttp::onStateChanged(int state)
{
    DEBUG() << "State changed to" << state << "and connections are" << connection[0].current << connection[1].current;
    if (state == QHttp::Closing || state == QHttp::Unconnected) {
        if (!m_inCancel && m_pendingRequests.isEmpty()
            && !connection[0].current && !connection[1].current)
            emit connectionClosed(info);
    }
}

void WebCoreHttp::cancel(QWebNetworkJob* request)
{
    bool doEmit = true;
    m_inCancel = true;
    for (int i = 0; i < 2; ++i) {
        if (request == connection[i].current) {
            connection[i].http->abort();
            doEmit = false;
        }
    }
    if (!m_pendingRequests.removeAll(request))
        doEmit = false;
    m_inCancel = false;

    if (doEmit)
        request->networkInterface()->finished(request, 1);

    if (m_pendingRequests.isEmpty()
        && !connection[0].current && !connection[1].current)
        emit connectionClosed(info);
}

void WebCoreHttp::onSslErrors(const QList<QSslError>& errors)
{
    int c = getConnection();
    QWebNetworkJob *job = connection[c].current;
    if (job) {
        bool continueAnyway = false;
        emit job->networkInterface()->sslErrors(job->frame(), job->url(), errors, &continueAnyway);
#ifndef QT_NO_OPENSSL
        if (continueAnyway)
            connection[c].http->ignoreSslErrors();
#endif
    }
}

void WebCoreHttp::onAuthenticationRequired(const QString& hostname, quint16 port, QAuthenticator *auth)
{
    int c = getConnection();
    QWebNetworkJob *job = connection[c].current;
    if (job) {
        emit job->networkInterface()->authenticate(job->frame(), job->url(), hostname, port, auth);
        if (auth->isNull())
            connection[c].http->abort();
    }
}

void WebCoreHttp::onProxyAuthenticationRequired(const QNetworkProxy& proxy, QAuthenticator *auth)
{
    int c = getConnection();
    QWebNetworkJob *job = connection[c].current;
    if (job) {
        emit job->networkInterface()->authenticateProxy(job->frame(), job->url(), proxy, auth);
        if (auth->isNull())
            connection[c].http->abort();
    }
}

HostInfo::HostInfo(const QUrl& url)
    : protocol(url.scheme())
    , host(url.host())
    , port(url.port())
{
    if (port < 0) {
        if (protocol == QLatin1String("http"))
            port = 80;
        else if (protocol == QLatin1String("https"))
            port = 443;
    }
}

#endif
