summaryrefslogtreecommitdiffstats
path: root/library/safe.tcl
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2009-12-16 23:31:31 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2009-12-16 23:31:31 (GMT)
commit1bfee26eaac2704c6966f6a5138eb1ea6c60d0c9 (patch)
tree975d4feb1bef267978e6693d9d311cf84f92890f /library/safe.tcl
parentb37c64be40edeb5c2f75e084417fb802058ae239 (diff)
downloadtcl-1bfee26eaac2704c6966f6a5138eb1ea6c60d0c9.zip
tcl-1bfee26eaac2704c6966f6a5138eb1ea6c60d0c9.tar.gz
tcl-1bfee26eaac2704c6966f6a5138eb1ea6c60d0c9.tar.bz2
Upgrade to Safe Base's handling of [glob] to be more permissive with the
feature set supported, but stricter with path management. It also now has an error pattern more like the standard [glob] command.
Diffstat (limited to 'library/safe.tcl')
-rw-r--r--library/safe.tcl102
1 files changed, 77 insertions, 25 deletions
diff --git a/library/safe.tcl b/library/safe.tcl
index 52b539b..3b9ee19 100644
--- a/library/safe.tcl
+++ b/library/safe.tcl
@@ -12,7 +12,7 @@
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: safe.tcl,v 1.16.4.3 2009/12/09 22:34:20 andreas_kupries Exp $
+# RCS: @(#) $Id: safe.tcl,v 1.16.4.4 2009/12/16 23:31:31 dkf Exp $
#
# The implementation is based on namespaces. These naming conventions are
@@ -655,30 +655,43 @@ proc ::safe::AliasGlob {slave args} {
Log $slave "GLOB ! $args" NOTICE
set cmd {}
set at 0
+ array set got {
+ -directory 0
+ -nocomplain 0
+ -join 0
+ -tails 0
+ -- 0
+ }
+
+ if {$::tcl_platform(platform) eq "windows"} {
+ set dirPartRE {^(.*)[\\/]}
+ } else {
+ set dirPartRE {^(.*)/}
+ }
set dir {}
set virtualdir {}
while {$at < [llength $args]} {
switch -glob -- [set opt [lindex $args $at]] {
- -nocomplain -
- -join {
+ -nocomplain - -- - -join - -tails {
lappend cmd $opt
+ set got($opt) 1
incr at
}
- -directory {
- set virtualdir [lindex $args [incr at]]
- # Get the real path from the virtual one and check that the
- # path is in the access path of that slave.
- try {
- set dir [TranslatePath $slave $virtualdir]
- DirInAccessPath $slave $dir
- } on error msg {
- Log $slave $msg
- return -code error "permission denied"
+ -types - -type {
+ lappend cmd -types [lindex $args [incr at]]
+ incr at
+ }
+ -directory {
+ if {$got($opt)} {
+ return -code error \
+ {"-directory" cannot be used with "-path"}
}
- lappend cmd -directory $dir
+ set got($opt) 1
+ set virtualdir [lindex $args [incr at]]
incr at
+ lappend cmd -directory $dir
}
pkgIndex.tcl {
# Oops, this is globbing a subdirectory in regular package
@@ -692,22 +705,58 @@ proc ::safe::AliasGlob {slave args} {
return -code error "Safe base rejecting glob option '$opt'"
}
default {
- if {[regexp {(.*)[\\/]} $opt -> thedir]} {
- try {
- DirInAccessPath $slave [TranslatePath $slave $thedir]
- } on error msg {
- Log $slave $msg
- return -code error "permission denied"
- }
- }
- lappend cmd $opt
- incr at
+ break
+ }
+ }
+ if {$got(--) || $got(-join)} break
+ }
+
+ # Get the real path from the virtual one and check that the path is in the
+ # access path of that slave. Done after basic argument processing so that
+ # we know if -nocomplain is set.
+ if {$got(-directory)} {
+ if {[catch {
+ set dir [TranslatePath $slave $virtualdir]
+ DirInAccessPath $slave $dir
+ } msg]} {
+ Log $slave $msg
+ if {!$got(-nocomplain)} {
+ return -code error "permission denied"
+ } else {
+ return
}
}
}
+ # Apply the -join semantics ourselves
+ if {$got(-join)} {
+ set args [lreplace $args $at end [join [lrange $args $at end] "/"]]
+ }
+
+ # Process remaining pattern arguments
+ set firstPattern [llength $cmd]
+ while {$at < [llength $args]} {
+ set opt [lindex $args $at]
+ incr at
+ if {[regexp $dirPartRE $opt -> thedir] && [catch {
+ set thedir [file join $virtualdir $thedir]
+ DirInAccessPath $slave [TranslatePath $slave $thedir]
+ } msg]} {
+ Log $slave $msg
+ if {$got(-nocomplain)} {
+ continue
+ } else {
+ return -code error "permission denied"
+ }
+ }
+ lappend cmd $opt
+ }
+
Log $slave "GLOB = $cmd" NOTICE
+ if {$got(-nocomplain) && [llength $cmd] eq $firstPattern} {
+ return
+ }
if {[catch {
::interp invokehidden $slave glob {*}$cmd
} msg]} {
@@ -719,8 +768,11 @@ proc ::safe::AliasGlob {slave args} {
# Translate path back to what the slave should see.
set res {}
+ set l [string length $dir]
foreach p $msg {
- regsub -- ^$dir $p $virtualdir p
+ if {[string equal -length $l $dir $p]} {
+ set p [string replace $p 0 [expr {$l-1}] $virtualdir]
+ }
lappend res $p
}