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.



62
63
64
65
# File 'lib/evalhook.rb', line 62

def initialize
  super
  self.base_namespace = Object
end

Instance Attribute Details

#base_namespaceObject

Returns the value of attribute base_namespace.



60
61
62
# File 'lib/evalhook.rb', line 60

def base_namespace
  @base_namespace
end

Instance Method Details

#disposeObject

Disposes all code packets created on this context



295
296
297
298
299
# File 'lib/evalhook.rb', line 295

def dispose
  if @all_packets
    @all_packets.each(&:dispose)
  end
end

#evalhook(*args) ⇒ Object



312
313
314
# File 'lib/evalhook.rb', line 312

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

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



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

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



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

def handle_cdecl(*args)
  nil
end

#handle_colon2(context, name) ⇒ Object



250
251
252
# File 'lib/evalhook.rb', line 250

def handle_colon2(context,name)
  nil
end

#handle_colon3(*args) ⇒ Object

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



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

def handle_colon3(*args)
  nil
end

#handle_const(name) ⇒ Object

Overwrite to handle const read access



246
247
248
# File 'lib/evalhook.rb', line 246

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



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

def handle_gasgn(*args)
  nil
end

#handle_gvar(global_id) ⇒ Object

Overwrite to handle global variable read access



255
256
257
# File 'lib/evalhook.rb', line 255

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



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

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)



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

def handle_xstr(*args)
  nil
end

#hooked_cdecl(klass, const_id, value) ⇒ Object

:nodoc:



116
117
118
119
120
121
122
123
124
125
126
# File 'lib/evalhook.rb', line 116

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:



107
108
109
110
111
112
113
114
# File 'lib/evalhook.rb', line 107

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:



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

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:



128
129
130
131
132
133
134
135
136
# File 'lib/evalhook.rb', line 128

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:



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

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:



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/evalhook.rb', line 147

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:



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/evalhook.rb', line 184

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:



259
260
261
# File 'lib/evalhook.rb', line 259

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

#internal_eval(b_, original_args) ⇒ Object

used internally

Raises:

  • (ArgumentError)


306
307
308
309
# File 'lib/evalhook.rb', line 306

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

pack.dispose


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

def packet(code)
  @global_variable_name = nil
  partialruby_packet = partialruby_context.packet(code)

  @all_packets ||= []
  newpacket = EvalHook::Packet.new(partialruby_packet, @global_variable_name)
  @all_packets << newpacket
  newpacket
end

#partialruby_contextObject



67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/evalhook.rb', line 67

def partialruby_context
  unless @partialruby_context
    @partialruby_context = PartialRuby::Context.new

    @partialruby_context.pre_process do |tree|
      @global_variable_name = "$hook_handler_" + rand(10000000000).to_s
      eval("#{@global_variable_name} = self")

      EvalHook::TreeProcessor.new(self, @global_variable_name).process(tree)
    end
  end
  @partialruby_context
end

#private_method_check(recv, mname) ⇒ Object



317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/evalhook.rb', line 317

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