File indexing completed on 2024-04-28 15:23:20

0001 /*
0002  *  This file is part of the KDE libraries
0003  *  Copyright (C) 2003 Apple Computer, Inc.
0004  *
0005  *  This library is free software; you can redistribute it and/or
0006  *  modify it under the terms of the GNU Lesser General Public
0007  *  License as published by the Free Software Foundation; either
0008  *  version 2 of the License, or (at your option) any later version.
0009  *
0010  *  This library is distributed in the hope that it will be useful,
0011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  *  Lesser General Public License for more details.
0014  *
0015  *  You should have received a copy of the GNU Lesser General Public
0016  *  License along with this library; if not, write to the Free Software
0017  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
0018  */
0019 
0020 #ifndef _XMLHTTPREQUEST_H_
0021 #define _XMLHTTPREQUEST_H_
0022 
0023 #include "ecma/kjs_binding.h"
0024 #include "ecma/kjs_dom.h"
0025 #include <kencodingdetector.h>
0026 #include "kio/jobclasses.h"
0027 #include <QPointer>
0028 #include <QHash>
0029 
0030 #include "xml/dom_nodeimpl.h"
0031 
0032 namespace KJS
0033 {
0034 
0035 class JSEventListener;
0036 class XMLHttpRequestQObject;
0037 
0038 class CaseInsensitiveString
0039 {
0040 public:
0041     CaseInsensitiveString(const char *s) : str(QLatin1String(s)) { }
0042     CaseInsensitiveString(const QString &s) : str(s) { }
0043 
0044     QString original() const
0045     {
0046         return str;
0047     }
0048     QString toLower() const
0049     {
0050         return str.toLower();
0051     }
0052 
0053 private:
0054     QString str;
0055 };
0056 
0057 inline bool operator==(const CaseInsensitiveString &a,
0058                        const CaseInsensitiveString &b)
0059 {
0060     return a.original().compare(b.original(), Qt::CaseInsensitive) == 0;
0061 }
0062 
0063 inline uint qHash(const CaseInsensitiveString &key)
0064 {
0065     return qHash(key.toLower());
0066 }
0067 
0068 typedef QHash<CaseInsensitiveString, QString> HTTPHeaderMap;
0069 
0070 // these exact numeric values are important because JS expects them
0071 enum XMLHttpRequestState {
0072     XHRS_Uninitialized = 0,
0073     XHRS_Open = 1,
0074     XHRS_Sent = 2,
0075     XHRS_Receiving = 3,
0076     XHRS_Loaded = 4
0077 };
0078 
0079 class XMLHttpRequestConstructorImp : public JSObject
0080 {
0081 public:
0082     XMLHttpRequestConstructorImp(ExecState *exec, DOM::DocumentImpl *d);
0083     bool implementsConstruct() const override;
0084     using KJS::JSObject::construct;
0085     JSObject *construct(ExecState *exec, const List &args) override;
0086 private:
0087     SharedPtr<DOM::DocumentImpl> doc;
0088 };
0089 
0090 class XMLHttpRequest : public DOMObject, public DOM::EventTargetImpl
0091 {
0092 public:
0093     XMLHttpRequest(ExecState *, DOM::DocumentImpl *d);
0094     ~XMLHttpRequest();
0095 
0096     Type eventTargetType() const override
0097     {
0098         return XML_HTTP_REQUEST;
0099     }
0100 
0101     using KJS::JSObject::getOwnPropertySlot;
0102     bool getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) override;
0103     JSValue *getValueProperty(ExecState *exec, int token) const;
0104     using KJS::JSObject::put;
0105     void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None) override;
0106     void putValueProperty(ExecState *exec, int token, JSValue *value, int /*attr*/);
0107     bool toBoolean(ExecState *) const override
0108     {
0109         return true;
0110     }
0111     const ClassInfo *classInfo() const override
0112     {
0113         return &info;
0114     }
0115     static const ClassInfo info;
0116     enum { Onload, Onreadystatechange, ReadyState, ResponseText, ResponseXML, Status, StatusText, Abort,
0117            GetAllResponseHeaders, GetResponseHeader, Open, Send, SetRequestHeader,
0118            OverrideMIMEType
0119          };
0120 
0121 private:
0122     friend class XMLHttpRequestProtoFunc;
0123     friend class XMLHttpRequestQObject;
0124 
0125     JSValue *getStatusText() const;
0126     JSValue *getStatus() const;
0127     bool urlMatchesDocumentDomain(const QUrl &) const;
0128 
0129     XMLHttpRequestQObject *qObject;
0130 
0131 #ifdef APPLE_CHANGES
0132     void slotData(KIO::Job *job, const char *data, int size);
0133 #else
0134     void slotData(KIO::Job *job, const QByteArray &data);
0135 #endif
0136     void slotFinished(KJob *);
0137     void slotRedirection(KIO::Job *, const QUrl &);
0138 
0139     void processSyncLoadResults(const QByteArray &data, const QUrl &finalURL, const QString &headers);
0140 
0141     void open(const QString &_method, const QUrl &_url, bool _async, int &ec);
0142     void send(const QString &_body, int &ec);
0143     void abort();
0144     void setRequestHeader(const QString &name, const QString &value, int &ec);
0145     void overrideMIMEType(const QString &override);
0146     JSValue *getAllResponseHeaders(int &ec) const;
0147     JSValue *getResponseHeader(const QString &name, int &ec) const;
0148 
0149     void changeState(XMLHttpRequestState newState);
0150 
0151     QPointer<DOM::DocumentImpl> doc;
0152 
0153     QUrl url;
0154     QString m_method;
0155     bool async;
0156     HTTPHeaderMap m_requestHeaders;
0157     QString m_mimeTypeOverride;
0158     QString contentType;
0159 
0160     KIO::StoredTransferJob *job;
0161 
0162     XMLHttpRequestState m_state;
0163     JSEventListener *onReadyStateChangeListener;
0164     JSEventListener *onLoadListener;
0165 
0166     KEncodingDetector *decoder;
0167     bool              binaryMode; // just byte-expand data,
0168     // don't pass it through the decoder.
0169     void clearDecoder();
0170 
0171     QString encoding;
0172     QString responseHeaders;
0173 
0174     QString response;
0175     mutable bool createdDocument;
0176     mutable bool typeIsXML;
0177     mutable SharedPtr<DOM::DocumentImpl> responseXML;
0178 
0179     bool aborted;
0180 };
0181 
0182 class XMLHttpRequestQObject : public QObject
0183 {
0184     Q_OBJECT
0185 
0186 public:
0187     XMLHttpRequestQObject(XMLHttpRequest *_jsObject);
0188 
0189 public Q_SLOTS:
0190     void slotData(KIO::Job *job, const QByteArray &data);
0191     void slotFinished(KJob *job);
0192     void slotRedirection(KIO::Job *job, const QUrl &url);
0193 
0194 private:
0195     XMLHttpRequest *jsObject;
0196 };
0197 
0198 } // namespace
0199 
0200 #endif