summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2016-10-08 16:41:51 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2016-10-08 16:41:51 (GMT)
commit42bb1615c096d6485d36f6a07eab36f2e2e95b3b (patch)
treed5b3a9663302e1a59ba7aad9e0aa489de6650bf6
parentbe3376f36c02b2b317b509aed67b7751e656ecbb (diff)
parent0ac8f1e19818ac7aa6fd35de8e3190bcd24dcb6d (diff)
downloadtcl-42bb1615c096d6485d36f6a07eab36f2e2e95b3b.zip
tcl-42bb1615c096d6485d36f6a07eab36f2e2e95b3b.tar.gz
tcl-42bb1615c096d6485d36f6a07eab36f2e2e95b3b.tar.bz2
[838e99a76d] Ensure that encodings are handled with application/xml and friends.
-rw-r--r--library/http/http.tcl34
-rw-r--r--tests/http.test8
-rw-r--r--tests/httpd4
3 files changed, 45 insertions, 1 deletions
diff --git a/library/http/http.tcl b/library/http/http.tcl
index 5a05fa0..dfd6996 100644
--- a/library/http/http.tcl
+++ b/library/http/http.tcl
@@ -1047,7 +1047,7 @@ proc http::Event {sock token} {
fconfigure $sock -translation binary
if {
- $state(-binary) || ![string match -nocase text* $state(type)]
+ $state(-binary) || [IsBinaryContentType $state(type)]
} {
# Turn off conversions for non-text data
set state(binary) 1
@@ -1183,6 +1183,38 @@ proc http::Event {sock token} {
}
}
+# http::IsBinaryContentType --
+#
+# Determine if the content-type means that we should definitely transfer
+# the data as binary. [Bug 838e99a76d]
+#
+# Arguments
+# type The content-type of the data.
+#
+# Results:
+# Boolean, true if we definitely should be binary.
+
+proc http::IsBinaryContentType {type} {
+ lassign [split [string tolower $type] "/;"] major minor
+ if {$major eq "text"} {
+ return false
+ }
+ # There's a bunch of XML-as-application-format things about. See RFC 3023
+ # and so on.
+ if {$major eq "application"} {
+ set minor [string trimright $minor]
+ if {$minor in {"xml" "xml-external-parsed-entity" "xml-dtd"}} {
+ return false
+ }
+ }
+ # Not just application/foobar+xml but also image/svg+xml, so let us not
+ # restrict things for now...
+ if {[string match "*+xml" $minor]} {
+ return false
+ }
+ return true
+}
+
# http::getTextLine --
#
# Get one line with the stream in blocking crlf mode
diff --git a/tests/http.test b/tests/http.test
index 41820cb..12ad475 100644
--- a/tests/http.test
+++ b/tests/http.test
@@ -133,6 +133,7 @@ set tail /a/b/c
set url //[info hostname]:$port/a/b/c
set fullurl HTTP://user:pass@[info hostname]:$port/a/b/c
set binurl //[info hostname]:$port/binary
+set xmlurl //[info hostname]:$port/xml
set posturl //[info hostname]:$port/post
set badposturl //[info hostname]:$port/droppost
set authorityurl //[info hostname]:$port
@@ -431,6 +432,13 @@ Accept text/plain,application/tcl-test-value
Accept-Encoding .*
Content-Type application/x-www-form-urlencoded
Content-Length 5}
+# Bug 838e99a76d
+test http-3.33 {http::geturl application/xml is text} -body {
+ set token [http::geturl "$xmlurl"]
+ scan [http::data $token] "<%\[^>]>%c<%\[^>]>"
+} -cleanup {
+ catch { http::cleanup $token }
+} -result {test 4660 /test}
test http-4.1 {http::Event} -body {
set token [http::geturl $url -keepalive 0]
diff --git a/tests/httpd b/tests/httpd
index c934fac..40e10df 100644
--- a/tests/httpd
+++ b/tests/httpd
@@ -171,6 +171,10 @@ proc httpdRespond { sock } {
set html "$bindata[info hostname]:$port$data(url)"
set type application/octet-stream
}
+ *xml* {
+ set html [encoding convertto utf-8 "<test>\u1234</test>"]
+ set type "application/xml;charset=UTF-8"
+ }
*post* {
set html "Got [string length $data(query)] bytes"
set type text/plain