summaryrefslogtreecommitdiffstats
path: root/tests/auto/network
diff options
context:
space:
mode:
authorJo Asplin <jo.asplin@nokia.com>2011-09-06 13:46:40 +0200
committerJo Asplin <jo.asplin@nokia.com>2011-09-09 09:32:17 +0200
commitc59f9ad7768a007ca7a49ea11b16617529e86d52 (patch)
treed481be2a727f8461a76c2b729fc7e93784a3cff1 /tests/auto/network
parent2d41aff1e8557a43268bce631df834bfa79593cf (diff)
Moved network autotests into new directory structure
Task-number: QTBUG-21223 Change-Id: I55dbf5c42a1c5d938b9e0c9bf7d90457a6c26bbc Reviewed-on: http://codereview.qt-project.org/4259 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Sergio Ahumada <sergio.ahumada@nokia.com> Reviewed-by: Rohan McGovern <rohan.mcgovern@nokia.com>
Diffstat (limited to 'tests/auto/network')
-rw-r--r--tests/auto/network/access/access.pro20
-rw-r--r--tests/auto/network/access/qabstractnetworkcache/.gitignore1
-rw-r--r--tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro14
-rwxr-xr-xtests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_cachecontrol-expire.cgi7
-rwxr-xr-xtests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_cachecontrol.cgi13
-rwxr-xr-xtests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_cachecontrol200.cgi9
-rwxr-xr-xtests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_etag200.cgi5
-rwxr-xr-xtests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_etag304.cgi11
-rwxr-xr-xtests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_expires200.cgi5
-rwxr-xr-xtests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_expires304.cgi11
-rwxr-xr-xtests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_expires500.cgi11
-rwxr-xr-xtests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_lastModified200.cgi5
-rwxr-xr-xtests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_lastModified304.cgi11
-rw-r--r--tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp416
-rw-r--r--tests/auto/network/access/qftp/.gitattributes1
-rw-r--r--tests/auto/network/access/qftp/.gitignore2
-rw-r--r--tests/auto/network/access/qftp/qftp.pro22
-rw-r--r--tests/auto/network/access/qftp/rfc3252.txt899
-rw-r--r--tests/auto/network/access/qftp/tst_qftp.cpp2170
-rw-r--r--tests/auto/network/access/qhttp/.gitattributes1
-rw-r--r--tests/auto/network/access/qhttp/.gitignore1
-rw-r--r--tests/auto/network/access/qhttp/dummyserver.h114
-rw-r--r--tests/auto/network/access/qhttp/qhttp.pro31
-rw-r--r--tests/auto/network/access/qhttp/rfc3252.txt899
-rw-r--r--tests/auto/network/access/qhttp/trolltech8
-rw-r--r--tests/auto/network/access/qhttp/tst_qhttp.cpp1576
-rwxr-xr-xtests/auto/network/access/qhttp/webserver/cgi-bin/retrieve_testfile.cgi6
-rwxr-xr-xtests/auto/network/access/qhttp/webserver/cgi-bin/rfc.cgi5
-rwxr-xr-xtests/auto/network/access/qhttp/webserver/cgi-bin/store_testfile.cgi6
-rw-r--r--tests/auto/network/access/qhttp/webserver/index.html899
-rw-r--r--tests/auto/network/access/qhttp/webserver/rfc3252899
-rw-r--r--tests/auto/network/access/qhttp/webserver/rfc3252.txt899
-rw-r--r--tests/auto/network/access/qhttpnetworkconnection/.gitignore1
-rw-r--r--tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro13
-rw-r--r--tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp1131
-rw-r--r--tests/auto/network/access/qhttpnetworkreply/.gitignore1
-rw-r--r--tests/auto/network/access/qhttpnetworkreply/qhttpnetworkreply.pro7
-rw-r--r--tests/auto/network/access/qhttpnetworkreply/tst_qhttpnetworkreply.cpp134
-rw-r--r--tests/auto/network/access/qnetworkaccessmanager/qnetworkaccessmanager.pro6
-rw-r--r--tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp111
-rw-r--r--tests/auto/network/access/qnetworkcachemetadata/.gitignore1
-rw-r--r--tests/auto/network/access/qnetworkcachemetadata/qnetworkcachemetadata.pro7
-rw-r--r--tests/auto/network/access/qnetworkcachemetadata/tst_qnetworkcachemetadata.cpp373
-rw-r--r--tests/auto/network/access/qnetworkcookie/.gitignore1
-rw-r--r--tests/auto/network/access/qnetworkcookie/qnetworkcookie.pro5
-rw-r--r--tests/auto/network/access/qnetworkcookie/tst_qnetworkcookie.cpp733
-rw-r--r--tests/auto/network/access/qnetworkcookiejar/.gitignore1
-rw-r--r--tests/auto/network/access/qnetworkcookiejar/qnetworkcookiejar.pro5
-rw-r--r--tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp446
-rw-r--r--tests/auto/network/access/qnetworkdiskcache/.gitignore1
-rw-r--r--tests/auto/network/access/qnetworkdiskcache/qnetworkdiskcache.pro7
-rw-r--r--tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp677
-rw-r--r--tests/auto/network/access/qnetworkreply/.gitattributes3
-rw-r--r--tests/auto/network/access/qnetworkreply/.gitignore3
-rw-r--r--tests/auto/network/access/qnetworkreply/bigfile17980
-rw-r--r--tests/auto/network/access/qnetworkreply/certs/aspiriniks.ca.crt22
-rw-r--r--tests/auto/network/access/qnetworkreply/certs/fluke.cert75
-rw-r--r--tests/auto/network/access/qnetworkreply/certs/fluke.key15
-rw-r--r--tests/auto/network/access/qnetworkreply/certs/qt-test-server-cacert.pem17
-rw-r--r--tests/auto/network/access/qnetworkreply/certs/server.key15
-rw-r--r--tests/auto/network/access/qnetworkreply/certs/server.pem24
-rw-r--r--tests/auto/network/access/qnetworkreply/echo/echo.pro6
-rw-r--r--tests/auto/network/access/qnetworkreply/echo/main.cpp62
-rw-r--r--tests/auto/network/access/qnetworkreply/empty0
-rw-r--r--tests/auto/network/access/qnetworkreply/image1.jpgbin0 -> 1045459 bytes
-rw-r--r--tests/auto/network/access/qnetworkreply/image2.jpgbin0 -> 879218 bytes
-rw-r--r--tests/auto/network/access/qnetworkreply/image3.jpgbin0 -> 887729 bytes
-rw-r--r--tests/auto/network/access/qnetworkreply/qnetworkreply.pro7
-rw-r--r--tests/auto/network/access/qnetworkreply/qnetworkreply.qrc5
-rw-r--r--tests/auto/network/access/qnetworkreply/resource283
-rw-r--r--tests/auto/network/access/qnetworkreply/rfc3252.txt899
-rw-r--r--tests/auto/network/access/qnetworkreply/smb-file.txt1
-rw-r--r--tests/auto/network/access/qnetworkreply/test/test.pro38
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp6342
-rw-r--r--tests/auto/network/access/qnetworkrequest/.gitignore1
-rw-r--r--tests/auto/network/access/qnetworkrequest/qnetworkrequest.pro5
-rw-r--r--tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp496
-rw-r--r--tests/auto/network/bearer/bearer.pro6
-rw-r--r--tests/auto/network/bearer/qbearertestcommon.h87
-rw-r--r--tests/auto/network/bearer/qnetworkconfiguration/qnetworkconfiguration.pro15
-rw-r--r--tests/auto/network/bearer/qnetworkconfiguration/tst_qnetworkconfiguration.cpp311
-rw-r--r--tests/auto/network/bearer/qnetworkconfigurationmanager/qnetworkconfigurationmanager.pro15
-rw-r--r--tests/auto/network/bearer/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp378
-rw-r--r--tests/auto/network/bearer/qnetworksession/lackey/lackey.pro15
-rw-r--r--tests/auto/network/bearer/qnetworksession/lackey/main.cpp155
-rw-r--r--tests/auto/network/bearer/qnetworksession/qnetworksession.pro3
-rw-r--r--tests/auto/network/bearer/qnetworksession/test/test.pro26
-rw-r--r--tests/auto/network/bearer/qnetworksession/test/tst_qnetworksession.cpp1683
-rw-r--r--tests/auto/network/kernel/kernel.pro14
-rw-r--r--tests/auto/network/kernel/qauthenticator/qauthenticator.pro5
-rw-r--r--tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp155
-rw-r--r--tests/auto/network/kernel/qhostaddress/.gitignore1
-rw-r--r--tests/auto/network/kernel/qhostaddress/qhostaddress.pro15
-rw-r--r--tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp611
-rw-r--r--tests/auto/network/kernel/qhostinfo/.gitignore1
-rw-r--r--tests/auto/network/kernel/qhostinfo/qhostinfo.pro16
-rw-r--r--tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp665
-rw-r--r--tests/auto/network/kernel/qnetworkaddressentry/.gitignore1
-rw-r--r--tests/auto/network/kernel/qnetworkaddressentry/qnetworkaddressentry.pro6
-rw-r--r--tests/auto/network/kernel/qnetworkaddressentry/tst_qnetworkaddressentry.cpp185
-rw-r--r--tests/auto/network/kernel/qnetworkinterface/.gitignore1
-rw-r--r--tests/auto/network/kernel/qnetworkinterface/qnetworkinterface.pro7
-rw-r--r--tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp241
-rw-r--r--tests/auto/network/kernel/qnetworkproxy/.gitignore1
-rw-r--r--tests/auto/network/kernel/qnetworkproxy/qnetworkproxy.pro11
-rw-r--r--tests/auto/network/kernel/qnetworkproxy/tst_qnetworkproxy.cpp118
-rw-r--r--tests/auto/network/kernel/qnetworkproxyfactory/.gitignore1
-rw-r--r--tests/auto/network/kernel/qnetworkproxyfactory/qnetworkproxyfactory.pro11
-rw-r--r--tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp275
-rw-r--r--tests/auto/network/network.pro8
-rw-r--r--tests/auto/network/socket/platformsocketengine/.gitignore1
-rw-r--r--tests/auto/network/socket/platformsocketengine/platformsocketengine.pri19
-rw-r--r--tests/auto/network/socket/platformsocketengine/platformsocketengine.pro16
-rw-r--r--tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp763
-rw-r--r--tests/auto/network/socket/qabstractsocket/.gitignore1
-rw-r--r--tests/auto/network/socket/qabstractsocket/qabstractsocket.pro11
-rw-r--r--tests/auto/network/socket/qabstractsocket/tst_qabstractsocket.cpp109
-rw-r--r--tests/auto/network/socket/qhttpsocketengine/.gitignore1
-rw-r--r--tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro13
-rw-r--r--tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp748
-rw-r--r--tests/auto/network/socket/qlocalsocket/.gitignore2
-rw-r--r--tests/auto/network/socket/qlocalsocket/example/client/client.pro10
-rw-r--r--tests/auto/network/socket/qlocalsocket/example/client/main.cpp84
-rw-r--r--tests/auto/network/socket/qlocalsocket/example/example.pro3
-rw-r--r--tests/auto/network/socket/qlocalsocket/example/server/main.cpp97
-rw-r--r--tests/auto/network/socket/qlocalsocket/example/server/server.pro13
-rw-r--r--tests/auto/network/socket/qlocalsocket/lackey/lackey.pro16
-rw-r--r--tests/auto/network/socket/qlocalsocket/lackey/main.cpp296
-rwxr-xr-xtests/auto/network/socket/qlocalsocket/lackey/scripts/client.js35
-rw-r--r--tests/auto/network/socket/qlocalsocket/lackey/scripts/server.js19
-rw-r--r--tests/auto/network/socket/qlocalsocket/qlocalsocket.pro4
-rw-r--r--tests/auto/network/socket/qlocalsocket/test/test.pro50
-rw-r--r--tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp1120
-rw-r--r--tests/auto/network/socket/qsocks5socketengine/.gitignore1
-rw-r--r--tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro17
-rw-r--r--tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp963
-rw-r--r--tests/auto/network/socket/qtcpserver/.gitignore3
-rw-r--r--tests/auto/network/socket/qtcpserver/crashingServer/crashingServer.pro9
-rw-r--r--tests/auto/network/socket/qtcpserver/crashingServer/main.cpp70
-rw-r--r--tests/auto/network/socket/qtcpserver/qtcpserver.pro4
-rw-r--r--tests/auto/network/socket/qtcpserver/test/test.pro37
-rw-r--r--tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp817
-rw-r--r--tests/auto/network/socket/qtcpsocket/.gitignore3
-rw-r--r--tests/auto/network/socket/qtcpsocket/qtcpsocket.pro8
-rw-r--r--tests/auto/network/socket/qtcpsocket/stressTest/Test.cpp146
-rw-r--r--tests/auto/network/socket/qtcpsocket/stressTest/Test.h95
-rw-r--r--tests/auto/network/socket/qtcpsocket/stressTest/main.cpp67
-rw-r--r--tests/auto/network/socket/qtcpsocket/stressTest/stressTest.pro12
-rw-r--r--tests/auto/network/socket/qtcpsocket/test/test.pro33
-rw-r--r--tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp2684
-rw-r--r--tests/auto/network/socket/qudpsocket/.gitignore2
-rw-r--r--tests/auto/network/socket/qudpsocket/clientserver/clientserver.pro8
-rw-r--r--tests/auto/network/socket/qudpsocket/clientserver/main.cpp170
-rw-r--r--tests/auto/network/socket/qudpsocket/qudpsocket.pro4
-rw-r--r--tests/auto/network/socket/qudpsocket/test/test.pro28
-rw-r--r--tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp1356
-rw-r--r--tests/auto/network/socket/qudpsocket/udpServer/main.cpp90
-rw-r--r--tests/auto/network/socket/qudpsocket/udpServer/udpServer.pro7
-rw-r--r--tests/auto/network/socket/socket.pro17
-rw-r--r--tests/auto/network/ssl/qsslcertificate/.gitignore1
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/ca-cert.pem33
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/ca-cert.pem.digest-md51
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/ca-cert.pem.digest-sha11
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san-utf8.pem16
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san-utf8.pem.san5
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san.pem13
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san.pem.san5
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.derbin0 -> 461 bytes
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.der.pubkeybin0 -> 162 bytes
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem12
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem.digest-md51
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem.digest-sha11
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem.pubkey6
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert.derbin0 -> 503 bytes
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert.der.pubkeybin0 -> 162 bytes
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert.pem13
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert.pem.digest-md51
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert.pem.digest-sha11
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert.pem.pubkey6
-rwxr-xr-xtests/auto/network/ssl/qsslcertificate/certificates/gencertificates.sh104
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/san.cnf5
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/badguy-nul-cn.crt81
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/badguy-nul-san.crt83
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted-google.com-diginotar.pem30
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted1.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted2.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted3.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted4.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted5.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted6.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted7.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted8.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted9.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-expiration-date.pem15
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-expiration-date.txt.0.9.842
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-expiration-date.txt.1.0.042
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-serial-number.pem14
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/malformed-just-begin-no-newline.pem1
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/malformed-just-begin.pem1
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/natwest-banking.pem36
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/no-ending-newline.pem13
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/test-cn-two-cns-cert.pem67
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/test-cn-with-drink-cert.pem66
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/trailing-whitespace.pem13
-rw-r--r--tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro29
-rw-r--r--tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp995
-rw-r--r--tests/auto/network/ssl/qsslcertificate/verify-certs/README2
-rw-r--r--tests/auto/network/ssl/qsslcertificate/verify-certs/cacert.pem23
-rw-r--r--tests/auto/network/ssl/qsslcertificate/verify-certs/test-addons-mozilla-org-cert.pem34
-rw-r--r--tests/auto/network/ssl/qsslcertificate/verify-certs/test-intermediate-ca-cert.pem66
-rw-r--r--tests/auto/network/ssl/qsslcertificate/verify-certs/test-intermediate-is-ca-cert.pem53
-rw-r--r--tests/auto/network/ssl/qsslcertificate/verify-certs/test-intermediate-not-ca-cert.pem54
-rw-r--r--tests/auto/network/ssl/qsslcertificate/verify-certs/test-ocsp-good-cert.pem67
-rw-r--r--tests/auto/network/ssl/qsslcipher/.gitignore1
-rw-r--r--tests/auto/network/ssl/qsslcipher/qsslcipher.pro18
-rw-r--r--tests/auto/network/ssl/qsslcipher/tst_qsslcipher.cpp101
-rw-r--r--tests/auto/network/ssl/qsslerror/.gitignore1
-rw-r--r--tests/auto/network/ssl/qsslerror/qsslerror.pro18
-rw-r--r--tests/auto/network/ssl/qsslerror/tst_qsslerror.cpp122
-rw-r--r--tests/auto/network/ssl/qsslkey/.gitignore1
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-1024.derbin0 -> 447 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-1024.pem12
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512.derbin0 -> 251 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-576.derbin0 -> 275 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-576.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-960.derbin0 -> 419 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-960.pem11
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-1024.derbin0 -> 442 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-1024.pem12
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-512.derbin0 -> 244 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-512.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-576.derbin0 -> 268 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-576.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-960.derbin0 -> 414 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-960.pem11
-rwxr-xr-xtests/auto/network/ssl/qsslkey/keys/genkeys.sh82
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-1023.derbin0 -> 605 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-1023.pem15
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-1024.derbin0 -> 608 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-1024.pem15
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-2048.derbin0 -> 1190 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-2048.pem27
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-40.derbin0 -> 49 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-40.pem4
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-511.derbin0 -> 316 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-511.pem9
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512.derbin0 -> 320 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512.pem9
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-999.derbin0 -> 591 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-999.pem15
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-1023.derbin0 -> 161 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-1023.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-1024.derbin0 -> 162 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-1024.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-2048.derbin0 -> 294 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-2048.pem9
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-40.derbin0 -> 35 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-40.pem3
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-511.derbin0 -> 93 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-511.pem4
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-512.derbin0 -> 94 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-512.pem4
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-999.derbin0 -> 157 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-999.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/qsslkey.pro32
-rw-r--r--tests/auto/network/ssl/qsslkey/rsa-with-passphrase.pem18
-rw-r--r--tests/auto/network/ssl/qsslkey/rsa-without-passphrase.pem15
-rw-r--r--tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp447
-rw-r--r--tests/auto/network/ssl/qsslsocket/.gitignore1
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/aspiriniks.ca.crt22
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/fake-login.live.com.key15
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/fake-login.live.com.pem19
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/fluke.cert75
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/fluke.key15
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/qt-test-server-cacert.pem17
-rw-r--r--tests/auto/network/ssl/qsslsocket/qsslsocket.pro48
-rw-r--r--tests/auto/network/ssl/qsslsocket/ssl.tar.gzbin0 -> 36299 bytes
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp2097
-rw-r--r--tests/auto/network/ssl/ssl.pro8
280 files changed, 59668 insertions, 0 deletions
diff --git a/tests/auto/network/access/access.pro b/tests/auto/network/access/access.pro
new file mode 100644
index 0000000000..53b16f07b8
--- /dev/null
+++ b/tests/auto/network/access/access.pro
@@ -0,0 +1,20 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qnetworkdiskcache \
+ qnetworkcookiejar \
+ qnetworkaccessmanager \
+ qnetworkcookie \
+ qnetworkrequest \
+ qhttpnetworkconnection \
+ qnetworkreply \
+ qnetworkcachemetadata \
+ qftp \
+ qhttpnetworkreply \
+ qhttp \
+ qabstractnetworkcache \
+
+!contains(QT_CONFIG, private_tests): SUBDIRS -= \
+ qhttpnetworkconnection \
+ qhttpnetworkreply \
+
+
diff --git a/tests/auto/network/access/qabstractnetworkcache/.gitignore b/tests/auto/network/access/qabstractnetworkcache/.gitignore
new file mode 100644
index 0000000000..72766dddce
--- /dev/null
+++ b/tests/auto/network/access/qabstractnetworkcache/.gitignore
@@ -0,0 +1 @@
+tst_qabstractnetworkcache
diff --git a/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro b/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro
new file mode 100644
index 0000000000..4dea3c9c8c
--- /dev/null
+++ b/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro
@@ -0,0 +1,14 @@
+load(qttest_p4)
+QT += network
+QT -= gui
+SOURCES += tst_qabstractnetworkcache.cpp
+
+wince*|symbian: {
+ testFiles.files = tests
+ testFiles.path = .
+ DEPLOYMENT += testFiles
+}
+
+symbian: TARGET.CAPABILITY = NetworkServices
+
+CONFIG += insignificant_test # QTBUG-20686; note, assumed unstable on all platforms
diff --git a/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_cachecontrol-expire.cgi b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_cachecontrol-expire.cgi
new file mode 100755
index 0000000000..7dc506fc1e
--- /dev/null
+++ b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_cachecontrol-expire.cgi
@@ -0,0 +1,7 @@
+#!/bin/bash
+# cache control takes precedence over expires
+echo "Cache-Control: max-age=-1"
+echo "Expires: Mon, 30 Oct 2028 14:19:41 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_cachecontrol.cgi b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_cachecontrol.cgi
new file mode 100755
index 0000000000..f2edfc161f
--- /dev/null
+++ b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_cachecontrol.cgi
@@ -0,0 +1,13 @@
+#!/bin/bash
+if [ ! -z ${HTTP_IF_MODIFIED_SINCE} ] ; then
+ echo "Status: 304"
+ echo ""
+ exit;
+fi
+
+cc=`echo "${QUERY_STRING}" | sed -e s/%20/\ /g`
+echo "Cache-Control: $cc"
+echo "Last-Modified: Sat, 31 Oct 1981 06:00:00 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_cachecontrol200.cgi b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_cachecontrol200.cgi
new file mode 100755
index 0000000000..e44d5ed570
--- /dev/null
+++ b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_cachecontrol200.cgi
@@ -0,0 +1,9 @@
+#!/bin/bash
+cc=`echo "${QUERY_STRING}" | sed -e s/%20/\ /g`
+echo "Status: 200"
+echo "Cache-Control: $cc"
+echo "Last-Modified: Sat, 31 Oct 1981 06:00:00 GMT"
+echo "Content-type: text/html";
+echo "X-Script: $0"
+echo ""
+echo "Hello World!"
diff --git a/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_etag200.cgi b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_etag200.cgi
new file mode 100755
index 0000000000..0966abfdd1
--- /dev/null
+++ b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_etag200.cgi
@@ -0,0 +1,5 @@
+#!/bin/bash
+echo "ETag: foo"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_etag304.cgi b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_etag304.cgi
new file mode 100755
index 0000000000..91a4b922bd
--- /dev/null
+++ b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_etag304.cgi
@@ -0,0 +1,11 @@
+#!/bin/bash
+if [ ! -z ${HTTP_IF_NONE_MATCH} ] ; then
+ echo "Status: 304"
+ echo ""
+ exit;
+fi
+
+echo "ETag: foo"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_expires200.cgi b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_expires200.cgi
new file mode 100755
index 0000000000..e18ebc86ad
--- /dev/null
+++ b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_expires200.cgi
@@ -0,0 +1,5 @@
+#!/bin/bash
+echo "Expires: Sat, 31 Oct 1981 6:00:00 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_expires304.cgi b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_expires304.cgi
new file mode 100755
index 0000000000..1c7de1cd77
--- /dev/null
+++ b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_expires304.cgi
@@ -0,0 +1,11 @@
+#!/bin/bash
+if [ ${HTTP_IF_MODIFIED_SINCE} == "Mon, 30 Oct 2028 14:19:41 GMT" ] ; then
+ echo "Status: 304"
+ echo ""
+ exit;
+fi
+
+echo "Expires: Mon, 30 Oct 2028 14:19:41 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_expires500.cgi b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_expires500.cgi
new file mode 100755
index 0000000000..9615c4f0bd
--- /dev/null
+++ b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_expires500.cgi
@@ -0,0 +1,11 @@
+#!/bin/bash
+if [ ! -z ${HTTP_IF_MODIFIED_SINCE} ] ; then
+ echo "Status: 500"
+ echo ""
+ exit;
+fi
+
+echo "Expires: Mon, 30 Oct 2028 14:19:41 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_lastModified200.cgi b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_lastModified200.cgi
new file mode 100755
index 0000000000..5dc219b1e7
--- /dev/null
+++ b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_lastModified200.cgi
@@ -0,0 +1,5 @@
+#!/bin/bash
+echo "Last-Modified: Sat, 31 Oct 1981 6:00:00 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_lastModified304.cgi b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_lastModified304.cgi
new file mode 100755
index 0000000000..bdf23bed2f
--- /dev/null
+++ b/tests/auto/network/access/qabstractnetworkcache/tests/httpcachetest_lastModified304.cgi
@@ -0,0 +1,11 @@
+#!/bin/bash
+if [ ${HTTP_IF_MODIFIED_SINCE} == "Sat, 31 Oct 1981 06:00:00 GMT" ] ; then
+ echo "Status: 304"
+ echo ""
+ exit;
+fi
+
+echo "Last-Modified: Sat, 31 Oct 1981 06:00:00 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp b/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp
new file mode 100644
index 0000000000..244c9b13b5
--- /dev/null
+++ b/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp
@@ -0,0 +1,416 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtNetwork/QtNetwork>
+#include "../../../../shared/util.h"
+#include "../../../network-settings.h"
+
+#ifndef QT_NO_BEARERMANAGEMENT
+#include <QtNetwork/qnetworkconfigmanager.h>
+#include <QtNetwork/qnetworkconfiguration.h>
+#include <QtNetwork/qnetworksession.h>
+#endif
+
+#define TESTFILE QString("http://%1/qtest/cgi-bin/").arg(QtNetworkSettings::serverName())
+
+class tst_QAbstractNetworkCache : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QAbstractNetworkCache();
+ virtual ~tst_QAbstractNetworkCache();
+
+private slots:
+ void initTestCase();
+ void expires_data();
+ void expires();
+ void expiresSynchronous_data();
+ void expiresSynchronous();
+
+ void lastModified_data();
+ void lastModified();
+ void lastModifiedSynchronous_data();
+ void lastModifiedSynchronous();
+
+ void etag_data();
+ void etag();
+ void etagSynchronous_data();
+ void etagSynchronous();
+
+ void cacheControl_data();
+ void cacheControl();
+ void cacheControlSynchronous_data();
+ void cacheControlSynchronous();
+
+ void deleteCache();
+
+private:
+ void check();
+ void checkSynchronous();
+
+#ifndef QT_NO_BEARERMANAGEMENT
+ QNetworkConfigurationManager *netConfMan;
+ QNetworkConfiguration networkConfiguration;
+ QScopedPointer<QNetworkSession> networkSession;
+#endif
+};
+
+class NetworkDiskCache : public QNetworkDiskCache
+{
+ Q_OBJECT
+public:
+ NetworkDiskCache(QObject *parent = 0)
+ : QNetworkDiskCache(parent)
+ , gotData(false)
+ {
+ QString location = QDir::tempPath() + QLatin1String("/tst_qnetworkdiskcache/");
+ setCacheDirectory(location);
+ clear();
+ }
+
+ QIODevice *data(const QUrl &url)
+ {
+ gotData = true;
+ return QNetworkDiskCache::data(url);
+ }
+
+ bool gotData;
+};
+
+
+tst_QAbstractNetworkCache::tst_QAbstractNetworkCache()
+{
+ Q_SET_DEFAULT_IAP
+
+ QCoreApplication::setOrganizationName(QLatin1String("Trolltech"));
+ QCoreApplication::setApplicationName(QLatin1String("autotest_qabstractnetworkcache"));
+ QCoreApplication::setApplicationVersion(QLatin1String("1.0"));
+}
+
+tst_QAbstractNetworkCache::~tst_QAbstractNetworkCache()
+{
+}
+
+static bool AlwaysTrue = true;
+static bool AlwaysFalse = false;
+
+Q_DECLARE_METATYPE(QNetworkRequest::CacheLoadControl)
+
+
+void tst_QAbstractNetworkCache::initTestCase()
+{
+#ifndef QT_NO_BEARERMANAGEMENT
+ netConfMan = new QNetworkConfigurationManager(this);
+ networkConfiguration = netConfMan->defaultConfiguration();
+ networkSession.reset(new QNetworkSession(networkConfiguration));
+ if (!networkSession->isOpen()) {
+ networkSession->open();
+ QVERIFY(networkSession->waitForOpened(30000));
+ }
+#endif
+}
+
+
+void tst_QAbstractNetworkCache::expires_data()
+{
+ QTest::addColumn<QNetworkRequest::CacheLoadControl>("cacheLoadControl");
+ QTest::addColumn<QString>("url");
+ QTest::addColumn<bool>("fetchFromCache");
+
+ QTest::newRow("304-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_expires304.cgi" << AlwaysFalse;
+ QTest::newRow("304-1") << QNetworkRequest::PreferNetwork << "httpcachetest_expires304.cgi" << true;
+ QTest::newRow("304-2") << QNetworkRequest::AlwaysCache << "httpcachetest_expires304.cgi" << AlwaysTrue;
+ QTest::newRow("304-3") << QNetworkRequest::PreferCache << "httpcachetest_expires304.cgi" << true;
+
+ QTest::newRow("500-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_expires500.cgi" << AlwaysFalse;
+ QTest::newRow("500-1") << QNetworkRequest::PreferNetwork << "httpcachetest_expires500.cgi" << true;
+ QTest::newRow("500-2") << QNetworkRequest::AlwaysCache << "httpcachetest_expires500.cgi" << AlwaysTrue;
+ QTest::newRow("500-3") << QNetworkRequest::PreferCache << "httpcachetest_expires500.cgi" << true;
+
+ QTest::newRow("200-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_expires200.cgi" << AlwaysFalse;
+ QTest::newRow("200-1") << QNetworkRequest::PreferNetwork << "httpcachetest_expires200.cgi" << false;
+ QTest::newRow("200-2") << QNetworkRequest::AlwaysCache << "httpcachetest_expires200.cgi" << AlwaysTrue;
+ QTest::newRow("200-3") << QNetworkRequest::PreferCache << "httpcachetest_expires200.cgi" << false;
+}
+
+void tst_QAbstractNetworkCache::expires()
+{
+ check();
+}
+
+void tst_QAbstractNetworkCache::expiresSynchronous_data()
+{
+ expires_data();
+}
+
+void tst_QAbstractNetworkCache::expiresSynchronous()
+{
+ checkSynchronous();
+}
+
+void tst_QAbstractNetworkCache::lastModified_data()
+{
+ QTest::addColumn<QNetworkRequest::CacheLoadControl>("cacheLoadControl");
+ QTest::addColumn<QString>("url");
+ QTest::addColumn<bool>("fetchFromCache");
+
+ QTest::newRow("304-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_lastModified304.cgi" << AlwaysFalse;
+ QTest::newRow("304-1") << QNetworkRequest::PreferNetwork << "httpcachetest_lastModified304.cgi" << true;
+ QTest::newRow("304-2") << QNetworkRequest::AlwaysCache << "httpcachetest_lastModified304.cgi" << AlwaysTrue;
+ QTest::newRow("304-3") << QNetworkRequest::PreferCache << "httpcachetest_lastModified304.cgi" << true;
+
+ QTest::newRow("200-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_lastModified200.cgi" << AlwaysFalse;
+ QTest::newRow("200-1") << QNetworkRequest::PreferNetwork << "httpcachetest_lastModified200.cgi" << false;
+ QTest::newRow("200-2") << QNetworkRequest::AlwaysCache << "httpcachetest_lastModified200.cgi" << AlwaysTrue;
+ QTest::newRow("200-3") << QNetworkRequest::PreferCache << "httpcachetest_lastModified200.cgi" << false;
+}
+
+void tst_QAbstractNetworkCache::lastModified()
+{
+ check();
+}
+
+void tst_QAbstractNetworkCache::lastModifiedSynchronous_data()
+{
+ tst_QAbstractNetworkCache::lastModified_data();
+}
+
+void tst_QAbstractNetworkCache::lastModifiedSynchronous()
+{
+ checkSynchronous();
+}
+
+void tst_QAbstractNetworkCache::etag_data()
+{
+ QTest::addColumn<QNetworkRequest::CacheLoadControl>("cacheLoadControl");
+ QTest::addColumn<QString>("url");
+ QTest::addColumn<bool>("fetchFromCache");
+
+ QTest::newRow("304-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_etag304.cgi" << AlwaysFalse;
+ QTest::newRow("304-1") << QNetworkRequest::PreferNetwork << "httpcachetest_etag304.cgi" << true;
+ QTest::newRow("304-2") << QNetworkRequest::AlwaysCache << "httpcachetest_etag304.cgi" << AlwaysTrue;
+ QTest::newRow("304-3") << QNetworkRequest::PreferCache << "httpcachetest_etag304.cgi" << true;
+
+ QTest::newRow("200-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_etag200.cgi" << AlwaysFalse;
+ QTest::newRow("200-1") << QNetworkRequest::PreferNetwork << "httpcachetest_etag200.cgi" << false;
+ QTest::newRow("200-2") << QNetworkRequest::AlwaysCache << "httpcachetest_etag200.cgi" << AlwaysTrue;
+ QTest::newRow("200-3") << QNetworkRequest::PreferCache << "httpcachetest_etag200.cgi" << false;
+}
+
+void tst_QAbstractNetworkCache::etag()
+{
+ check();
+}
+
+void tst_QAbstractNetworkCache::etagSynchronous_data()
+{
+ tst_QAbstractNetworkCache::etag_data();
+}
+
+void tst_QAbstractNetworkCache::etagSynchronous()
+{
+ checkSynchronous();
+}
+
+void tst_QAbstractNetworkCache::cacheControl_data()
+{
+ QTest::addColumn<QNetworkRequest::CacheLoadControl>("cacheLoadControl");
+ QTest::addColumn<QString>("url");
+ QTest::addColumn<bool>("fetchFromCache");
+ QTest::newRow("200-0") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol.cgi?max-age=-1" << true;
+ QTest::newRow("200-1") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol-expire.cgi" << false;
+
+ QTest::newRow("200-2") << QNetworkRequest::AlwaysNetwork << "httpcachetest_cachecontrol.cgi?no-cache" << AlwaysFalse;
+ QTest::newRow("200-3") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol.cgi?no-cache" << false;
+ QTest::newRow("200-4") << QNetworkRequest::AlwaysCache << "httpcachetest_cachecontrol.cgi?no-cache" << false;
+ QTest::newRow("200-5") << QNetworkRequest::PreferCache << "httpcachetest_cachecontrol.cgi?no-cache" << false;
+
+ QTest::newRow("304-0") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol.cgi?max-age=1000" << true;
+
+ QTest::newRow("304-1") << QNetworkRequest::AlwaysNetwork << "httpcachetest_cachecontrol.cgi?max-age=1000, must-revalidate" << AlwaysFalse;
+ QTest::newRow("304-2") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol.cgi?max-age=1000, must-revalidate" << true;
+ QTest::newRow("304-3") << QNetworkRequest::AlwaysCache << "httpcachetest_cachecontrol.cgi?max-age=1000, must-revalidate" << false;
+ QTest::newRow("304-4") << QNetworkRequest::PreferCache << "httpcachetest_cachecontrol.cgi?max-age=1000, must-revalidate" << true;
+
+ // see QTBUG-7060
+ //QTest::newRow("nokia-boston") << QNetworkRequest::PreferNetwork << "http://waplabdc.nokia-boston.com/browser/users/venkat/cache/Cache_directives/private_1b.asp" << true;
+ QTest::newRow("304-2b") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol200.cgi?private, max-age=1000" << true;
+ QTest::newRow("304-4b") << QNetworkRequest::PreferCache << "httpcachetest_cachecontrol200.cgi?private, max-age=1000" << true;
+}
+
+void tst_QAbstractNetworkCache::cacheControl()
+{
+ check();
+}
+
+void tst_QAbstractNetworkCache::cacheControlSynchronous_data()
+{
+ tst_QAbstractNetworkCache::cacheControl_data();
+}
+
+void tst_QAbstractNetworkCache::cacheControlSynchronous()
+{
+ checkSynchronous();
+}
+
+void tst_QAbstractNetworkCache::check()
+{
+ QFETCH(QNetworkRequest::CacheLoadControl, cacheLoadControl);
+ QFETCH(QString, url);
+ QFETCH(bool, fetchFromCache);
+
+ QNetworkAccessManager manager;
+ NetworkDiskCache *diskCache = new NetworkDiskCache(&manager);
+ manager.setCache(diskCache);
+ QCOMPARE(diskCache->gotData, false);
+
+ QUrl realUrl = url.contains("://") ? url : TESTFILE + url;
+ QNetworkRequest request(realUrl);
+
+ // prime the cache
+ QNetworkReply *reply = manager.get(request);
+ QSignalSpy downloaded1(reply, SIGNAL(finished()));
+ QTRY_COMPARE(downloaded1.count(), 1);
+ QCOMPARE(diskCache->gotData, false);
+ QByteArray goodData = reply->readAll();
+
+ request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, cacheLoadControl);
+
+ // should be in the cache now
+ QNetworkReply *reply2 = manager.get(request);
+ QSignalSpy downloaded2(reply2, SIGNAL(finished()));
+ QTRY_COMPARE(downloaded2.count(), 1);
+
+ QByteArray secondData = reply2->readAll();
+ if (!fetchFromCache && cacheLoadControl == QNetworkRequest::AlwaysCache) {
+ QCOMPARE(reply2->error(), QNetworkReply::ContentNotFoundError);
+ QCOMPARE(secondData, QByteArray());
+ } else {
+ QCOMPARE(reply2->error(), QNetworkReply::NoError);
+ QCOMPARE(QString(secondData), QString(goodData));
+ QCOMPARE(secondData, goodData);
+ QCOMPARE(reply2->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
+ }
+
+ if (fetchFromCache) {
+ QList<QByteArray> rawHeaderList = reply->rawHeaderList();
+ QList<QByteArray> rawHeaderList2 = reply2->rawHeaderList();
+ qSort(rawHeaderList);
+ qSort(rawHeaderList2);
+ }
+ QCOMPARE(diskCache->gotData, fetchFromCache);
+}
+
+void tst_QAbstractNetworkCache::checkSynchronous()
+{
+ QSKIP("not working yet, see QTBUG-15221", SkipAll);
+
+ QFETCH(QNetworkRequest::CacheLoadControl, cacheLoadControl);
+ QFETCH(QString, url);
+ QFETCH(bool, fetchFromCache);
+
+ QNetworkAccessManager manager;
+ NetworkDiskCache *diskCache = new NetworkDiskCache(&manager);
+ manager.setCache(diskCache);
+ QCOMPARE(diskCache->gotData, false);
+
+ QUrl realUrl = url.contains("://") ? url : TESTFILE + url;
+ QNetworkRequest request(realUrl);
+
+ request.setAttribute(
+ QNetworkRequest::SynchronousRequestAttribute,
+ true);
+
+ // prime the cache
+ QNetworkReply *reply = manager.get(request);
+ QVERIFY(reply->isFinished()); // synchronous
+ QCOMPARE(diskCache->gotData, false);
+ QByteArray goodData = reply->readAll();
+
+ request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, cacheLoadControl);
+
+ // should be in the cache now
+ QNetworkReply *reply2 = manager.get(request);
+ QVERIFY(reply2->isFinished()); // synchronous
+
+ QByteArray secondData = reply2->readAll();
+ if (!fetchFromCache && cacheLoadControl == QNetworkRequest::AlwaysCache) {
+ QCOMPARE(reply2->error(), QNetworkReply::ContentNotFoundError);
+ QCOMPARE(secondData, QByteArray());
+ } else {
+ if (reply2->error() != QNetworkReply::NoError)
+ qDebug() << reply2->errorString();
+ QCOMPARE(reply2->error(), QNetworkReply::NoError);
+ QCOMPARE(QString(secondData), QString(goodData));
+ QCOMPARE(secondData, goodData);
+ QCOMPARE(reply2->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
+ }
+
+ if (fetchFromCache) {
+ QList<QByteArray> rawHeaderList = reply->rawHeaderList();
+ QList<QByteArray> rawHeaderList2 = reply2->rawHeaderList();
+ qSort(rawHeaderList);
+ qSort(rawHeaderList2);
+ }
+ QCOMPARE(diskCache->gotData, fetchFromCache);
+}
+
+void tst_QAbstractNetworkCache::deleteCache()
+{
+ QNetworkAccessManager manager;
+ NetworkDiskCache *diskCache = new NetworkDiskCache(&manager);
+ manager.setCache(diskCache);
+
+ QString url = "httpcachetest_cachecontrol.cgi?max-age=1000";
+ QNetworkRequest request(QUrl(TESTFILE + url));
+ QNetworkReply *reply = manager.get(request);
+ QSignalSpy downloaded1(reply, SIGNAL(finished()));
+ manager.setCache(0);
+ QTRY_COMPARE(downloaded1.count(), 1);
+}
+
+
+QTEST_MAIN(tst_QAbstractNetworkCache)
+#include "tst_qabstractnetworkcache.moc"
+
diff --git a/tests/auto/network/access/qftp/.gitattributes b/tests/auto/network/access/qftp/.gitattributes
new file mode 100644
index 0000000000..e04709aa2e
--- /dev/null
+++ b/tests/auto/network/access/qftp/.gitattributes
@@ -0,0 +1 @@
+rfc3252.txt -crlf
diff --git a/tests/auto/network/access/qftp/.gitignore b/tests/auto/network/access/qftp/.gitignore
new file mode 100644
index 0000000000..7a4845df05
--- /dev/null
+++ b/tests/auto/network/access/qftp/.gitignore
@@ -0,0 +1,2 @@
+tst_qftp
+tst_QFtp_activeMode_inittab
diff --git a/tests/auto/network/access/qftp/qftp.pro b/tests/auto/network/access/qftp/qftp.pro
new file mode 100644
index 0000000000..8f63d6e26e
--- /dev/null
+++ b/tests/auto/network/access/qftp/qftp.pro
@@ -0,0 +1,22 @@
+load(qttest_p4)
+SOURCES += tst_qftp.cpp
+
+
+QT = core network network-private
+
+wince*: {
+ addFiles.files = rfc3252.txt
+ addFiles.path = .
+ DEPLOYMENT += addFiles
+ DEFINES += SRCDIR=\\\"\\\"
+} else:symbian {
+ addFiles.files = rfc3252.txt
+ addFiles.path = .
+ DEPLOYMENT += addFiles
+ TARGET.EPOCHEAPSIZE="0x100 0x1000000"
+ TARGET.CAPABILITY = NetworkServices
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
+
+CONFIG+=insignificant_test # uses live qt-test-server, inherently unstable
diff --git a/tests/auto/network/access/qftp/rfc3252.txt b/tests/auto/network/access/qftp/rfc3252.txt
new file mode 100644
index 0000000000..b80c61bf0a
--- /dev/null
+++ b/tests/auto/network/access/qftp/rfc3252.txt
@@ -0,0 +1,899 @@
+
+
+
+
+
+
+Network Working Group H. Kennedy
+Request for Comments: 3252 Mimezine
+Category: Informational 1 April 2002
+
+
+ Binary Lexical Octet Ad-hoc Transport
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ This document defines a reformulation of IP and two transport layer
+ protocols (TCP and UDP) as XML applications.
+
+1. Introduction
+
+1.1. Overview
+
+ This document describes the Binary Lexical Octet Ad-hoc Transport
+ (BLOAT): a reformulation of a widely-deployed network-layer protocol
+ (IP [RFC791]), and two associated transport layer protocols (TCP
+ [RFC793] and UDP [RFC768]) as XML [XML] applications. It also
+ describes methods for transporting BLOAT over Ethernet and IEEE 802
+ networks as well as encapsulating BLOAT in IP for gatewaying BLOAT
+ across the public Internet.
+
+1.2. Motivation
+
+ The wild popularity of XML as a basis for application-level protocols
+ such as the Blocks Extensible Exchange Protocol [RFC3080], the Simple
+ Object Access Protocol [SOAP], and Jabber [JABBER] prompted
+ investigation into the possibility of extending the use of XML in the
+ protocol stack. Using XML at both the transport and network layer in
+ addition to the application layer would provide for an amazing amount
+ of power and flexibility while removing dependencies on proprietary
+ and hard-to-understand binary protocols. This protocol unification
+ would also allow applications to use a single XML parser for all
+ aspects of their operation, eliminating developer time spent figuring
+ out the intricacies of each new protocol, and moving the hard work of
+
+
+
+
+Kennedy Informational [Page 1]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ parsing to the XML toolset. The use of XML also mitigates concerns
+ over "network vs. host" byte ordering which is at the root of many
+ network application bugs.
+
+1.3. Relation to Existing Protocols
+
+ The reformulations specified in this RFC follow as closely as
+ possible the spirit of the RFCs on which they are based, and so MAY
+ contain elements or attributes that would not be needed in a pure
+ reworking (e.g. length attributes, which are implicit in XML.)
+
+ The layering of network and transport protocols are maintained in
+ this RFC despite the optimizations that could be made if the line
+ were somewhat blurred (i.e. merging TCP and IP into a single, larger
+ element in the DTD) in order to foster future use of this protocol as
+ a basis for reformulating other protocols (such as ICMP.)
+
+ Other than the encoding, the behavioral aspects of each of the
+ existing protocols remain unchanged. Routing, address spaces, TCP
+ congestion control, etc. behave as specified in the extant standards.
+ Adapting to new standards and experimental algorithm heuristics for
+ improving performance will become much easier once the move to BLOAT
+ has been completed.
+
+1.4. Requirement Levels
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in BCP 14, RFC 2119
+ [RFC2119].
+
+2. IPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC.
+ IPoXML is the root protocol REQUIRED for effective use of TCPoXML
+ (section 3.) and higher-level application protocols.
+
+ The DTD for this document type can be found in section 7.1.
+
+ The routing of IPoXML can be easily implemented on hosts with an XML
+ parser, as the regular structure lends itself handily to parsing and
+ validation of the document/datagram and then processing the
+ destination address, TTL, and checksum before sending it on to its
+ next-hop.
+
+ The reformulation of IPv4 was chosen over IPv6 [RFC2460] due to the
+ wider deployment of IPv4 and the fact that implementing IPv6 as XML
+ would have exceeded the 1500 byte Ethernet MTU.
+
+
+
+Kennedy Informational [Page 2]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ All BLOAT implementations MUST use - and specify - the UTF-8 encoding
+ of RFC 2279 [RFC2279]. All BLOAT document/datagrams MUST be well-
+ formed and include the XMLDecl.
+
+2.1. IP Description
+
+ A number of items have changed (for the better) from the original IP
+ specification. Bit-masks, where present have been converted into
+ human-readable values. IP addresses are listed in their dotted-
+ decimal notation [RFC1123]. Length and checksum values are present
+ as decimal integers.
+
+ To calculate the length and checksum fields of the IP element, a
+ canonicalized form of the element MUST be used. The canonical form
+ SHALL have no whitespace (including newline characters) between
+ elements and only one space character between attributes. There
+ SHALL NOT be a space following the last attribute in an element.
+
+ An iterative method SHOULD be used to calculate checksums, as the
+ length field will vary based on the size of the checksum.
+
+ The payload element bears special attention. Due to the character
+ set restrictions of XML, the payload of IP datagrams (which MAY
+ contain arbitrary data) MUST be encoded for transport. This RFC
+ REQUIRES the contents of the payload to be encoded in the base-64
+ encoding of RFC 2045 [RFC2045], but removes the requirement that the
+ encoded output MUST be wrapped on 76-character lines.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 3]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+2.2. Example Datagram
+
+ The following is an example IPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ <ip>
+ <header length="474">
+ <version value="4"/>
+ <tos precedence="Routine" delay="Normal" throughput="Normal"
+ relibility="Normal" reserved="0"/>
+ <total.length value="461"/>
+ <id value="1"/>
+ <flags reserved="0" df="dont" mf="last"/>
+ <offset value="0"/>
+ <ttl value="255"/>
+ <protocol value="6"/>
+ <checksum value="8707"/>
+ <source address="10.0.0.22"/>
+ <destination address="10.0.0.1"/>
+ <options>
+ <end copied="0" class="0" number="0"/>
+ </options>
+ <padding pad="0"/>
+ </header>
+ <payload>
+ </payload>
+ </ip>
+
+3. TCPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.2.
+
+3.1. TCP Description
+
+ A number of items have changed from the original TCP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+ To calculate the length and checksum fields of the TCP element, a
+ canonicalized form of the element MUST be used as in section 2.1.
+
+ An iterative method SHOULD be used to calculate checksums as in
+ section 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+
+
+Kennedy Informational [Page 4]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ The TCP offset element was expanded to a maximum of 255 from 16 to
+ allow for the increased size of the header in XML.
+
+ TCPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+3.2. Example Datagram
+
+ The following is an example TCPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ <tcp>
+ <tcp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <sequence number="322622954"/>
+ <acknowledgement number="689715995"/>
+ <offset number=""/>
+ <reserved value="0"/>
+ <control syn="1" ack="1"/>
+ <window size="1"/>
+ <urgent pointer="0"/>
+ <checksum value="2988"/>
+ <tcp.options>
+ <tcp.end kind="0"/>
+ </tcp.options>
+ <padding pad="0"/>
+ </tcp.header>
+ <payload>
+ </payload>
+ </tcp>
+
+4. UDPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.3.
+
+4.1. UDP Description
+
+ A number of items have changed from the original UDP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+
+
+
+
+
+
+Kennedy Informational [Page 5]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ To calculate the length and checksum fields of the UDP element, a
+ canonicalized form of the element MUST be used as in section 2.1. An
+ iterative method SHOULD be used to calculate checksums as in section
+ 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+ UDPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+4.2. Example Datagram
+
+ The following is an example UDPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ <udp>
+ <udp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <udp.length value="143"/>
+ <checksum value="2988"/>
+ </udp.header>
+ <payload>
+ </payload>
+ </udp>
+
+5. Network Transport
+
+ This document provides for the transmission of BLOAT datagrams over
+ two common families of physical layer transport. Future RFCs will
+ address additional transports as routing vendors catch up to the
+ specification, and we begin to see BLOAT routed across the Internet
+ backbone.
+
+5.1. Ethernet
+
+ BLOAT is encapsulated in Ethernet datagrams as in [RFC894] with the
+ exception that the type field of the Ethernet frame MUST contain the
+ value 0xBEEF. The first 5 octets of the Ethernet frame payload will
+ be 0x3c 3f 78 6d 6c ("<?xml".)
+
+5.2. IEEE 802
+
+ BLOAT is encapsulated in IEEE 802 Networks as in [RFC1042] except
+ that the protocol type code for IPoXML is 0xBEEF.
+
+
+
+
+
+Kennedy Informational [Page 6]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+6. Gatewaying over IP
+
+ In order to facilitate the gradual introduction of BLOAT into the
+ public Internet, BLOAT MAY be encapsulated in IP as in [RFC2003] to
+ gateway between networks that run BLOAT natively on their LANs.
+
+7. DTDs
+
+ The Transport DTDs (7.2. and 7.3.) build on the definitions in the
+ Network DTD (7.1.)
+
+ The DTDs are referenced by their PubidLiteral and SystemLiteral (from
+ [XML]) although it is understood that most IPoXML implementations
+ will not need to pull down the DTD, as it will normally be embedded
+ in the implementation, and presents something of a catch-22 if you
+ need to load part of your network protocol over the network.
+
+7.1. IPoXML DTD
+
+ <!--
+ DTD for IP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ -->
+ <!--
+ DTD data types:
+
+ Digits [0..9]+
+
+ Precedence "NetworkControl | InternetworkControl |
+ CRITIC | FlashOverride | Flash | Immediate |
+ Priority | Routine"
+
+ IP4Addr "dotted-decimal" notation of [RFC1123]
+
+ Class [0..3]
+
+ Sec "Unclassified | Confidential | EFTO | MMMM | PROG |
+ Restricted | Secret | Top Secret | Reserved"
+
+ Compartments [0..65535]
+
+ Handling [0..65535]
+
+ TCC [0..16777216]
+
+ -->
+
+
+
+Kennedy Informational [Page 7]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ENTITY % Digits "CDATA">
+ <!ENTITY % Precedence "CDATA">
+ <!ENTITY % IP4Addr "CDATA">
+ <!ENTITY % Class "CDATA">
+ <!ENTITY % Sec "CDATA">
+ <!ENTITY % Compartments "CDATA">
+ <!ENTITY % Handling "CDATA">
+ <!ENTITY % TCC "CDATA">
+
+ <!ELEMENT ip (header, payload)>
+
+ <!ELEMENT header (version, tos, total.length, id, flags, offset, ttl,
+ protocol, checksum, source, destination, options,
+ padding)>
+ <!-- length of header in 32-bit words -->
+ <!ATTLIST header
+ length %Digits; #REQUIRED>
+
+ <!ELEMENT version EMPTY>
+ <!-- ip version. SHOULD be "4" -->
+ <!ATTLIST version
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT tos EMPTY>
+ <!ATTLIST tos
+ precedence %Precedence; #REQUIRED
+ delay (normal | low) #REQUIRED
+ throughput (normal | high) #REQUIRED
+ relibility (normal | high) #REQUIRED
+ reserved CDATA #FIXED "0">
+
+ <!ELEMENT total.length EMPTY>
+ <!--
+ total length of datagram (header and payload) in octets, MUST be
+ less than 65,535 (and SHOULD be less than 1024 for IPoXML on local
+ ethernets).
+ -->
+ <!ATTLIST total.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT id EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST id
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT flags EMPTY>
+ <!-- df = don't fragment, mf = more fragments -->
+ <!ATTLIST flags
+
+
+
+Kennedy Informational [Page 8]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ reserved CDATA #FIXED "0"
+ df (may|dont) #REQUIRED
+ mf (last|more) #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= offset <= 8192 measured in 8 octet (64-bit) chunks -->
+ <!ATTLIST offset
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT ttl EMPTY>
+ <!-- 0 <= ttl <= 255 -->
+ <!ATTLIST ttl
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT protocol EMPTY>
+ <!-- 0 <= protocol <= 255 (per IANA) -->
+ <!ATTLIST protocol
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT checksum EMPTY>
+ <!-- 0 <= checksum <= 65535 (over header only) -->
+ <!ATTLIST checksum
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT source EMPTY>
+ <!ATTLIST source
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT destination EMPTY>
+ <!ATTLIST destination
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT options ( end | noop | security | loose | strict | record
+ | stream | timestamp )*>
+
+ <!ELEMENT end EMPTY>
+ <!ATTLIST end
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "0">
+
+ <!ELEMENT noop EMPTY>
+ <!ATTLIST noop
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "1">
+
+ <!ELEMENT security EMPTY>
+
+
+
+Kennedy Informational [Page 9]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST security
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "2"
+ length CDATA #FIXED "11"
+ security %Sec; #REQUIRED
+ compartments %Compartments; #REQUIRED
+ handling %Handling; #REQUIRED
+ tcc %TCC; #REQUIRED>
+ <!ELEMENT loose (hop)+>
+ <!ATTLIST loose
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "3"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT hop EMPTY>
+ <!ATTLIST hop
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT strict (hop)+>
+ <!ATTLIST strict
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "9"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT record (hop)+>
+ <!ATTLIST record
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "7"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT stream EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST stream
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "8"
+ length CDATA #FIXED "4"
+ id %Digits; #REQUIRED>
+
+ <!ELEMENT timestamp (tstamp)+>
+ <!-- 0 <= oflw <=15 -->
+
+
+
+Kennedy Informational [Page 10]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST timestamp
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "2"
+ number CDATA #FIXED "4"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED
+ oflw %Digits; #REQUIRED
+ flag (0 | 1 | 3) #REQUIRED>
+
+ <!ELEMENT tstamp EMPTY>
+ <!ATTLIST tstamp
+ time %Digits; #REQUIRED
+ address %IP4Addr; #IMPLIED>
+ <!--
+ padding to bring header to 32-bit boundary.
+ pad MUST be "0"*
+ -->
+ <!ELEMENT padding EMPTY>
+ <!ATTLIST padding
+ pad CDATA #REQUIRED>
+
+ <!-- payload MUST be encoded as base-64 [RFC2045], as modified
+ by section 2.1 of this RFC -->
+ <!ELEMENT payload (CDATA)>
+
+7.2. TCPoXML DTD
+
+ <!--
+ DTD for TCP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ -->
+
+ <!-- the pseudoheader is only included for checksum calculations -->
+ <!ELEMENT tcp (tcp.pseudoheader?, tcp.header, payload)>
+
+ <!ELEMENT tcp.header (src, dest, sequence, acknowledgement, offset,
+ reserved, control, window, checksum, urgent,
+ tcp.options, padding)>
+
+ <!ELEMENT src EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+ <!ATTLIST src
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT dest EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+
+
+
+Kennedy Informational [Page 11]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST dest
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT sequence EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST sequence
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT acknowledgement EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST acknowledgement
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= number <= 255 -->
+ <!ATTLIST offset
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT reserved EMPTY>
+ <!ATTLIST reserved
+ value CDATA #FIXED "0">
+
+ <!ELEMENT control EMPTY>
+ <!ATTLIST control
+ urg (0|1) #IMPLIED
+ ack (0|1) #IMPLIED
+ psh (0|1) #IMPLIED
+ rst (0|1) #IMPLIED
+ syn (0|1) #IMPLIED
+ fin (0|1) #IMPLIED>
+
+ <!ELEMENT window EMPTY>
+ <!-- 0 <= size <= 65,535 -->
+ <!ATTLIST window
+ size %Digits; #REQUIRED>
+
+ <!--
+ checksum as in ip, but with
+ the following pseudo-header added into the tcp element:
+ -->
+ <!ELEMENT tcp.pseudoheader (source, destination, protocol,
+ tcp.length)>
+
+ <!--
+ tcp header + data length in octets. does not include the size of
+
+ the pseudoheader.
+ -->
+
+
+
+Kennedy Informational [Page 12]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ELEMENT tcp.length EMPTY>
+ <!ATTLIST tcp.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT urgent EMPTY>
+ <!-- 0 <= pointer <= 65,535 -->
+ <!ATTLIST urgent
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT tcp.options (tcp.end | tcp.noop | tcp.mss)+>
+
+ <!ELEMENT tcp.end EMPTY>
+ <!ATTLIST tcp.end
+ kind CDATA #FIXED "0">
+
+ <!ELEMENT tcp.noop EMPTY>
+ <!ATTLIST tcp.noop
+ kind CDATA #FIXED "1">
+
+ <!ELEMENT tcp.mss EMPTY>
+ <!ATTLIST tcp.mss
+ kind CDATA #FIXED "2"
+ length CDATA #FIXED "4"
+ size %Digits; #REQUIRED>
+
+7.3. UDPoXML DTD
+
+ <!--
+ DTD for UDP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ -->
+
+ <!ELEMENT udp (udp.pseudoheader?, udp.header, payload)>
+
+ <!ELEMENT udp.header (src, dest, udp.length, checksum)>
+
+ <!ELEMENT udp.pseudoheader (source, destination, protocol,
+ udp.length)>
+
+ <!--
+ udp header + data length in octets. does not include the size of
+ the pseudoheader.
+ -->
+ <!ELEMENT udp.length EMPTY>
+ <!ATTLIST udp.length
+ value %Digits; #REQUIRED>
+
+
+
+Kennedy Informational [Page 13]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+8. Security Considerations
+
+ XML, as a subset of SGML, has the same security considerations as
+ specified in SGML Media Types [RFC1874]. Security considerations
+ that apply to IP, TCP and UDP also likely apply to BLOAT as it does
+ not attempt to correct for issues not related to message format.
+
+9. References
+
+ [JABBER] Miller, J., "Jabber", draft-miller-jabber-00.txt,
+ February 2002. (Work in Progress)
+
+ [RFC768] Postel, J., "User Datagram Protocol", STD 6, RFC 768,
+ August 1980.
+
+ [RFC791] Postel, J., "Internet Protocol", STD 5, RFC 791,
+ September 1981.
+
+ [RFC793] Postel, J., "Transmission Control Protocol", STD 7, RFC
+ 793, September 1981.
+
+ [RFC894] Hornig, C., "Standard for the Transmission of IP
+ Datagrams over Ethernet Networks.", RFC 894, April 1984.
+
+ [RFC1042] Postel, J. and J. Reynolds, "Standard for the
+ Transmission of IP Datagrams Over IEEE 802 Networks", STD
+ 43, RFC 1042, February 1988.
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts -
+ Application and Support", RFC 1123, October 1989.
+
+ [RFC1874] Levinson, E., "SGML Media Types", RFC 1874, December
+ 1995.
+
+ [RFC2003] Perkins, C., "IP Encapsulation within IP", RFC 2003,
+ October 1996.
+
+ [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message
+ Bodies", RFC 2045, November 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+
+
+
+
+Kennedy Informational [Page 14]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ [RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6
+ (IPv6) Specification", RFC 2460, December 1998.
+
+ [RFC3080] Rose, M., "The Blocks Extensible Exchange Protocol Core",
+ RFC 3080, March 2001.
+
+ [SOAP] Box, D., Ehnebuske, D., Kakivaya, G., Layman, A.,
+ Mendelsohn, N., Nielsen, H. F., Thatte, S. Winer, D.,
+ "Simple Object Access Protocol (SOAP) 1.1" World Wide Web
+ Consortium Note, May 2000 http://www.w3.org/TR/SOAP/
+
+ [XML] Bray, T., Paoli, J., Sperberg-McQueen, C. M., "Extensible
+ Markup Language (XML)" World Wide Web Consortium
+ Recommendation REC- xml-19980210.
+ http://www.w3.org/TR/1998/REC-xml-19980210
+
+10. Author's Address
+
+ Hugh Kennedy
+ Mimezine
+ 1060 West Addison
+ Chicago, IL 60613
+ USA
+
+ EMail: kennedyh@engin.umich.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 15]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+11. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 16]
+
diff --git a/tests/auto/network/access/qftp/tst_qftp.cpp b/tests/auto/network/access/qftp/tst_qftp.cpp
new file mode 100644
index 0000000000..117ac92ed7
--- /dev/null
+++ b/tests/auto/network/access/qftp/tst_qftp.cpp
@@ -0,0 +1,2170 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qfile.h>
+#include <qbuffer.h>
+#include "qftp.h"
+#include <qmap.h>
+#include <time.h>
+#include <stdlib.h>
+#include <QNetworkProxy>
+#include <QNetworkConfiguration>
+#include <qnetworkconfigmanager.h>
+#include <QNetworkSession>
+#include <QtNetwork/private/qnetworksession_p.h>
+
+#include "../../../network-settings.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+#ifdef Q_OS_SYMBIAN
+// In Symbian OS test data is located in applications private dir
+// Application private dir is default serach path for files, so SRCDIR can be set to empty
+#define SRCDIR ""
+#endif
+
+#ifndef QT_NO_BEARERMANAGEMENT
+Q_DECLARE_METATYPE(QNetworkConfiguration)
+#endif
+
+class tst_QFtp : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QFtp();
+ virtual ~tst_QFtp();
+
+
+public slots:
+ void initTestCase_data();
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void connectToHost_data();
+ void connectToHost();
+ void connectToUnresponsiveHost();
+ void login_data();
+ void login();
+ void close_data();
+ void close();
+
+ void list_data();
+ void list();
+ void cd_data();
+ void cd();
+ void get_data();
+ void get();
+ void put_data();
+ void put();
+ void remove();
+ void mkdir_data();
+ void mkdir();
+ void mkdir2();
+ void rmdir();
+ void rename_data();
+ void rename();
+
+ void commandSequence_data();
+ void commandSequence();
+
+ void abort_data();
+ void abort();
+
+ void bytesAvailable_data();
+ void bytesAvailable();
+
+ void activeMode();
+
+ void proxy_data();
+ void proxy();
+
+ void binaryAscii();
+
+ void doneSignal();
+ void queueMoreCommandsInDoneSlot();
+
+ void qtbug7359Crash();
+
+protected slots:
+ void stateChanged( int );
+ void listInfo( const QUrlInfo & );
+ void readyRead();
+ void dataTransferProgress(qint64, qint64);
+
+ void commandStarted( int );
+ void commandFinished( int, bool );
+ void done( bool );
+ void activeModeDone( bool );
+ void mkdir2Slot(int id, bool error);
+ void cdUpSlot(bool);
+
+private:
+ QFtp *newFtp();
+ void addCommand( QFtp::Command, int );
+ bool fileExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &file, const QString &cdDir = QString::null );
+ bool dirExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &cdDir, const QString &dirToCreate );
+
+ void renameInit( const QString &host, const QString &user, const QString &password, const QString &createFile );
+ void renameCleanup( const QString &host, const QString &user, const QString &password, const QString &fileToDelete );
+
+ QFtp *ftp;
+#ifndef QT_NO_BEARERMANAGEMENT
+ QSharedPointer<QNetworkSession> networkSessionExplicit;
+ QSharedPointer<QNetworkSession> networkSessionImplicit;
+#endif
+
+ QList<int> ids; // helper to make sure that all expected signals are emitted
+ int current_id;
+
+ int connectToHost_state;
+ int close_state;
+ int login_state;
+ int cur_state;
+ struct CommandResult
+ {
+ int id;
+ int success;
+ };
+ QMap< QFtp::Command, CommandResult > resultMap;
+ typedef QMap<QFtp::Command,CommandResult>::Iterator ResMapIt;
+
+ int done_success;
+ int commandSequence_success;
+
+ qlonglong bytesAvailable_finishedGet;
+ qlonglong bytesAvailable_finished;
+ qlonglong bytesAvailable_done;
+
+ QList<QUrlInfo> listInfo_i;
+ QByteArray newData_ba;
+ qlonglong bytesTotal;
+ qlonglong bytesDone;
+
+ bool inFileDirExistsFunction;
+
+ QString uniqueExtension;
+};
+
+//#define DUMP_SIGNALS
+
+const int bytesTotal_init = -10;
+const int bytesDone_init = -10;
+
+tst_QFtp::tst_QFtp() :
+ ftp(0)
+{
+}
+
+tst_QFtp::~tst_QFtp()
+{
+}
+
+void tst_QFtp::initTestCase_data()
+{
+ QTest::addColumn<bool>("setProxy");
+ QTest::addColumn<int>("proxyType");
+ QTest::addColumn<bool>("setSession");
+
+ QTest::newRow("WithoutProxy") << false << 0 << false;
+ QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy) << false;
+ //### doesn't work well yet.
+ //QTest::newRow("WithHttpProxy") << true << int(QNetworkProxy::HttpProxy);
+
+#ifndef QT_NO_BEARERMANAGEMENT
+ QTest::newRow("WithoutProxyWithSession") << false << 0 << true;
+ QTest::newRow("WithSocks5ProxyAndSession") << true << int(QNetworkProxy::Socks5Proxy) << true;
+#endif
+}
+
+void tst_QFtp::initTestCase()
+{
+#ifndef QT_NO_BEARERMANAGEMENT
+ QNetworkConfigurationManager manager;
+ networkSessionImplicit = QSharedPointer<QNetworkSession>(new QNetworkSession(manager.defaultConfiguration()));
+ networkSessionImplicit->open();
+ QVERIFY(networkSessionImplicit->waitForOpened(60000)); //there may be user prompt on 1st connect
+#endif
+}
+
+void tst_QFtp::cleanupTestCase()
+{
+#ifndef QT_NO_BEARERMANAGEMENT
+ networkSessionExplicit.clear();
+ networkSessionImplicit.clear();
+#endif
+}
+
+void tst_QFtp::init()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ QFETCH_GLOBAL(int, proxyType);
+ QFETCH_GLOBAL(bool, setSession);
+ if (setProxy) {
+ if (proxyType == QNetworkProxy::Socks5Proxy) {
+ QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
+ } else if (proxyType == QNetworkProxy::HttpProxy) {
+ QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128));
+ }
+ }
+#ifndef QT_NO_BEARERMANAGEMENT
+ if (setSession) {
+ networkSessionExplicit = networkSessionImplicit;
+ if (!networkSessionExplicit->isOpen()) {
+ networkSessionExplicit->open();
+ QVERIFY(networkSessionExplicit->waitForOpened(30000));
+ }
+ } else {
+ networkSessionExplicit.clear();
+ }
+#endif
+
+ delete ftp;
+ ftp = 0;
+
+ ids.clear();
+ current_id = 0;
+
+ resultMap.clear();
+ connectToHost_state = -1;
+ close_state = -1;
+ login_state = -1;
+ cur_state = QFtp::Unconnected;
+
+ listInfo_i.clear();
+ newData_ba = QByteArray();
+ bytesTotal = bytesTotal_init;
+ bytesDone = bytesDone_init;
+
+ done_success = -1;
+ commandSequence_success = -1;
+
+ bytesAvailable_finishedGet = 1234567890;
+ bytesAvailable_finished = 1234567890;
+ bytesAvailable_done = 1234567890;
+
+ inFileDirExistsFunction = FALSE;
+
+#if !defined(Q_OS_WINCE)
+ srand(time(0));
+ uniqueExtension = QString("%1%2%3").arg((qulonglong)this).arg(rand()).arg((qulonglong)time(0));
+#else
+ srand(0);
+ uniqueExtension = QString("%1%2%3").arg((qulonglong)this).arg(rand()).arg((qulonglong)(0));
+#endif
+}
+
+void tst_QFtp::cleanup()
+{
+ if (ftp) {
+ delete ftp;
+ ftp = 0;
+ }
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy) {
+ QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy);
+ }
+
+ delete ftp;
+ ftp = 0;
+#ifndef QT_NO_BEARERMANAGEMENT
+ networkSessionExplicit.clear();
+#endif
+}
+
+void tst_QFtp::connectToHost_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<int>("state");
+
+ QTest::newRow( "ok01" ) << QtNetworkSettings::serverName() << (uint)21 << (int)QFtp::Connected;
+ QTest::newRow( "error01" ) << QtNetworkSettings::serverName() << (uint)2222 << (int)QFtp::Unconnected;
+ QTest::newRow( "error02" ) << QString("foo.bar") << (uint)21 << (int)QFtp::Unconnected;
+}
+
+void tst_QFtp::connectToHost()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+
+ QTestEventLoop::instance().enterLoop( 61 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ QTEST( connectToHost_state, "state" );
+
+ ResMapIt it = resultMap.find( QFtp::ConnectToHost );
+ QVERIFY( it != resultMap.end() );
+ QFETCH( int, state );
+ if ( state == QFtp::Connected ) {
+ QVERIFY( it.value().success == 1 );
+ } else {
+ QVERIFY( it.value().success == 0 );
+ }
+}
+
+void tst_QFtp::connectToUnresponsiveHost()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ QSKIP( "This test takes too long if we test with proxies too", SkipSingle );
+
+ QString host = "192.0.2.42"; // IP out of TEST-NET, should be unreachable
+ uint port = 21;
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+
+ qDebug( "About to connect to host that won't reply (this test takes 60 seconds)" );
+ QTestEventLoop::instance().enterLoop( 61 );
+#ifdef Q_OS_WIN
+ /* On Windows, we do not get a timeout, because Winsock is behaving in a strange way:
+ We issue two "WSAConnect()" calls, after the first, as a result we get WSAEWOULDBLOCK,
+ after the second, we get WSAEISCONN, which means that the socket is connected, which cannot be.
+ However, after some seconds we get a socket error saying that the remote host closed the connection,
+ which can neither be. For this test, that would actually enable us to finish before timout, but handling that case
+ (in void QFtpPI::error(QAbstractSocket::SocketError e)) breaks
+ a lot of other stuff in QFtp, so we just expect this test to fail on Windows.
+ */
+ QEXPECT_FAIL("", "timeout not working due to strange Windows socket behaviour (see source file of this test for explanation)", Abort);
+#else
+ QEXPECT_FAIL("", "QTBUG-20687", Abort);
+#endif
+ QVERIFY2(! QTestEventLoop::instance().timeout(), "Network timeout longer than expected (should have been 60 seconds)");
+
+ QVERIFY( ftp->state() == QFtp::Unconnected);
+ ResMapIt it = resultMap.find( QFtp::ConnectToHost );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( it.value().success == 0 );
+
+ delete ftp;
+ ftp = 0;
+}
+
+void tst_QFtp::login_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<int>("success");
+
+ QTest::newRow( "ok01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << 1;
+ QTest::newRow( "ok02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString() << 1;
+ QTest::newRow( "ok03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString("foo") << 1;
+ QTest::newRow( "ok04" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << 1;
+
+ QTest::newRow( "error01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("foo") << QString() << 0;
+ QTest::newRow( "error02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("foo") << QString("bar") << 0;
+}
+
+void tst_QFtp::login()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::Login );
+ QVERIFY( it != resultMap.end() );
+ QTEST( it.value().success, "success" );
+
+ if ( it.value().success ) {
+ QVERIFY( login_state == QFtp::LoggedIn );
+ } else {
+ QVERIFY( login_state != QFtp::LoggedIn );
+ }
+}
+
+void tst_QFtp::close_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<bool>("login");
+
+ QTest::newRow( "login01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << (bool)TRUE;
+ QTest::newRow( "login02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString() << (bool)TRUE;
+ QTest::newRow( "login03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString("foo") << (bool)TRUE;
+ QTest::newRow( "login04" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << (bool)TRUE;
+
+ QTest::newRow( "no-login01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("") << QString("") << (bool)FALSE;
+}
+
+void tst_QFtp::close()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( bool, login );
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ if ( login )
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ QCOMPARE( close_state, (int)QFtp::Unconnected );
+
+ ResMapIt it = resultMap.find( QFtp::Close );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( it.value().success == 1 );
+}
+
+void tst_QFtp::list_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<QString>("dir");
+ QTest::addColumn<int>("success");
+ QTest::addColumn<QStringList>("entryNames"); // ### we should rather use a QList<QUrlInfo> here
+
+ QStringList flukeRoot;
+ flukeRoot << "pub";
+ flukeRoot << "qtest";
+ QStringList flukeQtest;
+ flukeQtest << "bigfile";
+ flukeQtest << "nonASCII";
+ flukeQtest << "rfc3252";
+ flukeQtest << "rfc3252.txt";
+ flukeQtest << "upload";
+
+ QTest::newRow( "workDir01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString() << 1 << flukeRoot;
+ QTest::newRow( "workDir02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString() << 1 << flukeRoot;
+
+ QTest::newRow( "relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
+
+ QTest::newRow( "absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
+ QTest::newRow( "absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
+
+ QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 1 << QStringList();
+ QTest::newRow( "nonExist02" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/foo") << 1 << QStringList();
+ // ### The microsoft server does not seem to work properly at the moment --
+ // I am also not able to open a data connection with other, non-Qt FTP
+ // clients to it.
+ // QTest::newRow( "nonExist03" ) << "ftp.microsoft.com" << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
+
+ QStringList susePub;
+ susePub << "README.mirror-policy" << "axp" << "i386" << "ia64" << "install" << "noarch" << "pubring.gpg-build.suse.de" << "update" << "x86_64";
+ QTest::newRow( "epsvNotSupported" ) << QString("ftp.funet.fi") << (uint)21 << QString::fromLatin1("ftp") << QString::fromLatin1("root@") << QString("/pub/Linux/suse/suse") << 1 << susePub;
+}
+
+void tst_QFtp::list()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( QString, dir );
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::List, ftp->list( dir ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::List );
+ QVERIFY( it != resultMap.end() );
+ QTEST( it.value().success, "success" );
+ QFETCH( QStringList, entryNames );
+ QCOMPARE( listInfo_i.count(), entryNames.count() );
+ for ( uint i=0; i < (uint) entryNames.count(); i++ ) {
+ QCOMPARE( listInfo_i[i].name(), entryNames[i] );
+ }
+}
+
+void tst_QFtp::cd_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<QString>("dir");
+ QTest::addColumn<int>("success");
+ QTest::addColumn<QStringList>("entryNames"); // ### we should rather use a QList<QUrlInfo> here
+
+ QStringList flukeRoot;
+ flukeRoot << "qtest";
+ QStringList flukeQtest;
+ flukeQtest << "bigfile";
+ flukeQtest << "nonASCII";
+ flukeQtest << "rfc3252";
+ flukeQtest << "rfc3252.txt";
+ flukeQtest << "upload";
+
+ QTest::newRow( "relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
+
+ QTest::newRow( "absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
+ QTest::newRow( "absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
+
+ QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 0 << QStringList();
+ QTest::newRow( "nonExist03" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
+}
+
+void tst_QFtp::cd()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( QString, dir );
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Cd, ftp->cd( dir ) );
+ addCommand( QFtp::List, ftp->list() );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() ) {
+ QFAIL( "Network operation timed out" );
+ }
+
+ ResMapIt it = resultMap.find( QFtp::Cd );
+ QVERIFY( it != resultMap.end() );
+ QTEST( it.value().success, "success" );
+ QFETCH( QStringList, entryNames );
+ QCOMPARE( listInfo_i.count(), entryNames.count() );
+ for ( uint i=0; i < (uint) entryNames.count(); i++ ) {
+ QCOMPARE( listInfo_i[i].name(), entryNames[i] );
+ }
+}
+
+void tst_QFtp::get_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<int>("success");
+ QTest::addColumn<QByteArray>("res");
+ QTest::addColumn<bool>("useIODevice");
+
+ // ### move this into external testdata
+ QFile file( SRCDIR "rfc3252.txt" );
+ QVERIFY( file.open( QIODevice::ReadOnly ) );
+ QByteArray rfc3252 = file.readAll();
+
+ // test the two get() overloads in one routine
+ for ( int i=0; i<2; i++ ) {
+ QTest::newRow( QString("relPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << "qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
+ QTest::newRow( QString("relPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << "qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
+
+ QTest::newRow( QString("absPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << "/qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
+ QTest::newRow( QString("absPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << "/var/ftp/qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
+
+ QTest::newRow( QString("nonExist01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << QString("foo") << 0 << QByteArray() << (bool)(i==1);
+ QTest::newRow( QString("nonExist02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << QString("/foo") << 0 << QByteArray() << (bool)(i==1);
+ }
+}
+
+void tst_QFtp::get()
+{
+ // for the overload that takes a QIODevice
+ QByteArray buf_ba;
+ QBuffer buf( &buf_ba );
+
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( QString, file );
+ QFETCH( bool, useIODevice );
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ if ( useIODevice ) {
+ buf.open( QIODevice::WriteOnly );
+ addCommand( QFtp::Get, ftp->get( file, &buf ) );
+ } else {
+ addCommand( QFtp::Get, ftp->get( file ) );
+ }
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 50 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::Get );
+ QVERIFY( it != resultMap.end() );
+ QTEST( it.value().success, "success" );
+ if ( useIODevice ) {
+ QTEST( buf_ba, "res" );
+ } else {
+ QTEST( newData_ba, "res" );
+ }
+ QVERIFY( bytesTotal != bytesTotal_init );
+ if ( bytesTotal != -1 ) {
+ QVERIFY( bytesDone == bytesTotal );
+ }
+ if ( useIODevice ) {
+ if ( bytesDone != bytesDone_init ) {
+ QVERIFY( (int)buf_ba.size() == bytesDone );
+ }
+ } else {
+ if ( bytesDone != bytesDone_init ) {
+ QVERIFY( (int)newData_ba.size() == bytesDone );
+ }
+ }
+}
+
+void tst_QFtp::put_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QByteArray>("fileData");
+ QTest::addColumn<bool>("useIODevice");
+ QTest::addColumn<int>("success");
+
+ // ### move this into external testdata
+ QFile file( SRCDIR "rfc3252.txt" );
+ QVERIFY( file.open( QIODevice::ReadOnly ) );
+ QByteArray rfc3252 = file.readAll();
+
+ QByteArray bigData( 10*1024*1024, 0 );
+ bigData.fill( 'A' );
+
+ // test the two put() overloads in one routine
+ for ( int i=0; i<2; i++ ) {
+ QTest::newRow( QString("relPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << QString("qtest/upload/rel01_%1") << rfc3252
+ << (bool)(i==1) << 1;
+ /*
+ QTest::newRow( QString("relPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << QString("qtest/upload/rel02_%1") << rfc3252
+ << (bool)(i==1) << 1;
+ QTest::newRow( QString("relPath03_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << QString("qtest/upload/rel03_%1") << QByteArray()
+ << (bool)(i==1) << 1;
+ QTest::newRow( QString("relPath04_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << QString("qtest/upload/rel04_%1") << bigData
+ << (bool)(i==1) << 1;
+
+ QTest::newRow( QString("absPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << QString("/qtest/upload/abs01_%1") << rfc3252
+ << (bool)(i==1) << 1;
+ QTest::newRow( QString("absPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << QString("/srv/ftp/qtest/upload/abs02_%1") << rfc3252
+ << (bool)(i==1) << 1;
+
+ QTest::newRow( QString("nonExist01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << QString("foo") << QByteArray()
+ << (bool)(i==1) << 0;
+ QTest::newRow( QString("nonExist02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << QString("/foo") << QByteArray()
+ << (bool)(i==1) << 0;
+*/
+ }
+}
+
+void tst_QFtp::put()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( QString, file );
+ QFETCH( QByteArray, fileData );
+ QFETCH( bool, useIODevice );
+
+#ifdef Q_OS_WIN
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy) {
+ QFETCH_GLOBAL(int, proxyType);
+ if (proxyType == QNetworkProxy::Socks5Proxy) {
+ QSKIP("With socks5 the put() test takes too long time on Windows.", SkipAll);
+ }
+ }
+#endif
+
+ const int timestep = 50;
+
+ if(file.contains('%'))
+ file = file.arg(uniqueExtension);
+
+ // for the overload that takes a QIODevice
+ QBuffer buf_fileData( &fileData );
+ buf_fileData.open( QIODevice::ReadOnly );
+
+ ResMapIt it;
+ //////////////////////////////////////////////////////////////////
+ // upload the file
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ if ( useIODevice )
+ addCommand( QFtp::Put, ftp->put( &buf_fileData, file ) );
+ else
+ addCommand( QFtp::Put, ftp->put( fileData, file ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ for(int time = 0; time <= fileData.length() / 20000; time += timestep) {
+ QTestEventLoop::instance().enterLoop( timestep );
+ if(ftp->currentCommand() == QFtp::None)
+ break;
+ }
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ it = resultMap.find( QFtp::Put );
+ QVERIFY( it != resultMap.end() );
+ QTEST( it.value().success, "success" );
+ if ( !it.value().success ) {
+ QVERIFY( !fileExists( host, port, user, password, file ) );
+ return; // the following tests are only meaningful if the file could be put
+ }
+ QVERIFY( bytesTotal == (int)fileData.size() );
+ QVERIFY( bytesDone == bytesTotal );
+
+ QVERIFY( fileExists( host, port, user, password, file ) );
+
+ //////////////////////////////////////////////////////////////////
+ // fetch file to make sure that it is equal to the uploaded file
+ init();
+ ftp = newFtp();
+ QBuffer buf;
+ buf.open( QIODevice::WriteOnly );
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Get, ftp->get( file, &buf ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ for(int time = 0; time <= fileData.length() / 20000; time += timestep) {
+ QTestEventLoop::instance().enterLoop( timestep );
+ if(ftp->currentCommand() == QFtp::None)
+ break;
+ }
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ QVERIFY( done_success == 1 );
+ QTEST( buf.buffer(), "fileData" );
+
+ //////////////////////////////////////////////////////////////////
+ // cleanup (i.e. remove the file) -- this also tests the remove command
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Remove, ftp->remove( file ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( timestep );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ it = resultMap.find( QFtp::Remove );
+ QVERIFY( it != resultMap.end() );
+ QCOMPARE( it.value().success, 1 );
+
+ QVERIFY( !fileExists( host, port, user, password, file ) );
+}
+
+void tst_QFtp::remove()
+{
+ DEPENDS_ON( "put" );
+}
+
+void tst_QFtp::mkdir_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<QString>("cdDir");
+ QTest::addColumn<QString>("dirToCreate");
+ QTest::addColumn<int>("success");
+
+ QTest::newRow( "relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << "qtest/upload" << QString("rel01_%1") << 1;
+ QTest::newRow( "relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << "qtest/upload" << QString("rel02_%1") << 1;
+ QTest::newRow( "relPath03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << "qtest/upload" << QString("rel03_%1") << 1;
+
+ QTest::newRow( "absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << "." << QString("/qtest/upload/abs01_%1") << 1;
+ QTest::newRow( "absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << "." << QString("/var/ftp/qtest/upload/abs02_%1") << 1;
+
+ // QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 0;
+ QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << "." << QString("foo") << 0;
+ QTest::newRow( "nonExist02" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << "." << QString("/foo") << 0;
+}
+
+void tst_QFtp::mkdir()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( QString, cdDir );
+ QFETCH( QString, dirToCreate );
+
+ if(dirToCreate.contains('%'))
+ dirToCreate = dirToCreate.arg(uniqueExtension);
+
+ //////////////////////////////////////////////////////////////////
+ // create the directory
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Cd, ftp->cd( cdDir ) );
+ addCommand( QFtp::Mkdir, ftp->mkdir( dirToCreate ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::Mkdir );
+ QVERIFY( it != resultMap.end() );
+ QTEST( it.value().success, "success" );
+ if ( !it.value().success ) {
+ QVERIFY( !dirExists( host, port, user, password, cdDir, dirToCreate ) );
+ return; // the following tests are only meaningful if the dir could be created
+ }
+ QVERIFY( dirExists( host, port, user, password, cdDir, dirToCreate ) );
+
+ //////////////////////////////////////////////////////////////////
+ // create the directory again (should always fail!)
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Cd, ftp->cd( cdDir ) );
+ addCommand( QFtp::Mkdir, ftp->mkdir( dirToCreate ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ it = resultMap.find( QFtp::Mkdir );
+ QVERIFY( it != resultMap.end() );
+ QCOMPARE( it.value().success, 0 );
+
+ //////////////////////////////////////////////////////////////////
+ // remove the directory
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Cd, ftp->cd( cdDir ) );
+ addCommand( QFtp::Rmdir, ftp->rmdir( dirToCreate ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ it = resultMap.find( QFtp::Rmdir );
+ QVERIFY( it != resultMap.end() );
+ QCOMPARE( it.value().success, 1 );
+
+ QVERIFY( !dirExists( host, port, user, password, cdDir, dirToCreate ) );
+}
+
+void tst_QFtp::mkdir2()
+{
+ ftp = new QFtp;
+ ftp->connectToHost(QtNetworkSettings::serverName());
+ ftp->login();
+ current_id = ftp->cd("kake/test");
+
+ QEventLoop loop;
+ connect(ftp, SIGNAL(done(bool)), &loop, SLOT(quit()));
+ connect(ftp, SIGNAL(commandFinished(int, bool)), this, SLOT(mkdir2Slot(int, bool)));
+ QTimer::singleShot(5000, &loop, SLOT(quit()));
+
+ QSignalSpy commandStartedSpy(ftp, SIGNAL(commandStarted(int)));
+ QSignalSpy commandFinishedSpy(ftp, SIGNAL(commandFinished(int, bool)));
+
+ loop.exec();
+
+ QCOMPARE(commandStartedSpy.count(), 4); // connect, login, cd, mkdir
+ QCOMPARE(commandFinishedSpy.count(), 4);
+
+ for (int i = 0; i < 4; ++i)
+ QCOMPARE(commandFinishedSpy.at(i).at(0), commandStartedSpy.at(i).at(0));
+
+ QVERIFY(!commandFinishedSpy.at(0).at(1).toBool());
+ QVERIFY(!commandFinishedSpy.at(1).at(1).toBool());
+ QVERIFY(commandFinishedSpy.at(2).at(1).toBool());
+ QVERIFY(commandFinishedSpy.at(3).at(1).toBool());
+
+ delete ftp;
+ ftp = 0;
+}
+
+void tst_QFtp::mkdir2Slot(int id, bool)
+{
+ if (id == current_id)
+ ftp->mkdir("kake/test");
+}
+
+void tst_QFtp::rmdir()
+{
+ DEPENDS_ON( "mkdir" );
+}
+
+void tst_QFtp::rename_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<QString>("cdDir");
+ QTest::addColumn<QString>("oldfile");
+ QTest::addColumn<QString>("newfile");
+ QTest::addColumn<QString>("createFile");
+ QTest::addColumn<QString>("renamedFile");
+ QTest::addColumn<int>("success");
+
+ QTest::newRow("relPath01") << QtNetworkSettings::serverName() << QString() << QString()
+ << "qtest/upload"
+ << QString("rel_old01_%1") << QString("rel_new01_%1")
+ << QString("qtest/upload/rel_old01_%1") << QString("qtest/upload/rel_new01_%1")
+ << 1;
+ QTest::newRow("relPath02") << QtNetworkSettings::serverName() << QString("ftptest") << "password"
+ << "qtest/upload"
+ << QString("rel_old02_%1") << QString("rel_new02_%1")
+ << QString("qtest/upload/rel_old02_%1") << QString("qtest/upload/rel_new02_%1")
+ << 1;
+ QTest::newRow("relPath03") << QtNetworkSettings::serverName() << QString("ftptest") << "password"
+ << "qtest/upload"
+ << QString("rel_old03_%1")<< QString("rel_new03_%1")
+ << QString("qtest/upload/rel_old03_%1") << QString("qtest/upload/rel_new03_%1")
+ << 1;
+
+ QTest::newRow("absPath01") << QtNetworkSettings::serverName() << QString() << QString()
+ << QString()
+ << QString("/qtest/upload/abs_old01_%1") << QString("/qtest/upload/abs_new01_%1")
+ << QString("/qtest/upload/abs_old01_%1") << QString("/qtest/upload/abs_new01_%1")
+ << 1;
+ QTest::newRow("absPath02") << QtNetworkSettings::serverName() << QString("ftptest") << "password"
+ << QString()
+ << QString("/var/ftp/qtest/upload/abs_old02_%1") << QString("/var/ftp/qtest/upload/abs_new02_%1")
+ << QString("/var/ftp/qtest/upload/abs_old02_%1") << QString("/var/ftp/qtest/upload/abs_new02_%1")
+ << 1;
+
+ QTest::newRow("nonExist01") << QtNetworkSettings::serverName() << QString() << QString()
+ << QString()
+ << QString("foo") << "new_foo"
+ << QString() << QString()
+ << 0;
+ QTest::newRow("nonExist02") << QtNetworkSettings::serverName() << QString() << QString()
+ << QString()
+ << QString("/foo") << QString("/new_foo")
+ << QString() << QString()
+ << 0;
+}
+
+void tst_QFtp::renameInit( const QString &host, const QString &user, const QString &password, const QString &createFile )
+{
+ if ( !createFile.isNull() ) {
+ // upload the file
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Put, ftp->put( QByteArray(), createFile ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 50 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::Put );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( it.value().success == 1 );
+
+ QVERIFY( fileExists( host, 21, user, password, createFile ) );
+ }
+}
+
+void tst_QFtp::renameCleanup( const QString &host, const QString &user, const QString &password, const QString &fileToDelete )
+{
+ if ( !fileToDelete.isNull() ) {
+ // cleanup (i.e. remove the file)
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Remove, ftp->remove( fileToDelete ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::Remove );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( it.value().success == 1 );
+
+ QVERIFY( !fileExists( host, 21, user, password, fileToDelete ) );
+ }
+}
+
+void tst_QFtp::rename()
+{
+ QFETCH( QString, host );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( QString, cdDir );
+ QFETCH( QString, oldfile );
+ QFETCH( QString, newfile );
+ QFETCH( QString, createFile );
+ QFETCH( QString, renamedFile );
+
+ if(oldfile.contains('%'))
+ oldfile = oldfile.arg(uniqueExtension);
+ if(newfile.contains('%'))
+ newfile = newfile.arg(uniqueExtension);
+ if(createFile.contains('%'))
+ createFile = createFile.arg(uniqueExtension);
+ if(renamedFile.contains('%'))
+ renamedFile = renamedFile.arg(uniqueExtension);
+
+ renameInit( host, user, password, createFile );
+
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ if ( !cdDir.isNull() )
+ addCommand( QFtp::Cd, ftp->cd( cdDir ) );
+ addCommand( QFtp::Rename, ftp->rename( oldfile, newfile ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::Rename );
+ QVERIFY( it != resultMap.end() );
+ QTEST( it.value().success, "success" );
+
+ if ( it.value().success ) {
+ QVERIFY( !fileExists( host, 21, user, password, oldfile, cdDir ) );
+ QVERIFY( fileExists( host, 21, user, password, newfile, cdDir ) );
+ QVERIFY( fileExists( host, 21, user, password, renamedFile ) );
+ } else {
+ QVERIFY( !fileExists( host, 21, user, password, newfile, cdDir ) );
+ QVERIFY( !fileExists( host, 21, user, password, renamedFile ) );
+ }
+
+ renameCleanup( host, user, password, renamedFile );
+}
+
+/*
+ The commandSequence() test does not test any particular function. It rather
+ tests a sequence of arbitrary commands specified in the test data.
+*/
+class FtpCommand
+{
+public:
+ FtpCommand() :
+ cmd(QFtp::None)
+ { }
+
+ FtpCommand( QFtp::Command command ) :
+ cmd(command)
+ { }
+
+ FtpCommand( QFtp::Command command, const QStringList &arguments ) :
+ cmd(command), args(arguments)
+ { }
+
+ FtpCommand( const FtpCommand &c )
+ { *this = c; }
+
+ FtpCommand &operator=( const FtpCommand &c )
+ {
+ this->cmd = c.cmd;
+ this->args = c.args;
+ return *this;
+ }
+
+ QFtp::Command cmd;
+ QStringList args;
+};
+QDataStream &operator<<( QDataStream &s, const FtpCommand &command )
+{
+ s << (int)command.cmd;
+ s << command.args;
+ return s;
+}
+QDataStream &operator>>( QDataStream &s, FtpCommand &command )
+{
+ int tmp;
+ s >> tmp;
+ command.cmd = (QFtp::Command)tmp;
+ s >> command.args;
+ return s;
+}
+Q_DECLARE_METATYPE(QList<FtpCommand>)
+
+void tst_QFtp::commandSequence_data()
+{
+ // some "constants"
+ QStringList argConnectToHost01;
+ argConnectToHost01 << QtNetworkSettings::serverName() << "21";
+
+ QStringList argLogin01, argLogin02, argLogin03, argLogin04;
+ argLogin01 << QString() << QString();
+ argLogin02 << "ftp" << QString();
+ argLogin03 << "ftp" << "foo";
+ argLogin04 << QString("ftptest") << "password";
+
+ FtpCommand connectToHost01( QFtp::ConnectToHost, argConnectToHost01 );
+ FtpCommand login01( QFtp::Login, argLogin01 );
+ FtpCommand login02( QFtp::Login, argLogin01 );
+ FtpCommand login03( QFtp::Login, argLogin01 );
+ FtpCommand login04( QFtp::Login, argLogin01 );
+ FtpCommand close01( QFtp::Close );
+
+ QTest::addColumn<QList<FtpCommand> >("cmds");
+ QTest::addColumn<int>("success");
+
+ // success data
+ {
+ QList<FtpCommand> cmds;
+ cmds << connectToHost01;
+ QTest::newRow( "simple_ok01" ) << cmds << 1;
+ }
+ {
+ QList<FtpCommand> cmds;
+ cmds << connectToHost01;
+ cmds << login01;
+ QTest::newRow( "simple_ok02" ) << cmds << 1;
+ }
+ {
+ QList<FtpCommand> cmds;
+ cmds << connectToHost01;
+ cmds << login01;
+ cmds << close01;
+ QTest::newRow( "simple_ok03" ) << cmds << 1;
+ }
+ {
+ QList<FtpCommand> cmds;
+ cmds << connectToHost01;
+ cmds << close01;
+ QTest::newRow( "simple_ok04" ) << cmds << 1;
+ }
+ {
+ QList<FtpCommand> cmds;
+ cmds << connectToHost01;
+ cmds << login01;
+ cmds << close01;
+ cmds << connectToHost01;
+ cmds << login02;
+ cmds << close01;
+ QTest::newRow( "connect_twice" ) << cmds << 1;
+ }
+
+ // error data
+ {
+ QList<FtpCommand> cmds;
+ cmds << close01;
+ QTest::newRow( "error01" ) << cmds << 0;
+ }
+ {
+ QList<FtpCommand> cmds;
+ cmds << login01;
+ QTest::newRow( "error02" ) << cmds << 0;
+ }
+ {
+ QList<FtpCommand> cmds;
+ cmds << login01;
+ cmds << close01;
+ QTest::newRow( "error03" ) << cmds << 0;
+ }
+ {
+ QList<FtpCommand> cmds;
+ cmds << connectToHost01;
+ cmds << login01;
+ cmds << close01;
+ cmds << login01;
+ QTest::newRow( "error04" ) << cmds << 0;
+ }
+}
+
+void tst_QFtp::commandSequence()
+{
+ QFETCH( QList<FtpCommand>, cmds );
+
+ ftp = newFtp();
+ QList<FtpCommand>::iterator it;
+ for ( it = cmds.begin(); it != cmds.end(); ++it ) {
+ switch ( (*it).cmd ) {
+ case QFtp::ConnectToHost:
+ {
+ QVERIFY( (*it).args.count() == 2 );
+ uint port;
+ bool portOk;
+ port = (*it).args[1].toUInt( &portOk );
+ QVERIFY( portOk );
+ ids << ftp->connectToHost( (*it).args[0], port );
+ }
+ break;
+ case QFtp::Login:
+ QVERIFY( (*it).args.count() == 2 );
+ ids << ftp->login( (*it).args[0], (*it).args[1] );
+ break;
+ case QFtp::Close:
+ QVERIFY( (*it).args.count() == 0 );
+ ids << ftp->close();
+ break;
+ default:
+ QFAIL( "Error in test: unexpected enum value" );
+ break;
+ }
+ }
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ QTEST( commandSequence_success, "success" );
+}
+
+void tst_QFtp::abort_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QByteArray>("uploadData");
+
+ QTest::newRow( "get_fluke01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/bigfile") << QByteArray();
+ QTest::newRow( "get_fluke02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/rfc3252") << QByteArray();
+
+ // Qt/CE and Symbian test environment has to less memory for this test
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
+ QByteArray bigData( 10*1024*1024, 0 );
+#else
+ QByteArray bigData( 1*1024*1024, 0 );
+#endif
+ bigData.fill( 'B' );
+ QTest::newRow( "put_fluke01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/upload/abort_put") << bigData;
+}
+
+void tst_QFtp::abort()
+{
+ // In case you wonder where the abort() actually happens, look into
+ // tst_QFtp::dataTransferProgress
+ //
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, file );
+ QFETCH( QByteArray, uploadData );
+
+ QFtp::Command cmd;
+ if ( uploadData.size() == 0 )
+ cmd = QFtp::Get;
+ else
+ cmd = QFtp::Put;
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login() );
+ if ( cmd == QFtp::Get )
+ addCommand( cmd, ftp->get( file ) );
+ else
+ addCommand( cmd, ftp->put( uploadData, file ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ for(int time = 0; time <= uploadData.length() / 30000; time += 30) {
+ QTestEventLoop::instance().enterLoop( 50 );
+ if(ftp->currentCommand() == QFtp::None)
+ break;
+ }
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( cmd );
+ QVERIFY( it != resultMap.end() );
+ // ### how to test the abort?
+ if ( it.value().success ) {
+ // The FTP server on fluke is sadly returning a success, even when
+ // the operation was aborted. So we have to use some heuristics.
+ if ( host == QtNetworkSettings::serverName() ) {
+ if ( cmd == QFtp::Get ) {
+ QVERIFY(bytesDone <= bytesTotal);
+ } else {
+ // put commands should always be aborted, since we use really
+ // big data
+ QVERIFY( bytesDone != bytesTotal );
+ }
+ } else {
+ // this could be tested by verifying that no more progress signals are emitted
+ QVERIFY(bytesDone <= bytesTotal);
+ }
+ } else {
+ QVERIFY( bytesDone != bytesTotal );
+ }
+
+ if ( cmd == QFtp::Put ) {
+ //////////////////////////////////////
+ // cleanup (i.e. remove the file)
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login() );
+ addCommand( QFtp::Remove, ftp->remove( file ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ it = resultMap.find( QFtp::Remove );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( it.value().success == 1 );
+ }
+}
+
+void tst_QFtp::bytesAvailable_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<int>("type");
+ QTest::addColumn<qlonglong>("bytesAvailFinishedGet");
+ QTest::addColumn<qlonglong>("bytesAvailFinished");
+ QTest::addColumn<qlonglong>("bytesAvailDone");
+
+ QTest::newRow( "fluke01" ) << QtNetworkSettings::serverName() << QString("qtest/bigfile") << 0 << (qlonglong)519240 << (qlonglong)519240 << (qlonglong)519240;
+ QTest::newRow( "fluke02" ) << QtNetworkSettings::serverName() << QString("qtest/rfc3252") << 0 << (qlonglong)25962 << (qlonglong)25962 << (qlonglong)25962;
+
+ QTest::newRow( "fluke03" ) << QtNetworkSettings::serverName() << QString("qtest/bigfile") << 1 << (qlonglong)519240 << (qlonglong)0 << (qlonglong)0;
+ QTest::newRow( "fluke04" ) << QtNetworkSettings::serverName() << QString("qtest/rfc3252") << 1 << (qlonglong)25962 << (qlonglong)0 << (qlonglong)0;
+}
+
+void tst_QFtp::bytesAvailable()
+{
+ QFETCH( QString, host );
+ QFETCH( QString, file );
+ QFETCH( int, type );
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host ) );
+ addCommand( QFtp::Login, ftp->login() );
+ addCommand( QFtp::Get, ftp->get( file ) );
+ if ( type != 0 )
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 40 );
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::Get );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( it.value().success );
+
+ QFETCH(qlonglong, bytesAvailFinishedGet);
+ QCOMPARE(bytesAvailable_finishedGet, bytesAvailFinishedGet);
+
+ QFETCH(qlonglong, bytesAvailFinished);
+ QCOMPARE(bytesAvailable_finished, bytesAvailFinished);
+
+ QFETCH(qlonglong, bytesAvailDone);
+ QCOMPARE(bytesAvailable_done, bytesAvailDone);
+
+ ftp->readAll();
+ QVERIFY( ftp->bytesAvailable() == 0 );
+ delete ftp;
+ ftp = 0;
+}
+
+void tst_QFtp::activeMode()
+{
+ QFile file("tst_QFtp_activeMode_inittab");
+ file.open(QIODevice::ReadWrite);
+ QFtp ftp;
+ ftp.setTransferMode(QFtp::Active);
+ ftp.connectToHost(QtNetworkSettings::serverName(), 21);
+ ftp.login();
+ ftp.list();
+ ftp.get("/qtest/rfc3252.txt", &file);
+ connect(&ftp, SIGNAL(done(bool)), SLOT(activeModeDone(bool)));
+ QTestEventLoop::instance().enterLoop(900);
+ QFile::remove("tst_QFtp_activeMode_inittab");
+ QVERIFY(done_success == 1);
+
+}
+
+void tst_QFtp::activeModeDone(bool error)
+{
+ done_success = error ? -1 : 1;
+ QTestEventLoop::instance().exitLoop();
+}
+
+void tst_QFtp::proxy_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<QString>("dir");
+ QTest::addColumn<int>("success");
+ QTest::addColumn<QStringList>("entryNames"); // ### we should rather use a QList<QUrlInfo> here
+
+ QStringList flukeRoot;
+ flukeRoot << "qtest";
+ QStringList flukeQtest;
+ flukeQtest << "bigfile";
+ flukeQtest << "nonASCII";
+ flukeQtest << "rfc3252";
+ flukeQtest << "rfc3252.txt";
+ flukeQtest << "upload";
+
+ QTest::newRow( "proxy_relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "proxy_relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
+
+ QTest::newRow( "proxy_absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
+ QTest::newRow( "proxy_absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
+
+ QTest::newRow( "proxy_nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 0 << QStringList();
+ QTest::newRow( "proxy_nonExist03" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
+}
+
+void tst_QFtp::proxy()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( QString, dir );
+
+ ftp = newFtp();
+ addCommand( QFtp::SetProxy, ftp->setProxy( QtNetworkSettings::serverName(), 2121 ) );
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Cd, ftp->cd( dir ) );
+ addCommand( QFtp::List, ftp->list() );
+
+ QTestEventLoop::instance().enterLoop( 50 );
+
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() ) {
+ QFAIL( "Network operation timed out" );
+ }
+
+ ResMapIt it = resultMap.find( QFtp::Cd );
+ QVERIFY( it != resultMap.end() );
+ QFETCH( int, success );
+ QCOMPARE( it.value().success, success );
+ QFETCH( QStringList, entryNames );
+ QCOMPARE( listInfo_i.count(), entryNames.count() );
+ for ( uint i=0; i < (uint) entryNames.count(); i++ ) {
+ QCOMPARE( listInfo_i[i].name(), entryNames[i] );
+ }
+}
+
+void tst_QFtp::binaryAscii()
+{
+ QString file = "asciifile%1.txt";
+
+ if(file.contains('%'))
+ file = file.arg(uniqueExtension);
+
+ QByteArray putData = "a line of text\r\n";
+
+ init();
+ ftp = newFtp();
+ addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::serverName(), 21));
+ addCommand(QFtp::Login, ftp->login("ftptest", "password"));
+ addCommand(QFtp::Cd, ftp->cd("qtest/upload"));
+ addCommand(QFtp::Put, ftp->put(putData, file, QFtp::Ascii));
+ addCommand(QFtp::Close, ftp->close());
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find(QFtp::Put);
+ QVERIFY(it != resultMap.end());
+ QVERIFY(it.value().success);
+
+ QByteArray getData;
+ QBuffer getBuf(&getData);
+ getBuf.open(QBuffer::WriteOnly);
+
+ init();
+ ftp = newFtp();
+ addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::serverName(), 21));
+ addCommand(QFtp::Login, ftp->login("ftptest", "password"));
+ addCommand(QFtp::Cd, ftp->cd("qtest/upload"));
+ addCommand(QFtp::Get, ftp->get(file, &getBuf, QFtp::Binary));
+ addCommand(QFtp::Close, ftp->close());
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it2 = resultMap.find(QFtp::Get);
+ QVERIFY(it2 != resultMap.end());
+ QVERIFY(it2.value().success);
+ // most modern ftp servers leave the file as it is by default
+ // (and do not remove the windows line ending), the -1 below could be
+ // deleted in the future
+ QVERIFY(getData.size() == putData.size()-1);
+ //////////////////////////////////////////////////////////////////
+ // cleanup (i.e. remove the file) -- this also tests the remove command
+ init();
+ ftp = newFtp();
+ addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::serverName(), 21));
+ addCommand(QFtp::Login, ftp->login("ftptest", "password"));
+ addCommand(QFtp::Cd, ftp->cd("qtest/upload"));
+ addCommand(QFtp::Remove, ftp->remove(file));
+ addCommand(QFtp::Close, ftp->close());
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ it = resultMap.find( QFtp::Remove );
+ QVERIFY( it != resultMap.end() );
+ QCOMPARE( it.value().success, 1 );
+
+ QVERIFY(!fileExists(QtNetworkSettings::serverName(), 21, "ftptest", "password", file));
+}
+
+
+// test QFtp::currentId() and QFtp::currentCommand()
+#define CURRENTCOMMAND_TEST \
+{ \
+ ResMapIt it; \
+ for ( it = resultMap.begin(); it != resultMap.end(); ++it ) { \
+ if ( it.value().id == ftp->currentId() ) { \
+ QVERIFY( it.key() == ftp->currentCommand() ); \
+ } \
+} \
+}
+
+void tst_QFtp::commandStarted( int id )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d:commandStarted( %d )", ftp->currentId(), id );
+#endif
+ // make sure that the commandStarted and commandFinished are nested correctly
+ QVERIFY( current_id == 0 );
+ current_id = id;
+
+ QVERIFY( !ids.isEmpty() );
+ QVERIFY( ids.first() == id );
+ if ( ids.count() > 1 ) {
+ QVERIFY( ftp->hasPendingCommands() );
+ } else {
+ QVERIFY( !ftp->hasPendingCommands() );
+ }
+
+ QVERIFY( ftp->currentId() == id );
+ QVERIFY( cur_state == ftp->state() );
+ CURRENTCOMMAND_TEST;
+
+ QVERIFY( ftp->error() == QFtp::NoError );
+}
+
+void tst_QFtp::commandFinished( int id, bool error )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d:commandFinished( %d, %d ) -- errorString: '%s'",
+ ftp->currentId(), id, (int)error, ftp->errorString().toLatin1().constData() );
+#endif
+ if ( ftp->currentCommand() == QFtp::Get ) {
+ bytesAvailable_finishedGet = ftp->bytesAvailable();
+ }
+ bytesAvailable_finished = ftp->bytesAvailable();
+
+ // make sure that the commandStarted and commandFinished are nested correctly
+ QVERIFY( current_id == id );
+ current_id = 0;
+
+ QVERIFY( !ids.isEmpty() );
+ QVERIFY( ids.first() == id );
+ if ( !error && ids.count() > 1) {
+ QVERIFY( ftp->hasPendingCommands() );
+ } else {
+ QVERIFY( !ftp->hasPendingCommands() );
+ }
+ if ( error ) {
+ QVERIFY( ftp->error() != QFtp::NoError );
+ ids.clear();
+ } else {
+ QVERIFY( ftp->error() == QFtp::NoError );
+ ids.pop_front();
+ }
+
+ QVERIFY( ftp->currentId() == id );
+ QVERIFY( cur_state == ftp->state() );
+ CURRENTCOMMAND_TEST;
+
+ if ( QTest::currentTestFunction() != QLatin1String("commandSequence") ) {
+ ResMapIt it = resultMap.find( ftp->currentCommand() );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( it.value().success == -1 );
+ if ( error )
+ it.value().success = 0;
+ else
+ it.value().success = 1;
+ }
+}
+
+void tst_QFtp::done( bool error )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d:done( %d )", ftp->currentId(), (int)error );
+#endif
+ bytesAvailable_done = ftp->bytesAvailable();
+
+ QVERIFY( ftp->currentId() == 0 );
+ QVERIFY( current_id == 0 );
+ QVERIFY( ids.isEmpty() );
+ QVERIFY( cur_state == ftp->state() );
+ QVERIFY( !ftp->hasPendingCommands() );
+
+ if ( QTest::currentTestFunction() == QLatin1String("commandSequence") ) {
+ QVERIFY( commandSequence_success == -1 );
+ if ( error )
+ commandSequence_success = 0;
+ else
+ commandSequence_success = 1;
+ }
+ QVERIFY( done_success == -1 );
+ if ( error ) {
+ QVERIFY( ftp->error() != QFtp::NoError );
+ done_success = 0;
+ } else {
+ QVERIFY( ftp->error() == QFtp::NoError );
+ done_success = 1;
+ }
+ QTestEventLoop::instance().exitLoop();
+}
+
+void tst_QFtp::stateChanged( int state )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d: stateChanged( %d )", ftp->currentId(), state );
+#endif
+ QCOMPARE( ftp->currentId(), current_id );
+ CURRENTCOMMAND_TEST;
+
+ QVERIFY( state != cur_state );
+ QCOMPARE( state, (int)ftp->state() );
+ if ( state != QFtp::Unconnected ) {
+ // make sure that the states are always emitted in the right order (for
+ // this, we assume an ordering on the enum values, which they have at
+ // the moment)
+ QVERIFY( cur_state < state );
+
+ // make sure that state changes are only emitted in response to certain
+ // commands
+ switch ( state ) {
+ case QFtp::HostLookup:
+ case QFtp::Connecting:
+ case QFtp::Connected:
+ QCOMPARE( (int)ftp->currentCommand(), (int)QFtp::ConnectToHost );
+ break;
+ case QFtp::LoggedIn:
+ QCOMPARE( (int)ftp->currentCommand(), (int)QFtp::Login );
+ break;
+ case QFtp::Closing:
+ QCOMPARE( (int)ftp->currentCommand(), (int)QFtp::Close );
+ break;
+ default:
+ QWARN( QString("Unexpected state '%1'").arg(state).toLatin1().constData() );
+ break;
+ }
+ }
+ cur_state = state;
+
+ if ( QTest::currentTestFunction() == QLatin1String("connectToHost") ) {
+ switch ( state ) {
+ case QFtp::HostLookup:
+ case QFtp::Connecting:
+ case QFtp::LoggedIn:
+ case QFtp::Closing:
+ // ignore
+ break;
+ case QFtp::Connected:
+ case QFtp::Unconnected:
+ QVERIFY( connectToHost_state == -1 );
+ connectToHost_state = state;
+ break;
+ default:
+ QWARN( QString("Unknown state '%1'").arg(state).toLatin1().constData() );
+ break;
+ }
+ } else if ( QTest::currentTestFunction() == QLatin1String("close") ) {
+ ResMapIt it = resultMap.find( QFtp::Close );
+ if ( it!=resultMap.end() && ftp->currentId()==it.value().id ) {
+ if ( state == QFtp::Closing ) {
+ QVERIFY( close_state == -1 );
+ close_state = state;
+ } else if ( state == QFtp::Unconnected ) {
+ QVERIFY( close_state == QFtp::Closing );
+ close_state = state;
+ }
+ }
+ } else if ( QTest::currentTestFunction() == QLatin1String("login") ) {
+ ResMapIt it = resultMap.find( QFtp::Login );
+ if ( it!=resultMap.end() && ftp->currentId()==it.value().id ) {
+ if ( state == QFtp::LoggedIn ) {
+ QVERIFY( login_state == -1 );
+ login_state = state;
+ }
+ }
+ }
+}
+
+void tst_QFtp::listInfo( const QUrlInfo &i )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d: listInfo( %s )", ftp->currentId(), i.name().toLatin1().constData() );
+#endif
+ QCOMPARE( ftp->currentId(), current_id );
+ if ( ids.count() > 1 ) {
+ QVERIFY( ftp->hasPendingCommands() );
+ } else {
+ QVERIFY( !ftp->hasPendingCommands() );
+ }
+ QVERIFY( cur_state == ftp->state() );
+ CURRENTCOMMAND_TEST;
+
+ if ( QTest::currentTestFunction()==QLatin1String("list") || QTest::currentTestFunction()==QLatin1String("cd") || QTest::currentTestFunction()==QLatin1String("proxy") || inFileDirExistsFunction ) {
+ ResMapIt it = resultMap.find( QFtp::List );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( ftp->currentId() == it.value().id );
+ listInfo_i << i;
+ }
+}
+
+void tst_QFtp::readyRead()
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d: readyRead(), bytesAvailable == %lu", ftp->currentId(), ftp->bytesAvailable() );
+#endif
+ QCOMPARE( ftp->currentId(), current_id );
+ if ( ids.count() > 1 ) {
+ QVERIFY( ftp->hasPendingCommands() );
+ } else {
+ QVERIFY( !ftp->hasPendingCommands() );
+ }
+ QVERIFY( cur_state == ftp->state() );
+ CURRENTCOMMAND_TEST;
+
+ if ( QTest::currentTestFunction() != QLatin1String("bytesAvailable") ) {
+ int oldSize = newData_ba.size();
+ qlonglong bytesAvail = ftp->bytesAvailable();
+ QByteArray ba = ftp->readAll();
+ QVERIFY( ba.size() == (int) bytesAvail );
+ newData_ba.resize( oldSize + ba.size() );
+ memcpy( newData_ba.data()+oldSize, ba.data(), ba.size() );
+
+ if ( bytesTotal != -1 ) {
+ QVERIFY( (int)newData_ba.size() <= bytesTotal );
+ }
+ QVERIFY( (int)newData_ba.size() == bytesDone );
+ }
+}
+
+void tst_QFtp::dataTransferProgress( qint64 done, qint64 total )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d: dataTransferProgress( %lli, %lli )", ftp->currentId(), done, total );
+#endif
+ QCOMPARE( ftp->currentId(), current_id );
+ if ( ids.count() > 1 ) {
+ QVERIFY( ftp->hasPendingCommands() );
+ } else {
+ QVERIFY( !ftp->hasPendingCommands() );
+ }
+ QVERIFY( cur_state == ftp->state() );
+ CURRENTCOMMAND_TEST;
+
+ if ( bytesTotal == bytesTotal_init ) {
+ bytesTotal = total;
+ } else {
+ QVERIFY( bytesTotal == total );
+ }
+
+ QVERIFY( bytesTotal != bytesTotal_init );
+ QVERIFY( bytesDone <= done );
+ bytesDone = done;
+ if ( bytesTotal != -1 ) {
+ QVERIFY( bytesDone <= bytesTotal );
+ }
+
+ if ( QTest::currentTestFunction() == QLatin1String("abort") ) {
+ // ### it would be nice if we could specify in our testdata when to do
+ // the abort
+ if ( done >= total/100000 ) {
+ if ( ids.count() != 1 ) {
+ // do abort only once
+ int tmpId = ids.first();
+ ids.clear();
+ ids << tmpId;
+ ftp->abort();
+ }
+ }
+ }
+}
+
+
+QFtp *tst_QFtp::newFtp()
+{
+ QFtp *nFtp = new QFtp( this );
+#ifndef QT_NO_BEARERMANAGEMENT
+ if (networkSessionExplicit) {
+ nFtp->setProperty("_q_networksession", QVariant::fromValue(networkSessionExplicit));
+ }
+#endif
+ connect( nFtp, SIGNAL(commandStarted(int)),
+ SLOT(commandStarted(int)) );
+ connect( nFtp, SIGNAL(commandFinished(int,bool)),
+ SLOT(commandFinished(int,bool)) );
+ connect( nFtp, SIGNAL(done(bool)),
+ SLOT(done(bool)) );
+ connect( nFtp, SIGNAL(stateChanged(int)),
+ SLOT(stateChanged(int)) );
+ connect( nFtp, SIGNAL(listInfo(const QUrlInfo&)),
+ SLOT(listInfo(const QUrlInfo&)) );
+ connect( nFtp, SIGNAL(readyRead()),
+ SLOT(readyRead()) );
+ connect( nFtp, SIGNAL(dataTransferProgress(qint64, qint64)),
+ SLOT(dataTransferProgress(qint64, qint64)) );
+
+ return nFtp;
+}
+
+void tst_QFtp::addCommand( QFtp::Command cmd, int id )
+{
+ ids << id;
+ CommandResult res;
+ res.id = id;
+ res.success = -1;
+ resultMap[ cmd ] = res;
+}
+
+bool tst_QFtp::fileExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &file, const QString &cdDir )
+{
+ init();
+ ftp = newFtp();
+ // ### make these tests work
+ if (ftp->currentId() != 0) {
+ qWarning("ftp->currentId() != 0");
+ return FALSE;
+ }
+
+ if (ftp->state() != QFtp::Unconnected) {
+ qWarning("ftp->state() != QFtp::Unconnected");
+ return FALSE;
+ }
+
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ if ( !cdDir.isNull() )
+ addCommand( QFtp::Cd, ftp->cd( cdDir ) );
+ addCommand( QFtp::List, ftp->list( file ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ inFileDirExistsFunction = TRUE;
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() ) {
+ // ### make this test work
+ qWarning("tst_QFtp::fileExists: Network operation timed out");
+ return FALSE;
+ }
+ inFileDirExistsFunction = FALSE;
+
+ ResMapIt it = resultMap.find( QFtp::ConnectToHost );
+ // ### make these tests work
+ if (it == resultMap.end()) {
+ qWarning("it != resultMap.end()");
+ return FALSE;
+ }
+
+ if (it.value().success == -1) {
+ qWarning("it.value().success != -1");
+ return FALSE;
+ }
+
+ if ( it.value().success == 1 ) {
+ for ( uint i=0; i < (uint) listInfo_i.count(); i++ ) {
+ if ( QFileInfo(listInfo_i[i].name()).fileName() == QFileInfo(file).fileName() )
+ return TRUE;
+ }
+ }
+
+ //this is not a good warning considering sometime this function is used to test that a file does not exist
+ //qWarning("file doesn't exist");
+ return FALSE;
+}
+
+bool tst_QFtp::dirExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &cdDir, const QString &dirToCreate )
+{
+ init();
+ ftp = newFtp();
+ // ### make these tests work
+ // QCOMPARE( ftp->currentId(), 0 );
+ // QCOMPARE( (int)ftp->state(), (int)QFtp::Unconnected );
+
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ if ( dirToCreate.startsWith( "/" ) )
+ addCommand( QFtp::Cd, ftp->cd( dirToCreate ) );
+ else
+ addCommand( QFtp::Cd, ftp->cd( cdDir + "/" + dirToCreate ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ inFileDirExistsFunction = TRUE;
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ ftp = 0;
+ if ( QTestEventLoop::instance().timeout() ) {
+ // ### make this test work
+ // QFAIL( "Network operation timed out" );
+ qWarning("tst_QFtp::dirExists: Network operation timed out");
+ return FALSE;
+ }
+ inFileDirExistsFunction = FALSE;
+
+ ResMapIt it = resultMap.find( QFtp::Cd );
+ // ### make these tests work
+ // QVERIFY( it != resultMap.end() );
+ // QVERIFY( it.value().success != -1 );
+ return it.value().success == 1;
+}
+
+void tst_QFtp::doneSignal()
+{
+ QFtp ftp;
+ QSignalSpy spy(&ftp, SIGNAL(done(bool)));
+
+ ftp.connectToHost(QtNetworkSettings::serverName());
+ ftp.login("anonymous");
+ ftp.list();
+ ftp.close();
+
+ done_success = 0;
+ connect(&ftp, SIGNAL(done(bool)), &(QTestEventLoop::instance()), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(61);
+ if (QTestEventLoop::instance().timeout())
+ QFAIL("Network operation timed out");
+
+ QTest::qWait(200);
+
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.first().first().toBool(), false);
+}
+
+void tst_QFtp::queueMoreCommandsInDoneSlot()
+{
+ QSKIP("Task 127050 && 113966", SkipSingle);
+
+ QFtp ftp;
+ QSignalSpy doneSpy(&ftp, SIGNAL(done(bool)));
+ QSignalSpy commandFinishedSpy(&ftp, SIGNAL(commandFinished(int, bool)));
+
+ this->ftp = &ftp;
+ connect(&ftp, SIGNAL(done(bool)), this, SLOT(cdUpSlot(bool)));
+
+ ftp.connectToHost("ftp.qt.nokia.com");
+ ftp.login();
+ ftp.cd("qt");
+ ftp.rmdir("qtest-removedir-noexist");
+
+ while ( ftp.hasPendingCommands() || ftp.currentCommand() != QFtp::None ) {
+ QCoreApplication::instance()->processEvents(QEventLoop::AllEvents
+ | QEventLoop::WaitForMoreEvents);
+ }
+
+ QCOMPARE(doneSpy.count(), 2);
+ QCOMPARE(doneSpy.first().first().toBool(), true);
+ QCOMPARE(doneSpy.last().first().toBool(), false);
+
+ QCOMPARE(commandFinishedSpy.count(), 6);
+ int firstId = commandFinishedSpy.at(0).at(0).toInt();
+ QCOMPARE(commandFinishedSpy.at(0).at(1).toBool(), false);
+ QCOMPARE(commandFinishedSpy.at(1).at(0).toInt(), firstId + 1);
+ QCOMPARE(commandFinishedSpy.at(1).at(1).toBool(), false);
+ QCOMPARE(commandFinishedSpy.at(2).at(0).toInt(), firstId + 2);
+ QCOMPARE(commandFinishedSpy.at(2).at(1).toBool(), false);
+ QCOMPARE(commandFinishedSpy.at(3).at(0).toInt(), firstId + 3);
+ QCOMPARE(commandFinishedSpy.at(3).at(1).toBool(), true);
+ QCOMPARE(commandFinishedSpy.at(4).at(0).toInt(), firstId + 4);
+ QCOMPARE(commandFinishedSpy.at(4).at(1).toBool(), false);
+ QCOMPARE(commandFinishedSpy.at(5).at(0).toInt(), firstId + 5);
+ QCOMPARE(commandFinishedSpy.at(5).at(1).toBool(), false);
+
+ this->ftp = 0;
+}
+
+void tst_QFtp::cdUpSlot(bool error)
+{
+ if (error) {
+ ftp->cd("..");
+ ftp->cd("qt");
+ }
+}
+
+void tst_QFtp::qtbug7359Crash()
+{
+ QFtp ftp;
+ ftp.connectToHost("127.0.0.1");
+
+ QTime t;
+ int elapsed;
+
+ t.start();
+ while ((elapsed = t.elapsed()) < 200)
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 200 - elapsed);
+
+ ftp.close();
+ t.restart();
+ while ((elapsed = t.elapsed()) < 1000)
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 1000 - elapsed);
+
+ ftp.connectToHost("127.0.0.1");
+
+ t.restart();
+ while ((elapsed = t.elapsed()) < 2000)
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 2000 - elapsed);
+}
+
+QTEST_MAIN(tst_QFtp)
+
+#include "tst_qftp.moc"
diff --git a/tests/auto/network/access/qhttp/.gitattributes b/tests/auto/network/access/qhttp/.gitattributes
new file mode 100644
index 0000000000..e04709aa2e
--- /dev/null
+++ b/tests/auto/network/access/qhttp/.gitattributes
@@ -0,0 +1 @@
+rfc3252.txt -crlf
diff --git a/tests/auto/network/access/qhttp/.gitignore b/tests/auto/network/access/qhttp/.gitignore
new file mode 100644
index 0000000000..00c1f492cd
--- /dev/null
+++ b/tests/auto/network/access/qhttp/.gitignore
@@ -0,0 +1 @@
+tst_qhttp
diff --git a/tests/auto/network/access/qhttp/dummyserver.h b/tests/auto/network/access/qhttp/dummyserver.h
new file mode 100644
index 0000000000..7c14ae2f14
--- /dev/null
+++ b/tests/auto/network/access/qhttp/dummyserver.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+// Use if you need
+
+class DummyHttpServer : public QTcpServer
+{
+ Q_OBJECT
+public:
+ DummyHttpServer() : phase(Header)
+ { listen(); }
+
+protected:
+ enum {
+ Header,
+ Data1,
+ Data2,
+ Close
+ } phase;
+ void incomingConnection(int socketDescriptor)
+ {
+ QSslSocket *socket = new QSslSocket(this);
+ socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState);
+ socket->ignoreSslErrors();
+ socket->startServerEncryption();
+ connect(socket, SIGNAL(readyRead()), SLOT(handleReadyRead()));
+ }
+
+public slots:
+ void handleReadyRead()
+ {
+ QTcpSocket *socket = static_cast<QTcpSocket *>(sender());
+ socket->readAll();
+ if (phase != Header)
+ return;
+
+ phase = Data1;
+ static const char header[] =
+ "HTTP/1.0 200 OK\r\n"
+ "Date: Fri, 07 Sep 2007 12:33:18 GMT\r\n"
+ "Server: Apache\r\n"
+ "Expires:\r\n"
+ "Cache-Control:\r\n"
+ "Pragma:\r\n"
+ "Last-Modified: Thu, 06 Sep 2007 08:52:06 +0000\r\n"
+ "Etag: a700f59a6ccb1ad39af68d998aa36fb1\r\n"
+ "Vary: Accept-Encoding\r\n"
+ "Content-Length: 6560\r\n"
+ "Connection: close\r\n"
+ "Content-Type: text/html; charset=utf-8\r\n"
+ "\r\n";
+
+
+ socket->write(header, sizeof header - 1);
+ connect(socket, SIGNAL(bytesWritten(qint64)), SLOT(handleBytesWritten()), Qt::QueuedConnection);
+ }
+
+ void handleBytesWritten()
+ {
+ QTcpSocket *socket = static_cast<QTcpSocket *>(sender());
+ if (socket->bytesToWrite() != 0)
+ return;
+
+ if (phase == Data1) {
+ QByteArray data(4096, 'a');
+ socket->write(data);
+ phase = Data2;
+ } else if (phase == Data2) {
+ QByteArray data(2464, 'a');
+ socket->write(data);
+ phase = Close;
+ } else {
+ //socket->disconnectFromHost();
+ //socket->deleteLater();
+ }
+ }
+};
diff --git a/tests/auto/network/access/qhttp/qhttp.pro b/tests/auto/network/access/qhttp/qhttp.pro
new file mode 100644
index 0000000000..f01f60f3d7
--- /dev/null
+++ b/tests/auto/network/access/qhttp/qhttp.pro
@@ -0,0 +1,31 @@
+load(qttest_p4)
+SOURCES += tst_qhttp.cpp
+
+
+QT = core network
+
+wince*: {
+ webFiles.files = webserver/*
+ webFiles.path = webserver
+ cgi.files = webserver/cgi-bin/*
+ cgi.path = webserver/cgi-bin
+ addFiles.files = rfc3252.txt trolltech
+ addFiles.path = .
+ DEPLOYMENT += addFiles webFiles cgi
+ DEFINES += SRCDIR=\\\"\\\"
+} else:symbian {
+ webFiles.files = webserver/*
+ webFiles.path = webserver
+ cgi.files = webserver/cgi-bin/*
+ cgi.path = webserver/cgi-bin
+ addFiles.files = rfc3252.txt trolltech
+ addFiles.path = .
+ DEPLOYMENT += addFiles webFiles cgi
+ TARGET.CAPABILITY = NetworkServices
+} else:vxworks*: {
+ DEFINES += SRCDIR=\\\"\\\"
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
+
+CONFIG+=insignificant_test
diff --git a/tests/auto/network/access/qhttp/rfc3252.txt b/tests/auto/network/access/qhttp/rfc3252.txt
new file mode 100644
index 0000000000..b80c61bf0a
--- /dev/null
+++ b/tests/auto/network/access/qhttp/rfc3252.txt
@@ -0,0 +1,899 @@
+
+
+
+
+
+
+Network Working Group H. Kennedy
+Request for Comments: 3252 Mimezine
+Category: Informational 1 April 2002
+
+
+ Binary Lexical Octet Ad-hoc Transport
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ This document defines a reformulation of IP and two transport layer
+ protocols (TCP and UDP) as XML applications.
+
+1. Introduction
+
+1.1. Overview
+
+ This document describes the Binary Lexical Octet Ad-hoc Transport
+ (BLOAT): a reformulation of a widely-deployed network-layer protocol
+ (IP [RFC791]), and two associated transport layer protocols (TCP
+ [RFC793] and UDP [RFC768]) as XML [XML] applications. It also
+ describes methods for transporting BLOAT over Ethernet and IEEE 802
+ networks as well as encapsulating BLOAT in IP for gatewaying BLOAT
+ across the public Internet.
+
+1.2. Motivation
+
+ The wild popularity of XML as a basis for application-level protocols
+ such as the Blocks Extensible Exchange Protocol [RFC3080], the Simple
+ Object Access Protocol [SOAP], and Jabber [JABBER] prompted
+ investigation into the possibility of extending the use of XML in the
+ protocol stack. Using XML at both the transport and network layer in
+ addition to the application layer would provide for an amazing amount
+ of power and flexibility while removing dependencies on proprietary
+ and hard-to-understand binary protocols. This protocol unification
+ would also allow applications to use a single XML parser for all
+ aspects of their operation, eliminating developer time spent figuring
+ out the intricacies of each new protocol, and moving the hard work of
+
+
+
+
+Kennedy Informational [Page 1]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ parsing to the XML toolset. The use of XML also mitigates concerns
+ over "network vs. host" byte ordering which is at the root of many
+ network application bugs.
+
+1.3. Relation to Existing Protocols
+
+ The reformulations specified in this RFC follow as closely as
+ possible the spirit of the RFCs on which they are based, and so MAY
+ contain elements or attributes that would not be needed in a pure
+ reworking (e.g. length attributes, which are implicit in XML.)
+
+ The layering of network and transport protocols are maintained in
+ this RFC despite the optimizations that could be made if the line
+ were somewhat blurred (i.e. merging TCP and IP into a single, larger
+ element in the DTD) in order to foster future use of this protocol as
+ a basis for reformulating other protocols (such as ICMP.)
+
+ Other than the encoding, the behavioral aspects of each of the
+ existing protocols remain unchanged. Routing, address spaces, TCP
+ congestion control, etc. behave as specified in the extant standards.
+ Adapting to new standards and experimental algorithm heuristics for
+ improving performance will become much easier once the move to BLOAT
+ has been completed.
+
+1.4. Requirement Levels
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in BCP 14, RFC 2119
+ [RFC2119].
+
+2. IPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC.
+ IPoXML is the root protocol REQUIRED for effective use of TCPoXML
+ (section 3.) and higher-level application protocols.
+
+ The DTD for this document type can be found in section 7.1.
+
+ The routing of IPoXML can be easily implemented on hosts with an XML
+ parser, as the regular structure lends itself handily to parsing and
+ validation of the document/datagram and then processing the
+ destination address, TTL, and checksum before sending it on to its
+ next-hop.
+
+ The reformulation of IPv4 was chosen over IPv6 [RFC2460] due to the
+ wider deployment of IPv4 and the fact that implementing IPv6 as XML
+ would have exceeded the 1500 byte Ethernet MTU.
+
+
+
+Kennedy Informational [Page 2]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ All BLOAT implementations MUST use - and specify - the UTF-8 encoding
+ of RFC 2279 [RFC2279]. All BLOAT document/datagrams MUST be well-
+ formed and include the XMLDecl.
+
+2.1. IP Description
+
+ A number of items have changed (for the better) from the original IP
+ specification. Bit-masks, where present have been converted into
+ human-readable values. IP addresses are listed in their dotted-
+ decimal notation [RFC1123]. Length and checksum values are present
+ as decimal integers.
+
+ To calculate the length and checksum fields of the IP element, a
+ canonicalized form of the element MUST be used. The canonical form
+ SHALL have no whitespace (including newline characters) between
+ elements and only one space character between attributes. There
+ SHALL NOT be a space following the last attribute in an element.
+
+ An iterative method SHOULD be used to calculate checksums, as the
+ length field will vary based on the size of the checksum.
+
+ The payload element bears special attention. Due to the character
+ set restrictions of XML, the payload of IP datagrams (which MAY
+ contain arbitrary data) MUST be encoded for transport. This RFC
+ REQUIRES the contents of the payload to be encoded in the base-64
+ encoding of RFC 2045 [RFC2045], but removes the requirement that the
+ encoded output MUST be wrapped on 76-character lines.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 3]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+2.2. Example Datagram
+
+ The following is an example IPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ <ip>
+ <header length="474">
+ <version value="4"/>
+ <tos precedence="Routine" delay="Normal" throughput="Normal"
+ relibility="Normal" reserved="0"/>
+ <total.length value="461"/>
+ <id value="1"/>
+ <flags reserved="0" df="dont" mf="last"/>
+ <offset value="0"/>
+ <ttl value="255"/>
+ <protocol value="6"/>
+ <checksum value="8707"/>
+ <source address="10.0.0.22"/>
+ <destination address="10.0.0.1"/>
+ <options>
+ <end copied="0" class="0" number="0"/>
+ </options>
+ <padding pad="0"/>
+ </header>
+ <payload>
+ </payload>
+ </ip>
+
+3. TCPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.2.
+
+3.1. TCP Description
+
+ A number of items have changed from the original TCP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+ To calculate the length and checksum fields of the TCP element, a
+ canonicalized form of the element MUST be used as in section 2.1.
+
+ An iterative method SHOULD be used to calculate checksums as in
+ section 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+
+
+Kennedy Informational [Page 4]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ The TCP offset element was expanded to a maximum of 255 from 16 to
+ allow for the increased size of the header in XML.
+
+ TCPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+3.2. Example Datagram
+
+ The following is an example TCPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ <tcp>
+ <tcp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <sequence number="322622954"/>
+ <acknowledgement number="689715995"/>
+ <offset number=""/>
+ <reserved value="0"/>
+ <control syn="1" ack="1"/>
+ <window size="1"/>
+ <urgent pointer="0"/>
+ <checksum value="2988"/>
+ <tcp.options>
+ <tcp.end kind="0"/>
+ </tcp.options>
+ <padding pad="0"/>
+ </tcp.header>
+ <payload>
+ </payload>
+ </tcp>
+
+4. UDPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.3.
+
+4.1. UDP Description
+
+ A number of items have changed from the original UDP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+
+
+
+
+
+
+Kennedy Informational [Page 5]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ To calculate the length and checksum fields of the UDP element, a
+ canonicalized form of the element MUST be used as in section 2.1. An
+ iterative method SHOULD be used to calculate checksums as in section
+ 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+ UDPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+4.2. Example Datagram
+
+ The following is an example UDPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ <udp>
+ <udp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <udp.length value="143"/>
+ <checksum value="2988"/>
+ </udp.header>
+ <payload>
+ </payload>
+ </udp>
+
+5. Network Transport
+
+ This document provides for the transmission of BLOAT datagrams over
+ two common families of physical layer transport. Future RFCs will
+ address additional transports as routing vendors catch up to the
+ specification, and we begin to see BLOAT routed across the Internet
+ backbone.
+
+5.1. Ethernet
+
+ BLOAT is encapsulated in Ethernet datagrams as in [RFC894] with the
+ exception that the type field of the Ethernet frame MUST contain the
+ value 0xBEEF. The first 5 octets of the Ethernet frame payload will
+ be 0x3c 3f 78 6d 6c ("<?xml".)
+
+5.2. IEEE 802
+
+ BLOAT is encapsulated in IEEE 802 Networks as in [RFC1042] except
+ that the protocol type code for IPoXML is 0xBEEF.
+
+
+
+
+
+Kennedy Informational [Page 6]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+6. Gatewaying over IP
+
+ In order to facilitate the gradual introduction of BLOAT into the
+ public Internet, BLOAT MAY be encapsulated in IP as in [RFC2003] to
+ gateway between networks that run BLOAT natively on their LANs.
+
+7. DTDs
+
+ The Transport DTDs (7.2. and 7.3.) build on the definitions in the
+ Network DTD (7.1.)
+
+ The DTDs are referenced by their PubidLiteral and SystemLiteral (from
+ [XML]) although it is understood that most IPoXML implementations
+ will not need to pull down the DTD, as it will normally be embedded
+ in the implementation, and presents something of a catch-22 if you
+ need to load part of your network protocol over the network.
+
+7.1. IPoXML DTD
+
+ <!--
+ DTD for IP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ -->
+ <!--
+ DTD data types:
+
+ Digits [0..9]+
+
+ Precedence "NetworkControl | InternetworkControl |
+ CRITIC | FlashOverride | Flash | Immediate |
+ Priority | Routine"
+
+ IP4Addr "dotted-decimal" notation of [RFC1123]
+
+ Class [0..3]
+
+ Sec "Unclassified | Confidential | EFTO | MMMM | PROG |
+ Restricted | Secret | Top Secret | Reserved"
+
+ Compartments [0..65535]
+
+ Handling [0..65535]
+
+ TCC [0..16777216]
+
+ -->
+
+
+
+Kennedy Informational [Page 7]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ENTITY % Digits "CDATA">
+ <!ENTITY % Precedence "CDATA">
+ <!ENTITY % IP4Addr "CDATA">
+ <!ENTITY % Class "CDATA">
+ <!ENTITY % Sec "CDATA">
+ <!ENTITY % Compartments "CDATA">
+ <!ENTITY % Handling "CDATA">
+ <!ENTITY % TCC "CDATA">
+
+ <!ELEMENT ip (header, payload)>
+
+ <!ELEMENT header (version, tos, total.length, id, flags, offset, ttl,
+ protocol, checksum, source, destination, options,
+ padding)>
+ <!-- length of header in 32-bit words -->
+ <!ATTLIST header
+ length %Digits; #REQUIRED>
+
+ <!ELEMENT version EMPTY>
+ <!-- ip version. SHOULD be "4" -->
+ <!ATTLIST version
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT tos EMPTY>
+ <!ATTLIST tos
+ precedence %Precedence; #REQUIRED
+ delay (normal | low) #REQUIRED
+ throughput (normal | high) #REQUIRED
+ relibility (normal | high) #REQUIRED
+ reserved CDATA #FIXED "0">
+
+ <!ELEMENT total.length EMPTY>
+ <!--
+ total length of datagram (header and payload) in octets, MUST be
+ less than 65,535 (and SHOULD be less than 1024 for IPoXML on local
+ ethernets).
+ -->
+ <!ATTLIST total.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT id EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST id
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT flags EMPTY>
+ <!-- df = don't fragment, mf = more fragments -->
+ <!ATTLIST flags
+
+
+
+Kennedy Informational [Page 8]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ reserved CDATA #FIXED "0"
+ df (may|dont) #REQUIRED
+ mf (last|more) #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= offset <= 8192 measured in 8 octet (64-bit) chunks -->
+ <!ATTLIST offset
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT ttl EMPTY>
+ <!-- 0 <= ttl <= 255 -->
+ <!ATTLIST ttl
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT protocol EMPTY>
+ <!-- 0 <= protocol <= 255 (per IANA) -->
+ <!ATTLIST protocol
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT checksum EMPTY>
+ <!-- 0 <= checksum <= 65535 (over header only) -->
+ <!ATTLIST checksum
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT source EMPTY>
+ <!ATTLIST source
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT destination EMPTY>
+ <!ATTLIST destination
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT options ( end | noop | security | loose | strict | record
+ | stream | timestamp )*>
+
+ <!ELEMENT end EMPTY>
+ <!ATTLIST end
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "0">
+
+ <!ELEMENT noop EMPTY>
+ <!ATTLIST noop
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "1">
+
+ <!ELEMENT security EMPTY>
+
+
+
+Kennedy Informational [Page 9]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST security
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "2"
+ length CDATA #FIXED "11"
+ security %Sec; #REQUIRED
+ compartments %Compartments; #REQUIRED
+ handling %Handling; #REQUIRED
+ tcc %TCC; #REQUIRED>
+ <!ELEMENT loose (hop)+>
+ <!ATTLIST loose
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "3"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT hop EMPTY>
+ <!ATTLIST hop
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT strict (hop)+>
+ <!ATTLIST strict
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "9"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT record (hop)+>
+ <!ATTLIST record
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "7"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT stream EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST stream
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "8"
+ length CDATA #FIXED "4"
+ id %Digits; #REQUIRED>
+
+ <!ELEMENT timestamp (tstamp)+>
+ <!-- 0 <= oflw <=15 -->
+
+
+
+Kennedy Informational [Page 10]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST timestamp
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "2"
+ number CDATA #FIXED "4"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED
+ oflw %Digits; #REQUIRED
+ flag (0 | 1 | 3) #REQUIRED>
+
+ <!ELEMENT tstamp EMPTY>
+ <!ATTLIST tstamp
+ time %Digits; #REQUIRED
+ address %IP4Addr; #IMPLIED>
+ <!--
+ padding to bring header to 32-bit boundary.
+ pad MUST be "0"*
+ -->
+ <!ELEMENT padding EMPTY>
+ <!ATTLIST padding
+ pad CDATA #REQUIRED>
+
+ <!-- payload MUST be encoded as base-64 [RFC2045], as modified
+ by section 2.1 of this RFC -->
+ <!ELEMENT payload (CDATA)>
+
+7.2. TCPoXML DTD
+
+ <!--
+ DTD for TCP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ -->
+
+ <!-- the pseudoheader is only included for checksum calculations -->
+ <!ELEMENT tcp (tcp.pseudoheader?, tcp.header, payload)>
+
+ <!ELEMENT tcp.header (src, dest, sequence, acknowledgement, offset,
+ reserved, control, window, checksum, urgent,
+ tcp.options, padding)>
+
+ <!ELEMENT src EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+ <!ATTLIST src
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT dest EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+
+
+
+Kennedy Informational [Page 11]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST dest
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT sequence EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST sequence
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT acknowledgement EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST acknowledgement
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= number <= 255 -->
+ <!ATTLIST offset
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT reserved EMPTY>
+ <!ATTLIST reserved
+ value CDATA #FIXED "0">
+
+ <!ELEMENT control EMPTY>
+ <!ATTLIST control
+ urg (0|1) #IMPLIED
+ ack (0|1) #IMPLIED
+ psh (0|1) #IMPLIED
+ rst (0|1) #IMPLIED
+ syn (0|1) #IMPLIED
+ fin (0|1) #IMPLIED>
+
+ <!ELEMENT window EMPTY>
+ <!-- 0 <= size <= 65,535 -->
+ <!ATTLIST window
+ size %Digits; #REQUIRED>
+
+ <!--
+ checksum as in ip, but with
+ the following pseudo-header added into the tcp element:
+ -->
+ <!ELEMENT tcp.pseudoheader (source, destination, protocol,
+ tcp.length)>
+
+ <!--
+ tcp header + data length in octets. does not include the size of
+
+ the pseudoheader.
+ -->
+
+
+
+Kennedy Informational [Page 12]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ELEMENT tcp.length EMPTY>
+ <!ATTLIST tcp.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT urgent EMPTY>
+ <!-- 0 <= pointer <= 65,535 -->
+ <!ATTLIST urgent
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT tcp.options (tcp.end | tcp.noop | tcp.mss)+>
+
+ <!ELEMENT tcp.end EMPTY>
+ <!ATTLIST tcp.end
+ kind CDATA #FIXED "0">
+
+ <!ELEMENT tcp.noop EMPTY>
+ <!ATTLIST tcp.noop
+ kind CDATA #FIXED "1">
+
+ <!ELEMENT tcp.mss EMPTY>
+ <!ATTLIST tcp.mss
+ kind CDATA #FIXED "2"
+ length CDATA #FIXED "4"
+ size %Digits; #REQUIRED>
+
+7.3. UDPoXML DTD
+
+ <!--
+ DTD for UDP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ -->
+
+ <!ELEMENT udp (udp.pseudoheader?, udp.header, payload)>
+
+ <!ELEMENT udp.header (src, dest, udp.length, checksum)>
+
+ <!ELEMENT udp.pseudoheader (source, destination, protocol,
+ udp.length)>
+
+ <!--
+ udp header + data length in octets. does not include the size of
+ the pseudoheader.
+ -->
+ <!ELEMENT udp.length EMPTY>
+ <!ATTLIST udp.length
+ value %Digits; #REQUIRED>
+
+
+
+Kennedy Informational [Page 13]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+8. Security Considerations
+
+ XML, as a subset of SGML, has the same security considerations as
+ specified in SGML Media Types [RFC1874]. Security considerations
+ that apply to IP, TCP and UDP also likely apply to BLOAT as it does
+ not attempt to correct for issues not related to message format.
+
+9. References
+
+ [JABBER] Miller, J., "Jabber", draft-miller-jabber-00.txt,
+ February 2002. (Work in Progress)
+
+ [RFC768] Postel, J., "User Datagram Protocol", STD 6, RFC 768,
+ August 1980.
+
+ [RFC791] Postel, J., "Internet Protocol", STD 5, RFC 791,
+ September 1981.
+
+ [RFC793] Postel, J., "Transmission Control Protocol", STD 7, RFC
+ 793, September 1981.
+
+ [RFC894] Hornig, C., "Standard for the Transmission of IP
+ Datagrams over Ethernet Networks.", RFC 894, April 1984.
+
+ [RFC1042] Postel, J. and J. Reynolds, "Standard for the
+ Transmission of IP Datagrams Over IEEE 802 Networks", STD
+ 43, RFC 1042, February 1988.
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts -
+ Application and Support", RFC 1123, October 1989.
+
+ [RFC1874] Levinson, E., "SGML Media Types", RFC 1874, December
+ 1995.
+
+ [RFC2003] Perkins, C., "IP Encapsulation within IP", RFC 2003,
+ October 1996.
+
+ [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message
+ Bodies", RFC 2045, November 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+
+
+
+
+Kennedy Informational [Page 14]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ [RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6
+ (IPv6) Specification", RFC 2460, December 1998.
+
+ [RFC3080] Rose, M., "The Blocks Extensible Exchange Protocol Core",
+ RFC 3080, March 2001.
+
+ [SOAP] Box, D., Ehnebuske, D., Kakivaya, G., Layman, A.,
+ Mendelsohn, N., Nielsen, H. F., Thatte, S. Winer, D.,
+ "Simple Object Access Protocol (SOAP) 1.1" World Wide Web
+ Consortium Note, May 2000 http://www.w3.org/TR/SOAP/
+
+ [XML] Bray, T., Paoli, J., Sperberg-McQueen, C. M., "Extensible
+ Markup Language (XML)" World Wide Web Consortium
+ Recommendation REC- xml-19980210.
+ http://www.w3.org/TR/1998/REC-xml-19980210
+
+10. Author's Address
+
+ Hugh Kennedy
+ Mimezine
+ 1060 West Addison
+ Chicago, IL 60613
+ USA
+
+ EMail: kennedyh@engin.umich.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 15]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+11. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 16]
+
diff --git a/tests/auto/network/access/qhttp/trolltech b/tests/auto/network/access/qhttp/trolltech
new file mode 100644
index 0000000000..c155360e8d
--- /dev/null
+++ b/tests/auto/network/access/qhttp/trolltech
@@ -0,0 +1,8 @@
+<html>
+ <head>
+ <title>Test</title>
+ </head>
+ <body>
+ <h1>Test</h1>
+ </body>
+</html>
diff --git a/tests/auto/network/access/qhttp/tst_qhttp.cpp b/tests/auto/network/access/qhttp/tst_qhttp.cpp
new file mode 100644
index 0000000000..8875232714
--- /dev/null
+++ b/tests/auto/network/access/qhttp/tst_qhttp.cpp
@@ -0,0 +1,1576 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qbuffer.h>
+#include <qcoreapplication.h>
+#include <qfile.h>
+#include <qhostinfo.h>
+#include <qhttp.h>
+#include <qlist.h>
+#include <qpointer.h>
+#include <qtcpsocket.h>
+#include <qtcpserver.h>
+#include <qauthenticator.h>
+#include <QNetworkProxy>
+#ifndef QT_NO_OPENSSL
+# include <qsslsocket.h>
+#endif
+
+#include "../../../network-settings.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+#ifdef Q_OS_SYMBIAN
+// In Symbian OS test data is located in applications private dir
+// And underlying Open C have application private dir in default search path
+#define SRCDIR ""
+#endif
+
+Q_DECLARE_METATYPE(QHttpResponseHeader)
+
+class tst_QHttp : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QHttp();
+ virtual ~tst_QHttp();
+
+
+public slots:
+ void initTestCase_data();
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void constructing();
+ void invalidRequests();
+ void get_data();
+ void get();
+ void head_data();
+ void head();
+ void post_data();
+ void post();
+ void request_data();
+ void request();
+ void authorization_data();
+ void authorization();
+ void proxy_data();
+ void proxy();
+ void proxy2();
+ void proxy3();
+ void postAuthNtlm();
+ void proxyAndSsl();
+ void cachingProxyAndSsl();
+ void reconnect();
+ void setSocket();
+ void unexpectedRemoteClose();
+ void pctEncodedPath();
+ void caseInsensitiveKeys();
+ void emptyBodyInReply();
+ void abortInReadyRead();
+ void abortInResponseHeaderReceived();
+ void nestedEventLoop();
+ void connectionClose();
+
+protected slots:
+ void stateChanged( int );
+ void responseHeaderReceived( const QHttpResponseHeader & );
+ void readyRead( const QHttpResponseHeader& );
+ void dataSendProgress( int, int );
+ void dataReadProgress( int , int );
+
+ void requestStarted( int );
+ void requestFinished( int, bool );
+ void done( bool );
+
+ void reconnect_state(int state);
+ void proxy2_slot();
+ void nestedEventLoop_slot(int id);
+
+ void abortSender();
+ void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth);
+
+private:
+ QHttp *newHttp(bool withAuth = false);
+ void addRequest( QHttpRequestHeader, int );
+ bool headerAreEqual( const QHttpHeader&, const QHttpHeader& );
+
+ QHttp *http;
+
+ struct RequestResult
+ {
+ QHttpRequestHeader req;
+ QHttpResponseHeader resp;
+ int success;
+ };
+ QMap< int, RequestResult > resultMap;
+ typedef QMap<int,RequestResult>::Iterator ResMapIt;
+ QList<int> ids; // helper to make sure that all expected signals are emitted
+
+ int current_id;
+ int cur_state;
+ int done_success;
+
+ QByteArray readyRead_ba;
+
+ int bytesTotalSend;
+ int bytesDoneSend;
+ int bytesTotalRead;
+ int bytesDoneRead;
+
+ int getId;
+ int headId;
+ int postId;
+
+ int reconnect_state_connect_count;
+
+ bool connectionWithAuth;
+ bool proxyAuthCalled;
+};
+
+class ClosingServer: public QTcpServer
+{
+ Q_OBJECT
+public:
+ ClosingServer()
+ {
+ connect(this, SIGNAL(newConnection()), SLOT(handleConnection()));
+ listen();
+ }
+
+public slots:
+ void handleConnection()
+ {
+ delete nextPendingConnection();
+ }
+};
+
+//#define DUMP_SIGNALS
+
+const int bytesTotal_init = -10;
+const int bytesDone_init = -10;
+
+tst_QHttp::tst_QHttp()
+{
+ Q_SET_DEFAULT_IAP
+}
+
+tst_QHttp::~tst_QHttp()
+{
+}
+
+void tst_QHttp::initTestCase_data()
+{
+ QTest::addColumn<bool>("setProxy");
+ QTest::addColumn<int>("proxyType");
+
+ QTest::newRow("WithoutProxy") << false << 0;
+ QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy);
+}
+
+void tst_QHttp::initTestCase()
+{
+}
+
+void tst_QHttp::cleanupTestCase()
+{
+}
+
+void tst_QHttp::init()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy) {
+ QFETCH_GLOBAL(int, proxyType);
+ if (proxyType == QNetworkProxy::Socks5Proxy) {
+ QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
+ }
+ }
+
+ http = 0;
+
+ resultMap.clear();
+ ids.clear();
+
+ current_id = 0;
+ cur_state = QHttp::Unconnected;
+ done_success = -1;
+
+ readyRead_ba = QByteArray();
+
+ getId = -1;
+ headId = -1;
+ postId = -1;
+}
+
+void tst_QHttp::cleanup()
+{
+ delete http;
+ http = 0;
+
+ QCoreApplication::processEvents();
+
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy) {
+ QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy);
+ }
+}
+
+void tst_QHttp::constructing()
+{
+ //QHeader
+ {
+ QHttpRequestHeader header;
+ header.addValue("key1", "val1");
+ header.addValue("key2", "val2");
+ header.addValue("key1", "val3");
+ QCOMPARE(header.values().size(), 3);
+ QCOMPARE(header.allValues("key1").size(), 2);
+ QVERIFY(header.hasKey("key2"));
+ QCOMPARE(header.keys().count(), 2);
+
+ }
+
+ {
+ QHttpResponseHeader header(200);
+ }
+}
+
+void tst_QHttp::invalidRequests()
+{
+ QHttp http;
+ http.setHost("localhost"); // we will not actually connect
+
+ QTest::ignoreMessage(QtWarningMsg, "QHttp: empty path requested is invalid -- using '/'");
+ http.get(QString());
+
+ QTest::ignoreMessage(QtWarningMsg, "QHttp: empty path requested is invalid -- using '/'");
+ http.head(QString());
+
+ QTest::ignoreMessage(QtWarningMsg, "QHttp: empty path requested is invalid -- using '/'");
+ http.post(QString(), QByteArray());
+
+ QTest::ignoreMessage(QtWarningMsg, "QHttp: empty path requested is invalid -- using '/'");
+ http.request(QHttpRequestHeader("PROPFIND", QString()));
+}
+
+void tst_QHttp::get_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<int>("success");
+ QTest::addColumn<int>("statusCode");
+ QTest::addColumn<QByteArray>("res");
+ QTest::addColumn<bool>("useIODevice");
+
+ // ### move this into external testdata
+ QFile file( SRCDIR "rfc3252.txt" );
+ QVERIFY( file.open( QIODevice::ReadOnly ) );
+ QByteArray rfc3252 = file.readAll();
+ file.close();
+
+ file.setFileName( SRCDIR "trolltech" );
+ QVERIFY( file.open( QIODevice::ReadOnly ) );
+ QByteArray trolltech = file.readAll();
+ file.close();
+
+ // test the two get() modes in one routine
+ for ( int i=0; i<2; i++ ) {
+ QTest::newRow(QString("path_01_%1").arg(i).toLatin1()) << QtNetworkSettings::serverName() << 80u
+ << QString("/qtest/rfc3252.txt") << 1 << 200 << rfc3252 << (bool)(i==1);
+ QTest::newRow( QString("path_02_%1").arg(i).toLatin1() ) << QString("www.ietf.org") << 80u
+ << QString("/rfc/rfc3252.txt") << 1 << 200 << rfc3252 << (bool)(i==1);
+
+ QTest::newRow( QString("uri_01_%1").arg(i).toLatin1() ) << QtNetworkSettings::serverName() << 80u
+ << QString("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt") << 1 << 200 << rfc3252 << (bool)(i==1);
+ QTest::newRow( QString("uri_02_%1").arg(i).toLatin1() ) << "www.ietf.org" << 80u
+ << QString("http://www.ietf.org/rfc/rfc3252.txt") << 1 << 200 << rfc3252 << (bool)(i==1);
+
+ QTest::newRow( QString("fail_01_%1").arg(i).toLatin1() ) << QString("this-host-will-not-exist.") << 80u
+ << QString("/qtest/rfc3252.txt") << 0 << 0 << QByteArray() << (bool)(i==1);
+
+ QTest::newRow( QString("failprot_01_%1").arg(i).toLatin1() ) << QtNetworkSettings::serverName() << 80u
+ << QString("/t") << 1 << 404 << QByteArray() << (bool)(i==1);
+ QTest::newRow( QString("failprot_02_%1").arg(i).toLatin1() ) << QtNetworkSettings::serverName() << 80u
+ << QString("qtest/rfc3252.txt") << 1 << 400 << QByteArray() << (bool)(i==1);
+
+ // qt.nokia.com/doc uses transfer-encoding=chunked
+ /* qt.nokia.com/doc no longer seams to be using chuncked encodig.
+ QTest::newRow( QString("chunked_01_%1").arg(i).toLatin1() ) << QString("test.troll.no") << 80u
+ << QString("/") << 1 << 200 << trolltech << (bool)(i==1);
+ */
+ QTest::newRow( QString("chunked_02_%1").arg(i).toLatin1() ) << QtNetworkSettings::serverName() << 80u
+ << QString("/qtest/cgi-bin/rfc.cgi") << 1 << 200 << rfc3252 << (bool)(i==1);
+ }
+}
+
+void tst_QHttp::get()
+{
+ // for the overload that takes a QIODevice
+ QByteArray buf_ba;
+ QBuffer buf( &buf_ba );
+
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, path );
+ QFETCH( bool, useIODevice );
+
+ http = newHttp();
+ QCOMPARE( http->currentId(), 0 );
+ QCOMPARE( (int)http->state(), (int)QHttp::Unconnected );
+
+ addRequest( QHttpRequestHeader(), http->setHost( host, port ) );
+ if ( useIODevice ) {
+ buf.open( QIODevice::WriteOnly );
+ getId = http->get( path, &buf );
+ } else {
+ getId = http->get( path );
+ }
+ addRequest( QHttpRequestHeader(), getId );
+
+ QTestEventLoop::instance().enterLoop( 50 );
+
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt res = resultMap.find( getId );
+ QVERIFY( res != resultMap.end() );
+ if ( res.value().success!=1 && host=="www.ietf.org" ) {
+ // The nightly tests fail from time to time. In order to make them more
+ // stable, add some debug output that might help locate the problem (I
+ // can't reproduce the problem in the non-nightly builds).
+ qDebug( "Error %d: %s", http->error(), http->errorString().toLatin1().constData() );
+ }
+ QTEST( res.value().success, "success" );
+ if ( res.value().success ) {
+ QTEST( res.value().resp.statusCode(), "statusCode" );
+
+ QFETCH( QByteArray, res );
+ if ( res.count() > 0 ) {
+ if ( useIODevice ) {
+ QCOMPARE(buf_ba, res);
+ if ( bytesDoneRead != bytesDone_init )
+ QVERIFY( (int)buf_ba.size() == bytesDoneRead );
+ } else {
+ QCOMPARE(readyRead_ba, res);
+ if ( bytesDoneRead != bytesDone_init )
+ QVERIFY( (int)readyRead_ba.size() == bytesDoneRead );
+ }
+ }
+ QVERIFY( bytesTotalRead != bytesTotal_init );
+ if ( bytesTotalRead > 0 )
+ QVERIFY( bytesDoneRead == bytesTotalRead );
+ } else {
+ QVERIFY( !res.value().resp.isValid() );
+ }
+}
+
+void tst_QHttp::head_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<int>("success");
+ QTest::addColumn<int>("statusCode");
+ QTest::addColumn<uint>("contentLength");
+
+ QTest::newRow( "path_01" ) << QtNetworkSettings::serverName() << 80u
+ << QString("/qtest/rfc3252.txt") << 1 << 200 << 25962u;
+
+ QTest::newRow( "path_02" ) << QString("www.ietf.org") << 80u
+ << QString("/rfc/rfc3252.txt") << 1 << 200 << 25962u;
+
+ QTest::newRow( "uri_01" ) << QtNetworkSettings::serverName() << 80u
+ << QString("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt") << 1 << 200 << 25962u;
+
+ QTest::newRow( "uri_02" ) << QString("www.ietf.org") << 80u
+ << QString("http://www.ietf.org/rfc/rfc3252.txt") << 1 << 200 << 25962u;
+
+ QTest::newRow( "fail_01" ) << QString("this-host-will-not-exist.") << 80u
+ << QString("/qtest/rfc3252.txt") << 0 << 0 << 0u;
+
+ QTest::newRow( "failprot_01" ) << QtNetworkSettings::serverName() << 80u
+ << QString("/t") << 1 << 404 << 0u;
+
+ QTest::newRow( "failprot_02" ) << QtNetworkSettings::serverName() << 80u
+ << QString("qtest/rfc3252.txt") << 1 << 400 << 0u;
+
+ /* qt.nokia.com/doc no longer seams to be using chuncked encodig.
+ QTest::newRow( "chunked_01" ) << QString("qt.nokia.com/doc") << 80u
+ << QString("/index.html") << 1 << 200 << 0u;
+ */
+ QTest::newRow( "chunked_02" ) << QtNetworkSettings::serverName() << 80u
+ << QString("/qtest/cgi-bin/rfc.cgi") << 1 << 200 << 0u;
+}
+
+void tst_QHttp::head()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, path );
+
+ http = newHttp();
+ QCOMPARE( http->currentId(), 0 );
+ QCOMPARE( (int)http->state(), (int)QHttp::Unconnected );
+
+ addRequest( QHttpRequestHeader(), http->setHost( host, port ) );
+ headId = http->head( path );
+ addRequest( QHttpRequestHeader(), headId );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt res = resultMap.find( headId );
+ QVERIFY( res != resultMap.end() );
+ if ( res.value().success!=1 && host=="www.ietf.org" ) {
+ // The nightly tests fail from time to time. In order to make them more
+ // stable, add some debug output that might help locate the problem (I
+ // can't reproduce the problem in the non-nightly builds).
+ qDebug( "Error %d: %s", http->error(), http->errorString().toLatin1().constData() );
+ }
+ QTEST( res.value().success, "success" );
+ if ( res.value().success ) {
+ QTEST( res.value().resp.statusCode(), "statusCode" );
+ QTEST( res.value().resp.contentLength(), "contentLength" );
+
+ QCOMPARE( (uint)readyRead_ba.size(), 0u );
+ QVERIFY( bytesTotalRead == bytesTotal_init );
+ QVERIFY( bytesDoneRead == bytesDone_init );
+ } else {
+ QVERIFY( !res.value().resp.isValid() );
+ }
+}
+
+void tst_QHttp::post_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<bool>("useIODevice");
+ QTest::addColumn<bool>("useProxy");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<int>("port");
+ QTest::addColumn<bool>("ssl");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<QByteArray>("result");
+
+ QByteArray md5sum;
+ md5sum = "d41d8cd98f00b204e9800998ecf8427e";
+ QTest::newRow("empty-data")
+ << QString() << false << false
+ << QtNetworkSettings::serverName() << 80 << false << "/qtest/cgi-bin/md5sum.cgi" << md5sum;
+ QTest::newRow("empty-device")
+ << QString() << true << false
+ << QtNetworkSettings::serverName() << 80 << false << "/qtest/cgi-bin/md5sum.cgi" << md5sum;
+ QTest::newRow("proxy-empty-data")
+ << QString() << false << true
+ << QtNetworkSettings::serverName() << 80 << false << "/qtest/cgi-bin/md5sum.cgi" << md5sum;
+
+ md5sum = "b3e32ac459b99d3f59318f3ac31e4bee";
+ QTest::newRow("data") << "rfc3252.txt" << false << false
+ << QtNetworkSettings::serverName() << 80 << false << "/qtest/cgi-bin/md5sum.cgi"
+ << md5sum;
+ QTest::newRow("device") << "rfc3252.txt" << true << false
+ << QtNetworkSettings::serverName() << 80 << false << "/qtest/cgi-bin/md5sum.cgi"
+ << md5sum;
+ QTest::newRow("proxy-data") << "rfc3252.txt" << false << true
+ << QtNetworkSettings::serverName() << 80 << false << "/qtest/cgi-bin/md5sum.cgi"
+ << md5sum;
+
+#ifndef QT_NO_OPENSSL
+ md5sum = "d41d8cd98f00b204e9800998ecf8427e";
+ QTest::newRow("empty-data-ssl")
+ << QString() << false << false
+ << QtNetworkSettings::serverName() << 443 << true << "/qtest/cgi-bin/md5sum.cgi" << md5sum;
+ QTest::newRow("empty-device-ssl")
+ << QString() << true << false
+ << QtNetworkSettings::serverName() << 443 << true << "/qtest/cgi-bin/md5sum.cgi" << md5sum;
+ QTest::newRow("proxy-empty-data-ssl")
+ << QString() << false << true
+ << QtNetworkSettings::serverName() << 443 << true << "/qtest/cgi-bin/md5sum.cgi" << md5sum;
+ md5sum = "b3e32ac459b99d3f59318f3ac31e4bee";
+ QTest::newRow("data-ssl") << "rfc3252.txt" << false << false
+ << QtNetworkSettings::serverName() << 443 << true << "/qtest/cgi-bin/md5sum.cgi"
+ << md5sum;
+ QTest::newRow("device-ssl") << "rfc3252.txt" << true << false
+ << QtNetworkSettings::serverName() << 443 << true << "/qtest/cgi-bin/md5sum.cgi"
+ << md5sum;
+ QTest::newRow("proxy-data-ssl") << "rfc3252.txt" << false << true
+ << QtNetworkSettings::serverName() << 443 << true << "/qtest/cgi-bin/md5sum.cgi"
+ << md5sum;
+#endif
+
+ // the following test won't work. See task 185996
+/*
+ QTest::newRow("proxy-device") << "rfc3252.txt" << true << true
+ << QtNetworkSettings::serverName() << 80 << "/qtest/cgi-bin/md5sum.cgi"
+ << md5sum;
+*/
+}
+
+void tst_QHttp::post()
+{
+ QFETCH(QString, source);
+ QFETCH(bool, useIODevice);
+ QFETCH(bool, useProxy);
+ QFETCH(QString, host);
+ QFETCH(int, port);
+ QFETCH(bool, ssl);
+ QFETCH(QString, path);
+
+ http = newHttp(useProxy);
+#ifndef QT_NO_OPENSSL
+ QObject::connect(http, SIGNAL(sslErrors(const QList<QSslError> &)),
+ http, SLOT(ignoreSslErrors()));
+#endif
+ QCOMPARE(http->currentId(), 0);
+ QCOMPARE((int)http->state(), (int)QHttp::Unconnected);
+ if (useProxy)
+ addRequest(QHttpRequestHeader(), http->setProxy(QtNetworkSettings::serverName(), 3129));
+ addRequest(QHttpRequestHeader(), http->setHost(host, (ssl ? QHttp::ConnectionModeHttps : QHttp::ConnectionModeHttp), port));
+
+ // add the POST request
+ QFile file(SRCDIR + source);
+ QBuffer emptyBuffer;
+ QIODevice *dev;
+ if (!source.isEmpty()) {
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ dev = &file;
+ } else {
+ emptyBuffer.open(QIODevice::ReadOnly);
+ dev = &emptyBuffer;
+ }
+
+ if (useIODevice)
+ postId = http->post(path, dev);
+ else
+ postId = http->post(path, dev->readAll());
+ addRequest(QHttpRequestHeader(), postId);
+
+ // run request
+ connect(http, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
+ QTestEventLoop::instance().enterLoop( 30 );
+
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt res = resultMap.find(postId);
+ QVERIFY(res != resultMap.end());
+ QVERIFY(res.value().success);
+ QCOMPARE(res.value().resp.statusCode(), 200);
+ QTEST(readyRead_ba.trimmed(), "result");
+}
+
+void tst_QHttp::request_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<bool>("useIODevice");
+ QTest::addColumn<bool>("useProxy");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<int>("port");
+ QTest::addColumn<QString>("method");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<QByteArray>("result");
+
+ QFile source(SRCDIR "rfc3252.txt");
+ if (!source.open(QIODevice::ReadOnly))
+ return;
+
+ QByteArray contents = source.readAll();
+ QByteArray md5sum = QCryptographicHash::hash(contents, QCryptographicHash::Md5).toHex() + '\n';
+ QByteArray emptyMd5sum = "d41d8cd98f00b204e9800998ecf8427e\n";
+
+ QTest::newRow("head") << QString() << false << false << QtNetworkSettings::serverName() << 80
+ << "HEAD" << "/qtest/rfc3252.txt"
+ << QByteArray();
+ QTest::newRow("get") << QString() << false << false << QtNetworkSettings::serverName() << 80
+ << "GET" << "/qtest/rfc3252.txt"
+ << contents;
+ QTest::newRow("post-empty-data") << QString() << false << false
+ << QtNetworkSettings::serverName() << 80 << "POST" << "/qtest/cgi-bin/md5sum.cgi"
+ << emptyMd5sum;
+ QTest::newRow("post-empty-device") << QString() << true << false
+ << QtNetworkSettings::serverName() << 80 << "POST" << "/qtest/cgi-bin/md5sum.cgi"
+ << emptyMd5sum;
+ QTest::newRow("post-data") << "rfc3252.txt" << false << false
+ << QtNetworkSettings::serverName() << 80 << "POST" << "/qtest/cgi-bin/md5sum.cgi"
+ << md5sum;
+ QTest::newRow("post-device") << "rfc3252.txt" << true << false
+ << QtNetworkSettings::serverName() << 80 << "POST" << "/qtest/cgi-bin/md5sum.cgi"
+ << md5sum;
+
+ QTest::newRow("proxy-head") << QString() << false << true << QtNetworkSettings::serverName() << 80
+ << "HEAD" << "/qtest/rfc3252.txt"
+ << QByteArray();
+ QTest::newRow("proxy-get") << QString() << false << true << QtNetworkSettings::serverName() << 80
+ << "GET" << "/qtest/rfc3252.txt"
+ << contents;
+ QTest::newRow("proxy-post-empty-data") << QString() << false << true
+ << QtNetworkSettings::serverName() << 80 << "POST" << "/qtest/cgi-bin/md5sum.cgi"
+ << emptyMd5sum;
+ QTest::newRow("proxy-post-data") << "rfc3252.txt" << false << true
+ << QtNetworkSettings::serverName() << 80 << "POST" << "/qtest/cgi-bin/md5sum.cgi"
+ << md5sum;
+ // the following test won't work. See task 185996
+/*
+ QTest::newRow("proxy-post-device") << "rfc3252.txt" << true << true
+ << QtNetworkSettings::serverName() << 80 << "POST" << "/qtest/cgi-bin/md5sum.cgi"
+ << md5sum;
+*/
+}
+
+void tst_QHttp::request()
+{
+ QFETCH(QString, source);
+ QFETCH(bool, useIODevice);
+ QFETCH(bool, useProxy);
+ QFETCH(QString, host);
+ QFETCH(int, port);
+ QFETCH(QString, method);
+ QFETCH(QString, path);
+
+ http = newHttp(useProxy);
+ QCOMPARE(http->currentId(), 0);
+ QCOMPARE((int)http->state(), (int)QHttp::Unconnected);
+ if (useProxy)
+ addRequest(QHttpRequestHeader(), http->setProxy(QtNetworkSettings::serverName(), 3129));
+ addRequest(QHttpRequestHeader(), http->setHost(host, port));
+
+ QFile file(SRCDIR + source);
+ QBuffer emptyBuffer;
+ QIODevice *dev;
+ if (!source.isEmpty()) {
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ dev = &file;
+ } else {
+ emptyBuffer.open(QIODevice::ReadOnly);
+ dev = &emptyBuffer;
+ }
+
+ // prepare the request
+ QHttpRequestHeader request;
+ request.setRequest(method, path, 1,1);
+ request.addValue("Host", host);
+ int *theId;
+
+ if (method == "POST")
+ theId = &postId;
+ else if (method == "GET")
+ theId = &getId;
+ else if (method == "HEAD")
+ theId = &headId;
+ else
+ QFAIL("You're lazy! Please implement your test!");
+
+ // now send the request
+ if (useIODevice)
+ *theId = http->request(request, dev);
+ else
+ *theId = http->request(request, dev->readAll());
+ addRequest(QHttpRequestHeader(), *theId);
+
+ // run request
+ connect(http, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
+ QTestEventLoop::instance().enterLoop( 30 );
+
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt res = resultMap.find(*theId);
+ QVERIFY(res != resultMap.end());
+ QVERIFY(res.value().success);
+ QCOMPARE(res.value().resp.statusCode(), 200);
+ QTEST(readyRead_ba, "result");
+}
+
+void tst_QHttp::authorization_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("pass");
+ QTest::addColumn<int>("result");
+
+ QTest::newRow("correct password") << QtNetworkSettings::serverName()
+ << QString::fromLatin1("/qtest/rfcs-auth/index.html")
+ << QString::fromLatin1("httptest")
+ << QString::fromLatin1("httptest")
+ << 200;
+
+ QTest::newRow("no password") << QtNetworkSettings::serverName()
+ << QString::fromLatin1("/qtest/rfcs-auth/index.html")
+ << QString::fromLatin1("")
+ << QString::fromLatin1("")
+ << 401;
+
+ QTest::newRow("wrong password") << QtNetworkSettings::serverName()
+ << QString::fromLatin1("/qtest/rfcs-auth/index.html")
+ << QString::fromLatin1("maliciu0s")
+ << QString::fromLatin1("h4X0r")
+ << 401;
+}
+
+void tst_QHttp::authorization()
+{
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(QString, user);
+ QFETCH(QString, pass);
+ QFETCH(int, result);
+
+ QEventLoop loop;
+
+ QHttp http;
+ connect(&http, SIGNAL(done(bool)), &loop, SLOT(quit()));
+
+ if (!user.isEmpty())
+ http.setUser(user, pass);
+ http.setHost(host);
+ int id = http.get(path);
+ Q_UNUSED(id);
+
+ QTimer::singleShot(5000, &loop, SLOT(quit()));
+ loop.exec();
+
+ QCOMPARE(http.lastResponse().statusCode(), result);
+}
+
+void tst_QHttp::proxy_data()
+{
+ QTest::addColumn<QString>("proxyhost");
+ QTest::addColumn<int>("port");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<QString>("proxyuser");
+ QTest::addColumn<QString>("proxypass");
+
+ QTest::newRow("qt-test-server") << QtNetworkSettings::serverName() << 3128
+ << QString::fromLatin1("qt.nokia.com") << QString::fromLatin1("/")
+ << QString::fromLatin1("") << QString::fromLatin1("");
+ QTest::newRow("qt-test-server pct") << QtNetworkSettings::serverName() << 3128
+ << QString::fromLatin1("qt.nokia.com") << QString::fromLatin1("/%64eveloper")
+ << QString::fromLatin1("") << QString::fromLatin1("");
+ QTest::newRow("qt-test-server-basic") << QtNetworkSettings::serverName() << 3129
+ << QString::fromLatin1("qt.nokia.com") << QString::fromLatin1("/")
+ << QString::fromLatin1("qsockstest") << QString::fromLatin1("password");
+
+#if 0
+ // NTLM requires sending the same request three times for it to work
+ // the tst_QHttp class is too strict to handle the byte counts sent by dataSendProgress
+ // So don't run this test:
+ QTest::newRow("qt-test-server-ntlm") << QtNetworkSettings::serverName() << 3130
+ << QString::fromLatin1("qt.nokia.com") << QString::fromLatin1("/")
+ << QString::fromLatin1("qsockstest") << QString::fromLatin1("password");
+#endif
+}
+
+void tst_QHttp::proxy()
+{
+ QFETCH(QString, proxyhost);
+ QFETCH(int, port);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(QString, proxyuser);
+ QFETCH(QString, proxypass);
+
+ http = newHttp(!proxyuser.isEmpty());
+
+ QCOMPARE(http->currentId(), 0);
+ QCOMPARE((int)http->state(), (int)QHttp::Unconnected);
+
+ addRequest(QHttpRequestHeader(), http->setProxy(proxyhost, port, proxyuser, proxypass));
+ addRequest(QHttpRequestHeader(), http->setHost(host));
+ getId = http->get(path);
+ addRequest(QHttpRequestHeader(), getId);
+
+ QTestEventLoop::instance().enterLoop(30);
+ if (QTestEventLoop::instance().timeout())
+ QFAIL("Network operation timed out");
+
+ ResMapIt res = resultMap.find(getId);
+ QVERIFY(res != resultMap.end());
+ QVERIFY(res.value().success);
+ QCOMPARE(res.value().resp.statusCode(), 200);
+}
+
+void tst_QHttp::proxy2()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ readyRead_ba.clear();
+
+ QHttp http;
+ http.setProxy(QtNetworkSettings::serverName(), 3128);
+ http.setHost(QtNetworkSettings::serverName());
+ http.get("/index.html");
+ http.get("/index.html");
+
+ connect(&http, SIGNAL(requestFinished(int, bool)),
+ this, SLOT(proxy2_slot()));
+ QTestEventLoop::instance().enterLoop(30);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ QCOMPARE(readyRead_ba.count("Welcome to qt-test-server"), 2);
+
+ readyRead_ba.clear();
+}
+
+void tst_QHttp::proxy2_slot()
+{
+ QHttp *http = static_cast<QHttp *>(sender());
+ readyRead_ba.append(http->readAll());
+ if (!http->hasPendingRequests())
+ QTestEventLoop::instance().exitLoop();
+}
+
+void tst_QHttp::proxy3()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ readyRead_ba.clear();
+
+ QTcpSocket socket;
+ socket.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128));
+
+ QHttp http;
+ http.setSocket(&socket);
+ http.setHost(QtNetworkSettings::serverName());
+ http.get("/index.html");
+ http.get("/index.html");
+
+ connect(&http, SIGNAL(requestFinished(int, bool)),
+ this, SLOT(proxy2_slot()));
+ QTestEventLoop::instance().enterLoop(30);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ QCOMPARE(readyRead_ba.count("Welcome to qt-test-server"), 2);
+
+ readyRead_ba.clear();
+}
+
+// test QHttp::currentId() and QHttp::currentRequest()
+#define CURRENTREQUEST_TEST \
+ { \
+ ResMapIt res = resultMap.find( http->currentId() ); \
+ QVERIFY( res != resultMap.end() ); \
+ if ( http->currentId() == getId ) { \
+ QCOMPARE( http->currentRequest().method(), QString("GET") ); \
+ } else if ( http->currentId() == headId ) { \
+ QCOMPARE( http->currentRequest().method(), QString("HEAD") ); \
+ } else if ( http->currentId() == postId ) { \
+ QCOMPARE( http->currentRequest().method(), QString("POST") ); \
+ } else { \
+ QVERIFY( headerAreEqual( http->currentRequest(), res.value().req ) ); \
+ } \
+ }
+
+void tst_QHttp::requestStarted( int id )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d:requestStarted( %d )", http->currentId(), id );
+#endif
+ // make sure that the requestStarted and requestFinished are nested correctly
+ QVERIFY( current_id == 0 );
+ current_id = id;
+
+ QVERIFY( !ids.isEmpty() );
+ QVERIFY( ids.first() == id );
+ if ( ids.count() > 1 ) {
+ QVERIFY( http->hasPendingRequests() );
+ } else {
+ QVERIFY( !http->hasPendingRequests() );
+ }
+
+ QVERIFY( http->currentId() == id );
+ QVERIFY( cur_state == http->state() );
+
+
+
+
+ CURRENTREQUEST_TEST;
+
+ QVERIFY( http->error() == QHttp::NoError );
+}
+
+void tst_QHttp::requestFinished( int id, bool error )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d:requestFinished( %d, %d ) -- errorString: '%s'",
+ http->currentId(), id, (int)error, http->errorString().toAscii().data() );
+#endif
+ // make sure that the requestStarted and requestFinished are nested correctly
+ QVERIFY( current_id == id );
+ current_id = 0;
+
+ QVERIFY( !ids.isEmpty() );
+ QVERIFY( ids.first() == id );
+ if ( ids.count() > 1 ) {
+ QVERIFY( http->hasPendingRequests() );
+ } else {
+ QVERIFY( !http->hasPendingRequests() );
+ }
+
+ if ( error ) {
+ QVERIFY( http->error() != QHttp::NoError );
+ ids.clear();
+ } else {
+ QVERIFY( http->error() == QHttp::NoError );
+ ids.pop_front();
+ }
+
+ QVERIFY( http->currentId() == id );
+ QVERIFY( cur_state == http->state() );
+ CURRENTREQUEST_TEST;
+
+ ResMapIt res = resultMap.find( http->currentId() );
+ QVERIFY( res != resultMap.end() );
+ QVERIFY( res.value().success == -1 );
+ if ( error )
+ res.value().success = 0;
+ else
+ res.value().success = 1;
+}
+
+void tst_QHttp::done( bool error )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d:done( %d )", http->currentId(), (int)error );
+#endif
+ QVERIFY( http->currentId() == 0 );
+ QVERIFY( current_id == 0 );
+ QVERIFY( ids.isEmpty() );
+ QVERIFY( cur_state == http->state() );
+ QVERIFY( !http->hasPendingRequests() );
+
+ QVERIFY( done_success == -1 );
+ if ( error ) {
+ QVERIFY( http->error() != QHttp::NoError );
+ done_success = 0;
+ } else {
+ QVERIFY( http->error() == QHttp::NoError );
+ done_success = 1;
+ }
+ QTestEventLoop::instance().exitLoop();
+}
+
+void tst_QHttp::stateChanged( int state )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d: stateChanged( %d )", http->currentId(), state );
+#endif
+ QCOMPARE( http->currentId(), current_id );
+ if ( ids.count() > 0 )
+ CURRENTREQUEST_TEST;
+
+ QVERIFY( state != cur_state );
+ QVERIFY( state == http->state() );
+ if ( state != QHttp::Unconnected && !connectionWithAuth ) {
+ // make sure that the states are always emitted in the right order (for
+ // this, we assume an ordering on the enum values, which they have at
+ // the moment)
+ // connections with authentication will possibly reconnect, so ignore them
+ QVERIFY( cur_state < state );
+ }
+ cur_state = state;
+
+ if (state == QHttp::Connecting) {
+ bytesTotalSend = bytesTotal_init;
+ bytesDoneSend = bytesDone_init;
+ bytesTotalRead = bytesTotal_init;
+ bytesDoneRead = bytesDone_init;
+ }
+}
+
+void tst_QHttp::responseHeaderReceived( const QHttpResponseHeader &header )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d: responseHeaderReceived(\n---{\n%s}---)", http->currentId(), header.toString().toAscii().data() );
+#endif
+ QCOMPARE( http->currentId(), current_id );
+ if ( ids.count() > 1 ) {
+ QVERIFY( http->hasPendingRequests() );
+ } else {
+ QVERIFY( !http->hasPendingRequests() );
+ }
+ CURRENTREQUEST_TEST;
+
+ resultMap[ http->currentId() ].resp = header;
+}
+
+void tst_QHttp::readyRead( const QHttpResponseHeader & )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d: readyRead()", http->currentId() );
+#endif
+ QCOMPARE( http->currentId(), current_id );
+ if ( ids.count() > 1 ) {
+ QVERIFY( http->hasPendingRequests() );
+ } else {
+ QVERIFY( !http->hasPendingRequests() );
+ }
+ QVERIFY( cur_state == http->state() );
+ CURRENTREQUEST_TEST;
+
+ if ( QTest::currentTestFunction() != QLatin1String("bytesAvailable") ) {
+ int oldSize = readyRead_ba.size();
+ quint64 bytesAvail = http->bytesAvailable();
+ QByteArray ba = http->readAll();
+ QVERIFY( (quint64) ba.size() == bytesAvail );
+ readyRead_ba.resize( oldSize + ba.size() );
+ memcpy( readyRead_ba.data()+oldSize, ba.data(), ba.size() );
+
+ if ( bytesTotalRead > 0 ) {
+ QVERIFY( (int)readyRead_ba.size() <= bytesTotalRead );
+ }
+ QVERIFY( (int)readyRead_ba.size() == bytesDoneRead );
+ }
+}
+
+void tst_QHttp::dataSendProgress( int done, int total )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d: dataSendProgress( %d, %d )", http->currentId(), done, total );
+#endif
+ QCOMPARE( http->currentId(), current_id );
+ if ( ids.count() > 1 ) {
+ QVERIFY( http->hasPendingRequests() );
+ } else {
+ QVERIFY( !http->hasPendingRequests() );
+ }
+ QVERIFY( cur_state == http->state() );
+ CURRENTREQUEST_TEST;
+
+ if ( bytesTotalSend == bytesTotal_init ) {
+ bytesTotalSend = total;
+ } else {
+ QCOMPARE( bytesTotalSend, total );
+ }
+
+ QVERIFY( bytesTotalSend != bytesTotal_init );
+ QVERIFY( bytesDoneSend <= done );
+ bytesDoneSend = done;
+ if ( bytesTotalSend > 0 ) {
+ QVERIFY( bytesDoneSend <= bytesTotalSend );
+ }
+
+ if ( QTest::currentTestFunction() == QLatin1String("abort") ) {
+ // ### it would be nice if we could specify in our testdata when to do
+ // the abort
+ if ( done >= total/100000 ) {
+ if ( ids.count() != 1 ) {
+ // do abort only once
+ int tmpId = ids.first();
+ ids.clear();
+ ids << tmpId;
+ http->abort();
+ }
+ }
+ }
+}
+
+void tst_QHttp::dataReadProgress( int done, int total )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d: dataReadProgress( %d, %d )", http->currentId(), done, total );
+#endif
+ QCOMPARE( http->currentId(), current_id );
+ if ( ids.count() > 1 ) {
+ QVERIFY( http->hasPendingRequests() );
+ } else {
+ QVERIFY( !http->hasPendingRequests() );
+ }
+ QVERIFY( cur_state == http->state() );
+ CURRENTREQUEST_TEST;
+
+ if ( bytesTotalRead == bytesTotal_init )
+ bytesTotalRead = total;
+ else {
+ QVERIFY( bytesTotalRead == total );
+ }
+
+ QVERIFY( bytesTotalRead != bytesTotal_init );
+ QVERIFY( bytesDoneRead <= done );
+ bytesDoneRead = done;
+ if ( bytesTotalRead > 0 ) {
+ QVERIFY( bytesDoneRead <= bytesTotalRead );
+ }
+
+ if ( QTest::currentTestFunction() == QLatin1String("abort") ) {
+ // ### it would be nice if we could specify in our testdata when to do
+ // the abort
+ if ( done >= total/100000 ) {
+ if ( ids.count() != 1 ) {
+ // do abort only once
+ int tmpId = ids.first();
+ ids.clear();
+ ids << tmpId;
+ http->abort();
+ }
+ }
+ }
+}
+
+
+QHttp *tst_QHttp::newHttp(bool withAuth)
+{
+ QHttp *nHttp = new QHttp( 0 );
+ connect( nHttp, SIGNAL(requestStarted(int)),
+ SLOT(requestStarted(int)) );
+ connect( nHttp, SIGNAL(requestFinished(int,bool)),
+ SLOT(requestFinished(int,bool)) );
+ connect( nHttp, SIGNAL(done(bool)),
+ SLOT(done(bool)) );
+ connect( nHttp, SIGNAL(stateChanged(int)),
+ SLOT(stateChanged(int)) );
+ connect( nHttp, SIGNAL(responseHeaderReceived(const QHttpResponseHeader&)),
+ SLOT(responseHeaderReceived(const QHttpResponseHeader&)) );
+ connect( nHttp, SIGNAL(readyRead(const QHttpResponseHeader&)),
+ SLOT(readyRead(const QHttpResponseHeader&)) );
+ connect( nHttp, SIGNAL(dataSendProgress(int,int)),
+ SLOT(dataSendProgress(int,int)) );
+ connect( nHttp, SIGNAL(dataReadProgress(int,int)),
+ SLOT(dataReadProgress(int,int)) );
+
+ connectionWithAuth = withAuth;
+ return nHttp;
+}
+
+void tst_QHttp::addRequest( QHttpRequestHeader header, int id )
+{
+ ids << id;
+ RequestResult res;
+ res.req = header;
+ res.success = -1;
+ resultMap[ id ] = res;
+}
+
+bool tst_QHttp::headerAreEqual( const QHttpHeader &h1, const QHttpHeader &h2 )
+{
+ if ( !h1.isValid() )
+ return !h2.isValid();
+ if ( !h2.isValid() )
+ return !h1.isValid();
+
+ return h1.toString() == h2.toString();
+}
+
+
+void tst_QHttp::reconnect()
+{
+ reconnect_state_connect_count = 0;
+
+ QHttp http;
+
+ QObject::connect(&http, SIGNAL(stateChanged(int)), this, SLOT(reconnect_state(int)));
+ http.setHost("trolltech.com", 80);
+ http.get("/company/index.html");
+ http.setHost("trolltech.com", 8080);
+ http.get("/company/index.html");
+
+ QTestEventLoop::instance().enterLoop(60);
+ if (QTestEventLoop::instance().timeout())
+ QFAIL("Network operation timed out");
+
+ QCOMPARE(reconnect_state_connect_count, 1);
+
+ QTestEventLoop::instance().enterLoop(60);
+ if (QTestEventLoop::instance().timeout())
+ QFAIL("Network operation timed out");
+
+ QCOMPARE(reconnect_state_connect_count, 2);
+}
+
+void tst_QHttp::reconnect_state(int state)
+{
+ if (state == QHttp::Connecting) {
+ ++reconnect_state_connect_count;
+ QTestEventLoop::instance().exitLoop();
+ }
+}
+
+void tst_QHttp::setSocket()
+{
+ QHttp *http = new QHttp;
+ QPointer<QTcpSocket> replacementSocket = new QTcpSocket;
+ http->setSocket(replacementSocket);
+ QCoreApplication::processEvents();
+ delete http;
+ QVERIFY(replacementSocket);
+ delete replacementSocket;
+}
+
+class Server : public QTcpServer
+{
+ Q_OBJECT
+public:
+ Server()
+ {
+ connect(this, SIGNAL(newConnection()),
+ this, SLOT(serveConnection()));
+ }
+
+private slots:
+ void serveConnection()
+ {
+ QTcpSocket *socket = nextPendingConnection();
+ socket->write("HTTP/1.1 404 Not found\r\n"
+ "content-length: 4\r\n\r\nabcd");
+ socket->disconnectFromHost();
+ };
+};
+
+void tst_QHttp::unexpectedRemoteClose()
+{
+ QFETCH_GLOBAL(int, proxyType);
+ if (proxyType == QNetworkProxy::Socks5Proxy) {
+ // This test doesn't make sense for SOCKS5
+ return;
+ }
+
+ Server server;
+ server.listen();
+ QCoreApplication::instance()->processEvents();
+
+ QEventLoop loop;
+ QTimer::singleShot(3000, &loop, SLOT(quit()));
+
+ QHttp http;
+ QObject::connect(&http, SIGNAL(done(bool)), &loop, SLOT(quit()));
+ QSignalSpy finishedSpy(&http, SIGNAL(requestFinished(int, bool)));
+ QSignalSpy doneSpy(&http, SIGNAL(done(bool)));
+
+ http.setHost("localhost", server.serverPort());
+ http.get("/");
+ http.get("/");
+ http.get("/");
+
+ loop.exec();
+
+ QCOMPARE(finishedSpy.count(), 4);
+ QVERIFY(!finishedSpy.at(1).at(1).toBool());
+ QVERIFY(!finishedSpy.at(2).at(1).toBool());
+ QVERIFY(!finishedSpy.at(3).at(1).toBool());
+ QCOMPARE(doneSpy.count(), 1);
+ QVERIFY(!doneSpy.at(0).at(0).toBool());
+}
+
+void tst_QHttp::pctEncodedPath()
+{
+ QHttpRequestHeader header;
+ header.setRequest("GET", "/index.asp/a=%20&b=%20&c=%20");
+ QCOMPARE(header.toString(), QString("GET /index.asp/a=%20&b=%20&c=%20 HTTP/1.1\r\n\r\n"));
+}
+
+void tst_QHttp::caseInsensitiveKeys()
+{
+ QHttpResponseHeader header("HTTP/1.1 200 OK\r\nContent-Length: 213\r\nX-Been-There: True\r\nLocation: http://www.TrollTech.com/\r\n\r\n");
+ QVERIFY(header.hasKey("Content-Length"));
+ QVERIFY(header.hasKey("X-Been-There"));
+ QVERIFY(header.hasKey("Location"));
+ QVERIFY(header.hasKey("content-length"));
+ QVERIFY(header.hasKey("x-been-there"));
+ QVERIFY(header.hasKey("location"));
+ QCOMPARE(header.value("Content-Length"), QString("213"));
+ QCOMPARE(header.value("X-Been-There"), QString("True"));
+ QCOMPARE(header.value("Location"), QString("http://www.TrollTech.com/"));
+ QCOMPARE(header.value("content-length"), QString("213"));
+ QCOMPARE(header.value("x-been-there"), QString("True"));
+ QCOMPARE(header.value("location"), QString("http://www.TrollTech.com/"));
+ QCOMPARE(header.allValues("location"), QStringList("http://www.TrollTech.com/"));
+
+ header.addValue("Content-Length", "213");
+ header.addValue("Content-Length", "214");
+ header.addValue("Content-Length", "215");
+ qDebug() << header.toString();
+}
+
+void tst_QHttp::proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth)
+{
+ proxyAuthCalled = true;
+ auth->setUser("qsockstest");
+ auth->setPassword("password");
+}
+
+void tst_QHttp::postAuthNtlm()
+{
+ QSKIP("NTLM not working", SkipAll);
+
+ QHostInfo info = QHostInfo::fromName(QHostInfo::localHostName());
+ QByteArray postData("Hello World");
+ QHttp http;
+
+ http.setHost(QtNetworkSettings::serverName());
+ http.setProxy(QtNetworkSettings::serverName(), 3130);
+ http.post("/", postData);
+
+ proxyAuthCalled = false;
+ connect(&http, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
+
+ QObject::connect(&http, SIGNAL(done(bool)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(3);
+ QObject::disconnect(&http, SIGNAL(done(bool)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ QVERIFY(proxyAuthCalled);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+};
+
+void tst_QHttp::proxyAndSsl()
+{
+#ifdef QT_NO_OPENSSL
+ QSKIP("No OpenSSL support in this platform", SkipAll);
+#else
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ QHttp http;
+
+ http.setHost(QtNetworkSettings::serverName(), QHttp::ConnectionModeHttps);
+ http.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3129));
+ http.get("/");
+
+ proxyAuthCalled = false;
+ connect(&http, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
+ connect(&http, SIGNAL(sslErrors(QList<QSslError>)),
+ &http, SLOT(ignoreSslErrors()));
+
+ QObject::connect(&http, SIGNAL(done(bool)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(3);
+ QObject::disconnect(&http, SIGNAL(done(bool)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY(proxyAuthCalled);
+
+ QHttpResponseHeader header = http.lastResponse();
+ QVERIFY(header.isValid());
+ QVERIFY(header.statusCode() < 400); // Should be 200, but as long as it's not an error, we're happy
+#endif
+}
+
+void tst_QHttp::cachingProxyAndSsl()
+{
+#ifdef QT_NO_OPENSSL
+ QSKIP("No OpenSSL support in this platform", SkipAll);
+#else
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ QHttp http;
+
+ http.setHost(QtNetworkSettings::serverName(), QHttp::ConnectionModeHttps);
+ http.setProxy(QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129));
+ http.get("/");
+
+ proxyAuthCalled = false;
+ connect(&http, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
+
+ QObject::connect(&http, SIGNAL(done(bool)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(3);
+ QObject::disconnect(&http, SIGNAL(done(bool)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY(!proxyAuthCalled); // NOT called! QHttp should get a socket error
+ QVERIFY(http.state() != QHttp::Connected);
+
+ QHttpResponseHeader header = http.lastResponse();
+ QVERIFY(!header.isValid());
+#endif
+}
+
+void tst_QHttp::emptyBodyInReply()
+{
+ // Note: if this test starts failing, please verify the date on the file
+ // returned by Apache on http://netiks.troll.no/
+ // It is right now hard-coded to the date below
+ QHttp http;
+ http.setHost(QtNetworkSettings::serverName());
+
+ QHttpRequestHeader headers("GET", "/");
+ headers.addValue("If-Modified-Since", "Sun, 16 Nov 2008 12:29:51 GMT");
+ headers.addValue("Host", QtNetworkSettings::serverName());
+ http.request(headers);
+
+ QObject::connect(&http, SIGNAL(done(bool)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(10);
+ QObject::disconnect(&http, SIGNAL(done(bool)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ // check the reply
+ if (http.lastResponse().statusCode() != 304) {
+ qWarning() << http.lastResponse().statusCode() << qPrintable(http.lastResponse().reasonPhrase());
+ qWarning() << "Last-Modified:" << qPrintable(http.lastResponse().value("last-modified"));
+ QFAIL("Server replied with the wrong status code; see warning output");
+ }
+}
+
+void tst_QHttp::abortSender()
+{
+ QHttp *http = qobject_cast<QHttp *>(sender());
+ if (http)
+ http->abort();
+}
+
+void tst_QHttp::abortInReadyRead()
+{
+ QHttp http;
+ http.setHost(QtNetworkSettings::serverName());
+ http.get("/qtest/bigfile");
+
+ qRegisterMetaType<QHttpResponseHeader>();
+ QSignalSpy spy(&http, SIGNAL(readyRead(QHttpResponseHeader)));
+
+ QObject::connect(&http, SIGNAL(readyRead(QHttpResponseHeader)), this, SLOT(abortSender()));
+ QObject::connect(&http, SIGNAL(done(bool)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(10);
+ QObject::disconnect(&http, SIGNAL(done(bool)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ QVERIFY2(!QTestEventLoop::instance().timeout(), "Network timeout");
+ QVERIFY(http.state() != QHttp::Connected);
+
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QHttp::abortInResponseHeaderReceived()
+{
+ QHttp http;
+ http.setHost(QtNetworkSettings::serverName());
+ http.get("/qtest/bigfile");
+
+ qRegisterMetaType<QHttpResponseHeader>();
+ QSignalSpy spy(&http, SIGNAL(readyRead(QHttpResponseHeader)));
+
+ QObject::connect(&http, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(abortSender()));
+ QObject::connect(&http, SIGNAL(done(bool)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(10);
+ QObject::disconnect(&http, SIGNAL(done(bool)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ QVERIFY2(!QTestEventLoop::instance().timeout(), "Network timeout");
+ QVERIFY(http.state() != QHttp::Connected);
+
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QHttp::connectionClose()
+{
+ // This was added in response to bug 176822
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ QHttp http;
+ ClosingServer server;
+ http.setHost("localhost", QHttp::ConnectionModeHttps, server.serverPort());
+ http.get("/login/gateway/processLogin");
+
+ // another possibility:
+ //http.setHost("nexus.passport.com", QHttp::ConnectionModeHttps, 443);
+ //http.get("/rdr/pprdr.asp");
+
+ QObject::connect(&http, SIGNAL(done(bool)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(900);
+ QObject::disconnect(&http, SIGNAL(done(bool)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ QVERIFY(!QTestEventLoop::instance().timeout());
+}
+
+void tst_QHttp::nestedEventLoop_slot(int id)
+{
+ if (!ids.contains(id))
+ return;
+ QEventLoop subloop;
+
+ // 16 seconds: fluke times out in 15 seconds, which triggers a QTcpSocket error
+ QTimer::singleShot(16000, &subloop, SLOT(quit()));
+ subloop.exec();
+
+ QTestEventLoop::instance().exitLoop();
+}
+
+void tst_QHttp::nestedEventLoop()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ http = new QHttp;
+ http->setHost(QtNetworkSettings::serverName());
+ int getId = http->get("/");
+
+ ids.clear();
+ ids << getId;
+
+ QSignalSpy spy(http, SIGNAL(requestStarted(int)));
+ QSignalSpy spy2(http, SIGNAL(done(bool)));
+
+ connect(http, SIGNAL(requestFinished(int,bool)), SLOT(nestedEventLoop_slot(int)));
+ QTestEventLoop::instance().enterLoop(20);
+
+ QVERIFY2(!QTestEventLoop::instance().timeout(), "Network timeout");
+
+ // Find out how many signals with the first argument equalling our id were found
+ int spyCount = 0;
+ for (int i = 0; i < spy.count(); ++i)
+ if (spy.at(i).at(0).toInt() == getId)
+ ++spyCount;
+
+ // each signal spied should have been emitted only once
+ QCOMPARE(spyCount, 1);
+ QCOMPARE(spy2.count(), 1);
+}
+
+QTEST_MAIN(tst_QHttp)
+#include "tst_qhttp.moc"
diff --git a/tests/auto/network/access/qhttp/webserver/cgi-bin/retrieve_testfile.cgi b/tests/auto/network/access/qhttp/webserver/cgi-bin/retrieve_testfile.cgi
new file mode 100755
index 0000000000..7896c505ca
--- /dev/null
+++ b/tests/auto/network/access/qhttp/webserver/cgi-bin/retrieve_testfile.cgi
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+echo "Content-type: text/plain";
+echo
+cat testfile
+echo "no file retrieved" > testfile
diff --git a/tests/auto/network/access/qhttp/webserver/cgi-bin/rfc.cgi b/tests/auto/network/access/qhttp/webserver/cgi-bin/rfc.cgi
new file mode 100755
index 0000000000..c68688ea31
--- /dev/null
+++ b/tests/auto/network/access/qhttp/webserver/cgi-bin/rfc.cgi
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+echo "Content-type: text/plain";
+echo
+cat ../rfc3252
diff --git a/tests/auto/network/access/qhttp/webserver/cgi-bin/store_testfile.cgi b/tests/auto/network/access/qhttp/webserver/cgi-bin/store_testfile.cgi
new file mode 100755
index 0000000000..e950f2af04
--- /dev/null
+++ b/tests/auto/network/access/qhttp/webserver/cgi-bin/store_testfile.cgi
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+echo "Content-type: text/plain";
+echo
+echo "file stored under 'testfile'"
+cat > testfile
diff --git a/tests/auto/network/access/qhttp/webserver/index.html b/tests/auto/network/access/qhttp/webserver/index.html
new file mode 100644
index 0000000000..b80c61bf0a
--- /dev/null
+++ b/tests/auto/network/access/qhttp/webserver/index.html
@@ -0,0 +1,899 @@
+
+
+
+
+
+
+Network Working Group H. Kennedy
+Request for Comments: 3252 Mimezine
+Category: Informational 1 April 2002
+
+
+ Binary Lexical Octet Ad-hoc Transport
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ This document defines a reformulation of IP and two transport layer
+ protocols (TCP and UDP) as XML applications.
+
+1. Introduction
+
+1.1. Overview
+
+ This document describes the Binary Lexical Octet Ad-hoc Transport
+ (BLOAT): a reformulation of a widely-deployed network-layer protocol
+ (IP [RFC791]), and two associated transport layer protocols (TCP
+ [RFC793] and UDP [RFC768]) as XML [XML] applications. It also
+ describes methods for transporting BLOAT over Ethernet and IEEE 802
+ networks as well as encapsulating BLOAT in IP for gatewaying BLOAT
+ across the public Internet.
+
+1.2. Motivation
+
+ The wild popularity of XML as a basis for application-level protocols
+ such as the Blocks Extensible Exchange Protocol [RFC3080], the Simple
+ Object Access Protocol [SOAP], and Jabber [JABBER] prompted
+ investigation into the possibility of extending the use of XML in the
+ protocol stack. Using XML at both the transport and network layer in
+ addition to the application layer would provide for an amazing amount
+ of power and flexibility while removing dependencies on proprietary
+ and hard-to-understand binary protocols. This protocol unification
+ would also allow applications to use a single XML parser for all
+ aspects of their operation, eliminating developer time spent figuring
+ out the intricacies of each new protocol, and moving the hard work of
+
+
+
+
+Kennedy Informational [Page 1]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ parsing to the XML toolset. The use of XML also mitigates concerns
+ over "network vs. host" byte ordering which is at the root of many
+ network application bugs.
+
+1.3. Relation to Existing Protocols
+
+ The reformulations specified in this RFC follow as closely as
+ possible the spirit of the RFCs on which they are based, and so MAY
+ contain elements or attributes that would not be needed in a pure
+ reworking (e.g. length attributes, which are implicit in XML.)
+
+ The layering of network and transport protocols are maintained in
+ this RFC despite the optimizations that could be made if the line
+ were somewhat blurred (i.e. merging TCP and IP into a single, larger
+ element in the DTD) in order to foster future use of this protocol as
+ a basis for reformulating other protocols (such as ICMP.)
+
+ Other than the encoding, the behavioral aspects of each of the
+ existing protocols remain unchanged. Routing, address spaces, TCP
+ congestion control, etc. behave as specified in the extant standards.
+ Adapting to new standards and experimental algorithm heuristics for
+ improving performance will become much easier once the move to BLOAT
+ has been completed.
+
+1.4. Requirement Levels
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in BCP 14, RFC 2119
+ [RFC2119].
+
+2. IPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC.
+ IPoXML is the root protocol REQUIRED for effective use of TCPoXML
+ (section 3.) and higher-level application protocols.
+
+ The DTD for this document type can be found in section 7.1.
+
+ The routing of IPoXML can be easily implemented on hosts with an XML
+ parser, as the regular structure lends itself handily to parsing and
+ validation of the document/datagram and then processing the
+ destination address, TTL, and checksum before sending it on to its
+ next-hop.
+
+ The reformulation of IPv4 was chosen over IPv6 [RFC2460] due to the
+ wider deployment of IPv4 and the fact that implementing IPv6 as XML
+ would have exceeded the 1500 byte Ethernet MTU.
+
+
+
+Kennedy Informational [Page 2]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ All BLOAT implementations MUST use - and specify - the UTF-8 encoding
+ of RFC 2279 [RFC2279]. All BLOAT document/datagrams MUST be well-
+ formed and include the XMLDecl.
+
+2.1. IP Description
+
+ A number of items have changed (for the better) from the original IP
+ specification. Bit-masks, where present have been converted into
+ human-readable values. IP addresses are listed in their dotted-
+ decimal notation [RFC1123]. Length and checksum values are present
+ as decimal integers.
+
+ To calculate the length and checksum fields of the IP element, a
+ canonicalized form of the element MUST be used. The canonical form
+ SHALL have no whitespace (including newline characters) between
+ elements and only one space character between attributes. There
+ SHALL NOT be a space following the last attribute in an element.
+
+ An iterative method SHOULD be used to calculate checksums, as the
+ length field will vary based on the size of the checksum.
+
+ The payload element bears special attention. Due to the character
+ set restrictions of XML, the payload of IP datagrams (which MAY
+ contain arbitrary data) MUST be encoded for transport. This RFC
+ REQUIRES the contents of the payload to be encoded in the base-64
+ encoding of RFC 2045 [RFC2045], but removes the requirement that the
+ encoded output MUST be wrapped on 76-character lines.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 3]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+2.2. Example Datagram
+
+ The following is an example IPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ <ip>
+ <header length="474">
+ <version value="4"/>
+ <tos precedence="Routine" delay="Normal" throughput="Normal"
+ relibility="Normal" reserved="0"/>
+ <total.length value="461"/>
+ <id value="1"/>
+ <flags reserved="0" df="dont" mf="last"/>
+ <offset value="0"/>
+ <ttl value="255"/>
+ <protocol value="6"/>
+ <checksum value="8707"/>
+ <source address="10.0.0.22"/>
+ <destination address="10.0.0.1"/>
+ <options>
+ <end copied="0" class="0" number="0"/>
+ </options>
+ <padding pad="0"/>
+ </header>
+ <payload>
+ </payload>
+ </ip>
+
+3. TCPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.2.
+
+3.1. TCP Description
+
+ A number of items have changed from the original TCP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+ To calculate the length and checksum fields of the TCP element, a
+ canonicalized form of the element MUST be used as in section 2.1.
+
+ An iterative method SHOULD be used to calculate checksums as in
+ section 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+
+
+Kennedy Informational [Page 4]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ The TCP offset element was expanded to a maximum of 255 from 16 to
+ allow for the increased size of the header in XML.
+
+ TCPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+3.2. Example Datagram
+
+ The following is an example TCPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ <tcp>
+ <tcp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <sequence number="322622954"/>
+ <acknowledgement number="689715995"/>
+ <offset number=""/>
+ <reserved value="0"/>
+ <control syn="1" ack="1"/>
+ <window size="1"/>
+ <urgent pointer="0"/>
+ <checksum value="2988"/>
+ <tcp.options>
+ <tcp.end kind="0"/>
+ </tcp.options>
+ <padding pad="0"/>
+ </tcp.header>
+ <payload>
+ </payload>
+ </tcp>
+
+4. UDPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.3.
+
+4.1. UDP Description
+
+ A number of items have changed from the original UDP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+
+
+
+
+
+
+Kennedy Informational [Page 5]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ To calculate the length and checksum fields of the UDP element, a
+ canonicalized form of the element MUST be used as in section 2.1. An
+ iterative method SHOULD be used to calculate checksums as in section
+ 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+ UDPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+4.2. Example Datagram
+
+ The following is an example UDPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ <udp>
+ <udp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <udp.length value="143"/>
+ <checksum value="2988"/>
+ </udp.header>
+ <payload>
+ </payload>
+ </udp>
+
+5. Network Transport
+
+ This document provides for the transmission of BLOAT datagrams over
+ two common families of physical layer transport. Future RFCs will
+ address additional transports as routing vendors catch up to the
+ specification, and we begin to see BLOAT routed across the Internet
+ backbone.
+
+5.1. Ethernet
+
+ BLOAT is encapsulated in Ethernet datagrams as in [RFC894] with the
+ exception that the type field of the Ethernet frame MUST contain the
+ value 0xBEEF. The first 5 octets of the Ethernet frame payload will
+ be 0x3c 3f 78 6d 6c ("<?xml".)
+
+5.2. IEEE 802
+
+ BLOAT is encapsulated in IEEE 802 Networks as in [RFC1042] except
+ that the protocol type code for IPoXML is 0xBEEF.
+
+
+
+
+
+Kennedy Informational [Page 6]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+6. Gatewaying over IP
+
+ In order to facilitate the gradual introduction of BLOAT into the
+ public Internet, BLOAT MAY be encapsulated in IP as in [RFC2003] to
+ gateway between networks that run BLOAT natively on their LANs.
+
+7. DTDs
+
+ The Transport DTDs (7.2. and 7.3.) build on the definitions in the
+ Network DTD (7.1.)
+
+ The DTDs are referenced by their PubidLiteral and SystemLiteral (from
+ [XML]) although it is understood that most IPoXML implementations
+ will not need to pull down the DTD, as it will normally be embedded
+ in the implementation, and presents something of a catch-22 if you
+ need to load part of your network protocol over the network.
+
+7.1. IPoXML DTD
+
+ <!--
+ DTD for IP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ -->
+ <!--
+ DTD data types:
+
+ Digits [0..9]+
+
+ Precedence "NetworkControl | InternetworkControl |
+ CRITIC | FlashOverride | Flash | Immediate |
+ Priority | Routine"
+
+ IP4Addr "dotted-decimal" notation of [RFC1123]
+
+ Class [0..3]
+
+ Sec "Unclassified | Confidential | EFTO | MMMM | PROG |
+ Restricted | Secret | Top Secret | Reserved"
+
+ Compartments [0..65535]
+
+ Handling [0..65535]
+
+ TCC [0..16777216]
+
+ -->
+
+
+
+Kennedy Informational [Page 7]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ENTITY % Digits "CDATA">
+ <!ENTITY % Precedence "CDATA">
+ <!ENTITY % IP4Addr "CDATA">
+ <!ENTITY % Class "CDATA">
+ <!ENTITY % Sec "CDATA">
+ <!ENTITY % Compartments "CDATA">
+ <!ENTITY % Handling "CDATA">
+ <!ENTITY % TCC "CDATA">
+
+ <!ELEMENT ip (header, payload)>
+
+ <!ELEMENT header (version, tos, total.length, id, flags, offset, ttl,
+ protocol, checksum, source, destination, options,
+ padding)>
+ <!-- length of header in 32-bit words -->
+ <!ATTLIST header
+ length %Digits; #REQUIRED>
+
+ <!ELEMENT version EMPTY>
+ <!-- ip version. SHOULD be "4" -->
+ <!ATTLIST version
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT tos EMPTY>
+ <!ATTLIST tos
+ precedence %Precedence; #REQUIRED
+ delay (normal | low) #REQUIRED
+ throughput (normal | high) #REQUIRED
+ relibility (normal | high) #REQUIRED
+ reserved CDATA #FIXED "0">
+
+ <!ELEMENT total.length EMPTY>
+ <!--
+ total length of datagram (header and payload) in octets, MUST be
+ less than 65,535 (and SHOULD be less than 1024 for IPoXML on local
+ ethernets).
+ -->
+ <!ATTLIST total.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT id EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST id
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT flags EMPTY>
+ <!-- df = don't fragment, mf = more fragments -->
+ <!ATTLIST flags
+
+
+
+Kennedy Informational [Page 8]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ reserved CDATA #FIXED "0"
+ df (may|dont) #REQUIRED
+ mf (last|more) #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= offset <= 8192 measured in 8 octet (64-bit) chunks -->
+ <!ATTLIST offset
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT ttl EMPTY>
+ <!-- 0 <= ttl <= 255 -->
+ <!ATTLIST ttl
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT protocol EMPTY>
+ <!-- 0 <= protocol <= 255 (per IANA) -->
+ <!ATTLIST protocol
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT checksum EMPTY>
+ <!-- 0 <= checksum <= 65535 (over header only) -->
+ <!ATTLIST checksum
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT source EMPTY>
+ <!ATTLIST source
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT destination EMPTY>
+ <!ATTLIST destination
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT options ( end | noop | security | loose | strict | record
+ | stream | timestamp )*>
+
+ <!ELEMENT end EMPTY>
+ <!ATTLIST end
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "0">
+
+ <!ELEMENT noop EMPTY>
+ <!ATTLIST noop
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "1">
+
+ <!ELEMENT security EMPTY>
+
+
+
+Kennedy Informational [Page 9]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST security
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "2"
+ length CDATA #FIXED "11"
+ security %Sec; #REQUIRED
+ compartments %Compartments; #REQUIRED
+ handling %Handling; #REQUIRED
+ tcc %TCC; #REQUIRED>
+ <!ELEMENT loose (hop)+>
+ <!ATTLIST loose
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "3"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT hop EMPTY>
+ <!ATTLIST hop
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT strict (hop)+>
+ <!ATTLIST strict
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "9"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT record (hop)+>
+ <!ATTLIST record
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "7"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT stream EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST stream
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "8"
+ length CDATA #FIXED "4"
+ id %Digits; #REQUIRED>
+
+ <!ELEMENT timestamp (tstamp)+>
+ <!-- 0 <= oflw <=15 -->
+
+
+
+Kennedy Informational [Page 10]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST timestamp
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "2"
+ number CDATA #FIXED "4"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED
+ oflw %Digits; #REQUIRED
+ flag (0 | 1 | 3) #REQUIRED>
+
+ <!ELEMENT tstamp EMPTY>
+ <!ATTLIST tstamp
+ time %Digits; #REQUIRED
+ address %IP4Addr; #IMPLIED>
+ <!--
+ padding to bring header to 32-bit boundary.
+ pad MUST be "0"*
+ -->
+ <!ELEMENT padding EMPTY>
+ <!ATTLIST padding
+ pad CDATA #REQUIRED>
+
+ <!-- payload MUST be encoded as base-64 [RFC2045], as modified
+ by section 2.1 of this RFC -->
+ <!ELEMENT payload (CDATA)>
+
+7.2. TCPoXML DTD
+
+ <!--
+ DTD for TCP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ -->
+
+ <!-- the pseudoheader is only included for checksum calculations -->
+ <!ELEMENT tcp (tcp.pseudoheader?, tcp.header, payload)>
+
+ <!ELEMENT tcp.header (src, dest, sequence, acknowledgement, offset,
+ reserved, control, window, checksum, urgent,
+ tcp.options, padding)>
+
+ <!ELEMENT src EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+ <!ATTLIST src
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT dest EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+
+
+
+Kennedy Informational [Page 11]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST dest
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT sequence EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST sequence
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT acknowledgement EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST acknowledgement
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= number <= 255 -->
+ <!ATTLIST offset
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT reserved EMPTY>
+ <!ATTLIST reserved
+ value CDATA #FIXED "0">
+
+ <!ELEMENT control EMPTY>
+ <!ATTLIST control
+ urg (0|1) #IMPLIED
+ ack (0|1) #IMPLIED
+ psh (0|1) #IMPLIED
+ rst (0|1) #IMPLIED
+ syn (0|1) #IMPLIED
+ fin (0|1) #IMPLIED>
+
+ <!ELEMENT window EMPTY>
+ <!-- 0 <= size <= 65,535 -->
+ <!ATTLIST window
+ size %Digits; #REQUIRED>
+
+ <!--
+ checksum as in ip, but with
+ the following pseudo-header added into the tcp element:
+ -->
+ <!ELEMENT tcp.pseudoheader (source, destination, protocol,
+ tcp.length)>
+
+ <!--
+ tcp header + data length in octets. does not include the size of
+
+ the pseudoheader.
+ -->
+
+
+
+Kennedy Informational [Page 12]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ELEMENT tcp.length EMPTY>
+ <!ATTLIST tcp.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT urgent EMPTY>
+ <!-- 0 <= pointer <= 65,535 -->
+ <!ATTLIST urgent
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT tcp.options (tcp.end | tcp.noop | tcp.mss)+>
+
+ <!ELEMENT tcp.end EMPTY>
+ <!ATTLIST tcp.end
+ kind CDATA #FIXED "0">
+
+ <!ELEMENT tcp.noop EMPTY>
+ <!ATTLIST tcp.noop
+ kind CDATA #FIXED "1">
+
+ <!ELEMENT tcp.mss EMPTY>
+ <!ATTLIST tcp.mss
+ kind CDATA #FIXED "2"
+ length CDATA #FIXED "4"
+ size %Digits; #REQUIRED>
+
+7.3. UDPoXML DTD
+
+ <!--
+ DTD for UDP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ -->
+
+ <!ELEMENT udp (udp.pseudoheader?, udp.header, payload)>
+
+ <!ELEMENT udp.header (src, dest, udp.length, checksum)>
+
+ <!ELEMENT udp.pseudoheader (source, destination, protocol,
+ udp.length)>
+
+ <!--
+ udp header + data length in octets. does not include the size of
+ the pseudoheader.
+ -->
+ <!ELEMENT udp.length EMPTY>
+ <!ATTLIST udp.length
+ value %Digits; #REQUIRED>
+
+
+
+Kennedy Informational [Page 13]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+8. Security Considerations
+
+ XML, as a subset of SGML, has the same security considerations as
+ specified in SGML Media Types [RFC1874]. Security considerations
+ that apply to IP, TCP and UDP also likely apply to BLOAT as it does
+ not attempt to correct for issues not related to message format.
+
+9. References
+
+ [JABBER] Miller, J., "Jabber", draft-miller-jabber-00.txt,
+ February 2002. (Work in Progress)
+
+ [RFC768] Postel, J., "User Datagram Protocol", STD 6, RFC 768,
+ August 1980.
+
+ [RFC791] Postel, J., "Internet Protocol", STD 5, RFC 791,
+ September 1981.
+
+ [RFC793] Postel, J., "Transmission Control Protocol", STD 7, RFC
+ 793, September 1981.
+
+ [RFC894] Hornig, C., "Standard for the Transmission of IP
+ Datagrams over Ethernet Networks.", RFC 894, April 1984.
+
+ [RFC1042] Postel, J. and J. Reynolds, "Standard for the
+ Transmission of IP Datagrams Over IEEE 802 Networks", STD
+ 43, RFC 1042, February 1988.
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts -
+ Application and Support", RFC 1123, October 1989.
+
+ [RFC1874] Levinson, E., "SGML Media Types", RFC 1874, December
+ 1995.
+
+ [RFC2003] Perkins, C., "IP Encapsulation within IP", RFC 2003,
+ October 1996.
+
+ [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message
+ Bodies", RFC 2045, November 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+
+
+
+
+Kennedy Informational [Page 14]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ [RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6
+ (IPv6) Specification", RFC 2460, December 1998.
+
+ [RFC3080] Rose, M., "The Blocks Extensible Exchange Protocol Core",
+ RFC 3080, March 2001.
+
+ [SOAP] Box, D., Ehnebuske, D., Kakivaya, G., Layman, A.,
+ Mendelsohn, N., Nielsen, H. F., Thatte, S. Winer, D.,
+ "Simple Object Access Protocol (SOAP) 1.1" World Wide Web
+ Consortium Note, May 2000 http://www.w3.org/TR/SOAP/
+
+ [XML] Bray, T., Paoli, J., Sperberg-McQueen, C. M., "Extensible
+ Markup Language (XML)" World Wide Web Consortium
+ Recommendation REC- xml-19980210.
+ http://www.w3.org/TR/1998/REC-xml-19980210
+
+10. Author's Address
+
+ Hugh Kennedy
+ Mimezine
+ 1060 West Addison
+ Chicago, IL 60613
+ USA
+
+ EMail: kennedyh@engin.umich.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 15]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+11. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 16]
+
diff --git a/tests/auto/network/access/qhttp/webserver/rfc3252 b/tests/auto/network/access/qhttp/webserver/rfc3252
new file mode 100644
index 0000000000..b80c61bf0a
--- /dev/null
+++ b/tests/auto/network/access/qhttp/webserver/rfc3252
@@ -0,0 +1,899 @@
+
+
+
+
+
+
+Network Working Group H. Kennedy
+Request for Comments: 3252 Mimezine
+Category: Informational 1 April 2002
+
+
+ Binary Lexical Octet Ad-hoc Transport
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ This document defines a reformulation of IP and two transport layer
+ protocols (TCP and UDP) as XML applications.
+
+1. Introduction
+
+1.1. Overview
+
+ This document describes the Binary Lexical Octet Ad-hoc Transport
+ (BLOAT): a reformulation of a widely-deployed network-layer protocol
+ (IP [RFC791]), and two associated transport layer protocols (TCP
+ [RFC793] and UDP [RFC768]) as XML [XML] applications. It also
+ describes methods for transporting BLOAT over Ethernet and IEEE 802
+ networks as well as encapsulating BLOAT in IP for gatewaying BLOAT
+ across the public Internet.
+
+1.2. Motivation
+
+ The wild popularity of XML as a basis for application-level protocols
+ such as the Blocks Extensible Exchange Protocol [RFC3080], the Simple
+ Object Access Protocol [SOAP], and Jabber [JABBER] prompted
+ investigation into the possibility of extending the use of XML in the
+ protocol stack. Using XML at both the transport and network layer in
+ addition to the application layer would provide for an amazing amount
+ of power and flexibility while removing dependencies on proprietary
+ and hard-to-understand binary protocols. This protocol unification
+ would also allow applications to use a single XML parser for all
+ aspects of their operation, eliminating developer time spent figuring
+ out the intricacies of each new protocol, and moving the hard work of
+
+
+
+
+Kennedy Informational [Page 1]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ parsing to the XML toolset. The use of XML also mitigates concerns
+ over "network vs. host" byte ordering which is at the root of many
+ network application bugs.
+
+1.3. Relation to Existing Protocols
+
+ The reformulations specified in this RFC follow as closely as
+ possible the spirit of the RFCs on which they are based, and so MAY
+ contain elements or attributes that would not be needed in a pure
+ reworking (e.g. length attributes, which are implicit in XML.)
+
+ The layering of network and transport protocols are maintained in
+ this RFC despite the optimizations that could be made if the line
+ were somewhat blurred (i.e. merging TCP and IP into a single, larger
+ element in the DTD) in order to foster future use of this protocol as
+ a basis for reformulating other protocols (such as ICMP.)
+
+ Other than the encoding, the behavioral aspects of each of the
+ existing protocols remain unchanged. Routing, address spaces, TCP
+ congestion control, etc. behave as specified in the extant standards.
+ Adapting to new standards and experimental algorithm heuristics for
+ improving performance will become much easier once the move to BLOAT
+ has been completed.
+
+1.4. Requirement Levels
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in BCP 14, RFC 2119
+ [RFC2119].
+
+2. IPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC.
+ IPoXML is the root protocol REQUIRED for effective use of TCPoXML
+ (section 3.) and higher-level application protocols.
+
+ The DTD for this document type can be found in section 7.1.
+
+ The routing of IPoXML can be easily implemented on hosts with an XML
+ parser, as the regular structure lends itself handily to parsing and
+ validation of the document/datagram and then processing the
+ destination address, TTL, and checksum before sending it on to its
+ next-hop.
+
+ The reformulation of IPv4 was chosen over IPv6 [RFC2460] due to the
+ wider deployment of IPv4 and the fact that implementing IPv6 as XML
+ would have exceeded the 1500 byte Ethernet MTU.
+
+
+
+Kennedy Informational [Page 2]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ All BLOAT implementations MUST use - and specify - the UTF-8 encoding
+ of RFC 2279 [RFC2279]. All BLOAT document/datagrams MUST be well-
+ formed and include the XMLDecl.
+
+2.1. IP Description
+
+ A number of items have changed (for the better) from the original IP
+ specification. Bit-masks, where present have been converted into
+ human-readable values. IP addresses are listed in their dotted-
+ decimal notation [RFC1123]. Length and checksum values are present
+ as decimal integers.
+
+ To calculate the length and checksum fields of the IP element, a
+ canonicalized form of the element MUST be used. The canonical form
+ SHALL have no whitespace (including newline characters) between
+ elements and only one space character between attributes. There
+ SHALL NOT be a space following the last attribute in an element.
+
+ An iterative method SHOULD be used to calculate checksums, as the
+ length field will vary based on the size of the checksum.
+
+ The payload element bears special attention. Due to the character
+ set restrictions of XML, the payload of IP datagrams (which MAY
+ contain arbitrary data) MUST be encoded for transport. This RFC
+ REQUIRES the contents of the payload to be encoded in the base-64
+ encoding of RFC 2045 [RFC2045], but removes the requirement that the
+ encoded output MUST be wrapped on 76-character lines.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 3]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+2.2. Example Datagram
+
+ The following is an example IPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ <ip>
+ <header length="474">
+ <version value="4"/>
+ <tos precedence="Routine" delay="Normal" throughput="Normal"
+ relibility="Normal" reserved="0"/>
+ <total.length value="461"/>
+ <id value="1"/>
+ <flags reserved="0" df="dont" mf="last"/>
+ <offset value="0"/>
+ <ttl value="255"/>
+ <protocol value="6"/>
+ <checksum value="8707"/>
+ <source address="10.0.0.22"/>
+ <destination address="10.0.0.1"/>
+ <options>
+ <end copied="0" class="0" number="0"/>
+ </options>
+ <padding pad="0"/>
+ </header>
+ <payload>
+ </payload>
+ </ip>
+
+3. TCPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.2.
+
+3.1. TCP Description
+
+ A number of items have changed from the original TCP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+ To calculate the length and checksum fields of the TCP element, a
+ canonicalized form of the element MUST be used as in section 2.1.
+
+ An iterative method SHOULD be used to calculate checksums as in
+ section 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+
+
+Kennedy Informational [Page 4]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ The TCP offset element was expanded to a maximum of 255 from 16 to
+ allow for the increased size of the header in XML.
+
+ TCPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+3.2. Example Datagram
+
+ The following is an example TCPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ <tcp>
+ <tcp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <sequence number="322622954"/>
+ <acknowledgement number="689715995"/>
+ <offset number=""/>
+ <reserved value="0"/>
+ <control syn="1" ack="1"/>
+ <window size="1"/>
+ <urgent pointer="0"/>
+ <checksum value="2988"/>
+ <tcp.options>
+ <tcp.end kind="0"/>
+ </tcp.options>
+ <padding pad="0"/>
+ </tcp.header>
+ <payload>
+ </payload>
+ </tcp>
+
+4. UDPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.3.
+
+4.1. UDP Description
+
+ A number of items have changed from the original UDP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+
+
+
+
+
+
+Kennedy Informational [Page 5]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ To calculate the length and checksum fields of the UDP element, a
+ canonicalized form of the element MUST be used as in section 2.1. An
+ iterative method SHOULD be used to calculate checksums as in section
+ 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+ UDPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+4.2. Example Datagram
+
+ The following is an example UDPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ <udp>
+ <udp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <udp.length value="143"/>
+ <checksum value="2988"/>
+ </udp.header>
+ <payload>
+ </payload>
+ </udp>
+
+5. Network Transport
+
+ This document provides for the transmission of BLOAT datagrams over
+ two common families of physical layer transport. Future RFCs will
+ address additional transports as routing vendors catch up to the
+ specification, and we begin to see BLOAT routed across the Internet
+ backbone.
+
+5.1. Ethernet
+
+ BLOAT is encapsulated in Ethernet datagrams as in [RFC894] with the
+ exception that the type field of the Ethernet frame MUST contain the
+ value 0xBEEF. The first 5 octets of the Ethernet frame payload will
+ be 0x3c 3f 78 6d 6c ("<?xml".)
+
+5.2. IEEE 802
+
+ BLOAT is encapsulated in IEEE 802 Networks as in [RFC1042] except
+ that the protocol type code for IPoXML is 0xBEEF.
+
+
+
+
+
+Kennedy Informational [Page 6]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+6. Gatewaying over IP
+
+ In order to facilitate the gradual introduction of BLOAT into the
+ public Internet, BLOAT MAY be encapsulated in IP as in [RFC2003] to
+ gateway between networks that run BLOAT natively on their LANs.
+
+7. DTDs
+
+ The Transport DTDs (7.2. and 7.3.) build on the definitions in the
+ Network DTD (7.1.)
+
+ The DTDs are referenced by their PubidLiteral and SystemLiteral (from
+ [XML]) although it is understood that most IPoXML implementations
+ will not need to pull down the DTD, as it will normally be embedded
+ in the implementation, and presents something of a catch-22 if you
+ need to load part of your network protocol over the network.
+
+7.1. IPoXML DTD
+
+ <!--
+ DTD for IP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ -->
+ <!--
+ DTD data types:
+
+ Digits [0..9]+
+
+ Precedence "NetworkControl | InternetworkControl |
+ CRITIC | FlashOverride | Flash | Immediate |
+ Priority | Routine"
+
+ IP4Addr "dotted-decimal" notation of [RFC1123]
+
+ Class [0..3]
+
+ Sec "Unclassified | Confidential | EFTO | MMMM | PROG |
+ Restricted | Secret | Top Secret | Reserved"
+
+ Compartments [0..65535]
+
+ Handling [0..65535]
+
+ TCC [0..16777216]
+
+ -->
+
+
+
+Kennedy Informational [Page 7]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ENTITY % Digits "CDATA">
+ <!ENTITY % Precedence "CDATA">
+ <!ENTITY % IP4Addr "CDATA">
+ <!ENTITY % Class "CDATA">
+ <!ENTITY % Sec "CDATA">
+ <!ENTITY % Compartments "CDATA">
+ <!ENTITY % Handling "CDATA">
+ <!ENTITY % TCC "CDATA">
+
+ <!ELEMENT ip (header, payload)>
+
+ <!ELEMENT header (version, tos, total.length, id, flags, offset, ttl,
+ protocol, checksum, source, destination, options,
+ padding)>
+ <!-- length of header in 32-bit words -->
+ <!ATTLIST header
+ length %Digits; #REQUIRED>
+
+ <!ELEMENT version EMPTY>
+ <!-- ip version. SHOULD be "4" -->
+ <!ATTLIST version
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT tos EMPTY>
+ <!ATTLIST tos
+ precedence %Precedence; #REQUIRED
+ delay (normal | low) #REQUIRED
+ throughput (normal | high) #REQUIRED
+ relibility (normal | high) #REQUIRED
+ reserved CDATA #FIXED "0">
+
+ <!ELEMENT total.length EMPTY>
+ <!--
+ total length of datagram (header and payload) in octets, MUST be
+ less than 65,535 (and SHOULD be less than 1024 for IPoXML on local
+ ethernets).
+ -->
+ <!ATTLIST total.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT id EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST id
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT flags EMPTY>
+ <!-- df = don't fragment, mf = more fragments -->
+ <!ATTLIST flags
+
+
+
+Kennedy Informational [Page 8]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ reserved CDATA #FIXED "0"
+ df (may|dont) #REQUIRED
+ mf (last|more) #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= offset <= 8192 measured in 8 octet (64-bit) chunks -->
+ <!ATTLIST offset
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT ttl EMPTY>
+ <!-- 0 <= ttl <= 255 -->
+ <!ATTLIST ttl
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT protocol EMPTY>
+ <!-- 0 <= protocol <= 255 (per IANA) -->
+ <!ATTLIST protocol
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT checksum EMPTY>
+ <!-- 0 <= checksum <= 65535 (over header only) -->
+ <!ATTLIST checksum
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT source EMPTY>
+ <!ATTLIST source
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT destination EMPTY>
+ <!ATTLIST destination
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT options ( end | noop | security | loose | strict | record
+ | stream | timestamp )*>
+
+ <!ELEMENT end EMPTY>
+ <!ATTLIST end
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "0">
+
+ <!ELEMENT noop EMPTY>
+ <!ATTLIST noop
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "1">
+
+ <!ELEMENT security EMPTY>
+
+
+
+Kennedy Informational [Page 9]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST security
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "2"
+ length CDATA #FIXED "11"
+ security %Sec; #REQUIRED
+ compartments %Compartments; #REQUIRED
+ handling %Handling; #REQUIRED
+ tcc %TCC; #REQUIRED>
+ <!ELEMENT loose (hop)+>
+ <!ATTLIST loose
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "3"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT hop EMPTY>
+ <!ATTLIST hop
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT strict (hop)+>
+ <!ATTLIST strict
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "9"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT record (hop)+>
+ <!ATTLIST record
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "7"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT stream EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST stream
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "8"
+ length CDATA #FIXED "4"
+ id %Digits; #REQUIRED>
+
+ <!ELEMENT timestamp (tstamp)+>
+ <!-- 0 <= oflw <=15 -->
+
+
+
+Kennedy Informational [Page 10]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST timestamp
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "2"
+ number CDATA #FIXED "4"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED
+ oflw %Digits; #REQUIRED
+ flag (0 | 1 | 3) #REQUIRED>
+
+ <!ELEMENT tstamp EMPTY>
+ <!ATTLIST tstamp
+ time %Digits; #REQUIRED
+ address %IP4Addr; #IMPLIED>
+ <!--
+ padding to bring header to 32-bit boundary.
+ pad MUST be "0"*
+ -->
+ <!ELEMENT padding EMPTY>
+ <!ATTLIST padding
+ pad CDATA #REQUIRED>
+
+ <!-- payload MUST be encoded as base-64 [RFC2045], as modified
+ by section 2.1 of this RFC -->
+ <!ELEMENT payload (CDATA)>
+
+7.2. TCPoXML DTD
+
+ <!--
+ DTD for TCP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ -->
+
+ <!-- the pseudoheader is only included for checksum calculations -->
+ <!ELEMENT tcp (tcp.pseudoheader?, tcp.header, payload)>
+
+ <!ELEMENT tcp.header (src, dest, sequence, acknowledgement, offset,
+ reserved, control, window, checksum, urgent,
+ tcp.options, padding)>
+
+ <!ELEMENT src EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+ <!ATTLIST src
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT dest EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+
+
+
+Kennedy Informational [Page 11]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST dest
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT sequence EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST sequence
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT acknowledgement EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST acknowledgement
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= number <= 255 -->
+ <!ATTLIST offset
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT reserved EMPTY>
+ <!ATTLIST reserved
+ value CDATA #FIXED "0">
+
+ <!ELEMENT control EMPTY>
+ <!ATTLIST control
+ urg (0|1) #IMPLIED
+ ack (0|1) #IMPLIED
+ psh (0|1) #IMPLIED
+ rst (0|1) #IMPLIED
+ syn (0|1) #IMPLIED
+ fin (0|1) #IMPLIED>
+
+ <!ELEMENT window EMPTY>
+ <!-- 0 <= size <= 65,535 -->
+ <!ATTLIST window
+ size %Digits; #REQUIRED>
+
+ <!--
+ checksum as in ip, but with
+ the following pseudo-header added into the tcp element:
+ -->
+ <!ELEMENT tcp.pseudoheader (source, destination, protocol,
+ tcp.length)>
+
+ <!--
+ tcp header + data length in octets. does not include the size of
+
+ the pseudoheader.
+ -->
+
+
+
+Kennedy Informational [Page 12]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ELEMENT tcp.length EMPTY>
+ <!ATTLIST tcp.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT urgent EMPTY>
+ <!-- 0 <= pointer <= 65,535 -->
+ <!ATTLIST urgent
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT tcp.options (tcp.end | tcp.noop | tcp.mss)+>
+
+ <!ELEMENT tcp.end EMPTY>
+ <!ATTLIST tcp.end
+ kind CDATA #FIXED "0">
+
+ <!ELEMENT tcp.noop EMPTY>
+ <!ATTLIST tcp.noop
+ kind CDATA #FIXED "1">
+
+ <!ELEMENT tcp.mss EMPTY>
+ <!ATTLIST tcp.mss
+ kind CDATA #FIXED "2"
+ length CDATA #FIXED "4"
+ size %Digits; #REQUIRED>
+
+7.3. UDPoXML DTD
+
+ <!--
+ DTD for UDP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ -->
+
+ <!ELEMENT udp (udp.pseudoheader?, udp.header, payload)>
+
+ <!ELEMENT udp.header (src, dest, udp.length, checksum)>
+
+ <!ELEMENT udp.pseudoheader (source, destination, protocol,
+ udp.length)>
+
+ <!--
+ udp header + data length in octets. does not include the size of
+ the pseudoheader.
+ -->
+ <!ELEMENT udp.length EMPTY>
+ <!ATTLIST udp.length
+ value %Digits; #REQUIRED>
+
+
+
+Kennedy Informational [Page 13]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+8. Security Considerations
+
+ XML, as a subset of SGML, has the same security considerations as
+ specified in SGML Media Types [RFC1874]. Security considerations
+ that apply to IP, TCP and UDP also likely apply to BLOAT as it does
+ not attempt to correct for issues not related to message format.
+
+9. References
+
+ [JABBER] Miller, J., "Jabber", draft-miller-jabber-00.txt,
+ February 2002. (Work in Progress)
+
+ [RFC768] Postel, J., "User Datagram Protocol", STD 6, RFC 768,
+ August 1980.
+
+ [RFC791] Postel, J., "Internet Protocol", STD 5, RFC 791,
+ September 1981.
+
+ [RFC793] Postel, J., "Transmission Control Protocol", STD 7, RFC
+ 793, September 1981.
+
+ [RFC894] Hornig, C., "Standard for the Transmission of IP
+ Datagrams over Ethernet Networks.", RFC 894, April 1984.
+
+ [RFC1042] Postel, J. and J. Reynolds, "Standard for the
+ Transmission of IP Datagrams Over IEEE 802 Networks", STD
+ 43, RFC 1042, February 1988.
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts -
+ Application and Support", RFC 1123, October 1989.
+
+ [RFC1874] Levinson, E., "SGML Media Types", RFC 1874, December
+ 1995.
+
+ [RFC2003] Perkins, C., "IP Encapsulation within IP", RFC 2003,
+ October 1996.
+
+ [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message
+ Bodies", RFC 2045, November 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+
+
+
+
+Kennedy Informational [Page 14]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ [RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6
+ (IPv6) Specification", RFC 2460, December 1998.
+
+ [RFC3080] Rose, M., "The Blocks Extensible Exchange Protocol Core",
+ RFC 3080, March 2001.
+
+ [SOAP] Box, D., Ehnebuske, D., Kakivaya, G., Layman, A.,
+ Mendelsohn, N., Nielsen, H. F., Thatte, S. Winer, D.,
+ "Simple Object Access Protocol (SOAP) 1.1" World Wide Web
+ Consortium Note, May 2000 http://www.w3.org/TR/SOAP/
+
+ [XML] Bray, T., Paoli, J., Sperberg-McQueen, C. M., "Extensible
+ Markup Language (XML)" World Wide Web Consortium
+ Recommendation REC- xml-19980210.
+ http://www.w3.org/TR/1998/REC-xml-19980210
+
+10. Author's Address
+
+ Hugh Kennedy
+ Mimezine
+ 1060 West Addison
+ Chicago, IL 60613
+ USA
+
+ EMail: kennedyh@engin.umich.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 15]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+11. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 16]
+
diff --git a/tests/auto/network/access/qhttp/webserver/rfc3252.txt b/tests/auto/network/access/qhttp/webserver/rfc3252.txt
new file mode 100644
index 0000000000..b80c61bf0a
--- /dev/null
+++ b/tests/auto/network/access/qhttp/webserver/rfc3252.txt
@@ -0,0 +1,899 @@
+
+
+
+
+
+
+Network Working Group H. Kennedy
+Request for Comments: 3252 Mimezine
+Category: Informational 1 April 2002
+
+
+ Binary Lexical Octet Ad-hoc Transport
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ This document defines a reformulation of IP and two transport layer
+ protocols (TCP and UDP) as XML applications.
+
+1. Introduction
+
+1.1. Overview
+
+ This document describes the Binary Lexical Octet Ad-hoc Transport
+ (BLOAT): a reformulation of a widely-deployed network-layer protocol
+ (IP [RFC791]), and two associated transport layer protocols (TCP
+ [RFC793] and UDP [RFC768]) as XML [XML] applications. It also
+ describes methods for transporting BLOAT over Ethernet and IEEE 802
+ networks as well as encapsulating BLOAT in IP for gatewaying BLOAT
+ across the public Internet.
+
+1.2. Motivation
+
+ The wild popularity of XML as a basis for application-level protocols
+ such as the Blocks Extensible Exchange Protocol [RFC3080], the Simple
+ Object Access Protocol [SOAP], and Jabber [JABBER] prompted
+ investigation into the possibility of extending the use of XML in the
+ protocol stack. Using XML at both the transport and network layer in
+ addition to the application layer would provide for an amazing amount
+ of power and flexibility while removing dependencies on proprietary
+ and hard-to-understand binary protocols. This protocol unification
+ would also allow applications to use a single XML parser for all
+ aspects of their operation, eliminating developer time spent figuring
+ out the intricacies of each new protocol, and moving the hard work of
+
+
+
+
+Kennedy Informational [Page 1]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ parsing to the XML toolset. The use of XML also mitigates concerns
+ over "network vs. host" byte ordering which is at the root of many
+ network application bugs.
+
+1.3. Relation to Existing Protocols
+
+ The reformulations specified in this RFC follow as closely as
+ possible the spirit of the RFCs on which they are based, and so MAY
+ contain elements or attributes that would not be needed in a pure
+ reworking (e.g. length attributes, which are implicit in XML.)
+
+ The layering of network and transport protocols are maintained in
+ this RFC despite the optimizations that could be made if the line
+ were somewhat blurred (i.e. merging TCP and IP into a single, larger
+ element in the DTD) in order to foster future use of this protocol as
+ a basis for reformulating other protocols (such as ICMP.)
+
+ Other than the encoding, the behavioral aspects of each of the
+ existing protocols remain unchanged. Routing, address spaces, TCP
+ congestion control, etc. behave as specified in the extant standards.
+ Adapting to new standards and experimental algorithm heuristics for
+ improving performance will become much easier once the move to BLOAT
+ has been completed.
+
+1.4. Requirement Levels
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in BCP 14, RFC 2119
+ [RFC2119].
+
+2. IPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC.
+ IPoXML is the root protocol REQUIRED for effective use of TCPoXML
+ (section 3.) and higher-level application protocols.
+
+ The DTD for this document type can be found in section 7.1.
+
+ The routing of IPoXML can be easily implemented on hosts with an XML
+ parser, as the regular structure lends itself handily to parsing and
+ validation of the document/datagram and then processing the
+ destination address, TTL, and checksum before sending it on to its
+ next-hop.
+
+ The reformulation of IPv4 was chosen over IPv6 [RFC2460] due to the
+ wider deployment of IPv4 and the fact that implementing IPv6 as XML
+ would have exceeded the 1500 byte Ethernet MTU.
+
+
+
+Kennedy Informational [Page 2]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ All BLOAT implementations MUST use - and specify - the UTF-8 encoding
+ of RFC 2279 [RFC2279]. All BLOAT document/datagrams MUST be well-
+ formed and include the XMLDecl.
+
+2.1. IP Description
+
+ A number of items have changed (for the better) from the original IP
+ specification. Bit-masks, where present have been converted into
+ human-readable values. IP addresses are listed in their dotted-
+ decimal notation [RFC1123]. Length and checksum values are present
+ as decimal integers.
+
+ To calculate the length and checksum fields of the IP element, a
+ canonicalized form of the element MUST be used. The canonical form
+ SHALL have no whitespace (including newline characters) between
+ elements and only one space character between attributes. There
+ SHALL NOT be a space following the last attribute in an element.
+
+ An iterative method SHOULD be used to calculate checksums, as the
+ length field will vary based on the size of the checksum.
+
+ The payload element bears special attention. Due to the character
+ set restrictions of XML, the payload of IP datagrams (which MAY
+ contain arbitrary data) MUST be encoded for transport. This RFC
+ REQUIRES the contents of the payload to be encoded in the base-64
+ encoding of RFC 2045 [RFC2045], but removes the requirement that the
+ encoded output MUST be wrapped on 76-character lines.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 3]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+2.2. Example Datagram
+
+ The following is an example IPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ <ip>
+ <header length="474">
+ <version value="4"/>
+ <tos precedence="Routine" delay="Normal" throughput="Normal"
+ relibility="Normal" reserved="0"/>
+ <total.length value="461"/>
+ <id value="1"/>
+ <flags reserved="0" df="dont" mf="last"/>
+ <offset value="0"/>
+ <ttl value="255"/>
+ <protocol value="6"/>
+ <checksum value="8707"/>
+ <source address="10.0.0.22"/>
+ <destination address="10.0.0.1"/>
+ <options>
+ <end copied="0" class="0" number="0"/>
+ </options>
+ <padding pad="0"/>
+ </header>
+ <payload>
+ </payload>
+ </ip>
+
+3. TCPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.2.
+
+3.1. TCP Description
+
+ A number of items have changed from the original TCP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+ To calculate the length and checksum fields of the TCP element, a
+ canonicalized form of the element MUST be used as in section 2.1.
+
+ An iterative method SHOULD be used to calculate checksums as in
+ section 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+
+
+Kennedy Informational [Page 4]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ The TCP offset element was expanded to a maximum of 255 from 16 to
+ allow for the increased size of the header in XML.
+
+ TCPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+3.2. Example Datagram
+
+ The following is an example TCPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ <tcp>
+ <tcp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <sequence number="322622954"/>
+ <acknowledgement number="689715995"/>
+ <offset number=""/>
+ <reserved value="0"/>
+ <control syn="1" ack="1"/>
+ <window size="1"/>
+ <urgent pointer="0"/>
+ <checksum value="2988"/>
+ <tcp.options>
+ <tcp.end kind="0"/>
+ </tcp.options>
+ <padding pad="0"/>
+ </tcp.header>
+ <payload>
+ </payload>
+ </tcp>
+
+4. UDPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.3.
+
+4.1. UDP Description
+
+ A number of items have changed from the original UDP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+
+
+
+
+
+
+Kennedy Informational [Page 5]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ To calculate the length and checksum fields of the UDP element, a
+ canonicalized form of the element MUST be used as in section 2.1. An
+ iterative method SHOULD be used to calculate checksums as in section
+ 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+ UDPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+4.2. Example Datagram
+
+ The following is an example UDPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ <udp>
+ <udp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <udp.length value="143"/>
+ <checksum value="2988"/>
+ </udp.header>
+ <payload>
+ </payload>
+ </udp>
+
+5. Network Transport
+
+ This document provides for the transmission of BLOAT datagrams over
+ two common families of physical layer transport. Future RFCs will
+ address additional transports as routing vendors catch up to the
+ specification, and we begin to see BLOAT routed across the Internet
+ backbone.
+
+5.1. Ethernet
+
+ BLOAT is encapsulated in Ethernet datagrams as in [RFC894] with the
+ exception that the type field of the Ethernet frame MUST contain the
+ value 0xBEEF. The first 5 octets of the Ethernet frame payload will
+ be 0x3c 3f 78 6d 6c ("<?xml".)
+
+5.2. IEEE 802
+
+ BLOAT is encapsulated in IEEE 802 Networks as in [RFC1042] except
+ that the protocol type code for IPoXML is 0xBEEF.
+
+
+
+
+
+Kennedy Informational [Page 6]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+6. Gatewaying over IP
+
+ In order to facilitate the gradual introduction of BLOAT into the
+ public Internet, BLOAT MAY be encapsulated in IP as in [RFC2003] to
+ gateway between networks that run BLOAT natively on their LANs.
+
+7. DTDs
+
+ The Transport DTDs (7.2. and 7.3.) build on the definitions in the
+ Network DTD (7.1.)
+
+ The DTDs are referenced by their PubidLiteral and SystemLiteral (from
+ [XML]) although it is understood that most IPoXML implementations
+ will not need to pull down the DTD, as it will normally be embedded
+ in the implementation, and presents something of a catch-22 if you
+ need to load part of your network protocol over the network.
+
+7.1. IPoXML DTD
+
+ <!--
+ DTD for IP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ -->
+ <!--
+ DTD data types:
+
+ Digits [0..9]+
+
+ Precedence "NetworkControl | InternetworkControl |
+ CRITIC | FlashOverride | Flash | Immediate |
+ Priority | Routine"
+
+ IP4Addr "dotted-decimal" notation of [RFC1123]
+
+ Class [0..3]
+
+ Sec "Unclassified | Confidential | EFTO | MMMM | PROG |
+ Restricted | Secret | Top Secret | Reserved"
+
+ Compartments [0..65535]
+
+ Handling [0..65535]
+
+ TCC [0..16777216]
+
+ -->
+
+
+
+Kennedy Informational [Page 7]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ENTITY % Digits "CDATA">
+ <!ENTITY % Precedence "CDATA">
+ <!ENTITY % IP4Addr "CDATA">
+ <!ENTITY % Class "CDATA">
+ <!ENTITY % Sec "CDATA">
+ <!ENTITY % Compartments "CDATA">
+ <!ENTITY % Handling "CDATA">
+ <!ENTITY % TCC "CDATA">
+
+ <!ELEMENT ip (header, payload)>
+
+ <!ELEMENT header (version, tos, total.length, id, flags, offset, ttl,
+ protocol, checksum, source, destination, options,
+ padding)>
+ <!-- length of header in 32-bit words -->
+ <!ATTLIST header
+ length %Digits; #REQUIRED>
+
+ <!ELEMENT version EMPTY>
+ <!-- ip version. SHOULD be "4" -->
+ <!ATTLIST version
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT tos EMPTY>
+ <!ATTLIST tos
+ precedence %Precedence; #REQUIRED
+ delay (normal | low) #REQUIRED
+ throughput (normal | high) #REQUIRED
+ relibility (normal | high) #REQUIRED
+ reserved CDATA #FIXED "0">
+
+ <!ELEMENT total.length EMPTY>
+ <!--
+ total length of datagram (header and payload) in octets, MUST be
+ less than 65,535 (and SHOULD be less than 1024 for IPoXML on local
+ ethernets).
+ -->
+ <!ATTLIST total.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT id EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST id
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT flags EMPTY>
+ <!-- df = don't fragment, mf = more fragments -->
+ <!ATTLIST flags
+
+
+
+Kennedy Informational [Page 8]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ reserved CDATA #FIXED "0"
+ df (may|dont) #REQUIRED
+ mf (last|more) #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= offset <= 8192 measured in 8 octet (64-bit) chunks -->
+ <!ATTLIST offset
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT ttl EMPTY>
+ <!-- 0 <= ttl <= 255 -->
+ <!ATTLIST ttl
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT protocol EMPTY>
+ <!-- 0 <= protocol <= 255 (per IANA) -->
+ <!ATTLIST protocol
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT checksum EMPTY>
+ <!-- 0 <= checksum <= 65535 (over header only) -->
+ <!ATTLIST checksum
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT source EMPTY>
+ <!ATTLIST source
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT destination EMPTY>
+ <!ATTLIST destination
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT options ( end | noop | security | loose | strict | record
+ | stream | timestamp )*>
+
+ <!ELEMENT end EMPTY>
+ <!ATTLIST end
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "0">
+
+ <!ELEMENT noop EMPTY>
+ <!ATTLIST noop
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "1">
+
+ <!ELEMENT security EMPTY>
+
+
+
+Kennedy Informational [Page 9]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST security
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "2"
+ length CDATA #FIXED "11"
+ security %Sec; #REQUIRED
+ compartments %Compartments; #REQUIRED
+ handling %Handling; #REQUIRED
+ tcc %TCC; #REQUIRED>
+ <!ELEMENT loose (hop)+>
+ <!ATTLIST loose
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "3"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT hop EMPTY>
+ <!ATTLIST hop
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT strict (hop)+>
+ <!ATTLIST strict
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "9"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT record (hop)+>
+ <!ATTLIST record
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "7"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT stream EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST stream
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "8"
+ length CDATA #FIXED "4"
+ id %Digits; #REQUIRED>
+
+ <!ELEMENT timestamp (tstamp)+>
+ <!-- 0 <= oflw <=15 -->
+
+
+
+Kennedy Informational [Page 10]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST timestamp
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "2"
+ number CDATA #FIXED "4"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED
+ oflw %Digits; #REQUIRED
+ flag (0 | 1 | 3) #REQUIRED>
+
+ <!ELEMENT tstamp EMPTY>
+ <!ATTLIST tstamp
+ time %Digits; #REQUIRED
+ address %IP4Addr; #IMPLIED>
+ <!--
+ padding to bring header to 32-bit boundary.
+ pad MUST be "0"*
+ -->
+ <!ELEMENT padding EMPTY>
+ <!ATTLIST padding
+ pad CDATA #REQUIRED>
+
+ <!-- payload MUST be encoded as base-64 [RFC2045], as modified
+ by section 2.1 of this RFC -->
+ <!ELEMENT payload (CDATA)>
+
+7.2. TCPoXML DTD
+
+ <!--
+ DTD for TCP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ -->
+
+ <!-- the pseudoheader is only included for checksum calculations -->
+ <!ELEMENT tcp (tcp.pseudoheader?, tcp.header, payload)>
+
+ <!ELEMENT tcp.header (src, dest, sequence, acknowledgement, offset,
+ reserved, control, window, checksum, urgent,
+ tcp.options, padding)>
+
+ <!ELEMENT src EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+ <!ATTLIST src
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT dest EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+
+
+
+Kennedy Informational [Page 11]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST dest
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT sequence EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST sequence
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT acknowledgement EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST acknowledgement
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= number <= 255 -->
+ <!ATTLIST offset
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT reserved EMPTY>
+ <!ATTLIST reserved
+ value CDATA #FIXED "0">
+
+ <!ELEMENT control EMPTY>
+ <!ATTLIST control
+ urg (0|1) #IMPLIED
+ ack (0|1) #IMPLIED
+ psh (0|1) #IMPLIED
+ rst (0|1) #IMPLIED
+ syn (0|1) #IMPLIED
+ fin (0|1) #IMPLIED>
+
+ <!ELEMENT window EMPTY>
+ <!-- 0 <= size <= 65,535 -->
+ <!ATTLIST window
+ size %Digits; #REQUIRED>
+
+ <!--
+ checksum as in ip, but with
+ the following pseudo-header added into the tcp element:
+ -->
+ <!ELEMENT tcp.pseudoheader (source, destination, protocol,
+ tcp.length)>
+
+ <!--
+ tcp header + data length in octets. does not include the size of
+
+ the pseudoheader.
+ -->
+
+
+
+Kennedy Informational [Page 12]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ELEMENT tcp.length EMPTY>
+ <!ATTLIST tcp.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT urgent EMPTY>
+ <!-- 0 <= pointer <= 65,535 -->
+ <!ATTLIST urgent
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT tcp.options (tcp.end | tcp.noop | tcp.mss)+>
+
+ <!ELEMENT tcp.end EMPTY>
+ <!ATTLIST tcp.end
+ kind CDATA #FIXED "0">
+
+ <!ELEMENT tcp.noop EMPTY>
+ <!ATTLIST tcp.noop
+ kind CDATA #FIXED "1">
+
+ <!ELEMENT tcp.mss EMPTY>
+ <!ATTLIST tcp.mss
+ kind CDATA #FIXED "2"
+ length CDATA #FIXED "4"
+ size %Digits; #REQUIRED>
+
+7.3. UDPoXML DTD
+
+ <!--
+ DTD for UDP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ -->
+
+ <!ELEMENT udp (udp.pseudoheader?, udp.header, payload)>
+
+ <!ELEMENT udp.header (src, dest, udp.length, checksum)>
+
+ <!ELEMENT udp.pseudoheader (source, destination, protocol,
+ udp.length)>
+
+ <!--
+ udp header + data length in octets. does not include the size of
+ the pseudoheader.
+ -->
+ <!ELEMENT udp.length EMPTY>
+ <!ATTLIST udp.length
+ value %Digits; #REQUIRED>
+
+
+
+Kennedy Informational [Page 13]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+8. Security Considerations
+
+ XML, as a subset of SGML, has the same security considerations as
+ specified in SGML Media Types [RFC1874]. Security considerations
+ that apply to IP, TCP and UDP also likely apply to BLOAT as it does
+ not attempt to correct for issues not related to message format.
+
+9. References
+
+ [JABBER] Miller, J., "Jabber", draft-miller-jabber-00.txt,
+ February 2002. (Work in Progress)
+
+ [RFC768] Postel, J., "User Datagram Protocol", STD 6, RFC 768,
+ August 1980.
+
+ [RFC791] Postel, J., "Internet Protocol", STD 5, RFC 791,
+ September 1981.
+
+ [RFC793] Postel, J., "Transmission Control Protocol", STD 7, RFC
+ 793, September 1981.
+
+ [RFC894] Hornig, C., "Standard for the Transmission of IP
+ Datagrams over Ethernet Networks.", RFC 894, April 1984.
+
+ [RFC1042] Postel, J. and J. Reynolds, "Standard for the
+ Transmission of IP Datagrams Over IEEE 802 Networks", STD
+ 43, RFC 1042, February 1988.
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts -
+ Application and Support", RFC 1123, October 1989.
+
+ [RFC1874] Levinson, E., "SGML Media Types", RFC 1874, December
+ 1995.
+
+ [RFC2003] Perkins, C., "IP Encapsulation within IP", RFC 2003,
+ October 1996.
+
+ [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message
+ Bodies", RFC 2045, November 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+
+
+
+
+Kennedy Informational [Page 14]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ [RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6
+ (IPv6) Specification", RFC 2460, December 1998.
+
+ [RFC3080] Rose, M., "The Blocks Extensible Exchange Protocol Core",
+ RFC 3080, March 2001.
+
+ [SOAP] Box, D., Ehnebuske, D., Kakivaya, G., Layman, A.,
+ Mendelsohn, N., Nielsen, H. F., Thatte, S. Winer, D.,
+ "Simple Object Access Protocol (SOAP) 1.1" World Wide Web
+ Consortium Note, May 2000 http://www.w3.org/TR/SOAP/
+
+ [XML] Bray, T., Paoli, J., Sperberg-McQueen, C. M., "Extensible
+ Markup Language (XML)" World Wide Web Consortium
+ Recommendation REC- xml-19980210.
+ http://www.w3.org/TR/1998/REC-xml-19980210
+
+10. Author's Address
+
+ Hugh Kennedy
+ Mimezine
+ 1060 West Addison
+ Chicago, IL 60613
+ USA
+
+ EMail: kennedyh@engin.umich.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 15]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+11. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 16]
+
diff --git a/tests/auto/network/access/qhttpnetworkconnection/.gitignore b/tests/auto/network/access/qhttpnetworkconnection/.gitignore
new file mode 100644
index 0000000000..4fe208868b
--- /dev/null
+++ b/tests/auto/network/access/qhttpnetworkconnection/.gitignore
@@ -0,0 +1 @@
+tst_qhttpnetworkconnection
diff --git a/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro b/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro
new file mode 100644
index 0000000000..1ce5d8a092
--- /dev/null
+++ b/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro
@@ -0,0 +1,13 @@
+load(qttest_p4)
+SOURCES += tst_qhttpnetworkconnection.cpp
+INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/zlib
+requires(contains(QT_CONFIG,private_tests))
+
+QT = core-private network-private
+
+symbian: TARGET.CAPABILITY = NetworkServices
+symbian: {
+ INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE
+}
+
+CONFIG+=insignificant_test # QTBUG-20981, crashes sometimes
diff --git a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
new file mode 100644
index 0000000000..2d30f6bca1
--- /dev/null
+++ b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
@@ -0,0 +1,1131 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include "private/qhttpnetworkconnection_p.h"
+#include "private/qnoncontiguousbytedevice_p.h"
+#include <QAuthenticator>
+
+#include "../../../network-settings.h"
+
+class tst_QHttpNetworkConnection: public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QHttpNetworkConnection();
+
+public Q_SLOTS:
+ void finishedReply();
+ void finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail);
+ void challenge401(const QHttpNetworkRequest &request, QAuthenticator *authenticator);
+#ifndef QT_NO_OPENSSL
+ void sslErrors(const QList<QSslError> &errors);
+#endif
+private:
+ bool finishedCalled;
+ bool finishedWithErrorCalled;
+ QNetworkReply::NetworkError netErrorCode;
+
+private Q_SLOTS:
+ void init();
+ void cleanup();
+ void initTestCase();
+ void cleanupTestCase();
+
+ void options_data();
+ void options();
+ void get_data();
+ void get();
+ void head_data();
+ void head();
+ void post_data();
+ void post();
+ void put_data();
+ void put();
+ void _delete_data();
+ void _delete();
+ void trace_data();
+ void trace();
+ void _connect_data();
+ void _connect();
+#ifndef QT_NO_COMPRESS
+ void compression_data();
+ void compression();
+#endif
+#ifndef QT_NO_OPENSSL
+ void ignoresslerror_data();
+ void ignoresslerror();
+#endif
+#ifdef QT_NO_OPENSSL
+ void nossl_data();
+ void nossl();
+#endif
+ void get401_data();
+ void get401();
+
+ void getMultiple_data();
+ void getMultiple();
+ void getMultipleWithPipeliningAndMultiplePriorities();
+ void getMultipleWithPriorities();
+
+ void getEmptyWithPipelining();
+
+ void getAndEverythingShouldBePipelined();
+
+ void getAndThenDeleteObject();
+ void getAndThenDeleteObject_data();
+};
+
+tst_QHttpNetworkConnection::tst_QHttpNetworkConnection()
+{
+ Q_SET_DEFAULT_IAP
+}
+
+void tst_QHttpNetworkConnection::initTestCase()
+{
+}
+
+void tst_QHttpNetworkConnection::cleanupTestCase()
+{
+}
+
+void tst_QHttpNetworkConnection::init()
+{
+}
+
+void tst_QHttpNetworkConnection::cleanup()
+{
+}
+
+void tst_QHttpNetworkConnection::options_data()
+{
+ // not tested yet
+}
+
+void tst_QHttpNetworkConnection::options()
+{
+ QEXPECT_FAIL("", "not tested yet", Continue);
+ QVERIFY(false);
+}
+
+void tst_QHttpNetworkConnection::head_data()
+{
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<int>("statusCode");
+ QTest::addColumn<QString>("statusString");
+ QTest::addColumn<int>("contentLength");
+
+ QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962;
+ QTest::newRow("success-external") << "http://" << "www.ietf.org" << "/rfc/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962;
+
+ QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1;
+ QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1;
+}
+
+void tst_QHttpNetworkConnection::head()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(int, statusCode);
+ QFETCH(QString, statusString);
+ QFETCH(int, contentLength);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+ QCOMPARE(connection.isSsl(), encrypt);
+
+ QHttpNetworkRequest request(protocol + host + path, QHttpNetworkRequest::Head);
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+
+ QTime stopWatch;
+ stopWatch.start();
+ do {
+ QCoreApplication::instance()->processEvents();
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ } while (!reply->isFinished());
+
+ QCOMPARE(reply->statusCode(), statusCode);
+ QCOMPARE(reply->reasonPhrase(), statusString);
+ // only check it if it is set and expected
+ if (reply->contentLength() != -1 && contentLength != -1)
+ QCOMPARE(reply->contentLength(), qint64(contentLength));
+
+ QVERIFY(reply->isFinished());
+
+ delete reply;
+}
+
+void tst_QHttpNetworkConnection::get_data()
+{
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<int>("statusCode");
+ QTest::addColumn<QString>("statusString");
+ QTest::addColumn<int>("contentLength");
+ QTest::addColumn<int>("downloadSize");
+
+ QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962;
+ QTest::newRow("success-external") << "http://" << "www.ietf.org" << "/rfc/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962;
+
+ QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1 << -1;
+ QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1 << -1;
+}
+
+void tst_QHttpNetworkConnection::get()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(int, statusCode);
+ QFETCH(QString, statusString);
+ QFETCH(int, contentLength);
+ QFETCH(int, downloadSize);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+ QCOMPARE(connection.isSsl(), encrypt);
+
+ QHttpNetworkRequest request(protocol + host + path);
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+
+ QTime stopWatch;
+ stopWatch.start();
+ forever {
+ QCoreApplication::instance()->processEvents();
+ if (reply->bytesAvailable())
+ break;
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ }
+
+ QCOMPARE(reply->statusCode(), statusCode);
+ QCOMPARE(reply->reasonPhrase(), statusString);
+ // only check it if it is set and expected
+ if (reply->contentLength() != -1 && contentLength != -1)
+ QCOMPARE(reply->contentLength(), qint64(contentLength));
+
+ stopWatch.start();
+ QByteArray ba;
+ do {
+ QCoreApplication::instance()->processEvents();
+ while (reply->bytesAvailable())
+ ba += reply->readAny();
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ } while (!reply->isFinished());
+
+ QVERIFY(reply->isFinished());
+ //do not require server generated error pages to be a fixed size
+ if (downloadSize != -1)
+ QCOMPARE(ba.size(), downloadSize);
+ //but check against content length if it was sent
+ if (reply->contentLength() != -1)
+ QCOMPARE(ba.size(), (int)reply->contentLength());
+
+ delete reply;
+}
+
+void tst_QHttpNetworkConnection::finishedReply()
+{
+ finishedCalled = true;
+}
+
+void tst_QHttpNetworkConnection::finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail)
+{
+ Q_UNUSED(detail)
+ finishedWithErrorCalled = true;
+ netErrorCode = errorCode;
+}
+
+void tst_QHttpNetworkConnection::put_data()
+{
+
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<QString>("data");
+ QTest::addColumn<bool>("succeed");
+
+ QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/dav/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<true;
+ QTest::newRow("fail-internal") << "http://" << QtNetworkSettings::serverName() << "/dav2/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<false;
+ QTest::newRow("fail-host") << "http://" << "fluke-nosuchhost.troll.no" << "/dav2/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<false;
+}
+
+void tst_QHttpNetworkConnection::put()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(QString, data);
+ QFETCH(bool, succeed);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+ QCOMPARE(connection.isSsl(), encrypt);
+
+ QHttpNetworkRequest request(protocol + host + path, QHttpNetworkRequest::Put);
+
+ QByteArray array = data.toLatin1();
+ QNonContiguousByteDevice *bd = QNonContiguousByteDeviceFactory::create(&array);
+ bd->setParent(this);
+ request.setUploadByteDevice(bd);
+
+ finishedCalled = false;
+ finishedWithErrorCalled = false;
+
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+ connect(reply, SIGNAL(finished()), SLOT(finishedReply()));
+ connect(reply, SIGNAL(finishedWithError(QNetworkReply::NetworkError, const QString &)),
+ SLOT(finishedWithError(QNetworkReply::NetworkError, const QString &)));
+
+ QTime stopWatch;
+ stopWatch.start();
+ do {
+ QCoreApplication::instance()->processEvents();
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ } while (!reply->isFinished() && !finishedCalled && !finishedWithErrorCalled);
+
+ if (reply->isFinished()) {
+ QByteArray ba;
+ while (reply->bytesAvailable())
+ ba += reply->readAny();
+ } else if(finishedWithErrorCalled) {
+ if(!succeed) {
+ delete reply;
+ return;
+ } else {
+ QFAIL("Error in PUT");
+ }
+ } else {
+ QFAIL("PUT timed out");
+ }
+
+ int status = reply->statusCode();
+ if (status != 200 && status != 201 && status != 204) {
+ if (succeed) {
+ qDebug()<<"PUT failed, Status Code:" <<status;
+ QFAIL("Error in PUT");
+ }
+ } else {
+ if (!succeed) {
+ qDebug()<<"PUT Should fail, Status Code:" <<status;
+ QFAIL("Error in PUT");
+ }
+ }
+ delete reply;
+}
+
+void tst_QHttpNetworkConnection::post_data()
+{
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<QString>("data");
+ QTest::addColumn<int>("statusCode");
+ QTest::addColumn<QString>("statusString");
+ QTest::addColumn<int>("contentLength");
+ QTest::addColumn<int>("downloadSize");
+
+ QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/cgi-bin/echo.cgi" << ushort(80) << false << "7 bytes" << 200 << "OK" << 7 << 7;
+ QTest::newRow("failure-internal") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << "Hello World" << 404 << "Not Found" << -1 << -1;
+}
+
+void tst_QHttpNetworkConnection::post()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(QString, data);
+ QFETCH(int, statusCode);
+ QFETCH(QString, statusString);
+ QFETCH(int, contentLength);
+ QFETCH(int, downloadSize);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+ QCOMPARE(connection.isSsl(), encrypt);
+
+ QHttpNetworkRequest request(protocol + host + path, QHttpNetworkRequest::Post);
+
+ QByteArray array = data.toLatin1();
+ QNonContiguousByteDevice *bd = QNonContiguousByteDeviceFactory::create(&array);
+ bd->setParent(this);
+ request.setUploadByteDevice(bd);
+
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+
+ QTime stopWatch;
+ stopWatch.start();
+ forever {
+ QCoreApplication::instance()->processEvents();
+ if (reply->bytesAvailable())
+ break;
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ }
+
+ QCOMPARE(reply->statusCode(), statusCode);
+ QCOMPARE(reply->reasonPhrase(), statusString);
+
+ qint64 cLen = reply->contentLength();
+ if (contentLength != -1) {
+ // only check the content length if test expected it to be set
+ if (cLen==-1) {
+ // HTTP 1.1 server may respond with chunked encoding and in that
+ // case contentLength is not present in reply -> verify that it is the case
+ QByteArray transferEnc = reply->headerField("Transfer-Encoding");
+ QCOMPARE(transferEnc, QByteArray("chunked"));
+ } else {
+ QCOMPARE(cLen, qint64(contentLength));
+ }
+ }
+
+ stopWatch.start();
+ QByteArray ba;
+ do {
+ QCoreApplication::instance()->processEvents();
+ while (reply->bytesAvailable())
+ ba += reply->readAny();
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ } while (!reply->isFinished());
+
+ QVERIFY(reply->isFinished());
+ //don't require fixed size for generated error pages
+ if (downloadSize != -1)
+ QCOMPARE(ba.size(), downloadSize);
+ //but do compare with content length if possible
+ if (cLen != -1)
+ QCOMPARE(ba.size(), (int)cLen);
+
+ delete reply;
+}
+
+void tst_QHttpNetworkConnection::_delete_data()
+{
+ // not tested yet
+}
+
+void tst_QHttpNetworkConnection::_delete()
+{
+ QEXPECT_FAIL("", "not tested yet", Continue);
+ QVERIFY(false);
+}
+
+void tst_QHttpNetworkConnection::trace_data()
+{
+ // not tested yet
+}
+
+void tst_QHttpNetworkConnection::trace()
+{
+ QEXPECT_FAIL("", "not tested yet", Continue);
+ QVERIFY(false);
+}
+
+void tst_QHttpNetworkConnection::_connect_data()
+{
+ // not tested yet
+}
+
+void tst_QHttpNetworkConnection::_connect()
+{
+ QEXPECT_FAIL("", "not tested yet", Continue);
+ QVERIFY(false);
+}
+
+void tst_QHttpNetworkConnection::challenge401(const QHttpNetworkRequest &request,
+ QAuthenticator *authenticator)
+{
+ Q_UNUSED(request)
+
+ QHttpNetworkReply *reply = qobject_cast<QHttpNetworkReply*>(sender());
+ if (reply) {
+ QHttpNetworkConnection *c = reply->connection();
+
+ QVariant val = c->property("setCredentials");
+ if (val.toBool()) {
+ QVariant user = c->property("username");
+ QVariant password = c->property("password");
+ authenticator->setUser(user.toString());
+ authenticator->setPassword(password.toString());
+ c->setProperty("setCredentials", false);
+ }
+ }
+}
+
+void tst_QHttpNetworkConnection::get401_data()
+{
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<bool>("setCredentials");
+ QTest::addColumn<QString>("username");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<int>("statusCode");
+
+ QTest::newRow("no-credentials") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << false << "" << ""<<401;
+ QTest::newRow("invalid-credentials") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << true << "test" << "test"<<401;
+ QTest::newRow("valid-credentials") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << true << "httptest" << "httptest"<<200;
+ QTest::newRow("digest-authentication-invalid") << "http://" << QtNetworkSettings::serverName() << "/qtest/auth-digest/index.html" << ushort(80) << false << true << "wrong" << "wrong"<<401;
+ QTest::newRow("digest-authentication-valid") << "http://" << QtNetworkSettings::serverName() << "/qtest/auth-digest/index.html" << ushort(80) << false << true << "httptest" << "httptest"<<200;
+}
+
+void tst_QHttpNetworkConnection::get401()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(bool, setCredentials);
+ QFETCH(QString, username);
+ QFETCH(QString, password);
+ QFETCH(int, statusCode);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+ QCOMPARE(connection.isSsl(), encrypt);
+ connection.setProperty("setCredentials", setCredentials);
+ connection.setProperty("username", username);
+ connection.setProperty("password", password);
+
+ QHttpNetworkRequest request(protocol + host + path);
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+ connect(reply, SIGNAL(authenticationRequired(const QHttpNetworkRequest&, QAuthenticator *)),
+ SLOT(challenge401(const QHttpNetworkRequest&, QAuthenticator *)));
+
+ finishedCalled = false;
+ finishedWithErrorCalled = false;
+
+ connect(reply, SIGNAL(finished()), SLOT(finishedReply()));
+ connect(reply, SIGNAL(finishedWithError(QNetworkReply::NetworkError, const QString &)),
+ SLOT(finishedWithError(QNetworkReply::NetworkError, const QString &)));
+
+ QTime stopWatch;
+ stopWatch.start();
+ forever {
+ QCoreApplication::instance()->processEvents();
+ if (finishedCalled)
+ break;
+ if (finishedWithErrorCalled)
+ break;
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ }
+ QCOMPARE(reply->statusCode(), statusCode);
+ delete reply;
+}
+
+#ifndef QT_NO_COMPRESS
+void tst_QHttpNetworkConnection::compression_data()
+{
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<int>("statusCode");
+ QTest::addColumn<QString>("statusString");
+ QTest::addColumn<int>("contentLength");
+ QTest::addColumn<int>("downloadSize");
+ QTest::addColumn<bool>("autoCompress");
+ QTest::addColumn<QString>("contentCoding");
+
+ QTest::newRow("success-autogzip-temp") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs/rfc2616.html" << ushort(80) << false << 200 << "OK" << -1 << 418321 << true << "";
+ QTest::newRow("success-nogzip-temp") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs/rfc2616.html" << ushort(80) << false << 200 << "OK" << 418321 << 418321 << false << "identity";
+ QTest::newRow("success-manualgzip-temp") << "http://" << QtNetworkSettings::serverName() << "/qtest/deflate/rfc2616.html" << ushort(80) << false << 200 << "OK" << 119124 << 119124 << false << "gzip";
+
+}
+
+void tst_QHttpNetworkConnection::compression()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(int, statusCode);
+ QFETCH(QString, statusString);
+ QFETCH(int, contentLength);
+ QFETCH(int, downloadSize);
+ QFETCH(bool, autoCompress);
+ QFETCH(QString, contentCoding);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+ QCOMPARE(connection.isSsl(), encrypt);
+
+ QHttpNetworkRequest request(protocol + host + path);
+ if (!autoCompress)
+ request.setHeaderField("Accept-Encoding", contentCoding.toLatin1());
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+ QTime stopWatch;
+ stopWatch.start();
+ forever {
+ QCoreApplication::instance()->processEvents();
+ if (reply->bytesAvailable())
+ break;
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ }
+
+ QCOMPARE(reply->statusCode(), statusCode);
+ QCOMPARE(reply->reasonPhrase(), statusString);
+ bool isLengthOk = (reply->contentLength() == qint64(contentLength)
+ || reply->contentLength() == qint64(downloadSize)
+ || reply->contentLength() == -1); //apache2 does not send content-length for compressed pages
+
+ QVERIFY(isLengthOk);
+
+ stopWatch.start();
+ QByteArray ba;
+ do {
+ QCoreApplication::instance()->processEvents();
+ while (reply->bytesAvailable())
+ ba += reply->readAny();
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ } while (!reply->isFinished());
+
+ QVERIFY(reply->isFinished());
+ QCOMPARE(ba.size(), downloadSize);
+
+ delete reply;
+}
+#endif
+
+#ifndef QT_NO_OPENSSL
+void tst_QHttpNetworkConnection::sslErrors(const QList<QSslError> &errors)
+{
+ Q_UNUSED(errors)
+
+ QHttpNetworkReply *reply = qobject_cast<QHttpNetworkReply*>(sender());
+ if (reply) {
+ QHttpNetworkConnection *connection = reply->connection();
+
+ QVariant val = connection->property("ignoreFromSignal");
+ if (val.toBool())
+ connection->ignoreSslErrors();
+ finishedWithErrorCalled = true;
+ }
+}
+
+void tst_QHttpNetworkConnection::ignoresslerror_data()
+{
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<bool>("ignoreInit");
+ QTest::addColumn<bool>("ignoreFromSignal");
+ QTest::addColumn<int>("statusCode");
+
+ // This test will work only if the website has ssl errors.
+ // fluke's certificate is signed by a non-standard authority.
+ // Since we don't introduce that CA into the SSL verification chain,
+ // connecting should fail.
+ QTest::newRow("success-init") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true << true << false << 200;
+ QTest::newRow("success-fromSignal") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true << false << true << 200;
+ QTest::newRow("failure") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true << false << false << 100;
+}
+
+void tst_QHttpNetworkConnection::ignoresslerror()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(bool, ignoreInit);
+ QFETCH(bool, ignoreFromSignal);
+ QFETCH(int, statusCode);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+ if (ignoreInit)
+ connection.ignoreSslErrors();
+ QCOMPARE(connection.isSsl(), encrypt);
+ connection.setProperty("ignoreFromSignal", ignoreFromSignal);
+
+ QHttpNetworkRequest request(protocol + host + path);
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+ connect(reply, SIGNAL(sslErrors(const QList<QSslError>&)),
+ SLOT(sslErrors(const QList<QSslError>&)));
+
+ finishedWithErrorCalled = false;
+
+ connect(reply, SIGNAL(finished()), SLOT(finishedReply()));
+
+ QTime stopWatch;
+ stopWatch.start();
+ forever {
+ QCoreApplication::instance()->processEvents();
+ if (reply->bytesAvailable())
+ break;
+ if (statusCode == 100 && finishedWithErrorCalled)
+ break;
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ }
+ QCOMPARE(reply->statusCode(), statusCode);
+ delete reply;
+}
+#endif
+
+#ifdef QT_NO_OPENSSL
+Q_DECLARE_METATYPE(QNetworkReply::NetworkError)
+void tst_QHttpNetworkConnection::nossl_data()
+{
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<QNetworkReply::NetworkError>("networkError");
+
+ QTest::newRow("protocol-error") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true <<QNetworkReply::ProtocolUnknownError;
+}
+
+void tst_QHttpNetworkConnection::nossl()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(QNetworkReply::NetworkError, networkError);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+
+ QHttpNetworkRequest request(protocol + host + path);
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+
+ finishedWithErrorCalled = false;
+ netErrorCode = QNetworkReply::NoError;
+
+ connect(reply, SIGNAL(finished()), SLOT(finishedReply()));
+ connect(reply, SIGNAL(finishedWithError(QNetworkReply::NetworkError, const QString &)),
+ SLOT(finishedWithError(QNetworkReply::NetworkError, const QString &)));
+
+ QTime stopWatch;
+ stopWatch.start();
+ forever {
+ QCoreApplication::instance()->processEvents();
+ if (finishedWithErrorCalled)
+ break;
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ }
+ QCOMPARE(netErrorCode, networkError);
+ delete reply;
+}
+#endif
+
+
+void tst_QHttpNetworkConnection::getMultiple_data()
+{
+ QTest::addColumn<quint16>("connectionCount");
+ QTest::addColumn<bool>("pipeliningAllowed");
+ // send 100 requests. apache will usually force-close after 100 requests in a single tcp connection
+ QTest::addColumn<int>("requestCount");
+
+ QTest::newRow("6 connections, no pipelining, 100 requests") << quint16(6) << false << 100;
+ QTest::newRow("1 connection, no pipelining, 100 requests") << quint16(1) << false << 100;
+ QTest::newRow("6 connections, pipelining allowed, 100 requests") << quint16(6) << true << 100;
+ QTest::newRow("1 connection, pipelining allowed, 100 requests") << quint16(1) << true << 100;
+}
+
+void tst_QHttpNetworkConnection::getMultiple()
+{
+ QFETCH(quint16, connectionCount);
+ QFETCH(bool, pipeliningAllowed);
+ QFETCH(int, requestCount);
+
+ QHttpNetworkConnection connection(connectionCount, QtNetworkSettings::serverName());
+
+ QList<QHttpNetworkRequest*> requests;
+ QList<QHttpNetworkReply*> replies;
+
+ for (int i = 0; i < requestCount; i++) {
+ // depending on what you use the results will vary.
+ // for the "real" results, use a URL that has "internet latency" for you. Then (6 connections, pipelining) will win.
+ // for LAN latency, you will possibly get that (1 connection, no pipelining) is the fastest
+ QHttpNetworkRequest *request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ // located in Berlin:
+ //QHttpNetworkRequest *request = new QHttpNetworkRequest(QUrl("http://klinsmann.nokia.trolltech.de/~berlin/qtcreatorad.gif"));
+ if (pipeliningAllowed)
+ request->setPipeliningAllowed(true);
+ requests.append(request);
+ QHttpNetworkReply *reply = connection.sendRequest(*request);
+ replies.append(reply);
+ }
+
+ QTime stopWatch;
+ stopWatch.start();
+ int finishedCount = 0;
+ do {
+ QCoreApplication::instance()->processEvents();
+ if (stopWatch.elapsed() >= 60000)
+ break;
+
+ finishedCount = 0;
+ for (int i = 0; i < replies.length(); i++)
+ if (replies.at(i)->isFinished())
+ finishedCount++;
+
+ } while (finishedCount != replies.length());
+
+ // redundant
+ for (int i = 0; i < replies.length(); i++)
+ QVERIFY(replies.at(i)->isFinished());
+
+ qDebug() << "===" << stopWatch.elapsed() << "msec ===";
+
+ qDeleteAll(requests);
+ qDeleteAll(replies);
+}
+
+void tst_QHttpNetworkConnection::getMultipleWithPipeliningAndMultiplePriorities()
+{
+ quint16 requestCount = 100;
+
+ // use 2 connections.
+ QHttpNetworkConnection connection(2, QtNetworkSettings::serverName());
+
+ QList<QHttpNetworkRequest*> requests;
+ QList<QHttpNetworkReply*> replies;
+
+ for (int i = 0; i < requestCount; i++) {
+ QHttpNetworkRequest *request = 0;
+ if (i % 3)
+ request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt", QHttpNetworkRequest::Get);
+ else
+ request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt", QHttpNetworkRequest::Head);
+
+ if (i % 2 || i % 3)
+ request->setPipeliningAllowed(true);
+
+ if (i % 3)
+ request->setPriority(QHttpNetworkRequest::HighPriority);
+ else if (i % 5)
+ request->setPriority(QHttpNetworkRequest::NormalPriority);
+ else if (i % 7)
+ request->setPriority(QHttpNetworkRequest::LowPriority);
+
+ requests.append(request);
+ QHttpNetworkReply *reply = connection.sendRequest(*request);
+ replies.append(reply);
+ }
+
+ QTime stopWatch;
+ stopWatch.start();
+ int finishedCount = 0;
+ do {
+ QCoreApplication::instance()->processEvents();
+ if (stopWatch.elapsed() >= 60000)
+ break;
+
+ finishedCount = 0;
+ for (int i = 0; i < replies.length(); i++)
+ if (replies.at(i)->isFinished())
+ finishedCount++;
+
+ } while (finishedCount != replies.length());
+
+ int pipelinedCount = 0;
+ for (int i = 0; i < replies.length(); i++) {
+ QVERIFY(replies.at(i)->isFinished());
+ QVERIFY (!(replies.at(i)->request().isPipeliningAllowed() == false
+ && replies.at(i)->isPipeliningUsed()));
+
+ if (replies.at(i)->isPipeliningUsed())
+ pipelinedCount++;
+ }
+
+ // We allow pipelining for every 2nd,3rd,4th,6th,8th,9th,10th etc request.
+ // Assume that half of the requests had been pipelined.
+ // (this is a very relaxed condition, when last measured 79 of 100
+ // requests had been pipelined)
+ QVERIFY(pipelinedCount >= requestCount / 2);
+
+ qDebug() << "===" << stopWatch.elapsed() << "msec ===";
+
+ qDeleteAll(requests);
+ qDeleteAll(replies);
+}
+
+class GetMultipleWithPrioritiesReceiver : public QObject
+{
+ Q_OBJECT
+public:
+ int highPrioReceived;
+ int lowPrioReceived;
+ int requestCount;
+ GetMultipleWithPrioritiesReceiver(int rq) : highPrioReceived(0), lowPrioReceived(0), requestCount(rq) { }
+public Q_SLOTS:
+ void finishedSlot() {
+ QHttpNetworkReply *reply = (QHttpNetworkReply*) sender();
+ if (reply->request().priority() == QHttpNetworkRequest::HighPriority)
+ highPrioReceived++;
+ else if (reply->request().priority() == QHttpNetworkRequest::LowPriority)
+ lowPrioReceived++;
+ else
+ QFAIL("Wrong priority!?");
+
+ QVERIFY(highPrioReceived + 7 >= lowPrioReceived);
+
+ if (highPrioReceived + lowPrioReceived == requestCount)
+ QTestEventLoop::instance().exitLoop();
+ }
+};
+
+void tst_QHttpNetworkConnection::getMultipleWithPriorities()
+{
+ quint16 requestCount = 100;
+ // use 2 connections.
+ QHttpNetworkConnection connection(2, QtNetworkSettings::serverName());
+ GetMultipleWithPrioritiesReceiver receiver(requestCount);
+ QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QList<QHttpNetworkRequest*> requests;
+ QList<QHttpNetworkReply*> replies;
+
+ for (int i = 0; i < requestCount; i++) {
+ QHttpNetworkRequest *request = 0;
+ if (i % 3)
+ request = new QHttpNetworkRequest(url, QHttpNetworkRequest::Get);
+ else
+ request = new QHttpNetworkRequest(url, QHttpNetworkRequest::Head);
+
+ if (i % 2)
+ request->setPriority(QHttpNetworkRequest::HighPriority);
+ else
+ request->setPriority(QHttpNetworkRequest::LowPriority);
+
+ requests.append(request);
+ QHttpNetworkReply *reply = connection.sendRequest(*request);
+ connect(reply, SIGNAL(finished()), &receiver, SLOT(finishedSlot()));
+ replies.append(reply);
+ }
+
+ QTestEventLoop::instance().enterLoop(40);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ qDeleteAll(requests);
+ qDeleteAll(replies);
+}
+
+
+class GetEmptyWithPipeliningReceiver : public QObject
+{
+ Q_OBJECT
+public:
+ int receivedCount;
+ int requestCount;
+ GetEmptyWithPipeliningReceiver(int rq) : receivedCount(0),requestCount(rq) { }
+public Q_SLOTS:
+ void finishedSlot() {
+ QHttpNetworkReply *reply = (QHttpNetworkReply*) sender();
+ Q_UNUSED(reply);
+ receivedCount++;
+
+ if (receivedCount == requestCount)
+ QTestEventLoop::instance().exitLoop();
+ }
+};
+
+void tst_QHttpNetworkConnection::getEmptyWithPipelining()
+{
+ quint16 requestCount = 50;
+ // use 2 connections.
+ QHttpNetworkConnection connection(2, QtNetworkSettings::serverName());
+ GetEmptyWithPipeliningReceiver receiver(requestCount);
+
+ QUrl url("http://" + QtNetworkSettings::serverName() + "/cgi-bin/echo.cgi"); // a get on this = getting an empty file
+ QList<QHttpNetworkRequest*> requests;
+ QList<QHttpNetworkReply*> replies;
+
+ for (int i = 0; i < requestCount; i++) {
+ QHttpNetworkRequest *request = 0;
+ request = new QHttpNetworkRequest(url, QHttpNetworkRequest::Get);
+ request->setPipeliningAllowed(true);
+
+ requests.append(request);
+ QHttpNetworkReply *reply = connection.sendRequest(*request);
+ connect(reply, SIGNAL(finished()), &receiver, SLOT(finishedSlot()));
+ replies.append(reply);
+ }
+
+ QTestEventLoop::instance().enterLoop(20);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ qDeleteAll(requests);
+ qDeleteAll(replies);
+}
+
+class GetAndEverythingShouldBePipelinedReceiver : public QObject
+{
+ Q_OBJECT
+public:
+ int receivedCount;
+ int requestCount;
+ GetAndEverythingShouldBePipelinedReceiver(int rq) : receivedCount(0),requestCount(rq) { }
+public Q_SLOTS:
+ void finishedSlot() {
+ QHttpNetworkReply *reply = (QHttpNetworkReply*) sender();
+ Q_UNUSED(reply);
+ receivedCount++;
+
+ if (receivedCount == requestCount)
+ QTestEventLoop::instance().exitLoop();
+ }
+};
+
+void tst_QHttpNetworkConnection::getAndEverythingShouldBePipelined()
+{
+ quint16 requestCount = 100;
+ // use 1 connection.
+ QHttpNetworkConnection connection(1, QtNetworkSettings::serverName());
+ QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QList<QHttpNetworkRequest*> requests;
+ QList<QHttpNetworkReply*> replies;
+
+ GetAndEverythingShouldBePipelinedReceiver receiver(requestCount);
+
+ for (int i = 0; i < requestCount; i++) {
+ QHttpNetworkRequest *request = 0;
+ request = new QHttpNetworkRequest(url, QHttpNetworkRequest::Get);
+ request->setPipeliningAllowed(true);
+ requests.append(request);
+ QHttpNetworkReply *reply = connection.sendRequest(*request);
+ connect(reply, SIGNAL(finished()), &receiver, SLOT(finishedSlot()));
+ replies.append(reply);
+ }
+ QTestEventLoop::instance().enterLoop(40);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ qDeleteAll(requests);
+ qDeleteAll(replies);
+
+}
+
+
+void tst_QHttpNetworkConnection::getAndThenDeleteObject_data()
+{
+ QTest::addColumn<bool>("replyFirst");
+
+ QTest::newRow("delete-reply-first") << true;
+ QTest::newRow("delete-connection-first") << false;
+}
+
+void tst_QHttpNetworkConnection::getAndThenDeleteObject()
+{
+ // yes, this will leak if the testcase fails. I don't care. It must not fail then :P
+ QHttpNetworkConnection *connection = new QHttpNetworkConnection(QtNetworkSettings::serverName());
+ QHttpNetworkRequest request("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile");
+ QHttpNetworkReply *reply = connection->sendRequest(request);
+ reply->setDownstreamLimited(true);
+
+ QTime stopWatch;
+ stopWatch.start();
+ forever {
+ QCoreApplication::instance()->processEvents();
+ if (reply->bytesAvailable())
+ break;
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ }
+
+ QVERIFY(reply->bytesAvailable());
+ QCOMPARE(reply->statusCode() ,200);
+ QVERIFY(!reply->isFinished()); // must not be finished
+
+ QFETCH(bool, replyFirst);
+
+ if (replyFirst) {
+ delete reply;
+ delete connection;
+ } else {
+ delete connection;
+ delete reply;
+ }
+}
+
+
+
+QTEST_MAIN(tst_QHttpNetworkConnection)
+#include "tst_qhttpnetworkconnection.moc"
diff --git a/tests/auto/network/access/qhttpnetworkreply/.gitignore b/tests/auto/network/access/qhttpnetworkreply/.gitignore
new file mode 100644
index 0000000000..fdd4e2be86
--- /dev/null
+++ b/tests/auto/network/access/qhttpnetworkreply/.gitignore
@@ -0,0 +1 @@
+tst_qhttpnetworkreply
diff --git a/tests/auto/network/access/qhttpnetworkreply/qhttpnetworkreply.pro b/tests/auto/network/access/qhttpnetworkreply/qhttpnetworkreply.pro
new file mode 100644
index 0000000000..8ce9f6f760
--- /dev/null
+++ b/tests/auto/network/access/qhttpnetworkreply/qhttpnetworkreply.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+SOURCES += tst_qhttpnetworkreply.cpp
+INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/zlib
+requires(contains(QT_CONFIG,private_tests))
+
+QT = core-private network-private
+symbian: TARGET.CAPABILITY = NetworkServices
diff --git a/tests/auto/network/access/qhttpnetworkreply/tst_qhttpnetworkreply.cpp b/tests/auto/network/access/qhttpnetworkreply/tst_qhttpnetworkreply.cpp
new file mode 100644
index 0000000000..513b20ec82
--- /dev/null
+++ b/tests/auto/network/access/qhttpnetworkreply/tst_qhttpnetworkreply.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include "private/qhttpnetworkconnection_p.h"
+
+class tst_QHttpNetworkReply: public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void init();
+ void cleanup();
+ void initTestCase();
+ void cleanupTestCase();
+
+ void parseHeader_data();
+ void parseHeader();
+};
+
+
+void tst_QHttpNetworkReply::initTestCase()
+{
+}
+
+void tst_QHttpNetworkReply::cleanupTestCase()
+{
+}
+
+void tst_QHttpNetworkReply::init()
+{
+}
+
+void tst_QHttpNetworkReply::cleanup()
+{
+}
+
+void tst_QHttpNetworkReply::parseHeader_data()
+{
+ QTest::addColumn<QByteArray>("headers");
+ QTest::addColumn<QStringList>("fields");
+ QTest::addColumn<QStringList>("values");
+
+ QTest::newRow("empty-field") << QByteArray("Set-Cookie: \r\n")
+ << (QStringList() << "Set-Cookie")
+ << (QStringList() << "");
+ QTest::newRow("single-field") << QByteArray("Content-Type: text/html; charset=utf-8\r\n")
+ << (QStringList() << "Content-Type")
+ << (QStringList() << "text/html; charset=utf-8");
+ QTest::newRow("single-field-continued") << QByteArray("Content-Type: text/html;\r\n"
+ " charset=utf-8\r\n")
+ << (QStringList() << "Content-Type")
+ << (QStringList() << "text/html; charset=utf-8");
+
+ QTest::newRow("multi-field") << QByteArray("Content-Type: text/html; charset=utf-8\r\n"
+ "Content-Length: 1024\r\n"
+ "Content-Encoding: gzip\r\n")
+ << (QStringList() << "Content-Type" << "Content-Length" << "Content-Encoding")
+ << (QStringList() << "text/html; charset=utf-8" << "1024" << "gzip");
+ QTest::newRow("multi-field-with-emtpy") << QByteArray("Content-Type: text/html; charset=utf-8\r\n"
+ "Content-Length: 1024\r\n"
+ "Set-Cookie: \r\n"
+ "Content-Encoding: gzip\r\n")
+ << (QStringList() << "Content-Type" << "Content-Length" << "Set-Cookie" << "Content-Encoding")
+ << (QStringList() << "text/html; charset=utf-8" << "1024" << "" << "gzip");
+
+ QTest::newRow("lws-field") << QByteArray("Content-Type: text/html; charset=utf-8\r\n"
+ "Content-Length:\r\n 1024\r\n"
+ "Content-Encoding: gzip\r\n")
+ << (QStringList() << "Content-Type" << "Content-Length" << "Content-Encoding")
+ << (QStringList() << "text/html; charset=utf-8" << "1024" << "gzip");
+
+ QTest::newRow("duplicated-field") << QByteArray("Vary: Accept-Language\r\n"
+ "Vary: Cookie\r\n"
+ "Vary: User-Agent\r\n")
+ << (QStringList() << "Vary")
+ << (QStringList() << "Accept-Language, Cookie, User-Agent");
+}
+
+void tst_QHttpNetworkReply::parseHeader()
+{
+ QFETCH(QByteArray, headers);
+ QFETCH(QStringList, fields);
+ QFETCH(QStringList, values);
+
+ QHttpNetworkReply reply;
+ reply.parseHeader(headers);
+ for (int i = 0; i < fields.count(); ++i) {
+ //qDebug() << "field" << fields.at(i) << "value" << reply.headerField(fields.at(i)) << "expected" << values.at(i);
+ QString field = reply.headerField(fields.at(i).toLatin1());
+ QCOMPARE(field, values.at(i));
+ }
+}
+
+QTEST_MAIN(tst_QHttpNetworkReply)
+#include "tst_qhttpnetworkreply.moc"
diff --git a/tests/auto/network/access/qnetworkaccessmanager/qnetworkaccessmanager.pro b/tests/auto/network/access/qnetworkaccessmanager/qnetworkaccessmanager.pro
new file mode 100644
index 0000000000..3ccbffbde8
--- /dev/null
+++ b/tests/auto/network/access/qnetworkaccessmanager/qnetworkaccessmanager.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+SOURCES += tst_qnetworkaccessmanager.cpp
+QT = core network
+
+symbian: TARGET.CAPABILITY = NetworkServices
+
diff --git a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
new file mode 100644
index 0000000000..14804b5187
--- /dev/null
+++ b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <QtNetwork/QNetworkAccessManager>
+#include <QtNetwork/QNetworkConfigurationManager>
+
+#include <QtCore/QDebug>
+
+Q_DECLARE_METATYPE(QNetworkAccessManager::NetworkAccessibility);
+
+class tst_QNetworkAccessManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QNetworkAccessManager();
+
+private slots:
+ void networkAccessible();
+};
+
+tst_QNetworkAccessManager::tst_QNetworkAccessManager()
+{
+}
+
+void tst_QNetworkAccessManager::networkAccessible()
+{
+ QNetworkAccessManager manager;
+
+ qRegisterMetaType<QNetworkAccessManager::NetworkAccessibility>("QNetworkAccessManager::NetworkAccessibility");
+
+ QSignalSpy spy(&manager,
+ SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)));
+
+ QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::UnknownAccessibility);
+
+ manager.setNetworkAccessible(QNetworkAccessManager::NotAccessible);
+
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(),
+ QNetworkAccessManager::NotAccessible);
+ QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::NotAccessible);
+
+ manager.setNetworkAccessible(QNetworkAccessManager::Accessible);
+
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(),
+ QNetworkAccessManager::UnknownAccessibility);
+ QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::UnknownAccessibility);
+
+ QNetworkConfigurationManager configManager;
+ QNetworkConfiguration defaultConfig = configManager.defaultConfiguration();
+ if (defaultConfig.isValid()) {
+ manager.setConfiguration(defaultConfig);
+
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(),
+ QNetworkAccessManager::Accessible);
+ QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::Accessible);
+
+ manager.setNetworkAccessible(QNetworkAccessManager::NotAccessible);
+
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(QNetworkAccessManager::NetworkAccessibility(spy.takeFirst().at(0).toInt()),
+ QNetworkAccessManager::NotAccessible);
+ QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::NotAccessible);
+ }
+}
+
+QTEST_MAIN(tst_QNetworkAccessManager)
+#include "tst_qnetworkaccessmanager.moc"
diff --git a/tests/auto/network/access/qnetworkcachemetadata/.gitignore b/tests/auto/network/access/qnetworkcachemetadata/.gitignore
new file mode 100644
index 0000000000..76f9e574b1
--- /dev/null
+++ b/tests/auto/network/access/qnetworkcachemetadata/.gitignore
@@ -0,0 +1 @@
+tst_qnetworkcachemetadata
diff --git a/tests/auto/network/access/qnetworkcachemetadata/qnetworkcachemetadata.pro b/tests/auto/network/access/qnetworkcachemetadata/qnetworkcachemetadata.pro
new file mode 100644
index 0000000000..ae0941e964
--- /dev/null
+++ b/tests/auto/network/access/qnetworkcachemetadata/qnetworkcachemetadata.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+QT -= gui
+QT += network
+SOURCES += tst_qnetworkcachemetadata.cpp
+
+symbian: TARGET.CAPABILITY = NetworkServices
+
diff --git a/tests/auto/network/access/qnetworkcachemetadata/tst_qnetworkcachemetadata.cpp b/tests/auto/network/access/qnetworkcachemetadata/tst_qnetworkcachemetadata.cpp
new file mode 100644
index 0000000000..a5b63bd7d5
--- /dev/null
+++ b/tests/auto/network/access/qnetworkcachemetadata/tst_qnetworkcachemetadata.cpp
@@ -0,0 +1,373 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qabstractnetworkcache.h>
+
+#define EXAMPLE_URL "http://user:pass@www.example.com/#foo"
+
+class tst_QNetworkCacheMetaData : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qnetworkcachemetadata_data();
+ void qnetworkcachemetadata();
+
+ void expirationDate_data();
+ void expirationDate();
+ void isValid_data();
+ void isValid();
+ void lastModified_data();
+ void lastModified();
+ void operatorEqual_data();
+ void operatorEqual();
+ void operatorEqualEqual_data();
+ void operatorEqualEqual();
+ void rawHeaders_data();
+ void rawHeaders();
+ void saveToDisk_data();
+ void saveToDisk();
+ void url_data();
+ void url();
+
+ void stream();
+};
+
+// Subclass that exposes the protected functions.
+class SubQNetworkCacheMetaData : public QNetworkCacheMetaData
+{
+public:};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QNetworkCacheMetaData::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QNetworkCacheMetaData::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QNetworkCacheMetaData::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QNetworkCacheMetaData::cleanup()
+{
+}
+
+void tst_QNetworkCacheMetaData::qnetworkcachemetadata_data()
+{
+}
+
+void tst_QNetworkCacheMetaData::qnetworkcachemetadata()
+{
+ QNetworkCacheMetaData data;
+ QCOMPARE(data.expirationDate(), QDateTime());
+ QCOMPARE(data.isValid(), false);
+ QCOMPARE(data.lastModified(), QDateTime());
+ QCOMPARE(data.operator!=(QNetworkCacheMetaData()), false);
+ QNetworkCacheMetaData metaData;
+ QCOMPARE(data.operator=(metaData), QNetworkCacheMetaData());
+ QCOMPARE(data.operator==(QNetworkCacheMetaData()), true);
+ QCOMPARE(data.rawHeaders(), QNetworkCacheMetaData::RawHeaderList());
+ QCOMPARE(data.saveToDisk(), true);
+ QCOMPARE(data.url(), QUrl());
+ data.setExpirationDate(QDateTime());
+ data.setLastModified(QDateTime());
+ data.setRawHeaders(QNetworkCacheMetaData::RawHeaderList());
+ data.setSaveToDisk(false);
+ data.setUrl(QUrl());
+}
+
+void tst_QNetworkCacheMetaData::expirationDate_data()
+{
+ QTest::addColumn<QDateTime>("expirationDate");
+ QTest::newRow("null") << QDateTime();
+ QTest::newRow("now") << QDateTime::currentDateTime();
+}
+
+// public QDateTime expirationDate() const
+void tst_QNetworkCacheMetaData::expirationDate()
+{
+ QFETCH(QDateTime, expirationDate);
+
+ SubQNetworkCacheMetaData data;
+
+ data.setExpirationDate(expirationDate);
+ QCOMPARE(data.expirationDate(), expirationDate);
+}
+
+Q_DECLARE_METATYPE(QNetworkCacheMetaData)
+void tst_QNetworkCacheMetaData::isValid_data()
+{
+ QTest::addColumn<QNetworkCacheMetaData>("data");
+ QTest::addColumn<bool>("isValid");
+
+ QNetworkCacheMetaData metaData;
+ QTest::newRow("null") << metaData << false;
+
+ QNetworkCacheMetaData data1;
+ data1.setUrl(QUrl(EXAMPLE_URL));
+ QTest::newRow("valid-1") << data1 << true;
+
+ QNetworkCacheMetaData data2;
+ QNetworkCacheMetaData::RawHeaderList headers;
+ headers.append(QNetworkCacheMetaData::RawHeader("foo", "Bar"));
+ data2.setRawHeaders(headers);
+ QTest::newRow("valid-2") << data2 << true;
+
+ QNetworkCacheMetaData data3;
+ data3.setLastModified(QDateTime::currentDateTime());
+ QTest::newRow("valid-3") << data3 << true;
+
+ QNetworkCacheMetaData data4;
+ data4.setExpirationDate(QDateTime::currentDateTime());
+ QTest::newRow("valid-4") << data4 << true;
+
+ QNetworkCacheMetaData data5;
+ data5.setSaveToDisk(false);
+ QTest::newRow("valid-5") << data5 << true;
+}
+
+// public bool isValid() const
+void tst_QNetworkCacheMetaData::isValid()
+{
+ QFETCH(QNetworkCacheMetaData, data);
+ QFETCH(bool, isValid);
+
+ QCOMPARE(data.isValid(), isValid);
+}
+
+void tst_QNetworkCacheMetaData::lastModified_data()
+{
+ QTest::addColumn<QDateTime>("lastModified");
+ QTest::newRow("null") << QDateTime();
+ QTest::newRow("now") << QDateTime::currentDateTime();
+}
+
+// public QDateTime lastModified() const
+void tst_QNetworkCacheMetaData::lastModified()
+{
+ QFETCH(QDateTime, lastModified);
+
+ SubQNetworkCacheMetaData data;
+
+ data.setLastModified(lastModified);
+ QCOMPARE(data.lastModified(), lastModified);
+}
+
+void tst_QNetworkCacheMetaData::operatorEqual_data()
+{
+ QTest::addColumn<QNetworkCacheMetaData>("other");
+ QTest::newRow("null") << QNetworkCacheMetaData();
+
+ QNetworkCacheMetaData data;
+ data.setUrl(QUrl(EXAMPLE_URL));
+ QNetworkCacheMetaData::RawHeaderList headers;
+ headers.append(QNetworkCacheMetaData::RawHeader("foo", "Bar"));
+ data.setRawHeaders(headers);
+ data.setLastModified(QDateTime::currentDateTime());
+ data.setExpirationDate(QDateTime::currentDateTime());
+ data.setSaveToDisk(false);
+ QTest::newRow("valid") << data;
+}
+
+// public QNetworkCacheMetaData& operator=(QNetworkCacheMetaData const& other)
+void tst_QNetworkCacheMetaData::operatorEqual()
+{
+ QFETCH(QNetworkCacheMetaData, other);
+
+ QNetworkCacheMetaData data = other;
+
+ QCOMPARE(data, other);
+}
+
+void tst_QNetworkCacheMetaData::operatorEqualEqual_data()
+{
+ QTest::addColumn<QNetworkCacheMetaData>("a");
+ QTest::addColumn<QNetworkCacheMetaData>("b");
+ QTest::addColumn<bool>("operatorEqualEqual");
+ QTest::newRow("null") << QNetworkCacheMetaData() << QNetworkCacheMetaData() << true;
+
+ QNetworkCacheMetaData data1;
+ data1.setUrl(QUrl(EXAMPLE_URL));
+ QTest::newRow("valid-1-1") << data1 << QNetworkCacheMetaData() << false;
+ QTest::newRow("valid-1-2") << data1 << data1 << true;
+
+ QNetworkCacheMetaData data2;
+ QNetworkCacheMetaData::RawHeaderList headers;
+ headers.append(QNetworkCacheMetaData::RawHeader("foo", "Bar"));
+ data2.setRawHeaders(headers);
+ QTest::newRow("valid-2-1") << data2 << QNetworkCacheMetaData() << false;
+ QTest::newRow("valid-2-2") << data2 << data2 << true;
+ QTest::newRow("valid-2-3") << data2 << data1 << false;
+
+ QNetworkCacheMetaData data3;
+ data3.setLastModified(QDateTime::currentDateTime());
+ QTest::newRow("valid-3-1") << data3 << QNetworkCacheMetaData() << false;
+ QTest::newRow("valid-3-2") << data3 << data3 << true;
+ QTest::newRow("valid-3-3") << data3 << data1 << false;
+ QTest::newRow("valid-3-4") << data3 << data2 << false;
+
+ QNetworkCacheMetaData data4;
+ data4.setExpirationDate(QDateTime::currentDateTime());
+ QTest::newRow("valid-4-1") << data4 << QNetworkCacheMetaData() << false;
+ QTest::newRow("valid-4-2") << data4 << data4 << true;
+ QTest::newRow("valid-4-3") << data4 << data1 << false;
+ QTest::newRow("valid-4-4") << data4 << data2 << false;
+ QTest::newRow("valid-4-5") << data4 << data3 << false;
+
+ QNetworkCacheMetaData data5;
+ data5.setSaveToDisk(false);
+ QTest::newRow("valid-5-1") << data5 << QNetworkCacheMetaData() << false;
+ QTest::newRow("valid-5-2") << data5 << data5 << true;
+ QTest::newRow("valid-5-3") << data5 << data1 << false;
+ QTest::newRow("valid-5-4") << data5 << data2 << false;
+ QTest::newRow("valid-5-5") << data5 << data3 << false;
+ QTest::newRow("valid-5-6") << data5 << data4 << false;
+}
+
+// public bool operator==(QNetworkCacheMetaData const& other) const
+void tst_QNetworkCacheMetaData::operatorEqualEqual()
+{
+ QFETCH(QNetworkCacheMetaData, a);
+ QFETCH(QNetworkCacheMetaData, b);
+ QFETCH(bool, operatorEqualEqual);
+
+ QCOMPARE(a == b, operatorEqualEqual);
+}
+
+Q_DECLARE_METATYPE(QNetworkCacheMetaData::RawHeaderList)
+void tst_QNetworkCacheMetaData::rawHeaders_data()
+{
+ QTest::addColumn<QNetworkCacheMetaData::RawHeaderList>("rawHeaders");
+ QTest::newRow("null") << QNetworkCacheMetaData::RawHeaderList();
+ QNetworkCacheMetaData::RawHeaderList headers;
+ headers.append(QNetworkCacheMetaData::RawHeader("foo", "Bar"));
+ QTest::newRow("valie") << headers;
+}
+
+// public QNetworkCacheMetaData::RawHeaderList rawHeaders() const
+void tst_QNetworkCacheMetaData::rawHeaders()
+{
+ QFETCH(QNetworkCacheMetaData::RawHeaderList, rawHeaders);
+
+ SubQNetworkCacheMetaData data;
+
+ data.setRawHeaders(rawHeaders);
+ QCOMPARE(data.rawHeaders(), rawHeaders);
+}
+
+void tst_QNetworkCacheMetaData::saveToDisk_data()
+{
+ QTest::addColumn<bool>("saveToDisk");
+ QTest::newRow("false") << false;
+ QTest::newRow("true") << true;
+}
+
+// public bool saveToDisk() const
+void tst_QNetworkCacheMetaData::saveToDisk()
+{
+ QFETCH(bool, saveToDisk);
+
+ SubQNetworkCacheMetaData data;
+
+ data.setSaveToDisk(saveToDisk);
+ QCOMPARE(data.saveToDisk(), saveToDisk);
+}
+
+void tst_QNetworkCacheMetaData::url_data()
+{
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<QUrl>("expected");
+ QTest::newRow("null") << QUrl() << QUrl();
+ QTest::newRow("valid") << QUrl(EXAMPLE_URL) << QUrl("http://user@www.example.com/");
+}
+
+// public QUrl url() const
+void tst_QNetworkCacheMetaData::url()
+{
+ QFETCH(QUrl, url);
+ QFETCH(QUrl, expected);
+
+ SubQNetworkCacheMetaData data;
+ data.setUrl(url);
+ QCOMPARE(data.url(), expected);
+}
+
+void tst_QNetworkCacheMetaData::stream()
+{
+ QNetworkCacheMetaData data;
+ data.setUrl(QUrl(EXAMPLE_URL));
+ QNetworkCacheMetaData::RawHeaderList headers;
+ headers.append(QNetworkCacheMetaData::RawHeader("foo", "Bar"));
+ data.setRawHeaders(headers);
+ data.setLastModified(QDateTime::currentDateTime());
+ data.setExpirationDate(QDateTime::currentDateTime());
+ data.setSaveToDisk(false);
+
+ QBuffer buffer;
+ buffer.open(QIODevice::ReadWrite);
+ QDataStream stream(&buffer);
+ stream << data;
+
+ buffer.seek(0);
+ QNetworkCacheMetaData data2;
+ stream >> data2;
+ QCOMPARE(data2, data);
+}
+
+QTEST_MAIN(tst_QNetworkCacheMetaData)
+#include "tst_qnetworkcachemetadata.moc"
+
diff --git a/tests/auto/network/access/qnetworkcookie/.gitignore b/tests/auto/network/access/qnetworkcookie/.gitignore
new file mode 100644
index 0000000000..90d1081d12
--- /dev/null
+++ b/tests/auto/network/access/qnetworkcookie/.gitignore
@@ -0,0 +1 @@
+tst_qnetworkcookie
diff --git a/tests/auto/network/access/qnetworkcookie/qnetworkcookie.pro b/tests/auto/network/access/qnetworkcookie/qnetworkcookie.pro
new file mode 100644
index 0000000000..2f31138daf
--- /dev/null
+++ b/tests/auto/network/access/qnetworkcookie/qnetworkcookie.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+SOURCES += tst_qnetworkcookie.cpp
+
+QT = core network
+symbian: TARGET.CAPABILITY = NetworkServices
diff --git a/tests/auto/network/access/qnetworkcookie/tst_qnetworkcookie.cpp b/tests/auto/network/access/qnetworkcookie/tst_qnetworkcookie.cpp
new file mode 100644
index 0000000000..a83f6dda91
--- /dev/null
+++ b/tests/auto/network/access/qnetworkcookie/tst_qnetworkcookie.cpp
@@ -0,0 +1,733 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtCore/QUrl>
+#include <QtNetwork/QNetworkCookie>
+
+
+class tst_QNetworkCookie: public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void getterSetter();
+
+ void parseSingleCookie_data();
+ void parseSingleCookie();
+
+ void parseMultipleCookies_data();
+ void parseMultipleCookies();
+};
+
+QT_BEGIN_NAMESPACE
+
+namespace QTest {
+ template<>
+ char *toString(const QNetworkCookie &cookie)
+ {
+ return qstrdup(cookie.toRawForm());
+ }
+
+ template<>
+ char *toString(const QList<QNetworkCookie> &list)
+ {
+ QString result = "QList(";
+ bool first = true;
+ foreach (QNetworkCookie cookie, list) {
+ if (!first)
+ result += ", ";
+ first = false;
+ result += QString::fromLatin1("QNetworkCookie(%1)").arg(QLatin1String(cookie.toRawForm()));
+ }
+
+ return qstrdup(result.append(')').toLocal8Bit());
+ }
+}
+
+QT_END_NAMESPACE
+
+void tst_QNetworkCookie::getterSetter()
+{
+ QNetworkCookie cookie;
+ QNetworkCookie otherCookie;
+
+ QVERIFY(cookie == otherCookie);
+ QCOMPARE(cookie, otherCookie);
+ QVERIFY(!(cookie != otherCookie));
+
+ QVERIFY(!cookie.isSecure());
+ QVERIFY(cookie.isSessionCookie());
+ QVERIFY(!cookie.expirationDate().isValid());
+ QVERIFY(cookie.domain().isEmpty());
+ QVERIFY(cookie.path().isEmpty());
+ QVERIFY(cookie.name().isEmpty());
+ QVERIFY(cookie.value().isEmpty());
+
+ // change something
+ cookie.setName("foo");
+ QVERIFY(!(cookie == otherCookie));
+ QVERIFY(cookie != otherCookie);
+
+ // test getters and setters:
+ QCOMPARE(cookie.name(), QByteArray("foo"));
+ cookie.setName(0);
+ QVERIFY(cookie.name().isEmpty());
+
+ cookie.setValue("bar");
+ QCOMPARE(cookie.value(), QByteArray("bar"));
+ cookie.setValue(0);
+ QVERIFY(cookie.value().isEmpty());
+
+ cookie.setPath("/");
+ QCOMPARE(cookie.path(), QString("/"));
+ cookie.setPath(QString());
+ QVERIFY(cookie.path().isEmpty());
+
+ cookie.setDomain(".tld");
+ QCOMPARE(cookie.domain(), QString(".tld"));
+ cookie.setDomain(QString());
+ QVERIFY(cookie.domain().isEmpty());
+
+ QDateTime now = QDateTime::currentDateTime();
+ cookie.setExpirationDate(now);
+ QCOMPARE(cookie.expirationDate(), now);
+ QVERIFY(!cookie.isSessionCookie());
+ cookie.setExpirationDate(QDateTime());
+ QVERIFY(!cookie.expirationDate().isValid());
+ QVERIFY(cookie.isSessionCookie());
+
+ cookie.setSecure(true);
+ QVERIFY(cookie.isSecure());
+ cookie.setSecure(false);
+ QVERIFY(!cookie.isSecure());
+
+ QVERIFY(cookie == otherCookie);
+}
+
+void tst_QNetworkCookie::parseSingleCookie_data()
+{
+ QTest::addColumn<QString>("cookieString");
+ QTest::addColumn<QNetworkCookie>("expectedCookie");
+
+ QNetworkCookie cookie;
+ cookie.setName("a");
+ QTest::newRow("basic") << "a=" << cookie;
+ QTest::newRow("basic2") << " a=" << cookie;
+ QTest::newRow("basic3") << "a= " << cookie;
+ QTest::newRow("basic4") << " a= " << cookie;
+ QTest::newRow("basic5") << " a= ;" << cookie;
+ QTest::newRow("basic6") << " a=; " << cookie;
+ QTest::newRow("basic7") << " a =" << cookie;
+ QTest::newRow("basic8") << " a = " << cookie;
+
+ cookie.setValue("b");
+ QTest::newRow("with-value") << "a=b" << cookie;
+ QTest::newRow("with-value2") << " a=b" << cookie;
+ QTest::newRow("with-value3") << "a=b " << cookie;
+ QTest::newRow("with-value4") << " a=b " << cookie;
+ QTest::newRow("with-value4") << " a=b ;" << cookie;
+ QTest::newRow("with-value5") << "a =b" << cookie;
+ QTest::newRow("with-value6") << "a= b" << cookie;
+ QTest::newRow("with-value7") << "a = b" << cookie;
+ QTest::newRow("with-value8") << "a = b " << cookie;
+
+ cookie.setValue("\",\"");
+ QTest::newRow("with-value-with-special1") << "a = \",\" " << cookie;
+ cookie.setValue("\";\"");
+ QTest::newRow("with-value-with-special2") << "a = \";\" " << cookie;
+ cookie.setValue("\" \"");
+ QTest::newRow("with-value-with-special3") << "a = \" \" " << cookie;
+ cookie.setValue("\"\\\"\"");
+ QTest::newRow("with-value-with-special4") << "a = \"\\\"\" " << cookie;
+ cookie.setValue("\"\\\"a, b; c\\\"\"");
+ QTest::newRow("with-value-with-special5") << "a = \"\\\"a, b; c\\\"\"" << cookie;
+
+ cookie.setValue("b c");
+ QTest::newRow("with-value-with-whitespace") << "a = b c" << cookie;
+
+ cookie.setValue("\"b\"");
+ QTest::newRow("quoted-value") << "a = \"b\"" << cookie;
+ cookie.setValue("\"b c\"");
+ QTest::newRow("quoted-value-with-whitespace") << "a = \"b c\"" << cookie;
+
+ cookie.setValue("b");
+ cookie.setSecure(true);
+ QTest::newRow("secure") << "a=b;secure" << cookie;
+ QTest::newRow("secure2") << "a=b;secure " << cookie;
+ QTest::newRow("secure3") << "a=b; secure" << cookie;
+ QTest::newRow("secure4") << "a=b; secure " << cookie;
+ QTest::newRow("secure5") << "a=b ;secure" << cookie;
+ QTest::newRow("secure6") << "a=b ;secure " << cookie;
+ QTest::newRow("secure7") << "a=b ; secure " << cookie;
+ QTest::newRow("secure8") << "a=b; Secure" << cookie;
+
+ cookie.setSecure(false);
+ cookie.setHttpOnly(true);
+ QTest::newRow("httponly") << "a=b;httponly" << cookie;
+ QTest::newRow("httponly2") << "a=b;HttpOnly " << cookie;
+ QTest::newRow("httponly3") << "a=b; httpOnly" << cookie;
+ QTest::newRow("httponly4") << "a=b; HttpOnly " << cookie;
+ QTest::newRow("httponly5") << "a=b ;HttpOnly" << cookie;
+ QTest::newRow("httponly6") << "a=b ;httponly " << cookie;
+ QTest::newRow("httponly7") << "a=b ; HttpOnly " << cookie;
+ QTest::newRow("httponly8") << "a=b; Httponly" << cookie;
+
+ cookie.setHttpOnly(false);
+ cookie.setPath("/");
+ QTest::newRow("path1") << "a=b;path=/" << cookie;
+ QTest::newRow("path2") << "a=b; path=/" << cookie;
+ QTest::newRow("path3") << "a=b;path=/ " << cookie;
+ QTest::newRow("path4") << "a=b;path =/ " << cookie;
+ QTest::newRow("path5") << "a=b;path= / " << cookie;
+ QTest::newRow("path6") << "a=b;path = / " << cookie;
+ QTest::newRow("path7") << "a=b;Path = / " << cookie;
+ QTest::newRow("path8") << "a=b; PATH = / " << cookie;
+
+ cookie.setPath("/foo");
+ QTest::newRow("path9") << "a=b;path=/foo" << cookie;
+
+ // some weird paths:
+ cookie.setPath("/with spaces");
+ QTest::newRow("path-with-spaces") << "a=b;path=/with%20spaces" << cookie;
+ QTest::newRow("path-with-spaces2") << "a=b; path=/with%20spaces " << cookie;
+ QTest::newRow("path-with-spaces3") << "a=b; path=\"/with spaces\"" << cookie;
+ QTest::newRow("path-with-spaces4") << "a=b; path = \"/with spaces\" " << cookie;
+
+ cookie.setPath("/with\"Quotes");
+ QTest::newRow("path-with-quotes") << "a=b; path = /with%22Quotes" << cookie;
+ QTest::newRow("path-with-quotes2") << "a=b; path = \"/with\\\"Quotes\"" << cookie;
+
+ cookie.setPath(QString::fromUtf8("/R\303\251sum\303\251"));
+ QTest::newRow("path-with-utf8") << "a=b;path=/R\303\251sum\303\251" << cookie;
+ QTest::newRow("path-with-utf8-2") << "a=b;path=/R%C3%A9sum%C3%A9" << cookie;
+
+ cookie.setPath(QString());
+ cookie.setDomain("qt.nokia.com");
+ QTest::newRow("plain-domain1") << "a=b;domain=qt.nokia.com" << cookie;
+ QTest::newRow("plain-domain2") << "a=b; domain=qt.nokia.com " << cookie;
+ QTest::newRow("plain-domain3") << "a=b;domain=QT.NOKIA.COM" << cookie;
+ QTest::newRow("plain-domain4") << "a=b;DOMAIN = QT.NOKIA.COM" << cookie;
+
+ cookie.setDomain(".qt.nokia.com");
+ QTest::newRow("dot-domain1") << "a=b;domain=.qt.nokia.com" << cookie;
+ QTest::newRow("dot-domain2") << "a=b; domain=.qt.nokia.com" << cookie;
+ QTest::newRow("dot-domain3") << "a=b; domain=.QT.NOKIA.COM" << cookie;
+ QTest::newRow("dot-domain4") << "a=b; Domain = .QT.NOKIA.COM" << cookie;
+
+ cookie.setDomain(QString::fromUtf8(".d\303\270gn\303\245pent.troll.no"));
+ QTest::newRow("idn-domain1") << "a=b;domain=.xn--dgnpent-gxa2o.troll.no" << cookie;
+ QTest::newRow("idn-domain2") << "a=b;domain=.d\303\270gn\303\245pent.troll.no" << cookie;
+ QTest::newRow("idn-domain3") << "a=b;domain=.XN--DGNPENT-GXA2O.TROLL.NO" << cookie;
+ QTest::newRow("idn-domain4") << "a=b;domain=.D\303\230GN\303\205PENT.troll.NO" << cookie;
+
+ cookie.setDomain(".qt.nokia.com");
+ cookie.setPath("/");
+ QTest::newRow("two-fields") << "a=b;domain=.qt.nokia.com;path=/" << cookie;
+ QTest::newRow("two-fields2") << "a=b; domain=.qt.nokia.com; path=/" << cookie;
+ QTest::newRow("two-fields3") << "a=b; domain=.qt.nokia.com ; path=/ " << cookie;
+ QTest::newRow("two-fields4") << "a=b;path=/; domain=.qt.nokia.com" << cookie;
+ QTest::newRow("two-fields5") << "a=b; path=/ ; domain=.qt.nokia.com" << cookie;
+ QTest::newRow("two-fields6") << "a=b; path= / ; domain =.qt.nokia.com" << cookie;
+
+ cookie.setSecure(true);
+ QTest::newRow("three-fields") << "a=b;domain=.qt.nokia.com;path=/;secure" << cookie;
+ QTest::newRow("three-fields2") << "a=b;secure;path=/;domain=.qt.nokia.com" << cookie;
+ QTest::newRow("three-fields3") << "a=b;secure;domain=.qt.nokia.com; path=/" << cookie;
+ QTest::newRow("three-fields4") << "a = b;secure;domain=.qt.nokia.com; path=/" << cookie;
+
+ cookie = QNetworkCookie();
+ cookie.setName("a");
+ cookie.setValue("b");
+ cookie.setExpirationDate(QDateTime(QDate(2012, 1, 29), QTime(23, 59, 59), Qt::UTC));
+ QTest::newRow("broken-expiration1") << "a=b; expires=Sun, 29-Jan-2012 23:59:59;" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1999, 11, 9), QTime(23, 12, 40), Qt::UTC));
+ QTest::newRow("expiration1") << "a=b;expires=Wednesday, 09-Nov-1999 23:12:40 GMT" << cookie;
+ QTest::newRow("expiration2") << "a=b;expires=Wed, 09-Nov-1999 23:12:40 GMT" << cookie;
+ QTest::newRow("expiration3") << "a=b; expires=Wednesday, 09-Nov-1999 23:12:40 GMT " << cookie;
+ QTest::newRow("expiration-utc") << "a=b;expires=Wednesday, 09-Nov-1999 23:12:40 UTC" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(3, 20, 0, 0), Qt::UTC));
+ QTest::newRow("time-0") << "a=b;expires=14 Apr 89 03:20" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(3, 20, 12, 0), Qt::UTC));
+ QTest::newRow("time-1") << "a=b;expires=14 Apr 89 03:20:12" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(3, 20, 12, 88), Qt::UTC));
+ QTest::newRow("time-2") << "a=b;expires=14 Apr 89 03:20:12.88" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(3, 20, 12, 88), Qt::UTC));
+ QTest::newRow("time-3") << "a=b;expires=14 Apr 89 03:20:12.88am" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(15, 20, 12, 88), Qt::UTC));
+ QTest::newRow("time-4") << "a=b;expires=14 Apr 89 03:20:12.88pm" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(3, 20, 12, 88), Qt::UTC));
+ QTest::newRow("time-5") << "a=b;expires=14 Apr 89 03:20:12.88 Am" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(15, 20, 12, 88), Qt::UTC));
+ QTest::newRow("time-6") << "a=b;expires=14 Apr 89 03:20:12.88 PM" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(15, 20, 12, 88), Qt::UTC));
+ QTest::newRow("time-7") << "a=b;expires=14 Apr 89 3:20:12.88 PM" << cookie;
+
+ // normal months
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(1, 1), Qt::UTC));
+ QTest::newRow("months-1") << "a=b;expires=Jan 1 89 1:1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 2, 1), QTime(1, 1), Qt::UTC));
+ QTest::newRow("months-2") << "a=b;expires=Feb 1 89 1:1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 3, 1), QTime(1, 1), Qt::UTC));
+ QTest::newRow("months-3") << "a=b;expires=mar 1 89 1:1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 4, 1), QTime(1, 1), Qt::UTC));
+ QTest::newRow("months-4") << "a=b;expires=Apr 1 89 1:1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 5, 1), QTime(1, 1), Qt::UTC));
+ QTest::newRow("months-5") << "a=b;expires=May 1 89 1:1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 6, 1), QTime(1, 1), Qt::UTC));
+ QTest::newRow("months-6") << "a=b;expires=Jun 1 89 1:1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 7, 1), QTime(1, 1), Qt::UTC));
+ QTest::newRow("months-7") << "a=b;expires=Jul 1 89 1:1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 8, 1), QTime(1, 1), Qt::UTC));
+ QTest::newRow("months-8") << "a=b;expires=Aug 1 89 1:1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 9, 1), QTime(1, 1), Qt::UTC));
+ QTest::newRow("months-9") << "a=b;expires=Sep 1 89 1:1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 10, 1), QTime(1, 1), Qt::UTC));
+ QTest::newRow("months-10") << "a=b;expires=Oct 1 89 1:1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 11, 1), QTime(1, 1), Qt::UTC));
+ QTest::newRow("months-11") << "a=b;expires=Nov 1 89 1:1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 12, 1), QTime(1, 1), Qt::UTC));
+ QTest::newRow("months-12") << "a=b;expires=Dec 1 89 1:1" << cookie;
+
+ // extra months
+ cookie.setExpirationDate(QDateTime(QDate(1989, 12, 1), QTime(1, 1), Qt::UTC));
+ QTest::newRow("months-13") << "a=b;expires=December 1 89 1:1" << cookie;
+ QTest::newRow("months-14") << "a=b;expires=1 89 1:1 Dec" << cookie;
+ //cookie.setExpirationDate(QDateTime());
+ //QTest::newRow("months-15") << "a=b;expires=1 89 1:1 De" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(2024, 2, 29), QTime(1, 1), Qt::UTC));
+ QTest::newRow("months-16") << "a=b;expires=2024 29 Feb 1:1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(2024, 2, 29), QTime(1, 1), Qt::UTC));
+ QTest::newRow("months-17") << "a=b;expires=Fri, 29-Feb-2024 01:01:00 GMT" << cookie;
+ QTest::newRow("months-18") << "a=b;expires=2024 29 Feb 1:1 GMT" << cookie;
+
+ // normal offsets
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-0") << "a=b;expires=Jan 1 89 8:0 PST" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-1") << "a=b;expires=Jan 1 89 8:0 PDT" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-2") << "a=b;expires=Jan 1 89 7:0 MST" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-3") << "a=b;expires=Jan 1 89 7:0 MDT" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-4") << "a=b;expires=Jan 1 89 6:0 CST" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-5") << "a=b;expires=Jan 1 89 6:0 CDT" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-6") << "a=b;expires=Jan 1 89 5:0 EST" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-7") << "a=b;expires=Jan 1 89 5:0 EDT" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-8") << "a=b;expires=Jan 1 89 4:0 AST" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-9") << "a=b;expires=Jan 1 89 3:0 NST" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-10") << "a=b;expires=Jan 1 89 0:0 GMT" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-11") << "a=b;expires=Jan 1 89 0:0 BST" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 2), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-12") << "a=b;expires=Jan 1 89 23:0 MET" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 2), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-13") << "a=b;expires=Jan 1 89 22:0 EET" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 2), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-14") << "a=b;expires=Jan 1 89 15:0 JST" << cookie;
+
+ // extra offsets
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 2), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-14") << "a=b;expires=Jan 1 89 15:0 JST+1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(1, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-15") << "a=b;expires=Jan 1 89 0:0 GMT+1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-15b") << "a=b;expires=Jan 1 89 1:0 GMT-1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(1, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-16") << "a=b;expires=Jan 1 89 0:0 GMT+01" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(1, 5), Qt::UTC));
+ QTest::newRow("zoneoffset-17") << "a=b;expires=Jan 1 89 0:0 GMT+0105" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-18") << "a=b;expires=Jan 1 89 0:0 GMT+015" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-19") << "a=b;expires=Jan 1 89 0:0 GM" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-19b") << "a=b;expires=Jan 1 89 0:0 GMT" << cookie;
+
+ // offsets from gmt
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(1, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-20") << "a=b;expires=Jan 1 89 0:0 +1" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(1, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-21") << "a=b;expires=Jan 1 89 0:0 +01" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(1, 1), Qt::UTC));
+ QTest::newRow("zoneoffset-22") << "a=b;expires=Jan 1 89 0:0 +0101" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("zoneoffset-23") << "a=b;expires=Jan 1 89 1:0 -1" << cookie;
+
+ // Y2k
+ cookie.setExpirationDate(QDateTime(QDate(2000, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("year-0") << "a=b;expires=Jan 1 00 0:0" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1970, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("year-1") << "a=b;expires=Jan 1 70 0:0" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1971, 1, 1), QTime(0, 0), Qt::UTC));
+ QTest::newRow("year-2") << "a=b;expires=Jan 1 71 0:0" << cookie;
+
+ // Day, month, year
+ cookie.setExpirationDate(QDateTime(QDate(2013, 1, 2), QTime(0, 0), Qt::UTC));
+ QTest::newRow("date-0") << "a=b;expires=Jan 2 13 0:0" << cookie;
+ QTest::newRow("date-1") << "a=b;expires=1-2-13 0:0" << cookie;
+ QTest::newRow("date-2") << "a=b;expires=1/2/13 0:0" << cookie;
+ QTest::newRow("date-3") << "a=b;expires=Jan 2 13 0:0" << cookie;
+ QTest::newRow("date-4") << "a=b;expires=Jan 2, 13 0:0" << cookie;
+ QTest::newRow("date-5") << "a=b;expires=1-2-13 0:0" << cookie;
+ QTest::newRow("date-6") << "a=b;expires=1/2/13 0:0" << cookie;
+
+ // Known Year, determine month and day
+ cookie.setExpirationDate(QDateTime(QDate(1995, 1, 13), QTime(0, 0), Qt::UTC));
+ QTest::newRow("knownyear-0") << "a=b;expires=13/1/95 0:0" << cookie;
+ QTest::newRow("knownyear-1") << "a=b;expires=95/13/1 0:0" << cookie;
+ QTest::newRow("knownyear-2") << "a=b;expires=1995/1/13 0:0" << cookie;
+ QTest::newRow("knownyear-3") << "a=b;expires=1995/13/1 0:0" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1995, 1, 2), QTime(0, 0), Qt::UTC));
+ QTest::newRow("knownyear-4") << "a=b;expires=1/2/95 0:0" << cookie;
+ QTest::newRow("knownyear-5") << "a=b;expires=95/1/2 0:0" << cookie;
+
+ // Known Year, Known day, determining month
+ cookie.setExpirationDate(QDateTime(QDate(1995, 1, 13), QTime(0, 0), Qt::UTC));
+ QTest::newRow("knownYD-0") << "a=b;expires=13/1/95 0:0" << cookie;
+ QTest::newRow("knownYD-1") << "a=b;expires=1/13/95 0:0" << cookie;
+ QTest::newRow("knownYD-2") << "a=b;expires=95/13/1 0:0" << cookie;
+ QTest::newRow("knownYD-3") << "a=b;expires=95/1/13 0:0" << cookie;
+
+ // Month comes before Year
+ cookie.setExpirationDate(QDateTime(QDate(2021, 03, 26), QTime(0, 0), Qt::UTC));
+ QTest::newRow("month-0") << "a=b;expires=26/03/21 0:0" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(2015, 12, 30), QTime(16, 25, 0, 0), Qt::UTC));
+ QTest::newRow("month-1") << "a=b;expires=wed 16:25pm December 2015 30" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(2031, 11, 11), QTime(16, 25, 0, 0), Qt::UTC));
+ QTest::newRow("month-2") << "a=b;expires=16:25 11 31 11" << cookie;
+
+ // The very ambiguous cases
+ // Matching Firefox's behavior of guessing month, day, year in those cases
+ cookie.setExpirationDate(QDateTime(QDate(2013, 10, 2), QTime(0, 0), Qt::UTC));
+ QTest::newRow("ambiguousd-0") << "a=b;expires=10/2/13 0:0" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(2013, 2, 10), QTime(0, 0), Qt::UTC));
+ QTest::newRow("ambiguousd-1") << "a=b;expires=2/10/13 0:0" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(2010, 2, 3), QTime(0, 0), Qt::UTC));
+ QTest::newRow("ambiguousd-2") << "a=b;expires=2/3/10 0:0" << cookie;
+
+ // FYI If you try these in Firefox it wont set a cookie for the following two string
+ // because 03 is turned into the year at which point it is expired
+ cookie.setExpirationDate(QDateTime(QDate(2003, 2, 10), QTime(0, 0), Qt::UTC));
+ QTest::newRow("ambiguousd-3") << "a=b;expires=2/10/3 0:0" << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(2003, 10, 2), QTime(0, 0), Qt::UTC));
+ QTest::newRow("ambiguousd-4") << "a=b;expires=10/2/3 0:0" << cookie;
+
+ // These are the cookies that firefox's source says it can parse
+ cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(3, 20, 0, 0), Qt::UTC));
+ QTest::newRow("firefox-0") << "a=b;expires=14 Apr 89 03:20" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(3, 20, 0, 0), Qt::UTC));
+ QTest::newRow("firefox-1") << "a=b;expires=14 Apr 89 03:20 GMT" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1989, 3, 17), QTime(4, 1, 33, 0), Qt::UTC));
+ QTest::newRow("firefox-2") << "a=b;expires=Fri, 17 Mar 89 4:01:33" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1989, 3, 17), QTime(4, 1, 0, 0), Qt::UTC));
+ QTest::newRow("firefox-3") << "a=b;expires=Fri, 17 Mar 89 4:01 GMT" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 16), QTime(16-8, 12, 0, 0), Qt::UTC));
+ QTest::newRow("firefox-4") << "a=b;expires=Mon Jan 16 16:12 PDT 1989" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1989, 1, 16), QTime(17, 42, 0, 0), Qt::UTC));
+ QTest::newRow("firefox-5") << "a=b;expires=Mon Jan 16 16:12 +0130 1989" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1992, 5, 6), QTime(16-9, 41, 0, 0), Qt::UTC));
+ QTest::newRow("firefox-6") << "a=b;expires=6 May 1992 16:41-JST (Wednesday)" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1993, 8, 22), QTime(10, 59, 12, 82), Qt::UTC));
+ QTest::newRow("firefox-7") << "a=b;expires=22-AUG-1993 10:59:12.82" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1993, 8, 22), QTime(22, 59, 0, 0), Qt::UTC));
+ QTest::newRow("firefox-8") << "a=b;expires=22-AUG-1993 10:59pm" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1993, 8, 22), QTime(12, 59, 0, 0), Qt::UTC));
+ QTest::newRow("firefox-9") << "a=b;expires=22-AUG-1993 12:59am" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1993, 8, 22), QTime(12, 59, 0, 0), Qt::UTC));
+ QTest::newRow("firefox-10") << "a=b;expires=22-AUG-1993 12:59 PM" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1995, 8, 4), QTime(15, 54, 0, 0), Qt::UTC));
+ QTest::newRow("firefox-11") << "a=b;expires=Friday, August 04, 1995 3:54 PM" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1995, 6, 21), QTime(16, 24, 34, 0), Qt::UTC));
+ QTest::newRow("firefox-12") << "a=b;expires=06/21/95 04:24:34 PM" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1995, 6, 20), QTime(21, 7, 0, 0), Qt::UTC));
+ QTest::newRow("firefox-13") << "a=b;expires=20/06/95 21:07" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1995, 6, 8), QTime(19-5, 32, 48, 0), Qt::UTC));
+ QTest::newRow("firefox-14") << "a=b;expires=95-06-08 19:32:48 EDT" << cookie;
+
+ // Edge cases caught by fuzzing
+ // These are about the default cause creates dates that don't exits
+ cookie.setExpirationDate(QDateTime(QDate(2030, 2, 25), QTime(1, 1, 0, 0), Qt::UTC));
+ QTest::newRow("fuzz-0") << "a=b; expires=30 -000002 1:1 25;" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(2031, 11, 20), QTime(1, 1, 0, 0), Qt::UTC));
+ QTest::newRow("fuzz-1") << "a=b; expires=31 11 20 1:1;" << cookie;
+
+ // April only has 30 days
+ cookie.setExpirationDate(QDateTime(QDate(2031, 4, 30), QTime(1, 1, 0, 0), Qt::UTC));
+ QTest::newRow("fuzz-2") << "a=b; expires=31 30 4 1:1" << cookie;
+
+ // 9 must be the month so 31 can't be the day
+ cookie.setExpirationDate(QDateTime(QDate(2031, 9, 21), QTime(1, 1, 0, 0), Qt::UTC));
+ QTest::newRow("fuzz-3") << "a=b; expires=31 21 9 1:1" << cookie;
+
+ // Year is known, then fallback to defaults of filling in month and day
+ cookie.setExpirationDate(QDateTime(QDate(2031, 11, 1), QTime(1, 1, 0, 0), Qt::UTC));
+ QTest::newRow("fuzz-4") << "a=b; expires=31 11 01 1:1" << cookie;
+
+ // 2 must be the month so 30 can't be the day
+ cookie.setExpirationDate(QDateTime(QDate(2030, 2, 20), QTime(1, 1, 0, 0), Qt::UTC));
+ QTest::newRow("fuzz-5") << "a=b; expires=30 02 20 1:1" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(2021, 12, 22), QTime(1, 1, 0, 0), Qt::UTC));
+ QTest::newRow("fuzz-6") << "a=b; expires=2021 12 22 1:1" << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(2029, 2, 23), QTime(1, 1, 0, 0), Qt::UTC));
+ QTest::newRow("fuzz-7") << "a=b; expires=29 23 Feb 1:1" << cookie;
+
+ // 11 and 6 don't have 31 days
+ cookie.setExpirationDate(QDateTime(QDate(2031, 11, 06), QTime(1, 1, 0, 0), Qt::UTC));
+ QTest::newRow("fuzz-8") << "a=b; expires=31 11 06 1:1" << cookie;
+
+ // two-digit years:
+ // from 70 until 99, we assume 20th century
+ cookie.setExpirationDate(QDateTime(QDate(1999, 11, 9), QTime(23, 12, 40), Qt::UTC));
+ QTest::newRow("expiration-2digit1") << "a=b; expires=Wednesday, 09-Nov-99 23:12:40 GMT " << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(1970, 1, 1), QTime(23, 12, 40), Qt::UTC));
+ QTest::newRow("expiration-2digit2") << "a=b; expires=Thursday, 01-Jan-70 23:12:40 GMT " << cookie;
+ // from 00 until 69, we assume 21st century
+ cookie.setExpirationDate(QDateTime(QDate(2000, 1, 1), QTime(23, 12, 40), Qt::UTC));
+ QTest::newRow("expiration-2digit3") << "a=b; expires=Saturday, 01-Jan-00 23:12:40 GMT " << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(2020, 1, 1), QTime(23, 12, 40), Qt::UTC));
+ QTest::newRow("expiration-2digit4") << "a=b; expires=Wednesday, 01-Jan-20 23:12:40 GMT " << cookie;
+ cookie.setExpirationDate(QDateTime(QDate(2069, 1, 1), QTime(23, 12, 40), Qt::UTC));
+ QTest::newRow("expiration-2digit5") << "a=b; expires=Wednesday, 01-Jan-69 23:12:40 GMT " << cookie;
+
+ cookie.setExpirationDate(QDateTime(QDate(1999, 11, 9), QTime(23, 12, 40), Qt::UTC));
+
+ cookie.setPath("/");
+ QTest::newRow("expires+path") << "a=b; expires=Wed, 09-Nov-1999 23:12:40 GMT; path=/" << cookie;
+ QTest::newRow("path+expires") << "a=b; path=/;expires=Wed, 09-Nov-1999 23:12:40 GMT " << cookie;
+
+ cookie.setDomain(".qt.nokia.com");
+ QTest::newRow("full") << "a=b; domain=.qt.nokia.com;expires=Wed, 09-Nov-1999 23:12:40 GMT;path=/" << cookie;
+ QTest::newRow("full2") << "a=b;path=/; expires=Wed, 09-Nov-1999 23:12:40 GMT ;domain=.qt.nokia.com" << cookie;
+
+ // cookies obtained from the network:
+ cookie = QNetworkCookie("__siteid", "1");
+ cookie.setPath("/");
+ cookie.setExpirationDate(QDateTime(QDate(9999, 12, 31), QTime(23, 59, 59), Qt::UTC));
+ QTest::newRow("network2") << "__siteid=1; expires=Fri, 31-Dec-9999 23:59:59 GMT; path=/" << cookie;
+
+ cookie = QNetworkCookie("YM.LC", "v=2&m=9993_262838_159_1558_1063_0_5649_4012_3776161073,9426_260205_549_1295_1336_0_5141_4738_3922731647,6733_258196_952_1364_643_0_3560_-1_0,3677_237633_1294_1294_19267_0_3244_29483_4102206176,1315_235149_1693_1541_941_0_3224_1691_1861378060,1858_214311_2100_1298_19538_0_2873_30900_716411652,6258_212007_2506_1285_1017_0_2868_3606_4288540264,3743_207884_2895_1362_2759_0_2545_7114_3388520216,2654_205253_3257_1297_1332_0_2504_4682_3048534803,1891_184881_3660_1291_19079_0_978_29178_2592538685&f=1&n=20&s=date&o=down&e=1196548712&b=Inbox&u=removed");
+ cookie.setPath("/");
+ cookie.setDomain("mail.yahoo.com");
+ QTest::newRow("network3") << "YM.LC=v=2&m=9993_262838_159_1558_1063_0_5649_4012_3776161073,9426_260205_549_1295_1336_0_5141_4738_3922731647,6733_258196_952_1364_643_0_3560_-1_0,3677_237633_1294_1294_19267_0_3244_29483_4102206176,1315_235149_1693_1541_941_0_3224_1691_1861378060,1858_214311_2100_1298_19538_0_2873_30900_716411652,6258_212007_2506_1285_1017_0_2868_3606_4288540264,3743_207884_2895_1362_2759_0_2545_7114_3388520216,2654_205253_3257_1297_1332_0_2504_4682_3048534803,1891_184881_3660_1291_19079_0_978_29178_2592538685&f=1&n=20&s=date&o=down&e=1196548712&b=Inbox&u=removed; path=/; domain=mail.yahoo.com" << cookie;
+
+ cookie = QNetworkCookie("__ac", "\"c2hhdXNtYW46U2FTYW80Wm8%3D\"");
+ cookie.setPath("/");
+ cookie.setExpirationDate(QDateTime(QDate(2008, 8, 30), QTime(20, 21, 49), Qt::UTC));
+ QTest::newRow("network4") << "__ac=\"c2hhdXNtYW46U2FTYW80Wm8%3D\"; Path=/; Expires=Sat, 30 Aug 2008 20:21:49 +0000" << cookie;
+
+ // linkedin.com sends cookies in quotes and expects the cookie in quotes
+ cookie = QNetworkCookie("leo_auth_token", "\"GST:UroVXaxYA3sVSkoVjMNH9bj4dZxVzK2yekgrAUxMfUsyLTNyPjoP60:1298974875:b675566ae32ab36d7a708c0efbf446a5c22b9fca\"");
+ cookie.setPath("/");
+ cookie.setExpirationDate(QDateTime(QDate(2011, 3, 1), QTime(10, 51, 14), Qt::UTC));
+ QTest::newRow("network5") << "leo_auth_token=\"GST:UroVXaxYA3sVSkoVjMNH9bj4dZxVzK2yekgrAUxMfUsyLTNyPjoP60:1298974875:b675566ae32ab36d7a708c0efbf446a5c22b9fca\"; Version=1; Max-Age=1799; Expires=Tue, 01-Mar-2011 10:51:14 GMT; Path=/" << cookie;
+
+
+}
+
+void tst_QNetworkCookie::parseSingleCookie()
+{
+ QFETCH(QString, cookieString);
+ QFETCH(QNetworkCookie, expectedCookie);
+
+ QList<QNetworkCookie> result = QNetworkCookie::parseCookies(cookieString.toLatin1());
+
+ //QEXPECT_FAIL("network2", "QDateTime parsing problem: the date is beyond year 8000", Abort);
+ QCOMPARE(result.count(), 1);
+ QEXPECT_FAIL("network3", "Cookie value contains commas, violating the HTTP spec", Abort);
+ QCOMPARE(result.at(0), expectedCookie);
+
+ result = QNetworkCookie::parseCookies(result.at(0).toRawForm());
+ QCOMPARE(result.count(), 1);
+
+ // Drop any millisecond information, if there's any
+ QDateTime dt = expectedCookie.expirationDate();
+ if (dt.isValid()) {
+ QTime t = dt.time();
+ dt.setTime(t.addMSecs(-t.msec()));
+ expectedCookie.setExpirationDate(dt);
+ }
+
+ QCOMPARE(result.at(0), expectedCookie);
+}
+
+void tst_QNetworkCookie::parseMultipleCookies_data()
+{
+ QTest::addColumn<QString>("cookieString");
+ QTest::addColumn<QList<QNetworkCookie> >("expectedCookies");
+
+ QList<QNetworkCookie> list;
+ QTest::newRow("empty") << "" << list;
+
+ // these are technically empty cookies:
+ QTest::newRow("invalid-01") << ";" << list;
+ QTest::newRow("invalid-02") << " " << list;
+ QTest::newRow("invalid-03") << " ," << list;
+ QTest::newRow("invalid-04") << ";;,, ; ; , , ; , ;" << list;
+
+ // these are really invalid:
+ // reason: malformed NAME=VALUE pair
+ QTest::newRow("invalid-05") << "foo" << list;
+ QTest::newRow("invalid-06") << "=b" << list;
+ QTest::newRow("invalid-09") << "foo,a=b" << list;
+ QTest::newRow("invalid-11") << ";path=/" << list;
+
+ // reason: malformed expiration date string
+ QTest::newRow("invalid-12") << "a=b;expires=" << list;
+ QTest::newRow("invalid-13") << "a=b;expires=foobar" << list;
+ QTest::newRow("invalid-14") << "a=b;expires=foobar, abc" << list;
+ QTest::newRow("invalid-15") << "a=b;expires=foobar, dd-mmm-yyyy hh:mm:ss GMT; path=/" << list;
+ QTest::newRow("invalid-16") << "a=b;expires=foobar, 32-Caz-1999 24:01:60 GMT; path=/" << list;
+
+ QNetworkCookie cookie;
+ cookie.setName("a");
+ list += cookie;
+ cookie.setName("c");
+ cookie.setValue("d");
+ list += cookie;
+ QTest::newRow("two-1") << "a=,c=d" << list;
+ QTest::newRow("two-2") << "a=, c=d" << list;
+ QTest::newRow("two-3") << "a= ,c=d" << list;
+ QTest::newRow("two-4") << "a= , c=d" << list;
+
+ list.clear();
+ list += cookie;
+ cookie.setName("a");
+ cookie.setValue(QByteArray());
+ list += cookie;
+ QTest::newRow("two-5") << "c=d,a=" << list;
+ QTest::newRow("two-6") << "c=d, a=" << list;
+ QTest::newRow("two-7") << "c=d , a=" << list;
+
+ cookie.setName("foo");
+ cookie.setValue("bar");
+ cookie.setPath("/");
+ list += cookie;
+ QTest::newRow("complex-1") << "c=d, a=, foo=bar; path=/" << list;
+
+ cookie.setName("baz");
+ cookie.setDomain(".qt.nokia.com");
+ list.prepend(cookie);
+ QTest::newRow("complex-2") << "baz=bar; path=/; domain=.qt.nokia.com, c=d,a=,foo=bar; path=/" << list;
+
+ // cookies obtained from the network:
+ cookie = QNetworkCookie("id", "51706646077999719");
+ cookie.setDomain(".bluestreak.com");
+ cookie.setPath("/");
+ cookie.setExpirationDate(QDateTime(QDate(2017, 12, 05), QTime(9, 11, 7), Qt::UTC));
+ list << cookie;
+ cookie.setName("bb");
+ cookie.setValue("\\\"K14144t\\\"_AAQ\\\"ototrK_A_ttot44AQ4KwoRQtoto|");
+ list << cookie;
+ cookie.setName("adv");
+ cookie.setValue(QByteArray());
+ list << cookie;
+ QTest::newRow("network1") << "id=51706646077999719 bb=\"K14144t\"_AAQ\"ototrK_A_ttot44AQ4KwoRQtoto| adv=; Domain=.bluestreak.com; expires=Tuesday 05-Dec-2017 09:11:07 GMT; path=/;" << list;
+
+ QNetworkCookie cookieA;
+ cookieA.setName("a");
+ cookieA.setValue("b");
+
+ QNetworkCookie cookieB;
+ cookieB.setName("c");
+ cookieB.setValue("d");
+
+ // NewLine
+ cookieA.setExpirationDate(QDateTime(QDate(2009, 3, 10), QTime(7, 0, 0, 0), Qt::UTC));
+ cookieB.setExpirationDate(QDateTime(QDate(2009, 3, 20), QTime(7, 0, 0, 0), Qt::UTC));
+ list = QList<QNetworkCookie>() << cookieA << cookieB;
+ QTest::newRow("real-0") << "a=b; expires=Tue Mar 10 07:00:00 2009 GMT\nc=d; expires=Fri Mar 20 07:00:00 2009 GMT" << list;
+ QTest::newRow("real-1") << "a=b; expires=Tue Mar 10 07:00:00 2009 GMT\n\nc=d; expires=Fri Mar 20 07:00:00 2009 GMT" << list;
+ QTest::newRow("real-2") << "a=b; expires=Mar 10 07:00:00 2009 GMT, Tue\nc=d; expires=Fri Mar 20 07:00:00 2009 GMT" << list;
+
+ // Match firefox's behavior
+ cookieA.setPath("/foo");
+ list = QList<QNetworkCookie>() << cookieA << cookieB;
+ QTest::newRow("real-3") << "a=b; expires=Mar 10 07:00:00 2009 GMT, Tue; path=/foo\nc=d; expires=Fri Mar 20 07:00:00 2009 GMT" << list;
+
+ // do not accept cookies with non-alphanumeric characters in domain field (QTBUG-11029)
+ cookie = QNetworkCookie("NonAlphNumDomName", "NonAlphNumDomValue");
+ cookie.setDomain("!@#$%^&*();:."); // the ';' is actually problematic, because it is a separator
+ list = QList<QNetworkCookie>();
+ QTest::newRow("domain-non-alpha-numeric") << "NonAlphNumDomName=NonAlphNumDomValue; domain=!@#$%^&*()" << list;
+ QTest::newRow("expiration-3digit1") << "a=b; expires=123" << list; // used to ASSERT
+}
+
+void tst_QNetworkCookie::parseMultipleCookies()
+{
+ QFETCH(QString, cookieString);
+ QFETCH(QList<QNetworkCookie>, expectedCookies);
+
+ QList<QNetworkCookie> result = QNetworkCookie::parseCookies(cookieString.toLatin1());
+
+ QEXPECT_FAIL("network1", "Apparently multiple cookies set in one request (and an invalid date)", Abort);
+ QCOMPARE(result, expectedCookies);
+}
+
+QTEST_MAIN(tst_QNetworkCookie)
+#include "tst_qnetworkcookie.moc"
diff --git a/tests/auto/network/access/qnetworkcookiejar/.gitignore b/tests/auto/network/access/qnetworkcookiejar/.gitignore
new file mode 100644
index 0000000000..918754a274
--- /dev/null
+++ b/tests/auto/network/access/qnetworkcookiejar/.gitignore
@@ -0,0 +1 @@
+tst_qnetworkcookiejar
diff --git a/tests/auto/network/access/qnetworkcookiejar/qnetworkcookiejar.pro b/tests/auto/network/access/qnetworkcookiejar/qnetworkcookiejar.pro
new file mode 100644
index 0000000000..4e5f01745a
--- /dev/null
+++ b/tests/auto/network/access/qnetworkcookiejar/qnetworkcookiejar.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+SOURCES += tst_qnetworkcookiejar.cpp
+
+QT = core core-private network network-private
+symbian: TARGET.CAPABILITY = NetworkServices
diff --git a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp
new file mode 100644
index 0000000000..1b4256bb00
--- /dev/null
+++ b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp
@@ -0,0 +1,446 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtNetwork/QNetworkCookieJar>
+#include "private/qtldurl_p.h"
+
+class tst_QNetworkCookieJar: public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void getterSetter();
+ void setCookiesFromUrl_data();
+ void setCookiesFromUrl();
+ void cookiesForUrl_data();
+ void cookiesForUrl();
+ void effectiveTLDs_data();
+ void effectiveTLDs();
+};
+
+QT_BEGIN_NAMESPACE
+
+namespace QTest {
+ template<>
+ char *toString(const QNetworkCookie &cookie)
+ {
+ return qstrdup(cookie.toRawForm());
+ }
+
+ template<>
+ char *toString(const QList<QNetworkCookie> &list)
+ {
+ QString result = "QList(";
+ bool first = true;
+ foreach (QNetworkCookie cookie, list) {
+ if (!first)
+ result += ", ";
+ first = false;
+ result += QString::fromLatin1("QNetworkCookie(%1)").arg(QLatin1String(cookie.toRawForm()));
+ }
+
+ return qstrdup(result.append(')').toLocal8Bit());
+ }
+}
+
+QT_END_NAMESPACE
+
+class MyCookieJar: public QNetworkCookieJar
+{
+public:
+ inline QList<QNetworkCookie> allCookies() const
+ { return QNetworkCookieJar::allCookies(); }
+ inline void setAllCookies(const QList<QNetworkCookie> &cookieList)
+ { QNetworkCookieJar::setAllCookies(cookieList); }
+};
+
+void tst_QNetworkCookieJar::getterSetter()
+{
+ MyCookieJar jar;
+
+ QVERIFY(jar.allCookies().isEmpty());
+
+ QList<QNetworkCookie> list;
+ QNetworkCookie cookie;
+ cookie.setName("a");
+ list << cookie;
+
+ jar.setAllCookies(list);
+ QCOMPARE(jar.allCookies(), list);
+}
+
+void tst_QNetworkCookieJar::setCookiesFromUrl_data()
+{
+ QTest::addColumn<QList<QNetworkCookie> >("preset");
+ QTest::addColumn<QNetworkCookie>("newCookie");
+ QTest::addColumn<QString>("referenceUrl");
+ QTest::addColumn<QList<QNetworkCookie> >("expectedResult");
+ QTest::addColumn<bool>("setCookies");
+
+ QList<QNetworkCookie> preset;
+ QList<QNetworkCookie> result;
+ QNetworkCookie cookie;
+
+ cookie.setName("a");
+ cookie.setPath("/");
+ cookie.setDomain(".foo.tld");
+ result += cookie;
+ QTest::newRow("just-add") << preset << cookie << "http://www.foo.tld" << result << true;
+
+ preset = result;
+ QTest::newRow("replace-1") << preset << cookie << "http://www.foo.tld" << result << true;
+
+ cookie.setValue("bc");
+ result.clear();
+ result += cookie;
+ QTest::newRow("replace-2") << preset << cookie << "http://www.foo.tld" << result << true;
+
+ preset = result;
+ cookie.setName("d");
+ result += cookie;
+ QTest::newRow("append") << preset << cookie << "http://www.foo.tld" << result << true;
+
+ cookie = preset.at(0);
+ result = preset;
+ cookie.setPath("/something");
+ result += cookie;
+ QTest::newRow("diff-path") << preset << cookie << "http://www.foo.tld/something" << result << true;
+
+ preset.clear();
+ preset += cookie;
+ cookie.setPath("/");
+ QTest::newRow("diff-path-order") << preset << cookie << "http://www.foo.tld" << result << true;
+
+ preset.clear();
+ result.clear();
+ QNetworkCookie finalCookie = cookie;
+ cookie.setDomain("foo.tld");
+ finalCookie.setDomain(".foo.tld");
+ result += finalCookie;
+ QTest::newRow("should-add-dot-prefix") << preset << cookie << "http://www.foo.tld" << result << true;
+
+ result.clear();
+ cookie.setDomain("");
+ finalCookie.setDomain("www.foo.tld");
+ result += finalCookie;
+ QTest::newRow("should-set-default-domain") << preset << cookie << "http://www.foo.tld" << result << true;
+
+ // security test:
+ result.clear();
+ preset.clear();
+ cookie.setDomain("something.completely.different");
+ QTest::newRow("security-domain-1") << preset << cookie << "http://www.foo.tld" << result << false;
+
+ // we want the cookie to be accepted although the path does not match, see QTBUG-5815
+ cookie.setDomain(".foo.tld");
+ cookie.setPath("/something");
+ result += cookie;
+ QTest::newRow("security-path-1") << preset << cookie << "http://www.foo.tld" << result << true;
+
+ // check effective TLDs
+ // 1. co.uk is an effective TLD, should be denied
+ result.clear();
+ preset.clear();
+ cookie.setPath("/");
+ cookie.setDomain(".co.uk");
+ QTest::newRow("effective-tld1-denied") << preset << cookie << "http://something.co.uk" << result << false;
+ cookie.setDomain("co.uk");
+ QTest::newRow("effective-tld1-denied2") << preset << cookie << "http://something.co.uk" << result << false;
+ cookie.setDomain(".something.co.uk");
+ result += cookie;
+ QTest::newRow("effective-tld1-accepted") << preset << cookie << "http://something.co.uk" << result << true;
+
+ // 2. anything .ar is an effective TLD ('*.ar'), but 'gobiernoelectronico.ar' is an exception
+ result.clear();
+ preset.clear();
+ cookie.setDomain(".farmacia.ar");
+ QTest::newRow("effective-tld2-denied") << preset << cookie << "http://farmacia.ar" << result << false;
+ QTest::newRow("effective-tld2-denied2") << preset << cookie << "http://www.farmacia.ar" << result << false;
+ QTest::newRow("effective-tld2-denied3") << preset << cookie << "http://www.anything.farmacia.ar" << result << false;
+ cookie.setDomain(".gobiernoelectronico.ar");
+ result += cookie;
+ QTest::newRow("effective-tld2-accepted") << preset << cookie << "http://www.gobiernoelectronico.ar" << result << true;
+
+
+ // setting the defaults:
+ finalCookie = cookie;
+ finalCookie.setPath("/something/");
+ finalCookie.setDomain("www.foo.tld");
+ cookie.setPath("");
+ cookie.setDomain("");
+ result.clear();
+ result += finalCookie;
+ QTest::newRow("defaults-1") << preset << cookie << "http://www.foo.tld/something/" << result << true;
+
+ finalCookie.setPath("/");
+ result.clear();
+ result += finalCookie;
+ QTest::newRow("defaults-2") << preset << cookie << "http://www.foo.tld" << result << true;
+
+ // security test: do not accept cookie domains like ".com" nor ".com." (see RFC 2109 section 4.3.2)
+ result.clear();
+ preset.clear();
+ cookie.setDomain(".com");
+ QTest::newRow("rfc2109-4.3.2-ex3") << preset << cookie << "http://x.foo.com" << result << false;
+
+ result.clear();
+ preset.clear();
+ cookie.setDomain(".com.");
+ QTest::newRow("rfc2109-4.3.2-ex3-2") << preset << cookie << "http://x.foo.com" << result << false;
+}
+
+void tst_QNetworkCookieJar::setCookiesFromUrl()
+{
+ QFETCH(QList<QNetworkCookie>, preset);
+ QFETCH(QNetworkCookie, newCookie);
+ QFETCH(QString, referenceUrl);
+ QFETCH(QList<QNetworkCookie>, expectedResult);
+ QFETCH(bool, setCookies);
+
+ QList<QNetworkCookie> cookieList;
+ cookieList += newCookie;
+ MyCookieJar jar;
+ jar.setAllCookies(preset);
+ QCOMPARE(jar.setCookiesFromUrl(cookieList, referenceUrl), setCookies);
+
+ QList<QNetworkCookie> result = jar.allCookies();
+ foreach (QNetworkCookie cookie, expectedResult) {
+ QVERIFY2(result.contains(cookie), cookie.toRawForm());
+ result.removeAll(cookie);
+ }
+ QVERIFY2(result.isEmpty(), QTest::toString(result));
+}
+
+void tst_QNetworkCookieJar::cookiesForUrl_data()
+{
+ QTest::addColumn<QList<QNetworkCookie> >("allCookies");
+ QTest::addColumn<QString>("url");
+ QTest::addColumn<QList<QNetworkCookie> >("expectedResult");
+
+ QList<QNetworkCookie> allCookies;
+ QList<QNetworkCookie> result;
+
+ QTest::newRow("no-cookies") << allCookies << "http://foo.bar/" << result;
+
+ QNetworkCookie cookie;
+ cookie.setName("a");
+ cookie.setPath("/web");
+ cookie.setDomain(".nokia.com");
+ allCookies += cookie;
+
+ QTest::newRow("no-match-1") << allCookies << "http://foo.bar/" << result;
+ QTest::newRow("no-match-2") << allCookies << "http://foo.bar/web" << result;
+ QTest::newRow("no-match-3") << allCookies << "http://foo.bar/web/wiki" << result;
+ QTest::newRow("no-match-4") << allCookies << "http://nokia.com" << result;
+ QTest::newRow("no-match-5") << allCookies << "http://qt.nokia.com" << result;
+ QTest::newRow("no-match-6") << allCookies << "http://nokia.com/webinar" << result;
+ QTest::newRow("no-match-7") << allCookies << "http://qt.nokia.com/webinar" << result;
+
+ result = allCookies;
+ QTest::newRow("match-1") << allCookies << "http://nokia.com/web" << result;
+ QTest::newRow("match-2") << allCookies << "http://nokia.com/web/" << result;
+ QTest::newRow("match-3") << allCookies << "http://nokia.com/web/content" << result;
+ QTest::newRow("match-4") << allCookies << "http://qt.nokia.com/web" << result;
+ QTest::newRow("match-4") << allCookies << "http://qt.nokia.com/web/" << result;
+ QTest::newRow("match-6") << allCookies << "http://qt.nokia.com/web/content" << result;
+
+ cookie.setPath("/web/wiki");
+ allCookies += cookie;
+
+ // exact same results as before:
+ QTest::newRow("one-match-1") << allCookies << "http://nokia.com/web" << result;
+ QTest::newRow("one-match-2") << allCookies << "http://nokia.com/web/" << result;
+ QTest::newRow("one-match-3") << allCookies << "http://nokia.com/web/content" << result;
+ QTest::newRow("one-match-4") << allCookies << "http://qt.nokia.com/web" << result;
+ QTest::newRow("one-match-4") << allCookies << "http://qt.nokia.com/web/" << result;
+ QTest::newRow("one-match-6") << allCookies << "http://qt.nokia.com/web/content" << result;
+
+ result.prepend(cookie); // longer path, it must match first
+ QTest::newRow("two-matches-1") << allCookies << "http://nokia.com/web/wiki" << result;
+ QTest::newRow("two-matches-2") << allCookies << "http://qt.nokia.com/web/wiki" << result;
+
+ // invert the order;
+ allCookies.clear();
+ allCookies << result.at(1) << result.at(0);
+ QTest::newRow("two-matches-3") << allCookies << "http://nokia.com/web/wiki" << result;
+ QTest::newRow("two-matches-4") << allCookies << "http://qt.nokia.com/web/wiki" << result;
+
+ // expired cookie
+ allCookies.clear();
+ cookie.setExpirationDate(QDateTime::fromString("09-Nov-1999", "dd-MMM-yyyy"));
+ allCookies += cookie;
+ result.clear();
+ QTest::newRow("exp-match-1") << allCookies << "http://nokia.com/web" << result;
+ QTest::newRow("exp-match-2") << allCookies << "http://nokia.com/web/" << result;
+ QTest::newRow("exp-match-3") << allCookies << "http://nokia.com/web/content" << result;
+ QTest::newRow("exp-match-4") << allCookies << "http://qt.nokia.com/web" << result;
+ QTest::newRow("exp-match-4") << allCookies << "http://qt.nokia.com/web/" << result;
+ QTest::newRow("exp-match-6") << allCookies << "http://qt.nokia.com/web/content" << result;
+
+ // path matching
+ allCookies.clear();
+ QNetworkCookie anotherCookie;
+ anotherCookie.setName("a");
+ anotherCookie.setPath("/web");
+ anotherCookie.setDomain(".nokia.com");
+ allCookies += anotherCookie;
+ result.clear();
+ QTest::newRow("path-unmatch-1") << allCookies << "http://nokia.com/" << result;
+ QTest::newRow("path-unmatch-2") << allCookies << "http://nokia.com/something/else" << result;
+ result += anotherCookie;
+ QTest::newRow("path-match-1") << allCookies << "http://nokia.com/web" << result;
+ QTest::newRow("path-match-2") << allCookies << "http://nokia.com/web/" << result;
+ QTest::newRow("path-match-3") << allCookies << "http://nokia.com/web/content" << result;
+
+ // secure cookies
+ allCookies.clear();
+ result.clear();
+ QNetworkCookie secureCookie;
+ secureCookie.setName("a");
+ secureCookie.setPath("/web");
+ secureCookie.setDomain(".nokia.com");
+ secureCookie.setSecure(true);
+ allCookies += secureCookie;
+ QTest::newRow("no-match-secure-1") << allCookies << "http://nokia.com/web" << result;
+ QTest::newRow("no-match-secure-2") << allCookies << "http://qt.nokia.com/web" << result;
+ result += secureCookie;
+ QTest::newRow("match-secure-1") << allCookies << "https://nokia.com/web" << result;
+ QTest::newRow("match-secure-2") << allCookies << "https://qt.nokia.com/web" << result;
+
+}
+
+void tst_QNetworkCookieJar::cookiesForUrl()
+{
+ QFETCH(QList<QNetworkCookie>, allCookies);
+ QFETCH(QString, url);
+ QFETCH(QList<QNetworkCookie>, expectedResult);
+
+ MyCookieJar jar;
+ jar.setAllCookies(allCookies);
+
+ QList<QNetworkCookie> result = jar.cookiesForUrl(url);
+ QCOMPARE(result, expectedResult);
+}
+
+void tst_QNetworkCookieJar::effectiveTLDs_data()
+{
+ QTest::addColumn<QString>("domain");
+ QTest::addColumn<bool>("isTLD");
+
+ QTest::newRow("yes1") << "com" << true;
+ QTest::newRow("yes2") << "de" << true;
+ QTest::newRow("yes3") << "ulm.museum" << true;
+ QTest::newRow("yes4") << "krodsherad.no" << true;
+ QTest::newRow("yes5") << "1.bg" << true;
+ QTest::newRow("yes6") << "com.cn" << true;
+ QTest::newRow("yes7") << "org.ws" << true;
+ QTest::newRow("yes8") << "co.uk" << true;
+ QTest::newRow("yes9") << "wallonie.museum" << true;
+
+ QTest::newRow("no1") << "anything.com" << false;
+ QTest::newRow("no2") << "anything.de" << false;
+ QTest::newRow("no3") << "eselsberg.ulm.museum" << false;
+ QTest::newRow("no4") << "noe.krodsherad.no" << false;
+ QTest::newRow("no5") << "2.1.bg" << false;
+ QTest::newRow("no6") << "foo.com.cn" << false;
+ QTest::newRow("no7") << "something.org.ws" << false;
+ QTest::newRow("no8") << "teatime.co.uk" << false;
+ QTest::newRow("no9") << "bla" << false;
+ QTest::newRow("no10") << "bla.bla" << false;
+
+ const ushort s1[] = {0x74, 0x72, 0x61, 0x6e, 0xf8, 0x79, 0x2e, 0x6e, 0x6f, 0x00}; // xn--trany-yua.no
+ const ushort s2[] = {0x5d9, 0x5e8, 0x5d5, 0x5e9, 0x5dc, 0x5d9, 0x5dd, 0x2e, 0x6d, 0x75, 0x73, 0x65, 0x75, 0x6d, 0x00}; // xn--9dbhblg6di.museum
+ const ushort s3[] = {0x7ec4, 0x7e54, 0x2e, 0x68, 0x6b, 0x00}; // xn--mk0axi.hk
+ const ushort s4[] = {0x7f51, 0x7edc, 0x2e, 0x63, 0x6e, 0x00}; // xn--io0a7i.cn
+ const ushort s5[] = {0x72, 0xe1, 0x68, 0x6b, 0x6b, 0x65, 0x72, 0xe1, 0x76, 0x6a, 0x75, 0x2e, 0x6e, 0x6f, 0x00}; // xn--rhkkervju-01af.no
+ const ushort s6[] = {0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0x00}; // xn--clchc0ea0b2g2a9gcd
+ const ushort s7[] = {0x627, 0x644, 0x627, 0x631, 0x62f, 0x646, 0x00}; // xn--mgbayh7gpa
+ const ushort s8[] = {0x63, 0x6f, 0x72, 0x72, 0x65, 0x69, 0x6f, 0x73, 0x2d, 0x65, 0x2d, 0x74, 0x65, 0x6c, 0x65,
+ 0x63, 0x6f, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0xe7, 0xf5, 0x65, 0x73, 0x2e, 0x6d, 0x75,
+ 0x73, 0x65, 0x75, 0x6d, 0x00}; // xn--correios-e-telecomunicaes-ghc29a.museum
+ QTest::newRow("yes-specialchars1") << QString::fromUtf16(s1) << true;
+ QTest::newRow("yes-specialchars2") << QString::fromUtf16(s2) << true;
+ QTest::newRow("yes-specialchars3") << QString::fromUtf16(s3) << true;
+ QTest::newRow("yes-specialchars4") << QString::fromUtf16(s4) << true;
+ QTest::newRow("yes-specialchars5") << QString::fromUtf16(s5) << true;
+ QTest::newRow("yes-specialchars6") << QString::fromUtf16(s6) << true;
+ QTest::newRow("yes-specialchars7") << QString::fromUtf16(s7) << true;
+ QTest::newRow("yes-specialchars8") << QString::fromUtf16(s8) << true;
+
+ QTest::newRow("no-specialchars1") << QString::fromUtf16(s1).prepend("something") << false;
+ QTest::newRow("no-specialchars2") << QString::fromUtf16(s2).prepend(QString::fromUtf16(s2)) << false;
+ QTest::newRow("no-specialchars2.5") << QString::fromUtf16(s2).prepend("whatever") << false;
+ QTest::newRow("no-specialchars3") << QString::fromUtf16(s3).prepend("foo") << false;
+ QTest::newRow("no-specialchars4") << QString::fromUtf16(s4).prepend("bar") << false;
+ QTest::newRow("no-specialchars5") << QString::fromUtf16(s5).prepend(QString::fromUtf16(s2)) << false;
+ QTest::newRow("no-specialchars6") << QString::fromUtf16(s6).prepend(QLatin1Char('.') + QString::fromUtf16(s6)) << false;
+ QTest::newRow("no-specialchars7") << QString::fromUtf16(s7).prepend("bla") << false;
+ QTest::newRow("no-specialchars8") << QString::fromUtf16(s8).append("foo") << false;
+
+ QTest::newRow("exception1") << "pref.iwate.jp" << false;
+ QTest::newRow("exception2") << "omanpost.om" << false;
+ QTest::newRow("exception3") << "omantel.om" << false;
+ QTest::newRow("exception4") << "gobiernoelectronico.ar" << false;
+ QTest::newRow("exception5") << "pref.ishikawa.jp" << false;
+
+ QTest::newRow("yes-wildcard1") << "*.jm" << true;
+ QTest::newRow("yes-wildcard1.5") << "anything.jm" << true;
+ QTest::newRow("yes-wildcard2") << "something.kh" << true;
+ QTest::newRow("yes-wildcard3") << "whatever.uk" << true;
+ QTest::newRow("yes-wildcard4") << "anything.shizuoka.jp" << true;
+ QTest::newRow("yes-wildcard5") << "foo.sch.uk" << true;
+}
+
+void tst_QNetworkCookieJar::effectiveTLDs()
+{
+#ifndef QT_BUILD_INTERNAL
+ QSKIP("Test requires private API", SkipAll);
+#endif
+ QFETCH(QString, domain);
+ QFETCH(bool, isTLD);
+ QCOMPARE(qIsEffectiveTLD(domain), isTLD);
+}
+
+QTEST_MAIN(tst_QNetworkCookieJar)
+#include "tst_qnetworkcookiejar.moc"
+
diff --git a/tests/auto/network/access/qnetworkdiskcache/.gitignore b/tests/auto/network/access/qnetworkdiskcache/.gitignore
new file mode 100644
index 0000000000..37a1ff2a42
--- /dev/null
+++ b/tests/auto/network/access/qnetworkdiskcache/.gitignore
@@ -0,0 +1 @@
+tst_qnetworkdiskcache
diff --git a/tests/auto/network/access/qnetworkdiskcache/qnetworkdiskcache.pro b/tests/auto/network/access/qnetworkdiskcache/qnetworkdiskcache.pro
new file mode 100644
index 0000000000..c05171dac7
--- /dev/null
+++ b/tests/auto/network/access/qnetworkdiskcache/qnetworkdiskcache.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+QT -= gui
+QT += network
+SOURCES += tst_qnetworkdiskcache.cpp
+
+symbian: TARGET.CAPABILITY = NetworkServices
+
diff --git a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp
new file mode 100644
index 0000000000..030eae60a0
--- /dev/null
+++ b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp
@@ -0,0 +1,677 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtNetwork/QtNetwork>
+#include <qnetworkdiskcache.h>
+#include "../../../../shared/util.h"
+
+#define EXAMPLE_URL "http://user:pass@www.example.com/#foo"
+//cached objects are organized into these many subdirs
+#define NUM_SUBDIRECTORIES 16
+
+class tst_QNetworkDiskCache : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qnetworkdiskcache_data();
+ void qnetworkdiskcache();
+
+ void prepare();
+ void cacheSize();
+ void clear();
+ void data_data();
+ void data();
+ void metaData();
+ void remove();
+ void setCacheDirectory_data();
+ void setCacheDirectory();
+ void updateMetaData();
+ void fileMetaData();
+ void expire();
+
+ void oldCacheVersionFile_data();
+ void oldCacheVersionFile();
+
+ void sync();
+
+ void crashWhenParentingCache();
+};
+
+// FIXME same as in tst_qnetworkreply.cpp .. could be unified
+// Does not work for POST/PUT!
+class MiniHttpServer: public QTcpServer
+{
+ Q_OBJECT
+public:
+ QTcpSocket *client; // always the last one that was received
+ QByteArray dataToTransmit;
+ QByteArray receivedData;
+ bool doClose;
+ bool multiple;
+ int totalConnections;
+
+ MiniHttpServer(const QByteArray &data) : client(0), dataToTransmit(data), doClose(true), multiple(false), totalConnections(0)
+ {
+ listen();
+ connect(this, SIGNAL(newConnection()), this, SLOT(doAccept()));
+ }
+
+public slots:
+ void doAccept()
+ {
+ client = nextPendingConnection();
+ client->setParent(this);
+ ++totalConnections;
+ connect(client, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
+ }
+
+ void readyReadSlot()
+ {
+ receivedData += client->readAll();
+ int doubleEndlPos = receivedData.indexOf("\r\n\r\n");
+
+ if (doubleEndlPos != -1) {
+ // multiple requests incoming. remove the bytes of the current one
+ if (multiple)
+ receivedData.remove(0, doubleEndlPos+4);
+
+ client->write(dataToTransmit);
+ if (doClose) {
+ client->disconnectFromHost();
+ disconnect(client, 0, this, 0);
+ client = 0;
+ }
+ }
+ }
+};
+
+// Subclass that exposes the protected functions.
+class SubQNetworkDiskCache : public QNetworkDiskCache
+{
+public:
+ ~SubQNetworkDiskCache()
+ {
+ if (!cacheDirectory().isEmpty())
+ clear();
+ }
+
+ QNetworkCacheMetaData call_fileMetaData(QString const &fileName)
+ { return SubQNetworkDiskCache::fileMetaData(fileName); }
+
+ qint64 call_expire()
+ { return SubQNetworkDiskCache::expire(); }
+
+ void setupWithOne(const QUrl &url, const QNetworkCacheMetaData &metaData = QNetworkCacheMetaData())
+ {
+ setCacheDirectory(QDir::tempPath() + "/diskCache");
+
+ QIODevice *d = 0;
+ if (metaData.isValid()) {
+ d = prepare(metaData);
+ } else {
+ QNetworkCacheMetaData m;
+ m.setUrl(url);
+ QNetworkCacheMetaData::RawHeader header("content-type", "text/html");
+ QNetworkCacheMetaData::RawHeaderList list;
+ list.append(header);
+ m.setRawHeaders(list);
+ d = prepare(m);
+ }
+ d->write("Hello World!");
+ insert(d);
+ }
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QNetworkDiskCache::initTestCase()
+{
+ SubQNetworkDiskCache cache;
+ cache.setCacheDirectory(QDir::tempPath() + "/diskCache");
+ cache.clear();
+ QString s = QDir::tempPath() + "/diskCache/";
+ QDir dir;
+ dir.rmdir(s + "data7"); // the number is the internal cache version
+ dir.rmdir(s + "prepared");
+ dir.rmdir(s);
+ dir.rmdir(s + "http"); // delete directory used by 4.7 and earlier (would make the tests fail)
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QNetworkDiskCache::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QNetworkDiskCache::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QNetworkDiskCache::cleanup()
+{
+}
+
+void tst_QNetworkDiskCache::qnetworkdiskcache_data()
+{
+}
+
+void tst_QNetworkDiskCache::qnetworkdiskcache()
+{
+ QUrl url(EXAMPLE_URL);
+ SubQNetworkDiskCache cache;
+ QCOMPARE(cache.cacheDirectory(), QString());
+ QCOMPARE(cache.cacheSize(), qint64(0));
+ cache.clear();
+ QCOMPARE(cache.metaData(QUrl()), QNetworkCacheMetaData());
+ QCOMPARE(cache.remove(QUrl()), false);
+ QCOMPARE(cache.remove(url), false);
+ cache.insert((QIODevice*)0);
+ cache.setCacheDirectory(QString());
+ cache.updateMetaData(QNetworkCacheMetaData());
+ cache.prepare(QNetworkCacheMetaData());
+ QCOMPARE(cache.call_fileMetaData(QString()), QNetworkCacheMetaData());
+
+ // leave one hanging around...
+ QNetworkDiskCache badCache;
+ QNetworkCacheMetaData metaData;
+ metaData.setUrl(url);
+ badCache.prepare(metaData);
+ badCache.setCacheDirectory(QDir::tempPath() + "/diskCache");
+ badCache.prepare(metaData);
+}
+
+void tst_QNetworkDiskCache::prepare()
+{
+ SubQNetworkDiskCache cache;
+ cache.setCacheDirectory(QDir::tempPath() + "/diskCache");
+
+ QUrl url(EXAMPLE_URL);
+ QNetworkCacheMetaData metaData;
+ metaData.setUrl(url);
+
+ cache.prepare(metaData);
+ cache.remove(url);
+}
+
+// public qint64 cacheSize() const
+void tst_QNetworkDiskCache::cacheSize()
+{
+ SubQNetworkDiskCache cache;
+ cache.setCacheDirectory(QDir::tempPath() + "/diskCache");
+ QCOMPARE(cache.cacheSize(), qint64(0));
+
+ QUrl url(EXAMPLE_URL);
+ QNetworkCacheMetaData metaData;
+ metaData.setUrl(url);
+ QIODevice *d = cache.prepare(metaData);
+ cache.insert(d);
+ QVERIFY(cache.cacheSize() > qint64(0));
+
+ cache.clear();
+ QCOMPARE(cache.cacheSize(), qint64(0));
+}
+
+static QStringList countFiles(const QString dir)
+{
+ QStringList list;
+ QDir::Filters filter(QDir::AllEntries | QDir::NoDotAndDotDot);
+ QDirIterator it(dir, filter, QDirIterator::Subdirectories);
+ while (it.hasNext())
+ list.append(it.next());
+ return list;
+}
+
+// public void clear()
+void tst_QNetworkDiskCache::clear()
+{
+ SubQNetworkDiskCache cache;
+ QUrl url(EXAMPLE_URL);
+ cache.setupWithOne(url);
+ QVERIFY(cache.cacheSize() > qint64(0));
+
+ QString cacheDirectory = cache.cacheDirectory();
+ QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 3);
+ cache.clear();
+ QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 2);
+
+ // don't delete files that it didn't create
+ QTemporaryFile file(cacheDirectory + "/XXXXXX");
+ if (file.open()) {
+ QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 3);
+ cache.clear();
+ QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 3);
+ }
+}
+
+Q_DECLARE_METATYPE(QNetworkCacheMetaData)
+void tst_QNetworkDiskCache::data_data()
+{
+ QTest::addColumn<QNetworkCacheMetaData>("data");
+
+ QTest::newRow("null") << QNetworkCacheMetaData();
+
+ QUrl url(EXAMPLE_URL);
+ QNetworkCacheMetaData metaData;
+ metaData.setUrl(url);
+ QNetworkCacheMetaData::RawHeaderList headers;
+ headers.append(QNetworkCacheMetaData::RawHeader("type", "bin"));
+ metaData.setRawHeaders(headers);
+ QTest::newRow("null") << metaData;
+}
+
+// public QIODevice* data(QUrl const& url)
+void tst_QNetworkDiskCache::data()
+{
+ QFETCH(QNetworkCacheMetaData, data);
+ SubQNetworkDiskCache cache;
+ QUrl url(EXAMPLE_URL);
+ cache.setupWithOne(url, data);
+
+ for (int i = 0; i < 3; ++i) {
+ QIODevice *d = cache.data(url);
+ QVERIFY(d);
+ QCOMPARE(d->readAll(), QByteArray("Hello World!"));
+ delete d;
+ }
+}
+
+// public QNetworkCacheMetaData metaData(QUrl const& url)
+void tst_QNetworkDiskCache::metaData()
+{
+ SubQNetworkDiskCache cache;
+
+ QUrl url(EXAMPLE_URL);
+ QNetworkCacheMetaData metaData;
+ metaData.setUrl(url);
+ QNetworkCacheMetaData::RawHeaderList headers;
+ headers.append(QNetworkCacheMetaData::RawHeader("type", "bin"));
+ metaData.setRawHeaders(headers);
+ metaData.setLastModified(QDateTime::currentDateTime());
+ metaData.setExpirationDate(QDateTime::currentDateTime());
+ metaData.setSaveToDisk(true);
+
+ cache.setupWithOne(url, metaData);
+
+ for (int i = 0; i < 3; ++i) {
+ QNetworkCacheMetaData cacheMetaData = cache.metaData(url);
+ QVERIFY(cacheMetaData.isValid());
+ QCOMPARE(metaData, cacheMetaData);
+ }
+}
+
+// public bool remove(QUrl const& url)
+void tst_QNetworkDiskCache::remove()
+{
+ SubQNetworkDiskCache cache;
+ QUrl url(EXAMPLE_URL);
+ cache.setupWithOne(url);
+ QString cacheDirectory = cache.cacheDirectory();
+ QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 3);
+ cache.remove(url);
+ QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 2);
+}
+
+void tst_QNetworkDiskCache::setCacheDirectory_data()
+{
+ QTest::addColumn<QString>("cacheDir");
+ QTest::newRow("null") << QString();
+ QDir dir("foo");
+ QTest::newRow("foo") << dir.absolutePath() + QString("/");
+}
+
+// public void setCacheDirectory(QString const& cacheDir)
+void tst_QNetworkDiskCache::setCacheDirectory()
+{
+ QFETCH(QString, cacheDir);
+
+ SubQNetworkDiskCache cache;
+ cache.setCacheDirectory(cacheDir);
+ QCOMPARE(cache.cacheDirectory(), cacheDir);
+}
+
+// public void updateMetaData(QNetworkCacheMetaData const& metaData)
+void tst_QNetworkDiskCache::updateMetaData()
+{
+ QUrl url(EXAMPLE_URL);
+ SubQNetworkDiskCache cache;
+ cache.setupWithOne(url);
+
+ QNetworkCacheMetaData metaData = cache.metaData(url);
+ metaData.setLastModified(QDateTime::currentDateTime());
+ cache.updateMetaData(metaData);
+ QNetworkCacheMetaData newMetaData = cache.metaData(url);
+ QCOMPARE(newMetaData, metaData);
+}
+
+// protected QNetworkCacheMetaData fileMetaData(QString const& fileName)
+void tst_QNetworkDiskCache::fileMetaData()
+{
+ SubQNetworkDiskCache cache;
+ QUrl url(EXAMPLE_URL);
+ cache.setupWithOne(url);
+
+ url.setPassword(QString());
+ url.setFragment(QString());
+
+ QString cacheDirectory = cache.cacheDirectory();
+ QStringList list = countFiles(cacheDirectory);
+ QCOMPARE(list.count(), NUM_SUBDIRECTORIES + 3);
+ foreach(QString fileName, list) {
+ QFileInfo info(fileName);
+ if (info.isFile()) {
+ QNetworkCacheMetaData metaData = cache.call_fileMetaData(fileName);
+ QCOMPARE(metaData.url(), url);
+ }
+ }
+
+ QTemporaryFile file(cacheDirectory + "/qt_temp.XXXXXX");
+ if (file.open()) {
+ QNetworkCacheMetaData metaData = cache.call_fileMetaData(file.fileName());
+ QVERIFY(!metaData.isValid());
+ }
+}
+
+// protected qint64 expire()
+void tst_QNetworkDiskCache::expire()
+{
+ SubQNetworkDiskCache cache;
+ cache.setCacheDirectory(QDir::tempPath() + "/diskCache");
+ QCOMPARE(cache.call_expire(), (qint64)0);
+ QUrl url(EXAMPLE_URL);
+ cache.setupWithOne(url);
+ QVERIFY(cache.call_expire() > (qint64)0);
+ qint64 limit = (1024 * 1024 / 4) * 5;
+ cache.setMaximumCacheSize(limit);
+
+ qint64 max = cache.maximumCacheSize();
+ QCOMPARE(max, limit);
+ for (int i = 0; i < 10; ++i) {
+ if (i % 3 == 0)
+ QTest::qWait(2000);
+ QNetworkCacheMetaData m;
+ m.setUrl(QUrl("http://www.foo.com/" + QString::number(i)));
+ QIODevice *d = cache.prepare(m);
+ QString bigString;
+ bigString.fill(QLatin1Char('Z'), (1024 * 1024 / 4));
+ d->write(bigString.toLatin1().data());
+ cache.insert(d);
+ QVERIFY(cache.call_expire() < max);
+ }
+
+ QString cacheDirectory = cache.cacheDirectory();
+ QStringList list = countFiles(cacheDirectory);
+ QStringList cacheList;
+ foreach(QString fileName, list) {
+ QFileInfo info(fileName);
+ if (info.isFile()) {
+ QNetworkCacheMetaData metaData = cache.call_fileMetaData(fileName);
+ cacheList.append(metaData.url().toString());
+ }
+ }
+ qSort(cacheList);
+ for (int i = 0; i < cacheList.count(); ++i) {
+ QString fileName = cacheList[i];
+ QCOMPARE(fileName, QString("http://www.foo.com/%1").arg(i + 6));
+ }
+}
+
+void tst_QNetworkDiskCache::oldCacheVersionFile_data()
+{
+ QTest::addColumn<int>("pass");
+ QTest::newRow("0") << 0;
+ QTest::newRow("1") << 1;
+}
+
+void tst_QNetworkDiskCache::oldCacheVersionFile()
+{
+ QFETCH(int, pass);
+ SubQNetworkDiskCache cache;
+ QUrl url(EXAMPLE_URL);
+ cache.setupWithOne(url);
+
+ if (pass == 0) {
+ QString name;
+ {
+ QTemporaryFile file(cache.cacheDirectory() + "/XXXXXX.d");
+ file.setAutoRemove(false);
+ QVERIFY(file.open());
+ QDataStream out(&file);
+ out << qint32(0xe8);
+ out << qint32(2);
+ name = file.fileName();
+ file.close();
+ }
+
+ QVERIFY(QFile::exists(name));
+ QNetworkCacheMetaData metaData = cache.call_fileMetaData(name);
+ QVERIFY(!metaData.isValid());
+ QVERIFY(!QFile::exists(name));
+ } else {
+ QStringList files = countFiles(cache.cacheDirectory());
+ QCOMPARE(files.count(), NUM_SUBDIRECTORIES + 3);
+ // find the file
+ QString cacheFile;
+ foreach (QString file, files) {
+ QFileInfo info(file);
+ if (info.isFile())
+ cacheFile = file;
+ }
+ QVERIFY(QFile::exists(cacheFile));
+
+ QFile file(cacheFile);
+ QVERIFY(file.open(QFile::ReadWrite));
+ QDataStream out(&file);
+ out << qint32(0xe8);
+ out << qint32(2);
+ file.close();
+
+ QIODevice *device = cache.data(url);
+ QVERIFY(!device);
+ QVERIFY(!QFile::exists(cacheFile));
+ }
+}
+
+class Runner : public QThread
+{
+
+public:
+ Runner()
+ : QThread()
+ , other(0)
+ {}
+
+ void run()
+ {
+ QByteArray longString = "Hello World, this is some long string, well not really that long";
+ for (int j = 0; j < 10; ++j)
+ longString += longString;
+ QByteArray longString2 = "Help, I am stuck in an autotest!";
+ QUrl url(EXAMPLE_URL);
+
+ QNetworkCacheMetaData metaData;
+ metaData.setUrl(url);
+ QNetworkCacheMetaData::RawHeaderList headers;
+ headers.append(QNetworkCacheMetaData::RawHeader("type", "bin"));
+ metaData.setRawHeaders(headers);
+ metaData.setLastModified(dt);
+ metaData.setSaveToDisk(true);
+
+ QNetworkCacheMetaData metaData2 = metaData;
+ metaData2.setExpirationDate(dt);
+
+ QNetworkDiskCache cache;
+ cache.setCacheDirectory(QDir::tempPath() + "/diskCache");
+
+ int read = 0;
+
+ int i = 0;
+ for (; i < 5000; ++i) {
+ if (other && other->isFinished())
+ break;
+
+ if (write) {
+ QNetworkCacheMetaData m;
+ if (qrand() % 2 == 0)
+ m = metaData;
+ else
+ m = metaData2;
+
+ if (qrand() % 20 == 1) {
+ //qDebug() << "write update";
+ cache.updateMetaData(m);
+ continue;
+ }
+
+ QIODevice *device = cache.prepare(m);
+ if (qrand() % 20 == 1) {
+ //qDebug() << "write remove";
+ cache.remove(url);
+ continue;
+ }
+ QVERIFY(device);
+ if (qrand() % 2 == 0)
+ device->write(longString);
+ else
+ device->write(longString2);
+ //qDebug() << "write write" << device->size();
+ cache.insert(device);
+ continue;
+ }
+
+ QNetworkCacheMetaData gotMetaData = cache.metaData(url);
+ if (gotMetaData.isValid()) {
+ QVERIFY(gotMetaData == metaData || gotMetaData == metaData2);
+ QIODevice *d = cache.data(url);
+ if (d) {
+ QByteArray x = d->readAll();
+ if (x != longString && x != longString2) {
+ qDebug() << x.length() << QString(x);
+ gotMetaData = cache.metaData(url);
+ qDebug() << (gotMetaData.url().toString())
+ << gotMetaData.lastModified()
+ << gotMetaData.expirationDate()
+ << gotMetaData.saveToDisk();
+ }
+ if (gotMetaData.isValid())
+ QVERIFY(x == longString || x == longString2);
+ read++;
+ delete d;
+ }
+ }
+ if (qrand() % 5 == 1)
+ cache.remove(url);
+ if (qrand() % 5 == 1)
+ cache.clear();
+ sleep(0);
+ }
+ //qDebug() << "read!" << read << i;
+ }
+
+ QDateTime dt;
+ bool write;
+ Runner *other;
+};
+
+void tst_QNetworkDiskCache::crashWhenParentingCache()
+{
+ // the trick here is to not send the complete response
+ // but some data. So we get a readyRead() and it gets tried
+ // to be saved to the cache
+ QByteArray data("HTTP/1.0 200 OK\r\nCache-Control: max-age=300\r\nAge: 1\r\nContent-Length: 5\r\n\r\n123");
+ MiniHttpServer server(data);
+
+ QNetworkAccessManager *manager = new QNetworkAccessManager();
+ QNetworkDiskCache *diskCache = new QNetworkDiskCache(manager); // parent to qnam!
+ // we expect the temp dir to be cleaned at some point anyway
+ diskCache->setCacheDirectory(QString("%1/cacheDir_%2").arg(QDir::tempPath()).arg(QCoreApplication::applicationPid()));
+ manager->setCache(diskCache);
+
+ QUrl url("http://127.0.0.1:" + QString::number(server.serverPort()));
+ QNetworkRequest request(url);
+ // request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
+ QNetworkReply *reply = manager->get(request); // new reply is parented to qnam
+
+ // wait for readyRead of reply!
+ connect(reply, SIGNAL(readyRead()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(5);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ delete manager; // crashed before..
+}
+
+void tst_QNetworkDiskCache::sync()
+{
+ // This tests would be a nice to have, but is currently not supported.
+ return;
+
+ QTime midnight(0, 0, 0);
+ qsrand(midnight.secsTo(QTime::currentTime()));
+ Runner reader;
+ reader.dt = QDateTime::currentDateTime();
+ reader.write = false;
+
+ Runner writer;
+ writer.dt = reader.dt;
+ writer.write = true;
+
+ writer.other = &reader;
+ reader.other = &writer;
+
+ writer.start();
+ reader.start();
+ writer.wait();
+ reader.wait();
+}
+
+QTEST_MAIN(tst_QNetworkDiskCache)
+#include "tst_qnetworkdiskcache.moc"
+
diff --git a/tests/auto/network/access/qnetworkreply/.gitattributes b/tests/auto/network/access/qnetworkreply/.gitattributes
new file mode 100644
index 0000000000..80252cfd34
--- /dev/null
+++ b/tests/auto/network/access/qnetworkreply/.gitattributes
@@ -0,0 +1,3 @@
+rfc3252.txt -crlf
+bigfile -crlf
+resource -crlf
diff --git a/tests/auto/network/access/qnetworkreply/.gitignore b/tests/auto/network/access/qnetworkreply/.gitignore
new file mode 100644
index 0000000000..2797fcd809
--- /dev/null
+++ b/tests/auto/network/access/qnetworkreply/.gitignore
@@ -0,0 +1,3 @@
+tst_qnetworkreply
+echo/echo
+echo/echo.exe
diff --git a/tests/auto/network/access/qnetworkreply/bigfile b/tests/auto/network/access/qnetworkreply/bigfile
new file mode 100644
index 0000000000..cb114a2b0e
--- /dev/null
+++ b/tests/auto/network/access/qnetworkreply/bigfile
@@ -0,0 +1,17980 @@
+
+
+
+
+
+
+Network Working Group H. Kennedy
+Request for Comments: 3252 Mimezine
+Category: Informational 1 April 2002
+
+
+ Binary Lexical Octet Ad-hoc Transport
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ This document defines a reformulation of IP and two transport layer
+ protocols (TCP and UDP) as XML applications.
+
+1. Introduction
+
+1.1. Overview
+
+ This document describes the Binary Lexical Octet Ad-hoc Transport
+ (BLOAT): a reformulation of a widely-deployed network-layer protocol
+ (IP [RFC791]), and two associated transport layer protocols (TCP
+ [RFC793] and UDP [RFC768]) as XML [XML] applications. It also
+ describes methods for transporting BLOAT over Ethernet and IEEE 802
+ networks as well as encapsulating BLOAT in IP for gatewaying BLOAT
+ across the public Internet.
+
+1.2. Motivation
+
+ The wild popularity of XML as a basis for application-level protocols
+ such as the Blocks Extensible Exchange Protocol [RFC3080], the Simple
+ Object Access Protocol [SOAP], and Jabber [JABBER] prompted
+ investigation into the possibility of extending the use of XML in the
+ protocol stack. Using XML at both the transport and network layer in
+ addition to the application layer would provide for an amazing amount
+ of power and flexibility while removing dependencies on proprietary
+ and hard-to-understand binary protocols. This protocol unification
+ would also allow applications to use a single XML parser for all
+ aspects of their operation, eliminating developer time spent figuring
+ out the intricacies of each new protocol, and moving the hard work of
+
+
+
+
+Kennedy Informational [Page 1]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ parsing to the XML toolset. The use of XML also mitigates concerns
+ over "network vs. host" byte ordering which is at the root of many
+ network application bugs.
+
+1.3. Relation to Existing Protocols
+
+ The reformulations specified in this RFC follow as closely as
+ possible the spirit of the RFCs on which they are based, and so MAY
+ contain elements or attributes that would not be needed in a pure
+ reworking (e.g. length attributes, which are implicit in XML.)
+
+ The layering of network and transport protocols are maintained in
+ this RFC despite the optimizations that could be made if the line
+ were somewhat blurred (i.e. merging TCP and IP into a single, larger
+ element in the DTD) in order to foster future use of this protocol as
+ a basis for reformulating other protocols (such as ICMP.)
+
+ Other than the encoding, the behavioral aspects of each of the
+ existing protocols remain unchanged. Routing, address spaces, TCP
+ congestion control, etc. behave as specified in the extant standards.
+ Adapting to new standards and experimental algorithm heuristics for
+ improving performance will become much easier once the move to BLOAT
+ has been completed.
+
+1.4. Requirement Levels
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in BCP 14, RFC 2119
+ [RFC2119].
+
+2. IPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC.
+ IPoXML is the root protocol REQUIRED for effective use of TCPoXML
+ (section 3.) and higher-level application protocols.
+
+ The DTD for this document type can be found in section 7.1.
+
+ The routing of IPoXML can be easily implemented on hosts with an XML
+ parser, as the regular structure lends itself handily to parsing and
+ validation of the document/datagram and then processing the
+ destination address, TTL, and checksum before sending it on to its
+ next-hop.
+
+ The reformulation of IPv4 was chosen over IPv6 [RFC2460] due to the
+ wider deployment of IPv4 and the fact that implementing IPv6 as XML
+ would have exceeded the 1500 byte Ethernet MTU.
+
+
+
+Kennedy Informational [Page 2]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ All BLOAT implementations MUST use - and specify - the UTF-8 encoding
+ of RFC 2279 [RFC2279]. All BLOAT document/datagrams MUST be well-
+ formed and include the XMLDecl.
+
+2.1. IP Description
+
+ A number of items have changed (for the better) from the original IP
+ specification. Bit-masks, where present have been converted into
+ human-readable values. IP addresses are listed in their dotted-
+ decimal notation [RFC1123]. Length and checksum values are present
+ as decimal integers.
+
+ To calculate the length and checksum fields of the IP element, a
+ canonicalized form of the element MUST be used. The canonical form
+ SHALL have no whitespace (including newline characters) between
+ elements and only one space character between attributes. There
+ SHALL NOT be a space following the last attribute in an element.
+
+ An iterative method SHOULD be used to calculate checksums, as the
+ length field will vary based on the size of the checksum.
+
+ The payload element bears special attention. Due to the character
+ set restrictions of XML, the payload of IP datagrams (which MAY
+ contain arbitrary data) MUST be encoded for transport. This RFC
+ REQUIRES the contents of the payload to be encoded in the base-64
+ encoding of RFC 2045 [RFC2045], but removes the requirement that the
+ encoded output MUST be wrapped on 76-character lines.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 3]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+2.2. Example Datagram
+
+ The following is an example IPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ <ip>
+ <header length="474">
+ <version value="4"/>
+ <tos precedence="Routine" delay="Normal" throughput="Normal"
+ relibility="Normal" reserved="0"/>
+ <total.length value="461"/>
+ <id value="1"/>
+ <flags reserved="0" df="dont" mf="last"/>
+ <offset value="0"/>
+ <ttl value="255"/>
+ <protocol value="6"/>
+ <checksum value="8707"/>
+ <source address="10.0.0.22"/>
+ <destination address="10.0.0.1"/>
+ <options>
+ <end copied="0" class="0" number="0"/>
+ </options>
+ <padding pad="0"/>
+ </header>
+ <payload>
+ </payload>
+ </ip>
+
+3. TCPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.2.
+
+3.1. TCP Description
+
+ A number of items have changed from the original TCP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+ To calculate the length and checksum fields of the TCP element, a
+ canonicalized form of the element MUST be used as in section 2.1.
+
+ An iterative method SHOULD be used to calculate checksums as in
+ section 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+
+
+Kennedy Informational [Page 4]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ The TCP offset element was expanded to a maximum of 255 from 16 to
+ allow for the increased size of the header in XML.
+
+ TCPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+3.2. Example Datagram
+
+ The following is an example TCPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ <tcp>
+ <tcp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <sequence number="322622954"/>
+ <acknowledgement number="689715995"/>
+ <offset number=""/>
+ <reserved value="0"/>
+ <control syn="1" ack="1"/>
+ <window size="1"/>
+ <urgent pointer="0"/>
+ <checksum value="2988"/>
+ <tcp.options>
+ <tcp.end kind="0"/>
+ </tcp.options>
+ <padding pad="0"/>
+ </tcp.header>
+ <payload>
+ </payload>
+ </tcp>
+
+4. UDPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.3.
+
+4.1. UDP Description
+
+ A number of items have changed from the original UDP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+
+
+
+
+
+
+Kennedy Informational [Page 5]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ To calculate the length and checksum fields of the UDP element, a
+ canonicalized form of the element MUST be used as in section 2.1. An
+ iterative method SHOULD be used to calculate checksums as in section
+ 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+ UDPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+4.2. Example Datagram
+
+ The following is an example UDPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ <udp>
+ <udp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <udp.length value="143"/>
+ <checksum value="2988"/>
+ </udp.header>
+ <payload>
+ </payload>
+ </udp>
+
+5. Network Transport
+
+ This document provides for the transmission of BLOAT datagrams over
+ two common families of physical layer transport. Future RFCs will
+ address additional transports as routing vendors catch up to the
+ specification, and we begin to see BLOAT routed across the Internet
+ backbone.
+
+5.1. Ethernet
+
+ BLOAT is encapsulated in Ethernet datagrams as in [RFC894] with the
+ exception that the type field of the Ethernet frame MUST contain the
+ value 0xBEEF. The first 5 octets of the Ethernet frame payload will
+ be 0x3c 3f 78 6d 6c ("<?xml".)
+
+5.2. IEEE 802
+
+ BLOAT is encapsulated in IEEE 802 Networks as in [RFC1042] except
+ that the protocol type code for IPoXML is 0xBEEF.
+
+
+
+
+
+Kennedy Informational [Page 6]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+6. Gatewaying over IP
+
+ In order to facilitate the gradual introduction of BLOAT into the
+ public Internet, BLOAT MAY be encapsulated in IP as in [RFC2003] to
+ gateway between networks that run BLOAT natively on their LANs.
+
+7. DTDs
+
+ The Transport DTDs (7.2. and 7.3.) build on the definitions in the
+ Network DTD (7.1.)
+
+ The DTDs are referenced by their PubidLiteral and SystemLiteral (from
+ [XML]) although it is understood that most IPoXML implementations
+ will not need to pull down the DTD, as it will normally be embedded
+ in the implementation, and presents something of a catch-22 if you
+ need to load part of your network protocol over the network.
+
+7.1. IPoXML DTD
+
+ <!--
+ DTD for IP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ -->
+ <!--
+ DTD data types:
+
+ Digits [0..9]+
+
+ Precedence "NetworkControl | InternetworkControl |
+ CRITIC | FlashOverride | Flash | Immediate |
+ Priority | Routine"
+
+ IP4Addr "dotted-decimal" notation of [RFC1123]
+
+ Class [0..3]
+
+ Sec "Unclassified | Confidential | EFTO | MMMM | PROG |
+ Restricted | Secret | Top Secret | Reserved"
+
+ Compartments [0..65535]
+
+ Handling [0..65535]
+
+ TCC [0..16777216]
+
+ -->
+
+
+
+Kennedy Informational [Page 7]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ENTITY % Digits "CDATA">
+ <!ENTITY % Precedence "CDATA">
+ <!ENTITY % IP4Addr "CDATA">
+ <!ENTITY % Class "CDATA">
+ <!ENTITY % Sec "CDATA">
+ <!ENTITY % Compartments "CDATA">
+ <!ENTITY % Handling "CDATA">
+ <!ENTITY % TCC "CDATA">
+
+ <!ELEMENT ip (header, payload)>
+
+ <!ELEMENT header (version, tos, total.length, id, flags, offset, ttl,
+ protocol, checksum, source, destination, options,
+ padding)>
+ <!-- length of header in 32-bit words -->
+ <!ATTLIST header
+ length %Digits; #REQUIRED>
+
+ <!ELEMENT version EMPTY>
+ <!-- ip version. SHOULD be "4" -->
+ <!ATTLIST version
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT tos EMPTY>
+ <!ATTLIST tos
+ precedence %Precedence; #REQUIRED
+ delay (normal | low) #REQUIRED
+ throughput (normal | high) #REQUIRED
+ relibility (normal | high) #REQUIRED
+ reserved CDATA #FIXED "0">
+
+ <!ELEMENT total.length EMPTY>
+ <!--
+ total length of datagram (header and payload) in octets, MUST be
+ less than 65,535 (and SHOULD be less than 1024 for IPoXML on local
+ ethernets).
+ -->
+ <!ATTLIST total.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT id EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST id
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT flags EMPTY>
+ <!-- df = don't fragment, mf = more fragments -->
+ <!ATTLIST flags
+
+
+
+Kennedy Informational [Page 8]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ reserved CDATA #FIXED "0"
+ df (may|dont) #REQUIRED
+ mf (last|more) #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= offset <= 8192 measured in 8 octet (64-bit) chunks -->
+ <!ATTLIST offset
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT ttl EMPTY>
+ <!-- 0 <= ttl <= 255 -->
+ <!ATTLIST ttl
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT protocol EMPTY>
+ <!-- 0 <= protocol <= 255 (per IANA) -->
+ <!ATTLIST protocol
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT checksum EMPTY>
+ <!-- 0 <= checksum <= 65535 (over header only) -->
+ <!ATTLIST checksum
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT source EMPTY>
+ <!ATTLIST source
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT destination EMPTY>
+ <!ATTLIST destination
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT options ( end | noop | security | loose | strict | record
+ | stream | timestamp )*>
+
+ <!ELEMENT end EMPTY>
+ <!ATTLIST end
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "0">
+
+ <!ELEMENT noop EMPTY>
+ <!ATTLIST noop
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "1">
+
+ <!ELEMENT security EMPTY>
+
+
+
+Kennedy Informational [Page 9]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST security
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "2"
+ length CDATA #FIXED "11"
+ security %Sec; #REQUIRED
+ compartments %Compartments; #REQUIRED
+ handling %Handling; #REQUIRED
+ tcc %TCC; #REQUIRED>
+ <!ELEMENT loose (hop)+>
+ <!ATTLIST loose
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "3"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT hop EMPTY>
+ <!ATTLIST hop
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT strict (hop)+>
+ <!ATTLIST strict
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "9"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT record (hop)+>
+ <!ATTLIST record
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "7"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT stream EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST stream
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "8"
+ length CDATA #FIXED "4"
+ id %Digits; #REQUIRED>
+
+ <!ELEMENT timestamp (tstamp)+>
+ <!-- 0 <= oflw <=15 -->
+
+
+
+Kennedy Informational [Page 10]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST timestamp
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "2"
+ number CDATA #FIXED "4"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED
+ oflw %Digits; #REQUIRED
+ flag (0 | 1 | 3) #REQUIRED>
+
+ <!ELEMENT tstamp EMPTY>
+ <!ATTLIST tstamp
+ time %Digits; #REQUIRED
+ address %IP4Addr; #IMPLIED>
+ <!--
+ padding to bring header to 32-bit boundary.
+ pad MUST be "0"*
+ -->
+ <!ELEMENT padding EMPTY>
+ <!ATTLIST padding
+ pad CDATA #REQUIRED>
+
+ <!-- payload MUST be encoded as base-64 [RFC2045], as modified
+ by section 2.1 of this RFC -->
+ <!ELEMENT payload (CDATA)>
+
+7.2. TCPoXML DTD
+
+ <!--
+ DTD for TCP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ -->
+
+ <!-- the pseudoheader is only included for checksum calculations -->
+ <!ELEMENT tcp (tcp.pseudoheader?, tcp.header, payload)>
+
+ <!ELEMENT tcp.header (src, dest, sequence, acknowledgement, offset,
+ reserved, control, window, checksum, urgent,
+ tcp.options, padding)>
+
+ <!ELEMENT src EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+ <!ATTLIST src
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT dest EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+
+
+
+Kennedy Informational [Page 11]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST dest
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT sequence EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST sequence
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT acknowledgement EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST acknowledgement
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= number <= 255 -->
+ <!ATTLIST offset
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT reserved EMPTY>
+ <!ATTLIST reserved
+ value CDATA #FIXED "0">
+
+ <!ELEMENT control EMPTY>
+ <!ATTLIST control
+ urg (0|1) #IMPLIED
+ ack (0|1) #IMPLIED
+ psh (0|1) #IMPLIED
+ rst (0|1) #IMPLIED
+ syn (0|1) #IMPLIED
+ fin (0|1) #IMPLIED>
+
+ <!ELEMENT window EMPTY>
+ <!-- 0 <= size <= 65,535 -->
+ <!ATTLIST window
+ size %Digits; #REQUIRED>
+
+ <!--
+ checksum as in ip, but with
+ the following pseudo-header added into the tcp element:
+ -->
+ <!ELEMENT tcp.pseudoheader (source, destination, protocol,
+ tcp.length)>
+
+ <!--
+ tcp header + data length in octets. does not include the size of
+
+ the pseudoheader.
+ -->
+
+
+
+Kennedy Informational [Page 12]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ELEMENT tcp.length EMPTY>
+ <!ATTLIST tcp.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT urgent EMPTY>
+ <!-- 0 <= pointer <= 65,535 -->
+ <!ATTLIST urgent
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT tcp.options (tcp.end | tcp.noop | tcp.mss)+>
+
+ <!ELEMENT tcp.end EMPTY>
+ <!ATTLIST tcp.end
+ kind CDATA #FIXED "0">
+
+ <!ELEMENT tcp.noop EMPTY>
+ <!ATTLIST tcp.noop
+ kind CDATA #FIXED "1">
+
+ <!ELEMENT tcp.mss EMPTY>
+ <!ATTLIST tcp.mss
+ kind CDATA #FIXED "2"
+ length CDATA #FIXED "4"
+ size %Digits; #REQUIRED>
+
+7.3. UDPoXML DTD
+
+ <!--
+ DTD for UDP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ -->
+
+ <!ELEMENT udp (udp.pseudoheader?, udp.header, payload)>
+
+ <!ELEMENT udp.header (src, dest, udp.length, checksum)>
+
+ <!ELEMENT udp.pseudoheader (source, destination, protocol,
+ udp.length)>
+
+ <!--
+ udp header + data length in octets. does not include the size of
+ the pseudoheader.
+ -->
+ <!ELEMENT udp.length EMPTY>
+ <!ATTLIST udp.length
+ value %Digits; #REQUIRED>
+
+
+
+Kennedy Informational [Page 13]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+8. Security Considerations
+
+ XML, as a subset of SGML, has the same security considerations as
+ specified in SGML Media Types [RFC1874]. Security considerations
+ that apply to IP, TCP and UDP also likely apply to BLOAT as it does
+ not attempt to correct for issues not related to message format.
+
+9. References
+
+ [JABBER] Miller, J., "Jabber", draft-miller-jabber-00.txt,
+ February 2002. (Work in Progress)
+
+ [RFC768] Postel, J., "User Datagram Protocol", STD 6, RFC 768,
+ August 1980.
+
+ [RFC791] Postel, J., "Internet Protocol", STD 5, RFC 791,
+ September 1981.
+
+ [RFC793] Postel, J., "Transmission Control Protocol", STD 7, RFC
+ 793, September 1981.
+
+ [RFC894] Hornig, C., "Standard for the Transmission of IP
+ Datagrams over Ethernet Networks.", RFC 894, April 1984.
+
+ [RFC1042] Postel, J. and J. Reynolds, "Standard for the
+ Transmission of IP Datagrams Over IEEE 802 Networks", STD
+ 43, RFC 1042, February 1988.
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts -
+ Application and Support", RFC 1123, October 1989.
+
+ [RFC1874] Levinson, E., "SGML Media Types", RFC 1874, December
+ 1995.
+
+ [RFC2003] Perkins, C., "IP Encapsulation within IP", RFC 2003,
+ October 1996.
+
+ [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message
+ Bodies", RFC 2045, November 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+
+
+
+
+Kennedy Informational [Page 14]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ [RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6
+ (IPv6) Specification", RFC 2460, December 1998.
+
+ [RFC3080] Rose, M., "The Blocks Extensible Exchange Protocol Core",
+ RFC 3080, March 2001.
+
+ [SOAP] Box, D., Ehnebuske, D., Kakivaya, G., Layman, A.,
+ Mendelsohn, N., Nielsen, H. F., Thatte, S. Winer, D.,
+ "Simple Object Access Protocol (SOAP) 1.1" World Wide Web
+ Consortium Note, May 2000 http://www.w3.org/TR/SOAP/
+
+ [XML] Bray, T., Paoli, J., Sperberg-McQueen, C. M., "Extensible
+ Markup Language (XML)" World Wide Web Consortium
+ Recommendation REC- xml-19980210.
+ http://www.w3.org/TR/1998/REC-xml-19980210
+
+10. Author's Address
+
+ Hugh Kennedy
+ Mimezine
+ 1060 West Addison
+ Chicago, IL 60613
+ USA
+
+ EMail: kennedyh@engin.umich.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 15]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+11. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 16]
+
+
+
+
+
+
+
+Network Working Group H. Kennedy
+Request for Comments: 3252 Mimezine
+Category: Informational 1 April 2002
+
+
+ Binary Lexical Octet Ad-hoc Transport
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ This document defines a reformulation of IP and two transport layer
+ protocols (TCP and UDP) as XML applications.
+
+1. Introduction
+
+1.1. Overview
+
+ This document describes the Binary Lexical Octet Ad-hoc Transport
+ (BLOAT): a reformulation of a widely-deployed network-layer protocol
+ (IP [RFC791]), and two associated transport layer protocols (TCP
+ [RFC793] and UDP [RFC768]) as XML [XML] applications. It also
+ describes methods for transporting BLOAT over Ethernet and IEEE 802
+ networks as well as encapsulating BLOAT in IP for gatewaying BLOAT
+ across the public Internet.
+
+1.2. Motivation
+
+ The wild popularity of XML as a basis for application-level protocols
+ such as the Blocks Extensible Exchange Protocol [RFC3080], the Simple
+ Object Access Protocol [SOAP], and Jabber [JABBER] prompted
+ investigation into the possibility of extending the use of XML in the
+ protocol stack. Using XML at both the transport and network layer in
+ addition to the application layer would provide for an amazing amount
+ of power and flexibility while removing dependencies on proprietary
+ and hard-to-understand binary protocols. This protocol unification
+ would also allow applications to use a single XML parser for all
+ aspects of their operation, eliminating developer time spent figuring
+ out the intricacies of each new protocol, and moving the hard work of
+
+
+
+
+Kennedy Informational [Page 1]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ parsing to the XML toolset. The use of XML also mitigates concerns
+ over "network vs. host" byte ordering which is at the root of many
+ network application bugs.
+
+1.3. Relation to Existing Protocols
+
+ The reformulations specified in this RFC follow as closely as
+ possible the spirit of the RFCs on which they are based, and so MAY
+ contain elements or attributes that would not be needed in a pure
+ reworking (e.g. length attributes, which are implicit in XML.)
+
+ The layering of network and transport protocols are maintained in
+ this RFC despite the optimizations that could be made if the line
+ were somewhat blurred (i.e. merging TCP and IP into a single, larger
+ element in the DTD) in order to foster future use of this protocol as
+ a basis for reformulating other protocols (such as ICMP.)
+
+ Other than the encoding, the behavioral aspects of each of the
+ existing protocols remain unchanged. Routing, address spaces, TCP
+ congestion control, etc. behave as specified in the extant standards.
+ Adapting to new standards and experimental algorithm heuristics for
+ improving performance will become much easier once the move to BLOAT
+ has been completed.
+
+1.4. Requirement Levels
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in BCP 14, RFC 2119
+ [RFC2119].
+
+2. IPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC.
+ IPoXML is the root protocol REQUIRED for effective use of TCPoXML
+ (section 3.) and higher-level application protocols.
+
+ The DTD for this document type can be found in section 7.1.
+
+ The routing of IPoXML can be easily implemented on hosts with an XML
+ parser, as the regular structure lends itself handily to parsing and
+ validation of the document/datagram and then processing the
+ destination address, TTL, and checksum before sending it on to its
+ next-hop.
+
+ The reformulation of IPv4 was chosen over IPv6 [RFC2460] due to the
+ wider deployment of IPv4 and the fact that implementing IPv6 as XML
+ would have exceeded the 1500 byte Ethernet MTU.
+
+
+
+Kennedy Informational [Page 2]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ All BLOAT implementations MUST use - and specify - the UTF-8 encoding
+ of RFC 2279 [RFC2279]. All BLOAT document/datagrams MUST be well-
+ formed and include the XMLDecl.
+
+2.1. IP Description
+
+ A number of items have changed (for the better) from the original IP
+ specification. Bit-masks, where present have been converted into
+ human-readable values. IP addresses are listed in their dotted-
+ decimal notation [RFC1123]. Length and checksum values are present
+ as decimal integers.
+
+ To calculate the length and checksum fields of the IP element, a
+ canonicalized form of the element MUST be used. The canonical form
+ SHALL have no whitespace (including newline characters) between
+ elements and only one space character between attributes. There
+ SHALL NOT be a space following the last attribute in an element.
+
+ An iterative method SHOULD be used to calculate checksums, as the
+ length field will vary based on the size of the checksum.
+
+ The payload element bears special attention. Due to the character
+ set restrictions of XML, the payload of IP datagrams (which MAY
+ contain arbitrary data) MUST be encoded for transport. This RFC
+ REQUIRES the contents of the payload to be encoded in the base-64
+ encoding of RFC 2045 [RFC2045], but removes the requirement that the
+ encoded output MUST be wrapped on 76-character lines.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 3]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+2.2. Example Datagram
+
+ The following is an example IPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ <ip>
+ <header length="474">
+ <version value="4"/>
+ <tos precedence="Routine" delay="Normal" throughput="Normal"
+ relibility="Normal" reserved="0"/>
+ <total.length value="461"/>
+ <id value="1"/>
+ <flags reserved="0" df="dont" mf="last"/>
+ <offset value="0"/>
+ <ttl value="255"/>
+ <protocol value="6"/>
+ <checksum value="8707"/>
+ <source address="10.0.0.22"/>
+ <destination address="10.0.0.1"/>
+ <options>
+ <end copied="0" class="0" number="0"/>
+ </options>
+ <padding pad="0"/>
+ </header>
+ <payload>
+ </payload>
+ </ip>
+
+3. TCPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.2.
+
+3.1. TCP Description
+
+ A number of items have changed from the original TCP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+ To calculate the length and checksum fields of the TCP element, a
+ canonicalized form of the element MUST be used as in section 2.1.
+
+ An iterative method SHOULD be used to calculate checksums as in
+ section 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+
+
+Kennedy Informational [Page 4]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ The TCP offset element was expanded to a maximum of 255 from 16 to
+ allow for the increased size of the header in XML.
+
+ TCPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+3.2. Example Datagram
+
+ The following is an example TCPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ <tcp>
+ <tcp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <sequence number="322622954"/>
+ <acknowledgement number="689715995"/>
+ <offset number=""/>
+ <reserved value="0"/>
+ <control syn="1" ack="1"/>
+ <window size="1"/>
+ <urgent pointer="0"/>
+ <checksum value="2988"/>
+ <tcp.options>
+ <tcp.end kind="0"/>
+ </tcp.options>
+ <padding pad="0"/>
+ </tcp.header>
+ <payload>
+ </payload>
+ </tcp>
+
+4. UDPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.3.
+
+4.1. UDP Description
+
+ A number of items have changed from the original UDP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+
+
+
+
+
+
+Kennedy Informational [Page 5]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ To calculate the length and checksum fields of the UDP element, a
+ canonicalized form of the element MUST be used as in section 2.1. An
+ iterative method SHOULD be used to calculate checksums as in section
+ 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+ UDPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+4.2. Example Datagram
+
+ The following is an example UDPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ <udp>
+ <udp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <udp.length value="143"/>
+ <checksum value="2988"/>
+ </udp.header>
+ <payload>
+ </payload>
+ </udp>
+
+5. Network Transport
+
+ This document provides for the transmission of BLOAT datagrams over
+ two common families of physical layer transport. Future RFCs will
+ address additional transports as routing vendors catch up to the
+ specification, and we begin to see BLOAT routed across the Internet
+ backbone.
+
+5.1. Ethernet
+
+ BLOAT is encapsulated in Ethernet datagrams as in [RFC894] with the
+ exception that the type field of the Ethernet frame MUST contain the
+ value 0xBEEF. The first 5 octets of the Ethernet frame payload will
+ be 0x3c 3f 78 6d 6c ("<?xml".)
+
+5.2. IEEE 802
+
+ BLOAT is encapsulated in IEEE 802 Networks as in [RFC1042] except
+ that the protocol type code for IPoXML is 0xBEEF.
+
+
+
+
+
+Kennedy Informational [Page 6]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+6. Gatewaying over IP
+
+ In order to facilitate the gradual introduction of BLOAT into the
+ public Internet, BLOAT MAY be encapsulated in IP as in [RFC2003] to
+ gateway between networks that run BLOAT natively on their LANs.
+
+7. DTDs
+
+ The Transport DTDs (7.2. and 7.3.) build on the definitions in the
+ Network DTD (7.1.)
+
+ The DTDs are referenced by their PubidLiteral and SystemLiteral (from
+ [XML]) although it is understood that most IPoXML implementations
+ will not need to pull down the DTD, as it will normally be embedded
+ in the implementation, and presents something of a catch-22 if you
+ need to load part of your network protocol over the network.
+
+7.1. IPoXML DTD
+
+ <!--
+ DTD for IP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ -->
+ <!--
+ DTD data types:
+
+ Digits [0..9]+
+
+ Precedence "NetworkControl | InternetworkControl |
+ CRITIC | FlashOverride | Flash | Immediate |
+ Priority | Routine"
+
+ IP4Addr "dotted-decimal" notation of [RFC1123]
+
+ Class [0..3]
+
+ Sec "Unclassified | Confidential | EFTO | MMMM | PROG |
+ Restricted | Secret | Top Secret | Reserved"
+
+ Compartments [0..65535]
+
+ Handling [0..65535]
+
+ TCC [0..16777216]
+
+ -->
+
+
+
+Kennedy Informational [Page 7]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ENTITY % Digits "CDATA">
+ <!ENTITY % Precedence "CDATA">
+ <!ENTITY % IP4Addr "CDATA">
+ <!ENTITY % Class "CDATA">
+ <!ENTITY % Sec "CDATA">
+ <!ENTITY % Compartments "CDATA">
+ <!ENTITY % Handling "CDATA">
+ <!ENTITY % TCC "CDATA">
+
+ <!ELEMENT ip (header, payload)>
+
+ <!ELEMENT header (version, tos, total.length, id, flags, offset, ttl,
+ protocol, checksum, source, destination, options,
+ padding)>
+ <!-- length of header in 32-bit words -->
+ <!ATTLIST header
+ length %Digits; #REQUIRED>
+
+ <!ELEMENT version EMPTY>
+ <!-- ip version. SHOULD be "4" -->
+ <!ATTLIST version
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT tos EMPTY>
+ <!ATTLIST tos
+ precedence %Precedence; #REQUIRED
+ delay (normal | low) #REQUIRED
+ throughput (normal | high) #REQUIRED
+ relibility (normal | high) #REQUIRED
+ reserved CDATA #FIXED "0">
+
+ <!ELEMENT total.length EMPTY>
+ <!--
+ total length of datagram (header and payload) in octets, MUST be
+ less than 65,535 (and SHOULD be less than 1024 for IPoXML on local
+ ethernets).
+ -->
+ <!ATTLIST total.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT id EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST id
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT flags EMPTY>
+ <!-- df = don't fragment, mf = more fragments -->
+ <!ATTLIST flags
+
+
+
+Kennedy Informational [Page 8]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ reserved CDATA #FIXED "0"
+ df (may|dont) #REQUIRED
+ mf (last|more) #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= offset <= 8192 measured in 8 octet (64-bit) chunks -->
+ <!ATTLIST offset
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT ttl EMPTY>
+ <!-- 0 <= ttl <= 255 -->
+ <!ATTLIST ttl
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT protocol EMPTY>
+ <!-- 0 <= protocol <= 255 (per IANA) -->
+ <!ATTLIST protocol
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT checksum EMPTY>
+ <!-- 0 <= checksum <= 65535 (over header only) -->
+ <!ATTLIST checksum
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT source EMPTY>
+ <!ATTLIST source
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT destination EMPTY>
+ <!ATTLIST destination
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT options ( end | noop | security | loose | strict | record
+ | stream | timestamp )*>
+
+ <!ELEMENT end EMPTY>
+ <!ATTLIST end
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "0">
+
+ <!ELEMENT noop EMPTY>
+ <!ATTLIST noop
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "1">
+
+ <!ELEMENT security EMPTY>
+
+
+
+Kennedy Informational [Page 9]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST security
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "2"
+ length CDATA #FIXED "11"
+ security %Sec; #REQUIRED
+ compartments %Compartments; #REQUIRED
+ handling %Handling; #REQUIRED
+ tcc %TCC; #REQUIRED>
+ <!ELEMENT loose (hop)+>
+ <!ATTLIST loose
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "3"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT hop EMPTY>
+ <!ATTLIST hop
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT strict (hop)+>
+ <!ATTLIST strict
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "9"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT record (hop)+>
+ <!ATTLIST record
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "7"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT stream EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST stream
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "8"
+ length CDATA #FIXED "4"
+ id %Digits; #REQUIRED>
+
+ <!ELEMENT timestamp (tstamp)+>
+ <!-- 0 <= oflw <=15 -->
+
+
+
+Kennedy Informational [Page 10]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST timestamp
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "2"
+ number CDATA #FIXED "4"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED
+ oflw %Digits; #REQUIRED
+ flag (0 | 1 | 3) #REQUIRED>
+
+ <!ELEMENT tstamp EMPTY>
+ <!ATTLIST tstamp
+ time %Digits; #REQUIRED
+ address %IP4Addr; #IMPLIED>
+ <!--
+ padding to bring header to 32-bit boundary.
+ pad MUST be "0"*
+ -->
+ <!ELEMENT padding EMPTY>
+ <!ATTLIST padding
+ pad CDATA #REQUIRED>
+
+ <!-- payload MUST be encoded as base-64 [RFC2045], as modified
+ by section 2.1 of this RFC -->
+ <!ELEMENT payload (CDATA)>
+
+7.2. TCPoXML DTD
+
+ <!--
+ DTD for TCP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ -->
+
+ <!-- the pseudoheader is only included for checksum calculations -->
+ <!ELEMENT tcp (tcp.pseudoheader?, tcp.header, payload)>
+
+ <!ELEMENT tcp.header (src, dest, sequence, acknowledgement, offset,
+ reserved, control, window, checksum, urgent,
+ tcp.options, padding)>
+
+ <!ELEMENT src EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+ <!ATTLIST src
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT dest EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+
+
+
+Kennedy Informational [Page 11]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST dest
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT sequence EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST sequence
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT acknowledgement EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST acknowledgement
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= number <= 255 -->
+ <!ATTLIST offset
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT reserved EMPTY>
+ <!ATTLIST reserved
+ value CDATA #FIXED "0">
+
+ <!ELEMENT control EMPTY>
+ <!ATTLIST control
+ urg (0|1) #IMPLIED
+ ack (0|1) #IMPLIED
+ psh (0|1) #IMPLIED
+ rst (0|1) #IMPLIED
+ syn (0|1) #IMPLIED
+ fin (0|1) #IMPLIED>
+
+ <!ELEMENT window EMPTY>
+ <!-- 0 <= size <= 65,535 -->
+ <!ATTLIST window
+ size %Digits; #REQUIRED>
+
+ <!--
+ checksum as in ip, but with
+ the following pseudo-header added into the tcp element:
+ -->
+ <!ELEMENT tcp.pseudoheader (source, destination, protocol,
+ tcp.length)>
+
+ <!--
+ tcp header + data length in octets. does not include the size of
+
+ the pseudoheader.
+ -->
+
+
+
+Kennedy Informational [Page 12]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ELEMENT tcp.length EMPTY>
+ <!ATTLIST tcp.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT urgent EMPTY>
+ <!-- 0 <= pointer <= 65,535 -->
+ <!ATTLIST urgent
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT tcp.options (tcp.end | tcp.noop | tcp.mss)+>
+
+ <!ELEMENT tcp.end EMPTY>
+ <!ATTLIST tcp.end
+ kind CDATA #FIXED "0">
+
+ <!ELEMENT tcp.noop EMPTY>
+ <!ATTLIST tcp.noop
+ kind CDATA #FIXED "1">
+
+ <!ELEMENT tcp.mss EMPTY>
+ <!ATTLIST tcp.mss
+ kind CDATA #FIXED "2"
+ length CDATA #FIXED "4"
+ size %Digits; #REQUIRED>
+
+7.3. UDPoXML DTD
+
+ <!--
+ DTD for UDP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ -->
+
+ <!ELEMENT udp (udp.pseudoheader?, udp.header, payload)>
+
+ <!ELEMENT udp.header (src, dest, udp.length, checksum)>
+
+ <!ELEMENT udp.pseudoheader (source, destination, protocol,
+ udp.length)>
+
+ <!--
+ udp header + data length in octets. does not include the size of
+ the pseudoheader.
+ -->
+ <!ELEMENT udp.length EMPTY>
+ <!ATTLIST udp.length
+ value %Digits; #REQUIRED>
+
+
+
+Kennedy Informational [Page 13]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+8. Security Considerations
+
+ XML, as a subset of SGML, has the same security considerations as
+ specified in SGML Media Types [RFC1874]. Security considerations
+ that apply to IP, TCP and UDP also likely apply to BLOAT as it does
+ not attempt to correct for issues not related to message format.
+
+9. References
+
+ [JABBER] Miller, J., "Jabber", draft-miller-jabber-00.txt,
+ February 2002. (Work in Progress)
+
+ [RFC768] Postel, J., "User Datagram Protocol", STD 6, RFC 768,
+ August 1980.
+
+ [RFC791] Postel, J., "Internet Protocol", STD 5, RFC 791,
+ September 1981.
+
+ [RFC793] Postel, J., "Transmission Control Protocol", STD 7, RFC
+ 793, September 1981.
+
+ [RFC894] Hornig, C., "Standard for the Transmission of IP
+ Datagrams over Ethernet Networks.", RFC 894, April 1984.
+
+ [RFC1042] Postel, J. and J. Reynolds, "Standard for the
+ Transmission of IP Datagrams Over IEEE 802 Networks", STD
+ 43, RFC 1042, February 1988.
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts -
+ Application and Support", RFC 1123, October 1989.
+
+ [RFC1874] Levinson, E., "SGML Media Types", RFC 1874, December
+ 1995.
+
+ [RFC2003] Perkins, C., "IP Encapsulation within IP", RFC 2003,
+ October 1996.
+
+ [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message
+ Bodies", RFC 2045, November 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+
+
+
+
+Kennedy Informational [Page 14]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ [RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6
+ (IPv6) Specification", RFC 2460, December 1998.
+
+ [RFC3080] Rose, M., "The Blocks Extensible Exchange Protocol Core",
+ RFC 3080, March 2001.
+
+ [SOAP] Box, D., Ehnebuske, D., Kakivaya, G., Layman, A.,
+ Mendelsohn, N., Nielsen, H. F., Thatte, S. Winer, D.,
+ "Simple Object Access Protocol (SOAP) 1.1" World Wide Web
+ Consortium Note, May 2000 http://www.w3.org/TR/SOAP/
+
+ [XML] Bray, T., Paoli, J., Sperberg-McQueen, C. M., "Extensible
+ Markup Language (XML)" World Wide Web Consortium
+ Recommendation REC- xml-19980210.
+ http://www.w3.org/TR/1998/REC-xml-19980210
+
+10. Author's Address
+
+ Hugh Kennedy
+ Mimezine
+ 1060 West Addison
+ Chicago, IL 60613
+ USA
+
+ EMail: kennedyh@engin.umich.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 15]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+11. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 16]
+
+
+
+
+
+
+
+Network Working Group H. Kennedy
+Request for Comments: 3252 Mimezine
+Category: Informational 1 April 2002
+
+
+ Binary Lexical Octet Ad-hoc Transport
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ This document defines a reformulation of IP and two transport layer
+ protocols (TCP and UDP) as XML applications.
+
+1. Introduction
+
+1.1. Overview
+
+ This document describes the Binary Lexical Octet Ad-hoc Transport
+ (BLOAT): a reformulation of a widely-deployed network-layer protocol
+ (IP [RFC791]), and two associated transport layer protocols (TCP
+ [RFC793] and UDP [RFC768]) as XML [XML] applications. It also
+ describes methods for transporting BLOAT over Ethernet and IEEE 802
+ networks as well as encapsulating BLOAT in IP for gatewaying BLOAT
+ across the public Internet.
+
+1.2. Motivation
+
+ The wild popularity of XML as a basis for application-level protocols
+ such as the Blocks Extensible Exchange Protocol [RFC3080], the Simple
+ Object Access Protocol [SOAP], and Jabber [JABBER] prompted
+ investigation into the possibility of extending the use of XML in the
+ protocol stack. Using XML at both the transport and network layer in
+ addition to the application layer would provide for an amazing amount
+ of power and flexibility while removing dependencies on proprietary
+ and hard-to-understand binary protocols. This protocol unification
+ would also allow applications to use a single XML parser for all
+ aspects of their operation, eliminating developer time spent figuring
+ out the intricacies of each new protocol, and moving the hard work of
+
+
+
+
+Kennedy Informational [Page 1]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ parsing to the XML toolset. The use of XML also mitigates concerns
+ over "network vs. host" byte ordering which is at the root of many
+ network application bugs.
+
+1.3. Relation to Existing Protocols
+
+ The reformulations specified in this RFC follow as closely as
+ possible the spirit of the RFCs on which they are based, and so MAY
+ contain elements or attributes that would not be needed in a pure
+ reworking (e.g. length attributes, which are implicit in XML.)
+
+ The layering of network and transport protocols are maintained in
+ this RFC despite the optimizations that could be made if the line
+ were somewhat blurred (i.e. merging TCP and IP into a single, larger
+ element in the DTD) in order to foster future use of this protocol as
+ a basis for reformulating other protocols (such as ICMP.)
+
+ Other than the encoding, the behavioral aspects of each of the
+ existing protocols remain unchanged. Routing, address spaces, TCP
+ congestion control, etc. behave as specified in the extant standards.
+ Adapting to new standards and experimental algorithm heuristics for
+ improving performance will become much easier once the move to BLOAT
+ has been completed.
+
+1.4. Requirement Levels
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in BCP 14, RFC 2119
+ [RFC2119].
+
+2. IPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC.
+ IPoXML is the root protocol REQUIRED for effective use of TCPoXML
+ (section 3.) and higher-level application protocols.
+
+ The DTD for this document type can be found in section 7.1.
+
+ The routing of IPoXML can be easily implemented on hosts with an XML
+ parser, as the regular structure lends itself handily to parsing and
+ validation of the document/datagram and then processing the
+ destination address, TTL, and checksum before sending it on to its
+ next-hop.
+
+ The reformulation of IPv4 was chosen over IPv6 [RFC2460] due to the
+ wider deployment of IPv4 and the fact that implementing IPv6 as XML
+ would have exceeded the 1500 byte Ethernet MTU.
+
+
+
+Kennedy Informational [Page 2]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ All BLOAT implementations MUST use - and specify - the UTF-8 encoding
+ of RFC 2279 [RFC2279]. All BLOAT document/datagrams MUST be well-
+ formed and include the XMLDecl.
+
+2.1. IP Description
+
+ A number of items have changed (for the better) from the original IP
+ specification. Bit-masks, where present have been converted into
+ human-readable values. IP addresses are listed in their dotted-
+ decimal notation [RFC1123]. Length and checksum values are present
+ as decimal integers.
+
+ To calculate the length and checksum fields of the IP element, a
+ canonicalized form of the element MUST be used. The canonical form
+ SHALL have no whitespace (including newline characters) between
+ elements and only one space character between attributes. There
+ SHALL NOT be a space following the last attribute in an element.
+
+ An iterative method SHOULD be used to calculate checksums, as the
+ length field will vary based on the size of the checksum.
+
+ The payload element bears special attention. Due to the character
+ set restrictions of XML, the payload of IP datagrams (which MAY
+ contain arbitrary data) MUST be encoded for transport. This RFC
+ REQUIRES the contents of the payload to be encoded in the base-64
+ encoding of RFC 2045 [RFC2045], but removes the requirement that the
+ encoded output MUST be wrapped on 76-character lines.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 3]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+2.2. Example Datagram
+
+ The following is an example IPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ <ip>
+ <header length="474">
+ <version value="4"/>
+ <tos precedence="Routine" delay="Normal" throughput="Normal"
+ relibility="Normal" reserved="0"/>
+ <total.length value="461"/>
+ <id value="1"/>
+ <flags reserved="0" df="dont" mf="last"/>
+ <offset value="0"/>
+ <ttl value="255"/>
+ <protocol value="6"/>
+ <checksum value="8707"/>
+ <source address="10.0.0.22"/>
+ <destination address="10.0.0.1"/>
+ <options>
+ <end copied="0" class="0" number="0"/>
+ </options>
+ <padding pad="0"/>
+ </header>
+ <payload>
+ </payload>
+ </ip>
+
+3. TCPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.2.
+
+3.1. TCP Description
+
+ A number of items have changed from the original TCP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+ To calculate the length and checksum fields of the TCP element, a
+ canonicalized form of the element MUST be used as in section 2.1.
+
+ An iterative method SHOULD be used to calculate checksums as in
+ section 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+
+
+Kennedy Informational [Page 4]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ The TCP offset element was expanded to a maximum of 255 from 16 to
+ allow for the increased size of the header in XML.
+
+ TCPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+3.2. Example Datagram
+
+ The following is an example TCPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ <tcp>
+ <tcp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <sequence number="322622954"/>
+ <acknowledgement number="689715995"/>
+ <offset number=""/>
+ <reserved value="0"/>
+ <control syn="1" ack="1"/>
+ <window size="1"/>
+ <urgent pointer="0"/>
+ <checksum value="2988"/>
+ <tcp.options>
+ <tcp.end kind="0"/>
+ </tcp.options>
+ <padding pad="0"/>
+ </tcp.header>
+ <payload>
+ </payload>
+ </tcp>
+
+4. UDPoXML
+
+ This protocol MUST be implemented to be compliant with this RFC. The
+ DTD for this document type can be found in section 7.3.
+
+4.1. UDP Description
+
+ A number of items have changed from the original UDP specification.
+ Bit-masks, where present have been converted into human-readable
+ values. Length and checksum and port values are present as decimal
+ integers.
+
+
+
+
+
+
+
+Kennedy Informational [Page 5]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ To calculate the length and checksum fields of the UDP element, a
+ canonicalized form of the element MUST be used as in section 2.1. An
+ iterative method SHOULD be used to calculate checksums as in section
+ 2.1.
+
+ The payload element MUST be encoded as in section 2.1.
+
+ UDPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header
+ as well as the <!DOCTYPE> declaration.
+
+4.2. Example Datagram
+
+ The following is an example UDPoXML datagram with an empty payload:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ <udp>
+ <udp.header>
+ <src port="31415"/>
+ <dest port="42424"/>
+ <udp.length value="143"/>
+ <checksum value="2988"/>
+ </udp.header>
+ <payload>
+ </payload>
+ </udp>
+
+5. Network Transport
+
+ This document provides for the transmission of BLOAT datagrams over
+ two common families of physical layer transport. Future RFCs will
+ address additional transports as routing vendors catch up to the
+ specification, and we begin to see BLOAT routed across the Internet
+ backbone.
+
+5.1. Ethernet
+
+ BLOAT is encapsulated in Ethernet datagrams as in [RFC894] with the
+ exception that the type field of the Ethernet frame MUST contain the
+ value 0xBEEF. The first 5 octets of the Ethernet frame payload will
+ be 0x3c 3f 78 6d 6c ("<?xml".)
+
+5.2. IEEE 802
+
+ BLOAT is encapsulated in IEEE 802 Networks as in [RFC1042] except
+ that the protocol type code for IPoXML is 0xBEEF.
+
+
+
+
+
+Kennedy Informational [Page 6]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+6. Gatewaying over IP
+
+ In order to facilitate the gradual introduction of BLOAT into the
+ public Internet, BLOAT MAY be encapsulated in IP as in [RFC2003] to
+ gateway between networks that run BLOAT natively on their LANs.
+
+7. DTDs
+
+ The Transport DTDs (7.2. and 7.3.) build on the definitions in the
+ Network DTD (7.1.)
+
+ The DTDs are referenced by their PubidLiteral and SystemLiteral (from
+ [XML]) although it is understood that most IPoXML implementations
+ will not need to pull down the DTD, as it will normally be embedded
+ in the implementation, and presents something of a catch-22 if you
+ need to load part of your network protocol over the network.
+
+7.1. IPoXML DTD
+
+ <!--
+ DTD for IP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd">
+ -->
+ <!--
+ DTD data types:
+
+ Digits [0..9]+
+
+ Precedence "NetworkControl | InternetworkControl |
+ CRITIC | FlashOverride | Flash | Immediate |
+ Priority | Routine"
+
+ IP4Addr "dotted-decimal" notation of [RFC1123]
+
+ Class [0..3]
+
+ Sec "Unclassified | Confidential | EFTO | MMMM | PROG |
+ Restricted | Secret | Top Secret | Reserved"
+
+ Compartments [0..65535]
+
+ Handling [0..65535]
+
+ TCC [0..16777216]
+
+ -->
+
+
+
+Kennedy Informational [Page 7]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ENTITY % Digits "CDATA">
+ <!ENTITY % Precedence "CDATA">
+ <!ENTITY % IP4Addr "CDATA">
+ <!ENTITY % Class "CDATA">
+ <!ENTITY % Sec "CDATA">
+ <!ENTITY % Compartments "CDATA">
+ <!ENTITY % Handling "CDATA">
+ <!ENTITY % TCC "CDATA">
+
+ <!ELEMENT ip (header, payload)>
+
+ <!ELEMENT header (version, tos, total.length, id, flags, offset, ttl,
+ protocol, checksum, source, destination, options,
+ padding)>
+ <!-- length of header in 32-bit words -->
+ <!ATTLIST header
+ length %Digits; #REQUIRED>
+
+ <!ELEMENT version EMPTY>
+ <!-- ip version. SHOULD be "4" -->
+ <!ATTLIST version
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT tos EMPTY>
+ <!ATTLIST tos
+ precedence %Precedence; #REQUIRED
+ delay (normal | low) #REQUIRED
+ throughput (normal | high) #REQUIRED
+ relibility (normal | high) #REQUIRED
+ reserved CDATA #FIXED "0">
+
+ <!ELEMENT total.length EMPTY>
+ <!--
+ total length of datagram (header and payload) in octets, MUST be
+ less than 65,535 (and SHOULD be less than 1024 for IPoXML on local
+ ethernets).
+ -->
+ <!ATTLIST total.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT id EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST id
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT flags EMPTY>
+ <!-- df = don't fragment, mf = more fragments -->
+ <!ATTLIST flags
+
+
+
+Kennedy Informational [Page 8]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ reserved CDATA #FIXED "0"
+ df (may|dont) #REQUIRED
+ mf (last|more) #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= offset <= 8192 measured in 8 octet (64-bit) chunks -->
+ <!ATTLIST offset
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT ttl EMPTY>
+ <!-- 0 <= ttl <= 255 -->
+ <!ATTLIST ttl
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT protocol EMPTY>
+ <!-- 0 <= protocol <= 255 (per IANA) -->
+ <!ATTLIST protocol
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT checksum EMPTY>
+ <!-- 0 <= checksum <= 65535 (over header only) -->
+ <!ATTLIST checksum
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT source EMPTY>
+ <!ATTLIST source
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT destination EMPTY>
+ <!ATTLIST destination
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT options ( end | noop | security | loose | strict | record
+ | stream | timestamp )*>
+
+ <!ELEMENT end EMPTY>
+ <!ATTLIST end
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "0">
+
+ <!ELEMENT noop EMPTY>
+ <!ATTLIST noop
+ copied (0|1) #REQUIRED
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "1">
+
+ <!ELEMENT security EMPTY>
+
+
+
+Kennedy Informational [Page 9]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST security
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "2"
+ length CDATA #FIXED "11"
+ security %Sec; #REQUIRED
+ compartments %Compartments; #REQUIRED
+ handling %Handling; #REQUIRED
+ tcc %TCC; #REQUIRED>
+ <!ELEMENT loose (hop)+>
+ <!ATTLIST loose
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "3"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT hop EMPTY>
+ <!ATTLIST hop
+ address %IP4Addr; #REQUIRED>
+
+ <!ELEMENT strict (hop)+>
+ <!ATTLIST strict
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "9"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT record (hop)+>
+ <!ATTLIST record
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "7"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT stream EMPTY>
+ <!-- 0 <= id <= 65,535 -->
+ <!ATTLIST stream
+ copied CDATA #FIXED "1"
+ class CDATA #FIXED "0"
+ number CDATA #FIXED "8"
+ length CDATA #FIXED "4"
+ id %Digits; #REQUIRED>
+
+ <!ELEMENT timestamp (tstamp)+>
+ <!-- 0 <= oflw <=15 -->
+
+
+
+Kennedy Informational [Page 10]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST timestamp
+ copied CDATA #FIXED "0"
+ class CDATA #FIXED "2"
+ number CDATA #FIXED "4"
+ length %Digits; #REQUIRED
+ pointer %Digits; #REQUIRED
+ oflw %Digits; #REQUIRED
+ flag (0 | 1 | 3) #REQUIRED>
+
+ <!ELEMENT tstamp EMPTY>
+ <!ATTLIST tstamp
+ time %Digits; #REQUIRED
+ address %IP4Addr; #IMPLIED>
+ <!--
+ padding to bring header to 32-bit boundary.
+ pad MUST be "0"*
+ -->
+ <!ELEMENT padding EMPTY>
+ <!ATTLIST padding
+ pad CDATA #REQUIRED>
+
+ <!-- payload MUST be encoded as base-64 [RFC2045], as modified
+ by section 2.1 of this RFC -->
+ <!ELEMENT payload (CDATA)>
+
+7.2. TCPoXML DTD
+
+ <!--
+ DTD for TCP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd">
+ -->
+
+ <!-- the pseudoheader is only included for checksum calculations -->
+ <!ELEMENT tcp (tcp.pseudoheader?, tcp.header, payload)>
+
+ <!ELEMENT tcp.header (src, dest, sequence, acknowledgement, offset,
+ reserved, control, window, checksum, urgent,
+ tcp.options, padding)>
+
+ <!ELEMENT src EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+ <!ATTLIST src
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT dest EMPTY>
+ <!-- 0 <= port <= 65,535 -->
+
+
+
+Kennedy Informational [Page 11]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ATTLIST dest
+ port %Digits; #REQUIRED>
+
+ <!ELEMENT sequence EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST sequence
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT acknowledgement EMPTY>
+ <!-- 0 <= number <= 4294967295 -->
+ <!ATTLIST acknowledgement
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT offset EMPTY>
+ <!-- 0 <= number <= 255 -->
+ <!ATTLIST offset
+ number %Digits; #REQUIRED>
+
+ <!ELEMENT reserved EMPTY>
+ <!ATTLIST reserved
+ value CDATA #FIXED "0">
+
+ <!ELEMENT control EMPTY>
+ <!ATTLIST control
+ urg (0|1) #IMPLIED
+ ack (0|1) #IMPLIED
+ psh (0|1) #IMPLIED
+ rst (0|1) #IMPLIED
+ syn (0|1) #IMPLIED
+ fin (0|1) #IMPLIED>
+
+ <!ELEMENT window EMPTY>
+ <!-- 0 <= size <= 65,535 -->
+ <!ATTLIST window
+ size %Digits; #REQUIRED>
+
+ <!--
+ checksum as in ip, but with
+ the following pseudo-header added into the tcp element:
+ -->
+ <!ELEMENT tcp.pseudoheader (source, destination, protocol,
+ tcp.length)>
+
+ <!--
+ tcp header + data length in octets. does not include the size of
+
+ the pseudoheader.
+ -->
+
+
+
+Kennedy Informational [Page 12]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ <!ELEMENT tcp.length EMPTY>
+ <!ATTLIST tcp.length
+ value %Digits; #REQUIRED>
+
+ <!ELEMENT urgent EMPTY>
+ <!-- 0 <= pointer <= 65,535 -->
+ <!ATTLIST urgent
+ pointer %Digits; #REQUIRED>
+
+ <!ELEMENT tcp.options (tcp.end | tcp.noop | tcp.mss)+>
+
+ <!ELEMENT tcp.end EMPTY>
+ <!ATTLIST tcp.end
+ kind CDATA #FIXED "0">
+
+ <!ELEMENT tcp.noop EMPTY>
+ <!ATTLIST tcp.noop
+ kind CDATA #FIXED "1">
+
+ <!ELEMENT tcp.mss EMPTY>
+ <!ATTLIST tcp.mss
+ kind CDATA #FIXED "2"
+ length CDATA #FIXED "4"
+ size %Digits; #REQUIRED>
+
+7.3. UDPoXML DTD
+
+ <!--
+ DTD for UDP over XML.
+ Refer to this DTD as:
+
+ <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd">
+ -->
+
+ <!ELEMENT udp (udp.pseudoheader?, udp.header, payload)>
+
+ <!ELEMENT udp.header (src, dest, udp.length, checksum)>
+
+ <!ELEMENT udp.pseudoheader (source, destination, protocol,
+ udp.length)>
+
+ <!--
+ udp header + data length in octets. does not include the size of
+ the pseudoheader.
+ -->
+ <!ELEMENT udp.length EMPTY>
+ <!ATTLIST udp.length
+ value %Digits; #REQUIRED>
+
+
+
+Kennedy Informational [Page 13]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+8. Security Considerations
+
+ XML, as a subset of SGML, has the same security considerations as
+ specified in SGML Media Types [RFC1874]. Security considerations
+ that apply to IP, TCP and UDP also likely apply to BLOAT as it does
+ not attempt to correct for issues not related to message format.
+
+9. References
+
+ [JABBER] Miller, J., "Jabber", draft-miller-jabber-00.txt,
+ February 2002. (Work in Progress)
+
+ [RFC768] Postel, J., "User Datagram Protocol", STD 6, RFC 768,
+ August 1980.
+
+ [RFC791] Postel, J., "Internet Protocol", STD 5, RFC 791,
+ September 1981.
+
+ [RFC793] Postel, J., "Transmission Control Protocol", STD 7, RFC
+ 793, September 1981.
+
+ [RFC894] Hornig, C., "Standard for the Transmission of IP
+ Datagrams over Ethernet Networks.", RFC 894, April 1984.
+
+ [RFC1042] Postel, J. and J. Reynolds, "Standard for the
+ Transmission of IP Datagrams Over IEEE 802 Networks", STD
+ 43, RFC 1042, February 1988.
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts -
+ Application and Support", RFC 1123, October 1989.
+
+ [RFC1874] Levinson, E., "SGML Media Types", RFC 1874, December
+ 1995.
+
+ [RFC2003] Perkins, C., "IP Encapsulation within IP", RFC 2003,
+ October 1996.
+
+ [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message
+ Bodies", RFC 2045, November 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+
+
+
+
+Kennedy Informational [Page 14]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+ [RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6
+ (IPv6) Specification", RFC 2460, December 1998.
+
+ [RFC3080] Rose, M., "The Blocks Extensible Exchange Protocol Core",
+ RFC 3080, March 2001.
+
+ [SOAP] Box, D., Ehnebuske, D., Kakivaya, G., Layman, A.,
+ Mendelsohn, N., Nielsen, H. F., Thatte, S. Winer, D.,
+ "Simple Object Access Protocol (SOAP) 1.1" World Wide Web
+ Consortium Note, May 2000 http://www.w3.org/TR/SOAP/
+
+ [XML] Bray, T., Paoli, J., Sperberg-McQueen, C. M., "Extensible
+ Markup Language (XML)" World Wide Web Consortium
+ Recommendation REC- xml-19980210.
+ http://www.w3.org/TR/1998/REC-xml-19980210
+
+10. Author's Address
+
+ Hugh Kennedy
+ Mimezine
+ 1060 West Addison
+ Chicago, IL 60613
+ USA
+
+ EMail: kennedyh@engin.umich.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kennedy Informational [Page 15]
+
+RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002
+
+
+11. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+