0)) { return $rev; } $rev = strtoupper($rev); if ($rev == 'HEAD' || $rev == 'PREV' || $rev == 'COMMITTED') return $rev; else return 'HEAD'; } // Make sure that we have a repository if ($rep) { $svnrep = new SVNRepository($rep); // Retrieve the request information $path1 = @$_REQUEST['compare'][0]; $path2 = @$_REQUEST['compare'][1]; $rev1 = (int)@$_REQUEST['compare_rev'][0]; $rev2 = (int)@$_REQUEST['compare_rev'][1]; $manualorder = (@$_REQUEST['manualorder'] == 1); $ignoreWhitespace = (@$_REQUEST['ignorews'] == 1); // Some page links put the revision with the path... if (strpos($path1, '@')) { list($path1, $rev1) = explode('@', $path1); } else if (strpos($path1, '@') === 0) { // Something went wrong. The path is missing. $rev1 = substr($path1, 1); $path1 = '/'; } if (strpos($path2, '@')) { list($path2, $rev2) = explode('@', $path2); } else if (strpos($path2, '@') === 0) { $rev2 = substr($path2, 1); $path2 = '/'; } $rev1 = checkRevision($rev1); $rev2 = checkRevision($rev2); // Choose a sensible comparison order unless told not to if (!$manualorder && is_numeric($rev1) && is_numeric($rev2) && $rev1 > $rev2) { $temppath = $path1; $path1 = $path2; $path2 = $temppath; $temprev = $rev1; $rev1 = $rev2; $rev2 = $temprev; } $vars['rev1url'] = $config->getURL($rep, $path1, 'dir').createRevAndPegString($rev1, $rev1); $vars['rev2url'] = $config->getURL($rep, $path2, 'dir').createRevAndPegString($rev2, $rev2); $url = $config->getURL($rep, '', 'comp'); $vars['reverselink'] = ''.$lang['REVCOMP'].''; if (!$ignoreWhitespace) { $vars['ignorewhitespacelink'] = ''.$lang['IGNOREWHITESPACE'].''; } else { $vars['regardwhitespacelink'] = ''.$lang['REGARDWHITESPACE'].''; } if ($rev1 == 0) $rev1 = 'HEAD'; if ($rev2 == 0) $rev2 = 'HEAD'; $vars['repname'] = escape($rep->getDisplayName()); $vars['action'] = $lang['PATHCOMPARISON']; $hidden = ''; if ($config->multiViews) { $hidden .= ''; } else { $hidden .= ''; } $vars['compare_form'] = '
'; // safe paths are a hack for fixing XSS exploit $vars['path1'] = escape($path1); $vars['safepath1'] = escape($path1); $vars['path2'] = escape($path2); $vars['safepath2'] = escape($path2); $vars['rev1'] = $rev1; $vars['rev2'] = $rev2; $history1 = $svnrep->getLog($path1, $rev1, $rev1, false, 1); if (!$history1) { header('HTTP/1.x 404 Not Found', true, 404); $vars['error'] = $lang['NOPATH']; } else { $history2 = $svnrep->getLog($path2, $rev2, $rev2, false, 1); if (!$history2) { header('HTTP/1.x 404 Not Found', true, 404); $vars['error'] = $lang['NOPATH']; } } // Set variables used for the more recent of the two revisions $history = ($rev1 >= $rev2 ? $history1 : $history2); if ($history) { $logEntry = $history->curEntry; $vars['rev'] = $logEntry->rev; $vars['peg'] = $peg; $vars['date'] = $logEntry->date; $vars['age'] = datetimeFormatDuration(time() - strtotime($logEntry->date)); $vars['author'] = $logEntry->author; $vars['log'] = xml_entities($logEntry->msg); } else { $vars['warning'] = 'Problem with comparison.'; } $noinput = empty($path1) || empty($path2); // Generate the diff listing $relativePath1 = $path1; $relativePath2 = $path2; $svnpath1 = encodepath($svnrep->getSvnPath(str_replace(DIRECTORY_SEPARATOR, '/', $path1))); $svnpath2 = encodepath($svnrep->getSvnPath(str_replace(DIRECTORY_SEPARATOR, '/', $path2))); $debug = false; if (!$noinput) { $cmd = $config->getSvnCommand().$rep->svnCredentials().' diff '.($ignoreWhitespace ? '-x "-w --ignore-eol-style" ' : '').quote($svnpath1.'@'.$rev1).' '.quote($svnpath2.'@'.$rev2); } function clearVars() { global $ignoreWhitespace, $listing, $index; if ($ignoreWhitespace && $index > 1) { $endBlock = false; $previous = $index - 1; if ($listing[$previous]['endpath']) $endBlock = 'newpath'; else if ($listing[$previous]['enddifflines']) $endBlock = 'difflines'; if ($endBlock !== false) { // check if block ending at previous contains real diff data $i = $previous; $containsOnlyEqualDiff = true; $addedLines = array(); $removedLines = array(); while ($i >= 0 && !$listing[$i - 1][$endBlock]) { $diffclass = $listing[$i - 1]['diffclass']; if ($diffclass !== 'diffadded' && $diffclass !== 'diffdeleted') { if ($addedLines !== $removedLines) { $containsOnlyEqualDiff = false; break; } } if (count($addedLines) > 0 && $addedLines === $removedLines) { $addedLines = array(); $removedLines = array(); } if ($diffclass === 'diff') { $i--; continue; } if ($diffclass === null) { $containsOnlyEqualDiff = false; break;; } if ($diffclass === 'diffdeleted') { if (count($addedLines) <= count($removedLines)) { $containsOnlyEqualDiff = false; break;; } array_unshift($removedLines, $listing[$i - 1]['line']); $i--; continue; } if ($diffclass === 'diffadded') { if (count($removedLines) > 0) { $containsOnlyEqualDiff = false; break;; } array_unshift($addedLines, $listing[$i - 1]['line']); $i--; continue; } assert(false); } if ($containsOnlyEqualDiff) { $containsOnlyEqualDiff = $addedLines === $removedLines; } // remove blocks which only contain diffclass=diff and equal removes and adds if ($containsOnlyEqualDiff) { for ($j = $i - 1; $j < $index; $j++) { unset($listing[$j]); } $index = $i - 1; } } } $listing[$index]['newpath'] = null; $listing[$index]['endpath'] = null; $listing[$index]['info'] = null; $listing[$index]['diffclass'] = null; $listing[$index]['difflines'] = null; $listing[$index]['enddifflines'] = null; $listing[$index]['properties'] = null; } $vars['success'] = false; if (!$noinput) { // TODO: Report warning/error if comparison encounters any problems if ($diff = popenCommand($cmd, 'r')) { $listing = array(); $index = 0; $indiff = false; $indiffproper = false; $getLine = true; $node = null; $bufferedLine = false; $vars['success'] = true; while (!feof($diff)) { if ($getLine) { if ($bufferedLine === false) { $bufferedLine = rtrim(fgets($diff), "\r\n"); } $newlineR = strpos($bufferedLine, "\r"); $newlineN = strpos($bufferedLine, "\n"); if ($newlineR === false && $newlineN === false) { $line = $bufferedLine; $bufferedLine = false; } else { $newline = ($newlineR < $newlineN ? $newlineR : $newlineN); $line = substr($bufferedLine, 0, $newline); $bufferedLine = substr($bufferedLine, $newline + 1); } } clearVars(); $getLine = true; if ($debug) print 'Line = "'.$line.'"