From d1e81fec8bc718930ce4b040decfefcadaffe7b6 Mon Sep 17 00:00:00 2001 From: Andrew Garrett Date: Thu, 17 Jul 2008 12:19:51 +0000 Subject: [PATCH] Add wfDiff function, similar to wfMerge (some copied), used in AbuseFilter extension to generate a line-by-line machine-readable diff between two texts. Shells out to diff utility. --- includes/DefaultSettings.php | 5 +++ includes/GlobalFunctions.php | 60 ++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 29e52321fa..058cbce8a0 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -1738,6 +1738,11 @@ $wgAntiLockFlags = 0; */ $wgDiff3 = '/usr/bin/diff3'; +/** + * Path to the GNU diff utility. + */ +$wgDiff = '/usr/bin/diff'; + /** * We can also compress text stored in the 'text' table. If this is set on, new * revisions will be compressed on page save if zlib support is available. Any diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 8185a7fa5f..7dbe0dd337 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -1178,6 +1178,66 @@ function wfMerge( $old, $mine, $yours, &$result ){ return ! $conflict; } +/** + * Returns unified plain-text diff of two texts. + * Useful for machine processing of diffs. + * @param $before string The text before the changes. + * @param $after string The text after the changes. + * @param $params string Command-line options for the diff command. + * @return string Unified diff of $before and $after + */ +function wfDiff( $before, $after, $params = '-u' ) { + global $wgDiff; + + # This check may also protect against code injection in + # case of broken installations. + if(! file_exists( $wgDiff ) ){ + wfDebug( "diff3 not found\n" ); + return false; + } + + # Make temporary files + $td = wfTempDir(); + $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' ); + $newtextFile = fopen( $newtextName = tempnam( $td, 'merge-your-' ), 'w' ); + + fwrite( $oldtextFile, $before ); fclose( $oldtextFile ); + fwrite( $newtextFile, $after ); fclose( $newtextFile ); + + // Get the diff of the two files + $cmd = "$wgDiff " . $params . ' ' .wfEscapeShellArg( $oldtextName, $newtextName ); + + $h = popen( $cmd, 'r' ); + + $diff = ''; + + do { + $data = fread( $h, 8192 ); + if ( strlen( $data ) == 0 ) { + break; + } + $diff .= $data; + } while ( true ); + + // Clean up + pclose( $h ); + unlink( $oldtextName ); + unlink( $newtextName ); + + // Kill the --- and +++ lines. They're not useful. + $diff_lines = explode( "\n", $diff ); + if (strpos( '---', $diff_lines[0] ) == 0) { + unset($diff_lines[0]); + } + if (strpos( '+++', $diff_lines[1] ) == 0) { + unset($diff_lines[1]); + } + + $diff = implode( "\n", $diff_lines ); + + return $diff; +} + /** * @todo document */ -- 2.20.1