function runCommand($cmd, $mayReturnNothing = false) { global $lang; $output = array(); $err = false; $c = quoteCommand($cmd); $descriptorspec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')); $resource = proc_open($c, $descriptorspec, $pipes); $error = ''; if (!is_resource($resource)) { echo '<p>' . $lang['BADCMD'] . ': <code>' . stripCredentialsFromCommand($cmd) . '</code></p>'; exit; } $handle = $pipes[1]; $firstline = true; while (!feof($handle)) { $line = fgets($handle); if ($firstline && empty($line) && !$mayReturnNothing) { $err = true; } $firstline = false; $output[] = toOutputEncoding(rtrim($line)); } while (!feof($pipes[2])) { $error .= fgets($pipes[2]); } $error = toOutputEncoding(trim($error)); fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($resource); if (!$err) { return $output; } else { echo '<p>' . $lang['BADCMD'] . ': <code>' . stripCredentialsFromCommand($cmd) . '</code></p><p>' . nl2br($error) . '</p>'; } }
function command_diff($all, $ignoreWhitespace, $ent, $newtname, $oldtname) { global $config, $lang, $arrayBased, $fileBased; $context = 5; if ($all) { // Setting the context to 0 makes diff generate the wrong line numbers! $context = 1; } // Open a pipe to the diff command with $context lines of context $cmd = quoteCommand($config->diff . ' -w -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; $listing = diff_result($all, $ent, $newtname, $oldtname, $diff); fclose($pipes[1]); while (!feof($pipes[2])) { $error .= fgets($pipes[2]); } $error = toOutputEncoding(trim($error)); if (!empty($error)) { $error = '<p>' . $lang['BADCMD'] . ': <code>' . $cmd . '</code></p><p>' . nl2br($error) . '</p>'; } fclose($pipes[2]); proc_close($resource); } else { $error = '<p>' . $lang['BADCMD'] . ': <code>' . $cmd . '</code></p>'; } if (!empty($error)) { echo $error; if (is_resource($resource)) { fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($resource); } exit; } return $listing; }
function getLog($path, $brev = '', $erev = 1, $quiet = false, $limit = 2, $peg = '') { global $config, $curLog; $xml_parser = xml_parser_create('UTF-8'); xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true); xml_set_element_handler($xml_parser, 'logStartElement', 'logEndElement'); xml_set_character_data_handler($xml_parser, 'logCharacterData'); // Since directories returned by svn log don't have trailing slashes (:-(), // we must remove the trailing slash from the path for comparison purposes. if ($path != '/' && $path[strlen($path) - 1] == '/') { $path = substr($path, 0, -1); } $curLog = new SVNLog(); $curLog->entries = array(); $curLog->path = $path; $revStr = ''; if ($brev && $erev) { $revStr = '-r' . $brev . ':' . $erev; } else { if ($brev) { $revStr = '-r' . $brev . ':1'; } } if (($config->subversionMajorVersion > 1 || $config->subversionMinorVersion >= 2) && $limit != 0) { $revStr .= ' --limit ' . $limit; } // Get the log info $path = encodepath($this->getSvnPath($path)); $info = '--verbose'; if ($quiet) { $info = '--quiet'; } if ($peg) { $pegrev = '@' . $peg; } else { if ($brev) { $pegrev = '@' . $brev; } else { $pegrev = ''; } } $cmd = quoteCommand($config->getSvnCommand() . ' log --xml ' . $info . ' ' . $revStr . ' ' . $this->repConfig->svnParams() . quote($path . $pegrev)); $descriptorspec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')); $resource = proc_open($cmd, $descriptorspec, $pipes); if (!is_resource($resource)) { global $lang; echo $lang['BADCMD'] . ': <br/><br/><code>' . stripCredentialsFromCommand($cmd) . '</code>'; exit; } $handle = $pipes[1]; $firstline = true; while (!feof($handle)) { $line = fgets($handle); if (!xml_parse($xml_parser, $line, feof($handle))) { $errorMsg = sprintf('XML error: %s (%d) at line %d column %d byte %d' . "\n" . 'cmd: %s', xml_error_string(xml_get_error_code($xml_parser)), xml_get_error_code($xml_parser), xml_get_current_line_number($xml_parser), xml_get_current_column_number($xml_parser), xml_get_current_byte_index($xml_parser), $cmd); if (xml_get_error_code($xml_parser) != 5) { // errors can contain sensitive info! don't echo this ~J error_log($errorMsg); exit; } else { break; } } } $error = ''; while (!feof($pipes[2])) { $error .= fgets($pipes[2]); } $error = trim($error); fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($resource); if (!empty($error)) { $error = toOutputEncoding(nl2br(str_replace('svn: ', '', $error))); global $lang; error_log($lang['BADCMD'] . ': ' . $cmd); error_log($error); global $vars; if (strstr($error, 'found format')) { $vars['error'] = 'Repository uses a newer format than Subversion ' . $config->getSubversionVersion() . ' can read. ("' . substr($error, strrpos($error, 'Expected')) . '.")'; } else { if (strstr($error, 'No such revision')) { $vars['warning'] = 'Revision ' . $brev . ' of this resource does not exist.'; } else { $vars['error'] = $lang['BADCMD'] . ':<br/><br/><code>' . stripCredentialsFromCommand($cmd) . '</code><br/><br/>' . nl2br($error); } } return null; } xml_parser_free($xml_parser); foreach ($curLog->entries as $entryKey => $entry) { $fullModAccess = true; $anyModAccess = count($entry->mods) == 0; foreach ($entry->mods as $modKey => $mod) { $access = $this->repConfig->hasReadAccess($mod->path); if ($access) { $anyModAccess = true; } else { // hide modified entry when access is prohibited unset($curLog->entries[$entryKey]->mods[$modKey]); $fullModAccess = false; } } if (!$fullModAccess) { // hide commit message when access to any of the entries is prohibited $curLog->entries[$entryKey]->msg = ''; } if (!$anyModAccess) { // hide author and date when access to all of the entries is prohibited $curLog->entries[$entryKey]->author = ''; $curLog->entries[$entryKey]->date = ''; $curLog->entries[$entryKey]->committime = ''; $curLog->entries[$entryKey]->age = ''; } } return $curLog; }