⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 safe.tcl

📁 genesis 2000 v9.1软件下载
💻 TCL
📖 第 1 页 / 共 2 页
字号:
	AliasSubset $slave file file dir.* join root.* ext.* tail \		path.* split	# This alias interposes on the 'exit' command and cleanly terminates	# the slave.	::interp alias $slave exit {} [namespace current]::interpDelete $slave	# The allowed slave variables already have been set	# by Tcl_MakeSafe(3)	# Source init.tcl into the slave, to get auto_load and other	# procedures defined:	# We don't try to use the -rsrc on the mac because it would get	# confusing if you would want to customize init.tcl	# for a given set of safe slaves, on all the platforms	# you just need to give a specific access_path and	# the mac should be no exception. As there is no	# obvious full "safe ressources" design nor implementation	# for the mac, safe interps there will just don't	# have that ability. (A specific app can still reenable	# that using custom aliases if they want to).	# It would also make the security analysis and the Safe Tcl security	# model platform dependant and thus more error prone.	if {[catch {::interp eval $slave\		{source [file join $tcl_library init.tcl]}}\		msg]} {	    Log $slave "can't source init.tcl ($msg)";	    error "can't source init.tcl into slave $slave ($msg)"	}	return $slave    }    # Add (only if needed, avoid duplicates) 1 level of    # sub directories to an existing path list.    # Also removes non directories from the returned list.    proc AddSubDirs {pathList} {	set res {}	foreach dir $pathList {	    if {[file isdirectory $dir]} {		# check that we don't have it yet as a children		# of a previous dir		if {[lsearch -exact $res $dir]<0} {		    lappend res $dir;		}		foreach sub [glob -nocomplain -- [file join $dir *]] {		    if {    ([file isdirectory $sub])		         && ([lsearch -exact $res $sub]<0) } {			# new sub dir, add it !	                lappend res $sub;	            }		}	    }	}	return $res;    }    # This procedure deletes a safe slave managed by Safe Tcl and    # cleans up associated state:proc ::safe::interpDelete {slave} {        Log $slave "About to delete" NOTICE;	# If the slave has a cleanup hook registered, call it.	# check the existance because we might be called to delete an interp	# which has not been registered with us at all	set hookname [DeleteHookName $slave];	if {[Exists $hookname]} {	    set hook [Set $hookname];	    if {![::tcl::Lempty $hook]} {		# remove the hook now, otherwise if the hook		# calls us somehow, we'll loop		Unset $hookname;		if {[catch {eval $hook [list $slave]} err]} {		    Log $slave "Delete hook error ($err)";		}	    }	}	# Discard the global array of state associated with the slave, and	# delete the interpreter.	set statename [InterpStateName $slave];	if {[Exists $statename]} {	    Unset $statename;	}	# if we have been called twice, the interp might have been deleted	# already	if {[::interp exists $slave]} {	    ::interp delete $slave;	    Log $slave "Deleted" NOTICE;	}	return    }    # Set (or get) the loging mecanism proc ::safe::setLogCmd {args} {    variable Log;    if {[llength $args] == 0} {	return $Log;    } else {	if {[llength $args] == 1} {	    set Log [lindex $args 0];	} else {	    set Log $args	}    }}    # internal variable    variable Log {}    # ------------------- END OF PUBLIC METHODS ------------    #    # sets the slave auto_path to the master recorded value.    # also sets tcl_library to the first token of the virtual path.    #    proc SyncAccessPath {slave} {	set slave_auto_path [Set [VirtualPathListName $slave]];	::interp eval $slave [list set auto_path $slave_auto_path];	Log $slave \		"auto_path in $slave has been set to $slave_auto_path"\		NOTICE;	::interp eval $slave [list set tcl_library [lindex $slave_auto_path 0]];    }    # base name for storing all the slave states    # the array variable name for slave foo is thus "Sfoo"    # and for sub slave {foo bar} "Sfoo bar" (spaces are handled    # ok everywhere (or should))    # We add the S prefix to avoid that a slave interp called "Log"    # would smash our "Log" variable.    proc InterpStateName {slave} {	return "S$slave";    }    # Check that the given slave is "one of us"    proc IsInterp {slave} {	expr {    ([Exists [InterpStateName $slave]]) 	       && ([::interp exists $slave])}    }    # returns the virtual token for directory number N    # if the slave argument is given,     # it will return the corresponding master global variable name    proc PathToken {n {slave ""}} {	if {[string compare "" $slave]} {	    return "[InterpStateName $slave](access_path,$n)";	} else {	    # We need to have a ":" in the token string so	    # [file join] on the mac won't turn it into a relative	    # path.	    return "p(:$n:)";	}    }    # returns the variable name of the complete path list    proc PathListName {slave} {	return "[InterpStateName $slave](access_path)";    }    # returns the variable name of the complete path list    proc VirtualPathListName {slave} {	return "[InterpStateName $slave](access_path_slave)";    }    # returns the variable name of the number of items    proc PathNumberName {slave} {	return "[InterpStateName $slave](access_path,n)";    }    # returns the staticsok flag var name    proc StaticsOkName {slave} {	return "[InterpStateName $slave](staticsok)";    }    # returns the nestedok flag var name    proc NestedOkName {slave} {	return "[InterpStateName $slave](nestedok)";    }    # Run some code at the namespace toplevel    proc Toplevel {args} {	namespace eval [namespace current] $args;    }    # set/get values    proc Set {args} {	eval Toplevel set $args;    }    # lappend on toplevel vars    proc Lappend {args} {	eval Toplevel lappend $args;    }    # unset a var/token (currently just an global level eval)    proc Unset {args} {	eval Toplevel unset $args;    }    # test existance     proc Exists {varname} {	Toplevel info exists $varname;    }    # short cut for access path getting    proc GetAccessPath {slave} {	Set [PathListName $slave]    }    # short cut for statics ok flag getting    proc StaticsOk {slave} {	Set [StaticsOkName $slave]    }    # short cut for getting the multiples interps sub loading ok flag    proc NestedOk {slave} {	Set [NestedOkName $slave]    }    # interp deletion storing hook name    proc DeleteHookName {slave} {	return [InterpStateName $slave](cleanupHook)    }    #    # translate virtual path into real path    #    proc TranslatePath {slave path} {	# somehow strip the namespaces 'functionality' out (the danger	# is that we would strip valid macintosh "../" queries... :	if {[regexp {(::)|(\.\.)} $path]} {	    error "invalid characters in path $path";	}	set n [expr {[Set [PathNumberName $slave]]-1}];	for {} {$n>=0} {incr n -1} {	    # fill the token virtual names with their real value	    set [PathToken $n] [Set [PathToken $n $slave]];	}	# replaces the token by their value	subst -nobackslashes -nocommands $path;    }    # Log eventually log an error    # to enable error logging, set Log to {puts stderr} for instance    proc Log {slave msg {type ERROR}} {	variable Log;	if {[info exists Log] && [llength $Log]} {	    eval $Log [list "$type for slave $slave : $msg"];	}    }        # file name control (limit access to files/ressources that should be    # a valid tcl source file)    proc CheckFileName {slave file} {	# limit what can be sourced to .tcl	# and forbid files with more than 1 dot and	# longer than 14 chars	set ftail [file tail $file];	if {[string length $ftail]>14} {	    error "$ftail: filename too long";	}	if {[regexp {\..*\.} $ftail]} {	    error "$ftail: more than one dot is forbidden";	}	if {[string compare $ftail "tclIndex"] && \		[string compare [string tolower [file extension $ftail]]\		".tcl"]} {	    error "$ftail: must be a *.tcl or tclIndex";	}	if {![file exists $file]} {	    # don't tell the file path	    error "no such file or directory";	}	if {![file readable $file]} {	    # don't tell the file path	    error "not readable";	}    }    # AliasSource is the target of the "source" alias in safe interpreters.    proc AliasSource {slave args} {	set argc [llength $args];	# Allow only "source filename"	# (and not mac specific -rsrc for instance - see comment in ::init	# for current rationale)	if {$argc != 1} {	    set msg "wrong # args: should be \"source fileName\""	    Log $slave "$msg ($args)";	    return -code error $msg;	}	set file [lindex $args 0]		# get the real path from the virtual one.	if {[catch {set file [TranslatePath $slave $file]} msg]} {	    Log $slave $msg;	    return -code error "permission denied"	}		# check that the path is in the access path of that slave	if {[catch {FileInAccessPath $slave $file} msg]} {	    Log $slave $msg;	    return -code error "permission denied"	}	# do the checks on the filename :	if {[catch {CheckFileName $slave $file} msg]} {	    Log $slave "$file:$msg";	    return -code error $msg;	}	# passed all the tests , lets source it:	if {[catch {::interp invokehidden $slave source $file} msg]} {	    Log $slave $msg;	    return -code error "script error";	}	return $msg    }    # AliasLoad is the target of the "load" alias in safe interpreters.    proc AliasLoad {slave file args} {	set argc [llength $args];	if {$argc > 2} {	    set msg "load error: too many arguments";	    Log $slave "$msg ($argc) {$file $args}";	    return -code error $msg;	}	# package name (can be empty if file is not).	set package [lindex $args 0];	# Determine where to load. load use a relative interp path	# and {} means self, so we can directly and safely use passed arg.	set target [lindex $args 1];	if {[string length $target]} {	    # we will try to load into a sub sub interp	    # check that we want to authorize that.	    if {![NestedOk $slave]} {		Log $slave "loading to a sub interp (nestedok)\			disabled (trying to load $package to $target)";		return -code error "permission denied (nested load)";	    }	    	}	# Determine what kind of load is requested	if {[string length $file] == 0} {	    # static package loading	    if {[string length $package] == 0} {		set msg "load error: empty filename and no package name";		Log $slave $msg;		return -code error $msg;	    }	    if {![StaticsOk $slave]} {		Log $slave "static packages loading disabled\			(trying to load $package to $target)";		return -code error "permission denied (static package)";	    }	} else {	    # file loading	    # get the real path from the virtual one.	    if {[catch {set file [TranslatePath $slave $file]} msg]} {		Log $slave $msg;		return -code error "permission denied"	    }	    # check the translated path	    if {[catch {FileInAccessPath $slave $file} msg]} {		Log $slave $msg;		return -code error "permission denied (path)"	    }	}	if {[catch {::interp invokehidden\		$slave load $file $package $target} msg]} {	    Log $slave $msg;	    return -code error $msg	}	return $msg    }    # FileInAccessPath raises an error if the file is not found in    # the list of directories contained in the (master side recorded) slave's    # access path.    # the security here relies on "file dirname" answering the proper    # result.... needs checking ?    proc FileInAccessPath {slave file} {	set access_path [GetAccessPath $slave];	if {[file isdirectory $file]} {	    error "\"$file\": is a directory"	}	set parent [file dirname $file]	if {[lsearch -exact $access_path $parent] == -1} {	    error "\"$file\": not in access_path";	}    }    # This procedure enables access from a safe interpreter to only a subset of    # the subcommands of a command:    proc Subset {slave command okpat args} {	set subcommand [lindex $args 0]	if {[regexp $okpat $subcommand]} {	    return [eval {$command $subcommand} [lrange $args 1 end]]	}	set msg "not allowed to invoke subcommand $subcommand of $command";	Log $slave $msg;	error $msg;    }    # This procedure installs an alias in a slave that invokes "safesubset"    # in the master to execute allowed subcommands. It precomputes the pattern    # of allowed subcommands; you can use wildcards in the pattern if you wish    # to allow subcommand abbreviation.    #    # Syntax is: AliasSubset slave alias target subcommand1 subcommand2...    proc AliasSubset {slave alias target args} {	set pat ^(; set sep ""	foreach sub $args {	    append pat $sep$sub	    set sep |	}	append pat )\$	::interp alias $slave $alias {}\		[namespace current]::Subset $slave $target $pat    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -