Merge pull request #1177 from sandermarechal/stream-context

Allow setting stream context options
main
Jordi Boggiano 12 years ago
commit b3077bc4bc

@ -504,8 +504,10 @@ ignored.
The following repository types are supported:
* **composer:** A composer repository is simply a `packages.json` file served
via HTTP, that contains a list of `composer.json` objects with additional
`dist` and/or `source` information.
via the network (HTTP, FTP, SSH), that contains a list of `composer.json`
objects with additional `dist` and/or `source` information. The `packages.json`
file is loaded using a PHP stream. You can set extra options on that stream
using the `options` parameter.
* **vcs:** The version control system repository can fetch packages from git,
svn and hg repositories.
* **pear:** With this you can import any pear repository into your composer
@ -524,6 +526,15 @@ Example:
"type": "composer",
"url": "http://packages.example.com"
},
{
"type": "composer",
"url": "https://packages.example.com",
"options": {
"ssl": {
"verify_peer": "true"
}
}
},
{
"type": "vcs",
"url": "https://github.com/Seldaek/monolog"

@ -148,6 +148,13 @@ hash changed.
This field is optional. You probably don't need it for your own custom
repository.
#### stream options
The `packages.json` file is loaded using a PHP stream. You can set extra options
on that stream using the `options` parameter. You can set any valid PHP stream
context option. See [Context options and parameters](http://nl3.php.net/manual/en/context.php)
for more information.
### VCS
VCS stands for version control system. This includes versioning systems like

@ -85,3 +85,43 @@ itself.
"company/package3": "dev-master"
}
}
### Security
To secure your private repository you can host it over SSH or SSL using a client
certificate. In your project you can use the `options` parameter to specify the
connection options for the server.
Example using a custom repository using SSH (requires the SSH2 PECL extension):
{
"repositories": [
{
"type": "composer",
"url": "ssh2.sftp://example.org",
"options": {
"ssh2": {
"username": "composer",
"pubkey_file": "/home/composer/.ssh/id_rsa.pub",
"privkey_file": "/home/composer/.ssh/id_rsa"
}
}
}
]
}
Example using HTTP over SSL using a client certificate:
{
"repositories": [
{
"type": "composer",
"url": "https://example.org",
"options": {
"ssl": {
"cert_file": "/home/composer/.ssl/composer.pem",
}
}
}
]
}

@ -27,6 +27,7 @@ use Composer\Util\RemoteFilesystem;
class ComposerRepository extends ArrayRepository implements NotifiableRepositoryInterface, StreamableRepositoryInterface
{
protected $config;
protected $options;
protected $url;
protected $io;
protected $cache;
@ -37,7 +38,7 @@ class ComposerRepository extends ArrayRepository implements NotifiableRepository
public function __construct(array $repoConfig, IOInterface $io, Config $config)
{
if (!preg_match('{^\w+://}', $repoConfig['url'])) {
if (!preg_match('{^[\w.]+://}', $repoConfig['url'])) {
// assume http as the default protocol
$repoConfig['url'] = 'http://'.$repoConfig['url'];
}
@ -46,7 +47,12 @@ class ComposerRepository extends ArrayRepository implements NotifiableRepository
throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']);
}
if (!isset($repoConfig['options'])) {
$repoConfig['options'] = array();
}
$this->config = $config;
$this->options = $repoConfig['options'];
$this->url = $repoConfig['url'];
$this->io = $io;
$this->cache = new Cache($io, $config->get('home').'/cache/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url));
@ -199,7 +205,7 @@ class ComposerRepository extends ArrayRepository implements NotifiableRepository
$jsonUrl = $this->url . '/packages.json';
}
$json = new JsonFile($jsonUrl, new RemoteFilesystem($this->io));
$json = new JsonFile($jsonUrl, new RemoteFilesystem($this->io, $this->options));
$data = $json->read();
if (!empty($data['notify'])) {

@ -30,15 +30,17 @@ class RemoteFilesystem
private $result;
private $progress;
private $lastProgress;
private $options;
/**
* Constructor.
*
* @param IOInterface $io The IO instance
*/
public function __construct(IOInterface $io)
public function __construct(IOInterface $io, $options = array())
{
$this->io = $io;
$this->options = $options;
}
/**
@ -241,6 +243,8 @@ class RemoteFilesystem
$options['http']['header'] .= "Authorization: Basic $authStr\r\n";
}
$options = array_replace_recursive($options, $this->options);
return $options;
}
}

@ -47,6 +47,23 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase
$this->assertContains('Authorization: Basic', $options['http']['header']);
}
public function testGetOptionsForUrlWithStreamOptions()
{
$io = $this->getMock('Composer\IO\IOInterface');
$io
->expects($this->once())
->method('hasAuthorization')
->will($this->returnValue(true))
;
$streamOptions = array('ssl' => array(
'allow_self_signed' => true,
));
$res = $this->callGetOptionsForUrl($io, array('https://example.org'), $streamOptions);
$this->assertTrue(isset($res['ssl']) && isset($res['ssl']['allow_self_signed']) && true === $res['ssl']['allow_self_signed'], 'getOptions must return an array with a allow_self_signed set to true');
}
public function testCallbackGetFileSize()
{
$fs = new RemoteFilesystem($this->getMock('Composer\IO\IOInterface'));
@ -102,9 +119,9 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase
unlink($file);
}
protected function callGetOptionsForUrl($io, array $args = array())
protected function callGetOptionsForUrl($io, array $args = array(), array $options = array())
{
$fs = new RemoteFilesystem($io);
$fs = new RemoteFilesystem($io, $options);
$ref = new \ReflectionMethod($fs, 'getOptionsForUrl');
$ref->setAccessible(true);

Loading…
Cancel
Save