1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* ext/tk/lib/multi-tk.rb: add restriction to access the entried

command table and manipulate other IPs (for reason of security).
  Now, a IP object can be controlled by only its master IP or the
  default IP.
* ext/tk/lib/remote-tk.rb: add restriction to manipulate.
* ext/tk/tcltklib.c (ip_is_slave_of_p): add TclTkIp#slave_of?(ip)
  to check manipulability.
* ext/tk/lib/tk.rb: bug fix on handling of Tcl's namespaces.
* ext/tk/lib/tk/namespace.rb: ditto.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9562 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nagai 2005-11-18 08:39:29 +00:00
parent e93a1c580e
commit ed9a1f3e8f
6 changed files with 393 additions and 24 deletions

View file

@ -1,3 +1,19 @@
Fri Nov 18 17:35:09 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* ext/tk/lib/multi-tk.rb: add restriction to access the entried
command table and manipulate other IPs (for reason of security).
Now, a IP object can be controlled by only its master IP or the
default IP.
* ext/tk/lib/remote-tk.rb: add restriction to manipulate.
* ext/tk/tcltklib.c (ip_is_slave_of_p): add TclTkIp#slave_of?(ip)
to check manipulability.
* ext/tk/lib/tk.rb: bug fix on handling of Tcl's namespaces.
* ext/tk/lib/tk/namespace.rb: ditto.
Fri Nov 18 16:47:33 2005 NAKAMURA Usaku <usa@ruby-lang.org>
* file.c (file_s_dirname): added checks for some patterns with drive

View file

@ -63,7 +63,82 @@ class MultiTkIp
@@TK_TABLE_LIST = [].taint unless defined?(@@TK_TABLE_LIST)
@@TK_CMD_TBL = {}.taint unless defined?(@@TK_CMD_TBL)
unless defined?(@@TK_CMD_TBL)
@@TK_CMD_TBL = Object.new.taint
@@TK_CMD_TBL.instance_variable_set('@tbl', {}.taint)
class << @@TK_CMD_TBL
allow = [
'__send__', '__id__', 'freeze', 'inspect', 'kind_of?',
'[]', '[]=', 'delete', 'each', 'has_key?'
]
instance_methods.each{|m| undef_method(m) unless allow.index(m)}
def kind_of?(klass)
@tbl.kind_of?(klass)
end
def inspect
if Thread.current.group == ThreadGroup::Default
@tbl.inspect
else
ip = MultiTkIp.__getip
@tbl.reject{|idx, ent| ent.respond_to?(:ip) && ent.ip != ip}.inspect
end
end
def [](idx)
return unless (ent = @tbl[idx])
if Thread.current.group == ThreadGroup::Default
ent
elsif ent.respond_to?(:ip)
(ent.ip == MultiTkIp.__getip)? ent: nil
else
ent
end
end
def []=(idx,val)
if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default
fail SecurityError,"cannot change the entried command"
end
@tbl[idx] = val
end
def delete(idx, &blk)
# if gets an entry, is permited to delete
if self[idx]
@tbl.delete(idx)
elsif blk
blk.call(idx)
else
nil
end
end
def each(&blk)
if Thread.current.group == ThreadGroup::Default
@tbl.each(&blk)
else
ip = MultiTkIp.__getip
@tbl.each{|idx, ent|
blk.call(idx, ent) unless ent.respond_to?(:ip) && ent.ip != ip
}
end
self
end
def has_key?(k)
@tbl.has_key?(k)
end
alias include? has_key?
alias key? has_key?
alias member? has_key?
end
@@TK_CMD_TBL.freeze
end
######################################
@ -876,6 +951,8 @@ class MultiTkIp
private :__create_safetk_frame
def __create_safe_slave_obj(safe_opts, app_name, tk_opts)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
# safe interpreter
ip_name = _create_slave_ip_name
slave_ip = @interp.create_slave(ip_name, true)
@ -917,6 +994,8 @@ class MultiTkIp
end
def __create_trusted_slave_obj(name, keys)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
ip_name = _create_slave_ip_name
slave_ip = @interp.create_slave(ip_name, false)
slave_ip._invoke('set', 'argv0', name) if name.kind_of?(String)
@ -929,6 +1008,8 @@ class MultiTkIp
######################################
def _create_slave_object(keys={})
raise SecurityError, "no permission to manipulate" unless self.manipulable?
ip = MultiTkIp.new_slave(self, keys={})
@slave_ip_tbl[ip.name] = ip
end
@ -1056,6 +1137,7 @@ class MultiTkIp
######################################
def _default_delete_hook(slave)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@slave_ip_tbl.delete(slave)
top = @slave_ip_top.delete(slave)
if top.kind_of?(String)
@ -1090,6 +1172,7 @@ class MultiTkIp
__getip._ip_id_
end
def _ip_id_
# for RemoteTkIp
''
end
@ -1192,19 +1275,21 @@ end
class MultiTkIp
def inspect
s = self.to_s.chop!
if master?
if @interp.deleted?
s << ':deleted-master'
if self.manipulable?
if master?
if @interp.deleted?
s << ':deleted-master'
else
s << ':master'
end
else
s << ':master'
end
else
if @interp.deleted?
s << ':deleted-slave'
elsif @interp.safe?
s << ':safe-slave'
else
s << ':trusted-slave'
if @interp.deleted?
s << ':deleted-slave'
elsif @interp.safe?
s << ':safe-slave'
else
s << ':trusted-slave'
end
end
end
s << '>'
@ -1229,6 +1314,7 @@ class MultiTkIp
end
def alive?
raise SecurityError, "no permission to manipulate" unless self.manipulable?
begin
return false unless @cmd_receiver.alive?
return false if @interp.deleted?
@ -1262,6 +1348,7 @@ class MultiTkIp
end
def slaves(all = false)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp','slaves').split.map!{|name|
if @slave_ip_tbl.key?(name)
@slave_ip_tbl[name]
@ -1275,6 +1362,20 @@ class MultiTkIp
def self.slaves(all = false)
__getip.slaves(all)
end
def manipulable?
return true if (Thread.current.group == ThreadGroup::Default)
ip = MultiTkIp.__getip
(ip == self) || ip._is_master_of?(@interp)
end
def self.manipulable?
true
end
def _is_master_of?(tcltkip_obj)
tcltkip_obj.slave_of?(@interp)
end
protected :_is_master_of?
end
@ -1403,6 +1504,7 @@ class MultiTkIp
# instance method
def eval_proc_core(req_val, cmd, *args)
# check
raise SecurityError, "no permission to manipulate" unless self.manipulable?
unless cmd.kind_of?(Proc) || cmd.kind_of?(Method)
raise RuntimeError, "A Proc/Method object is expected for the 'cmd' argument"
end
@ -1870,6 +1972,7 @@ end
# depend on TclTkIp
class MultiTkIp
def mainloop(check_root = true, restart_on_dead = true)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
#return self if self.slave?
#return self if self != @@DEFAULT_MASTER
if self != @@DEFAULT_MASTER
@ -1978,26 +2081,32 @@ class MultiTkIp
end
def make_safe
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.make_safe
end
def safe?
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.safe?
end
def safe_base?
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@safe_base
end
def allow_ruby_exit?
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.allow_ruby_exit?
end
def allow_ruby_exit= (mode)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.allow_ruby_exit = mode
end
def delete
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@slave_ip_tbl.each{|name, subip|
_destroy_slaves_of_slaveIP(subip)
=begin
@ -2060,19 +2169,23 @@ class MultiTkIp
end
def deleted?
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.deleted?
end
def has_mainwindow?
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.has_mainwindow?
end
def invalid_namespace?
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.invalid_namespace?
end
def abort(msg = nil)
if master?
raise SecurityError, "no permission to manipulate" unless self.manipulable?
if master? && !safe? && allow_ruby_exit?
if msg
Kernel.abort(msg)
else
@ -2086,7 +2199,8 @@ class MultiTkIp
end
def exit(st = true)
if master?
raise SecurityError, "no permission to manipulate" unless self.manipulable?
if master? && !safe? && allow_ruby_exit?
Kernel.exit(st)
else
delete
@ -2095,6 +2209,7 @@ class MultiTkIp
end
def exit!(st = false)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
if master? && !safe? && allow_ruby_exit?
Kernel.exit!(st)
else
@ -2104,6 +2219,8 @@ class MultiTkIp
end
def restart(app_name = nil, keys = {})
raise SecurityError, "no permission to manipulate" unless self.manipulable?
_init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS)
@interp._invoke('set', 'argv0', app_name) if app_name
@ -2115,102 +2232,130 @@ class MultiTkIp
end
def __eval(str)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.__eval(str)
end
def __invoke(*args)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.__invoke(*args)
end
def _eval(str)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._eval(str)
end
def _invoke(*args)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke(*args)
end
def _eval_without_enc(str)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._eval_without_enc(str)
end
def _invoke_without_enc(*args)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke_without_enc(*args)
end
def _eval_with_enc(str)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._eval_with_enc(str)
end
def _invoke_with_enc(*args)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke_with_enc(*args)
end
def _toUTF8(str, encoding=nil)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._toUTF8(str, encoding)
end
def _fromUTF8(str, encoding=nil)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._fromUTF8(str, encoding)
end
def _thread_vwait(var)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._thread_vwait(var)
end
def _thread_tkwait(mode, target)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._thread_tkwait(mode, target)
end
def _return_value
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._return_value
end
def _get_variable(var, flag)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._get_variable(var, flag)
end
def _get_variable2(var, idx, flag)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._get_variable2(var, idx, flag)
end
def _set_variable(var, value, flag)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._set_variable(var, value, flag)
end
def _set_variable2(var, idx, value, flag)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._set_variable2(var, idx, value, flag)
end
def _unset_variable(var, flag)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._unset_variable(var, flag)
end
def _unset_variable2(var, idx, flag)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._unset_variable2(var, idx, flag)
end
def _get_global_var(var)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._get_global_var(var)
end
def _get_global_var2(var, idx)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._get_global_var2(var, idx)
end
def _set_global_var(var, value)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._set_global_var(var, value)
end
def _set_global_var2(var, idx, value)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._set_global_var2(var, idx, value)
end
def _unset_global_var(var)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._unset_global_var(var)
end
def _unset_global_var2(var, idx)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._unset_global_var2(var, idx)
end
def _split_tklist(str)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._split_tklist(str)
end
def _merge_tklist(*args)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._merge_tklist(*args)
end
def _conv_listelement(arg)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._conv_listelement(arg)
end
end
@ -2261,6 +2406,7 @@ class MultiTkIp
private :_slavearg
def alias_info(slave, cmd_name)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
_lst2ary(@interp._invoke('interp', 'alias', _slavearg(slave), cmd_name))
end
def self.alias_info(slave, cmd_name)
@ -2268,6 +2414,7 @@ class MultiTkIp
end
def alias_delete(slave, cmd_name)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'alias', _slavearg(slave), cmd_name, '')
self
end
@ -2277,6 +2424,7 @@ class MultiTkIp
end
def def_alias(slave, new_cmd, org_cmd, *args)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
ret = @interp._invoke('interp', 'alias', _slavearg(slave), new_cmd,
'', org_cmd, *args)
(ret == new_cmd)? self: nil
@ -2287,6 +2435,7 @@ class MultiTkIp
end
def aliases(slave = '')
raise SecurityError, "no permission to manipulate" unless self.manipulable?
_lst2ary(@interp._invoke('interp', 'aliases', _slavearg(slave)))
end
def self.aliases(slave = '')
@ -2294,6 +2443,7 @@ class MultiTkIp
end
def delete_slaves(*args)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
slaves = args.collect{|s| _slavearg(s)}
@interp._invoke('interp', 'delete', *slaves) if slaves.size > 0
self
@ -2304,6 +2454,7 @@ class MultiTkIp
end
def exist?(slave = '')
raise SecurityError, "no permission to manipulate" unless self.manipulable?
ret = @interp._invoke('interp', 'exists', _slavearg(slave))
(ret == '1')? true: false
end
@ -2312,6 +2463,7 @@ class MultiTkIp
end
def delete_cmd(slave, cmd)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
slave_invoke = @interp._invoke('list', 'rename', cmd, '')
@interp._invoke('interp', 'eval', _slavearg(slave), slave_invoke)
self
@ -2322,6 +2474,7 @@ class MultiTkIp
end
def expose_cmd(slave, cmd, aliasname = nil)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
if aliasname
@interp._invoke('interp', 'expose', _slavearg(slave), cmd, aliasname)
else
@ -2335,6 +2488,7 @@ class MultiTkIp
end
def hide_cmd(slave, cmd, aliasname = nil)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
if aliasname
@interp._invoke('interp', 'hide', _slavearg(slave), cmd, aliasname)
else
@ -2348,6 +2502,7 @@ class MultiTkIp
end
def hidden_cmds(slave = '')
raise SecurityError, "no permission to manipulate" unless self.manipulable?
_lst2ary(@interp._invoke('interp', 'hidden', _slavearg(slave)))
end
def self.hidden_cmds(slave = '')
@ -2355,6 +2510,7 @@ class MultiTkIp
end
def invoke_hidden(slave, cmd, *args)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
if args[-1].kind_of?(Hash)
keys = _symbolkey2str(args.pop)
else
@ -2374,6 +2530,7 @@ class MultiTkIp
end
def invoke_hidden_on_global(slave, cmd, *args)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
if args[-1].kind_of?(Hash)
keys = _symbolkey2str(args.pop)
else
@ -2395,6 +2552,7 @@ class MultiTkIp
def invoke_hidden_on_namespace(slave, ns, cmd, *args)
# for Tcl8.5 or later
raise SecurityError, "no permission to manipulate" unless self.manipulable?
if args[-1].kind_of?(Hash)
keys = _symbolkey2str(args.pop)
else
@ -2411,6 +2569,7 @@ class MultiTkIp
end
def mark_trusted(slave = '')
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'marktrusted', _slavearg(slave))
self
end
@ -2420,6 +2579,8 @@ class MultiTkIp
end
def set_bgerror_handler(cmd = Proc.new, slave = nil, &b)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
unless TkComm._callback_entry?(cmd)
if !slave && b
slave = cmd
@ -2435,6 +2596,7 @@ class MultiTkIp
end
def get_bgerror_handler(slave = '')
raise SecurityError, "no permission to manipulate" unless self.manipulable?
procedure(@interp._invoke('interp', 'bgerror', _slavearg(slave)))
end
def self.bgerror(slave = '')
@ -2442,6 +2604,7 @@ class MultiTkIp
end
def set_limit(limit_type, slave = '', opts = {})
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'limit', _slavearg(slave), limit_type, opts)
end
def self.set_limit(limit_type, slave = '', opts = {})
@ -2449,6 +2612,8 @@ class MultiTkIp
end
def get_limit(limit_type, slave = '', slot = nil)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
if slot
num_or_str(@interp._invoke('interp', 'limit', _slavearg(slave),
limit_type, slot))
@ -2472,6 +2637,7 @@ class MultiTkIp
end
def recursion_limit(slave = '', limit = None)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
number(@interp._invoke('interp', 'recursionlimit',
_slavearg(slave), limit))
end
@ -2480,6 +2646,7 @@ class MultiTkIp
end
def alias_target(aliascmd, slave = '')
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'target', _slavearg(slave), aliascmd)
end
def self.alias_target(aliascmd, slave = '')
@ -2487,6 +2654,7 @@ class MultiTkIp
end
def share_stdin(dist, src = '')
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'share', src, 'stdin', dist)
self
end
@ -2496,6 +2664,7 @@ class MultiTkIp
end
def share_stdout(dist, src = '')
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'share', src, 'stdout', dist)
self
end
@ -2505,6 +2674,7 @@ class MultiTkIp
end
def share_stderr(dist, src = '')
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'share', src, 'stderr', dist)
self
end
@ -2514,6 +2684,7 @@ class MultiTkIp
end
def transfer_stdin(dist, src = '')
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'transfer', src, 'stdin', dist)
self
end
@ -2523,6 +2694,7 @@ class MultiTkIp
end
def transfer_stdout(dist, src = '')
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'transfer', src, 'stdout', dist)
self
end
@ -2532,6 +2704,7 @@ class MultiTkIp
end
def transfer_stderr(dist, src = '')
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'transfer', src, 'stderr', dist)
self
end
@ -2541,6 +2714,7 @@ class MultiTkIp
end
def share_stdio(dist, src = '')
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'share', src, 'stdin', dist)
@interp._invoke('interp', 'share', src, 'stdout', dist)
@interp._invoke('interp', 'share', src, 'stderr', dist)
@ -2552,6 +2726,7 @@ class MultiTkIp
end
def transfer_stdio(dist, src = '')
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'transfer', src, 'stdin', dist)
@interp._invoke('interp', 'transfer', src, 'stdout', dist)
@interp._invoke('interp', 'transfer', src, 'stderr', dist)
@ -2586,8 +2761,12 @@ class MultiTkIp
conf = _lst2ary(ip._eval("::safe::interpConfigure " +
@ip_name + " -#{slot}"))
if conf[0] == '-deleteHook'
=begin
if conf[1] =~ /^rb_out\S* (c(_\d+_)?\d+)/
ret[conf[0][1..-1]] = MultiTkIp._tk_cmd_tbl[$1]
=end
if conf[1] =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
ret[conf[0][1..-1]] = MultiTkIp._tk_cmd_tbl[$4]
else
ret[conf[0][1..-1]] = conf[1]
end
@ -2598,8 +2777,12 @@ class MultiTkIp
Hash[*_lst2ary(ip._eval("::safe::interpConfigure " +
@ip_name))].each{|k, v|
if k == '-deleteHook'
=begin
if v =~ /^rb_out\S* (c(_\d+_)?\d+)/
ret[k[1..-1]] = MultiTkIp._tk_cmd_tbl[$1]
=end
if v =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
ret[k[1..-1]] = MultiTkIp._tk_cmd_tbl[$4]
else
ret[k[1..-1]] = v
end
@ -2636,18 +2819,22 @@ end
# encoding convert
class MultiTkIp
def encoding
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.encoding
end
def encoding=(enc)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.encoding = enc
end
def encoding_convertfrom(str, enc=None)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.encoding_convertfrom(str, enc)
end
alias encoding_convert_from encoding_convertfrom
def encoding_convertto(str, enc=None)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.encoding_convertto(str, enc)
end
alias encoding_convert_to encoding_convertto

View file

@ -66,6 +66,11 @@ class RemoteTkIp
end
@interp = MultiTkIp.__getip
if @interp.safe?
fail SecurityError, "safe-IP cannot create RemoteTkIp"
end
@interp.allow_ruby_exit = false
@appname = @interp._invoke('tk', 'appname')
@remote = remote_ip.to_s.dup.freeze
@ -127,11 +132,26 @@ class RemoteTkIp
self.freeze # defend against modification
end
def manipulable?
return true if (Thread.current.group == ThreadGroup::Default)
MultiTkIp.__getip == @interp && ! @interp.safe?
end
def self.manipulable?
true
end
def _is_master_of?(tcltkip_obj)
tcltkip_obj == @interp
end
protected :_is_master_of?
def _ip_id_
@ip_id
end
def _available_check(timeout = 5)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
return nil if timeout < 1
@ret_val.value = ''
@interp._invoke('send', '-async', @remote,
@ -150,6 +170,8 @@ class RemoteTkIp
private :_available_check
def _create_connection
raise SecurityError, "no permission to manipulate" unless self.manipulable?
ip_id = '_' + @interp._invoke('send', @remote, <<-'EOS') + '_'
if {[catch {set _rubytk_control_ip_id_} ret] != 0} {
set _rubytk_control_ip_id_ 0
@ -170,6 +192,8 @@ class RemoteTkIp
private :_create_connection
def _appsend(enc_mode, async, *cmds)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
p ['_appsend', [@remote, @displayof], enc_mode, async, cmds] if $DEBUG
if $SAFE >= 4
fail SecurityError, "cannot send commands at level 4"
@ -210,6 +234,8 @@ class RemoteTkIp
end
def appsend(async, *args)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
if async != true && async != false && async != nil
args.unshift(async)
async = false
@ -222,6 +248,8 @@ class RemoteTkIp
end
def rb_appsend(async, *args)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
if async != true && async != false && async != nil
args.unshift(async)
async = false
@ -267,6 +295,8 @@ class RemoteTkIp
end
def deleted?
raise SecurityError, "no permission to manipulate" unless self.manipulable?
if @displayof
lst = @interp._invoke_without_enc('winfo', 'interps',
'-displayof', @displayof)
@ -282,6 +312,8 @@ class RemoteTkIp
end
def has_mainwindow?
raise SecurityError, "no permission to manipulate" unless self.manipulable?
begin
inf = @interp._invoke_without_enc('info', 'command', '.')
rescue Exception
@ -333,10 +365,12 @@ class RemoteTkIp
end
def _toUTF8(str, encoding=nil)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._toUTF8(str, encoding)
end
def _fromUTF8(str, encoding=nil)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._fromUTF8(str, encoding)
end
@ -349,6 +383,7 @@ class RemoteTkIp
end
def _return_value
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._return_value
end
@ -401,14 +436,17 @@ class RemoteTkIp
end
def _split_tklist(str)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._split_tklist(str)
end
def _merge_tklist(*args)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._merge_tklist(*args)
end
def _conv_listelement(str)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._conv_listelement(str)
end

View file

@ -16,6 +16,7 @@ class TclTkIp
alias _invoke_without_enc _invoke
def _ip_id_
# for RemoteTkIp
''
end
end
@ -189,6 +190,7 @@ module TkComm
module_function :_at
def tk_tcl2ruby(val, enc_mode = false, listobj = true)
=begin
if val =~ /^rb_out\S* (c(_\d+_)?\d+)/
#return Tk_CMDTBL[$1]
return TkCore::INTERP.tk_cmd_tbl[$1]
@ -199,6 +201,10 @@ module TkComm
# cmd_obj.cmd
#end
end
=end
if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
return TkCore::INTERP.tk_cmd_tbl[$4]
end
#if val.include? ?\s
# return val.split.collect{|v| tk_tcl2ruby(v)}
#end
@ -601,10 +607,14 @@ end
end
end
def procedure(val)
=begin
if val =~ /^rb_out\S* (c(_\d+_)?\d+)/
#Tk_CMDTBL[$1]
#TkCore::INTERP.tk_cmd_tbl[$1]
TkCore::INTERP.tk_cmd_tbl[$1].cmd
=end
if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
return TkCore::INTERP.tk_cmd_tbl[$4].cmd
else
#nil
val
@ -783,6 +793,13 @@ end
def install_cmd(cmd)
return '' if cmd == ''
begin
ns = TkCore::INTERP._invoke_without_enc('namespace', 'current')
ns = nil if ns == '::' # for backward compatibility
rescue
# probably, Tcl7.6
ns = nil
end
id = _next_cmd_id
#Tk_CMDTBL[id] = cmd
if cmd.kind_of?(TkCallbackEntry)
@ -794,10 +811,15 @@ end
@cmdtbl.taint unless @cmdtbl.tainted?
@cmdtbl.push id
#return Kernel.format("rb_out %s", id);
return 'rb_out' + TkCore::INTERP._ip_id_ + ' ' + id
if ns
'rb_out' << TkCore::INTERP._ip_id_ << ' ' << ns << ' ' << id
else
'rb_out' << TkCore::INTERP._ip_id_ << ' ' << id
end
end
def uninstall_cmd(id)
id = $1 if /rb_out\S* (c(_\d+_)?\d+)/ =~ id
#id = $1 if /rb_out\S* (c(_\d+_)?\d+)/ =~ id
id = $4 if id =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
#Tk_CMDTBL.delete(id)
TkCore::INTERP.tk_cmd_tbl.delete(id)
end
@ -915,9 +937,13 @@ module TkComm
def _bindinfo(what, context=nil)
if context
tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]) .collect {|cmdline|
=begin
if cmdline =~ /^rb_out\S* (c(?:_\d+_)?\d+)\s+(.*)$/
#[Tk_CMDTBL[$1], $2]
[TkCore::INTERP.tk_cmd_tbl[$1], $2]
=end
if cmdline =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
[TkCore::INTERP.tk_cmd_tbl[$4], $5]
else
cmdline
end
@ -1081,6 +1107,13 @@ module TkCore
INTERP.instance_eval{
@tk_cmd_tbl = {}.taint
def @tk_cmd_tbl.[]=(idx,val)
if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default
fail SecurityError,"cannot change the entried command"
end
super(idx,val)
end
@tk_windows = {}.taint
@tk_table_list = [].taint
@ -1190,6 +1223,28 @@ module TkCore
INTERP.add_tk_procs(TclTkLib::FINALIZE_PROC_NAME, '',
"bind all <#{WIDGET_DESTROY_HOOK}> {}")
INTERP.add_tk_procs('rb_out', 'ns args', <<-'EOL')
if [regexp {^::} $ns] {
set cmd {namespace eval $ns {ruby_cmd TkCore callback} $args}
} else {
set cmd {eval {ruby_cmd TkCore callback} $ns $args}
}
if {[set st [catch $cmd ret]] != 0} {
#return -code $st $ret
set idx [string first "\n\n" $ret]
if {$idx > 0} {
return -code $st \
-errorinfo [string range $ret [expr $idx + 2] \
[string length $ret]] \
[string range $ret 0 [expr $idx - 1]]
} else {
return -code $st $ret
}
} else {
return $ret
}
EOL
=begin
INTERP.add_tk_procs('rb_out', 'args', <<-'EOL')
if {[set st [catch {eval {ruby_cmd TkCore callback} $args} ret]] != 0} {
#return -code $st $ret
@ -1206,6 +1261,7 @@ module TkCore
return $ret
}
EOL
=end
=begin
INTERP.add_tk_procs('rb_out', 'args', <<-'EOL')
#regsub -all {\\} $args {\\\\} args
@ -4443,7 +4499,7 @@ end
#Tk.freeze
module Tk
RELEASE_DATE = '2005-10-24'.freeze
RELEASE_DATE = '2005-11-18'.freeze
autoload :AUTO_PATH, 'tk/variable'
autoload :TCL_PACKAGE_PATH, 'tk/variable'

View file

@ -14,6 +14,14 @@ class TkNamespace < TkObject
Tk_Namespace_ID_TBL = TkCore::INTERP.create_table
Tk_Namespace_ID = ["ns".freeze, "00000".taint].freeze
TkCore::INTERP.init_ip_env{ Tk_Namespace_ID_TBL.clear }
def TkNamespace.id2obj(id)
Tk_Namespace_ID_TBL[id]? Tk_Namespace_ID_TBL[id]: id
end
#####################################
class Ensemble < TkObject
def __cget_cmd
['namespace', 'ensemble', 'configure', self.path]
@ -107,6 +115,8 @@ class TkNamespace < TkObject
end
end
#####################################
class ScopeArgs < Array
include Tk
@ -139,6 +149,8 @@ class TkNamespace < TkObject
end
end
#####################################
class NsCode < TkObject
def initialize(scope)
@scope = scope + ' '
@ -154,6 +166,18 @@ class TkNamespace < TkObject
end
end
#####################################
def install_cmd(cmd)
lst = tk_split_simplelist(super(cmd), false, false)
if lst[1] =~ /^::/
lst[1] = @fullname
else
lst.insert(1, @fullname)
end
TkCore::INTERP._merge_tklist(*lst)
end
alias __tk_call tk_call
alias __tk_call_without_enc tk_call_without_enc
alias __tk_call_with_enc tk_call_with_enc
@ -252,17 +276,37 @@ class TkNamespace < TkObject
_get_eval_string(cmd, false)))
end
def self.current
def self.current_path
tk_call('namespace', 'current')
end
def current_path
@fullname
end
def self.current
ns = self.current_path
if Tk_Namespace_ID_TBL.key?(ns)
Tk_Namespace_ID_TBL[ns]
else
ns
end
end
def current_namespace
# ns_tk_call('namespace', 'current')
@fullname
# @fullname
self
end
alias current current_namespace
def self.delete(*ns_list)
tk_call('namespace', 'delete', *ns_list)
ns_list.each{|ns|
if ns.kind_of?(TkNamespace)
Tk_Namespace_ID_TBL.delete(ns.path)
else
Tk_Namespace_ID_TBL.delete(ns.to_s)
end
}
end
def delete
TkNamespece.delete(@fullname)
@ -302,14 +346,14 @@ class TkNamespace < TkObject
ret = code_obj.call(*args)
# uninstall_cmd(TkCore::INTERP._split_tklist(code_obj.path)[-1])
uninstall_cmd(_fromUTF8(TkCore::INTERP._split_tklist(_toUTF8(code_obj.path))[-1]))
ret
tk_tcl2ruby(ret)
end
def self.exist?(ns)
bool(tk_call('namespace', 'exists', ns))
end
def exist?
TkNamespece.delete(@fullname)
TkNamespece.exist?(@fullname)
end
def self.export(*patterns)
@ -349,7 +393,7 @@ class TkNamespace < TkObject
tk_call('namespace', 'inscope', namespace, script, *args)
end
def inscope(script, *args)
TkNamespace(@fullname, script, *args)
TkNamespace.inscope(@fullname, script, *args)
end
def self.origin(cmd)
@ -396,3 +440,5 @@ class TkNamespace < TkObject
tk_call('namespace', 'which', '-variable', name)
end
end
TkNamespace::Global = TkNamespace.new('::')

View file

@ -4,7 +4,7 @@
* Oct. 24, 1997 Y. Matsumoto
*/
#define TCLTKLIB_RELEASE_DATE "2005-11-07"
#define TCLTKLIB_RELEASE_DATE "2005-11-18"
#include "ruby.h"
#include "rubysig.h"
@ -94,6 +94,8 @@ static VALUE eTkCallbackRetry;
static VALUE eTkCallbackRedo;
static VALUE eTkCallbackThrow;
static VALUE tcltkip_class;
static ID ID_at_enc;
static ID ID_at_interp;
@ -4926,6 +4928,25 @@ ip_create_slave(argc, argv, self)
return tk_funcall(ip_create_slave_core, 2, callargv, self);
}
/* self is slave of master? */
static VALUE
ip_is_slave_of_p(self, master)
VALUE self, master;
{
if (!rb_obj_is_kind_of(master, tcltkip_class)) {
rb_raise(rb_eArgError, "expected TclTkIp object");
}
if (Tcl_GetMaster(get_ip(self)->ip) == get_ip(master)->ip) {
return Qtrue;
} else {
return Qfalse;
}
}
/* create console (if supported) */
#if defined(MAC_TCL) || defined(__WIN32__)
#if TCL_MAJOR_VERSION < 8 \
|| (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0) \
@ -7625,6 +7646,10 @@ Init_tcltklib()
/* --------------------------------------------------------------- */
tcltkip_class = ip;
/* --------------------------------------------------------------- */
rb_global_variable(&eTkCallbackReturn);
rb_global_variable(&eTkCallbackBreak);
rb_global_variable(&eTkCallbackContinue);
@ -7766,6 +7791,7 @@ Init_tcltklib()
rb_define_alloc_func(ip, ip_alloc);
rb_define_method(ip, "initialize", ip_init, -1);
rb_define_method(ip, "create_slave", ip_create_slave, -1);
rb_define_method(ip, "slave_of?", ip_is_slave_of_p, 1);
rb_define_method(ip, "make_safe", ip_make_safe, 0);
rb_define_method(ip, "safe?", ip_is_safe_p, 0);
rb_define_method(ip, "allow_ruby_exit?", ip_allow_ruby_exit_p, 0);