56 #include <QtCore/qtextcodec.h> |
56 #include <QtCore/qtextcodec.h> |
57 #include <QtCore/qxmlstream.h> |
57 #include <QtCore/qxmlstream.h> |
58 #include <QtCore/qstack.h> |
58 #include <QtCore/qstack.h> |
59 #include <QtCore/qdebug.h> |
59 #include <QtCore/qdebug.h> |
60 |
60 |
|
61 #ifndef QT_NO_XMLSTREAMREADER |
|
62 |
61 // From DOM-Level-3-Core spec |
63 // From DOM-Level-3-Core spec |
62 // http://www.w3.org/TR/DOM-Level-3-Core/core.html |
64 // http://www.w3.org/TR/DOM-Level-3-Core/core.html |
63 #define INDEX_SIZE_ERR 1 |
65 #define INDEX_SIZE_ERR 1 |
64 #define DOMSTRING_SIZE_ERR 2 |
66 #define DOMSTRING_SIZE_ERR 2 |
65 #define HIERARCHY_REQUEST_ERR 3 |
67 #define HIERARCHY_REQUEST_ERR 3 |
961 QString header(const QString &name); |
963 QString header(const QString &name); |
962 QString headers(); |
964 QString headers(); |
963 QScriptValue send(QScriptValue *me, const QByteArray &); |
965 QScriptValue send(QScriptValue *me, const QByteArray &); |
964 QScriptValue abort(QScriptValue *me); |
966 QScriptValue abort(QScriptValue *me); |
965 |
967 |
966 QString responseBody() const; |
968 QString responseBody(); |
967 const QByteArray & rawResponseBody() const; |
969 const QByteArray & rawResponseBody() const; |
|
970 bool receivedXml() const; |
968 private slots: |
971 private slots: |
969 void downloadProgress(qint64); |
972 void downloadProgress(qint64); |
970 void error(QNetworkReply::NetworkError); |
973 void error(QNetworkReply::NetworkError); |
971 void finished(); |
974 void finished(); |
972 |
975 |
985 typedef QPair<QByteArray, QByteArray> HeaderPair; |
988 typedef QPair<QByteArray, QByteArray> HeaderPair; |
986 typedef QList<HeaderPair> HeadersList; |
989 typedef QList<HeaderPair> HeadersList; |
987 HeadersList m_headersList; |
990 HeadersList m_headersList; |
988 void fillHeadersList(); |
991 void fillHeadersList(); |
989 |
992 |
|
993 bool m_gotXml; |
|
994 QByteArray m_mime; |
|
995 QByteArray m_charset; |
|
996 QTextCodec *m_textCodec; |
|
997 #ifndef QT_NO_TEXTCODEC |
|
998 QTextCodec* findTextCodec() const; |
|
999 #endif |
|
1000 void readEncoding(); |
|
1001 |
990 QScriptValue m_me; // Set to the data object while a send() is ongoing (to access the callback) |
1002 QScriptValue m_me; // Set to the data object while a send() is ongoing (to access the callback) |
991 |
1003 |
992 QScriptValue dispatchCallback(QScriptValue *me); |
1004 QScriptValue dispatchCallback(QScriptValue *me); |
993 void printError(const QScriptValue&); |
1005 void printError(const QScriptValue&); |
994 |
1006 |
1002 QNetworkAccessManager *networkAccessManager() { return m_nam; } |
1014 QNetworkAccessManager *networkAccessManager() { return m_nam; } |
1003 }; |
1015 }; |
1004 |
1016 |
1005 QDeclarativeXMLHttpRequest::QDeclarativeXMLHttpRequest(QNetworkAccessManager *manager) |
1017 QDeclarativeXMLHttpRequest::QDeclarativeXMLHttpRequest(QNetworkAccessManager *manager) |
1006 : m_state(Unsent), m_errorFlag(false), m_sendFlag(false), |
1018 : m_state(Unsent), m_errorFlag(false), m_sendFlag(false), |
1007 m_redirectCount(0), m_network(0), m_nam(manager) |
1019 m_redirectCount(0), m_gotXml(false), m_textCodec(0), m_network(0), m_nam(manager) |
1008 { |
1020 { |
1009 } |
1021 } |
1010 |
1022 |
1011 QDeclarativeXMLHttpRequest::~QDeclarativeXMLHttpRequest() |
1023 QDeclarativeXMLHttpRequest::~QDeclarativeXMLHttpRequest() |
1012 { |
1024 { |
1273 fillHeadersList (); |
1285 fillHeadersList (); |
1274 QScriptValue cbv = dispatchCallback(&m_me); |
1286 QScriptValue cbv = dispatchCallback(&m_me); |
1275 if (cbv.isError()) printError(cbv); |
1287 if (cbv.isError()) printError(cbv); |
1276 } |
1288 } |
1277 m_responseEntityBody.append(m_network->readAll()); |
1289 m_responseEntityBody.append(m_network->readAll()); |
|
1290 readEncoding(); |
1278 |
1291 |
1279 if (xhrDump()) { |
1292 if (xhrDump()) { |
1280 qWarning().nospace() << "XMLHttpRequest: RESPONSE " << qPrintable(m_url.toString()); |
1293 qWarning().nospace() << "XMLHttpRequest: RESPONSE " << qPrintable(m_url.toString()); |
1281 if (!m_responseEntityBody.isEmpty()) { |
1294 if (!m_responseEntityBody.isEmpty()) { |
1282 qWarning().nospace() << " " |
1295 qWarning().nospace() << " " |
1298 |
1311 |
1299 m_me = QScriptValue(); |
1312 m_me = QScriptValue(); |
1300 } |
1313 } |
1301 |
1314 |
1302 |
1315 |
1303 QString QDeclarativeXMLHttpRequest::responseBody() const |
1316 void QDeclarativeXMLHttpRequest::readEncoding() |
1304 { |
1317 { |
1305 QXmlStreamReader reader(m_responseEntityBody); |
1318 foreach (const HeaderPair &header, m_headersList) { |
1306 reader.readNext(); |
1319 if (header.first == "content-type") { |
1307 QTextCodec *codec = QTextCodec::codecForName(reader.documentEncoding().toString().toUtf8()); |
1320 int separatorIdx = header.second.indexOf(';'); |
1308 if (codec) |
1321 if (separatorIdx == -1) { |
1309 return codec->toUnicode(m_responseEntityBody); |
1322 m_mime == header.second; |
|
1323 } else { |
|
1324 m_mime = header.second.mid(0, separatorIdx); |
|
1325 int charsetIdx = header.second.indexOf("charset="); |
|
1326 if (charsetIdx != -1) { |
|
1327 charsetIdx += 8; |
|
1328 separatorIdx = header.second.indexOf(';', charsetIdx); |
|
1329 m_charset = header.second.mid(charsetIdx, separatorIdx >= 0 ? separatorIdx : header.second.length()); |
|
1330 } |
|
1331 } |
|
1332 break; |
|
1333 } |
|
1334 } |
|
1335 |
|
1336 if (m_mime.isEmpty() || m_mime == "text/xml" || m_mime == "application/xml" || m_mime.endsWith("+xml")) |
|
1337 m_gotXml = true; |
|
1338 } |
|
1339 |
|
1340 bool QDeclarativeXMLHttpRequest::receivedXml() const |
|
1341 { |
|
1342 return m_gotXml; |
|
1343 } |
|
1344 |
|
1345 |
|
1346 #ifndef QT_NO_TEXTCODEC |
|
1347 QTextCodec* QDeclarativeXMLHttpRequest::findTextCodec() const |
|
1348 { |
|
1349 QTextCodec *codec = 0; |
|
1350 |
|
1351 if (!m_charset.isEmpty()) |
|
1352 codec = QTextCodec::codecForName(m_charset); |
|
1353 |
|
1354 if (!codec && m_gotXml) { |
|
1355 QXmlStreamReader reader(m_responseEntityBody); |
|
1356 reader.readNext(); |
|
1357 codec = QTextCodec::codecForName(reader.documentEncoding().toString().toUtf8()); |
|
1358 } |
|
1359 |
|
1360 if (!codec && m_mime == "text/html") |
|
1361 codec = QTextCodec::codecForHtml(m_responseEntityBody, 0); |
|
1362 |
|
1363 if (!codec) |
|
1364 codec = QTextCodec::codecForUtfText(m_responseEntityBody, 0); |
|
1365 |
|
1366 if (!codec) |
|
1367 codec = QTextCodec::codecForName("UTF-8"); |
|
1368 return codec; |
|
1369 } |
|
1370 #endif |
|
1371 |
|
1372 |
|
1373 QString QDeclarativeXMLHttpRequest::responseBody() |
|
1374 { |
|
1375 #ifndef QT_NO_TEXTCODEC |
|
1376 if (!m_textCodec) |
|
1377 m_textCodec = findTextCodec(); |
|
1378 if (m_textCodec) |
|
1379 return m_textCodec->toUnicode(m_responseEntityBody); |
|
1380 #endif |
1310 |
1381 |
1311 return QString::fromUtf8(m_responseEntityBody); |
1382 return QString::fromUtf8(m_responseEntityBody); |
1312 } |
1383 } |
1313 |
1384 |
1314 const QByteArray &QDeclarativeXMLHttpRequest::rawResponseBody() const |
1385 const QByteArray &QDeclarativeXMLHttpRequest::rawResponseBody() const |
1566 { |
1637 { |
1567 QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject()); |
1638 QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject()); |
1568 if (!request) |
1639 if (!request) |
1569 THROW_REFERENCE("Not an XMLHttpRequest object"); |
1640 THROW_REFERENCE("Not an XMLHttpRequest object"); |
1570 |
1641 |
1571 if (request->readyState() != QDeclarativeXMLHttpRequest::Loading && |
1642 if (!request->receivedXml() || |
|
1643 request->readyState() != QDeclarativeXMLHttpRequest::Loading && |
1572 request->readyState() != QDeclarativeXMLHttpRequest::Done) |
1644 request->readyState() != QDeclarativeXMLHttpRequest::Done) |
1573 return engine->nullValue(); |
1645 return engine->nullValue(); |
1574 else |
1646 else |
1575 return Document::load(engine, request->rawResponseBody()); |
1647 return Document::load(engine, request->rawResponseBody()); |
1576 } |
1648 } |