pathSeparator.ini_get('include_path')); @include_once 'Text/Diff.php'; @include_once 'Text/Diff/Renderer.php'; @include_once 'Text/Diff/Renderer/unified.php'; include_once 'include/diff_util.php'; $arrayBased = false; $fileBased = false; class ListingHelper { var $_listing = array(); var $_index = 0; var $_blockStart = false; function _add($text1, $lineno1, $class1, $text2, $lineno2, $class2) { $listing = &$this->_listing; $index = &$this->_index; $listing[$index]['rev1diffclass'] = $class1; $listing[$index]['rev2diffclass'] = $class2; $listing[$index]['rev1line'] = $text1; $listing[$index]['rev2line'] = $text2; $listing[$index]['rev1lineno'] = $lineno1; $listing[$index]['rev2lineno'] = $lineno2; $listing[$index]['startblock'] = $this->_blockStart; $this->_blockStart = false; $index++; } function addDeletedLine($text, $lineno) { $this->_add($text, $lineno, 'diffdeleted', ' ', '-', 'diffempty'); } function addAddedLine($text, $lineno) { $this->_add(' ', '-', 'diffempty', $text, $lineno, 'diffadded'); } function addChangedLine($text1, $lineno1, $text2, $lineno2) { $this->_add($text1, $lineno1, 'diffchanged', $text2, $lineno2, 'diffchanged'); } // note that $text1 do not need to be equal $text2 if $ignoreWhitespace is true function addLine($text1, $lineno1, $text2, $lineno2) { $this->_add($text1, $lineno1, 'diff', $text2, $lineno2, 'diff'); } function startNewBlock() { $this->_blockStart = true; } function getListing() { return $this->_listing; } } function nextLine(&$obj) { global $arrayBased, $fileBased; if ($arrayBased) return array_shift($obj); if ($fileBased) return fgets($obj); return ''; } function endOfFile(&$obj) { global $arrayBased, $fileBased; if ($arrayBased) return count($obj) == 0; if ($fileBased) return feof($obj); return true; } function getWrappedLineFromFile($file, $is_highlighted) { $line = fgets($file); if ($line === false) return false; $line = toOutputEncoding($line); if (!$is_highlighted) { $line = escape($line); } if (strip_tags($line) === '') $line = ' '; return wrapInCodeTagIfNecessary($line); } function diff_result($all, $highlighted, $newtname, $oldtname, $obj, $ignoreWhitespace) { $ofile = fopen($oldtname, 'r'); $nfile = fopen($newtname, 'r'); // Get the first real line $line = nextLine($obj); $index = 0; $listingHelper = new ListingHelper(); $curoline = 1; $curnline = 1; $sensibleLineChanges = new SensibleLineChanges(new LineDiff($ignoreWhitespace)); while (!endOfFile($obj)) { // Get the first line of this range $oline = 0; sscanf($line, '@@ -%d', $oline); $line = substr($line, strpos($line, '+')); $nline = 0; sscanf($line, '+%d', $nline); while ($curoline < $oline || $curnline < $nline) { if ($curoline < $oline) { $text1 = getWrappedLineFromFile($ofile, $highlighted); $tmpoline = $curoline; $curoline++; } else { $tmpoline = '?'; $text1 = ' '; } if ($curnline < $nline) { $text2 = getWrappedLineFromFile($nfile, $highlighted); $tmpnline = $curnline; $curnline++; } else { $tmpnline = '?'; $text2 = ' '; } if ($all) { $listingHelper->addLine($text1, $tmpoline, $text2, $tmpnline); } } if (!$all && $line !== false) { $listingHelper->startNewBlock(); } $fin = false; while (!endOfFile($obj) && !$fin) { $line = nextLine($obj); if ($line === false || $line === '' || strncmp($line, '@@', 2) == 0) { $sensibleLineChanges->addChangesToListing($listingHelper, $highlighted); $fin = true; } else { $mod = $line{0}; $line = rtrim(substr($line, 1)); switch ($mod) { case '-': $text = getWrappedLineFromFile($ofile, $highlighted); $sensibleLineChanges->addDeletedLine($line, $text, $curoline); $curoline++; break; case '+': $text = getWrappedLineFromFile($nfile, $highlighted); $sensibleLineChanges->addAddedLine($line, $text, $curnline); $curnline++; break; default: $sensibleLineChanges->addChangesToListing($listingHelper, $highlighted); $text1 = getWrappedLineFromFile($ofile, $highlighted); $text2 = getWrappedLineFromFile($nfile, $highlighted); $listingHelper->addLine($text1, $curoline, $text2, $curnline); $curoline++; $curnline++; break; } } if (!$fin) { $index++; } } } $sensibleLineChanges->addChangesToListing($listingHelper, $highlighted); // Output the rest of the files if ($all) { while (!feof($ofile) || !feof($nfile)) { $noneof = false; $text1 = getWrappedLineFromFile($ofile, $highlighted); if ($text1 !== false) { $tmpoline = $curoline; $curoline++; $noneof = true; } else { $tmpoline = '-'; $text1 = ' '; } $text2 = getWrappedLineFromFile($nfile, $highlighted); if ($text2 !== false) { $tmpnline = $curnline; $curnline++; $noneof = true; } else { $tmpnline = '-'; $text2 = ' '; } if ($noneof) { $listingHelper->addLine($text1, $tmpoline, $text2, $tmpnline); } } } fclose($ofile); fclose($nfile); return $listingHelper->getListing(); } function command_diff($all, $ignoreWhitespace, $highlighted, $newtname, $oldtname, $newhlname, $oldhlname) { global $config, $lang, $arrayBased, $fileBased; $context = 5; if ($all) { // Setting the context to 0 makes diff generate the wrong line numbers! $context = 1; } if ($ignoreWhitespace) { $whitespaceFlag = ' -w'; } else { $whitespaceFlag = ''; } // Open a pipe to the diff command with $context lines of context $cmd = quoteCommand($config->diff.$whitespaceFlag.' -U '.$context.' "'.$oldtname.'" "'.$newtname.'"'); $descriptorspec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')); $resource = proc_open($cmd, $descriptorspec, $pipes); $error = ''; if (is_resource($resource)) { // We don't need to write fclose($pipes[0]); $diff = $pipes[1]; // Ignore the 3 header lines $line = fgets($diff); $line = fgets($diff); $arrayBased = false; $fileBased = true; if ($highlighted) { $listing = diff_result($all, $highlighted, $newhlname, $oldhlname, $diff, $ignoreWhitespace); } else { $listing = diff_result($all, $highlighted, $newtname, $oldtname, $diff, $ignoreWhitespace); } fclose($pipes[1]); while (!feof($pipes[2])) { $error .= fgets($pipes[2]); } $error = toOutputEncoding(trim($error)); if (!empty($error)) $error = '
'.$lang['BADCMD'].': '.$cmd.'
'.nl2br($error).'
'; fclose($pipes[2]); proc_close($resource); } else { $error = ''.$lang['BADCMD'].': '.$cmd.'