Skip to content

Commit

Permalink
Show more details on key before importing (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
theseer committed Feb 1, 2016
1 parent c5a9a77 commit ad445ce
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 36 deletions.
1 change: 1 addition & 0 deletions src/autoload.php
Expand Up @@ -72,6 +72,7 @@ function($class) {
'phario\\phive\\pharservice' => '/services/phar/PharService.php',
'phario\\phive\\phiveversion' => '/shared/PhiveVersion.php',
'phario\\phive\\phivexmlconfig' => '/shared/config/PhiveXmlConfig.php',
'phario\\phive\\publickey' => '/services/key/PublicKey.php',
'phario\\phive\\purgecommand' => '/commands/purge/PurgeCommand.php',
'phario\\phive\\purgecommandconfig' => '/commands/purge/PurgeCommandConfig.php',
'phario\\phive\\release' => '/shared/phar/Release.php',
Expand Down
5 changes: 5 additions & 0 deletions src/services/key/KeyDownloader.php
Expand Up @@ -3,6 +3,11 @@

interface KeyDownloader {

/**
* @param $keyId
*
* @return PublicKey
*/
public function download($keyId);

}
13 changes: 7 additions & 6 deletions src/services/key/KeyService.php
Expand Up @@ -42,9 +42,9 @@ public function __construct(
}

/**
* @param string $keyId
* @param $keyId
*
* @return string
* @return PublicKey
*/
public function downloadKey($keyId) {
$this->output->writeInfo(sprintf('Downloading key %s', $keyId));
Expand All @@ -58,12 +58,13 @@ public function downloadKey($keyId) {
* @return mixed
* @throws VerificationFailedException
*/
public function importKey($keyId, $key) {
if (!$this->input->confirm(sprintf('Import key %s?', $keyId))) {
throw new VerificationFailedException(sprintf('User declined import of key %s', $keyId));
public function importKey(PublicKey $key) {
$this->output->writeText("\n" . $key->getInfo() . "\n\n");
if (!$this->input->confirm('Import this key?')) {
throw new VerificationFailedException(sprintf('User declined import of key %s', $key->getId()));
}

return $this->keyImporter->importKey($key);
return $this->keyImporter->importKey($key->getKeyData());
}

}
103 changes: 103 additions & 0 deletions src/services/key/PublicKey.php
@@ -0,0 +1,103 @@
<?php
namespace PharIo\Phive;

class PublicKey {

/**
* @var string
*/
private $id;

/**
* @var string
*/
private $fingerprint;

/**
* @var array
*/
private $uids = [];

/**
* @var string
*/
private $public;

/**
* @var \DateTime
*/
private $created;

/**
* @var string
*/
private $bits;

/**
* PublicKey constructor.
*
* @param string $id
* @param string $public
* @param string $info
*/
public function __construct($id, $info, $public) {
$this->id = $id;
$this->public = $public;
$this->parseInfo($info);
}

/**
* @return string
*/
public function getId() {
return $this->id;
}

/**
* @return string
*/
public function getInfo() {
$info = [];
$info[] = "\tFingerprint: " . $this->fingerprint;
$info[] = '';
foreach($this->uids as $uid => $time) {
/** @var $time \DateTimeImmutable */
$info[] = sprintf("\t%s (%s)", $uid, $time->format('Y-m-d'));
}
$info[] = '';
$info[] = "\tCreated: " . $this->created->format('Y-m-d');
return join("\n", $info);
}

/**
* @return string
*/
public function getKeyData() {
return $this->public;
}

private function parseInfo($info) {
foreach(explode("\n", $info) as $line) {
$parts = explode(':', $line);
switch($parts[0]) {
default: {
continue;
}
case 'uid': {
// 0 1 2
// uid:Sebastian Bergmann <sebastian@php.net>:1405755775::
$this->uids[$parts[1]] = new \DateTimeImmutable('@' . $parts[2]);
break;
}
case 'pub': {
// 0 1 2 3 4
// pub:D8406D0D82947747293778314AA394086372C20A:1:4096:1405754086::
$this->fingerprint = trim(chunk_split($parts[1], 4, ' '));
$this->bits = $parts[3];
$this->created = new \DateTimeImmutable('@' . $parts[4]);
}
}
}
}

}
36 changes: 26 additions & 10 deletions src/services/key/gpg/GnupgKeyDownloader.php
Expand Up @@ -34,27 +34,43 @@ public function __construct(HttpClient $httpClient, array $keyServers, Cli\Outpu
/**
* @param string $keyId
*
* @return string
* @return PublicKey
* @throws DownloadFailedException
*/
public function download($keyId) {
$params = [
$publicParams = [
'search' => '0x' . $keyId,
'op' => 'get',
'options' => 'mr'
];
$infoParams = array_merge($publicParams, [
'op' => 'index',
'fingerprint' => 'on',
'exact' => 'on'
]);
foreach ($this->keyServers as $keyServer) {
$this->output->writeInfo(sprintf('Trying %s', $keyServer));
$result = $this->httpClient->get(new Url($keyServer . self::PATH), $params);
if ($result->getHttpCode() == 200) {
$this->output->writeInfo('Sucessfully downloaded key');
return $result->getBody();

$keyInfo = $this->httpClient->get(new Url($keyServer . self::PATH), $infoParams);
if ($keyInfo->getHttpCode() != 200) {
$this->output->writeWarning(
sprintf('Failed with status code %s: %s', $keyInfo->getHttpCode(), $keyInfo->getErrorMessage())
);
continue;
}

$publicKey = $this->httpClient->get(new Url($keyServer . self::PATH), $publicParams);
if ($publicKey->getHttpCode() != 200) {
$this->output->writeWarning(
sprintf('Failed with status code %s: %s', $publicKey->getHttpCode(), $publicKey->getErrorMessage())
);
continue;
}
$this->output->writeWarning(
sprintf('Failed with status code %s: %s', $result->getHttpCode(), $result->getErrorMessage())
);

$this->output->writeInfo('Sucessfully downloaded key');
return new PublicKey($keyId, $keyInfo->getBody(), $publicKey->getBody());
}
throw new DownloadFailedException(sprintf('Key %s not found on key servers', $keyId));
throw new DownloadFailedException(sprintf('PublicKey %s not found on key servers', $keyId));
}

}
40 changes: 21 additions & 19 deletions src/services/phar/PharService.php
Expand Up @@ -61,27 +61,29 @@ public function __construct(
* @param RequestedPhar $requestedPhar
* @param string $destination
* @param bool $makeCopy
*
* @return File
* @throws DownloadFailedException
* @throws PharRepositoryException
* @throws VerificationFailedException
*
*/
public function install(RequestedPhar $requestedPhar, $destination, $makeCopy = false) {
$release = $this->getRelease($requestedPhar);

$name = $this->getPharName($release->getUrl());
$version = $this->getPharVersion($release->getUrl());
if (!$this->repository->hasPhar($name, $version)) {
$phar = new Phar($name, $version, $this->downloader->download($release));
$this->repository->addPhar($phar);
} else {
$phar = $this->repository->getPhar($name, $version);
try {
$release = $this->getRelease($requestedPhar);

$name = $this->getPharName($release->getUrl());
$version = $this->getPharVersion($release->getUrl());
if (!$this->repository->hasPhar($name, $version)) {
$phar = new Phar($name, $version, $this->downloader->download($release));
$this->repository->addPhar($phar);
} else {
$phar = $this->repository->getPhar($name, $version);
}
$destination = $destination . '/' . $phar->getName();
$this->installer->install($phar->getFile(), $destination, $makeCopy);
$this->repository->addUsage($phar, $destination);
} catch (DownloadFailedException $e) {
$this->output->writeError($e->getMessage());
} catch (PharRepositoryException $e) {
$this->output->writeError($e->getMessage());
} catch (VerificationFailedException $e) {
$this->output->writeError($e->getMessage());
}
$destination = $destination . '/' . $phar->getName();
$this->installer->install($phar->getFile(), $destination, $makeCopy);
$this->repository->addUsage($phar, $destination);
}

/**
Expand Down Expand Up @@ -116,7 +118,7 @@ private function resolveAlias(PharAlias $alias) {
foreach ($this->aliasResolver->resolve($alias) as $repoUrl) {
try {
$repo = $this->pharIoRepositoryFactory->getRepository($repoUrl);
$releases = $repo->getReleases($alias);
$releases = $repo->getReleasesByAlias($alias);
return $releases->getLatest($alias->getVersionConstraint());
} catch (ResolveException $e) {
$this->output->writeWarning(
Expand Down
1 change: 0 additions & 1 deletion src/services/signature/gpg/GnupgSignatureVerifier.php
Expand Up @@ -37,7 +37,6 @@ public function verify($message, $signature) {
$result = new GnupgVerificationResult($this->gpg->verify($message, $signature)[0]);
if (!$result->wasVerificationSuccessful() && !$result->isKnownKey()) {
$this->keyService->importKey(
$result->getFingerprint(),
$this->keyService->downloadKey($result->getFingerprint())
);
}
Expand Down

0 comments on commit ad445ce

Please sign in to comment.