Add crossdomain file generator command

This commit is contained in:
Nicolas Le Goff
2014-06-10 19:10:41 +02:00
parent 6ee8d2bab3
commit bc88d0f474
10 changed files with 339 additions and 7 deletions

1
.gitignore vendored
View File

@@ -15,3 +15,4 @@ behat.yml
/datas
/www/assets
/www/skins/build
/www/crossdomain.xml

View File

@@ -17,6 +17,7 @@ namespace KonsoleKommander;
* @link www.phraseanet.com
*/
use Alchemy\Phrasea\Command\Plugin\ListPlugin;
use Alchemy\Phrasea\Command\Setup\CrossDomainGenerator;
use Alchemy\Phrasea\Command\Setup\H264ConfigurationDumper;
use Alchemy\Phrasea\Command\Setup\H264MappingGenerator;
use Alchemy\Phrasea\Core\Version;
@@ -104,6 +105,7 @@ $cli->command(new H264ConfigurationDumper());
$cli->command(new H264MappingGenerator());
$cli->command(new XSendFileConfigurationDumper());
$cli->command(new XSendFileMappingGenerator());
$cli->command(new CrossDomainGenerator());
$cli->loadPlugins();

View File

@@ -159,3 +159,29 @@ api_cors:
session:
idle: 0
lifetime: 604800 # 1 week
crossdomain:
site-control: 'master-only'
allow-access-from:
-
domain: '*.example.com'
secure: 'false'
-
domain: 'www.example.com'
secure: 'true'
to-ports: '507,516-523'
allow-access-from-identity:
-
fingerprint-algorithm: 'sha-1'
fingerprint: '01:23:45:67:89:ab:cd:ef:01:23:45:67:89:ab:cd:ef:01:23:45:67'
-
fingerprint-algorithm: 'sha256'
fingerprint: '01:23:45:67:89:ab:cd:ef:01:23:45:67:89:ab:cd:ef:01:23:45:67'
allow-http-request-headers-from:
-
domain: '*.bar.com'
secure: 'true'
headers: 'SOAPAction, X-Foo*'
-
domain: 'foo.example.com'
secure: 'false'
headers: 'Authorization,X-Foo*'

View File

@@ -0,0 +1,45 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2014 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Command\Setup;
use Alchemy\Phrasea\Command\Command;
use Alchemy\Phrasea\Utilities\CrossDomainDumper;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class CrossDomainGenerator extends Command
{
public function __construct($name = null)
{
parent::__construct('crossdomain:generate');
$this->setDescription('Generate crossdomain.xml file according to configuration');
}
/**
* {@inheritdoc}
*/
protected function doExecute(InputInterface $input, OutputInterface $output)
{
$configuration = $this->container['phraseanet.configuration']['crossdomain'];
$dumper = new CrossDomainDumper();
$xml = $dumper->dump($configuration);
$output->writeln($xml);
$this->container['filesystem']->dumpFile($this->container['root.path'].'/www/crossdomain.xml', $xml);
return ;
}
}

View File

@@ -18,7 +18,7 @@ namespace Alchemy\Phrasea\Core;
*/
class Version
{
protected static $number = '3.8.6-alpha.1';
protected static $number = '3.8.6-alpha.2';
protected static $name = 'Falcarius';
public static function getNumber()

View File

@@ -0,0 +1,107 @@
<?php
namespace Alchemy\Phrasea\Utilities;
/** Build crossdomain.xml file according to configuration */
class CrossDomainDumper
{
public function dump(array $configuration)
{
$xml = '<?xml version="1.0"?>'.PHP_EOL;
$xml .= '<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">'.PHP_EOL;
$xml .= '<cross-domain-policy>' . PHP_EOL;
$xml .= $this->getSiteControl($configuration);
$xml .= $this->getAllowAccess($configuration);
$xml .= $this->getAllowIdentity($configuration);
$xml .= $this->getAllowHeader($configuration);
$xml .= "</cross-domain-policy>";
return $xml;
}
private function getSiteControl(array $conf)
{
$xml = '';
if (isset($conf['site-control'])) {
$xml = "\t".'<site-control permitted-cross-domain-policies="'.$conf['site-control'].'"/>'.PHP_EOL;
}
return $xml;
}
private function getAllowAccess(array $conf)
{
$xml = '';
if (!isset($conf['allow-access-from'])) {
return $xml;
}
$allowAccess = $conf['allow-access-from'];
if (!is_array($allowAccess)) {
return $xml;
}
foreach ($allowAccess as $access) {
// domain is mandatory
if (!isset($access['domain'])) {
continue;
}
$domain = $access['domain'];
$secure = isset($access['secure']) ? $access['secure'] : false;
$ports = isset($access['to-ports']) ? $access['to-ports'] : false;
$xml .= "\t".'<allow-access-from domain="'.$domain.'"'. ($ports ? ' to-ports="'.$ports.'"' : '') . ($secure ? ' secure="'.$secure.'"': ''). '/>'.PHP_EOL;
}
return $xml;
}
private function getAllowIdentity(array $conf)
{
$xml = '';
if (!isset($conf['allow-access-from-identity'])) {
return $xml;
}
$allowAccess = $conf['allow-access-from-identity'];
if (!is_array($allowAccess)) {
return $xml;
}
foreach ($allowAccess as $access) {
$algorithm = isset($access['fingerprint-algorithm']) ? $access['fingerprint-algorithm'] : false;
$fingerprint = isset($access['fingerprint']) ? $access['fingerprint'] : false;
// both are mandatory
if (!$algorithm || !$fingerprint) {
continue;
}
$xml .= "\t".'<signatory><certificate fingerprint="'.$fingerprint.'" fingerprint-algorithm="'.$algorithm.'"/></signatory>'.PHP_EOL;
}
return $xml;
}
private function getAllowHeader(array $conf)
{
$xml = '';
if (!isset($conf['allow-http-request-headers-from'])) {
return $xml;
}
$allowHeaders = $conf['allow-http-request-headers-from'];
if (!is_array($allowHeaders)) {
return $xml;
}
foreach ($allowHeaders as $access) {
// domain & headers are mandatory
if (!isset($access['domain']) && !isset($access['headers'])) {
continue;
}
$secure = isset($access['secure']) ? $access['secure'] : false;
$xml .= "\t".'<allow-http-request-headers-from domain="'.$access['domain'].'" headers="'.$access['headers'].'"'. ($secure ? ' secure="'.$secure.'"': '') . '/>'.PHP_EOL;
}
return $xml;
}
}

View File

@@ -0,0 +1,65 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2014 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Alchemy\Phrasea\Application;
class patch_386alpha2a implements patchInterface
{
/** @var string */
private $release = '3.8.6-alpha.2';
/** @var array */
private $concern = array(base::APPLICATION_BOX);
/**
* {@inheritdoc}
*/
public function get_release()
{
return $this->release;
}
/**
* {@inheritdoc}
*/
public function require_all_upgrades()
{
return false;
}
/**
* {@inheritdoc}
*/
public function concern()
{
return $this->concern;
}
/**
* {@inheritdoc}
*/
public function apply(base $appbox, Application $app)
{
$config = $app['phraseanet.configuration']->getConfig();
$config['crossdomain'] = array(
'allow-access-from' => array(
array(
'domain' => '*.cooliris.com',
'secure' => 'false',
)
)
);
$app['phraseanet.configuration']->setConfig($config);
return true;
}
}

View File

@@ -163,3 +163,8 @@ session:
idle: 0
# 1 week
lifetime: 604800
crossdomain:
allow-access-from:
-
domain: '*.cooliris.com'
secure: 'false'

View File

@@ -0,0 +1,87 @@
<?php
namespace Alchemy\Tests\Phrasea\Utilities;
use Alchemy\Phrasea\Utilities\CrossDomainDumper;
class CrossDomainDumperTest extends \PHPUnit_Framework_TestCase
{
/**
* @dataProvider crossDomainProvider
*/
public function testDumper(array $configuration, $expected)
{
$dumper = new CrossDomainDumper();
$this->assertEquals($dumper->dump($configuration), $expected);
}
public function crossDomainProvider()
{
return array(
array(
array(
'site-control' => 'master-only',
'allow-access-from' => array(
array(
'domain'=> '*.example.com',
'secure'=> 'false'
),
array(
'domain'=> 'www.example.com',
'secure'=>'true',
'to-ports'=>'507,516-523'
)
),
'allow-access-from-identity' => array(
array(
'fingerprint-algorithm'=> 'sha-1',
'fingerprint'=> '01:23:45:67:89:ab:cd:ef:01:23:45:67:89:ab:cd:ef:01:23:45:67'
),
array(
'fingerprint-algorithm'=> 'sha256',
'fingerprint' => '01:23:45:67:89:ab:cd:ef:01:23:45:67:89:ab:cd:ef:01:23:45:67'
)
),
'allow-http-request-headers-from' => array(
array(
'domain'=> '*.bar.com',
'secure'=> 'true',
'headers'=> 'SOAPAction, X-Foo*'
),
array(
'domain'=> 'foo.example.com',
'secure'=> 'false',
'headers'=> 'Authorization,X-Foo*'
)
),
),
'<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<site-control permitted-cross-domain-policies="master-only"/>
<allow-access-from domain="*.example.com" secure="false"/>
<allow-access-from domain="www.example.com" to-ports="507,516-523" secure="true"/>
<signatory><certificate fingerprint="01:23:45:67:89:ab:cd:ef:01:23:45:67:89:ab:cd:ef:01:23:45:67" fingerprint-algorithm="sha-1"/></signatory>
<signatory><certificate fingerprint="01:23:45:67:89:ab:cd:ef:01:23:45:67:89:ab:cd:ef:01:23:45:67" fingerprint-algorithm="sha256"/></signatory>
<allow-http-request-headers-from domain="*.bar.com" headers="SOAPAction, X-Foo*" secure="true"/>
<allow-http-request-headers-from domain="foo.example.com" headers="Authorization,X-Foo*" secure="false"/>
</cross-domain-policy>'
),
array(
array(
'allow-access-from' => array(
array(
'domain'=> '*.cooliris.com',
'secure'=> 'false'
)
)
),
'<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*.cooliris.com" secure="false"/>
</cross-domain-policy>'
)
);
}
}

View File

@@ -1,6 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*.cooliris.com" secure="false" />
</cross-domain-policy>