/*
 *  This file is part of the KDE libraries
 *  Copyright (C) 2004, 2006 Apple Computer, Inc.
 *  Copyright (C) 2005-2007 Alexey Proskuryakov <ap@webkit.org>
 *  Copyright (C) 2007 Julien Chaffraix <julien.chaffraix@gmail.com>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#include "XMLHttpRequest.h"

#include "CString.h"
#include "Cache.h"
#include "DOMImplementation.h"
#include "Event.h"
#include "EventException.h"
#include "EventListener.h"
#include "EventNames.h"
#include "ExceptionCode.h"
#include "FormData.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "HTMLDocument.h"
#include "HTTPParsers.h"
#include "Page.h"
#include "PlatformString.h"
#include "RegularExpression.h"
#include "ResourceHandle.h"
#include "ResourceRequest.h"
#include "Settings.h"
#include "SubresourceLoader.h"
#include "TextEncoding.h"
#include "TextResourceDecoder.h"
#include "XMLHttpRequestException.h"
#include "kjs_binding.h"
#include <kjs/protect.h>
#include <wtf/Vector.h>

namespace WebCore {

using namespace EventNames;

typedef HashSet<XMLHttpRequest*> RequestsSet;

static HashMap<Document*, RequestsSet*>& requestsByDocument()
{
    static HashMap<Document*, RequestsSet*> map;
    return map;
}

static void addToRequestsByDocument(Document* doc, XMLHttpRequest* req)
{
    ASSERT(doc);
    ASSERT(req);

    RequestsSet* requests = requestsByDocument().get(doc);
    if (!requests) {
        requests = new RequestsSet;
        requestsByDocument().set(doc, requests);
    }

    ASSERT(!requests->contains(req));
    requests->add(req);
}

static void removeFromRequestsByDocument(Document* doc, XMLHttpRequest* req)
{
    ASSERT(doc);
    ASSERT(req);

    RequestsSet* requests = requestsByDocument().get(doc);
    ASSERT(requests);
    ASSERT(requests->contains(req));
    requests->remove(req);
    if (requests->isEmpty()) {
        requestsByDocument().remove(doc);
        delete requests;
    }
}

static bool isSafeRequestHeader(const String& name)
{
    static HashSet<String, CaseFoldingHash> forbiddenHeaders;
    static String proxyString("proxy-");
    
    if (forbiddenHeaders.isEmpty()) {
        forbiddenHeaders.add("accept-charset");
        forbiddenHeaders.add("accept-encoding");
        forbiddenHeaders.add("connection");
        forbiddenHeaders.add("content-length");
        forbiddenHeaders.add("content-transfer-encoding");
        forbiddenHeaders.add("date");
        forbiddenHeaders.add("expect");
        forbiddenHeaders.add("host");
        forbiddenHeaders.add("keep-alive");
        forbiddenHeaders.add("referer");
        forbiddenHeaders.add("te");
        forbiddenHeaders.add("trailer");
        forbiddenHeaders.add("transfer-encoding");
        forbiddenHeaders.add("upgrade");
        forbiddenHeaders.add("via");
    }
    
    return !forbiddenHeaders.contains(name) && !name.startsWith(proxyString, false);
}

// Determines if a string is a valid token, as defined by
// "token" in section 2.2 of RFC 2616.
static bool isValidToken(const String& name)
{
    unsigned length = name.length();
    for (unsigned i = 0; i < length; i++) {
        UChar c = name[i];
        
        if (c >= 127 || c <= 32)
            return false;
        
        if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' ||
            c == ',' || c == ';' || c == ':' || c == '\\' || c == '\"' ||
            c == '/' || c == '[' || c == ']' || c == '?' || c == '=' ||
            c == '{' || c == '}')
            return false;
    }
    
    return true;
}
    
static bool isValidHeaderValue(const String& name)
{
    // FIXME: This should really match name against 
    // field-value in section 4.2 of RFC 2616.
        
    return !name.contains('\r') && !name.contains('\n');
}
    
XMLHttpRequestState XMLHttpRequest::getReadyState() const
{
    return m_state;
}

const KJS::UString& XMLHttpRequest::getResponseText(ExceptionCode& ec) const
{
    return m_responseText;
}

Document* XMLHttpRequest::getResponseXML(ExceptionCode& ec) const
{
    if (m_state != Loaded)
        return 0;

    if (!m_createdDocument) {
        if (m_response.isHTTP() && !responseIsXML()) {
            // The W3C spec requires this.
            m_responseXML = 0;
        } else {
            m_responseXML = m_doc->implementation()->createDocument(0);
            m_responseXML->open();
            m_responseXML->setURL(m_url.deprecatedString());
            // FIXME: set Last-Modified and cookies (currently, those are only available for HTMLDocuments).
            m_responseXML->write(String(m_responseText));
            m_responseXML->finishParsing();
            m_responseXML->close();
            
            if (!m_responseXML->wellFormed())
                m_responseXML = 0;
        }
        m_createdDocument = true;
    }

    return m_responseXML.get();
}

EventListener* XMLHttpRequest::onReadyStateChangeListener() const
{
    return m_onReadyStateChangeListener.get();
}

void XMLHttpRequest::setOnReadyStateChangeListener(EventListener* eventListener)
{
    m_onReadyStateChangeListener = eventListener;
}

EventListener* XMLHttpRequest::onLoadListener() const
{
    return m_onLoadListener.get();
}

void XMLHttpRequest::setOnLoadListener(EventListener* eventListener)
{
    m_onLoadListener = eventListener;
}

void XMLHttpRequest::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
{
    EventListenersMap::iterator iter = m_eventListeners.find(eventType.impl());
    if (iter == m_eventListeners.end()) {
        ListenerVector listeners;
        listeners.append(eventListener);
        m_eventListeners.add(eventType.impl(), listeners);
    } else {
        ListenerVector& listeners = iter->second;
        for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter)
            if (*listenerIter == eventListener)
                return;
        
        listeners.append(eventListener);
        m_eventListeners.add(eventType.impl(), listeners);
    }
}

void XMLHttpRequest::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool)
{
    EventListenersMap::iterator iter = m_eventListeners.find(eventType.impl());
    if (iter == m_eventListeners.end())
        return;

    ListenerVector& listeners = iter->second;
    for (ListenerVector::const_iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter)
        if (*listenerIter == eventListener) {
            listeners.remove(listenerIter - listeners.begin());
            return;
        }
}

bool XMLHttpRequest::dispatchEvent(PassRefPtr<Event> evt, ExceptionCode& ec, bool /*tempEvent*/)
{
    // FIXME: check for other error conditions enumerated in the spec.
    if (evt->type().isEmpty()) {
        ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
        return true;
    }

    ListenerVector listenersCopy = m_eventListeners.get(evt->type().impl());
    for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) {
        evt->setTarget(this);
        evt->setCurrentTarget(this);
        listenerIter->get()->handleEvent(evt.get(), false);
    }

    return !evt->defaultPrevented();
}

XMLHttpRequest::XMLHttpRequest(Document* d)
    : m_doc(d)
    , m_async(true)
    , m_state(Uninitialized)
    , m_responseText("")
    , m_createdDocument(false)
    , m_aborted(false)
{
    ASSERT(m_doc);
    addToRequestsByDocument(m_doc, this);
}

XMLHttpRequest::~XMLHttpRequest()
{
    if (m_doc)
        removeFromRequestsByDocument(m_doc, this);
}

void XMLHttpRequest::changeState(XMLHttpRequestState newState)
{
    if (m_state != newState) {
        m_state = newState;
        callReadyStateChangeListener();
    }
}

void XMLHttpRequest::callReadyStateChangeListener()
{
    if (!m_doc || !m_doc->frame())
        return;

    RefPtr<Event> evt = new Event(readystatechangeEvent, false, false);
    if (m_onReadyStateChangeListener) {
        evt->setTarget(this);
        evt->setCurrentTarget(this);
        m_onReadyStateChangeListener->handleEvent(evt.get(), false);
    }

    ExceptionCode ec = 0;
    dispatchEvent(evt.release(), ec, false);
    ASSERT(!ec);
    
    if (m_state == Loaded) {
        evt = new Event(loadEvent, false, false);
        if (m_onLoadListener) {
            evt->setTarget(this);
            evt->setCurrentTarget(this);
            m_onLoadListener->handleEvent(evt.get(), false);
        }
        
        dispatchEvent(evt, ec, false);
        ASSERT(!ec);
    }
}

bool XMLHttpRequest::urlMatchesDocumentDomain(const KURL& url) const
{
    // a local file can load anything
    if (m_doc->isAllowedToLoadLocalResources())
        return true;

    // but a remote document can only load from the same port on the server
    KURL documentURL = m_doc->url();
    if (documentURL.protocol().lower() == url.protocol().lower()
            && documentURL.host().lower() == url.host().lower()
            && documentURL.port() == url.port())
        return true;

    return false;
}

void XMLHttpRequest::open(const String& method, const KURL& url, bool async, ExceptionCode& ec)
{
    abort();
    m_aborted = false;

    // clear stuff from possible previous load
    m_requestHeaders.clear();
    m_response = ResourceResponse();
    {
        KJS::JSLock lock;
        m_responseText = "";
    }
    m_createdDocument = false;
    m_responseXML = 0;

    ASSERT(m_state == Uninitialized);

    if (!urlMatchesDocumentDomain(url)) {
        ec = XMLHttpRequestException::PERMISSION_DENIED;
        return;
    }

    if (!isValidToken(method)) {
        ec = SYNTAX_ERR;
        return;
    }
    
    // Method names are case sensitive. But since Firefox uppercases method names it knows, we'll do the same.
    String methodUpper(method.upper());
    
    if (methodUpper == "TRACE" || methodUpper == "TRACK" || methodUpper == "CONNECT") {
        ec = XMLHttpRequestException::PERMISSION_DENIED;
        return;
    }

    m_url = url;

    if (methodUpper == "COPY" || methodUpper == "DELETE" || methodUpper == "GET" || methodUpper == "HEAD"
        || methodUpper == "INDEX" || methodUpper == "LOCK" || methodUpper == "M-POST" || methodUpper == "MKCOL" || methodUpper == "MOVE"
        || methodUpper == "OPTIONS" || methodUpper == "POST" || methodUpper == "PROPFIND" || methodUpper == "PROPPATCH" || methodUpper == "PUT" 
        || methodUpper == "UNLOCK")
        m_method = methodUpper.deprecatedString();
    else
        m_method = method.deprecatedString();

    m_async = async;

    changeState(Open);
}

void XMLHttpRequest::open(const String& method, const KURL& url, bool async, const String& user, ExceptionCode& ec)
{
    KURL urlWithCredentials(url);
    urlWithCredentials.setUser(user.deprecatedString());
    
    open(method, urlWithCredentials, async, ec);
}

void XMLHttpRequest::open(const String& method, const KURL& url, bool async, const String& user, const String& password, ExceptionCode& ec)
{
    KURL urlWithCredentials(url);
    urlWithCredentials.setUser(user.deprecatedString());
    urlWithCredentials.setPass(password.deprecatedString());
    
    open(method, urlWithCredentials, async, ec);
}

void XMLHttpRequest::send(const String& body, ExceptionCode& ec)
{
    if (!m_doc)
        return;

    if (m_state != Open) {
        ec = INVALID_STATE_ERR;
        return;
    }
  
    // FIXME: Should this abort or raise an exception instead if we already have a m_loader going?
    if (m_loader)
        return;

    m_aborted = false;

    ResourceRequest request(m_url);
    request.setHTTPMethod(m_method);
    
    if (!body.isNull() && m_method != "GET" && m_method != "HEAD" && (m_url.protocol().lower() == "http" || m_url.protocol().lower() == "https")) {
        String contentType = getRequestHeader("Content-Type");
        if (contentType.isEmpty()) {
            ExceptionCode ec = 0;
            Settings* settings = m_doc->settings();
            if (settings && settings->usesDashboardBackwardCompatibilityMode())
                setRequestHeader("Content-Type", "application/x-www-form-urlencoded", ec);
            else
                setRequestHeader("Content-Type", "application/xml", ec);
            ASSERT(ec == 0);
        }

        // FIXME: must use xmlEncoding for documents.
        String charset = "UTF-8";
      
        TextEncoding m_encoding(charset);
        if (!m_encoding.isValid()) // FIXME: report an error?
            m_encoding = UTF8Encoding();

        request.setHTTPBody(PassRefPtr<FormData>(new FormData(m_encoding.encode(body.characters(), body.length()))));
    }

    if (m_requestHeaders.size() > 0)
        request.addHTTPHeaderFields(m_requestHeaders);

    if (!m_async) {
        Vector<char> data;
        ResourceError error;
        ResourceResponse response;

        {
            // avoid deadlock in case the loader wants to use JS on a background thread
            KJS::JSLock::DropAllLocks dropLocks;
            if (m_doc->frame()) 
                m_doc->frame()->loader()->loadResourceSynchronously(request, error, response, data);
        }

        m_loader = 0;
        
        // No exception for file:/// resources, see <rdar://problem/4962298>.
        // Also, if we have an HTTP response, then it wasn't a network error in fact.
        if (error.isNull() || request.url().isLocalFile() || response.httpStatusCode() > 0)
            processSyncLoadResults(data, response);
        else
            ec = XMLHttpRequestException::NETWORK_ERR;

        return;
    }

    // SubresourceLoader::create can return null here, for example if we're no longer attached to a page.
    // This is true while running onunload handlers.
    // FIXME: We need to be able to send XMLHttpRequests from onunload, <http://bugs.webkit.org/show_bug.cgi?id=10904>.
    // FIXME: Maybe create can return null for other reasons too?
    // We need to keep content sniffing enabled for local files due to CFNetwork not providing a MIME type
    // for local files otherwise, <rdar://problem/5671813>.
    m_loader = SubresourceLoader::create(m_doc->frame(), this, request, false, true, request.url().isLocalFile());

    if (m_loader) {
        // Neither this object nor the JavaScript wrapper should be deleted while
        // a request is in progress because we need to keep the listeners alive,
        // and they are referenced by the JavaScript wrapper.
        ref();

        KJS::JSLock lock;
        KJS::gcProtectNullTolerant(KJS::ScriptInterpreter::getDOMObject(this));
    }
}

void XMLHttpRequest::abort()
{
    bool hadLoader = m_loader;

    m_aborted = true;
    
    if (hadLoader) {
        m_loader->cancel();
        m_loader = 0;
    }

    m_decoder = 0;

    if (hadLoader)
        dropProtection();

    m_state = Uninitialized;
}

void XMLHttpRequest::dropProtection()        
{
    {
        KJS::JSLock lock;
        KJS::JSValue* wrapper = KJS::ScriptInterpreter::getDOMObject(this);
        KJS::gcUnprotectNullTolerant(wrapper);
    
        // the XHR object itself holds on to the responseText, and
        // thus has extra cost even independent of any
        // responseText or responseXML objects it has handed
        // out. But it is protected from GC while loading, so this
        // can't be recouped until the load is done, so only
        // report the extra cost at that point.
    
        if (wrapper)
            KJS::Collector::reportExtraMemoryCost(m_responseText.size() * 2);
    }

    deref();
}

void XMLHttpRequest::overrideMIMEType(const String& override)
{
    m_mimeTypeOverride = override;
}
    
void XMLHttpRequest::setRequestHeader(const String& name, const String& value, ExceptionCode& ec)
{
    if (m_state != Open) {
        Settings* settings = m_doc ? m_doc->settings() : 0;
        if (settings && settings->usesDashboardBackwardCompatibilityMode())
            return;

        ec = INVALID_STATE_ERR;
        return;
    }

    if (!isValidToken(name) || !isValidHeaderValue(value)) {
        ec = SYNTAX_ERR;
        return;
    }
        
    // A privileged script (e.g. a Dashboard widget) can set any headers.
    if (!m_doc->isAllowedToLoadLocalResources() && !isSafeRequestHeader(name)) {
        if (m_doc && m_doc->frame() && m_doc->frame()->page())
            m_doc->frame()->page()->chrome()->addMessageToConsole(JSMessageSource, ErrorMessageLevel, "Refused to set unsafe header " + name, 1, String());
        return;
    }

    if (!m_requestHeaders.contains(name)) {
        m_requestHeaders.set(name, value);
        return;
    }
    
    String oldValue = m_requestHeaders.get(name);
    m_requestHeaders.set(name, oldValue + ", " + value);
}

String XMLHttpRequest::getRequestHeader(const String& name) const
{
    return m_requestHeaders.get(name);
}

String XMLHttpRequest::getAllResponseHeaders(ExceptionCode& ec) const
{
    if (m_state < Receiving) {
        ec = INVALID_STATE_ERR;
        return "";
    }

    Vector<UChar> stringBuilder;
    String separator(": ");

    HTTPHeaderMap::const_iterator end = m_response.httpHeaderFields().end();
    for (HTTPHeaderMap::const_iterator it = m_response.httpHeaderFields().begin(); it!= end; ++it) {
        stringBuilder.append(it->first.characters(), it->first.length());
        stringBuilder.append(separator.characters(), separator.length());
        stringBuilder.append(it->second.characters(), it->second.length());
        stringBuilder.append((UChar)'\r');
        stringBuilder.append((UChar)'\n');
    }

    return String::adopt(stringBuilder);
}

String XMLHttpRequest::getResponseHeader(const String& name, ExceptionCode& ec) const
{
    if (m_state < Receiving) {
        ec = INVALID_STATE_ERR;
        return "";
    }

    if (!isValidToken(name))
        return "";

    return m_response.httpHeaderField(name);
}

String XMLHttpRequest::responseMIMEType() const
{
    String mimeType = extractMIMETypeFromMediaType(m_mimeTypeOverride);
    if (mimeType.isEmpty()) {
        if (m_response.isHTTP())
            mimeType = extractMIMETypeFromMediaType(m_response.httpHeaderField("Content-Type"));
        else
            mimeType = m_response.mimeType();
    }
    if (mimeType.isEmpty())
        mimeType = "text/xml";
    
    return mimeType;
}

bool XMLHttpRequest::responseIsXML() const
{
    return DOMImplementation::isXMLMIMEType(responseMIMEType());
}

int XMLHttpRequest::getStatus(ExceptionCode& ec) const
{
    if (m_state == Uninitialized)
        return 0;
    
    if (m_response.httpStatusCode() == 0) {
        if (m_state != Receiving && m_state != Loaded)
            // status MUST be available in these states, but we don't get any headers from non-HTTP requests
            ec = INVALID_STATE_ERR;
    }

    return m_response.httpStatusCode();
}

String XMLHttpRequest::getStatusText(ExceptionCode& ec) const
{
    if (m_state == Uninitialized)
        return "";
    
    if (m_response.httpStatusCode() == 0) {
        if (m_state != Receiving && m_state != Loaded)
            // statusText MUST be available in these states, but we don't get any headers from non-HTTP requests
            ec = INVALID_STATE_ERR;
        return String();
    }

    // FIXME: should try to preserve status text in response
    return "OK";
}

void XMLHttpRequest::processSyncLoadResults(const Vector<char>& data, const ResourceResponse& response)
{
    if (!urlMatchesDocumentDomain(response.url())) {
        abort();
        return;
    }

    didReceiveResponse(0, response);
    changeState(Sent);
    if (m_aborted)
        return;

    const char* bytes = static_cast<const char*>(data.data());
    int len = static_cast<int>(data.size());

    didReceiveData(0, bytes, len);
    if (m_aborted)
        return;

    didFinishLoading(0);
}

void XMLHttpRequest::didFail(SubresourceLoader* loader, const ResourceError&)
{
    didFinishLoading(loader);
}

void XMLHttpRequest::didFinishLoading(SubresourceLoader* loader)
{
    if (m_aborted)
        return;
        
    ASSERT(loader == m_loader);

    if (m_state < Sent)
        changeState(Sent);

    {
        KJS::JSLock lock;
        if (m_decoder)
            m_responseText += m_decoder->flush();
    }

    bool hadLoader = m_loader;
    m_loader = 0;

    changeState(Loaded);
    m_decoder = 0;

    if (hadLoader)
        dropProtection();
}

void XMLHttpRequest::willSendRequest(SubresourceLoader*, ResourceRequest& request, const ResourceResponse& redirectResponse)
{
    if (!urlMatchesDocumentDomain(request.url()))
        abort();
}

void XMLHttpRequest::didReceiveResponse(SubresourceLoader*, const ResourceResponse& response)
{
    m_response = response;
    m_encoding = extractCharsetFromMediaType(m_mimeTypeOverride);
    if (m_encoding.isEmpty())
        m_encoding = response.textEncodingName();

}

void XMLHttpRequest::receivedCancellation(SubresourceLoader*, const AuthenticationChallenge& challenge)
{
    m_response = challenge.failureResponse();
}

void XMLHttpRequest::didReceiveData(SubresourceLoader*, const char* data, int len)
{
    if (m_state < Sent)
        changeState(Sent);
  
    if (!m_decoder) {
        if (!m_encoding.isEmpty())
            m_decoder = new TextResourceDecoder("text/plain", m_encoding);
        // allow TextResourceDecoder to look inside the m_response if it's XML or HTML
        else if (responseIsXML())
            m_decoder = new TextResourceDecoder("application/xml");
        else if (responseMIMEType() == "text/html")
            m_decoder = new TextResourceDecoder("text/html", "UTF-8");
        else
            m_decoder = new TextResourceDecoder("text/plain", "UTF-8");
    }
    if (len == 0)
        return;

    if (len == -1)
        len = strlen(data);

    String decoded = m_decoder->decode(data, len);

    {
        KJS::JSLock lock;
        m_responseText += decoded;
    }

    if (!m_aborted) {
        if (m_state != Receiving)
            changeState(Receiving);
        else
            // Firefox calls readyStateChanged every time it receives data, 4449442
            callReadyStateChangeListener();
    }
}

void XMLHttpRequest::cancelRequests(Document* m_doc)
{
    RequestsSet* requests = requestsByDocument().get(m_doc);
    if (!requests)
        return;
    RequestsSet copy = *requests;
    RequestsSet::const_iterator end = copy.end();
    for (RequestsSet::const_iterator it = copy.begin(); it != end; ++it)
        (*it)->abort();
}

void XMLHttpRequest::detachRequests(Document* m_doc)
{
    RequestsSet* requests = requestsByDocument().get(m_doc);
    if (!requests)
        return;
    requestsByDocument().remove(m_doc);
    RequestsSet::const_iterator end = requests->end();
    for (RequestsSet::const_iterator it = requests->begin(); it != end; ++it) {
        (*it)->m_doc = 0;
        (*it)->abort();
    }
    delete requests;
}

} // end namespace
