!C99Shell v. 2.0 [PHP 7 Update] [25.02.2019]!

Software: Apache. PHP/7.3.33 

uname -a: Linux acloudg.aryanict.com 4.18.0-513.9.1.lve.el8.x86_64 #1 SMP Mon Dec 4 15:01:22 UTC
2023 x86_64
 

uid=1095(katebhospital) gid=1098(katebhospital) groups=1098(katebhospital) 

Safe-mode: OFF (not secure)

/usr/share/tcl8.6/   drwxr-xr-x
Free 293.88 GB of 429.69 GB (68.39%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     safe.tcl (32.66 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# safe.tcl --
#
# This file provide a safe loading/sourcing mechanism for safe interpreters.
# It implements a virtual path mecanism to hide the real pathnames from the
# slave. It runs in a master interpreter and sets up data structure and
# aliases that will be invoked when used from a slave interpreter.
#
# See the safe.n man page for details.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

#
# The implementation is based on namespaces. These naming conventions are
# followed:
# Private procs starts with uppercase.
# Public  procs are exported and starts with lowercase
#

# Needed utilities package
package require opt 0.4.1

# Create the safe namespace
namespace eval ::safe {
    # Exported API:
    namespace export interpCreate interpInit interpConfigure interpDelete \
    interpAddToAccessPath interpFindInAccessPath setLogCmd
}

# Helper function to resolve the dual way of specifying staticsok (either
# by -noStatics or -statics 0)
proc ::safe::InterpStatics {} {
    foreach v {Args statics noStatics} {
    upvar $v $v
    }
    set flag [::tcl::OptProcArgGiven -noStatics]
    if {$flag && (!$noStatics == !$statics)
    && ([::tcl::OptProcArgGiven -statics])} {
    return -code error\
        "conflicting values given for -statics and -noStatics"
    }
    if {$flag} {
    return [expr {!$noStatics}]
    } else {
    return $statics
    }
}

# Helper function to resolve the dual way of specifying nested loading
# (either by -nestedLoadOk or -nested 1)
proc ::safe::InterpNested {} {
    foreach v {Args nested nestedLoadOk} {
    upvar $v $v
    }
    set flag [::tcl::OptProcArgGiven -nestedLoadOk]
    # note that the test here is the opposite of the "InterpStatics" one
    # (it is not -noNested... because of the wanted default value)
    if {$flag && (!$nestedLoadOk != !$nested)
    && ([::tcl::OptProcArgGiven -nested])} {
    return -code error\
        "conflicting values given for -nested and -nestedLoadOk"
    }
    if {$flag} {
    # another difference with "InterpStatics"
    return $nestedLoadOk
    } else {
    return $nested
    }
}

####
#
#  API entry points that needs argument parsing :
#
####

# Interface/entry point function and front end for "Create"
proc ::safe::interpCreate {args} {
    set Args [::tcl::OptKeyParse ::safe::interpCreate $args]
    InterpCreate $slave $accessPath \
    [InterpStatics] [InterpNested] $deleteHook
}

proc ::safe::interpInit {args} {
    set Args [::tcl::OptKeyParse ::safe::interpIC $args]
    if {![::interp exists $slave]} {
    return -code error "\"$slave\" is not an interpreter"
    }
    InterpInit $slave $accessPath \
    [InterpStatics] [InterpNested] $deleteHook
}

# Check that the given slave is "one of us"
proc ::safe::CheckInterp {slave} {
    namespace upvar ::safe S$slave state
    if {![info exists state] || ![::interp exists $slave]} {
    return -code error \
        "\"$slave\" is not an interpreter managed by ::safe::"
    }
}

# Interface/entry point function and front end for "Configure".  This code
# is awfully pedestrian because it would need more coupling and support
# between the way we store the configuration values in safe::interp's and
# the Opt package. Obviously we would like an OptConfigure to avoid
# duplicating all this code everywhere.
# -> TODO (the app should share or access easily the program/value stored
# by opt)

# This is even more complicated by the boolean flags with no values that
# we had the bad idea to support for the sake of user simplicity in
# create/init but which makes life hard in configure...
# So this will be hopefully written and some integrated with opt1.0
# (hopefully for tcl8.1 ?)
proc ::safe::interpConfigure {args} {
    switch [llength $args] {
    1 {
        # If we have exactly 1 argument the semantic is to return all
        # the current configuration. We still call OptKeyParse though
        # we know that "slave" is our given argument because it also
        # checks for the "-help" option.
        set Args [::tcl::OptKeyParse ::safe::interpIC $args]
        CheckInterp $slave
        namespace upvar ::safe S$slave state

        return [join [list \
        [list -accessPath $state(access_path)] \
        [list -statics    $state(staticsok)]   \
        [list -nested     $state(nestedok)]    \
            [list -deleteHook $state(cleanupHook)]]]
    }
    2 {
        # If we have exactly 2 arguments the semantic is a "configure
        # get"
        lassign $args slave arg

        # get the flag sub program (we 'know' about Opt's internal
        # representation of data)
        set desc [lindex [::tcl::OptKeyGetDesc ::safe::interpIC] 2]
        set hits [::tcl::OptHits desc $arg]
        if {$hits > 1} {
        return -code error [::tcl::OptAmbigous $desc $arg]
        } elseif {$hits == 0} {
        return -code error [::tcl::OptFlagUsage $desc $arg]
        }
        CheckInterp $slave
        namespace upvar ::safe S$slave state

        set item [::tcl::OptCurDesc $desc]
        set name [::tcl::OptName $item]
        switch -exact -- $name {
        -accessPath {
            return [list -accessPath $state(access_path)]
        }
        -statics    {
            return [list -statics $state(staticsok)]
        }
        -nested     {
            return [list -nested $state(nestedok)]
        }
        -deleteHook {
            return [list -deleteHook $state(cleanupHook)]
        }
        -noStatics {
            # it is most probably a set in fact but we would need
            # then to jump to the set part and it is not *sure*
            # that it is a set action that the user want, so force
            # it to use the unambigous -statics ?value? instead:
            return -code error\
            "ambigous query (get or set -noStatics ?)\
                use -statics instead"
        }
        -nestedLoadOk {
            return -code error\
            "ambigous query (get or set -nestedLoadOk ?)\
                use -nested instead"
        }
        default {
            return -code error "unknown flag $name (bug)"
        }
        }
    }
    default {
        # Otherwise we want to parse the arguments like init and
        # create did
        set Args [::tcl::OptKeyParse ::safe::interpIC $args]
        CheckInterp $slave
        namespace upvar ::safe S$slave state

        # Get the current (and not the default) values of whatever has
        # not been given:
        if {![::tcl::OptProcArgGiven -accessPath]} {
        set doreset 1
        set accessPath $state(access_path)
        } else {
        set doreset 0
        }
        if {
        ![::tcl::OptProcArgGiven -statics]
        && ![::tcl::OptProcArgGiven -noStatics]
        } then {
        set statics    $state(staticsok)
        } else {
        set statics    [InterpStatics]
        }
        if {
        [::tcl::OptProcArgGiven -nested] ||
        [::tcl::OptProcArgGiven -nestedLoadOk]
        } then {
        set nested     [InterpNested]
        } else {
        set nested     $state(nestedok)
        }
        if {![::tcl::OptProcArgGiven -deleteHook]} {
        set deleteHook $state(cleanupHook)
        }
        # we can now reconfigure :
        InterpSetConfig $slave $accessPath $statics $nested $deleteHook
        # auto_reset the slave (to completly synch the new access_path)
        if {$doreset} {
        if {[catch {::interp eval $slave {auto_reset}} msg]} {
            Log $slave "auto_reset failed: $msg"
        } else {
            Log $slave "successful auto_reset" NOTICE
        }
        }
    }
    }
}

####
#
#  Functions that actually implements the exported APIs
#
####

#
# safe::InterpCreate : doing the real job
#
# This procedure creates a safe slave and initializes it with the safe
# base aliases.
# NB: slave name must be simple alphanumeric string, no spaces, no (), no
# {},...  {because the state array is stored as part of the name}
#
# Returns the slave name.
#
# Optional Arguments :
# + slave name : if empty, generated name will be used
# + access_path: path list controlling where load/source can occur,
#                if empty: the master auto_path will be used.
# + staticsok  : flag, if 0 :no static package can be loaded (load {} Xxx)
#                      if 1 :static packages are ok.
# + nestedok: flag, if 0 :no loading to sub-sub interps (load xx xx sub)
#                      if 1 : multiple levels are ok.

# use the full name and no indent so auto_mkIndex can find us
proc ::safe::InterpCreate {
               slave
               access_path
               staticsok
               nestedok
               deletehook
               } {
    # Create the slave.
    if {$slave ne ""} {
    ::interp create -safe $slave
    } else {
    # empty argument: generate slave name
    set slave [::interp create -safe]
    }
    Log $slave "Created" NOTICE

    # Initialize it. (returns slave name)
    InterpInit $slave $access_path $staticsok $nestedok $deletehook
}

#
# InterpSetConfig (was setAccessPath) :
#    Sets up slave virtual auto_path and corresponding structure within
#    the master. Also sets the tcl_library in the slave to be the first
#    directory in the path.
#    NB: If you change the path after the slave has been initialized you
#    probably need to call "auto_reset" in the slave in order that it gets
#    the right auto_index() array values.

proc ::safe::InterpSetConfig {slave access_path staticsok nestedok deletehook} {
    global auto_path

    # determine and store the access path if empty
    if {$access_path eq ""} {
    set access_path $auto_path

    # Make sure that tcl_library is in auto_path and at the first
    # position (needed by setAccessPath)
    set where [lsearch -exact $access_path [info library]]
    if {$where == -1} {
        # not found, add it.
        set access_path [linsert $access_path 0 [info library]]
        Log $slave "tcl_library was not in auto_path,\
            added it to slave's access_path" NOTICE
    } elseif {$where != 0} {
        # not first, move it first
        set access_path [linsert \
                 [lreplace $access_path $where $where] \
                 0 [info library]]
        Log $slave "tcl_libray was not in first in auto_path,\
            moved it to front of slave's access_path" NOTICE
    }

    # Add 1st level sub dirs (will searched by auto loading from tcl
    # code in the slave using glob and thus fail, so we add them here
    # so by default it works the same).
    set access_path [AddSubDirs $access_path]
    }

    Log $slave "Setting accessPath=($access_path) staticsok=$staticsok\
        nestedok=$nestedok deletehook=($deletehook)" NOTICE

    namespace upvar ::safe S$slave state

    # clear old autopath if it existed
    # build new one
    # Extend the access list with the paths used to look for Tcl Modules.
    # We save the virtual form separately as well, as syncing it with the
    # slave has to be defered until the necessary commands are present for
    # setup.

    set norm_access_path  {}
    set slave_access_path {}
    set map_access_path   {}
    set remap_access_path {}
    set slave_tm_path     {}

    set i 0
    foreach dir $access_path {
    set token [PathToken $i]
    lappend slave_access_path  $token
    lappend map_access_path    $token $dir
    lappend remap_access_path  $dir $token
    lappend norm_access_path   [file normalize $dir]
    incr i
    }

    set morepaths [::tcl::tm::list]
    while {[llength $morepaths]} {
    set addpaths $morepaths
    set morepaths {}

    foreach dir $addpaths {
        # Prevent the addition of dirs on the tm list to the
        # result if they are already known.
        if {[dict exists $remap_access_path $dir]} {
        continue
        }

        set token [PathToken $i]
        lappend access_path        $dir
        lappend slave_access_path  $token
        lappend map_access_path    $token $dir
        lappend remap_access_path  $dir $token
        lappend norm_access_path   [file normalize $dir]
        lappend slave_tm_path $token
        incr i

        # [Bug 2854929]
        # Recursively find deeper paths which may contain
        # modules. Required to handle modules with names like
        # 'platform::shell', which translate into
        # 'platform/shell-X.tm', i.e arbitrarily deep
        # subdirectories.
        lappend morepaths {*}[glob -nocomplain -directory $dir -type d *]
    }
    }

    set state(access_path)       $access_path
    set state(access_path,map)   $map_access_path
    set state(access_path,remap) $remap_access_path
    set state(access_path,norm)  $norm_access_path
    set state(access_path,slave) $slave_access_path
    set state(tm_path_slave)     $slave_tm_path
    set state(staticsok)         $staticsok
    set state(nestedok)          $nestedok
    set state(cleanupHook)       $deletehook

    SyncAccessPath $slave
}

#
#
# FindInAccessPath:
#    Search for a real directory and returns its virtual Id (including the
#    "$")
proc ::safe::interpFindInAccessPath {slave path} {
    namespace upvar ::safe S$slave state

    if {![dict exists $state(access_path,remap) $path]} {
    return -code error "$path not found in access path $access_path"
    }

    return [dict get $state(access_path,remap) $path]
}

#
# addToAccessPath:
#    add (if needed) a real directory to access path and return its
#    virtual token (including the "$").
proc ::safe::interpAddToAccessPath {slave path} {
    # first check if the directory is already in there
    # (inlined interpFindInAccessPath).
    namespace upvar ::safe S$slave state

    if {[dict exists $state(access_path,remap) $path]} {
    return [dict get $state(access_path,remap) $path]
    }

    # new one, add it:
    set token [PathToken [llength $state(access_path)]]

    lappend state(access_path)       $path
    lappend state(access_path,slave) $token
    lappend state(access_path,map)   $token $path
    lappend state(access_path,remap) $path $token
    lappend state(access_path,norm)  [file normalize $path]

    SyncAccessPath $slave
    return $token
}

# This procedure applies the initializations to an already existing
# interpreter. It is useful when you want to install the safe base aliases
# into a preexisting safe interpreter.
proc ::safe::InterpInit {
             slave
             access_path
             staticsok
             nestedok
             deletehook
             } {
    # Configure will generate an access_path when access_path is empty.
    InterpSetConfig $slave $access_path $staticsok $nestedok $deletehook

    # NB we need to add [namespace current], aliases are always absolute
    # paths.

    # These aliases let the slave load files to define new commands
    # This alias lets the slave use the encoding names, convertfrom,
    # convertto, and system, but not "encoding system <name>" to set the
    # system encoding.
    # Handling Tcl Modules, we need a restricted form of Glob.
    # This alias interposes on the 'exit' command and cleanly terminates
    # the slave.

    foreach {command alias} {
    source   AliasSource
    load     AliasLoad
    encoding AliasEncoding
    exit     interpDelete
    glob     AliasGlob
    } {
    ::interp alias $slave $command {} [namespace current]::$alias $slave
    }

    # This alias lets the slave have access to a subset of the 'file'
    # command functionality.

    ::interp expose $slave file
    foreach subcommand {dirname extension rootname tail} {
    ::interp alias $slave ::tcl::file::$subcommand {} \
        ::safe::AliasFileSubcommand $slave $subcommand
    }
    foreach subcommand {
    atime attributes copy delete executable exists isdirectory isfile
    link lstat mtime mkdir nativename normalize owned readable readlink
    rename size stat tempfile type volumes writable
    } {
    ::interp alias $slave ::tcl::file::$subcommand {} \
        ::safe::BadSubcommand $slave file $subcommand
    }

    # Subcommands of info
    foreach {subcommand alias} {
    nameofexecutable   AliasExeName
    } {
    ::interp alias $slave ::tcl::info::$subcommand \
        {} [namespace current]::$alias $slave
    }

    # The allowed slave variables already have been set by Tcl_MakeSafe(3)

    # Source init.tcl and tm.tcl into the slave, to get auto_load and
    # other procedures defined:

    if {[catch {::interp eval $slave {
    source [file join $tcl_library init.tcl]
    }} msg opt]} {
    Log $slave "can't source init.tcl ($msg)"
    return -options $opt "can't source init.tcl into slave $slave ($msg)"
    }

    if {[catch {::interp eval $slave {
    source [file join $tcl_library tm.tcl]
    }} msg opt]} {
    Log $slave "can't source tm.tcl ($msg)"
    return -options $opt "can't source tm.tcl into slave $slave ($msg)"
    }

    # Sync the paths used to search for Tcl modules. This can be done only
    # now, after tm.tcl was loaded.
    namespace upvar ::safe S$slave state
    if {[llength $state(tm_path_slave)] > 0} {
    ::interp eval $slave [list \
        ::tcl::tm::add {*}[lreverse $state(tm_path_slave)]]
    }
    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 ::safe::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 {$dir ni $res} {
        lappend res $dir
        }
        foreach sub [glob -directory $dir -nocomplain *] {
        if {[file isdirectory $sub] && ($sub ni $res)} {
            # 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

    namespace upvar ::safe S$slave state

    # 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

    if {[info exists state(cleanupHook)]} {
    set hook $state(cleanupHook)
    if {[llength $hook]} {
        # remove the hook now, otherwise if the hook calls us somehow,
        # we'll loop
        unset state(cleanupHook)
        try {
        {*}$hook $slave
        } on error err {
        Log $slave "Delete hook error ($err)"
        }
    }
    }

    # Discard the global array of state associated with the slave, and
    # delete the interpreter.

    if {[info exists state]} {
    unset state
    }

    # 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 logging mecanism

proc ::safe::setLogCmd {args} {
    variable Log
    set la [llength $args]
    if {$la == 0} {
    return $Log
    } elseif {$la == 1} {
    set Log [lindex $args 0]
    } else {
    set Log $args
    }

    if {$Log eq ""} {
    # Disable logging completely. Calls to it will be compiled out
    # of all users.
    proc ::safe::Log {args} {}
    } else {
    # Activate logging, define proper command.

    proc ::safe::Log {slave msg {type ERROR}} {
        variable Log
        {*}$Log "$type for slave $slave : $msg"
        return
    }
    }
}

# ------------------- 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 ::safe::SyncAccessPath {slave} {
    namespace upvar ::safe S$slave state

    set slave_access_path $state(access_path,slave)
    ::interp eval $slave [list set auto_path $slave_access_path]

    Log $slave "auto_path in $slave has been set to $slave_access_path"\
    NOTICE

    # This code assumes that info library is the first element in the
    # list of auto_path's. See -> InterpSetConfig for the code which
    # ensures this condition.

    ::interp eval $slave [list \
          set tcl_library [lindex $slave_access_path 0]]
}

# Returns the virtual token for directory number N.
proc ::safe::PathToken {n} {
    # 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:)" ;# Form tested by case 7.2
}

#
# translate virtual path into real path
#
proc ::safe::TranslatePath {slave path} {
    namespace upvar ::safe S$slave state

    # somehow strip the namespaces 'functionality' out (the danger is that
    # we would strip valid macintosh "../" queries... :
    if {[string match "*::*" $path] || [string match "*..*" $path]} {
    return -code error "invalid characters in path $path"
    }

    # Use a cached map instead of computed local vars and subst.

    return [string map $state(access_path,map) $path]
}

# file name control (limit access to files/resources that should be a
# valid tcl source file)
proc ::safe::CheckFileName {slave file} {
    # This used to limit what can be sourced to ".tcl" and forbid files
    # with more than 1 dot and longer than 14 chars, but I changed that
    # for 8.4 as a safe interp has enough internal protection already to
    # allow sourcing anything. - hobbs

    if {![file exists $file]} {
    # don't tell the file path
    return -code error "no such file or directory"
    }

    if {![file readable $file]} {
    # don't tell the file path
    return -code error "not readable"
    }
}

# AliasFileSubcommand handles selected subcommands of [file] in safe
# interpreters that are *almost* safe. In particular, it just acts to
# prevent discovery of what home directories exist.

proc ::safe::AliasFileSubcommand {slave subcommand name} {
    if {[string match ~* $name]} {
    set name ./$name
    }
    tailcall ::interp invokehidden $slave tcl:file:$subcommand $name
}

# AliasGlob is the target of the "glob" alias in safe interpreters.

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 - -tails {
        lappend cmd $opt
        set got($opt) 1
        incr at
        }
        -types - -type {
        lappend cmd -types [lindex $args [incr at]]
        incr at
        }
        -directory {
        if {$got($opt)} {
            return -code error \
            {"-directory" cannot be used with "-path"}
        }
        set got($opt) 1
        set virtualdir [lindex $args [incr at]]
        incr at
        }
        pkgIndex.tcl {
        # Oops, this is globbing a subdirectory in regular package
        # search. That is not wanted. Abort, handler does catch
        # already (because glob was not defined before). See
        # package.tcl, lines 484ff in tclPkgUnknown.
        return -code error "unknown command glob"
        }
        -* {
        Log $slave "Safe base rejecting glob option '$opt'"
        return -code error "Safe base rejecting glob option '$opt'"
        }
        default {
        break
        }
    }
    if {$got(--)} 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)} {
    try {
        set dir [TranslatePath $slave $virtualdir]
        DirInAccessPath $slave $dir
    } on error msg {
        Log $slave $msg
        if {$got(-nocomplain)} return
        return -code error "permission denied"
    }
    lappend cmd -directory $dir
    }

    # 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]
    foreach opt [lrange $args $at end] {
    if {![regexp $dirPartRE $opt -> thedir thefile]} {
        set thedir .
    } elseif {[string match ~* $thedir]} {
        set thedir ./$thedir
    }
    if {$thedir eq "*" &&
        ($thefile eq "pkgIndex.tcl" || $thefile eq "*.tm")} {
        set mapped 0
        foreach d [glob -directory [TranslatePath $slave $virtualdir] \
               -types d -tails *] {
        catch {
            DirInAccessPath $slave \
            [TranslatePath $slave [file join $virtualdir $d]]
            lappend cmd [file join $d $thefile]
            set mapped 1
        }
        }
        if {$mapped} continue
    }
    try {
        DirInAccessPath $slave [TranslatePath $slave \
            [file join $virtualdir $thedir]]
    } on error msg {
        Log $slave $msg
        if {$got(-nocomplain)} continue
        return -code error "permission denied"
    }
    lappend cmd $opt
    }

    Log $slave "GLOB = $cmd" NOTICE

    if {$got(-nocomplain) && [llength $cmd] eq $firstPattern} {
    return
    }
    try {
    set entries [::interp invokehidden $slave glob {*}$cmd]
    } on error msg {
    Log $slave $msg
    return -code error "script error"
    }

    Log $slave "GLOB < $entries" NOTICE

    # Translate path back to what the slave should see.
    set res {}
    set l [string length $dir]
    foreach p $entries {
    if {[string equal -length $l $dir $p]} {
        set p [string replace $p 0 [expr {$l-1}] $virtualdir]
    }
    lappend res $p
    }

    Log $slave "GLOB > $res" NOTICE
    return $res
}

# AliasSource is the target of the "source" alias in safe interpreters.

proc ::safe::AliasSource {slave args} {
    set argc [llength $args]
    # Extended for handling of Tcl Modules to allow not only "source
    # filename", but "source -encoding E filename" as well.
    if {[lindex $args 0] eq "-encoding"} {
    incr argc -2
    set encoding [lindex $args 1]
    set at 2
    if {$encoding eq "identity"} {
        Log $slave "attempt to use the identity encoding"
        return -code error "permission denied"
    }
    } else {
    set at 0
    set encoding {}
    }
    if {$argc != 1} {
    set msg "wrong # args: should be \"source ?-encoding E? fileName\""
    Log $slave "$msg ($args)"
    return -code error $msg
    }
    set file [lindex $args $at]

    # get the real path from the virtual one.
    if {[catch {
    set realfile [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 $realfile
    } msg]} {
    Log $slave $msg
    return -code error "permission denied"
    }

    # do the checks on the filename :
    if {[catch {
    CheckFileName $slave $realfile
    } msg]} {
    Log $slave "$realfile:$msg"
    return -code error $msg
    }

    # Passed all the tests, lets source it. Note that we do this all manually
    # because we want to control [info script] in the slave so information
    # doesn't leak so much. [Bug 2913625]
    set old [::interp eval $slave {info script}]
    set replacementMsg "script error"
    set code [catch {
    set f [open $realfile]
    fconfigure $f -eofchar \032
    if {$encoding ne ""} {
        fconfigure $f -encoding $encoding
    }
    set contents [read $f]
    close $f
    ::interp eval $slave [list info script $file]
    } msg opt]
    if {$code == 0} {
    set code [catch {::interp eval $slave $contents} msg opt]
    set replacementMsg $msg
    }
    catch {interp eval $slave [list info script $old]}
    # Note that all non-errors are fine result codes from [source], so we must
    # take a little care to do it properly. [Bug 2923613]
    if {$code == 1} {
    Log $slave $msg
    return -code error $replacementMsg
    }
    return -code $code -options $opt $msg
}

# AliasLoad is the target of the "load" alias in safe interpreters.

proc ::safe::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]

    namespace upvar ::safe S$slave state

    # 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 {$target ne ""} {
    # we will try to load into a sub sub interp; check that we want to
    # authorize that.
    if {!$state(nestedok)} {
        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 {$file eq ""} {
    # static package loading
    if {$package eq ""} {
        set msg "load error: empty filename and no package name"
        Log $slave $msg
        return -code error $msg
    }
    if {!$state(staticsok)} {
        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.
    try {
        set file [TranslatePath $slave $file]
    } on error msg {
        Log $slave $msg
        return -code error "permission denied"
    }

    # check the translated path
    try {
        FileInAccessPath $slave $file
    } on error msg {
        Log $slave $msg
        return -code error "permission denied (path)"
    }
    }

    try {
    return [::interp invokehidden $slave load $file $package $target]
    } on error msg {
    Log $slave $msg
    return -code error $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 ::safe::FileInAccessPath {slave file} {
    namespace upvar ::safe S$slave state
    set access_path $state(access_path)

    if {[file isdirectory $file]} {
    return -code error "\"$file\": is a directory"
    }
    set parent [file dirname $file]

    # Normalize paths for comparison since lsearch knows nothing of
    # potential pathname anomalies.
    set norm_parent [file normalize $parent]

    namespace upvar ::safe S$slave state
    if {$norm_parent ni $state(access_path,norm)} {
    return -code error "\"$file\": not in access_path"
    }
}

proc ::safe::DirInAccessPath {slave dir} {
    namespace upvar ::safe S$slave state
    set access_path $state(access_path)

    if {[file isfile $dir]} {
    return -code error "\"$dir\": is a file"
    }

    # Normalize paths for comparison since lsearch knows nothing of
    # potential pathname anomalies.
    set norm_dir [file normalize $dir]

    namespace upvar ::safe S$slave state
    if {$norm_dir ni $state(access_path,norm)} {
    return -code error "\"$dir\": not in access_path"
    }
}

# This procedure is used to report an attempt to use an unsafe member of an
# ensemble command.

proc ::safe::BadSubcommand {slave command subcommand args} {
    set msg "not allowed to invoke subcommand $subcommand of $command"
    Log $slave $msg
    return -code error -errorcode {TCL SAFE SUBCOMMAND} $msg
}

# AliasEncoding is the target of the "encoding" alias in safe interpreters.

proc ::safe::AliasEncoding {slave option args} {
    # Note that [encoding dirs] is not supported in safe slaves at all
    set subcommands {convertfrom convertto names system}
    try {
    set option [tcl::prefix match -error [list -level 1 -errorcode \
        [list TCL LOOKUP INDEX option $option]] $subcommands $option]
    # Special case: [encoding system] ok, but [encoding system foo] not
    if {$option eq "system" && [llength $args]} {
        return -code error -errorcode {TCL WRONGARGS} \
        "wrong # args: should be \"encoding system\""
    }
    } on error {msg options} {
    Log $slave $msg
    return -options $options $msg
    }
    tailcall ::interp invokehidden $slave encoding $option {*}$args
}

# Various minor hiding of platform features. [Bug 2913625]

proc ::safe::AliasExeName {slave} {
    return ""
}

proc ::safe::Setup {} {
    ####
    #
    # Setup the arguments parsing
    #
    ####

    # Share the descriptions
    set temp [::tcl::OptKeyRegister {
    {-accessPath -list {} "access path for the slave"}
    {-noStatics "prevent loading of statically linked pkgs"}
    {-statics true "loading of statically linked pkgs"}
    {-nestedLoadOk "allow nested loading"}
    {-nested false "nested loading"}
    {-deleteHook -script {} "delete hook"}
    }]

    # create case (slave is optional)
    ::tcl::OptKeyRegister {
    {?slave? -name {} "name of the slave (optional)"}
    } ::safe::interpCreate

    # adding the flags sub programs to the command program (relying on Opt's
    # internal implementation details)
    lappend ::tcl::OptDesc(::safe::interpCreate) $::tcl::OptDesc($temp)

    # init and configure (slave is needed)
    ::tcl::OptKeyRegister {
    {slave -name {} "name of the slave"}
    } ::safe::interpIC

    # adding the flags sub programs to the command program (relying on Opt's
    # internal implementation details)
    lappend ::tcl::OptDesc(::safe::interpIC) $::tcl::OptDesc($temp)

    # temp not needed anymore
    ::tcl::OptKeyDelete $temp

    ####
    #
    # Default: No logging.
    #
    ####

    setLogCmd {}

    # Log eventually.
    # To enable error logging, set Log to {puts stderr} for instance,
    # via setLogCmd.
    return
}

namespace eval ::safe {
    # internal variables

    # Log command, set via 'setLogCmd'. Logging is disabled when empty.
    variable Log {}

    # The package maintains a state array per slave interp under its
    # control. The name of this array is S<interp-name>. This array is
    # brought into scope where needed, using 'namespace upvar'. The S
    # prefix is used to avoid that a slave interp called "Log" smashes
    # the "Log" variable.
    #
    # The array's elements are:
    #
    # access_path       : List of paths accessible to the slave.
    # access_path,norm  : Ditto, in normalized form.
    # access_path,slave : Ditto, as the path tokens as seen by the slave.
    # access_path,map   : dict ( token -> path )
    # access_path,remap : dict ( path -> token )
    # tm_path_slave     : List of TM root directories, as tokens seen by the slave.
    # staticsok         : Value of option -statics
    # nestedok          : Value of option -nested
    # cleanupHook       : Value of option -deleteHook
}

::safe::Setup

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.0 [PHP 7 Update] [25.02.2019] maintained by KaizenLouie | C99Shell Github | Generation time: 0.0049 ]--