
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
**     * Redistributions of source code must retain the above copyright
**       notice, this list of conditions and the following disclaimer.
**     * Redistributions in binary form must reproduce the above copyright
**       notice, this list of conditions and the following disclaimer in the
**       documentation and/or other materials provided with the distribution.
**     * Neither the name of the LibQxt project nor the
**       names of its contributors may be used to endorse or promote products
**       derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org>  <foundation@libqxt.org>
*****************************************************************************/

#include "qxtwebevent.h"
#include "qxtwebcontent.h"
#include <QBuffer>

/*!
\class QxtWebEvent

\inmodule QxtWeb

\brief The QxtWebEvent class is a base class of all QxtWeb event types

QxtWebEvent is the base class for all QxtWeb event classes. Event objects
contain event parameters.

The base QxtWebEvent class contains the type of the event and a session ID for
the session it relates to. Subclasses of QxtWebEvent contain additional
parameters describing the particular event.
*/

/*!
    \enum QxtWebEvent::EventType

    \value None Not an event.
    \value Request A request event.
    \value FileUpload A file upload event.
    \value Page A page event.
    \value StoreCookie A store cookie event.
    \value RemoveCookie A remove cookie event.
    \value Redirect A redirect event.
*/

/*!
 * Constructs a QxtWebEvent of the specified \a type for the specified \a sessionID.
 */
QxtWebEvent::QxtWebEvent(EventType type, int sessionID)
        : sessionID(sessionID), m_type(type) {}

/*!
 * Destroys the event.
 */
QxtWebEvent::~QxtWebEvent() {}

/*!
 * \fn EventType QxtWebEvent::type() const
 * Returns the event type.
 */

/*!
 * \variable QxtWebEvent::sessionID
 * Contains the ID of the session the event is related to.
 */

/*!
\class QxtWebRequestEvent

\inmodule QxtWeb

\brief The QxtWebRequestEvent class describes a request from a web browser

The QxtWebRequestEvent class contains information about a request from a web
browser.
*/

/*!
 * Constructs a QxtWebRequestEvent for the specified \a sessionID, \a requestID and \a url.
 */
QxtWebRequestEvent::QxtWebRequestEvent(int _sessionID, int _requestID, const QUrl& _url)
        : QxtWebEvent(QxtWebEvent::Request, _sessionID), requestID(_requestID), url(_url), originalUrl(_url), isSecure(false) {}

/*!
 * Destroys the event and any content that may still be associated with it.
 */
QxtWebRequestEvent::~QxtWebRequestEvent()
{
    if (content) delete content;
}

/*!
 * \variable QxtWebRequestEvent::requestID
 * Contains an opaque value generated by the session manager. This request ID
 * must be included in the QxtWebPageEvent or QxtWebPageEvent subclass that
 * is the response to the request.
 */

/*!
 * \variable QxtWebRequestEvent::url
 * Contains the request URL, possibly after rewriting by intermediate services
 * such as QxtWebServiceDirectory.
 */

/*!
 * \variable QxtWebRequestEvent::originalUrl
 * Contains the request URL exactly as it was sent from the web browser.
 */

/*!
 * \variable QxtWebRequestEvent::contentType
 * Contains the MIME type of the request body, if present.
 */

/*!
 * \variable QxtWebRequestEvent::content
 * Contains the content of the request body, if present.
 */

/*!
 * \variable QxtWebRequestEvent::isSecure
 * If the request was sent over an encrypted channel, such as HTTPS, isSecure will be
 * set to \a true and clientCertificate will be set. Otherwise, isSecure will be set
 * to \a false.
 *
 * \sa clientCertificate, remoteAddress
 */

/*!
 *  \variable QxtWebRequestEvent::remoteAddress
 *  This variable will contain the address of the client as a QHostAddress.
 *  In IPv6 dual-stack systems (generally only Linux), this may be a IPv4
 *  mapped address.
 *
 *  \warning This variable was originally declared as a QString value in
 *  prior releases, albeit undocumented until now.
 *
 * \sa isSecure, clientCertificate
 */

/*!
 * \variable QxtWebRequestEvent::clientCertificate
 * If the request was sent over an encrypted channel, such as HTTPS, clientCertificate
 * will contain the certificate presented by the requesting client, if any.
 *
 * This member variable is not available if Qt was not compiled with SSL support.
 *
 * \sa isSecure, remoteAddress
 */

/*!
 * \variable QxtWebRequestEvent::cookies
 * Contains all of the cookies sent by the web browser.
 */

/*!
 * \variable QxtWebRequestEvent::headers
 * Contains all of the headers sent by the web browser.
 *
 * Note that use of these values may not be portable across session managers.
 */

/*
QxtWebFileUploadEvent::QxtWebFileUploadEvent(int sessionID)
: QxtWebEvent(QxtWebEvent::FileUpload, sessionID) {}
*/

/*!
\class QxtWebErrorEvent

\inmodule QxtWeb

\brief The QxtWebErrorEvent class describes an error condition to be sent to a web browser

The QxtWebErrorEvent class contains information about an error that will be
sent to a web browser.

QxtWebErrorEvent is a QxtWebPageEvent, so the \a dataSource may be replaced
with a custom error page. If you choose to do this, be sure to delete the
original data source automatically generated by the constructor first.
*/

/*!
 * Constructs a QxtWebErrorEvent for the specified \a sessionID and \a requestID,
 * with the provided \a statusCode and \a statusMessage.
 *
 * The requestID is an opaque value generated by the session manager; services
 * will receive this value via QxtWebRequestEvent and must use it in every
 * event that responds to that request.
 */
QxtWebErrorEvent::QxtWebErrorEvent(int sessionID, int requestID, int statusCode, QByteArray statusMessage)
        : QxtWebPageEvent(sessionID, requestID, "<html><body><h1>" + statusMessage + "</h1></body></html>\r\n")
{
    status = statusCode;
    QxtWebPageEvent::statusMessage = statusMessage;
}

/*!
\class QxtWebPageEvent

\inmodule QxtWeb

\brief The QxtWebPageEvent class describes a web page or other content to be sent to a web browser

The QxtWebPageEvent class contains information about a web page or other similar
content that will be sent to a web browser.
*/

/*!
 * Constructs a QxtWebPageEvent for the specified \a sessionID and \a requestID that will
 * use the data from \a source as the content to be sent to the web browser.
 *
 * The requestID is an opaque value generated by the session manager; services
 * will receive this value via QxtWebRequestEvent and must use it in every
 * event that responds to that request.
 *
 * QxtWeb takes ownership of the source and will delete it when the response
 * is completed.
 */
QxtWebPageEvent::QxtWebPageEvent(int sessionID, int requestID, QIODevice* source)
        : QxtWebEvent(QxtWebEvent::Page, sessionID), dataSource(source), chunked(true), streaming(true), requestID(requestID),
        status(200), statusMessage("OK"), contentType("text/html") {}

/*!
 * Constructs a QxtWebPageEvent for the specified \a sessionID and \a requestID that will
 * use \a source as the content to be sent to the web browser.
 *
 * The requestID is an opaque value generated by the session manager; services
 * will receive this value via QxtWebRequestEvent and must use it in every
 * event that responds to that request.
 */
QxtWebPageEvent::QxtWebPageEvent(int sessionID, int requestID, QByteArray source)
        : QxtWebEvent(QxtWebEvent::Page, sessionID), chunked(false), streaming(false), requestID(requestID),
        status(200), statusMessage("OK"), contentType("text/html")
{
    QBuffer* buffer = new QBuffer;
    buffer->setData(source);
    buffer->open(QIODevice::ReadOnly);
    dataSource = buffer;
}

/*!
 * \internal
 */
QxtWebPageEvent::QxtWebPageEvent(QxtWebEvent::EventType typeOverride, int sessionID, int requestID, QByteArray source)
        : QxtWebEvent(typeOverride, sessionID), chunked(false), streaming(false), requestID(requestID),
        status(200), statusMessage("OK"), contentType("text/html")
{
    QBuffer* buffer = new QBuffer;
    buffer->setData(source);
    buffer->open(QIODevice::ReadOnly);
    dataSource = buffer;
}

/*!
 * Destroys the event and any data source attached to it.
 */
QxtWebPageEvent::~QxtWebPageEvent()
{
    if (!dataSource.isNull()) dataSource->deleteLater();
}

/*!
 * \variable QxtWebPageEvent::dataSource
 * Data will be read from this device and relayed to the web browser.
 */

/*!
 * \variable QxtWebPageEvent::chunked
 * If true, and if the web browser supports "chunked" encoding, the content
 * will be sent using "chunked" encoding. If false, or if the browser does not
 * support this encoding (for instance, HTTP/0.9 and HTTP/1.0 user agents),
 * HTTP keep-alive will be disabled.
 *
 * The default value is true when using the QIODevice* constructor and false
 * when using the QByteArray constructor.
 */

/*!
 * \variable QxtWebPageEvent::streaming
 * If true, the data source is considered to be a source of streaming data.
 * The QIODevice must emit the readyRead() signal when data is available and
 * must emit aboutToClose() after all data has been transferred. (This can
 * be accomplished by invoking QIODevice::close() on it after all data is
 * determined to have been transferred.)
 *
 * The default value is true when using the QIODevice* constructor and false
 * when using the QByteArray constructor. If using a QIODevice that does not
 * produce streaming data, such as QFile, this \a must be set to false to
 * ensure correct behavior.
 */

/*!
 * \variable QxtWebPageEvent::requestID
 * Contains the opaque requestID provided by QxtWebRequestEvent.
 */

/*!
 * \variable QxtWebPageEvent::status
 * Contains the HTTP status code that will be sent with the response.
 *
 * The default value is 200 ("OK").
 */

/*!
 * \variable QxtWebPageEvent::statusMessage
 * Contains the human-readable message associated with the HTTP status code
 * that will be sent with the response.
 *
 * The default value is "OK".
 */

/*!
 * \variable QxtWebPageEvent::contentType
 * Contains the MIME type of the content being sent to the web browser.
 *
 * The default value is "text/html".
 */

/*!
 * \variable QxtWebPageEvent::headers
 * Contains custom headers to be sent to the web browser.
 *
 * It is empty by default.
 */

/*!
\class QxtWebStoreCookieEvent

\inmodule QxtWeb

\brief The QxtWebStoreCookieEvent class describes a cookie to be sent to a web browser

The QxtWebStoreCookieEvent class instructs the session manager to store
a cookie on the web browser.
*/

/*!
 * Constructs a QxtWebStoreCookieEvent for the specified \a sessionID that will
 * store a cookie with the specified \a name and \a data on the web browser.
 *
 * If an \a expiration date is supplied, it will be passed to the browser along
 * with the cookie. The browser will delete the cookie automatically after
 * the specified date. If an expiration date is not supplied, the cookie will
 * expire when the browser is closed.
 *
 * The cookie will be assigned a path of / by default. You may change this
 * using the \a path member.
 */
QxtWebStoreCookieEvent::QxtWebStoreCookieEvent(int sessionID, QString name, QString data, QDateTime expiration)
        : QxtWebEvent(QxtWebEvent::StoreCookie, sessionID), name(name), data(data), expiration(expiration), path("/") {}

/*!
 * \variable QxtWebStoreCookieEvent::name
 * Contains the name of the cookie to be stored.
 */

/*!
 * \variable QxtWebStoreCookieEvent::data
 * Contains the content of the cookie to be stored.
 */

/*!
 * \variable QxtWebStoreCookieEvent::expiration
 * Contains the expiration date of the cookie to be stored. If null, the
 * cookie will expire when the web browser is closed.
 */

/*!
 * \variable QxtWebStoreCookieEvent::path
 * Contains the path of the cookie to be stored.
 *
 * The default value is "/". Set the path to an empty QString to send
 * the cookie with no path specifier.
 */

/*!
\class QxtWebRemoveCookieEvent

\inmodule QxtWeb

\brief The QxtWebRemoveCookieEvent class describes a cookie to be deleted from a web browser

The QxtWebStoreCookieEvent class instructs the session manager to remove
a cookie stored on the web browser.
*/

/*!
 * Constructs a QxtWebRemoveCookieEvent for the specified \a sessionID that
 * removed the cookie with \a name from the web browser.
 *
 * The cookie's path is / by default. You may change this using the \a path member.
 */
QxtWebRemoveCookieEvent::QxtWebRemoveCookieEvent(int sessionID, QString name)
        : QxtWebEvent(QxtWebEvent::RemoveCookie, sessionID), name(name) {}

/*!
 * \variable QxtWebRemoveCookieEvent::name
 * Contains the name of the cookie to be removed.
 */

/*!
 * \variable QxtWebStoreCookieEvent::path
 * Contains the path of the cookie to be removed.
 *
 * The default value is "/". Set the path to an empty QString to send
 * the cookie with no path specifier.
 */

/*!
\class QxtWebRedirectEvent

\inmodule QxtWeb

\brief The QxtWebRedirectEvent class describes a redirect event to be sent to a web browser

The QxtWebRedirectEvent class instructs the web browser to load a page found at
another location.

The default status code, 302, indicates that the requested page was found at
a different location. Other useful status codes are 301, which indicates
that the web browser should always use the new URL in place of the old one,
and (in HTTP/1.1) 307, which indicates that the web browser should reissue
the same request (including POST data) to the new URL.
*/

/*!
 * Constructs a QxtWebRedirectEvent for the specified \a sessionID and \a requestID that
 * instructs the browser to move to the specified \a destination URL with \a statusCode.
 */
QxtWebRedirectEvent::QxtWebRedirectEvent(int sessionID, int requestID, const QString& destination, int statusCode)
        : QxtWebPageEvent(QxtWebEvent::Redirect, sessionID, requestID, QString("Redirect: <a href='%1'>%1</a>").arg(destination).toUtf8()), destination(destination)
{
    QxtWebPageEvent::status = statusCode;
    QxtWebPageEvent::statusMessage = ("Redirect to " + destination).toUtf8();
}

/*!
 * \variable QxtWebRedirectEvent::destination
 * Contains the new location (absolute or relative) to which the browser
 * should redirect.
 */
