From: cattaghia on 2 May 2010 22:48 Hi again everyone! Quick ones now... 1) Is it possible to load "normal" Tk in a SafeBase interp? Or does the SafeBase interp force Tk to init itself with Tk_SafeInit? 2) The Tk commands which are removed by Tk_SafeInit (bell, grab, menu) are really *removed* or are them only hidden, like the some Tcl commands in safe interps? 3) According to the documentation, ::safe::loadTk allows a "-use" option which kinds of redirect the slave interp's "." window to another one. Is there something like this available for normal, "trusted" interps? Thanks! Fabricio Rocha Brasilia, Brasil
From: Gerald W. Lester on 3 May 2010 07:58 cattaghia wrote: > Hi again everyone! Quick ones now... > > 1) Is it possible to load "normal" Tk in a SafeBase interp? Or does > the SafeBase interp force Tk to init itself with Tk_SafeInit? I believe it will use Tk_SafeInit. > 2) The Tk commands which are removed by Tk_SafeInit (bell, grab, menu) > are really *removed* or are them only hidden, like the some Tcl > commands in safe interps? Not sure, but I believe they are hidden. > 3) According to the documentation, ::safe::loadTk allows a "-use" > option which kinds of redirect the slave interp's "." window to > another one. Is there something like this available for normal, > "trusted" interps? Yes, see man/help wish and man/help toplevel. --- news://freenews.netfront.net/ - complaints: news(a)netfront.net ---
From: cattaghia on 3 May 2010 21:13 Hi, Gerald, Do you mean the "argv" contents for wish? I found this one earlier, indeed, and I had already used the toplevel's "-use" option. But "interp" does not create another instance of wish or tclsh, does it? If it does, then passing command-line options would make sense; if it doesn't, something like "interp create ... -use $myContainerWidgetID" would be perfect, but in the docs I could find such option only for the Safe Base interps and SafeTk. I've been studying "interp" and its derivatives for a couple of days, but I could not find clear answers to these questions in the Wiki pages, in the manpages and in other sources like Brent Welch's online book and "Tcl and the Tk Toolkit" 2nd ed... Thanks! Fabricio Rocha Brasilia, Brasil
From: Keith Nash on 4 May 2010 11:17 Hello Fabricio, I think you are asking: is it possible to create an unsafe slave interpreter and then, when loading Tk, embed the slave's toplevel "." in a container frame of the master interpreter. I think the answer is "no": this operation is tied to the Safe Base. Running a standard unsafe interpreter this way is probably not what you want to do, because when "exit" is evaluated in the slave interpreter it will also cause the master to exit. The Safe Base provides a workaround for this problem, and a possible way to do what you want is to launch a Safe Base interpreter and then expose the unsafe commands (except exit) that the Safe Base has hidden. The command below does this, but I have not checked carefully whether it does all the initialisation needed to make the slave interpreter behave like an ordinary unsafe slave interpreter. Use ::safe::interpDelete to delete the interpreter. Keith. proc unsafeInterpInContainer {int winId} { # Create a Safe Base interpreter with Tk: safe::interpCreate $int ::safe::loadTk $int -use $winId # Get a list of hidden commands (except "exit"): set cmdList [interp hidden $int] set pos [lsearch -exact $cmdList exit] if {$pos != -1} { set cmdList [lreplace $cmdList $pos $pos] } # Remove Safe Base replacements for unsafe commands (except "exit"): foreach cmd $cmdList {$int eval [list catch [list rename $cmd {}]]} # Expose the hidden commands: foreach cmd $cmdList {interp expose $int $cmd} # Get rid of Safe Base directory tokens and use the same paths # as the present interpreter: $int eval [list set tcl_library $::tcl_library] $int eval [list set tk_library $::tk_library] $int eval [list set auto_path $::auto_path] $int eval [list set tcl_pkgPath $::tcl_pkgPath] $int eval {::tcl::tm::path remove {*}[::tcl::tm::path list]} $int eval [list ::tcl::tm::path add \ {*}[lreverse [::tcl::tm::path list]]] foreach {cmd instr} [$int eval array get ::auto_index] { $int eval [list set ::auto_index($cmd) \ [::safe::TranslatePath $int $instr]] } # Copy the environment and all elements of tcl_platform: $int eval [list array set ::tcl_platform [array get ::tcl_platform]] $int eval [list array set ::env [array get ::env]] # Mark the interpreter as trusted: interp marktrusted $int return $int }
From: cattaghia on 4 May 2010 14:37
Hello, Keith, thanks for the attention and the tips! Actually, what I would like to do was being able to use Tk stuff which is forbidden by ::safe::loadTk (menus, grab, clipboard) in a interpreter with some of the SafeBase protections. I did not reach this stage in my experiments yet, but it looks like the security model in ::safe::loadTk is way too restrictive for what I want (but completely justified for the purpose it was intended to, which AFAIK was the Tcl web plugin), so I will probably opt for using normal interps with some restricted aliases implemented. Before someone suggests, I found the "pluginmgr" package in tcllib and it seems to do a lot of what I'd like, but: a) of course, I want to create an app, but I am a hobbyist programmer. Learning Tcl is my actual goal, and the app will be a consequence and exercise. I'd rather spend some time studying interps and all these things instead of heading to a ready solution... b) pluginmgr requires Snit, and there's an enormous list of things I have to learn before trying the OO systems for Tcl (plus, I still have not found any comprehensive tutorial for any of these systems). So I have decided to make some experiments (Tcl/Tk 8.5.8) and got some conclusions: 1) "package require Tk" in a normal ("trusted") interp works flawlessly and fast. In a "vanilla safe" interp (created by "interp create -safe") it does not work, period. In a SafeBase interp created without values passed through the -accessPath option, all the directories in the master's auto_path and tcl_pkgPath are scanned for pkgIndex.tcl files (in my system, this includes a browse through all the directories under /usr/lib, which results in a +-25s delay) and finally the error message "not allowed to start Tk by master's safe::TkInit" appears. 2) "::safe::loadTk" does not work in the normal interp, as documented. In the vanilla safe interp, it generates the error message "can't read "Ssafeone(access_path,n)": no such element in array"; the documentation states that the safe interp must have been initialized or created by the SafeBase commands, so it seems that ::safe::loadTk is written for working only with the SafeBase token-based file access system. Not surprisingly, the command works perfectly in the SafeBase interp, but still does a search on every directory and subdirectories passed through -accessPath or those found in the master if the option is omitted. In BOTH cases an independent, decorated window appears (titled "Untrusted script", with a bottom panel in red borders with the same message and a "Delete" button), but when ::safe::loadTk is called in the vanilla safe interp this window does not have an "empty" space in it. After discovering how Tk can or cannot be loaded in the various kinds of interps, I tried another script which should embed the interps- created windows in a "Main Window" created in the master interpreter, with two labelframes "-container true" in it. This was somewhat surprising: 3) The "normal" interpreter had Tk loaded to it with "package require", and I created and packed on its main window a label. With the following line placed before the package require... interp eval normal [list set ::argv [dict create -use [winfo id .lblfrm1]]] .... the normal's window was correctly created in the master's container (.lblfrm1). But the labelframe's decoration and title disappeared! 4) The SafeBase interp had Tk loaded with "::safe::loadTk -use [winfo id .lblfrm2]". As expected, the "Untrusted script" second window did not appear. But it did not appear embedded in the master window, as I expected, and all the decoration of .lblfrm2 disappeared as well! I tried to replace .lblfrm2 with a regular frame, but this did not change anything. The container labelframes losing their decorations looked pretty strange and unexpected to me. It seems that something like [winfo id .lblfrm2] identifies the *whole area* of the labelframe, not its "inner frame", and all the "outer" decoration is lost when the labelframe's ID is given as value for the "-use" option for a toplevel. This is not in the docs and I think this is a bug, but you will certainly tell me I am wrong in something... Regards, Fabricio Rocha Brasilia, Brasil |