Class: EvalHook::HookHandler

Inherits:
Object
  • Object
show all
Includes:
RedirectHelper
Defined in:
lib/evalhook.rb,
lib/evalhook/multi_hook_handler.rb

Direct Known Subclasses

MultiHookHandler

Defined Under Namespace

Classes: HookedCallValue

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from RedirectHelper

#const_value, #global_value, #redirect_cdecl, #redirect_gasgn, #redirect_method

Constructor Details

#initializeHookHandler

Returns a new instance of HookHandler.



47
48
49
50
# File 'lib/evalhook.rb', line 47

def initialize
  super
  self.base_namespace = Object
end

Instance Attribute Details

#base_namespaceObject

Returns the value of attribute base_namespace.



45
46
47
# File 'lib/evalhook.rb', line 45

def base_namespace
  @base_namespace
end

Instance Method Details

#evalhook(*args) ⇒ Object



277
278
279
# File 'lib/evalhook.rb', line 277

def evalhook(*args)
  evalhook_i(*args)
end

#evalhook_i(code, b_ = nil, name = "(eval)", line = 1) ⇒ Object



244
245
246
# File 'lib/evalhook.rb', line 244

def evalhook_i(code, b_ = nil, name = "(eval)", line = 1)
  packet(code).run(b_,name,line)
end

#handle_cdecl(*args) ⇒ Object

Overwrite to handle the assignment/creation of constants. By default do nothing but assign the variable. See examples



207
208
209
# File 'lib/evalhook.rb', line 207

def handle_cdecl(*args)
  nil
end

#handle_colon2(context, name) ⇒ Object



231
232
233
# File 'lib/evalhook.rb', line 231

def handle_colon2(context,name)
  nil
end

#handle_colon3(*args) ⇒ Object

Overwrite to handle the evaluation o colon3 nodes (access to global namespace)



212
213
214
# File 'lib/evalhook.rb', line 212

def handle_colon3(*args)
  nil
end

#handle_const(name) ⇒ Object

Overwrite to handle const read access



227
228
229
# File 'lib/evalhook.rb', line 227

def handle_const(name)
  nil
end

#handle_gasgn(*args) ⇒ Object

Overwrite to handle the assignment/creation of global variables. By default do nothing but assign the variable. See examples



202
203
204
# File 'lib/evalhook.rb', line 202

def handle_gasgn(*args)
  nil
end

#handle_gvar(global_id) ⇒ Object

Overwrite to handle global variable read access



236
237
238
# File 'lib/evalhook.rb', line 236

def handle_gvar(global_id)
  nil
end

#handle_method(klass, recv, method_name) ⇒ Object

Overwrite to handle the method calls. By default do nothing and the methods are called normally



222
223
224
# File 'lib/evalhook.rb', line 222

def handle_method(klass,recv,method_name)
  nil
end

#handle_xstr(*args) ⇒ Object

Overwrite to handle the evaluation o xstr nodes (execution of shell commands)



217
218
219
# File 'lib/evalhook.rb', line 217

def handle_xstr(*args)
  nil
end

#hooked_cdecl(klass, const_id, value) ⇒ Object

:nodoc:



97
98
99
100
101
102
103
104
105
106
107
# File 'lib/evalhook.rb', line 97

def hooked_cdecl(klass, const_id, value) #:nodoc:
  ret = handle_cdecl( klass, const_id, value )

  if ret then
    klass = ret.klass
    const_id = ret.const_id
    value = ret.value
  end

  klass.const_set(const_id, value)
end

#hooked_colon2(context, name) ⇒ Object

:nodoc:



88
89
90
91
92
93
94
95
# File 'lib/evalhook.rb', line 88

def hooked_colon2(context,name) #:nodoc:
  ret = handle_colon2(context, name)
  if ret
    ret.value
  else
     context.const_get(name)
  end
end

#hooked_const(name) ⇒ Object

:nodoc:



79
80
81
82
83
84
85
86
# File 'lib/evalhook.rb', line 79

def hooked_const(name) #:nodoc:
  ret = handle_const(name)
  if ret
    ret.value
  else
     Object.const_get(name)
   end
end

#hooked_gasgn(global_id, value) ⇒ Object

:nodoc:



109
110
111
112
113
114
115
116
117
# File 'lib/evalhook.rb', line 109

def hooked_gasgn(global_id, value) #:nodoc:
  ret = handle_gasgn(global_id, value)

  if ret then
    global_id = ret.global_id
    value = ret.value
  end
  eval("#{global_id} = value")
end

#hooked_gvar(global_id) ⇒ Object

:nodoc:



70
71
72
73
74
75
76
77
# File 'lib/evalhook.rb', line 70

def hooked_gvar(global_id) #:nodoc:
  ret = handle_gvar(global_id)
  if ret
    ret.value
  else
    eval(global_id.to_s)
  end
end

#hooked_method(receiver, mname, klass = nil) ⇒ Object

:nodoc:



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/evalhook.rb', line 128

def hooked_method(receiver, mname, klass = nil) #:nodoc:
  m = nil
  is_method_missing = false

  unless klass
    m = begin
      receiver.method(mname)
    rescue
      is_method_missing = true
      receiver.public_method(:method_missing)
    end
    klass = m.owner
  else
    m = klass.instance_method(mname).bind(receiver)
  end

  ret = handle_method(klass, receiver, mname )

  if ret.kind_of? RedirectHelper::MethodRedirect
    klass = ret.klass
    mname = ret.method_name
    receiver = ret.recv

    begin
      m = ret.klass.instance_method(ret.method_name).bind(ret.recv)
    rescue
      m = ret.recv.method(ret.method_name)
    end
  end

  if is_method_missing
    orig_m = m
    m = lambda{|*x| orig_m.call(mname,*x) }
  end
  m
end

#hooked_variable_method(receiver, mname, _binding) ⇒ Object

:nodoc:



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/evalhook.rb', line 165

def hooked_variable_method(receiver, mname, _binding) #:nodoc:
  local_vars = _binding.eval("local_variables").map(&:to_s)
  if local_vars.include? mname.to_s
    HookedCallValue.new( _binding.eval(mname.to_s) )
  else
    is_method_missing = false
    m = begin 
      receiver.method(mname)
    rescue
      is_method_missing = true
      receiver.method(:method_missing)
    end

    klass = m.owner
    ret = handle_method(klass, receiver, mname )

    if ret.kind_of? RedirectHelper::MethodRedirect
      klass = ret.klass
      mname = ret.method_name
      receiver = ret.recv

      begin
        m = ret.klass.instance_method(ret.method_name).bind(ret.recv)
      rescue
        m = ret.recv.method(ret.method_name)
      end
    end

    if is_method_missing
      orig_m = m
      m = lambda{|*x| orig_m.call(mname,*x) }
    end
    m
  end
end

#hooked_xstr(str) ⇒ Object

:nodoc:



240
241
242
# File 'lib/evalhook.rb', line 240

def hooked_xstr(str) #:nodoc:
  runstr = handle_xstr(str) || str
end

#internal_eval(b_, original_args) ⇒ Object

used internally

Raises:

  • (ArgumentError)


271
272
273
274
# File 'lib/evalhook.rb', line 271

def internal_eval(b_, original_args)
  raise ArgumentError if original_args.size == 0
  evalhook_i(original_args[0], original_args[1] || b_, original_args[2] || "(eval)", original_args[3] || 0)
end

#packet(code) ⇒ Object

Creates a packet of preprocessed ruby code to run it later , useful to execute the same code repeatedly and avoid heavy preprocessing of ruby code all the times.

See EvalHook::Packet for more information

Example:

hook_handler = HookHandler.new

pack = hook_handler.packet('print "hello world\n"')
10.times do
  pack.run
end


262
263
264
# File 'lib/evalhook.rb', line 262

def packet(code)
  partialruby_context.packet(code)
end

#partialruby_contextObject



52
53
54
55
56
57
58
59
60
# File 'lib/evalhook.rb', line 52

def partialruby_context
  unless @partialruby_context
    @partialruby_context = PartialRuby::Context.new
    @partialruby_context.pre_process do |tree|
      EvalHook::TreeProcessor.new(self).process(tree)
    end
  end
  @partialruby_context
end

#private_method_check(recv, mname) ⇒ Object



282
283
284
285
286
287
288
289
290
291
292
293
# File 'lib/evalhook.rb', line 282

def private_method_check(recv, mname)
  begin
    recv.public_method(mname) 
  rescue NameError 
    begin
      recv.public_method(:method_missing) 
    rescue NameError
      raise NoMethodError
    end
  end
  recv
end