src/declarative/qml/qdeclarativexmlhttprequest.cpp
changeset 37 758a864f9613
parent 30 5dc02b23752f
--- a/src/declarative/qml/qdeclarativexmlhttprequest.cpp	Fri Sep 17 08:34:18 2010 +0300
+++ b/src/declarative/qml/qdeclarativexmlhttprequest.cpp	Mon Oct 04 01:19:32 2010 +0300
@@ -58,6 +58,8 @@
 #include <QtCore/qstack.h>
 #include <QtCore/qdebug.h>
 
+#ifndef QT_NO_XMLSTREAMREADER
+
 // From DOM-Level-3-Core spec
 // http://www.w3.org/TR/DOM-Level-3-Core/core.html
 #define INDEX_SIZE_ERR 1
@@ -963,8 +965,9 @@
     QScriptValue send(QScriptValue *me, const QByteArray &);
     QScriptValue abort(QScriptValue *me);
 
-    QString responseBody() const;
+    QString responseBody();
     const QByteArray & rawResponseBody() const;
+    bool receivedXml() const;
 private slots:
     void downloadProgress(qint64);
     void error(QNetworkReply::NetworkError);
@@ -987,6 +990,15 @@
     HeadersList m_headersList;
     void fillHeadersList();
 
+    bool m_gotXml;
+    QByteArray m_mime;
+    QByteArray m_charset;
+    QTextCodec *m_textCodec;
+#ifndef QT_NO_TEXTCODEC
+    QTextCodec* findTextCodec() const;
+#endif
+    void readEncoding();
+
     QScriptValue m_me; // Set to the data object while a send() is ongoing (to access the callback)
 
     QScriptValue dispatchCallback(QScriptValue *me);
@@ -1004,7 +1016,7 @@
 
 QDeclarativeXMLHttpRequest::QDeclarativeXMLHttpRequest(QNetworkAccessManager *manager)
 : m_state(Unsent), m_errorFlag(false), m_sendFlag(false),
-  m_redirectCount(0), m_network(0), m_nam(manager)
+  m_redirectCount(0), m_gotXml(false), m_textCodec(0), m_network(0), m_nam(manager)
 {
 }
 
@@ -1275,6 +1287,7 @@
         if (cbv.isError()) printError(cbv);
     }
     m_responseEntityBody.append(m_network->readAll());
+    readEncoding();
 
     if (xhrDump()) {
         qWarning().nospace() << "XMLHttpRequest: RESPONSE " << qPrintable(m_url.toString());
@@ -1300,13 +1313,71 @@
 }
 
 
-QString QDeclarativeXMLHttpRequest::responseBody() const
+void QDeclarativeXMLHttpRequest::readEncoding()
+{
+    foreach (const HeaderPair &header, m_headersList) {
+        if (header.first == "content-type") {
+            int separatorIdx = header.second.indexOf(';');
+            if (separatorIdx == -1) {
+                m_mime == header.second;
+            } else {
+                m_mime = header.second.mid(0, separatorIdx);
+                int charsetIdx = header.second.indexOf("charset=");
+                if (charsetIdx != -1) {
+                    charsetIdx += 8;
+                    separatorIdx = header.second.indexOf(';', charsetIdx);
+                    m_charset = header.second.mid(charsetIdx, separatorIdx >= 0 ? separatorIdx : header.second.length());
+                }
+            }
+            break;
+        }
+    }
+
+    if (m_mime.isEmpty() || m_mime == "text/xml" || m_mime == "application/xml" || m_mime.endsWith("+xml")) 
+        m_gotXml = true;
+}
+
+bool QDeclarativeXMLHttpRequest::receivedXml() const
+{
+    return m_gotXml;
+}
+
+
+#ifndef QT_NO_TEXTCODEC
+QTextCodec* QDeclarativeXMLHttpRequest::findTextCodec() const
 {
-    QXmlStreamReader reader(m_responseEntityBody);
-    reader.readNext();
-    QTextCodec *codec = QTextCodec::codecForName(reader.documentEncoding().toString().toUtf8());
-    if (codec)
-        return codec->toUnicode(m_responseEntityBody);
+    QTextCodec *codec = 0;
+
+    if (!m_charset.isEmpty()) 
+        codec = QTextCodec::codecForName(m_charset);
+
+    if (!codec && m_gotXml) {
+        QXmlStreamReader reader(m_responseEntityBody);
+        reader.readNext();
+        codec = QTextCodec::codecForName(reader.documentEncoding().toString().toUtf8());
+    }
+
+    if (!codec && m_mime == "text/html") 
+        codec = QTextCodec::codecForHtml(m_responseEntityBody, 0);
+
+    if (!codec)
+        codec = QTextCodec::codecForUtfText(m_responseEntityBody, 0);
+
+    if (!codec)
+        codec = QTextCodec::codecForName("UTF-8");
+    return codec;
+}
+#endif
+
+
+QString QDeclarativeXMLHttpRequest::responseBody()
+{
+#ifndef QT_NO_TEXTCODEC
+    if (!m_textCodec)
+        m_textCodec = findTextCodec();
+    if (m_textCodec)
+        return m_textCodec->toUnicode(m_responseEntityBody);
+#endif
 
     return QString::fromUtf8(m_responseEntityBody);
 }
@@ -1568,7 +1639,8 @@
     if (!request) 
         THROW_REFERENCE("Not an XMLHttpRequest object");
 
-    if (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
+    if (!request->receivedXml() ||
+        request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
         request->readyState() != QDeclarativeXMLHttpRequest::Done)
         return engine->nullValue();
     else  
@@ -1662,4 +1734,6 @@
 
 QT_END_NAMESPACE
 
+#endif // QT_NO_XMLSTREAMREADER
+
 #include <qdeclarativexmlhttprequest.moc>