Issues (1)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Hook.php (1 issue)

Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace SciActive;
3
4
/**
5
 * HookPHP
6
 *
7
 * An object method hooking system.
8
 *
9
 * Hooks are used to call a callback when a method is called and optionally
10
 * manipulate the arguments/function call/return value.
11
 *
12
 * @version 2.1.0
13
 * @license https://www.gnu.org/licenses/lgpl.html
14
 * @author Hunter Perrin <[email protected]>
15
 * @copyright SciActive.com
16
 * @link http://requirephp.org
17
 */
18
19
if (!class_exists('\SciActive\HookOverride')) {
20
  include_once(__DIR__.DIRECTORY_SEPARATOR.'HookOverride.php');
21
}
22
23
class Hook {
24
  /**
25
   * An array of the callbacks for each hook.
26
   * @var array
27
   */
28
  protected static $hooks = array();
29
  /**
30
   * A copy of the HookOverride_extend file.
31
   * @var string
32
   */
33
  private static $hookFile;
34
35
  /**
36
   * Add a callback.
37
   *
38
   * A callback is called either before a method runs or after. The callback
39
   * is passed an array of arguments or return value which it can freely
40
   * manipulate. If the callback runs before the method and sets the arguments
41
   * array to false (or causes an error), the method will not be run.
42
   * Callbacks before a method are passed the arguments given when the method
43
   * was called, while callbacks after a method are passed the return value
44
   * (in an array) of that method.
45
   *
46
   * The callback can receive up to 5 arguments, in this order:
47
   *
48
   * - &$arguments - An array of either arguments or a return value.
49
   * - $name - The name of the hook.
50
   * - &$object - The object on which the hook caught a method call.
51
   * - &$function - A callback for the method call which was caught. Altering
52
   *   this will cause a different function/method to run.
53
   * - &$data - An array in which callbacks can store data to communicate with
54
   *   later callbacks.
55
   *
56
   * A hook is the name of whatever method it should catch. A hook can also
57
   * have an arbitrary name, but be wary that it may already exist and it may
58
   * result in your callback being falsely called. In order to reduce the
59
   * chance of this, always use a plus sign (+) and your component's name to
60
   * begin arbitrary hook names. E.g. "+com_games_player_bonus".
61
   *
62
   * If the hook is called explicitly, callbacks defined to run before the
63
   * hook will run immediately followed by callbacks defined to run after.
64
   *
65
   * A negative $order value means the callback will be run before the method,
66
   * while a positive value means it will be run after. The smaller the order
67
   * number, the sooner the callback will be run. You can think of the order
68
   * value as a timeline of callbacks, zero (0) being the actual method being
69
   * hooked.
70
   *
71
   * Additional identical callbacks can be added in order to have a callback
72
   * called multiple times for one hook.
73
   *
74
   * The hook "all" is a pseudo hook which will run regardless of what was
75
   * actually caught. Callbacks attached to the "all" hook will run before
76
   * callbacks attached to the actual hook.
77
   *
78
   * Note: Be careful to avoid recursive callbacks, as they may result in an
79
   * infinite loop. All methods under $_ are automatically hooked.
80
   *
81
   * @param string $hook The name of the hook to catch.
82
   * @param int $order The order can be negative, which will run before the method, or positive, which will run after the method. It cannot be zero.
83
   * @param callback The callback.
84
   * @return array An array containing the IDs of the new callback and all matching callbacks.
85
   * @uses \SciActive\Hook::sortCallbacks() To resort the callback array in the correct order.
86
   */
87
  public static function addCallback($hook, $order, $function) {
88
    $callback = array($order, $function);
89
    if (!isset(Hook::$hooks[$hook])) {
90
      Hook::$hooks[$hook] = array();
91
    }
92
    Hook::$hooks[$hook][] = $callback;
93
    uasort(Hook::$hooks[$hook], '\\SciActive\\Hook::sortCallbacks');
94
    return array_keys(Hook::$hooks[$hook], $callback);
95
  }
96
97
  /**
98
   * Delete a callback by its ID.
99
   *
100
   * @param string $hook The name of the callback's hook.
101
   * @param int $id The ID of the callback.
102
   * @return int 1 if the callback was deleted, 2 if it didn't exist.
103
   */
104
  public static function delCallbackByID($hook, $id) {
105
    if (!isset(Hook::$hooks[$hook][$id])) {
106
      return 2;
107
    }
108
    unset(Hook::$hooks[$hook][$id]);
109
    return 1;
110
  }
111
112
  /**
113
   * Get the array of callbacks.
114
   *
115
   * Callbacks are stored in arrays inside this array. The keys of this array
116
   * are the name of the hook whose callbacks are contained in its value as an
117
   * array. Each array contains the values $order, $function, in that order.
118
   *
119
   * @return array An array of callbacks.
120
   */
121
  public static function getCallbacks() {
122
    return Hook::$hooks;
123
  }
124
125
  /**
126
   * Hook an object.
127
   *
128
   * This hooks all (public) methods defined in the given object.
129
   *
130
   * @param object &$object The object to hook.
131
   * @param string $prefix The prefix used to call the object's methods. Usually something like "$object->".
132
   * @param bool $recursive Whether to hook objects recursively.
133
   * @return bool True on success, false on failure.
134
   */
135
  public static function hookObject(&$object, $prefix = '', $recursive = true) {
136
    if ((object) $object === $object) {
137
      $isString = false;
138
    } else {
139
      $isString = true;
140
    }
141
142
    // Make sure we don't take over the hook object, or we'll end up
143
    // recursively calling ourself. Some system classes shouldn't be hooked.
144
    $className = str_replace('\\', '_', $isString ? $object : get_class($object));
145
    global $_;
146
    if (isset($_) && in_array($className, array('\SciActive\Hook', 'depend', 'config', 'info'))) {
147
      return false;
148
    }
149
150
    if ($recursive && !$isString) {
151
      foreach ($object as $curName => &$curProperty) {
152
        if ((object) $curProperty === $curProperty) {
153
          Hook::hookObject($curProperty, $prefix.$curName.'->');
154
        }
155
      }
156
    }
157
158
    if (!class_exists("\SciActive\HookOverride_$className")) {
159
      if ($isString) {
160
        $reflection = new \ReflectionClass($object);
161
      } else {
162
        $reflection = new \ReflectionObject($object);
163
      }
164
      $methods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC);
165
166
      $code = '';
167
      foreach ($methods as &$curMethod) {
168
        $fname = $curMethod->getName();
169
        if (in_array($fname, array('__construct', '__destruct', '__get', '__set', '__isset', '__unset', '__toString', '__invoke', '__set_state', '__clone', '__sleep', 'jsonSerialize'))) {
170
          continue;
171
        }
172
173
        //$fprefix = $curMethod->isFinal() ? 'final ' : '';
174
        $fprefix = $curMethod->isStatic() ? 'static ' : '';
175
        $params = $curMethod->getParameters();
176
        $paramArray = $paramNameArray = array();
177
        foreach ($params as &$curParam) {
178
          $paramName = $curParam->getName();
179
          $paramPrefix = $curParam->isVariadic() ? '...' : '';
180
          $paramPrefix .= $curParam->isPassedByReference() ? '&' : '';
181
          if ($curParam->isDefaultValueAvailable()) {
182
            $paramSuffix = ' = '.var_export($curParam->getDefaultValue(), true);
183
          } else {
184
            $paramSuffix = '';
185
          }
186
          $paramArray[] = "{$paramPrefix}\${$paramName}{$paramSuffix}";
187
          $paramNameArray[] = "{$paramPrefix}\${$paramName}";
188
        }
189
        unset($curParam);
190
        $code .= $fprefix."function $fname(".implode(', ', $paramArray).") {\n"
191
        .(defined('HHVM_VERSION') ?
192
          (
193
            // There is bad behavior in HHVM where debug_backtrace
194
            // won't return arguments, but calling func_get_args
195
            // somewhere in the function changes that behavior to be
196
            // consistent with official PHP. However, it also
197
            // returns arguments by value, instead of by reference.
198
            // So, we must use a more direct method.
199
            "  \$_HOOK_arguments = array();\n"
200
            .(count($paramNameArray) > 0 ?
201
              "  \$_HOOK_arguments[] = ".implode('; $_HOOK_arguments[] = ', $paramNameArray).";\n" :
202
              ''
203
            )
204
            ."  \$_HOOK_real_arg_count = func_num_args();\n"
205
            ."  \$_HOOK_arg_count = count(\$_HOOK_arguments);\n"
206
            ."  if (\$_HOOK_real_arg_count > \$_HOOK_arg_count) {\n"
207
            ."    for (\$i = \$_HOOK_arg_count; \$i < \$_HOOK_real_arg_count; \$i++)\n"
208
            ."      \$_HOOK_arguments[] = func_get_arg(\$i);\n"
209
            ."  }\n"
210
          ) : (
211
            // We must use a debug_backtrace, because that's the
212
            // best way to get all the passed arguments, by
213
            // reference. 5.4 and up lets us limit it to 1 frame.
214
            (version_compare(PHP_VERSION, '5.4.0') >= 0 ?
215
              "  \$_HOOK_arguments = debug_backtrace(false, 1);\n" :
216
              "  \$_HOOK_arguments = debug_backtrace(false);\n"
217
            )
218
            ."  \$_HOOK_arguments = \$_HOOK_arguments[0]['args'];\n"
219
          )
220
        )
221
        ."  \$_HOOK_function = array(\$this->_hookObject, '$fname');\n"
222
        ."  \$_HOOK_data = array();\n"
223
        ."  \\SciActive\\Hook::runCallbacks(\$this->_hookPrefix.'$fname', \$_HOOK_arguments, 'before', \$this->_hookObject, \$_HOOK_function, \$_HOOK_data);\n"
224
        ."  if (\$_HOOK_arguments !== false) {\n"
225
        ."    \$_HOOK_return = call_user_func_array(\$_HOOK_function, \$_HOOK_arguments);\n"
226
        ."    if ((object) \$_HOOK_return === \$_HOOK_return && get_class(\$_HOOK_return) === '$className')\n"
227
        ."      \\SciActive\\Hook::hookObject(\$_HOOK_return, '$prefix', false);\n"
228
        ."    \$_HOOK_return = array(\$_HOOK_return);\n"
229
        ."    \\SciActive\\Hook::runCallbacks(\$this->_hookPrefix.'$fname', \$_HOOK_return, 'after', \$this->_hookObject, \$_HOOK_function, \$_HOOK_data);\n"
230
        ."    if ((array) \$_HOOK_return === \$_HOOK_return)\n"
231
        ."      return \$_HOOK_return[0];\n"
232
        ."  }\n"
233
        ."}\n\n";
234
      }
235
      unset($curMethod);
236
      // Build a HookOverride class.
237
      $include = str_replace(array('_NAMEHERE_', '//#CODEHERE#', '<?php', '?>'), array($className, $code, '', ''), Hook::$hookFile);
238
      eval($include);
239
    }
240
241
    eval('$object = new \SciActive\HookOverride_'.$className.' ($object, $prefix);');
242
    return true;
243
  }
244
245
  /**
246
   * Run the callbacks for a given hook.
247
   *
248
   * Each callback is run and passed the array of arguments, and the name of
249
   * the given hook. If any callback changes $arguments to FALSE, the
250
   * following callbacks will not be called, and FALSE will be returned.
251
   *
252
   * @param string $name The name of the hook.
253
   * @param array &$arguments An array of arguments to be passed to the callbacks.
254
   * @param string $type The type of callbacks to run. 'before', 'after', or 'all'.
255
   * @param mixed &$object The object on which the hook was called.
256
   * @param callback &$function The function which is called at "0". You can change this in the "before" callbacks to effectively takeover a function.
257
   * @param array &$data A data array for callback communication.
258
   */
259
  public static function runCallbacks($name, &$arguments = array(), $type = 'all', &$object = null, &$function = null, &$data = array()) {
260 View Code Duplication
    if (isset(Hook::$hooks['all'])) {
261
      foreach (Hook::$hooks['all'] as $curCallback) {
262
        if (($type == 'all' && $curCallback[0] != 0) || ($type == 'before' && $curCallback[0] < 0) || ($type == 'after' && $curCallback[0] > 0)) {
263
          call_user_func_array($curCallback[1], array(&$arguments, $name, &$object, &$function, &$data));
264
          if ($arguments === false) {
265
            return;
266
          }
267
        }
268
      }
269
    }
270 View Code Duplication
    if (isset(Hook::$hooks[$name])) {
271
      foreach (Hook::$hooks[$name] as $curCallback) {
272
        if (($type == 'all' && $curCallback[0] != 0) || ($type == 'before' && $curCallback[0] < 0) || ($type == 'after' && $curCallback[0] > 0)) {
273
          call_user_func_array($curCallback[1], array(&$arguments, $name, &$object, &$function, &$data));
274
          if ($arguments === false) {
275
            return;
276
          }
277
        }
278
      }
279
    }
280
  }
281
282
  /**
283
   * Sort function for callback sorting.
284
   *
285
   * This assures that callbacks are executed in the correct order. Callback
286
   * IDs are preserved as long as uasort() is used.
287
   *
288
   * @param array $a The first callback in the comparison.
289
   * @param array $b The second callback in the comparison.
290
   * @return int 0 for equal, -1 for less than, 1 for greater than.
291
   * @access private
292
   */
293
  private static function sortCallbacks($a, $b) {
0 ignored issues
show
This method is not used, and could be removed.
Loading history...
294
    if ($a[0] == $b[0]) {
295
      return 0;
296
    }
297
    return ($a[0] < $b[0]) ? -1 : 1;
298
  }
299
300
  public static function getHookFile() {
301
    Hook::$hookFile = file_get_contents(__DIR__.DIRECTORY_SEPARATOR.'HookOverride_extend.php');
302
  }
303
}
304
305
Hook::getHookFile();
306