logsShowChanges(); $search = trim(@$_REQUEST['search']); $dosearch = strlen($search) > 0; $words = preg_split('#\s+#', $search); $fromRev = (int)@$_REQUEST['fr']; $startrev = strtoupper(trim(@$_REQUEST['sr'])); $endrev = strtoupper(trim(@$_REQUEST['er'])); $max = isset($_REQUEST['max']) ? (int)$_REQUEST['max'] : false; // Max number of results to find at a time $numSearchResults = 20; if ($search == '') { $dosearch = false; } // removeAccents // // Remove all the accents from a string. This function doesn't seem // ideal, but expecting everyone to install 'unac' seems a little // excessive as well... function removeAccents($string) { $string = htmlentities($string, ENT_QUOTES, 'ISO-8859-1'); $string = preg_replace('/&([A-Za-z])(acute|uml|circ|grave|ring|cedil|slash|tilde|caron);/', '$1', $string); return $string; } // Normalise the search words foreach ($words as $index => $word) { $words[$index] = strtolower(removeAccents($word)); // Remove empty string introduced by multiple spaces if (empty($words[$index])) unset($words[$index]); } if (empty($page)) $page = 1; // If searching, display all the results if ($dosearch) $all = true; $maxperpage = 20; // Make sure that we have a repository if ($rep) { $svnrep = new SVNRepository($rep); $history = $svnrep->getLog($path, 'HEAD', '', false, 1, ($path == '/') ? '' : $peg); if (!$history) { unset($vars['error']); $history = $svnrep->getLog($path, '', '', false, 1, ($path == '/') ? '' : $peg); if (!$history) { header('HTTP/1.x 404 Not Found', true, 404); $vars['error'] = $lang['NOPATH']; } } $youngest = ($history && isset($history->entries[0])) ? $history->entries[0]->rev : 0; if (empty($startrev)) { //$startrev = ($rev) ? $rev : 'HEAD'; $startrev = $rev; } else if ($startrev != 'HEAD' && $startrev != 'BASE' && $startrev != 'PREV' && $startrev != 'COMMITTED') { $startrev = (int)$startrev; } if (empty($endrev)) { $endrev = 1; } else if ($endrev != 'HEAD' && $endrev != 'BASE' && $endrev != 'PREV' && $endrev != 'COMMITTED') { $endrev = (int)$endrev; } if (empty($rev)) { $rev = $youngest; } if (empty($startrev)) { $startrev = $rev; } // make sure path is prefixed by a / $ppath = $path; if ($path == '' || $path{0} != '/') { $ppath = '/'.$path; } $vars['action'] = $lang['LOG']; $vars['rev'] = $rev; $vars['peg'] = $peg; $vars['path'] = escape($ppath); if ($history && isset($history->entries[0])) { $vars['log'] = xml_entities($history->entries[0]->msg); $vars['date'] = $history->entries[0]->date; $vars['age'] = datetimeFormatDuration(time() - strtotime($history->entries[0]->date)); $vars['author'] = $history->entries[0]->author; } if ($max === false) { $max = ($dosearch) ? 0 : 40; } else if ($max < 0) { $max = 40; } // TODO: If the rev is less than the head, get the path (may have been renamed!) // Will probably need to call `svn info`, parse XML output, and substring a path createPathLinks($rep, $ppath, $passrev, $peg); $passRevString = createRevAndPegString($rev, $peg); $isDirString = ($isDir) ? 'isdir=1&' : ''; unset($queryParams['repname']); unset($queryParams['path']); // Toggle 'showchanges' param for link to switch from the current behavior if ($showchanges == $rep->logsShowChanges()) $queryParams['showchanges'] = (int)!$showchanges; else unset($queryParams['showchanges']); $vars['changesurl'] = $config->getURL($rep, $path, 'log').buildQuery($queryParams); $vars['changeslink'] = ''.$lang[($showchanges ? 'HIDECHANGED' : 'SHOWCHANGED')].''; $vars['showchanges'] = $showchanges; // Revert 'showchanges' param to propagate the current behavior if ($showchanges == $rep->logsShowChanges()) unset($queryParams['showchanges']); else $queryParams['showchanges'] = (int)$showchanges; $vars['revurl'] = $config->getURL($rep, $path, 'revision').$isDirString.$passRevString; if ($isDir) { $vars['directoryurl'] = $config->getURL($rep, $path, 'dir').$passRevString.'#'.anchorForPath($path); $vars['directorylink'] = ''.$lang['LISTING'].''; } else { $vars['filedetailurl'] = $config->getURL($rep, $path, 'file').$passRevString; $vars['filedetaillink'] = ''.$lang['FILEDETAIL'].''; $vars['blameurl'] = $config->getURL($rep, $path, 'blame').$passRevString; $vars['blamelink'] = ''.$lang['BLAME'].''; $vars['diffurl'] = $config->getURL($rep, $path, 'diff').$passRevString; $vars['difflink'] = ''.$lang['DIFFPREV'].''; } if ($rep->isRssEnabled()) { $vars['rssurl'] = $config->getURL($rep, $path, 'rss').$isDirString.createRevAndPegString('', $peg); $vars['rsslink'] = ''.$lang['RSSFEED'].''; } if ($rev != $youngest) { if ($path == '/') { $vars['goyoungesturl'] = $config->getURL($rep, '', 'log').$isDirString; } else { $vars['goyoungesturl'] = $config->getURL($rep, $path, 'log').$isDirString.'peg='.($peg ? $peg : $rev); } $vars['goyoungestlink'] = ''.$lang['GOYOUNGEST'].''; } // We get the bugtraq variable just once based on the HEAD $bugtraq = new Bugtraq($rep, $svnrep, $ppath); $vars['logsearch_moreresultslink'] = ''; $vars['pagelinks'] = ''; $vars['showalllink'] = ''; if ($history) { $history = $svnrep->getLog($path, $startrev, $endrev, true, $max, $peg); if (empty($history)) { unset($vars['error']); $vars['warning'] = 'Revision '.$startrev.' of this resource does not exist.'; } } if (!empty($history)) { // Get the number of separate revisions $revisions = count($history->entries); if ($all) { $firstrevindex = 0; $lastrevindex = $revisions - 1; $pages = 1; } else { // Calculate the number of pages $pages = floor($revisions / $maxperpage); if (($revisions % $maxperpage) > 0) $pages++; if ($page > $pages) $page = $pages; // Work out where to start and stop $firstrevindex = ($page - 1) * $maxperpage; $lastrevindex = min($firstrevindex + $maxperpage - 1, $revisions - 1); } $frev = isset($history->entries[0]) ? $history->entries[0]->rev : false; $brev = isset($history->entries[$firstrevindex]) ? $history->entries[$firstrevindex]->rev : false; $erev = isset($history->entries[$lastrevindex]) ? $history->entries[$lastrevindex]->rev : false; $entries = array(); if ($brev && $erev) { $history = $svnrep->getLog($path, $brev, $erev, false, 0, $peg); if ($history) $entries = $history->entries; } $row = 0; $index = 0; $found = false; foreach ($entries as $revision) { // Assume a good match $match = true; $thisrev = $revision->rev; // Check the log for the search words, if searching if ($dosearch) { if ((empty($fromRev) || $fromRev > $thisrev)) { // Turn all the HTML entities into real characters. // Make sure that each word in the search in also in the log foreach ($words as $word) { if (strpos(strtolower(removeAccents($revision->msg)), $word) === false && strpos(strtolower(removeAccents($revision->author)), $word) === false) { $match = false; break; } } if ($match) { $numSearchResults--; $found = true; } } else { $match = false; } } $thisRevString = createRevAndPegString($thisrev, ($peg ? $peg : $thisrev)); if ($match) { // Add the trailing slash if we need to (svnlook history doesn't return trailing slashes!) $rpath = $revision->path; if (empty($rpath)) { $rpath = '/'; } else if ($isDir && $rpath{strlen($rpath) - 1} != '/') { $rpath .= '/'; } $precisePath = $revision->precisePath; if (empty($precisePath)) { $precisePath = '/'; } else if ($isDir && $precisePath{strlen($precisePath) - 1} != '/') { $precisePath .= '/'; } // Find the parent path (or the whole path if it's already a directory) $pos = strrpos($rpath, '/'); $parent = substr($rpath, 0, $pos + 1); $compareValue = (($isDir) ? $parent : $rpath).'@'.$thisrev; $listing[$index]['compare_box'] = ''; $url = $config->getURL($rep, $rpath, 'revision').$thisRevString; $listing[$index]['revlink'] = ''.$thisrev.''; $url = $config->getURL($rep, $precisePath, ($isDir ? 'dir' : 'file')).$thisRevString; $listing[$index]['revpathlink'] = ''.$precisePath.''; $listing[$index]['revpath'] = $precisePath; $listing[$index]['revauthor'] = $revision->author; $listing[$index]['revdate'] = $revision->date; $listing[$index]['revage'] = $revision->age; $listing[$index]['revlog'] = nl2br($bugtraq->replaceIDs(create_anchors(xml_entities($revision->msg)))); $listing[$index]['rowparity'] = $row; $listing[$index]['compareurl'] = $config->getURL($rep, '', 'comp').'compare[]='.$rpath.'@'.($thisrev - 1).'&compare[]='.$rpath.'@'.$thisrev; if ($showchanges) { // Aggregate added/deleted/modified paths for display in table $modpaths = array(); foreach ($revision->mods as $mod) { $modpaths[$mod->action][] = $mod->path; } ksort($modpaths); foreach ($modpaths as $action => $paths) { sort($paths); $modpaths[$action] = $paths; } $listing[$index]['revadded'] = (isset($modpaths['A'])) ? implode('
', $modpaths['A']) : ''; $listing[$index]['revdeleted'] = (isset($modpaths['D'])) ? implode('
', $modpaths['D']) : ''; $listing[$index]['revmodified'] = (isset($modpaths['M'])) ? implode('
', $modpaths['M']) : ''; } $row = 1 - $row; $index++; } // If we've reached the search limit, stop here... if (!$numSearchResults) { $url = $config->getURL($rep, $path, 'log').$isDirString.$thisRevString; $vars['logsearch_moreresultslink'] = ''.$lang['MORERESULTS'].''; break; } } $vars['logsearch_resultsfound'] = true; if ($dosearch && !$found) { if ($fromRev == 0) { $vars['logsearch_nomatches'] = true; $vars['logsearch_resultsfound'] = false; } else { $vars['logsearch_nomorematches'] = true; } } else if ($dosearch && $numSearchResults > 0) { $vars['logsearch_nomorematches'] = true; } // Work out the paging options, create links to pages of results if ($pages > 1) { $prev = $page - 1; $next = $page + 1; unset($queryParams['page']); $logurl = $config->getURL($rep, $path, 'log').buildQuery($queryParams); if ($page > 1) { $vars['pagelinks'] .= '←'.$lang['PREV'].''; } else { $vars['pagelinks'] .= '←'.$lang['PREV'].''; } for ($p = 1; $p <= $pages; $p++) { if ($p != $page) { $vars['pagelinks'] .= ''.$p.''; } else { $vars['pagelinks'] .= ''.$p.''; } } if ($page < $pages) { $vars['pagelinks'] .= ''.$lang['NEXT'].'→'; } else { $vars['pagelinks'] .= ''.$lang['NEXT'].'→'; } $vars['showalllink'] = ''.$lang['SHOWALL'].''; } } // Create form elements for filtering and searching log messages if ($config->multiViews) { $hidden = ''; } else { $hidden = ''; $hidden .= ''; } if ($isDir) $hidden .= ''; if ($peg) $hidden .= ''; if ($showchanges != $rep->logsShowChanges()) $hidden .= ''; $vars['logsearch_form'] = ''; // If a filter is in place, produce a link to clear all filter parameters if ($page !== 1 || $all || $dosearch || $fromRev || $startrev !== $rev || $endrev !== 1 || $max !== 40) { $url = $config->getURL($rep, $path, 'log').$isDirString.$passRevString; $vars['logsearch_clearloglink'] = ''.$lang['CLEARLOG'].''; } // Create form elements for comparing selected revisions $vars['compare_form'] = '
'; if ($config->multiViews) { $vars['compare_form'] .= ''; } else { $vars['compare_form'] .= ''; } $vars['compare_submit'] = ''; $vars['compare_endform'] = '
'; if (!$rep->hasReadAccess($path, false)) { $vars['error'] = $lang['NOACCESS']; checkSendingAuthHeader($rep); } } else { header('HTTP/1.x 404 Not Found', true, 404); } renderTemplate('log');