|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
package require opt 0.4.1; |
|
|
|
namespace eval ::safe { |
|
|
|
|
|
variable tkSafeId 0 |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
proc ::safe::tkInterpInit {slave argv} { |
|
global env tk_library |
|
|
|
|
|
set tk_library [file normalize $tk_library] |
|
|
|
|
|
allowTk $slave $argv |
|
|
|
|
|
::interp eval $slave [list set tk_library [::safe::interpAddToAccessPath $slave $tk_library]] |
|
foreach subdir [::safe::AddSubDirs [list $tk_library]] { |
|
::safe::interpAddToAccessPath $slave $subdir |
|
} |
|
return $slave |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc ::safe::loadTk {} {} |
|
|
|
::tcl::OptProc ::safe::loadTk { |
|
{slave -interp "name of the slave interpreter"} |
|
{-use -windowId {} "window Id to use (new toplevel otherwise)"} |
|
{-display -displayName {} "display name to use (current one otherwise)"} |
|
} { |
|
set displayGiven [::tcl::OptProcArgGiven "-display"] |
|
if {!$displayGiven} { |
|
|
|
|
|
if {[catch {set display [winfo screen .]}]} { |
|
if {[info exists ::env(DISPLAY)]} { |
|
set display $::env(DISPLAY) |
|
} else { |
|
Log $slave "no winfo screen . nor env(DISPLAY)" WARNING |
|
set display ":0.0" |
|
} |
|
} |
|
} |
|
|
|
|
|
namespace upvar ::safe S$slave state |
|
|
|
if {![::tcl::OptProcArgGiven "-use"]} { |
|
|
|
lassign [tkTopLevel $slave $display] w use |
|
|
|
|
|
|
|
set state(cleanupHook) [list tkDelete {} $w] |
|
} else { |
|
|
|
|
|
set state(cleanupHook) [list disallowTk] |
|
|
|
|
|
if {[string match ".*" $use]} { |
|
set windowName $use |
|
set use [winfo id $windowName] |
|
set nDisplay [winfo screen $windowName] |
|
} else { |
|
|
|
|
|
|
|
|
|
if {![catch {winfo pathname $use} name]} { |
|
set nDisplay [winfo screen $name] |
|
} else { |
|
|
|
set nDisplay $display |
|
} |
|
} |
|
if {$nDisplay ne $display} { |
|
if {$displayGiven} { |
|
return -code error -errorcode {TK DISPLAY SAFE} \ |
|
"conflicting -display $display and -use $use -> $nDisplay" |
|
} else { |
|
set display $nDisplay |
|
} |
|
} |
|
} |
|
|
|
|
|
tkInterpInit $slave [list "-use" $use "-display" $display] |
|
|
|
load {} Tk $slave |
|
|
|
return $slave |
|
} |
|
|
|
proc ::safe::TkInit {interpPath} { |
|
variable tkInit |
|
if {[info exists tkInit($interpPath)]} { |
|
set value $tkInit($interpPath) |
|
Log $interpPath "TkInit called, returning \"$value\"" NOTICE |
|
return $value |
|
} else { |
|
Log $interpPath "TkInit called for interp with clearance:\ |
|
preventing Tk init" ERROR |
|
return -code error -errorcode {TK SAFE PERMISSION} "not allowed" |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc ::safe::allowTk {interpPath argv} { |
|
variable tkInit |
|
set tkInit($interpPath) $argv |
|
return |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc ::safe::disallowTk {interpPath} { |
|
variable tkInit |
|
|
|
if {[info exists tkInit($interpPath)]} { |
|
unset tkInit($interpPath) |
|
} |
|
return |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc ::safe::tkDelete {W window slave} { |
|
|
|
|
|
|
|
|
|
Log $slave "Called tkDelete $W $window" NOTICE |
|
if {[::interp exists $slave]} { |
|
if {[catch {::safe::interpDelete $slave} msg]} { |
|
Log $slave "Deletion error : $msg" |
|
} |
|
} |
|
if {[winfo exists $window]} { |
|
Log $slave "Destroy toplevel $window" NOTICE |
|
destroy $window |
|
} |
|
|
|
|
|
disallowTk $slave |
|
return |
|
} |
|
|
|
proc ::safe::tkTopLevel {slave display} { |
|
variable tkSafeId |
|
incr tkSafeId |
|
set w ".safe$tkSafeId" |
|
if {[catch {toplevel $w -screen $display -class SafeTk} msg]} { |
|
return -code error -errorcode {TK TOPLEVEL SAFE} \ |
|
"Unable to create toplevel for safe slave \"$slave\" ($msg)" |
|
} |
|
Log $slave "New toplevel $w" NOTICE |
|
|
|
set msg "Untrusted Tcl applet ($slave)" |
|
wm title $w $msg |
|
|
|
|
|
ttk::style layout TWarningFrame {WarningFrame.border -sticky nswe} |
|
ttk::style configure TWarningFrame -background red |
|
|
|
set wc $w.fc |
|
ttk::frame $wc -relief ridge -borderwidth 4 -style TWarningFrame |
|
|
|
|
|
bindtags $wc [concat Safe$wc [bindtags $wc]] |
|
bind Safe$wc <Destroy> [list ::safe::tkDelete %W $w $slave] |
|
|
|
ttk::label $wc.l -text $msg -anchor w |
|
|
|
|
|
|
|
|
|
|
|
|
|
ttk::frame $wc.fb -borderwidth 0 |
|
ttk::button $wc.fb.b -text "Delete" \ |
|
-command [list ::safe::tkDelete $w $w $slave] |
|
pack $wc.fb.b -side right -fill both |
|
pack $wc.fb -side right -fill both -expand 1 |
|
pack $wc.l -side left -fill both -expand 1 -ipady 2 |
|
pack $wc -side bottom -fill x |
|
|
|
|
|
frame $w.c -container 1 |
|
pack $w.c -fill both -expand 1 |
|
|
|
|
|
list $w [winfo id $w.c] |
|
} |
|
|