/** * Render a response object. */ function render($output_body = true) { $this->outputHeaders(); if ($output_body) { $manifest = $this->stdio->exec(array('get_manifest_of', $this->revision)); $stanzas = IDF_Scm_Monotone_BasicIO::parse($manifest); $zip = new ZipStream(); foreach ($stanzas as $stanza) { if ($stanza[0]['key'] != 'file') { continue; } $content = $this->stdio->exec(array('get_file', $stanza[1]['hash'])); $zip->add_file($stanza[0]['values'][0], $content); } $zip->finish(); } }
/** * Removes the (monotone) key from all monotone projects of this forge * where the user of the key has write access to */ public function processKeyDelete($key) { try { if ($key->getType() != 'mtn') { return; } } catch (Exception $e) { // bad key type, skip it. return; } if (Pluf::f('mtn_db_access', 'local') == 'local') { return; } foreach (Pluf::factory('IDF_Project')->getList() as $project) { $conf = new IDF_Conf(); $conf->setProject($project); $scm = $conf->getVal('scm', 'mtn'); if ($scm != 'mtn') { continue; } $projectpath = self::_get_project_path($project); $auth_ids = self::_get_authorized_user_ids($project); if (!in_array($key->user, $auth_ids)) { continue; } $mtn_key_id = $key->getMtnId(); // if the project is not defined as private, all people have // read access already, so we don't need to write anything // and we currently do not check if read-permissions really // contains // pattern "*" // allow "*" // which is the default for non-private projects if ($project->private) { $read_perms = file_get_contents($projectpath . '/read-permissions'); $parsed_read_perms = array(); try { $parsed_read_perms = IDF_Scm_Monotone_BasicIO::parse($read_perms); } catch (Exception $e) { throw new IDF_Scm_Exception(sprintf(__('Could not parse read-permissions for project "%s": %s'), $shortname, $e->getMessage())); } // while we add new keys only to an existing wild-card entry // we remove dropped keys from all sections since the key // should be simply unavailable for all of them for ($h = 0; $h < count($parsed_read_perms); ++$h) { for ($i = 0; $i < count($parsed_read_perms[$h]); ++$i) { if ($parsed_read_perms[$h][$i]['key'] == 'allow' && $parsed_read_perms[$h][$i]['values'][0] == $mtn_key_id) { unset($parsed_read_perms[$h][$i]); continue; } } } $read_perms = IDF_Scm_Monotone_BasicIO::compile($parsed_read_perms); if (file_put_contents($projectpath . '/read-permissions', $read_perms, LOCK_EX) === false) { throw new IDF_Scm_Exception(sprintf(__('Could not write read-permissions for project "%s"'), $shortname)); } } $write_perms = file_get_contents($projectpath . '/write-permissions'); $lines = preg_split("/(\n|\r\n)/", $write_perms, -1, PREG_SPLIT_NO_EMPTY); for ($i = 0; $i < count($lines); ++$i) { if ($lines[$i] == $mtn_key_id) { unset($lines[$i]); // the key should actually only exist once in the // file, but we're paranoid continue; } } if (file_put_contents($projectpath . '/write-permissions', implode("\n", $lines) . "\n", LOCK_EX) === false) { throw new IDF_Scm_Exception(sprintf(__('Could not write write-permissions file for project "%s"'), $shortname)); } $mtn = IDF_Scm_Monotone::factory($project); $stdio = $mtn->getStdio(); // if the public key did not sign any revisions, drop it from // the database as well try { if (strlen($stdio->exec(array('select', 'k:' . $mtn_key_id))) == 0) { $stdio->exec(array('drop_public_key', $mtn_key_id)); } } catch (IDF_Scm_Exception $e) { if (strpos($e->getMessage(), 'there is no key named') === false) { throw $e; } } } }
private static function _triggerCommand($cmd) { $uc = Pluf::f('mtn_usher_conf', false); if (!$uc || !is_readable($uc)) { throw new IDF_Scm_Exception('"mtn_usher_conf" is not configured or not readable'); } $parsed_config = IDF_Scm_Monotone_BasicIO::parse(file_get_contents($uc)); $host = $port = $user = $pass = null; foreach ($parsed_config as $stanza) { foreach ($stanza as $line) { if ($line['key'] == 'adminaddr') { list($host, $port) = explode(":", @$line['values'][0]); break; } if ($line['key'] == 'userpass') { $user = @$line['values'][0]; $pass = @$line['values'][1]; } } } if (empty($host)) { throw new IDF_Scm_Exception('usher host is empty'); } if (!preg_match('/^\\d+$/', $port)) { throw new IDF_Scm_Exception('usher port is invalid'); } if (empty($user)) { throw new IDF_Scm_Exception('usher user is empty'); } if (empty($pass)) { throw new IDF_Scm_Exception('usher pass is empty'); } $sock = @fsockopen($host, $port, $errno, $errstr); if (!$sock) { throw new IDF_Scm_Exception("could not connect to usher: {$errstr} ({$errno})"); } fwrite($sock, 'USERPASS ' . $user . ' ' . $pass . "\n"); if (feof($sock)) { throw new IDF_Scm_Exception('usher closed the connection - this should not happen'); } fwrite($sock, $cmd . "\n"); $out = ''; while (!feof($sock)) { $out .= fgets($sock); } fclose($sock); $out = rtrim($out); if ($out == 'unknown command') { throw new IDF_Scm_Exception('unknown command: ' . $cmd); } return $out; }
/** * @see IDF_Scm::isCommitLarge() */ public function isCommitLarge($commit = null) { if (empty($commit)) { $commit = 'h:' . $this->getMainBranch(); } $revs = $this->_resolveSelector($commit); if (count($revs) == 0) { return false; } $out = $this->stdio->exec(array('get_revision', $revs[0])); $newAndPatchedFiles = 0; $stanzas = IDF_Scm_Monotone_BasicIO::parse($out); foreach ($stanzas as $stanza) { if ($stanza[0]['key'] == 'patch' || $stanza[0]['key'] == 'add_file') { $newAndPatchedFiles++; } } return $newAndPatchedFiles > 100; }