Issues (4967)

Security Analysis    not enabled

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.

wp-includes/class-wp-text-diff-renderer-table.php (5 issues)

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
/**
3
 * Diff API: WP_Text_Diff_Renderer_Table class
4
 *
5
 * @package WordPress
6
 * @subpackage Diff
7
 * @since 4.7.0
8
 */
9
10
/**
11
 * Table renderer to display the diff lines.
12
 *
13
 * @since 2.6.0
14
 * @uses Text_Diff_Renderer Extends
15
 */
16
class WP_Text_Diff_Renderer_Table extends Text_Diff_Renderer {
17
18
	/**
19
	 * @see Text_Diff_Renderer::_leading_context_lines
20
	 * @var int
21
	 * @access public
22
	 * @since 2.6.0
23
	 */
24
	public $_leading_context_lines  = 10000;
25
26
	/**
27
	 * @see Text_Diff_Renderer::_trailing_context_lines
28
	 * @var int
29
	 * @access public
30
	 * @since 2.6.0
31
	 */
32
	public $_trailing_context_lines = 10000;
33
34
	/**
35
	 * Threshold for when a diff should be saved or omitted.
36
	 *
37
	 * @var float
38
	 * @access protected
39
	 * @since 2.6.0
40
	 */
41
	protected $_diff_threshold = 0.6;
42
43
	/**
44
	 * Inline display helper object name.
45
	 *
46
	 * @var string
47
	 * @access protected
48
	 * @since 2.6.0
49
	 */
50
	protected $inline_diff_renderer = 'WP_Text_Diff_Renderer_inline';
51
52
	/**
53
	 * Should we show the split view or not
54
	 *
55
	 * @var string
56
	 * @access protected
57
	 * @since 3.6.0
58
	 */
59
	protected $_show_split_view = true;
60
61
	protected $compat_fields = array( '_show_split_view', 'inline_diff_renderer', '_diff_threshold' );
62
63
	/**
64
	 * Constructor - Call parent constructor with params array.
65
	 *
66
	 * This will set class properties based on the key value pairs in the array.
67
	 *
68
	 * @since 2.6.0
69
	 *
70
	 * @param array $params
71
	 */
72
	public function __construct( $params = array() ) {
73
		parent::__construct( $params );
74
		if ( isset( $params[ 'show_split_view' ] ) )
75
			$this->_show_split_view = $params[ 'show_split_view' ];
76
	}
77
78
	/**
79
	 * @ignore
80
	 *
81
	 * @param string $header
82
	 * @return string
83
	 */
84
	public function _startBlock( $header ) {
85
		return '';
86
	}
87
88
	/**
89
	 * @ignore
90
	 *
91
	 * @param array $lines
92
	 * @param string $prefix
93
	 */
94
	public function _lines( $lines, $prefix=' ' ) {
95
	}
96
97
	/**
98
	 * @ignore
99
	 *
100
	 * @param string $line HTML-escape the value.
101
	 * @return string
102
	 */
103
	public function addedLine( $line ) {
104
		return "<td class='diff-addedline'>{$line}</td>";
105
106
	}
107
108
	/**
109
	 * @ignore
110
	 *
111
	 * @param string $line HTML-escape the value.
112
	 * @return string
113
	 */
114
	public function deletedLine( $line ) {
115
		return "<td class='diff-deletedline'>{$line}</td>";
116
	}
117
118
	/**
119
	 * @ignore
120
	 *
121
	 * @param string $line HTML-escape the value.
122
	 * @return string
123
	 */
124
	public function contextLine( $line ) {
125
		return "<td class='diff-context'>{$line}</td>";
126
	}
127
128
	/**
129
	 * @ignore
130
	 *
131
	 * @return string
132
	 */
133
	public function emptyLine() {
134
		return '<td>&nbsp;</td>';
135
	}
136
137
	/**
138
	 * @ignore
139
	 * @access public
140
	 *
141
	 * @param array $lines
142
	 * @param bool $encode
143
	 * @return string
144
	 */
145 View Code Duplication
	public function _added( $lines, $encode = true ) {
146
		$r = '';
147
		foreach ($lines as $line) {
148
			if ( $encode ) {
149
				$processed_line = htmlspecialchars( $line );
150
151
				/**
152
				 * Contextually filters a diffed line.
153
				 *
154
				 * Filters TextDiff processing of diffed line. By default, diffs are processed with
155
				 * htmlspecialchars. Use this filter to remove or change the processing. Passes a context
156
				 * indicating if the line is added, deleted or unchanged.
157
				 *
158
				 * @since 4.1.0
159
				 *
160
				 * @param String $processed_line The processed diffed line.
161
				 * @param String $line           The unprocessed diffed line.
162
		 		 * @param string null            The line context. Values are 'added', 'deleted' or 'unchanged'.
163
				 */
164
				$line = apply_filters( 'process_text_diff_html', $processed_line, $line, 'added' );
165
			}
166
167
			if ( $this->_show_split_view ) {
168
				$r .= '<tr>' . $this->emptyLine() . $this->emptyLine() . $this->addedLine( $line ) . "</tr>\n";
169
			} else {
170
				$r .= '<tr>' . $this->addedLine( $line ) . "</tr>\n";
171
			}
172
		}
173
		return $r;
174
	}
175
176
	/**
177
	 * @ignore
178
	 * @access public
179
	 *
180
	 * @param array $lines
181
	 * @param bool $encode
182
	 * @return string
183
	 */
184 View Code Duplication
	public function _deleted( $lines, $encode = true ) {
185
		$r = '';
186
		foreach ($lines as $line) {
187
			if ( $encode ) {
188
				$processed_line = htmlspecialchars( $line );
189
190
				/** This filter is documented in wp-includes/wp-diff.php */
191
				$line = apply_filters( 'process_text_diff_html', $processed_line, $line, 'deleted' );
192
			}
193
			if ( $this->_show_split_view ) {
194
				$r .= '<tr>' . $this->deletedLine( $line ) . $this->emptyLine() . $this->emptyLine() . "</tr>\n";
195
			} else {
196
				$r .= '<tr>' . $this->deletedLine( $line ) . "</tr>\n";
197
			}
198
199
		}
200
		return $r;
201
	}
202
203
	/**
204
	 * @ignore
205
	 * @access public
206
	 *
207
	 * @param array $lines
208
	 * @param bool $encode
209
	 * @return string
210
	 */
211 View Code Duplication
	public function _context( $lines, $encode = true ) {
212
		$r = '';
213
		foreach ($lines as $line) {
214
			if ( $encode ) {
215
				$processed_line = htmlspecialchars( $line );
216
217
				/** This filter is documented in wp-includes/wp-diff.php */
218
				$line = apply_filters( 'process_text_diff_html', $processed_line, $line, 'unchanged' );
219
			}
220
			if (  $this->_show_split_view ) {
221
				$r .= '<tr>' . $this->contextLine( $line ) . $this->emptyLine() . $this->contextLine( $line )  . "</tr>\n";
222
			} else {
223
				$r .= '<tr>' . $this->contextLine( $line ) . "</tr>\n";
224
			}
225
		}
226
		return $r;
227
	}
228
229
	/**
230
	 * Process changed lines to do word-by-word diffs for extra highlighting.
231
	 *
232
	 * (TRAC style) sometimes these lines can actually be deleted or added rows.
233
	 * We do additional processing to figure that out
234
	 *
235
	 * @access public
236
	 * @since 2.6.0
237
	 *
238
	 * @param array $orig
239
	 * @param array $final
240
	 * @return string
241
	 */
242
	public function _changed( $orig, $final ) {
243
		$r = '';
244
245
		// Does the aforementioned additional processing
246
		// *_matches tell what rows are "the same" in orig and final. Those pairs will be diffed to get word changes
247
		//	match is numeric: an index in other column
248
		//	match is 'X': no match. It is a new row
249
		// *_rows are column vectors for the orig column and the final column.
250
		//	row >= 0: an indix of the $orig or $final array
251
		//	row  < 0: a blank row for that column
252
		list($orig_matches, $final_matches, $orig_rows, $final_rows) = $this->interleave_changed_lines( $orig, $final );
0 ignored issues
show
The assignment to $final_matches is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
253
254
		// These will hold the word changes as determined by an inline diff
255
		$orig_diffs  = array();
256
		$final_diffs = array();
257
258
		// Compute word diffs for each matched pair using the inline diff
259
		foreach ( $orig_matches as $o => $f ) {
260
			if ( is_numeric($o) && is_numeric($f) ) {
261
				$text_diff = new Text_Diff( 'auto', array( array($orig[$o]), array($final[$f]) ) );
262
				$renderer = new $this->inline_diff_renderer;
263
				$diff = $renderer->render( $text_diff );
264
265
				// If they're too different, don't include any <ins> or <dels>
266
				if ( preg_match_all( '!(<ins>.*?</ins>|<del>.*?</del>)!', $diff, $diff_matches ) ) {
267
					// length of all text between <ins> or <del>
268
					$stripped_matches = strlen(strip_tags( join(' ', $diff_matches[0]) ));
269
					// since we count lengith of text between <ins> or <del> (instead of picking just one),
270
					//	we double the length of chars not in those tags.
271
					$stripped_diff = strlen(strip_tags( $diff )) * 2 - $stripped_matches;
272
					$diff_ratio = $stripped_matches / $stripped_diff;
273
					if ( $diff_ratio > $this->_diff_threshold )
274
						continue; // Too different. Don't save diffs.
275
				}
276
277
				// Un-inline the diffs by removing del or ins
278
				$orig_diffs[$o]  = preg_replace( '|<ins>.*?</ins>|', '', $diff );
279
				$final_diffs[$f] = preg_replace( '|<del>.*?</del>|', '', $diff );
280
			}
281
		}
282
283
		foreach ( array_keys($orig_rows) as $row ) {
284
			// Both columns have blanks. Ignore them.
285
			if ( $orig_rows[$row] < 0 && $final_rows[$row] < 0 )
286
				continue;
287
288
			// If we have a word based diff, use it. Otherwise, use the normal line.
289
			if ( isset( $orig_diffs[$orig_rows[$row]] ) )
290
				$orig_line = $orig_diffs[$orig_rows[$row]];
291
			elseif ( isset( $orig[$orig_rows[$row]] ) )
292
				$orig_line = htmlspecialchars($orig[$orig_rows[$row]]);
293
			else
294
				$orig_line = '';
295
296
			if ( isset( $final_diffs[$final_rows[$row]] ) )
297
				$final_line = $final_diffs[$final_rows[$row]];
298
			elseif ( isset( $final[$final_rows[$row]] ) )
299
				$final_line = htmlspecialchars($final[$final_rows[$row]]);
300
			else
301
				$final_line = '';
302
303
			if ( $orig_rows[$row] < 0 ) { // Orig is blank. This is really an added row.
304
				$r .= $this->_added( array($final_line), false );
305
			} elseif ( $final_rows[$row] < 0 ) { // Final is blank. This is really a deleted row.
306
				$r .= $this->_deleted( array($orig_line), false );
307
			} else { // A true changed row.
308
				if ( $this->_show_split_view ) {
309
					$r .= '<tr>' . $this->deletedLine( $orig_line ) . $this->emptyLine() . $this->addedLine( $final_line ) . "</tr>\n";
310
				} else {
311
					$r .= '<tr>' . $this->deletedLine( $orig_line ) . "</tr><tr>" . $this->addedLine( $final_line ) . "</tr>\n";
312
				}
313
			}
314
		}
315
316
		return $r;
317
	}
318
319
	/**
320
	 * Takes changed blocks and matches which rows in orig turned into which rows in final.
321
	 *
322
	 * Returns
323
	 *	*_matches ( which rows match with which )
324
	 *	*_rows ( order of rows in each column interleaved with blank rows as
325
	 *		necessary )
326
	 *
327
	 * @since 2.6.0
328
	 *
329
	 * @param array $orig
330
	 * @param array $final
331
	 * @return array
0 ignored issues
show
Consider making the return type a bit more specific; maybe use array[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
332
	 */
333
	public function interleave_changed_lines( $orig, $final ) {
334
335
		// Contains all pairwise string comparisons. Keys are such that this need only be a one dimensional array.
336
		$matches = array();
337
		foreach ( array_keys($orig) as $o ) {
338
			foreach ( array_keys($final) as $f ) {
339
				$matches["$o,$f"] = $this->compute_string_distance( $orig[$o], $final[$f] );
340
			}
341
		}
342
		asort($matches); // Order by string distance.
343
344
		$orig_matches  = array();
345
		$final_matches = array();
346
347
		foreach ( $matches as $keys => $difference ) {
348
			list($o, $f) = explode(',', $keys);
349
			$o = (int) $o;
350
			$f = (int) $f;
351
352
			// Already have better matches for these guys
353
			if ( isset($orig_matches[$o]) && isset($final_matches[$f]) )
354
				continue;
355
356
			// First match for these guys. Must be best match
357
			if ( !isset($orig_matches[$o]) && !isset($final_matches[$f]) ) {
358
				$orig_matches[$o] = $f;
359
				$final_matches[$f] = $o;
360
				continue;
361
			}
362
363
			// Best match of this final is already taken?  Must mean this final is a new row.
364
			if ( isset($orig_matches[$o]) )
365
				$final_matches[$f] = 'x';
366
367
			// Best match of this orig is already taken?  Must mean this orig is a deleted row.
368
			elseif ( isset($final_matches[$f]) )
369
				$orig_matches[$o] = 'x';
370
		}
371
372
		// We read the text in this order
373
		ksort($orig_matches);
374
		ksort($final_matches);
375
376
		// Stores rows and blanks for each column.
377
		$orig_rows = $orig_rows_copy = array_keys($orig_matches);
378
		$final_rows = array_keys($final_matches);
379
380
		// Interleaves rows with blanks to keep matches aligned.
381
		// We may end up with some extraneous blank rows, but we'll just ignore them later.
382
		foreach ( $orig_rows_copy as $orig_row ) {
383
			$final_pos = array_search($orig_matches[$orig_row], $final_rows, true);
384
			$orig_pos = (int) array_search($orig_row, $orig_rows, true);
385
386
			if ( false === $final_pos ) { // This orig is paired with a blank final.
387
				array_splice( $final_rows, $orig_pos, 0, -1 );
388
			} elseif ( $final_pos < $orig_pos ) { // This orig's match is up a ways. Pad final with blank rows.
389
				$diff_pos = $final_pos - $orig_pos;
390
				while ( $diff_pos < 0 )
391
					array_splice( $final_rows, $orig_pos, 0, $diff_pos++ );
392
			} elseif ( $final_pos > $orig_pos ) { // This orig's match is down a ways. Pad orig with blank rows.
393
				$diff_pos = $orig_pos - $final_pos;
394
				while ( $diff_pos < 0 )
395
					array_splice( $orig_rows, $orig_pos, 0, $diff_pos++ );
396
			}
397
		}
398
399
		// Pad the ends with blank rows if the columns aren't the same length
400
		$diff_count = count($orig_rows) - count($final_rows);
401
		if ( $diff_count < 0 ) {
402
			while ( $diff_count < 0 )
403
				array_push($orig_rows, $diff_count++);
404
		} elseif ( $diff_count > 0 ) {
405
			$diff_count = -1 * $diff_count;
406
			while ( $diff_count < 0 )
407
				array_push($final_rows, $diff_count++);
408
		}
409
410
		return array($orig_matches, $final_matches, $orig_rows, $final_rows);
411
	}
412
413
	/**
414
	 * Computes a number that is intended to reflect the "distance" between two strings.
415
	 *
416
	 * @since 2.6.0
417
	 *
418
	 * @param string $string1
419
	 * @param string $string2
420
	 * @return int
0 ignored issues
show
Should the return type not be integer|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
421
	 */
422
	public function compute_string_distance( $string1, $string2 ) {
423
		// Vectors containing character frequency for all chars in each string
424
		$chars1 = count_chars($string1);
425
		$chars2 = count_chars($string2);
426
427
		// L1-norm of difference vector.
428
		$difference = array_sum( array_map( array($this, 'difference'), $chars1, $chars2 ) );
429
430
		// $string1 has zero length? Odd. Give huge penalty by not dividing.
431
		if ( !$string1 )
432
			return $difference;
433
434
		// Return distance per character (of string1).
435
		return $difference / strlen($string1);
436
	}
437
438
	/**
439
	 * @ignore
440
	 * @since 2.6.0
441
	 *
442
	 * @param int $a
443
	 * @param int $b
444
	 * @return int
0 ignored issues
show
Should the return type not be integer|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
445
	 */
446
	public function difference( $a, $b ) {
447
		return abs( $a - $b );
448
	}
449
450
	/**
451
	 * Make private properties readable for backward compatibility.
452
	 *
453
	 * @since 4.0.0
454
	 * @access public
455
	 *
456
	 * @param string $name Property to get.
457
	 * @return mixed Property.
458
	 */
459
	public function __get( $name ) {
460
		if ( in_array( $name, $this->compat_fields ) ) {
461
			return $this->$name;
462
		}
463
	}
464
465
	/**
466
	 * Make private properties settable for backward compatibility.
467
	 *
468
	 * @since 4.0.0
469
	 * @access public
470
	 *
471
	 * @param string $name  Property to check if set.
472
	 * @param mixed  $value Property value.
473
	 * @return mixed Newly-set property.
474
	 */
475
	public function __set( $name, $value ) {
476
		if ( in_array( $name, $this->compat_fields ) ) {
477
			return $this->$name = $value;
478
		}
479
	}
480
481
	/**
482
	 * Make private properties checkable for backward compatibility.
483
	 *
484
	 * @since 4.0.0
485
	 * @access public
486
	 *
487
	 * @param string $name Property to check if set.
488
	 * @return bool Whether the property is set.
0 ignored issues
show
Should the return type not be boolean|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
489
	 */
490
	public function __isset( $name ) {
491
		if ( in_array( $name, $this->compat_fields ) ) {
492
			return isset( $this->$name );
493
		}
494
	}
495
496
	/**
497
	 * Make private properties un-settable for backward compatibility.
498
	 *
499
	 * @since 4.0.0
500
	 * @access public
501
	 *
502
	 * @param string $name Property to unset.
503
	 */
504
	public function __unset( $name ) {
505
		if ( in_array( $name, $this->compat_fields ) ) {
506
			unset( $this->$name );
507
		}
508
	}
509
}
510