Class: TaintedLove::Utils::Proxy

Inherits:
Object
  • Object
show all
Defined in:
lib/tainted_love/utils/proxy.rb

Overview

Utility to wrap a an instance function.

Examples:

TaintedLove::Utils::Proxy.new('MyClass', :my_method) do
  def before
    if arguments.first.tainted?
      @should_taint = true
      do_something
    end
  end

  def around
    yield # calls the real method
  end

  def after
    return_value.taint if @should_taint
  end
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(klass = nil, method = nil) { ... } ⇒ Proxy

Creates a new proxy. If klass and ‘method` are provided, it will invoke #apply with those arguments.

Parameters:

  • klass (Class, String) (defaults to: nil)

    The target class

  • method (Symbol) (defaults to: nil)

    The method name to replace

Yields:

  • Evaluated the block in the context of the instance to customize the before, around and after methods



31
32
33
34
35
36
37
# File 'lib/tainted_love/utils/proxy.rb', line 31

def initialize(klass = nil, method = nil, &block)
  instance_eval(&block) unless block.nil?

  if !klass.nil? && !method.nil?
    apply(klass, method)
  end
end

Instance Attribute Details

#argumentsObject

Returns the value of attribute arguments.



24
25
26
# File 'lib/tainted_love/utils/proxy.rb', line 24

def arguments
  @arguments
end

#blockObject

Returns the value of attribute block.



24
25
26
# File 'lib/tainted_love/utils/proxy.rb', line 24

def block
  @block
end

#objectObject

Returns the value of attribute object.



24
25
26
# File 'lib/tainted_love/utils/proxy.rb', line 24

def object
  @object
end

#return_valueObject

Returns the value of attribute return_value.



24
25
26
# File 'lib/tainted_love/utils/proxy.rb', line 24

def return_value
  @return_value
end

Instance Method Details

#afterObject

Invoked after invoking the original method



44
45
# File 'lib/tainted_love/utils/proxy.rb', line 44

def after
end

#apply(klass, method) ⇒ Object

Replaces the method in the given klass.

Parameters:

  • klass (Class, String)

    The target class

  • method (Symbol)

    The method name to replace



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/tainted_love/utils/proxy.rb', line 75

def apply(klass, method)
  if klass.is_a?(String)
    return unless Object.const_defined?(klass)

    klass = Object.const_get(klass)
  end

  proxy = self
  original_method = "_tainted_love_original_#{method}"

  klass.class_eval do
    alias_method original_method, method

    define_method method do |*args, &given_block|
      proxy.handle(self, original_method, *args, &given_block)
    end
  end
end

#around { ... } ⇒ Object

Controls the call to the original function. The default implementation of this method will yield.

Yields:

  • The given block will invoke the original method



50
51
52
# File 'lib/tainted_love/utils/proxy.rb', line 50

def around
  yield
end

#beforeObject

Invoked before invoking the original method



40
41
# File 'lib/tainted_love/utils/proxy.rb', line 40

def before
end

#handle(object, method, *args, &block) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/tainted_love/utils/proxy.rb', line 54

def handle(object, method, *args, &block)
  # thread safety maybe?
  @arguments = args
  @block = block
  @object = object

  before

  around do
    @return_value = object.send(method, *@arguments, &@block)
  end

  after

  @return_value
end