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.



69
70
71
72
# File 'lib/evalhook.rb', line 69

def initialize
  super
  self.base_namespace = Object
end

Instance Attribute Details

#base_namespaceObject

Returns the value of attribute base_namespace.



67
68
69
# File 'lib/evalhook.rb', line 67

def base_namespace
  @base_namespace
end

Instance Method Details

#evalhook(*args) ⇒ Object



304
305
306
# File 'lib/evalhook.rb', line 304

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

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



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

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



219
220
221
# File 'lib/evalhook.rb', line 219

def handle_cdecl(*args)
  nil
end

#handle_colon2(context, name) ⇒ Object



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

def handle_colon2(context,name)
  nil
end

#handle_colon3(*args) ⇒ Object

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



224
225
226
# File 'lib/evalhook.rb', line 224

def handle_colon3(*args)
  nil
end

#handle_const(name) ⇒ Object

Overwrite to handle const read access



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

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



214
215
216
# File 'lib/evalhook.rb', line 214

def handle_gasgn(*args)
  nil
end

#handle_gvar(global_id) ⇒ Object

Overwrite to handle global variable read access



248
249
250
# File 'lib/evalhook.rb', line 248

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



234
235
236
# File 'lib/evalhook.rb', line 234

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)



229
230
231
# File 'lib/evalhook.rb', line 229

def handle_xstr(*args)
  nil
end

#hooked_cdecl(klass, const_id, value) ⇒ Object

:nodoc:



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

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:



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

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:



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

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:



121
122
123
124
125
126
127
128
129
# File 'lib/evalhook.rb', line 121

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:



82
83
84
85
86
87
88
89
# File 'lib/evalhook.rb', line 82

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:



140
141
142
143
144
145
146
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
# File 'lib/evalhook.rb', line 140

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:



177
178
179
180
181
182
183
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
# File 'lib/evalhook.rb', line 177

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:



252
253
254
# File 'lib/evalhook.rb', line 252

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

#internal_eval(b_, original_args) ⇒ Object

used internally

Raises:

  • (ArgumentError)


298
299
300
301
# File 'lib/evalhook.rb', line 298

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


274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/evalhook.rb', line 274

def packet(code)

  tree = nil

  begin
    tree = RubyParser.new.parse code
  rescue
    raise SyntaxError
  end

  context = PartialRuby::PureRubyContext.new

  tree = EvalHook::TreeProcessor.new(self).process(tree)

  emulationcode = context.emul tree

  EvalHook::Packet.new(emulationcode)
end

#private_method_check(recv, mname) ⇒ Object



309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/evalhook.rb', line 309

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