AGI_Others::phpagi_error_handler()   F
last analyzed

Complexity

Conditions 20
Paths 242

Size

Total Lines 75
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 20
eloc 51
nc 242
nop 5
dl 0
loc 75
rs 2.8083
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Inok\phpagi;
4
5
class AGI_Others
6
{
7
  const AST_CONFIG_DIR = '/etc/asterisk/';
8
  const AST_SPOOL_DIR = '/var/spool/asterisk/';
9
  const AST_TMP_DIR = self::AST_SPOOL_DIR . '/tmp/';
10
  const DEFAULT_PHPAGI_CONFIG = self::AST_CONFIG_DIR . '/phpagi.conf';
11
12
  const AST_DIGIT_ANY = '0123456789#*';
13
14
  const AGIRES_OK = 200;
15
16
  const AST_STATE_DOWN = 0;
17
  const AST_STATE_RESERVED = 1;
18
  const AST_STATE_OFFHOOK = 2;
19
  const AST_STATE_DIALING = 3;
20
  const AST_STATE_RING = 4;
21
  const AST_STATE_RINGING = 5;
22
  const AST_STATE_UP = 6;
23
  const AST_STATE_BUSY = 7;
24
  const AST_STATE_DIALING_OFFHOOK = 8;
25
  const AST_STATE_PRERING = 9;
26
27
  const AUDIO_FILENO = 3; // STDERR_FILENO + 1
28
29
  public static $phpagi_error_handler_email = null;
30
31
  /**
32
   * error handler for phpagi.
33
   *
34
   * @param integer $level PHP error level
35
   * @param string $message error message
36
   * @param string $file path to file
37
   * @param integer $line line number of error
38
   * @param array $context variables in the current scope
39
   */
40
  public static function phpagi_error_handler(int $level, string $message, string $file, int $line, array $context) {
41
    if (ini_get('error_reporting') == 0) {
42
      return; // this happens with an @
43
    }
44
45
    @syslog(LOG_WARNING, $file . '[' . $line . ']: ' . $message);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for syslog(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

45
    /** @scrutinizer ignore-unhandled */ @syslog(LOG_WARNING, $file . '[' . $line . ']: ' . $message);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
46
47
    if (function_exists('mail') && !is_null(self::$phpagi_error_handler_email)) { // generate email debugging information
48
      // decode error level
49
      switch ($level) {
50
        case E_WARNING:
51
        case E_USER_WARNING:
52
          $level = "Warning";
53
          break;
54
        case E_NOTICE:
55
        case E_USER_NOTICE:
56
          $level = "Notice";
57
          break;
58
        case E_USER_ERROR:
59
          $level = "Error";
60
          break;
61
      }
62
63
      // build message
64
      $basefile = basename($file);
65
      $subject = "$basefile/$line/$level: $message";
66
      $message = "$level: $message in $file on line $line\n\n";
67
68
      // figure out who we are
69
      if (function_exists('socket_create')) {
70
        $addr = null;
71
        $port = 80;
72
        $socket = @socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
73
        @socket_connect($socket, '64.0.0.0', $port);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for socket_connect(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

73
        /** @scrutinizer ignore-unhandled */ @socket_connect($socket, '64.0.0.0', $port);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
Bug introduced by
It seems like $socket can also be of type false; however, parameter $socket of socket_connect() does only seem to accept Socket|resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

73
        @socket_connect(/** @scrutinizer ignore-type */ $socket, '64.0.0.0', $port);
Loading history...
74
        @socket_getsockname($socket, $addr, $port);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for socket_getsockname(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

74
        /** @scrutinizer ignore-unhandled */ @socket_getsockname($socket, $addr, $port);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
Bug introduced by
It seems like $socket can also be of type false; however, parameter $socket of socket_getsockname() does only seem to accept Socket|resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

74
        @socket_getsockname(/** @scrutinizer ignore-type */ $socket, $addr, $port);
Loading history...
75
        @socket_close($socket);
0 ignored issues
show
Bug introduced by
Are you sure the usage of socket_close($socket) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Security Best Practice introduced by
It seems like you do not handle an error condition for socket_close(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

75
        /** @scrutinizer ignore-unhandled */ @socket_close($socket);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
Bug introduced by
It seems like $socket can also be of type false; however, parameter $socket of socket_close() does only seem to accept Socket|resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

75
        @socket_close(/** @scrutinizer ignore-type */ $socket);
Loading history...
76
        $message .= "\n\nIP Address: $addr\n";
77
      }
78
79
      // include variables
80
      $message .= "\n\nContext:\n" . print_r($context, true);
0 ignored issues
show
Bug introduced by
Are you sure print_r($context, true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

80
      $message .= "\n\nContext:\n" . /** @scrutinizer ignore-type */ print_r($context, true);
Loading history...
81
      $message .= "\n\nGLOBALS:\n" . print_r($GLOBALS, true);
0 ignored issues
show
Bug introduced by
Are you sure print_r($GLOBALS, true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

81
      $message .= "\n\nGLOBALS:\n" . /** @scrutinizer ignore-type */ print_r($GLOBALS, true);
Loading history...
82
      $message .= "\n\nBacktrace:\n" . print_r(debug_backtrace(), true);
0 ignored issues
show
Bug introduced by
Are you sure print_r(debug_backtrace(), true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

82
      $message .= "\n\nBacktrace:\n" . /** @scrutinizer ignore-type */ print_r(debug_backtrace(), true);
Loading history...
83
84
      // include code fragment
85
      if (file_exists($file)) {
86
        $message .= "\n\n$file:\n";
87
        $code = @file($file);
88
        for ($i = max(0, $line - 10); $i < min($line + 10, count($code)); $i++) {
0 ignored issues
show
Bug introduced by
It seems like $code can also be of type false; however, parameter $value of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

88
        for ($i = max(0, $line - 10); $i < min($line + 10, count(/** @scrutinizer ignore-type */ $code)); $i++) {
Loading history...
89
          $message .= ($i + 1) . "\t$code[$i]";
90
        }
91
      }
92
93
      // make sure message is fully readable (convert unprintable chars to hex representation)
94
      $ret = '';
95
      for ($i = 0; $i < strlen($message); $i++) {
96
        $c = ord($message[$i]);
97
        if ($c == 10 || $c == 13 || $c == 9) {
98
          $ret .= $message[$i];
99
        } elseif ($c < 16) {
100
          $ret .= '\x0' . dechex($c);
101
        } elseif ($c < 32 || $c > 127) {
102
          $ret .= '\x' . dechex($c);
103
        } else {
104
          $ret .= $message[$i];
105
        }
106
      }
107
      $message = $ret;
108
109
      // send the mail if less than 5 errors
110
      static $mailcount = 0;
111
      if ($mailcount < 5) {
112
        @mail(self::$phpagi_error_handler_email, $subject, $message);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for mail(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

112
        /** @scrutinizer ignore-unhandled */ @mail(self::$phpagi_error_handler_email, $subject, $message);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
113
      }
114
      $mailcount++;
115
    }
116
  }
117
}
118