如何在函数调用之前注入和删除php代码

时间:2012-02-13 14:27:45

标签: php regex code-injection

我希望能够在特定功能之前和之后注入一些PHP代码(探查器代码)。 函数和文件将在表单中手动插入,但我希望自动注入和删除。我使用正则表达式来定位所需的函数调用,但我无法找到如何在之前放置启用代码和在其后面的禁用代码。

2 个答案:

答案 0 :(得分:2)

功能 - runkit

您可以使用php runkit简单地重写该功能。假设您想要替换函数foo(),首先需要使用runkit_function_rename()重命名该函数:

runkit_function_rename( 'foo', '_foo');

而不仅仅是重新定义您的功能(通过func_get_args()call_user_func_array()动态处理参数):

function foo() {
  // Pre code
  $result = call_user_func_array( '_foo', func_get_args());
  // Post code
  return $result;
}

完成后,您可以删除临时功能runkit_function_remove()

runkit_function_remove( 'foo');

// And set up old one back
runkit_function_rename( '_foo', 'foo');

如果你真的需要更改你的函数代码(内联)和“预回调”和“回调后”是不够的,我恐怕我的应用程序设计有坏消息。

方法 - 简单包装

当你需要更新方法(不是函数)时,你可以用简单的包装器封装整个对象,利用php magic methods,你应该实现所有这些,但我只会展示{{3 }},__call()__set()__get()

class Wrapper {
// The class that we are about to handle
protected $___data = null;

// Actually the only function that is directly related  to Wrapper class
public function __construct( $data){
    $this->___data = $data;
}

// By default just call real method
// You may add pre and post callbacks for every function
public function __call( $funcName, $args){
    return call_user_func_array( array( $this->___data, $funcName), $args);
}

// Propagate set to deeper level
public function __set( $key, $val){
    $result = ($this->___data->{$key} = $val);
    if( $result == $this->___data){
        return $this;
    }
    return $result;
}

// Propagate get to deeper level
public function __get( $key){
    $result = $this->___data->{$key};
    if( $result == $this->___data){
        return $this;
    }
    return $result;
}

// Handles isset
public function __isset( $key){
    return isset( $this->___data->{$key});
}

}

一旦你有了这个,你可以简单地扩展这个类只是为了对一个方法进行特殊处理(比如类Bar方法foo()):

WrapperBar extends Wrapper {
    public function foo(){
         // Add magick
         return call_user_func_array( array( $this->___data, 'foo'), func_get_args());
    }
}

并将其用作:

 $bar = new Bar();
 $bar = new WrapperBar( $bar);
 $bar->foo( 'One', 'Two', '...');

答案 1 :(得分:2)

  

我希望能够在特定功能之前和之后注入一些PHP代码(探查器代码)。函数和文件将在表单中手动插入,但我希望自动注入和删除。我使用正则表达式来定位所需的函数调用,但我无法找到如何在之前放置启用代码和在其后面的禁用代码。

我想,错误的问题会产生错误的答案。如果要分析特定功能,请使用XDebug之类的分析器,而不是您自己编写的分析器。执行分析的代码注入听起来像是一项糟糕的工作,尽管可以使用runkit,正如 Vyktor 所建议的那样。

如果您确实想运行自己的代码,我想最简单的解决方案就是做这样的事情:

<?php
$profiler = function( $function ) {
   // your profiling code here.
};

$profiler( 'yourfunction' );
yourfunction( );
$profiler( 'yourfunction' );

然后,当您完成对应用程序的分析时,您可以简单地使用$profiler的替代函数来执行任何操作,这意味着它不会具有侵入性。

$profiler = function( $function ) {
    return;
};

但是,这会使分析在您的应用程序中传播。我只是使用现有的工具。