* Invision Power Services * IP.Board v3.2.3 * Compare and highlight differences between two strings or files * Last Updated: $Date: 2011-05-05 07:03:47 -0400 (Thu, 05 May 2011) $ * * * @author $Author: ips_terabyte $ * @copyright (c) 2001 - 2009 Invision Power Services, Inc. * @license This is NULLED! * @package IP.Board * @subpackage Kernel * @link http://hatynka.in * @since Thursday 10th February 2005 (10:47) * @version $Revision: 8644 $ */ if ( ! defined( 'IPS_CLASSES_PATH' ) ) { /** * Define classes path */ define( 'IPS_CLASSES_PATH', dirname(__FILE__) ); } class classDifference { # Globals /** * Shell command * * @access public * @var string */ public $diff_command = 'diff'; /** * Type of diff to use * * @access public * @var string [EXEC, CGI, PHP] */ public $method = 'EXEC'; /** * Differences found? * * @access public * @var integer */ public $diff_found = 0; /** * Post process DIFF result? * * @access public * @var integer */ public $post_process = 1; /** * Constructor * * @access public * @return @e void */ public function __construct() { //------------------------------- // Server? //------------------------------- if( strpos( strtolower( PHP_OS ), 'win' ) === 0 OR ( ! function_exists('exec') ) ) { $this->method = 'CGI'; } } /** * Wrapper function to get differences * * @access public * @param string Original string * @param string New string * @return string Diff data */ public function getDifferences( $str1, $str2 ) { $this->diff_found = 0; if ( $this->method != 'PHP' ) { $str1 = $this->_diffTagSpace($str1); $str2 = $this->_diffTagSpace($str2); $str1_lines = $this->_diffExplodeStringIntoWords($str1); $str2_lines = $this->_diffExplodeStringIntoWords($str2); } if ( $this->method == 'CGI' ) { $diff_res = $this->_getCgiDiff( implode( chr(10), $str1_lines ) . chr(10), implode( chr(10), $str2_lines ) . chr(10) ); } else if ( $this->method == 'PHP' ) { $diff_res = $this->_getPhpDiff( $str1, $str2 ); } else { $diff_res = $this->_getExecDiff( implode( chr(10), $str1_lines ) . chr(10), implode( chr(10), $str2_lines ) . chr(10) ); } //------------------------------- // Post process? //------------------------------- if ( $this->post_process ) { if ( is_array($diff_res) ) { reset($diff_res); $c = 0; $diff_res_array = array(); foreach( $diff_res as $l_val ) { if ( intval($l_val) ) { $c = intval($l_val); $diff_res_array[$c]['changeInfo'] = $l_val; } if (substr($l_val,0,1) == '<') { $diff_res_array[$c]['old'][] = substr($l_val,2); } if (substr($l_val,0,1) == '>') { $diff_res_array[$c]['new'][] = substr($l_val,2); } } $out_str = ''; $clr_buffer = ''; for ( $a = -1; $a < count($str1_lines); $a++ ) { if ( is_array( $diff_res_array[$a+1] ) ) { if ( strstr( $diff_res_array[$a+1]['changeInfo'], 'a') ) { $this->diff_found = 1; $clr_buffer .= htmlspecialchars($str1_lines[$a]).' '; } $out_str .= $clr_buffer; $clr_buffer = ''; if (is_array($diff_res_array[$a+1]['old'])) { $this->diff_found = 1; $out_str.=''.htmlspecialchars(implode(' ',$diff_res_array[$a+1]['old'])).' '; } if (is_array($diff_res_array[$a+1]['new'])) { $this->diff_found = 1; $out_str.=''.htmlspecialchars(implode(' ',$diff_res_array[$a+1]['new'])).' '; } $cip = explode(',',$diff_res_array[$a+1]['changeInfo']); if ( ! strcmp( $cip[0], $a + 1 ) ) { $new_line = intval($cip[1])-1; if ( $new_line > $a ) { $a = $new_line; } } } else { $clr_buffer .= htmlspecialchars($str1_lines[$a]).' '; } } $out_str .= $clr_buffer; $out_str = str_replace(' ',chr(10),$out_str); $out_str = $this->_diffTagSpace($out_str,1); return $out_str; } } else { return $diff_res; } } /** * Adds space character after HTML tags * * @access protected * @param string String * @param integer [Optional][0=reverse, 1=normal] * @return string Converted string */ protected function _diffTagSpace( $str, $rev=0 ) { if ( $rev ) { return str_replace(' <','<',str_replace('> ','>',$str) ); } else { return str_replace('<',' <',str_replace('>','> ',$str) ); } } /** * Explodes input string into words * * @access protected * @param string Input string * @return array Array of words in string */ protected function _diffExplodeStringIntoWords( $str ) { $str_array = $this->_explodeTrim( chr(10), $str ); $out_array = array(); reset($str_array); foreach( $str_array as $low ) { $all_words = $this->_explodeTrim( ' ', $low, 1 ); $out_array = array_merge($out_array, $all_words); $out_array[] = ''; $out_array[] = ''; } return $out_array; } /** * Explode into array and trim * * @access protected * @param string Delimiter * @param string String to check * @param integer [Optional] Remove blank lines * @return array Array of lines in string */ protected function _explodeTrim( $delim, $str, $remove_blank=0 ) { $tmp = explode( $delim, trim($str) ); $final = array(); foreach( $tmp as $i ) { if ( $remove_blank AND ( $i === '' OR $i === NULL ) ) //!$i AND $i !== 0 ) { continue; } else { $final[] = trim($i); } } return $final; } /** * Produce differences using PHP * * @access protected * @param string comapre string 1 * @param string comapre string 2 * @return string */ protected function _getPhpDiff( $str1 , $str2 ) { $str1 = explode( "\n", str_replace( "\r\n", "\n", $str1 ) ); $str2 = explode( "\n", str_replace( "\r\n", "\n", $str2 ) ); /* Set include path.. */ @set_include_path( IPS_KERNEL_PATH . 'PEAR/' );/*noLibHook*/ /* OMG.. too many PHP 5 errors under strict standards */ $oldReportLevel = error_reporting( 0 ); error_reporting( $oldReportLevel ^ E_STRICT ); require_once 'Text/Diff.php';/*noLibHook*/ require_once 'Text/Diff/Renderer.php';/*noLibHook*/ require_once 'Text/Diff/Renderer/inline.php';/*noLibHook*/ $diff = new Text_Diff( 'auto', array( $str1, $str2 ) ); $renderer = new Text_Diff_Renderer_inline(); $result = $renderer->render($diff); /* Go back to old reporting level */ error_reporting( $oldReportLevel | E_STRICT ); $result = str_replace( "", '', $result ); $result = str_replace( "", '', $result ); # Got a match? if ( strstr( $result, 'style="-ips-match:1"' ) ) { $this->diff_found = 1; } # No post processing please $this->post_process = 0; # Convert lines to a space, and two spaces to a single line //$result = str_replace(' ', chr(10), str_replace( "\n", " ", $result ) ); //$result = $this->_diffTagSpace($result,1); return $result; } /** * Produce differences using unix diff * * @access protected * @param string comapre string 1 * @param string comapre string 2 * @return string */ protected function _getExecDiff( $str1, $str2 ) { //------------------------------- // Write the tmp files //------------------------------- $file1 = IPS_ROOT_PATH . 'uploads/'.time().'-1'; $file2 = IPS_ROOT_PATH . 'uploads/'.time().'-2'; if ( $FH1 = @fopen( $file1, 'w' ) ) { @fwrite( $FH1, $str1, strlen($str1) ); @fclose( $FH1 ); } if ( $FH2 = @fopen( $file2, 'w' ) ) { @fwrite( $FH2, $str2, strlen($str2) ); @fclose( $FH2 ); } //------------------------------- // Check //------------------------------- if ( is_file( $file1 ) and is_file( $file2 ) ) { exec( $this->diff_command.' '.$file1.' '.$file2, $result ); @unlink( $file1 ); @unlink( $file2 ); return $result; } else { return "Ошибка, файлы не были записаны на диск"; } } /** * Produce differences using CGI * * @access protected * @param string comapre string 1 * @param string comapre string 2 * @return string */ protected function _getCgiDiff( $str1, $str2 ) { //----------------------------------------- // Load file management class //----------------------------------------- require_once( IPS_KERNEL_PATH . '/classFileManagement.php' );/*noLibHook*/ $this->classFileManagement = new classFileManagement(); //------------------------------- // Write the tmp files //------------------------------- $file1 = 'tmp-1'; $file2 = 'tmp-2'; if ( $FH1 = @fopen( IPS_ROOT_PATH.'uploads/'.$file1, 'w' ) ) { @fwrite( $FH1, $str1, strlen($str1) ); @fclose( $FH1 ); } if ( $FH2 = @fopen( IPS_ROOT_PATH.'uploads/'.$file2, 'w' ) ) { @fwrite( $FH2, $str2, strlen($str2) ); @fclose( $FH2 ); } //------------------------------- // Check //------------------------------- if ( is_file( IPS_ROOT_PATH . 'uploads/' . $file1 ) AND is_file( IPS_ROOT_PATH . 'uploads/' . $file2 ) ) { $result = $this->classFileManagement->getFileContents( ipsRegistry::$settings['board_url'] . "/" . CP_DIRECTORY . "/" . IPS_CGI_DIRECTORY . "/cgi_getdifference.cgi" ); @unlink( IPS_ROOT_PATH . 'uploads/' . $file1 ); @unlink( IPS_ROOT_PATH . 'uploads/' . $file2 ); return explode( "\n", $result ); } else { return "Ошибка, файлы не были записаны на диск"; } } } ?>