rallhook 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. data/AUTHORS +3 -0
  2. data/CHANGELOG +82 -0
  3. data/README +207 -0
  4. data/Rakefile +49 -0
  5. data/TODO +8 -0
  6. data/examples/hook/example1.rb +19 -0
  7. data/examples/hook/example2.rb +30 -0
  8. data/examples/hook/example3.rb +24 -0
  9. data/examples/hook/example4.rb +18 -0
  10. data/examples/hook/intercept.rb +41 -0
  11. data/examples/hook/intercept2.rb +49 -0
  12. data/examples/hook/redirect.rb +55 -0
  13. data/examples/hook/redirect_inherited.rb +28 -0
  14. data/examples/hook/shadow.rb +44 -0
  15. data/examples/instrospection/main.rb +13 -0
  16. data/examples/instrospection/source1.rb +4 -0
  17. data/examples/instrospection/source2.rb +4 -0
  18. data/ext/rallhook_base/distorm.h +401 -0
  19. data/ext/rallhook_base/extconf.rb +21 -0
  20. data/ext/rallhook_base/hook.c +165 -0
  21. data/ext/rallhook_base/hook.h +30 -0
  22. data/ext/rallhook_base/hook_rb_call.c +88 -0
  23. data/ext/rallhook_base/hook_rb_call.h +33 -0
  24. data/ext/rallhook_base/method_node.c +212 -0
  25. data/ext/rallhook_base/method_node.h +27 -0
  26. data/ext/rallhook_base/node_defs.h +294 -0
  27. data/ext/rallhook_base/rallhook.c +396 -0
  28. data/ext/rallhook_base/rb_call_fake.c +398 -0
  29. data/ext/rallhook_base/rb_call_fake.h +138 -0
  30. data/ext/rallhook_base/restrict_def.c +176 -0
  31. data/ext/rallhook_base/restrict_def.h +37 -0
  32. data/ext/rallhook_base/ruby_redirect.c +122 -0
  33. data/ext/rallhook_base/ruby_redirect.h +33 -0
  34. data/ext/rallhook_base/ruby_symbols.c +43 -0
  35. data/ext/rallhook_base/ruby_symbols.h +28 -0
  36. data/ext/rallhook_base/ruby_version.h +21 -0
  37. data/lib/rallhook/thread_hook.rb +37 -0
  38. data/lib/rallhook.rb +384 -0
  39. data/test/basic_proc.rb +45 -0
  40. data/test/integrity/test_array.rb +42 -0
  41. data/test/integrity/test_binding.rb +26 -0
  42. data/test/integrity/test_block.rb +37 -0
  43. data/test/integrity/test_call.rb +1 -0
  44. data/test/integrity/test_class_methods.rb +1 -0
  45. data/test/integrity/test_exception.rb +1 -0
  46. data/test/integrity/test_super.rb +34 -0
  47. data/test/introspection/test_call.rb +29 -0
  48. data/test/introspection/test_class_method.rb +41 -0
  49. data/test/introspection/test_file.rb +15 -0
  50. metadata +113 -0
@@ -0,0 +1,37 @@
1
+ /*
2
+
3
+ This file is part of the rallhook project, http://github.com/tario
4
+
5
+ Copyright (c) 2009-2010 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ rallhook is free software: you can redistribute it and/or modify
8
+ it under the terms of the gnu general public license as published by
9
+ the free software foundation, either version 3 of the license, or
10
+ (at your option) any later version.
11
+
12
+ rallhook is distributed in the hope that it will be useful,
13
+ but without any warranty; without even the implied warranty of
14
+ merchantability or fitness for a particular purpose. see the
15
+ gnu general public license for more details.
16
+
17
+ you should have received a copy of the gnu general public license
18
+ along with rallhook. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ */
21
+ #ifndef __RESTRICT_DEF_H
22
+ #define __RESTRICT_DEF_H
23
+
24
+ #include "ruby.h"
25
+
26
+ void init_restrict_def();
27
+
28
+ void disable_overwrite(VALUE current_thread);
29
+ void enable_overwrite(VALUE current_thread);
30
+
31
+ void shadow_redirect(VALUE* klass, VALUE* recv, ID* mid);
32
+
33
+ VALUE unshadow(VALUE klass) ;
34
+
35
+ VALUE shadow_or_create(VALUE klass);
36
+
37
+ #endif
@@ -0,0 +1,122 @@
1
+ /*
2
+
3
+ This file is part of the rallhook project, http://github.com/tario/rallhook
4
+
5
+ Copyright (c) 2009-2010 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ rallhook is free software: you can redistribute it and/or modify
8
+ it under the terms of the gnu general public license as published by
9
+ the free software foundation, either version 3 of the license, or
10
+ (at your option) any later version.
11
+
12
+ rallhook is distributed in the hope that it will be useful,
13
+ but without any warranty; without even the implied warranty of
14
+ merchantability or fitness for a particular purpose. see the
15
+ gnu general public license for more details.
16
+
17
+ you should have received a copy of the gnu general public license
18
+ along with rallhook. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ */
21
+ #include "ruby_redirect.h"
22
+ #include "ruby_symbols.h"
23
+ #include "rb_call_fake.h"
24
+ #include "hook_rb_call.h"
25
+ #include "pthread.h"
26
+
27
+ int code_changed = 0;
28
+
29
+ REDIRECTHANDLER current_redirect_handler;
30
+
31
+ void init_redirect();
32
+
33
+ int put_redirect_handler_( REDIRECTHANDLER redirect_handler) {
34
+ current_redirect_handler = redirect_handler;
35
+
36
+ if (!code_changed) {
37
+ // insert inconditional jmp from rb_call to rb_call_copy
38
+
39
+ #ifdef __i386__
40
+ rb_call_copy = (RBCALL)hook_rb_call(rb_call_fake_regs);
41
+ #endif
42
+
43
+ #ifdef __x86_64__
44
+ rb_call_copy = (RBCALL)hook_rb_call(rb_call_fake);
45
+ #endif
46
+ // calibrate protocol of rb_call
47
+ #ifdef __i386__
48
+ is_calibrate = 1;
49
+
50
+ VALUE test_value = LONG2FIX(0);
51
+
52
+ calibrate_recv = test_value;
53
+ calibrate_klass = CLASS_OF(test_value);
54
+ calibrate_mid = rb_intern("to_s");
55
+
56
+ rb_funcall(test_value, calibrate_mid, 0);
57
+
58
+
59
+ #endif
60
+
61
+ if (!rb_call_copy) {
62
+ rb_raise( rb_eFatal, "libruby incompatible with rallhook");
63
+ }
64
+
65
+ #ifdef RUBY1_9
66
+ #ifdef __i386__
67
+
68
+ rb_eval_string("def Object.___calibrate_x(x); end");
69
+
70
+ calibrate_recv = rb_cObject;
71
+ calibrate_klass = CLASS_OF(rb_cObject);
72
+ calibrate_mid = rb_intern("___calibrate_x");
73
+
74
+ vm_call_method_copy = (VMCALLMETHOD)hook_vm_call_method(vm_call_method_fake_regs);
75
+ vm_is_calibrate = 1;
76
+
77
+ char code[256];
78
+ snprintf(code, sizeof(code), "Object.___calibrate_x(%i)", test_value);
79
+ rb_eval_string(code);
80
+
81
+ #endif
82
+ #ifdef __x86_64__
83
+ vm_call_method_copy = (VMCALLMETHOD)hook_vm_call_method(vm_call_method_fake);
84
+ #endif
85
+
86
+ if (!vm_call_method_copy) {
87
+ rb_raise( rb_eFatal, "libruby incompatible with rallhook");
88
+ }
89
+ #endif
90
+
91
+ code_changed = 1;
92
+ }
93
+
94
+ return 0;
95
+ }
96
+
97
+
98
+ pthread_mutex_t put_redirect_handler_mutex;
99
+
100
+ int put_redirect_handler( REDIRECTHANDLER redirect_handler) {
101
+
102
+ pthread_mutex_lock(&put_redirect_handler_mutex);
103
+ put_redirect_handler_(redirect_handler);
104
+ pthread_mutex_unlock(&put_redirect_handler_mutex);
105
+ }
106
+
107
+
108
+ void init_redirect() {
109
+
110
+ pthread_mutexattr_t attr;
111
+
112
+ pthread_mutexattr_init(&attr);
113
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
114
+
115
+ pthread_mutex_init( &put_redirect_handler_mutex, &attr);
116
+
117
+ init_hook_rb_call();
118
+ rb_call_fake_init();
119
+ }
120
+
121
+
122
+
@@ -0,0 +1,33 @@
1
+ /*
2
+
3
+ This file is part of the rallhook project, http://github.com/tario/rallhook
4
+
5
+ Copyright (c) 2009-2010 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ rallhook is free software: you can redistribute it and/or modify
8
+ it under the terms of the gnu general public license as published by
9
+ the free software foundation, either version 3 of the license, or
10
+ (at your option) any later version.
11
+
12
+ rallhook is distributed in the hope that it will be useful,
13
+ but without any warranty; without even the implied warranty of
14
+ merchantability or fitness for a particular purpose. see the
15
+ gnu general public license for more details.
16
+
17
+ you should have received a copy of the gnu general public license
18
+ along with rallhook. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ */
21
+ #ifndef __RUBY_REDIRECT_H
22
+ #define __RUBY_REDIRECT_H
23
+
24
+ // Acts as facade of the division between the ruby interpreter modification
25
+
26
+ #include <ruby.h>
27
+
28
+ typedef void (*REDIRECTHANDLER) ( VALUE* klass, VALUE* recv, ID* mid );
29
+ int put_redirect_handler( REDIRECTHANDLER redirect_handler);
30
+
31
+ void init_redirect();
32
+
33
+ #endif
@@ -0,0 +1,43 @@
1
+ /*
2
+
3
+ This file is part of the rallhook project, http://github.com/tario/rallhook
4
+
5
+ Copyright (c) 2009-2010 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ rallhook is free software: you can redistribute it and/or modify
8
+ it under the terms of the gnu general public license as published by
9
+ the free software foundation, either version 3 of the license, or
10
+ (at your option) any later version.
11
+
12
+ rallhook is distributed in the hope that it will be useful,
13
+ but without any warranty; without even the implied warranty of
14
+ merchantability or fitness for a particular purpose. see the
15
+ gnu general public license for more details.
16
+
17
+ you should have received a copy of the gnu general public license
18
+ along with rallhook. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ */
21
+
22
+ #include "ruby_symbols.h"
23
+ #include "ruby.h"
24
+
25
+ void* ruby_resolv(unsigned char* p_base, const char* symbol_name) {
26
+ VALUE rb_mCymbol = rb_eval_string("Cymbol");
27
+ VALUE rb_str_symbol_name = rb_str_new2(symbol_name);
28
+
29
+ VALUE rb_offset = rb_funcall(rb_mCymbol,rb_intern("resolv"), 1, rb_str_symbol_name);
30
+
31
+ unsigned long long offset = FIX2LONG(rb_offset);
32
+
33
+ return (p_base + offset);
34
+ }
35
+
36
+
37
+ const char* current_libruby() {
38
+ VALUE rb_mCymbol = rb_eval_string("Cymbol");
39
+ VALUE rb_strSharedName = rb_funcall(rb_mCymbol,rb_intern("ruby_shared_name"), 0);
40
+
41
+ return rb_string_value_ptr(&rb_strSharedName);
42
+ }
43
+
@@ -0,0 +1,28 @@
1
+ /*
2
+
3
+ This file is part of the rallhook project, http://github.com/tario/rallhook
4
+
5
+ Copyright (c) 2009-2010 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ rallhook is free software: you can redistribute it and/or modify
8
+ it under the terms of the gnu general public license as published by
9
+ the free software foundation, either version 3 of the license, or
10
+ (at your option) any later version.
11
+
12
+ rallhook is distributed in the hope that it will be useful,
13
+ but without any warranty; without even the implied warranty of
14
+ merchantability or fitness for a particular purpose. see the
15
+ gnu general public license for more details.
16
+
17
+ you should have received a copy of the gnu general public license
18
+ along with rallhook. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ */
21
+
22
+ #ifndef __RUBY_SYMBOLS_H
23
+ #define __RUBY_SYMBOLS_H
24
+
25
+ void* ruby_resolv(unsigned char* p_base, const char* symbol_name);
26
+ const char* current_libruby();
27
+
28
+ #endif
@@ -0,0 +1,21 @@
1
+ /*
2
+
3
+ This file is part of the rallhook project, http://github.com/tario/rallhook
4
+
5
+ Copyright (c) 2009-2010 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ rallhook is free software: you can redistribute it and/or modify
8
+ it under the terms of the gnu general public license as published by
9
+ the free software foundation, either version 3 of the license, or
10
+ (at your option) any later version.
11
+
12
+ rallhook is distributed in the hope that it will be useful,
13
+ but without any warranty; without even the implied warranty of
14
+ merchantability or fitness for a particular purpose. see the
15
+ gnu general public license for more details.
16
+
17
+ you should have received a copy of the gnu general public license
18
+ along with rallhook. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ */
21
+
@@ -0,0 +1,37 @@
1
+ =begin
2
+
3
+ This file is part of the rallhook project, http://github.com/tario/
4
+
5
+ Copyright (c) 2009-2010 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ rallhook is free software: you can redistribute it and/or modify
8
+ it under the terms of the gnu general public license as published by
9
+ the free software foundation, either version 3 of the license, or
10
+ (at your option) any later version.
11
+
12
+ rallhook is distributed in the hope that it will be useful,
13
+ but without any warranty; without even the implied warranty of
14
+ merchantability or fitness for a particular purpose. see the
15
+ gnu general public license for more details.
16
+
17
+ you should have received a copy of the gnu general public license
18
+ along with rallhook. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ =end
21
+ class Thread
22
+
23
+ class << self
24
+ alias :original_new :new
25
+
26
+ private :original_new
27
+
28
+ def new
29
+ parent = current
30
+ original_new do
31
+ parent.acquire_attributes do
32
+ yield
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
data/lib/rallhook.rb ADDED
@@ -0,0 +1,384 @@
1
+ =begin
2
+
3
+ This file is part of the rallhook project, http://github.com/tario/
4
+
5
+ Copyright (c) 2009-2010 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ rallhook is free software: you can redistribute it and/or modify
8
+ it under the terms of the gnu general public license as published by
9
+ the free software foundation, either version 3 of the license, or
10
+ (at your option) any later version.
11
+
12
+ rallhook is distributed in the hope that it will be useful,
13
+ but without any warranty; without even the implied warranty of
14
+ merchantability or fitness for a particular purpose. see the
15
+ gnu general public license for more details.
16
+
17
+ you should have received a copy of the gnu general public license
18
+ along with rallhook. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ =end
21
+ require "rubygems"
22
+ require "rallhook_base"
23
+ require "rallhook/thread_hook"
24
+
25
+ module RallHook
26
+ #
27
+ #Internal class used for return method redirection messages
28
+ #Example:
29
+ # ...
30
+ # class X
31
+ # def foo
32
+ # end
33
+ # end
34
+ # def handle_method
35
+ # return RallHook::Redirect.new(X, X.new, :foo)
36
+ # end
37
+ # ...
38
+ #
39
+ #Note: Use x.redirect(:foo) instead (see Object#redirect )
40
+ #
41
+ class Redirect
42
+ include MethodRedirect
43
+
44
+ attr_reader :recv
45
+
46
+ def initialize(klass, recv, m, unhook = nil)
47
+ @klass = klass
48
+ @recv = recv
49
+ @method = m
50
+ @unhook = unhook
51
+ end
52
+ end
53
+ #
54
+ #Internal class used by RallHook::Helper#return_value
55
+ #
56
+ class ReturnHolder
57
+ def initialize(v)
58
+ @value = v
59
+ end
60
+ def value(*x)
61
+ @value
62
+ end
63
+ end
64
+
65
+ #
66
+ #This module brings together classes and methods to facilitate the handling
67
+ #
68
+ module Helper
69
+
70
+ #Equivalent to:
71
+ # recv.redirect(m, klass)
72
+ def redirect_call(klass, recv, m)
73
+ ::RallHook::Redirect.new(klass,recv,m)
74
+ end
75
+
76
+ #Return a value as return value of the method being handled
77
+ #Example:
78
+ #
79
+ # include RallHook::Helper
80
+ # def handle_method
81
+ # return_value(4) # all methods called returns 4
82
+ # end
83
+ #
84
+ def return_value(v)
85
+ recv = ReturnHolder.new(v)
86
+ klass = recv.class
87
+ m = :value
88
+ redirect_call(klass, recv, m)
89
+ end
90
+
91
+ #
92
+ #This class acts as base to define classes that acts as receptors and wrappers of
93
+ #redirected methods. Allows interception of methods with its parameters and controlled recall
94
+ #in a hooking logic
95
+ #
96
+ #Example 1: basic modifications of arguments
97
+ #
98
+ # class MethodHandler
99
+ # include RallHook::Helper
100
+ #
101
+ # class FooMethodWrapper < RallHook::MethodWrapper
102
+ # def call(foo_argument)
103
+ # original_call(foo_argument + 5) # add 5 in all calls to foo
104
+ # end
105
+ # end
106
+ #
107
+ # def handle_method (klass,recv,m,method_id)
108
+ # if m == :foo
109
+ # FooMethodWrapper.redirect_handler(klass,recv,m,method_id)
110
+ # else
111
+ # nil
112
+ # end
113
+ # end
114
+ # end
115
+ #
116
+ # ... hooking using MethodHandler ( see Hook#hook, README and examples)
117
+ #
118
+ #
119
+ #Example 2: generic recall of methods
120
+ #
121
+ # class MethodHandler
122
+ # include RallHook::Helper
123
+ #
124
+ # class GenericMethodWrapper < RallHook::MethodWrapper
125
+ # def call(*x)
126
+ # # call with reyield if block_given
127
+ # if block_given?
128
+ # original_call(*x) do |*a|
129
+ # yield(*a)
130
+ # end
131
+ # else
132
+ # original_call(*x)
133
+ # end
134
+ # end
135
+ # end
136
+ #
137
+ # def handle_method (klass,recv,m,method_id)
138
+ # return GenericMethodWrapper.redirect_handler(klass,recv,m,method_id)
139
+ # end
140
+ # end
141
+ #
142
+ # ... hooking using MethodHandler ( see Hook#hook, README and examples)
143
+ #
144
+ #
145
+ class MethodWrapper
146
+
147
+ attr_accessor :klass, :recv, :method_name, :method_id
148
+
149
+ #Reactivate the hook status to intercept methods
150
+ #Allow to pass a block to enable the hook status only in that block
151
+ #
152
+ #Example:
153
+ # class MethodHandler
154
+ # include RallHook::Helper
155
+ #
156
+ # class FooMethodWrapper < RallHook::MethodWrapper
157
+ # def call(foo_argument)
158
+ # original_call(foo_argument + 5) # add 5 in all calls to foo
159
+ # rehook do # the print "hello world hooked" are intercepted too
160
+ # print "hello world hooked\n"
161
+ # end
162
+ # end
163
+ # end
164
+ #
165
+ # ... definition of handle_method that use FooMethodWrapper as redirect, etc...
166
+ #
167
+ #Note: is not necesary to use rehook to hook the nested calls in original_call
168
+ #MethodWrapper#original_call does that internally
169
+ #
170
+ def rehook
171
+ if block_given?
172
+ ::RallHook::Hook.rehook do
173
+ yield
174
+ end
175
+ else
176
+ ::RallHook::Hook.rehook
177
+ end
178
+ end
179
+
180
+ #
181
+ #Same as Hook#from
182
+ #
183
+ def from(a)
184
+ ::RallHook::Hook.from(a)
185
+ self
186
+ end
187
+
188
+ #
189
+ #Recall the original method(specified in initialization parameters)
190
+ #
191
+ def original_call(*args)
192
+ mname = self.method_name
193
+ mklass = self.klass
194
+ mid = self.method_id
195
+ recv_ = self.recv
196
+
197
+ # original calls over the shadow of the class, not the original one
198
+ m = recv_.specific_method(mklass.shadow,mname)
199
+
200
+ if block_given?
201
+ from(3).rehook do
202
+ m.call(*args) do |*blockargs|
203
+ yield(*blockargs)
204
+ end
205
+ end
206
+ else
207
+ from(3).rehook do
208
+ m.call(*args)
209
+ end
210
+ end
211
+ end
212
+
213
+ #
214
+ #Target of redirection, should be implemented to intercept the call
215
+ #
216
+ def call(*args)
217
+ end
218
+
219
+ def call_with_rehook(*args)
220
+ if block_given?
221
+ call(*args) do |*x|
222
+ yield(*x)
223
+ end
224
+ else
225
+ call(*args)
226
+ end
227
+ ensure
228
+ rehook
229
+ end
230
+
231
+ #
232
+ #Makes a redirect_handler to wrap a method call with this MethodWrapper. Example:
233
+ #
234
+ # FooMethodWrapper.redirect_handler(klass,recv,m,method_id)
235
+ #
236
+ def self.redirect_handler(klass,recv,method_name, method_id)
237
+ if method_name
238
+
239
+ mw = self.new
240
+ mw.klass = klass
241
+ mw.recv = recv
242
+ mw.method_name = method_name
243
+ mw.method_id = method_id
244
+ if block_given?
245
+ yield(mw)
246
+ end
247
+ mw.redirect_with_unhook(:call_with_rehook)
248
+ else
249
+ nil
250
+ end
251
+ end
252
+
253
+ end
254
+ end
255
+
256
+
257
+
258
+ class HookHandler
259
+
260
+ #default method_handler of a Hook does nothing with any method call
261
+ def handle_method
262
+ nil
263
+ end
264
+
265
+ #enable the hook. Example
266
+ #
267
+ # class MethodHandler < Hook
268
+ # def handle_method
269
+ # nil # do nothing
270
+ # end
271
+ # end
272
+ #
273
+ # MethodHandler.hook do
274
+ # print "hello world\n"
275
+ # end
276
+ #
277
+
278
+ def hook
279
+ if block_given?
280
+ ::RallHook::Hook.hook self do
281
+ yield
282
+ end
283
+ else
284
+ ::RallHook::Hook.hook self
285
+ end
286
+ end
287
+
288
+ #Instance handler and activate the hook
289
+ #Example:
290
+ #
291
+ # class MethodHandler < Hook
292
+ # def handle_method
293
+ # nil # do nothing
294
+ # end
295
+ # end
296
+ #
297
+ # MethodHandler.hook do
298
+ # print "hello world\n"
299
+ # end
300
+
301
+ def self.hook
302
+ if block_given?
303
+ self.new.hook do
304
+ yield
305
+ end
306
+ else
307
+ self.new.hook
308
+ end
309
+ end
310
+ end
311
+
312
+
313
+
314
+ end
315
+
316
+ # To facilitate the use of hooking/redirection features,
317
+ # rallhook defines some methods in the Object class
318
+ #
319
+
320
+ class Object
321
+
322
+
323
+ # Same as redirect, but disable the hook/interception of methods (dont call handle_redirect) before
324
+ # make the call, the hook status may be restored with Hook#rehook
325
+ # Anyway, it is desirable to use MethodWrapper instead to "wrap" method calls
326
+ #
327
+ # see RallHook::Helper::MethodWrapper
328
+ #
329
+ def redirect_with_unhook(method_name, klass = nil)
330
+ if klass
331
+ ::RallHook::Redirect.new(klass,self,method_name,true)
332
+ else
333
+ ::RallHook::Redirect.new(self.class,self,method_name,true)
334
+ end
335
+
336
+ end
337
+
338
+ # Generates a redirect message to return it in handle_method to cause the redirection of
339
+ # the method that is beign processed with the object as receiver, the method_name the new target
340
+ # and the class as second parameter if specified
341
+ #
342
+ # Example:
343
+ # class X
344
+ # def foo(*args)
345
+ # end
346
+ # end
347
+ #
348
+ # class MethodHandler
349
+ # @@x = x.new
350
+ # def handle_method(klass, recv, m , method_id)
351
+ # if m == :bar then
352
+ # # redirect bar calls to foo in x
353
+ # return x.redirect(:foo)
354
+ # end
355
+ # nil # do nothing
356
+ # end
357
+ # end
358
+ #
359
+ # # hook using MethodHandler, etc... (see README and examples)
360
+ #
361
+ #
362
+ def redirect(method_name, klass = nil)
363
+ if klass
364
+ ::RallHook::Redirect.new(klass,self,method_name)
365
+ else
366
+ ::RallHook::Redirect.new(self.class,self,method_name)
367
+ end
368
+ end
369
+
370
+ def specific_method(arg1, arg2=nil)
371
+ if arg2
372
+ method_name = arg2
373
+ klass = arg1
374
+
375
+ if instance_of? Class
376
+ method(method_name)
377
+ else
378
+ klass.shadow.instance_method(method_name).unchecked_bind(self)
379
+ end
380
+ else
381
+ method(arg1)
382
+ end
383
+ end
384
+ end