home *** CD-ROM | disk | FTP | other *** search
/ Chip: Linux Special / CorelLinux_CHIP.iso / VMware / bin / vmware-wizard / lib / tk8.0 / safetk.tcl < prev    next >
Encoding:
Text File  |  1999-02-24  |  6.1 KB  |  205 lines

  1. # safetk.tcl --
  2. #
  3. # Support procs to use Tk in safe interpreters.
  4. #
  5. # RCS: @(#) $Id: safetk.tcl,v 1.3 1998/09/14 18:23:24 stanton Exp $
  6. #
  7. # Copyright (c) 1997 Sun Microsystems, Inc.
  8. #
  9. # See the file "license.terms" for information on usage and redistribution
  10. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  
  12. # see safetk.n for documentation
  13.  
  14. #
  15. #
  16. # Note: It is now ok to let untrusted code being executed
  17. #       between the creation of the interp and the actual loading
  18. #       of Tk in that interp because the C side Tk_Init will
  19. #       now look up the master interp and ask its safe::TkInit
  20. #       for the actual parameters to use for it's initialization (if allowed),
  21. #       not relying on the slave state.
  22. #
  23.  
  24. # We use opt (optional arguments parsing)
  25. package require opt 0.1;
  26.  
  27. namespace eval ::safe {
  28.  
  29.     # counter for safe toplevels
  30.     variable tkSafeId 0;
  31.  
  32.     #
  33.     # tkInterpInit : prepare the slave interpreter for tk loading
  34.     #                most of the real job is done by loadTk
  35.     # returns the slave name (tkInterpInit does)
  36.     #
  37.     proc ::safe::tkInterpInit {slave argv} {
  38.     global env tk_library
  39.  
  40.     # Clear Tk's access for that interp (path).
  41.     allowTk $slave $argv
  42.  
  43.     # there seems to be an obscure case where the tk_library
  44.     # variable value is changed to point to a sym link destination
  45.     # dir instead of the sym link itself, and thus where the $tk_library
  46.     # would then not be anymore one of the auto_path dir, so we use
  47.     # the addToAccessPath which adds if it's not already in instead
  48.     # of the more conventional findInAccessPath.
  49.     # Might be usefull for masters without Tk really loaded too.
  50.     ::interp eval $slave [list set tk_library [::safe::interpAddToAccessPath $slave $tk_library]]
  51.     return $slave;
  52.     }
  53.  
  54.  
  55. # tkInterpLoadTk : 
  56. # Do additional configuration as needed (calling tkInterpInit) 
  57. # and actually load Tk into the slave.
  58. # Either contained in the specified windowId (-use) or
  59. # creating a decorated toplevel for it.
  60.  
  61. # empty definition for auto_mkIndex
  62. proc ::safe::loadTk {} {}
  63.    
  64.     ::tcl::OptProc loadTk {
  65.     {slave -interp "name of the slave interpreter"}
  66.     {-use  -windowId {} "window Id to use (new toplevel otherwise)"}
  67.     {-display -displayName {} "display name to use (current one otherwise)"}
  68.     } {
  69.     set displayGiven [::tcl::OptProcArgGiven "-display"]
  70.     if {!$displayGiven} {
  71.         # Try to get the current display from "."
  72.         # (which might not exist if the master is tk-less)
  73.         if {[catch {set display [winfo screen .]}]} {
  74.         if {[info exists ::env(DISPLAY)]} {
  75.             set display $::env(DISPLAY)
  76.         } else {
  77.             Log $slave "no winfo screen . nor env(DISPLAY)" WARNING
  78.             set display ":0.0"
  79.         }
  80.         }
  81.     }
  82.     if {![::tcl::OptProcArgGiven "-use"]} {
  83.         # create a decorated toplevel
  84.         ::tcl::Lassign [tkTopLevel $slave $display] w use;
  85.         # set our delete hook (slave arg is added by interpDelete)
  86.         Set [DeleteHookName $slave] [list tkDelete {} $w];
  87.     } else {
  88.         # Let's be nice and also accept tk window names instead of ids
  89.         if {[string match ".*" $use]} {
  90.         set windowName $use
  91.         set use [winfo id $windowName]
  92.         set nDisplay [winfo screen $windowName]
  93.         } else {
  94.         # Check for a better -display value
  95.         # (works only for multi screens on single host, but not
  96.         #  cross hosts, for that a tk window name would be better
  97.         #  but embeding is also usefull for non tk names)
  98.         if {![catch {winfo pathname $use} name]} {
  99.             set nDisplay [winfo screen $name]
  100.         } else {
  101.             # Can't have a better one
  102.             set nDisplay $display
  103.         }
  104.         }
  105.         if {[string compare $nDisplay $display]} {
  106.         if {$displayGiven} {
  107.             error "conflicting -display $display and -use\
  108.                 $use -> $nDisplay"
  109.         } else {
  110.             set display $nDisplay
  111.         }
  112.         }
  113.     }
  114.  
  115.     # Prepares the slave for tk with those parameters
  116.  
  117.     tkInterpInit $slave [list "-use" $use "-display" $display]
  118.  
  119.     load {} Tk $slave
  120.  
  121.     return $slave
  122.     }
  123.  
  124. proc ::safe::TkInit {interpPath} {
  125.     variable tkInit
  126.     if {[info exists tkInit($interpPath)]} {
  127.     set value $tkInit($interpPath)
  128.     Log $interpPath "TkInit called, returning \"$value\"" NOTICE
  129.     return $value
  130.     } else {
  131.     Log $interpPath "TkInit called for interp with clearance:\
  132.         preventing Tk init" ERROR
  133.     error "not allowed"
  134.     }
  135. }
  136.  
  137. proc ::safe::allowTk {interpPath argv} {
  138.     variable tkInit
  139.     set tkInit($interpPath) $argv
  140. }
  141.  
  142.     proc ::safe::tkDelete {W window slave} {
  143.     # we are going to be called for each widget... skip untill it's
  144.     # top level
  145.     Log $slave "Called tkDelete $W $window" NOTICE;
  146.     if {[::interp exists $slave]} {
  147.         if {[catch {::safe::interpDelete $slave} msg]} {
  148.         Log $slave "Deletion error : $msg";
  149.         }
  150.     }
  151.     if {[winfo exists $window]} {
  152.         Log $slave "Destroy toplevel $window" NOTICE;
  153.         destroy $window;
  154.     }
  155.     }
  156.  
  157. proc ::safe::tkTopLevel {slave display} {
  158.     variable tkSafeId;
  159.     incr tkSafeId;
  160.     set w ".safe$tkSafeId";
  161.     if {[catch {toplevel $w -screen $display -class SafeTk} msg]} {
  162.     return -code error "Unable to create toplevel for\
  163.         safe slave \"$slave\" ($msg)";
  164.     }
  165.     Log $slave "New toplevel $w" NOTICE
  166.  
  167.     set msg "Untrusted Tcl applet ($slave)"
  168.     wm title $w $msg;
  169.  
  170.     # Control frame
  171.     set wc $w.fc
  172.     frame $wc -bg red -borderwidth 3 -relief ridge ;
  173.  
  174.     # We will destroy the interp when the window is destroyed
  175.     bindtags $wc [concat Safe$wc [bindtags $wc]]
  176.     bind Safe$wc <Destroy> [list ::safe::tkDelete %W $w $slave];
  177.  
  178.     label $wc.l -text $msg \
  179.         -padx 2 -pady 0 -anchor w;
  180.  
  181.     # We want the button to be the last visible item
  182.     # (so be packed first) and at the right and not resizing horizontally
  183.  
  184.     # frame the button so it does not expand horizontally
  185.     # but still have the default background instead of red one from the parent
  186.     frame  $wc.fb -bd 0 ;
  187.     button $wc.fb.b -text "Delete" \
  188.         -bd 1  -padx 2 -pady 0 -highlightthickness 0 \
  189.         -command [list ::safe::tkDelete $w $w $slave]
  190.     pack $wc.fb.b -side right -fill both ;
  191.     pack $wc.fb -side right -fill both -expand 1;
  192.     pack $wc.l -side left  -fill both -expand 1;
  193.     pack $wc -side bottom -fill x ;
  194.  
  195.     # Container frame
  196.     frame $w.c -container 1;
  197.     pack $w.c -fill both -expand 1;
  198.     
  199.     # return both the toplevel window name and the id to use for embedding
  200.     list $w [winfo id $w.c] ;
  201. }
  202.  
  203. }
  204.