GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( a6a2a3...83b34a )
by Marco
01:56
created

function.php ➔ dspamType()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 1
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
function imapFolder($cf, $username) {
4
	$return = array();
5
	$open='{'.$cf['mailhost'].':143/imap/novalidate-cert/authuser='.$cf['authuser'].'}';
6
        $m_mail = imap_open($open, $username, $cf['authpassword'], OP_READONLY)
7
                or syslog (LOG_EMERG, $cf['user'].': Error in IMAP connection to <'.$cf['mailhost'].'>: ' . imap_last_error());
8
        if ( !$m_mail ) exit(254);
0 ignored issues
show
Coding Style Compatibility introduced by
The function imapFolder() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
9
10
11
        syslog (LOG_INFO,$cf['user'].': Successfully connected to <'.$cf['mailhost'].'>; Listing folders of account <'.$username.'>...');
12
        //get all folder
13
	$list = imap_list($m_mail, $open, "*");
14
	imap_close($m_mail);
15
	if (is_array($list))
16
		foreach ($list as $mbox)
17
			$return[] = explode($open,$mbox,2)[1];
18
	else
19
		syslog (LOG_INFO,$cf['user'] . ': imap_list failed: ' . imap_last_error() );
20
	return $return;
21
}
22
23
function imapFind ($cf, $username, $folder) {
24
	$head=array();
25
	$m_mail = imap_open('{'.$cf['mailhost'].':143/imap/novalidate-cert/authuser='.$cf['authuser'].'}'.$folder, $username,$cf['authpassword'], OP_READONLY)
26
        	or syslog (LOG_EMERG, $cf['user'].': Error in IMAP connection to <'.$cf['mailhost'].'>: ' . imap_last_error());
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
27
	if ( !$m_mail ) exit(254);
0 ignored issues
show
Coding Style Compatibility introduced by
The function imapFind() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
28
		
29
30
	syslog (LOG_INFO,$cf['user'].': Successfully connected to <'.$cf['mailhost'].">; Reading <$folder> messages of last ".$cf['oldestday'].' days on account <'.$username.'>...');
31
	//get all messages
32
	$dateTh = date ( "d-M-Y", strToTime ( '-'.$cf['oldestday'].' days' ) );
33
	$m_search=imap_search ($m_mail, "SINCE \"$dateTh\" TEXT \"Authentication-Results: \"" );
34
35
36
	// Order results starting from newest message
37
	if ( empty($m_search) ) {
38
		syslog (LOG_INFO,$cf['user'].": No suitable mail found in <$folder> folder.");
39 View Code Duplication
	        if ( $ierr = imap_errors() )
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
40
	                foreach ( $ierr as $thiserr )
41
	                        syslog (LOG_ERR, $cf['user'].": IMAP Error: $thiserr");
42 View Code Duplication
	        if ( $ierr = imap_alerts() )
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
43
	                foreach ( $ierr as $thiserr )
44
	                        syslog (LOG_ALERT, $cf['user'].": IMAP Alert: $thiserr");
45
		imap_close( $m_mail );
46
		return FALSE;
47
	}
48
	$nmes = count ($m_search);
49
	syslog (LOG_INFO,$cf['user'].": Found $nmes mail in <$folder> folder.");
50
	if ($nmes>0) rsort($m_search);
51
52
        // loop for each message
53
	foreach ($m_search as $onem) 
54
		$head[] = imap_fetchheader($m_mail, $onem );
55
	imap_close($m_mail);
56
	return $head;
57
}
58
59
function dspamLevel($prob, $conf) {
60
/* Calculate DSPAM Level as the Spamassassin Plugin */
61
	if (is_null($prob) or is_null($conf)) return '-';
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
62
	$t_prob = abs((($prob - 0.5) * 2) * 100);
63
	return round(($t_prob + ($conf*100)) / 2);
64
}
65
66
function dspamType($classSpam) {
67
	switch($classSpam) {
68
		case 'HAM':
69
			return 'Innocent';
70
		case 'SPAM':
71
			return 'Spam';
72
		default:
73
			/* this should never happens */
74
			return $classSpam;
75
	}
76
}
77
78
function imapInfo($user,$header,$ARhosts,$dpl=false, $learn=false) {
79
/* Get relevant Info from header's mail */
80
/* Each line must end with /r/n         */
81
82
	$result = array(
83
                'date' => NULL,
84
                'from' => NULL,
85
                'messageid' => NULL,
86
		'dmarc' => array(
87
			'result' => NULL,
88
			'dom'	=> NULL
89
			),
90
		'spf' => array(
91
                        'result' => NULL,
92
                        'dom'   => NULL
93
                        ),
94
		'dkim' => array(
95
                        'result' => NULL,
96
                        'dom'   => NULL
97
                        ),
98
                'spam' => array(
99
                        'status' => NULL,
100
                        'score' => NULL,
101
                        'th'    => NULL,
102
                        ),
103
                'dspam' => array(
104
                        'type' => NULL,
105
                        'level' => NULL,
106
			'learn' => NULL
107
                        ),
108
		'warn' => NULL
109
        );
110
		
111
112 View Code Duplication
        if ( preg_match_all ('/^Authentication\-Results:\s+(?<host>[\w\.]+);(?:\s+|\r\n\s+)dmarc=(?<dmarc>\w+)\s+\(p=\w+\s+dis=\w+\)\s+header\.from=(?<DMARCfrom>[\w\.]+)/m',$header,$received) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
113
		$k=0;
114
                for ($i = count($received[0])-1;$i>=0;$i--) {
115
	                foreach ($ARhosts as $mx) {
116
				if ($mx == $received['host'][$i]) {
117
					/* This is a trusted AR result */
118
					$result['dmarc']['result']=$received['dmarc'][$i];
119
					$result['dmarc']['dom'] = $received['DMARCfrom'][$i];
120
					$k++;
121
				}
122
                	}
123
		}
124
        }
125
	$received=NULL;
126
	if ($k>1) $result['warn'][] = 'The trusted DMARC AR Headers are present more than once. Something wrong.';
0 ignored issues
show
Bug introduced by
The variable $k does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
127
128 View Code Duplication
        if ( preg_match_all('/^Authentication\-Results:\s+(?<host>[\w\.]+);(?:\s+|\r\n\s+)spf=(?<spf>\w+)\s+smtp\.(?:mailfrom|helo)=(?<SPFfrom>[\w\.]+)/m',$header,$received) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
129
		$k=0;
130
		for ($i = count($received[0])-1;$i>=0;$i--) {
131
			foreach ($ARhosts as $mx) {
132
				if ($mx == $received['host'][$i]) {
133
					/* This is a trusted AR result */
134
					$result['spf']['result']=$received['spf'][$i];
135
					$result['spf']['dom'] = $received['SPFfrom'][$i];
136
					$k++;
137
                        	}
138
                	}
139
        	}
140
	}
141
	$received=NULL;
142
	if ($k>1) $result['warn'][] = 'The trusted SPF AR Headers are present more than once. Something wrong.';
143
144
	$k=0;
145 View Code Duplication
        if ( preg_match_all('/^Authentication\-Results:\s+(?<host>[\w\.]+);(?:\s+|\r\n\s+)dkim=(?<dkim>\w+)\s+[\w\s\(\)\-]+header\.d=(?<DKIMdom>[\w\.]+)/m',$header,$received) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
146
		for ($i = count($received[0])-1;$i>=0;$i--) {
147
	                foreach ($ARhosts as $mx) {
148
        	                if ($mx == $received['host'][$i]) {
149
                	                /* This is a trusted AR result */
150
                        	        $result['dkim']['result']=$received['dkim'][$i];
151
                                	$result['dkim']['dom'] = $received['DKIMdom'][$i];
152
					$k++;
153
                        	}
154
                	}
155
        	}
156
	}
157
	$received=NULL;
158
	if ($k>1) $result['warn'][] = 'The trusted DKIM AR Headers are present more than once. Something wrong.';
159
160
	if ($dpl) { /* Use Spamassassin Plugin */
161
		if ( preg_match_all('/^X\-Spam\-Status:\s(?P<spamstatus>\w+)\,(?:\s+|\r\n\s+)score=(?P<score>[\-\.\d]+)(?:\s+|\r\n\s+)tagged_above=\-{0,1}\d+(?:\s+|\r\n\s+)required=(?P<th>[\-\.\d]+)(?:\s+|\r\n\s+)tests=\[(?:.|\r\n\s+)*DSPAM_(?P<dtype>SPAM|HAM)_(?P<dlevel>\d\d)(?:.|\r\n\s+)*\]/m',$header,$received) ) {
162
			$result['spam']['status']=$received['spamstatus'][0];
163
                	$result['spam']['score'] = $received['score'][0];
164
			$result['spam']['th'] = $received['th'][0];
165
			$result['dspam']['type'] = dspamType($received['dtype'][0]);
166
			$result['dspam']['level'] =$received['dlevel'][0];
167
        	}
168
        	if (count($received[0])>1) $result['warn'][] = 'The Spamassassin Headers are present more than once. I consider only the last one.';
169
	}
170
	else { /* Parse apart all DSPAM Header and calculate a level */
171
		if ( preg_match_all('/^X\-Spam\-Status:\s(?P<spamstatus>\w+)\,(?:\s+|\r\n\s+)score=(?P<score>[\-\.\d]+)(?:\s+|\r\n\s+)tagged_above=\-{0,1}\d+(?:\s+|\r\n\s+)required=(?P<th>[\-\.\d]+)(?:\s+|\r\n\s+)tests=\[(?:.|\r\n\s+)*\]/m',$header,$received) ) {
172
                        $result['spam']['status']=$received['spamstatus'][0];
173
                        $result['spam']['score'] = $received['score'][0];
174
                        $result['spam']['th'] = $received['th'][0];
175
			if (count($received[0])>1)
176
				$result['warn'][]= 'The Spamassassin Headers are present more than once. I consider only the last one.';
177
		}
178 View Code Duplication
		if ( preg_match ('/\r\nX\-DSPAM\-Result:\s(?P<result>.*)\r\n/',$header,$received) != 1)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
179
	                $result['warn'] = 'DSPAM Result invalid, not present or present more than once.';
180
	        else
181
                	$result['dspam']['type']=$received['result'];
182
		$prob = NULL;
183
		$conf = NULL;
184 View Code Duplication
                if ( preg_match ('/\r\nX\-DSPAM\-Probability:\s(?P<prob>.*)\r\n/',$header,$received) != 1)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
185
                        $result['warn'][] = 'DSPAM Probability invalid, not present or present more than once.';
186
		else
187
			$prob = $received['prob'];
188 View Code Duplication
		if ( preg_match ('/\r\nX\-DSPAM\-Confidence:\s(?P<conf>.*)\r\n/',$header,$received) != 1)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
189
                        $result['warn'][] = 'DSPAM Confidence invalid, not present or present more than once.';
190
		else
191
			$conf = $received['conf'];
192
		$result['dspam']['level'] = dspamLevel($prob,$conf);
193
	}
194
	$received=NULL;
195 View Code Duplication
	if ( preg_match ('/\r\nFrom:\s(?P<from>.*)\r\n/',$header,$received) != 1)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
196
                $result['warn'][] = 'From header invalid or not present';
197
        else
198
                $result['from'] = $received['from'];
199
200 View Code Duplication
        if ( preg_match ('/\r\nDate:\s(?P<date>.*)\r\n/',$header,$received) != 1)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
201
                $result['warn'][] = 'Date header invalid or not present';
202
	else
203
		$result['date'] = $received['date'];
204
205
	$received=NULL;
206 View Code Duplication
        if ( preg_match ('/\r\nMessage\-I(?:D|d):\s(?P<mid>.*)\r\n/',$header,$received) != 1)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
207
                $result['warn'][] = 'Message-ID invalid, not present or present more than once.';
208
	else
209
		$result['messageid']=$received['mid'];
210
211
        $received=NULL;
212
213
        switch ($learn) {
214
		case 'dspamc':
215 View Code Duplication
        		if ( preg_match ('/\r\nX\-DSPAM\-Signature:\s(?P<sig>.*)\r\n/',$header,$received) != 1)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
216
				$result['warn'] = 'DSPAM Signature invalid, not present or present more than once.';
217
			else
218
				$result['dspam']['learn']=$received['sig'];			
219
			break;
220
		case false:
221
			break;
222
		default:
223
			syslog (LOG_INFO,$user.': Error in "learn" imap configuration value. Please, set "dspamc" or "false".');
224
	}
225
	
226
        return $result;
227
}
228
229
230
231
232
function printTableHeader($title,$content,$footer=FALSE,$fcontent) {
233
        print <<<END
234
	<caption>$title</caption>
235
	<thead>
236
	<tr>
237
END;
238
	$kcontent = array_keys($content);
239
        $cols = count($kcontent);
240
        for ($i=0; $i<$cols; $i++) {
241
		$key = $kcontent[$i];
242
                printf ('<th colspan="%d" rowspan="%d">%s</th>',
243
			!is_array($content[$key]) ?:
244
			count(array_keys($content[$key])) ?: '1',
245
			!is_array($content[$key]) ?:
246
			empty(array_keys($content[$key])) ? '2' : '1',
247
			$kcontent[$i]);
248
	}
249
	print '</tr><tr>';
250
	for ($i=0; $i<$cols; $i++) {
251
		$key = $kcontent[$i];
252
		if (is_array($content[$key])&&($hs = array_keys($content[$key]))) {
253
			foreach ($hs as $h)
254
				printf('<th>%s</th>',$h);
255
		}
256
	}
257
		
258
        print '</tr></thead>';
259
        if ($footer) {
260
                print '<tfoot><tr>';
261
                print "<th colspan=\"$cols\">".$fcontent.'</th>';
262
                print '</tr></tfoot>';
263
        }
264
        return TRUE;
265
}
266
267
268
function formatVal($val, $learn) {
269
	foreach (array_keys($val) as $key) {
270
		if (is_array($val["$key"]) and ($key!='warn'))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
271
			$val["$key"] = formatVal($val["$key"], $learn);
272
		else {
273
			switch ($key) {
274
				case 'warn':
275
					if (empty($val["$key"]))
276
						$val["$key"] = '-';
277
					else 
278
						$val["$key"] = sprintf('<div title="%s">Y</div>',implode($val["$key"],"\n"));
279
					break;
280
				case 'learn':
281
					$val["$key"] = formLearn($learn, $val);
282
					break;
283
				default:
284
					$val["$key"] = htmlentities($val["$key"]);
285
			}
286
		}
287
	}
288
	return $val;
289
}
290
291
function formLearn($type, $par) {
292
	$return = NULL;
293
	switch ($type) {
294
		case 'dspamc':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
295
			$classes = array('Spam', 'Innocent');
296
			foreach ($classes as $class) {
297
				$par['class'] = $class;
298
				$val["$class"] = sprintf('dspamc --user dspam --deliver=summary --class=%s --source=error --signature=%s',
0 ignored issues
show
Coding Style Comprehensibility introduced by
$val was never initialized. Although not strictly required by PHP, it is generally a good practice to add $val = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
299
							strtolower($class), $par['learn']);
300
				if (($class != $par['type'])||($par['level']<99))
301
					$return .= sprintf(file_get_contents('formLearnDSPAM.htm'),
302
						$class,$class,$val["$class"],base64_encode(json_encode($par)),$class);
0 ignored issues
show
Bug introduced by
The variable $val does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
303
			}
304
		default:
305
			return $return;
306
	}
307
}
308
309
function printTableRow($row, $learn, $init=true) {
310
	$color = 'inherit';
311
	if ($init) 
312
		$row=formatVal($row,$learn);
313
	foreach( $row as $key => $val) {
314
		if (is_array($val))
315
			printTableRow($val, $learn, false);
316
		else {
317
			/* DSPAM format */
318
			if (isset($row['type']))
319
				switch($row['type']) {
320
					case 'Innocent':
321
					case 'HAM':
322
						$color = 'rgba(0,255,0, %.1f)';
323
						break;
324
					case 'Spam':
325
					case 'SPAM':
326
						$color = 'rgba(255,0,0,%.1f)';
327
			}
328
			/* DMARC, DKIM, SPF format */
329
			if (isset($row['result']))
330
				switch($row['result']) {
331
					case 'pass':
332
						$color = 'rgba(0,255,0, %.1f)';
333
						break;
334
					case 'fail':
335
						$color = 'rgba(255,0,0,%.1f)';
336
				}
337
			/* Spamassassin format */
338
			if (isset($row['status']))
339
	                        switch($row['status']) {
340
					case 'No':
341
						$color = 'rgba(0,255,0, %.1f)';
342
						break;
343
					case 'Yes':
344
						$color = 'rgba(255,0,0,%.1f)';
345
				}	
346
				
347
			$alpha = (is_numeric($val)AND($key=='type')) ? round($val/100,1) : 1.0;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
348
			$bg = sprintf(" style=\"background-color: $color\"", $alpha);		
349
			printf ('<td%s>%s</td>',$bg, $val);
350
		}
351
	}
352
}
353
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
354