Merge branch 'FixFormatDataHandling' of https://github.com/logmanoriginal/rss-bridge

This commit is contained in:
logmanoriginal 2016-08-29 20:52:28 +02:00
commit 370530b5ef
9 changed files with 51 additions and 72 deletions

View file

@ -6,8 +6,7 @@
class AtomFormat extends FormatAbstract{ class AtomFormat extends FormatAbstract{
public function stringify(){ public function stringify(){
/* Datas preparation */ $https = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 's' : '';
$https = ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 's' : '' );
$httpHost = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ''; $httpHost = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
$httpInfo = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : ''; $httpInfo = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '';
@ -20,12 +19,12 @@ class AtomFormat extends FormatAbstract{
$uri = $this->xml_encode($uri); $uri = $this->xml_encode($uri);
$entries = ''; $entries = '';
foreach($this->getDatas() as $data){ foreach($this->getItems() as $item){
$entryAuthor = is_null($data['author']) ? '' : $this->xml_encode($data['author']); $entryAuthor = isset($item['author']) ? $this->xml_encode($item['author']) : '';
$entryTitle = is_null($data['title']) ? '' : $this->xml_encode($data['title']); $entryTitle = isset($item['title']) ? $this->xml_encode($item['title']) : '';
$entryUri = is_null($data['uri']) ? '' : $this->xml_encode($data['uri']); $entryUri = isset($item['uri']) ? $this->xml_encode($item['uri']) : '';
$entryTimestamp = is_null($data['timestamp']) ? '' : $this->xml_encode(date(DATE_ATOM, $data['timestamp'])); $entryTimestamp = isset($item['timestamp']) ? $this->xml_encode(date(DATE_ATOM, $item['timestamp'])) : '';
$entryContent = is_null($data['content']) ? '' : $this->xml_encode($this->sanitizeHtml($data['content'])); $entryContent = isset($item['content']) ? $this->xml_encode($this->sanitizeHtml($item['content'])) : '';
$entries .= <<<EOD $entries .= <<<EOD
<entry> <entry>
@ -42,16 +41,7 @@ class AtomFormat extends FormatAbstract{
EOD; EOD;
} }
/* $feedTimestamp = date(DATE_ATOM, time());
TODO :
- Security: Disable Javascript ?
- <updated> : Define new extra info ?
- <content type="html"> : RFC look with xhtml, keep this in spite of ?
*/
// #### TEMPORARY FIX ###
$feedTimestamp = date(DATE_ATOM, time());
// ################
/* Data are prepared, now let's begin the "MAGIE !!!" */ /* Data are prepared, now let's begin the "MAGIE !!!" */
$toReturn = '<?xml version="1.0" encoding="UTF-8"?>'; $toReturn = '<?xml version="1.0" encoding="UTF-8"?>';
@ -70,11 +60,6 @@ $feedTimestamp = date(DATE_ATOM, time());
EOD; EOD;
// Remove invalid non-UTF8 characters // Remove invalid non-UTF8 characters
// We cannot use iconv because of a bug in some versions of iconv.
// See http://www.php.net/manual/fr/function.iconv.php#108643
//$toReturn = iconv("UTF-8", "UTF-8//IGNORE", $toReturn);
// So we use mb_convert_encoding instead:
ini_set('mbstring.substitute_character', 'none'); ini_set('mbstring.substitute_character', 'none');
$toReturn= mb_convert_encoding($toReturn, 'UTF-8', 'UTF-8'); $toReturn= mb_convert_encoding($toReturn, 'UTF-8', 'UTF-8');
return $toReturn; return $toReturn;
@ -82,7 +67,7 @@ EOD;
public function display(){ public function display(){
$this $this
->setContentType('application/atom+xml; charset=UTF-8') // We force UTF-8 in ATOM output. ->setContentType('application/atom+xml; charset=UTF-8')
->callContentType(); ->callContentType();
return parent::display(); return parent::display();

View file

@ -2,7 +2,6 @@
class HtmlFormat extends FormatAbstract{ class HtmlFormat extends FormatAbstract{
public function stringify(){ public function stringify(){
/* Datas preparation */
$extraInfos = $this->getExtraInfos(); $extraInfos = $this->getExtraInfos();
$title = htmlspecialchars($extraInfos['name']); $title = htmlspecialchars($extraInfos['name']);
$uri = htmlspecialchars($extraInfos['uri']); $uri = htmlspecialchars($extraInfos['uri']);
@ -10,12 +9,12 @@ class HtmlFormat extends FormatAbstract{
$mrssquery = str_replace('format=Html', 'format=Mrss', htmlentities($_SERVER['QUERY_STRING'])); $mrssquery = str_replace('format=Html', 'format=Mrss', htmlentities($_SERVER['QUERY_STRING']));
$entries = ''; $entries = '';
foreach($this->getDatas() as $data){ foreach($this->getItems() as $item){
$entryAuthor = isset($data['author']) ? '<br /><p class="author">by: ' . $data['author'] . '</p>' : ''; $entryAuthor = isset($item['author']) ? '<br /><p class="author">by: ' . $item['author'] . '</p>' : '';
$entryTitle = isset($data['title']) ? $this->sanitizeHtml(strip_tags($data['title'])) : ''; $entryTitle = isset($item['title']) ? $this->sanitizeHtml(strip_tags($item['title'])) : '';
$entryUri = isset($data['uri']) ? $data['uri'] : $uri; $entryUri = isset($item['uri']) ? $item['uri'] : $uri;
$entryTimestamp = isset($data['timestamp']) ? '<time datetime="' . date(DATE_ATOM, $data['timestamp']) . '">' . date(DATE_ATOM, $data['timestamp']) . '</time>' : ''; $entryTimestamp = isset($item['timestamp']) ? '<time datetime="' . date(DATE_ATOM, $item['timestamp']) . '">' . date(DATE_ATOM, $item['timestamp']) . '</time>' : '';
$entryContent = isset($data['content']) ? '<div class="content">' . $this->sanitizeHtml($data['content']). '</div>' : ''; $entryContent = isset($item['content']) ? '<div class="content">' . $this->sanitizeHtml($item['content']). '</div>' : '';
$entries .= <<<EOD $entries .= <<<EOD
<section class="feeditem"> <section class="feeditem">

View file

@ -6,10 +6,9 @@
class JsonFormat extends FormatAbstract{ class JsonFormat extends FormatAbstract{
public function stringify(){ public function stringify(){
// FIXME : sometime content can be null, transform to empty string $items = $this->getItems();
$datas = $this->getDatas();
return json_encode($datas, JSON_PRETTY_PRINT); return json_encode($items, JSON_PRETTY_PRINT);
} }
public function display(){ public function display(){

View file

@ -6,8 +6,7 @@
class MrssFormat extends FormatAbstract{ class MrssFormat extends FormatAbstract{
public function stringify(){ public function stringify(){
/* Datas preparation */ $https = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 's' : '';
$https = ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 's' : '' );
$httpHost = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ''; $httpHost = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
$httpInfo = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : ''; $httpInfo = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '';
@ -16,14 +15,15 @@ class MrssFormat extends FormatAbstract{
$extraInfos = $this->getExtraInfos(); $extraInfos = $this->getExtraInfos();
$title = $this->xml_encode($extraInfos['name']); $title = $this->xml_encode($extraInfos['name']);
$uri = $this->xml_encode(!empty($extraInfos['uri']) ? $extraInfos['uri'] : 'https://github.com/sebsauvage/rss-bridge'); $uri = $this->xml_encode(!empty($extraInfos['uri']) ? $extraInfos['uri'] : 'https://github.com/sebsauvage/rss-bridge');
$icon = $this->xml_encode('http://icons.better-idea.org/icon?url='. $uri .'&size=64');
$items = ''; $items = '';
foreach($this->getDatas() as $data){ foreach($this->getItems() as $item){
$itemAuthor = is_null($data['author']) ? '' : $this->xml_encode($data['author']); $itemAuthor = isset($item['author']) ? $this->xml_encode($item['author']) : '';
$itemTitle = strip_tags(is_null($data['title']) ? '' : $this->xml_encode($data['title'])); $itemTitle = strip_tags(isset($item['title']) ? $this->xml_encode($item['title']) : '');
$itemUri = is_null($data['uri']) ? '' : $this->xml_encode($data['uri']); $itemUri = isset($item['uri']) ? $this->xml_encode($item['uri']) : '';
$itemTimestamp = is_null($data['timestamp']) ? '' : $this->xml_encode(date(DATE_RFC2822, $data['timestamp'])); $itemTimestamp = isset($item['timestamp']) ? $this->xml_encode(date(DATE_RFC2822, $item['timestamp'])) : '';
$itemContent = is_null($data['content']) ? '' : $this->xml_encode($this->sanitizeHtml($data['content'])); $itemContent = isset($item['content']) ? $this->xml_encode($this->sanitizeHtml($item['content'])) : '';
$items .= <<<EOD $items .= <<<EOD
<item> <item>
@ -38,13 +38,6 @@ class MrssFormat extends FormatAbstract{
EOD; EOD;
} }
/*
TODO :
- Security: Disable Javascript ?
- <updated> : Define new extra info ?
- <content type="html"> : RFC look with xhtml, keep this in spite of ?
*/
/* Data are prepared, now let's begin the "MAGIE !!!" */ /* Data are prepared, now let's begin the "MAGIE !!!" */
$toReturn = '<?xml version="1.0" encoding="UTF-8"?>'; $toReturn = '<?xml version="1.0" encoding="UTF-8"?>';
$toReturn .= <<<EOD $toReturn .= <<<EOD
@ -53,6 +46,7 @@ EOD;
<title>{$title}</title> <title>{$title}</title>
<link>http{$https}://{$httpHost}{$httpInfo}/</link> <link>http{$https}://{$httpHost}{$httpInfo}/</link>
<description>{$title}</description> <description>{$title}</description>
<image url="{$icon}" title="{$title}" link="{$uri}"/>
<atom:link rel="alternate" type="text/html" href="{$uri}" /> <atom:link rel="alternate" type="text/html" href="{$uri}" />
<atom:link rel="self" href="http{$https}://{$httpHost}{$serverRequestUri}" /> <atom:link rel="self" href="http{$https}://{$httpHost}{$serverRequestUri}" />
{$items} {$items}
@ -61,11 +55,6 @@ EOD;
EOD; EOD;
// Remove invalid non-UTF8 characters // Remove invalid non-UTF8 characters
// We cannot use iconv because of a bug in some versions of iconv.
// See http://www.php.net/manual/fr/function.iconv.php#108643
//$toReturn = iconv("UTF-8", "UTF-8//IGNORE", $toReturn);
// So we use mb_convert_encoding instead:
ini_set('mbstring.substitute_character', 'none'); ini_set('mbstring.substitute_character', 'none');
$toReturn= mb_convert_encoding($toReturn, 'UTF-8', 'UTF-8'); $toReturn= mb_convert_encoding($toReturn, 'UTF-8', 'UTF-8');
return $toReturn; return $toReturn;
@ -73,7 +62,7 @@ EOD;
public function display(){ public function display(){
$this $this
->setContentType('application/rss+xml; charset=UTF-8') // We force UTF-8 in RSS output. ->setContentType('application/rss+xml; charset=UTF-8')
->callContentType(); ->callContentType();
return parent::display(); return parent::display();

View file

@ -6,8 +6,8 @@
class PlaintextFormat extends FormatAbstract{ class PlaintextFormat extends FormatAbstract{
public function stringify(){ public function stringify(){
$datas = $this->getDatas(); $items = $this->getItems();
return print_r($datas, true); return print_r($items, true);
} }
public function display(){ public function display(){

View file

@ -137,7 +137,7 @@ try{
try { try {
$format = Format::create($format); $format = Format::create($format);
$format $format
->setDatas($bridge->getDatas()) ->setItems($bridge->getItems())
->setExtraInfos(array( ->setExtraInfos(array(
'name' => $bridge->getName(), 'name' => $bridge->getName(),
'uri' => $bridge->getURI(), 'uri' => $bridge->getURI(),

View file

@ -139,7 +139,7 @@ abstract class BridgeAbstract implements BridgeInterface {
* Return items stored in the bridge * Return items stored in the bridge
* @return mixed * @return mixed
*/ */
public function getDatas(){ public function getItems(){
return $this->items; return $this->items;
} }
@ -267,7 +267,7 @@ abstract class BridgeAbstract implements BridgeInterface {
$this->collectData(); $this->collectData();
if(!is_null($this->cache)){ if(!is_null($this->cache)){
$this->cache->saveData($this->getDatas()); $this->cache->saveData($this->getItems());
} }
return; return;
} }
@ -360,7 +360,7 @@ abstract class BridgeAbstract implements BridgeInterface {
$this->collectData(); $this->collectData();
if(!is_null($this->cache)){ if(!is_null($this->cache)){
$this->cache->saveData($this->getDatas()); $this->cache->saveData($this->getItems());
} }
} }

View file

@ -7,7 +7,7 @@
interface FormatInterface{ interface FormatInterface{
public function stringify(); public function stringify();
public function display(); public function display();
public function setDatas(array $bridge); public function setItems(array $bridges);
} }
abstract class FormatAbstract implements FormatInterface{ abstract class FormatAbstract implements FormatInterface{
@ -16,7 +16,7 @@ abstract class FormatAbstract implements FormatInterface{
protected protected
$contentType, $contentType,
$charset, $charset,
$datas, $items,
$extraInfos $extraInfos
; ;
@ -48,18 +48,17 @@ abstract class FormatAbstract implements FormatInterface{
return $this; return $this;
} }
public function setDatas(array $datas){ public function setItems(array $items){
$this->datas = $datas; $this->items = array_map(array($this, 'array_trim'), $items);
return $this; return $this;
} }
public function getDatas(){ public function getItems(){
if( !is_array($this->datas) ){ if(!is_array($this->items))
throw new \LogicException('Feed the ' . get_class($this) . ' with "setDatas" method before !'); throw new \LogicException('Feed the ' . get_class($this) . ' with "setItems" method before !');
}
return $this->datas; return $this->items;
} }
/** /**
@ -99,7 +98,7 @@ abstract class FormatAbstract implements FormatInterface{
* Maybe we'll switch to http://htmlpurifier.org/ * Maybe we'll switch to http://htmlpurifier.org/
* or http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/index.php * or http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/index.php
*/ */
public function sanitizeHtml($html) protected function sanitizeHtml($html)
{ {
$html = str_replace('<script','<&zwnj;script',$html); // Disable scripts, but leave them visible. $html = str_replace('<script','<&zwnj;script',$html); // Disable scripts, but leave them visible.
$html = str_replace('<iframe','<&zwnj;iframe',$html); $html = str_replace('<iframe','<&zwnj;iframe',$html);
@ -107,6 +106,14 @@ abstract class FormatAbstract implements FormatInterface{
// We leave alone object and embed so that videos can play in RSS readers. // We leave alone object and embed so that videos can play in RSS readers.
return $html; return $html;
} }
protected function array_trim($elements){
foreach($elements as $key => $value){
if(is_string($value))
$elements[$key] = trim($value);
}
return $elements;
}
} }
class Format{ class Format{

View file

@ -32,7 +32,7 @@ require_once $vendorLibSimpleHtmlDom;
Format::setDir(__DIR__ . '/formats/'); Format::setDir(__DIR__ . '/formats/');
$format = Format::create('Atom'); $format = Format::create('Atom');
$format $format
->setDatas($bridge->getDatas()) ->setItems($bridge->getItems())
->setExtraInfos(array( ->setExtraInfos(array(
'name' => $bridge->getName(), 'name' => $bridge->getName(),
'uri' => $bridge->getURI(), 'uri' => $bridge->getURI(),