summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2015-05-20 13:37:21 (GMT)
committerdgp <dgp@users.sourceforge.net>2015-05-20 13:37:21 (GMT)
commitbd81f35273a7f2adea0f6e0f66f857a524dceec9 (patch)
treeb3e3f73a78933014c3a4402dac60b91d60897007
parent0ae5b5b3c1f58cf3ff2dff3f8c4b8191a9ef52bd (diff)
parentdeaa520c802ca31794d50a7afcbd691982111076 (diff)
downloadtcl-bd81f35273a7f2adea0f6e0f66f857a524dceec9.zip
tcl-bd81f35273a7f2adea0f6e0f66f857a524dceec9.tar.gz
tcl-bd81f35273a7f2adea0f6e0f66f857a524dceec9.tar.bz2
merge trunk
-rw-r--r--doc/re_syntax.n26
-rw-r--r--generic/tclCompCmdsGR.c15
-rw-r--r--library/http/http.tcl41
-rw-r--r--tests/http.test24
4 files changed, 76 insertions, 30 deletions
diff --git a/doc/re_syntax.n b/doc/re_syntax.n
index 46a180d..7988071 100644
--- a/doc/re_syntax.n
+++ b/doc/re_syntax.n
@@ -683,9 +683,33 @@ earlier in the RE taking priority over ones starting later. Note that
outer subexpressions thus take priority over their component
subexpressions.
.PP
-Note that the quantifiers \fB{1,1}\fR and \fB{1,1}?\fR can be used to
+The quantifiers \fB{1,1}\fR and \fB{1,1}?\fR can be used to
force longest and shortest preference, respectively, on a
subexpression or a whole RE.
+.RS
+.PP
+\fBNOTE:\fR This means that you can usually make a RE be non-greedy overall by
+putting \fB{1,1}?\fR after one of the first non-constraint atoms or
+parenthesized sub-expressions in it. \fIIt pays to experiment\fR with the
+placing of this non-greediness override on a suitable range of input texts
+when you are writing a RE if you are using this level of complexity.
+.PP
+For example, this regular expression is non-greedy, and will match the
+shortest substring possible given that
+.QW \fBabc\fR
+will be matched as early as possible (the quantifier does not change that):
+.PP
+.CS
+ab{1,1}?c.*x.*cba
+.CE
+.PP
+The atom
+.QW \fBa\fR
+has no greediness preference, we explicitly give one for
+.QW \fBb\fR ,
+and the remaining quantifiers are overridden to be non-greedy by the preceding
+non-greedy quantifier.
+.RE
.PP
Match lengths are measured in characters, not collating elements. An
empty string is considered longer than no match at all. For example,
diff --git a/generic/tclCompCmdsGR.c b/generic/tclCompCmdsGR.c
index b77c43c..b9c655b 100644
--- a/generic/tclCompCmdsGR.c
+++ b/generic/tclCompCmdsGR.c
@@ -1210,20 +1210,7 @@ TclCompileListCmd(
valueTokenPtr = TokenAfter(valueTokenPtr);
}
if (listObj != NULL) {
- int len;
- const char *bytes = Tcl_GetStringFromObj(listObj, &len);
-
- PushLiteral(envPtr, bytes, len);
- Tcl_DecrRefCount(listObj);
- if (len > 0) {
- /*
- * Force list interpretation!
- */
-
- TclEmitOpcode( INST_DUP, envPtr);
- TclEmitOpcode( INST_LIST_LENGTH, envPtr);
- TclEmitOpcode( INST_POP, envPtr);
- }
+ TclEmitPush(TclAddLiteralObj(envPtr, listObj, NULL), envPtr);
return TCL_OK;
}
diff --git a/library/http/http.tcl b/library/http/http.tcl
index 751ca13..5a05fa0 100644
--- a/library/http/http.tcl
+++ b/library/http/http.tcl
@@ -566,6 +566,10 @@ proc http::geturl {url args} {
# Proxy connections aren't shared among different hosts.
set state(socketinfo) $host:$port
+ # Save the accept types at this point to prevent a race condition. [Bug
+ # c11a51c482]
+ set state(accept-types) $http(-accept)
+
# See if we are supposed to use a previously opened channel.
if {$state(-keepalive)} {
variable socketmap
@@ -637,8 +641,20 @@ proc http::geturl {url args} {
return $token
}
+# http::Connected --
+#
+# Callback used when the connection to the HTTP server is actually
+# established.
+#
+# Arguments:
+# token State token.
+# proto What protocol (http, https, etc.) was used to connect.
+# phost Are we using keep-alive? Non-empty if yes.
+# srvurl Service-local URL that we're requesting
+# Results:
+# None.
-proc http::Connected { token proto phost srvurl} {
+proc http::Connected {token proto phost srvurl} {
variable http
variable urlTypes
@@ -691,13 +707,12 @@ proc http::Connected { token proto phost srvurl} {
if {[info exists state(-handler)]} {
set state(-protocol) 1.0
}
+ set accept_types_seen 0
if {[catch {
puts $sock "$how $srvurl HTTP/$state(-protocol)"
- puts $sock "Accept: $http(-accept)"
- array set hdrs $state(-headers)
- if {[info exists hdrs(Host)]} {
+ if {[dict exists $state(-headers) Host]} {
# Allow Host spoofing. [Bug 928154]
- puts $sock "Host: $hdrs(Host)"
+ puts $sock "Host: [dict get $state(-headers) Host]"
} elseif {$port == $defport} {
# Don't add port in this case, to handle broken servers. [Bug
# #504508]
@@ -705,7 +720,6 @@ proc http::Connected { token proto phost srvurl} {
} else {
puts $sock "Host: $host:$port"
}
- unset hdrs
puts $sock "User-Agent: $http(-useragent)"
if {$state(-protocol) == 1.0 && $state(-keepalive)} {
puts $sock "Connection: keep-alive"
@@ -718,18 +732,21 @@ proc http::Connected { token proto phost srvurl} {
}
set accept_encoding_seen 0
set content_type_seen 0
- foreach {key value} $state(-headers) {
+ dict for {key value} $state(-headers) {
+ set value [string map [list \n "" \r ""] $value]
+ set key [string map {" " -} [string trim $key]]
if {[string equal -nocase $key "host"]} {
continue
}
if {[string equal -nocase $key "accept-encoding"]} {
set accept_encoding_seen 1
}
+ if {[string equal -nocase $key "accept"]} {
+ set accept_types_seen 1
+ }
if {[string equal -nocase $key "content-type"]} {
set content_type_seen 1
}
- set value [string map [list \n "" \r ""] $value]
- set key [string trim $key]
if {[string equal -nocase $key "content-length"]} {
set contDone 1
set state(querylength) $value
@@ -738,6 +755,11 @@ proc http::Connected { token proto phost srvurl} {
puts $sock "$key: $value"
}
}
+ # Allow overriding the Accept header on a per-connection basis. Useful
+ # for working with REST services. [Bug c11a51c482]
+ if {!$accept_types_seen} {
+ puts $sock "Accept: $state(accept-types)"
+ }
if {!$accept_encoding_seen && ![info exists state(-handler)]} {
puts $sock "Accept-Encoding: gzip,deflate,compress"
}
@@ -795,7 +817,6 @@ proc http::Connected { token proto phost srvurl} {
Finish $token $err
}
}
-
}
# Data access functions:
diff --git a/tests/http.test b/tests/http.test
index a0a26de..41820cb 100644
--- a/tests/http.test
+++ b/tests/http.test
@@ -306,7 +306,6 @@ test http-3.13 {http::geturl socket leak test} {
for {set i 0} {$i < 3} {incr i} {
catch {http::geturl $badurl -timeout 5000}
}
-
# No extra channels should be taken
expr {[llength [file channels]] == $chanCount}
} 1
@@ -372,11 +371,11 @@ test http-3.27 {http::geturl: -headers override -type} -body {
http::data $token
} -cleanup {
http::cleanup $token
-} -match regexp -result {(?n)Accept \*/\*
-Host .*
+} -match regexp -result {(?n)Host .*
User-Agent .*
Connection close
Content-Type {text/plain;charset=utf-8}
+Accept \*/\*
Accept-Encoding .*
Content-Length 5}
test http-3.28 {http::geturl: -headers override -type default} -body {
@@ -385,11 +384,11 @@ test http-3.28 {http::geturl: -headers override -type default} -body {
http::data $token
} -cleanup {
http::cleanup $token
-} -match regexp -result {(?n)Accept \*/\*
-Host .*
+} -match regexp -result {(?n)Host .*
User-Agent .*
Connection close
Content-Type {text/plain;charset=utf-8}
+Accept \*/\*
Accept-Encoding .*
Content-Length 5}
test http-3.29 {http::geturl IPv6 address} -body {
@@ -418,6 +417,21 @@ test http-3.31 {http::geturl fragment without path} -body {
} -cleanup {
catch { http::cleanup $token }
} -result 200
+# Bug c11a51c482
+test http-3.32 {http::geturl: -headers override -accept default} -body {
+ set token [http::geturl $url/headers -query dummy \
+ -headers [list "Accept" "text/plain,application/tcl-test-value"]]
+ http::data $token
+} -cleanup {
+ http::cleanup $token
+} -match regexp -result {(?n)Host .*
+User-Agent .*
+Connection close
+Accept text/plain,application/tcl-test-value
+Accept-Encoding .*
+Content-Type application/x-www-form-urlencoded
+Content-Length 5}
+
test http-4.1 {http::Event} -body {
set token [http::geturl $url -keepalive 0]
upvar #0 $token data