Initial commit

This commit is contained in:
Christopher Vagnetoft
2016-04-19 15:54:03 +02:00
commit c378d62ccb
20 changed files with 1132 additions and 0 deletions

85
src/Hotfix/Hotfix.php Normal file
View File

@ -0,0 +1,85 @@
<?php
namespace NoccyLabs\Hotfix\Hotfix;
use Symfony\Component\Yaml\Yaml;
class Hotfix
{
protected $signer;
protected $header;
protected $body;
public function __construct($hotfix, $signer)
{
$this->load($hotfix);
$this->signer = $signer;
}
protected function load($hotfix)
{
// echo $hotfix."\n\n";
list ($header, $body) = explode("\n---\n", $hotfix, 2);
$header = Yaml::parse($header);
$this->header = $header;
$this->body = $body;
}
public function apply()
{
if (!array_key_exists('lang', $this->header)) {
$lang = 'bash';
} else {
$lang = strtolower($this->header['lang']);
}
$script = null;
switch ($lang) {
case 'bash':
$exec = "/bin/bash";
break;
case 'php':
$exec = "/usr/bin/env php";
break;
default:
fprintf(STDERR, "Error: Unsupported language %s\n", $lang);
return;
}
$tmpfile = sys_get_temp_dir()."/hotfix_".sha1($this->header['hotfix']);
file_put_contents($tmpfile, $this->body);
passthru($exec." ".$tmpfile);
unlink($tmpfile);
}
public function getSignedBy()
{
if (!$this->signer) {
return null;
}
return sprintf("%s <%s>",
$this->signer['uids'][0]['name'],
$this->signer['uids'][0]['email']
);
}
public function getName()
{
return $this->header['hotfix'];
}
public function getInfo()
{
return $this->header['info'];
}
public function getAuthor()
{
return $this->header['author'];
}
}

67
src/Hotfix/Loader.php Normal file
View File

@ -0,0 +1,67 @@
<?php
namespace NoccyLabs\Hotfix\Hotfix;
class Loader
{
protected $signedBy;
protected $loaders = [];
public function __construct()
{
$this->addLoader(new Loader\FileLoader());
$this->addLoader(new Loader\HttpLoader());
$this->addLoader(new Loader\GistLoader());
$this->addLoader(new Loader\PastebinLoader());
}
public function addLoader(Loader\LoaderInterface $loader)
{
$this->loaders[] = $loader;
}
public function load($fix, $insecure=false)
{
foreach ($this->loaders as $loader) {
$hotfix = $loader->load($fix);
if ($hotfix === false) {
continue;
}
$sigHeader = '-----BEGIN PGP SIGNATURE-----';
if (false === strpos($hotfix, $sigHeader)) {
if (!$insecure) {
throw new \Exception("Hotfix is not signed");
}
$body = $hotfix;
$signer = null;
} else {
list ($body, $signature) = explode($sigHeader, $hotfix);
$signature = $sigHeader.$signature;
$signer = $this->verifySignature($body, $signature);
}
return new Hotfix($body, $signer);
}
fprintf(STDERR, "Error: Couldn't load '%s'", $fix);
}
protected function verifySignature($body, $signature)
{
$gpg = gnupg_init();
$sigInfo = gnupg_verify($gpg, $body, $signature);
if ($sigInfo === false) {
throw new \Exception("Hotfix signature is not valid!");
}
$keyInfo = gnupg_keyinfo($gpg, $sigInfo[0]['fingerprint']);
if (empty($keyInfo)) {
throw new \Exception("Unknown signer (key id {$sigInfo[0]['fingerprint']})");
}
return $keyInfo[0];
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace NoccyLabs\Hotfix\Hotfix\Loader;
class FileLoader implements LoaderInterface
{
public function load($fix)
{
if ($fix[0] !== '/') {
$fix = getcwd()."/".$fix;
}
if (file_exists($fix)) {
$hotfix = file_get_contents($fix);
return $hotfix;
}
return false;
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace NoccyLabs\Hotfix\Hotfix\Loader;
class GistLoader implements LoaderInterface
{
public function load($fix)
{
if (!preg_match('/^gist\:/i', $fix)) {
return false;
}
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace NoccyLabs\Hotfix\Hotfix\Loader;
class HttpLoader implements LoaderInterface
{
public function load($fix)
{
return false;
}
}

View File

@ -0,0 +1,8 @@
<?php
namespace NoccyLabs\Hotfix\Hotfix\Loader;
interface LoaderInterface
{
public function load($fix);
}

View File

@ -0,0 +1,13 @@
<?php
namespace NoccyLabs\Hotfix\Hotfix\Loader;
class PastebinLoader implements LoaderInterface
{
public function load($fix)
{
if (!preg_match('/^pastebin\:/i', $fix)) {
return false;
}
}
}