Skip to content
This repository has been archived by the owner on Mar 15, 2020. It is now read-only.

Commit

Permalink
Add a new SHA256 strategy (#26)
Browse files Browse the repository at this point in the history
- Add new SHA256 strategy
- Deprecate SHA1 strategy
- Switch to SHA256 by default instead of previously SHA1

Closes #22.
  • Loading branch information
padraic authored and theofidry committed May 8, 2017
1 parent 8612ec1 commit 4dae322
Show file tree
Hide file tree
Showing 10 changed files with 369 additions and 98 deletions.
1 change: 0 additions & 1 deletion src/Strategy/GithubStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

class GithubStrategy implements StrategyInterface
{

const API_URL = 'https://packagist.org/packages/%s.json';

const STABLE = 'stable';
Expand Down
62 changes: 62 additions & 0 deletions src/Strategy/Sha256Strategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php
/**
* Humbug
*
* @category Humbug
* @package Humbug
* @copyright Copyright (c) 2017 Pádraic Brady (http://blog.astrumfutura.com)
* @license https://github.com/padraic/phar-updater/blob/master/LICENSE New BSD License
*
* This class is partially patterned after Composer's self-update.
*/

namespace Humbug\SelfUpdate\Strategy;

use Humbug\SelfUpdate\Updater;
use Humbug\SelfUpdate\Exception\HttpRequestException;
use Humbug\SelfUpdate\Exception\InvalidArgumentException;

final class Sha256Strategy extends ShaStrategyAbstract
{
/**
* Retrieve the current version available remotely.
*
* @param Updater $updater
* @return string|bool
*/
public function getCurrentRemoteVersion(Updater $updater)
{
/** Switch remote request errors to HttpRequestExceptions */
set_error_handler(array($updater, 'throwHttpRequestException'));
$version = humbug_get_contents($this->getVersionUrl());
restore_error_handler();
if (false === $version) {
throw new HttpRequestException(sprintf(
'Request to URL failed: %s', $this->getVersionUrl()
));
}
if (empty($version)) {
throw new HttpRequestException(
'Version request returned empty response.'
);
}
if (!preg_match('%^[a-z0-9]{64}%', $version, $matches)) {
throw new HttpRequestException(
'Version request returned incorrectly formatted response.'
);
}

return $matches[0];
}

/**
* Retrieve the current version of the local phar file.
*
* @param Updater $updater
* @return string
*/
public function getCurrentLocalVersion(Updater $updater)
{
return hash_file('sha256', $updater->getLocalPharFile());
}
}
95 changes: 4 additions & 91 deletions src/Strategy/ShaStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,12 @@
use Humbug\SelfUpdate\Exception\HttpRequestException;
use Humbug\SelfUpdate\Exception\InvalidArgumentException;

class ShaStrategy implements StrategyInterface
/**
* @deprecated 1.0.4 SHA-1 is increasingly susceptible to collision attacks; use SHA-256
*/
class ShaStrategy extends ShaStrategyAbstract
{

/**
* @var string
*/
protected $versionUrl;

/**
* @var string
*/
protected $pharUrl;

/**
* Download the remote Phar file.
*
* @param Updater $updater
* @return void
*/
public function download(Updater $updater)
{
/** Switch remote request errors to HttpRequestExceptions */
set_error_handler(array($updater, 'throwHttpRequestException'));
$result = humbug_get_contents($this->getPharUrl());
restore_error_handler();
if (false === $result) {
throw new HttpRequestException(sprintf(
'Request to URL failed: %s', $this->getPharUrl()
));
}

file_put_contents($updater->getTempPharFile(), $result);
}

/**
* Retrieve the current version available remotely.
*
Expand Down Expand Up @@ -91,63 +63,4 @@ public function getCurrentLocalVersion(Updater $updater)
{
return sha1_file($updater->getLocalPharFile());
}

/**
* Set URL to phar file
*
* @param string $url
*/
public function setPharUrl($url)
{
if (!$this->validateAllowedUrl($url)) {
throw new InvalidArgumentException(
sprintf('Invalid url passed as argument: %s.', $url)
);
}
$this->pharUrl = $url;
}

/**
* Get URL for phar file
*
* @return string
*/
public function getPharUrl()
{
return $this->pharUrl;
}

/**
* Set URL to version file
*
* @param string $url
*/
public function setVersionUrl($url)
{
if (!$this->validateAllowedUrl($url)) {
throw new InvalidArgumentException(
sprintf('Invalid url passed as argument: %s.', $url)
);
}
$this->versionUrl = $url;
}

/**
* Get URL for version file
*
* @return string
*/
public function getVersionUrl()
{
return $this->versionUrl;
}

protected function validateAllowedUrl($url)
{
if (filter_var($url, FILTER_VALIDATE_URL)
&& in_array(parse_url($url, PHP_URL_SCHEME), array('http', 'https', 'file'))) {
return true;
}
return false;
}
}
117 changes: 117 additions & 0 deletions src/Strategy/ShaStrategyAbstract.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?php
/**
* Humbug
*
* @category Humbug
* @package Humbug
* @copyright Copyright (c) 2015 Pádraic Brady (http://blog.astrumfutura.com)
* @license https://github.com/padraic/phar-updater/blob/master/LICENSE New BSD License
*
* This class is partially patterned after Composer's self-update.
*/

namespace Humbug\SelfUpdate\Strategy;

use Humbug\SelfUpdate\Updater;
use Humbug\SelfUpdate\Exception\HttpRequestException;
use Humbug\SelfUpdate\Exception\InvalidArgumentException;

abstract class ShaStrategyAbstract implements StrategyInterface
{

/** @private */
const SUPPORTED_SCHEMES = [
'http',
'https',
'file',
];

/**
* @var string
*/
protected $versionUrl;

/**
* @var string
*/
protected $pharUrl;

/**
* Download the remote Phar file.
*
* @param Updater $updater
* @return void
*/
public function download(Updater $updater)
{
/** Switch remote request errors to HttpRequestExceptions */
set_error_handler(array($updater, 'throwHttpRequestException'));
$result = humbug_get_contents($this->getPharUrl());
restore_error_handler();
if (false === $result) {
throw new HttpRequestException(sprintf(
'Request to URL failed: %s', $this->getPharUrl()
));
}

file_put_contents($updater->getTempPharFile(), $result);
}

/**
* Set URL to phar file
*
* @param string $url
*/
public function setPharUrl($url)
{
if (!$this->validateAllowedUrl($url)) {
throw new InvalidArgumentException(
sprintf('Invalid url passed as argument: %s.', $url)
);
}
$this->pharUrl = $url;
}

/**
* Get URL for phar file
*
* @return string
*/
public function getPharUrl()
{
return $this->pharUrl;
}

/**
* Set URL to version file
*
* @param string $url
*/
public function setVersionUrl($url)
{
if (!$this->validateAllowedUrl($url)) {
throw new InvalidArgumentException(
sprintf('Invalid url passed as argument: %s.', $url)
);
}
$this->versionUrl = $url;
}

/**
* Get URL for version file
*
* @return string
*/
public function getVersionUrl()
{
return $this->versionUrl;
}

protected function validateAllowedUrl($url)
{
return (
filter_var($url, FILTER_VALIDATE_URL)
&& in_array(parse_url($url, PHP_URL_SCHEME), self::SUPPORTED_SCHEMES)
);
}
}
23 changes: 19 additions & 4 deletions src/Updater.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
use Humbug\SelfUpdate\Exception\NoSignatureException;
use Humbug\SelfUpdate\Strategy\StrategyInterface;
use Humbug\SelfUpdate\Strategy\ShaStrategy;
use Humbug\SelfUpdate\Strategy\Sha256Strategy;
use Humbug\SelfUpdate\Strategy\GithubStrategy;

class Updater
{

const STRATEGY_SHA1 = 'sha1';

const STRATEGY_SHA256 = 'sha256';

const STRATEGY_GITHUB = 'github';

/**
Expand Down Expand Up @@ -164,6 +166,10 @@ public function setStrategy($strategy)
$this->strategy = new GithubStrategy;
break;

case self::STRATEGY_SHA256:
$this->strategy = new Sha256Strategy;
break;

default:
$this->strategy = new ShaStrategy;
break;
Expand Down Expand Up @@ -348,13 +354,22 @@ protected function downloadPhar()
);
}

if ($this->getStrategy() instanceof ShaStrategy) {
$tmpVersion = sha1_file($this->getTempPharFile());
if ($this->getStrategy() instanceof ShaStrategy
|| $this->getStrategy() instanceof Sha256Strategy
) {
if ($this->getStrategy() instanceof ShaStrategy) {
$tmpVersion = sha1_file($this->getTempPharFile());
$algo = 'SHA-1';
} else {
$tmpVersion = hash_file('sha256', $this->getTempPharFile());
$algo = 'SHA-256';
}
if ($tmpVersion !== $this->getNewVersion()) {
$this->cleanupAfterError();
throw new HttpRequestException(sprintf(
'Download file appears to be corrupted or outdated. The file '
. 'received does not have the expected SHA-1 hash: %s.',
. 'received does not have the expected %s hash: %s.',
$algo,
$this->getNewVersion()
));
}
Expand Down
Loading

0 comments on commit 4dae322

Please sign in to comment.