Skip to content
Snippets Groups Projects
Commit 825f322e authored by Patrick Barroca's avatar Patrick Barroca :grin:
Browse files

hotline #76805 : handle https in cms url transformer

parent e954ca77
Branches
Tags
3 merge requests!2723Master,!2721Hotline,!2719hotline #76805 : handle https in cms url transformer
Pipeline #4507 passed with stage
in 37 minutes and 37 seconds
- ticket #76805 : Articles : Respect du https dans les URL d'images lors de la modification d'un article
\ No newline at end of file
......@@ -1389,9 +1389,10 @@ class Class_Article extends Storm_Model_Abstract {
$this->$date_field = $attributes[$date_field] = ($this->_toDate($attributes[$date_field]));
}
$transformer = new Class_CmsUrlTransformer();
foreach(['description', 'contenu'] as $content_field) {
if (array_key_exists($content_field, $attributes))
$attributes[$content_field] = Class_CmsUrlTransformer::forSaving($attributes[$content_field]);
$attributes[$content_field] = $transformer->forSaving($attributes[$content_field]);
}
if(isset($attributes['pick_day']) && is_array($attributes['pick_day']))
......
......@@ -19,119 +19,137 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Helper utilisé pour transformUrlForSaving et transformUrlForEditing dans le CMS
*/
class Class_CmsUrlTransformer {
/*
* Utilisé pour corriger les URL sur les images dans l'édition
* du CMS
* Si dans le CMS on fait un copier/coller des images, selon le navigateur
* l'url d'origine n'est pas conservée.
* à l'édition on passe donc on URL absolu.
*/
public static function forEditing($content) {
return static::imgUrlRelativeToAbsolute($content);
protected $_hostname, $_basedir;
public function __construct($hostname='', $basedir='') {
$this->_hostname = $hostname;
$this->_basedir = $basedir;
}
protected function _canRemove() {
return '' !== $this->_hostname;
}
public function forEditing($content) {
return $this->imgUrlRelativeToAbsolute($content);
}
public static function imgUrlRelativeToAbsolute($content) {
public function imgUrlRelativeToAbsolute($content) {
return isset($_SERVER['HTTP_HOST'])
? preg_replace('/(< *img[^>]*src *= *["\']?)\/([^"\']*)/i',
'$1http://'.$_SERVER['HTTP_HOST'].'/$2',
'$1'. Class_Url::getProtocol() . $_SERVER['HTTP_HOST'].'/$2',
$content)
: $content;
}
/*
* A la sauvegarde de l'article, on passe les URL des images
* en relatif depuis la racine du site
*/
public static function forSaving($content) {
//voir les tests unitaires pour comprendre la regex
public function forSaving($content) {
return $this->imgUrlAbsoluteToRelative($content);
}
/** @see unit tests for regexp cases */
public function imgUrlAbsoluteToRelative($content) {
$re_base_url = str_replace('/', '\/', Class_Url::baseUrl());
$rel = preg_replace('/(< *img[^>]*src *= *["\']?)(http:\/\/'.$_SERVER['HTTP_HOST'].')?('.$re_base_url.')+([^"\']*)/i',
'$1$4',
$rel = preg_replace('/(< *img[^>]*src *= *["\']?)' . $this->_hostRegex($_SERVER['HTTP_HOST']) . '('.$re_base_url.')+([^"\']*)/i',
'$1$5',
$content);
return preg_replace('/(< *img[^>]*src *= *["\']?)[\.\.\/]+([^"\']*)/i',
'$1'. Class_Url::baseUrl() .'/$2',
$rel);
}
public static function removeHostFromArray($hostname,$basedir, $contents, &$replace_count = null) {
if (is_array($contents)) {
foreach ($contents as $index => $content) {
$contents[$index] = static::removeHostFromArray($hostname,$basedir, $content, $replace_count);
}
public function removeHostFromArray($contents, &$replace_count = null) {
if (!$this->_canRemove())
return $contents;
}
return static::removeHost($hostname,$basedir, $contents, $replace_count);
if (!is_array($contents))
return $this->removeHost($contents, $replace_count);
foreach ($contents as $index => $content)
$contents[$index] = $this->removeHostFromArray($content, $replace_count);
return $contents;
}
public static function removeHost($hostname,$basedir, $content, &$replace_count = null) {
public function removeHost($content, &$replace_count = null) {
if (!$this->_canRemove())
return $content;
$content = static::removeHostFromHtml($hostname,$basedir, $content, $count);
$content = $this->removeHostFromHtml($content, $count);
$replace_count = $count;
$content = static::removeHostFromUrl($hostname,$basedir, $content, $count);
$content = $this->removeHostFromUrl($content, $count);
$replace_count += $count;
return $content;
}
public static function removeHostFromHtml($hostname,$basedir, $content, &$replace_count = null) {
$hosts = ['web.afi-sa.net',
'opac3.pergame.net',
'www.'.$basedir,
'www.'.$hostname,
$hostname];
$regs = [];
foreach($hosts as $host) {
$regs []= '/(< *(a|img)[^>]*(href|src) *= *["\'])((http:\/\/)?' . $host. ')?(\/'.$basedir.')?(\/[^"\']*)/i';
}
public function removeHostFromHtml($content, &$replace_count = null) {
if (!$this->_canRemove())
return $content;
$mapper = function($host) {
return '/(< *(a|img)[^>]*(href|src) *= *["\'])' . $this->_hostRegex($host) . '(\/'.$this->_basedir.')?(\/[^"\']*)/i';
};
$regs = $this->_mapHostsWith($mapper);
return preg_replace($regs, '$1$7', $content, -1, $replace_count);
}
public static function removeBaseDir($hostname,$basedir, $content, &$replace_count = null) {
public function removeBaseDir($content, &$replace_count = null) {
if ('' === $this->_basedir)
return $content;
$regs = static::checkHostFromUrl($hostname,$basedir);
$regs = $this->_checkHostFromUrl();
return preg_replace($regs, '$1$4', $content, -1, $replace_count);
}
$result = preg_replace($regs, '$1$4', $content, -1, $replace_count);
return $result;
protected function _hostRegex($host) {
return '((https?:\/\/)?' . $host. ')?';
}
public static function checkHostFromUrl($hostname,$basedir) {
protected function _checkHostFromUrl() {
$mapper = function($host) {
return '/^' . $this->_hostRegex($host) . '(\/'.$this->_basedir.')?([\/?][^"\']*)/i';
};
return $this->_mapHostsWith($mapper);
}
protected function _mapHostsWith($closure) {
$hosts = ['web.afi-sa.net',
'opac3.pergame.net',
'www.'.$basedir,
'www.'.$hostname,
$hostname];
$regs = [];
foreach($hosts as $host) {
$regs []= '/^((http:\/\/)?' . $host. ')?(\/'.$basedir.')?([\/?][^"\']*)/i';
}
return $regs;
'www.'.$this->_basedir,
'www.'.$this->_hostname,
$this->_hostname];
$map = [];
foreach($hosts as $host)
$map[]= $closure($host);
return $map;
}
public static function removeHostFromUrl($hostname,$basedir, $content, &$replace_count = null) {
$regs = static::checkHostFromUrl($hostname,$basedir);
public function removeHostFromUrl($content, &$replace_count = null) {
$regs = $this->_checkHostFromUrl();
$result = preg_replace($regs, '$4', $content, -1, $replace_count);
if (strpos($result,"?") === 0 )
$result="/".$result;
if (strpos($result, '?') === 0 )
$result = '/' . $result;
return $result;
}
}
?>
\ No newline at end of file
......@@ -262,7 +262,7 @@ class Class_Newsletter extends Storm_Model_Abstract {
* @return string
*/
public function getContenu() {
return Class_CmsUrlTransformer::imgUrlRelativeToAbsolute(parent::getContenu());
return (new Class_CmsUrlTransformer())->imgUrlRelativeToAbsolute(parent::getContenu());
}
......
......@@ -70,8 +70,10 @@ abstract class ZendAfi_Controller_Action_Helper_RenderRssAbstract {
protected function getDescriptionForElement($data) {
return html_entity_decode(Class_CmsUrlTransformer::imgUrlRelativeToAbsolute($this->_view->tagArticleEvent($data)
. $data->getFullContent()));
$transformer = new Class_CmsUrlTransformer();
return html_entity_decode($transformer
->imgUrlRelativeToAbsolute($this->_view->tagArticleEvent($data)
. $data->getFullContent()));
}
......
......@@ -241,9 +241,10 @@ class ZendAfi_Controller_Plugin_Manager_Article extends ZendAfi_Controller_Plugi
protected function _getFormValues($model) {
$attributes=parent::_getFormValues($model);
$attributes = parent::_getFormValues($model);
$transformer = new Class_CmsUrlTransformer();
foreach(['description', 'contenu'] as $content_field)
$attributes[$content_field] = Class_CmsUrlTransformer::forEditing($attributes[$content_field]);
$attributes[$content_field] = $transformer->forEditing($attributes[$content_field]);
$attributes['pick_day'] = $model->getPickDayAsArray();
return $attributes;
......
......@@ -14,10 +14,11 @@ echo BASE_URL."\n";
$occurences = 0;
$articles = Class_Article::findAllBy(['where' => 'concat(description,contenu) like "%'. $basedir .'%"']);
$transformer = new Class_CmsUrlTransformer($hostname, $basedir);
foreach ($articles as $art) {
$art
->setDescription(Class_CmsUrlTransformer::removeHost($hostname,$basedir, $art->getDescription(), $countDesc))
->setContenu(Class_CmsUrlTransformer::removeHost($hostname,$basedir, $art->getContenu(), $countCont))
->setDescription($transformer->removeHost($art->getDescription(), $countDesc))
->setContenu($transformer->removeHost($art->getContenu(), $countCont))
->save();
$occurences += $countDesc + $countCont;
}
......
......@@ -21,10 +21,12 @@ $items = $loader();
echo count($items) . " domains to process found\n";
$occurences = 0;
$transformer = new Class_CmsUrlTransformer($hostname, $basedir);
foreach ($items as $item) {
echo $item->getId() . ' : ' . $item->getUrlImg() . " -> ";
$item
->setUrlImg(Class_CmsUrlTransformer::removeBaseDir($hostname, $basedir, $item->getUrlImg()))
->setUrlImg($transformer->removeBaseDir($item->getUrlImg()))
->save();
echo $item->getUrlImg() . "\n";
$occurences++;
......
......@@ -17,13 +17,16 @@ $occurences = 0;
$news_checked = 0;
$news = Class_Newsletter::findAllBy(['where' => 'contenu like "%' . $basedir . '%"']);
$transformer = new Class_CmsUrlTransformer($hostname, $basedir);
foreach ($news as $new) {
$news_checked++;
$new->setContenu(Class_CmsUrlTransformer::removeHost($hostname,$basedir, $new->getContenu(), $countContenu))
->save();
$new->setContenu($transformer->removeHost($new->getContenu(), $countContenu))
->save();
$occurences += $countContenu;
}
echo "News checked: $news_checked\n";
echo "$occurences occurence(s) replaced.\n";
?>
......@@ -16,19 +16,22 @@ echo BASE_URL."\n";
$occurences = 0;
$profils_checked = 0;
$profils = Class_Profil::findAllBy(['where' => 'concat(cfg_site,cfg_accueil) like "%' . $basedir . '%"']);
$transformer = new Class_CmsUrlTransformer($hostname, $basedir);
foreach ($profils as $profil) {
$profils_checked++;
$profil
->setCfgSite((Class_CmsUrlTransformer::removeHostFromArray($hostname,$basedir, $profil->getCfgSiteAsArray(), $countSite)))
->setCfgAccueil((Class_CmsUrlTransformer::removeHostFromArray($hostname,$basedir, $profil->getCfgAccueilAsArray(), $countAccueil)))
->setCfgSite(($transformer->removeHostFromArray($profil->getCfgSiteAsArray(), $countSite)))
->setCfgAccueil(($transformer->removeHostFromArray($profil->getCfgAccueilAsArray(), $countAccueil)))
->save();
$occurences += $countSite + $countAccueil;
}
foreach (Class_FRBR_Link::findAll() as $frbr) {
$frbr->setSource(Class_CmsUrlTransformer::removeBaseDir($hostname,$basedir, $frbr->getSource()));
$frbr->setTarget(Class_CmsUrlTransformer::removeBaseDir($hostname,$basedir, $frbr->getTarget()));
$frbr->setSource($transformer->removeBaseDir($frbr->getSource()));
$frbr->setTarget($transformer->removeBaseDir($frbr->getTarget()));
$frbr->save();
}
......
......@@ -19,13 +19,14 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
class CmsUrlTransformerTest extends Storm_Test_ModelTestCase {
class CmsUrlTransformerBasicsTest extends ModelTestCase {
protected $_storm_default_to_volatile = true;
public function setUp(){
parent::setUp();
$_SERVER['SCRIPT_NAME'] = '';
Class_Profil::beVolatile();
$cfg_accueil_jeunesse = ['modules' => ['1' => ['division' => '4',
'type_module' => 'RECH_SIMPLE',
'preferences' => ['recherche_avancee' => "on",
......@@ -92,17 +93,15 @@ class CmsUrlTransformerTest extends Storm_Test_ModelTestCase {
'logo_droite_link' => 'http://macommune.fr',
'header_img_cycle' => true]);
$this->transformer = new Class_CmsUrlTransformer;
$this->transformer = new Class_CmsUrlTransformer('ma-mediatheque.net', 'afi-opac3');
}
/** @test */
public function connectUrlShouldNotContainHost() {
$this->profil_jeunesse
->setCfgAccueil(Class_CmsUrlTransformer::removeHostFromArray("ma-mediatheque.net",
"afi-opac3",
$this->profil_jeunesse->getCfgAccueilAsArray(),
$countSite));
->setCfgAccueil($this->transformer->removeHostFromArray($this->profil_jeunesse->getCfgAccueilAsArray(),
$countSite));
$this->assertEquals('/?id_profil=1',
$this->profil_jeunesse->getCfgAccueilAsArray()['modules'][2]['preferences']['lien_connexion']);
......@@ -111,68 +110,30 @@ class CmsUrlTransformerTest extends Storm_Test_ModelTestCase {
/** @test */
public function baseDirShouldBeRemoved() {
$this->assertEquals("http://ma-mediatheque.fr/recherche/viewnotice/expressionRecherche/dragon/tri/*/clef/DRAGONJAUNEETLEDRAGONBLEULE-CONTECOREEN-LOUISC--PPICQUIER-2012-1/id/1805295",
Class_CmsUrlTransformer::removeBaseDir('ma-mediatheque.fr',
'casa',
'http://ma-mediatheque.fr/casa/recherche/viewnotice/expressionRecherche/dragon/tri/*/clef/DRAGONJAUNEETLEDRAGONBLEULE-CONTECOREEN-LOUISC--PPICQUIER-2012-1/id/1805295'));
$this->assertEquals("http://ma-mediatheque.net/recherche/viewnotice/expressionRecherche/dragon/tri/*/clef/DRAGONJAUNEETLEDRAGONBLEULE-CONTECOREEN-LOUISC--PPICQUIER-2012-1/id/1805295",
$this->transformer->removeBaseDir('http://ma-mediatheque.net/afi-opac3/recherche/viewnotice/expressionRecherche/dragon/tri/*/clef/DRAGONJAUNEETLEDRAGONBLEULE-CONTECOREEN-LOUISC--PPICQUIER-2012-1/id/1805295'));
}
/** @test */
public function headerJsShouldNotContainHost() {
$this->profil_jeunesse->setCfgSite(Class_CmsUrlTransformer::removeHostFromArray("ma-mediatheque.net","afi-opac3", $this->profil_jeunesse->getCfgSiteAsArray(), $countSite));
$this->profil_jeunesse
->setCfgSite($this->transformer->removeHostFromArray($this->profil_jeunesse->getCfgSiteAsArray(), $countSite));
Class_Profil::clearCache();
$this->assertEquals('/userfiles/jeunesse.js',
$this->profil_jeunesse->getCfgSiteAsArray()['header_js']);
}
/** @test */
public function forEditingShouldTransformToAbsoluteUrls() {
$this->assertEquals('<p>plan: <img src="http://localhost/userfile/image.png" />'.
'</p><img src="http://example.com/test.jpg"></img>',
$this->transformer->forEditing('<p>plan: <img src="/userfile/image.png" />'.
'</p><img src="http://example.com/test.jpg"></img>'));
$this->assertEquals('<div> photo <img src="http://localhost/test/desc.png" /></div>',
$this->transformer->forEditing('<div> photo <img src="/test/desc.png" /></div>'));
}
/** @test */
public function forSavingShouldTransformToRelativeUrls() {
$this->assertEquals('<p>plan: <img src="'.Class_Url::baseUrl().'/userfile/image.png" />'.
'</p><img src="'.Class_Url::baseUrl().'/images/test.jpg"></img>'.
'<img src="http://example.com/../test.jpg" />',
$this->transformer->forSaving('<p>plan: <img src="http://localhost' . Class_Url::baseUrl() . '/userfile/image.png" />'.
'</p><img src="../../images/test.jpg"></img><img src="http://example.com/../test.jpg" />'));
$this->assertEquals('<div> photo <img src="' . Class_Url::baseUrl() . '/test/desc.png" /></div>',
$this->transformer->forSaving('<div> photo <img src="http://localhost' . Class_Url::baseUrl() . '/test/desc.png" /></div>'));
}
/** @test */
public function chatenaySaveShouldNotRegress() {
$this->assertEquals('<a href="http://www.histoireencartes.com/" target="_blank">'.
'<img alt="" src="' . Class_Url::baseUrl() . '/userfiles/image/Histoire/armistice.jpg" style="width: 123px; height: 93px; " />'.
'<img alt="" src="' . Class_Url::baseUrl() . '/userfiles/image/Histoire/armistice.jpg" />'.
'<br /></a>',
$this->transformer->forSaving('<a href="http://www.histoireencartes.com/" target="_blank">'.
'<img alt="" src="' . Class_Url::baseUrl() . '/userfiles/image/Histoire/armistice.jpg" style="width: 123px; height: 93px; " />'.
'<img alt="" src="' . Class_Url::baseUrl() . Class_Url::baseUrl().'/userfiles/image/Histoire/armistice.jpg" />'.
'<br /></a>'));
}
public function urlTransmormDataProvider() {
return [
['Concert <a class="popup" href="/cms/id/12">de maiden</a> à la bib !',
'Concert <a class="popup" href="http://www.genevois-biblio.fr/genevois-biblio.fr/cms/id/12">de maiden</a> à la bib !',
'genevois-biblio.fr'],
['Concert <a class="popup" href="/cms/id/12">de maiden</a> à la bib !',
'Concert <a class="popup" href="https://www.genevois-biblio.fr/genevois-biblio.fr/cms/id/12">de maiden</a> à la bib !',
'genevois-biblio.fr'],
['Concert <a class="popup" href="/cms/id/12">de maiden</a> à la bib !',
'Concert <a class="popup" href="http://web.afi-sa.net/genevois-biblio.fr/cms/id/12">de maiden</a> à la bib !',
......@@ -233,10 +194,100 @@ class CmsUrlTransformerTest extends Storm_Test_ModelTestCase {
* @dataProvider urlTransmormDataProvider
*/
public function removeHostShouldTransformUrlsToRelative($expected, $content, $host) {
$this->assertEquals($expected,
$this->transformer->removeHost("ma-mediatheque.net",$host, $content));
$transformer = new Class_CmsUrlTransformer('ma-mediatheque.net', $host);
$this->assertEquals($expected, $transformer->removeHost($content));
}
}
?>
\ No newline at end of file
class CmsUrlTransformerSavingEditingTest extends ModelTestCase {
protected $_storm_default_to_volatile = true;
public function setUp() {
parent::setUp();
$this->transformer = new Class_CmsUrlTransformer('ma-mediatheque.net', 'afi-opac3');
}
public function tearDown() {
unset($_SERVER['HTTPS']);
parent::tearDown();
}
/** @test */
public function forEditingShouldTransformToAbsoluteUrls() {
$this->assertEquals('<p>plan: <img src="http://localhost/userfile/image.png" />'.
'</p><img src="http://example.com/test.jpg"></img>',
$this->transformer->forEditing('<p>plan: <img src="/userfile/image.png" />'.
'</p><img src="http://example.com/test.jpg"></img>'));
$this->assertEquals('<div> photo <img src="http://localhost/test/desc.png" /></div>',
$this->transformer->forEditing('<div> photo <img src="/test/desc.png" /></div>'));
}
/** @test */
public function forSavingShouldTransformToRelativeUrls() {
$this->assertEquals('<p>plan: <img src="'.Class_Url::baseUrl().'/userfile/image.png" />'.
'</p><img src="'.Class_Url::baseUrl().'/images/test.jpg"></img>'.
'<img src="http://example.com/../test.jpg" />',
$this->transformer->forSaving('<p>plan: <img src="http://localhost' . Class_Url::baseUrl() . '/userfile/image.png" />'.
'</p><img src="../../images/test.jpg"></img><img src="http://example.com/../test.jpg" />'));
$this->assertEquals('<div> photo <img src="' . Class_Url::baseUrl() . '/test/desc.png" /></div>',
$this->transformer->forSaving('<div> photo <img src="http://localhost' . Class_Url::baseUrl() . '/test/desc.png" /></div>'));
}
/** @test */
public function chatenaySaveShouldNotRegress() {
$this->assertEquals('<a href="http://www.histoireencartes.com/" target="_blank">'.
'<img alt="" src="' . Class_Url::baseUrl() . '/userfiles/image/Histoire/armistice.jpg" style="width: 123px; height: 93px; " />'.
'<img alt="" src="' . Class_Url::baseUrl() . '/userfiles/image/Histoire/armistice.jpg" />'.
'<br /></a>',
$this->transformer->forSaving('<a href="http://www.histoireencartes.com/" target="_blank">'.
'<img alt="" src="' . Class_Url::baseUrl() . '/userfiles/image/Histoire/armistice.jpg" style="width: 123px; height: 93px; " />'.
'<img alt="" src="' . Class_Url::baseUrl() . Class_Url::baseUrl().'/userfiles/image/Histoire/armistice.jpg" />'.
'<br /></a>'));
}
/** @test */
public function withHttpsOnForEditingShouldProvideHttps() {
$_SERVER['HTTPS'] = 'on';
$this->assertEquals('<p>plan: <img src="https://localhost/userfile/image.png" />'.
'</p><img src="http://example.com/test.jpg"></img>',
$this->transformer->forEditing('<p>plan: <img src="/userfile/image.png" />'.
'</p><img src="http://example.com/test.jpg"></img>'));
}
/** @test */
public function withoutHttpsOnButForceHttpsForEditingShouldProvideHttps() {
Class_AdminVar::set('FORCE_HTTPS', '1');
$this->assertEquals('<p>plan: <img src="https://localhost/userfile/image.png" />'.
'</p><img src="http://example.com/test.jpg"></img>',
$this->transformer->forEditing('<p>plan: <img src="/userfile/image.png" />'.
'</p><img src="http://example.com/test.jpg"></img>'));
}
/** @test */
public function forSavingWithHttpsShouldTransformToRelativeUrls() {
$base_url = Class_Url::baseUrl();
$this->assertEquals('<p>plan: <img src="'.$base_url.'/userfile/image.png" />'.
'</p><img src="'.$base_url.'/images/test.jpg"></img>'.
'<img src="http://example.com/../test.jpg" />',
$this->transformer->forSaving('<p>plan: <img src="https://localhost' . $base_url . '/userfile/image.png" />'.
'</p><img src="../../images/test.jpg"></img><img src="http://example.com/../test.jpg" />'));
$this->assertEquals('<div> photo <img src="' . $base_url . '/test/desc.png" /></div>',
$this->transformer->forSaving('<div> photo <img src="https://localhost' . $base_url . '/test/desc.png" /></div>'));
}
}
\ No newline at end of file
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment