diff --git a/htdocs/includes/boxes/box_external_rss.php b/htdocs/includes/boxes/box_external_rss.php
index 46bdf76faa4..b39a512f213 100644
--- a/htdocs/includes/boxes/box_external_rss.php
+++ b/htdocs/includes/boxes/box_external_rss.php
@@ -29,7 +29,7 @@
\version $Revision$
*/
-include_once(DOL_DOCUMENT_ROOT."/includes/magpierss/rss_fetch.inc");
+include_once(MAGPIERSS_PATH."rss_fetch.inc");
include_once(DOL_DOCUMENT_ROOT."/includes/boxes/modules_boxes.php");
diff --git a/htdocs/includes/magpierss/README b/htdocs/includes/magpierss/README
new file mode 100644
index 00000000000..6af7edb07c8
--- /dev/null
+++ b/htdocs/includes/magpierss/README
@@ -0,0 +1,48 @@
+NAME
+
+ MagpieRSS - a simple RSS integration tool
+
+SYNOPSIS
+
+ require_once(rss_fetch.inc);
+ $url = $_GET['url'];
+ $rss = fetch_rss( $url );
+
+ echo "Channel Title: " . $rss->channel['title'] . "
";
+ echo "
";
+ foreach ($rss->items as $item) {
+ $href = $item['link'];
+ $title = $item['title'];
+ echo "- $title
";
+ }
+ echo "
";
+
+DESCRIPTION
+
+ MapieRSS is an XML-based RSS parser in PHP. It attempts to be "PHP-like",
+ and simple to use.
+
+ Some features include:
+
+ * supports RSS 0.9 - 1.0, with limited RSS 2.0 support
+ * supports namespaces, and modules, including mod_content and mod_event
+ * open minded [1]
+ * simple, functional interface, to object oriented backend parser
+ * automatic caching of parsed RSS objects makes its easy to integrate
+ * supports conditional GET with Last-Modified, and ETag
+ * uses constants for easy override of default behaviour
+ * heavily commented
+
+
+1. By open minded I mean Magpie will accept any tag it finds in good faith that
+ it was supposed to be here. For strict validation, look elsewhere.
+
+
+GETTING STARTED
+
+
+
+COPYRIGHT:
+ Copyright(c) 2002 kellan@protest.net. All rights reserved.
+ This software is released under the GNU General Public License.
+ Please read the disclaimer at the top of the Snoopy.class.inc file.
diff --git a/htdocs/includes/magpierss/extlib/Snoopy.class.inc b/htdocs/includes/magpierss/extlib/Snoopy.class.inc
index e0b3e0cf65c..cf832d0b2ab 100644
--- a/htdocs/includes/magpierss/extlib/Snoopy.class.inc
+++ b/htdocs/includes/magpierss/extlib/Snoopy.class.inc
@@ -198,8 +198,10 @@ class Snoopy
return true;
break;
case "https":
- if(!$this->curl_path || (!is_executable($this->curl_path)))
+ if(!$this->curl_path || (!is_executable($this->curl_path))) {
+ $this->error = "Bad curl ($this->curl_path), can't fetch HTTPS \n";
return false;
+ }
$this->host = $URI_PARTS["host"];
if(!empty($URI_PARTS["port"]))
$this->port = $URI_PARTS["port"];
@@ -258,325 +260,6 @@ class Snoopy
return true;
}
-/*======================================================================*\
- Function: submit
- Purpose: submit an http form
- Input: $URI the location to post the data
- $formvars the formvars to use.
- format: $formvars["var"] = "val";
- Output: $this->results the text output from the post
-\*======================================================================*/
-
- function submit($URI, $formvars="", $formfiles="")
- {
- unset($postdata);
-
- $postdata = $this->_prepare_post_body($formvars, $formfiles);
-
- $URI_PARTS = parse_url($URI);
- if (!empty($URI_PARTS["user"]))
- $this->user = $URI_PARTS["user"];
- if (!empty($URI_PARTS["pass"]))
- $this->pass = $URI_PARTS["pass"];
-
- switch($URI_PARTS["scheme"])
- {
- case "http":
- $this->host = $URI_PARTS["host"];
- if(!empty($URI_PARTS["port"]))
- $this->port = $URI_PARTS["port"];
- if($this->_connect($fp))
- {
- if($this->_isproxy)
- {
- // using proxy, send entire URI
- $this->_httprequest($URI,$fp,$URI,$this->_submit_method,$this->_submit_type,$postdata);
- }
- else
- {
- $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
- // no proxy, send only the path
- $this->_httprequest($path, $fp, $URI, $this->_submit_method, $this->_submit_type, $postdata);
- }
-
- $this->_disconnect($fp);
-
- if($this->_redirectaddr)
- {
- /* url was redirected, check if we've hit the max depth */
- if($this->maxredirs > $this->_redirectdepth)
- {
- if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr))
- $this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]);
-
- // only follow redirect if it's on this site, or offsiteok is true
- if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
- {
- /* follow the redirect */
- $this->_redirectdepth++;
- $this->lastredirectaddr=$this->_redirectaddr;
- $this->submit($this->_redirectaddr,$formvars, $formfiles);
- }
- }
- }
-
- if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
- {
- $frameurls = $this->_frameurls;
- $this->_frameurls = array();
-
- while(list(,$frameurl) = each($frameurls))
- {
- if($this->_framedepth < $this->maxframes)
- {
- $this->fetch($frameurl);
- $this->_framedepth++;
- }
- else
- break;
- }
- }
-
- }
- else
- {
- return false;
- }
- return true;
- break;
- case "https":
- if(!$this->curl_path || (!is_executable($this->curl_path)))
- return false;
- $this->host = $URI_PARTS["host"];
- if(!empty($URI_PARTS["port"]))
- $this->port = $URI_PARTS["port"];
- if($this->_isproxy)
- {
- // using proxy, send entire URI
- $this->_httpsrequest($URI, $URI, $this->_submit_method, $this->_submit_type, $postdata);
- }
- else
- {
- $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
- // no proxy, send only the path
- $this->_httpsrequest($path, $URI, $this->_submit_method, $this->_submit_type, $postdata);
- }
-
- if($this->_redirectaddr)
- {
- /* url was redirected, check if we've hit the max depth */
- if($this->maxredirs > $this->_redirectdepth)
- {
- if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr))
- $this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]);
-
- // only follow redirect if it's on this site, or offsiteok is true
- if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
- {
- /* follow the redirect */
- $this->_redirectdepth++;
- $this->lastredirectaddr=$this->_redirectaddr;
- $this->submit($this->_redirectaddr,$formvars, $formfiles);
- }
- }
- }
-
- if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
- {
- $frameurls = $this->_frameurls;
- $this->_frameurls = array();
-
- while(list(,$frameurl) = each($frameurls))
- {
- if($this->_framedepth < $this->maxframes)
- {
- $this->fetch($frameurl);
- $this->_framedepth++;
- }
- else
- break;
- }
- }
- return true;
- break;
-
- default:
- // not a valid protocol
- $this->error = 'Invalid protocol "'.$URI_PARTS["scheme"].'"\n';
- return false;
- break;
- }
- return true;
- }
-
-/*======================================================================*\
- Function: fetchlinks
- Purpose: fetch the links from a web page
- Input: $URI where you are fetching from
- Output: $this->results an array of the URLs
-\*======================================================================*/
-
- function fetchlinks($URI)
- {
- if ($this->fetch($URI))
- {
-
- if(is_array($this->results))
- {
- for($x=0;$xresults);$x++)
- $this->results[$x] = $this->_striplinks($this->results[$x]);
- }
- else
- $this->results = $this->_striplinks($this->results);
-
- if($this->expandlinks)
- $this->results = $this->_expandlinks($this->results, $URI);
- return true;
- }
- else
- return false;
- }
-
-/*======================================================================*\
- Function: fetchform
- Purpose: fetch the form elements from a web page
- Input: $URI where you are fetching from
- Output: $this->results the resulting html form
-\*======================================================================*/
-
- function fetchform($URI)
- {
-
- if ($this->fetch($URI))
- {
-
- if(is_array($this->results))
- {
- for($x=0;$xresults);$x++)
- $this->results[$x] = $this->_stripform($this->results[$x]);
- }
- else
- $this->results = $this->_stripform($this->results);
-
- return true;
- }
- else
- return false;
- }
-
-
-/*======================================================================*\
- Function: fetchtext
- Purpose: fetch the text from a web page, stripping the links
- Input: $URI where you are fetching from
- Output: $this->results the text from the web page
-\*======================================================================*/
-
- function fetchtext($URI)
- {
- if($this->fetch($URI))
- {
- if(is_array($this->results))
- {
- for($x=0;$xresults);$x++)
- $this->results[$x] = $this->_striptext($this->results[$x]);
- }
- else
- $this->results = $this->_striptext($this->results);
- return true;
- }
- else
- return false;
- }
-
-/*======================================================================*\
- Function: submitlinks
- Purpose: grab links from a form submission
- Input: $URI where you are submitting from
- Output: $this->results an array of the links from the post
-\*======================================================================*/
-
- function submitlinks($URI, $formvars="", $formfiles="")
- {
- if($this->submit($URI,$formvars, $formfiles))
- {
- if(is_array($this->results))
- {
- for($x=0;$xresults);$x++)
- {
- $this->results[$x] = $this->_striplinks($this->results[$x]);
- if($this->expandlinks)
- $this->results[$x] = $this->_expandlinks($this->results[$x],$URI);
- }
- }
- else
- {
- $this->results = $this->_striplinks($this->results);
- if($this->expandlinks)
- $this->results = $this->_expandlinks($this->results,$URI);
- }
- return true;
- }
- else
- return false;
- }
-
-/*======================================================================*\
- Function: submittext
- Purpose: grab text from a form submission
- Input: $URI where you are submitting from
- Output: $this->results the text from the web page
-\*======================================================================*/
-
- function submittext($URI, $formvars = "", $formfiles = "")
- {
- if($this->submit($URI,$formvars, $formfiles))
- {
- if(is_array($this->results))
- {
- for($x=0;$xresults);$x++)
- {
- $this->results[$x] = $this->_striptext($this->results[$x]);
- if($this->expandlinks)
- $this->results[$x] = $this->_expandlinks($this->results[$x],$URI);
- }
- }
- else
- {
- $this->results = $this->_striptext($this->results);
- if($this->expandlinks)
- $this->results = $this->_expandlinks($this->results,$URI);
- }
- return true;
- }
- else
- return false;
- }
-
-
-
-/*======================================================================*\
- Function: set_submit_multipart
- Purpose: Set the form submission content type to
- multipart/form-data
-\*======================================================================*/
- function set_submit_multipart()
- {
- $this->_submit_type = "multipart/form-data";
- }
-
-
-/*======================================================================*\
- Function: set_submit_normal
- Purpose: Set the form submission content type to
- application/x-www-form-urlencoded
-\*======================================================================*/
- function set_submit_normal()
- {
- $this->_submit_type = "application/x-www-form-urlencoded";
- }
-
-
/*======================================================================*\
@@ -812,7 +495,8 @@ class Snoopy
return false;
}
- if($currentHeader == "\r\n")
+ // if($currentHeader == "\r\n")
+ if(preg_match("/^\r?\n$/", $currentHeader) )
break;
// if a header begins with Location: or URI:, set the redirect
@@ -970,6 +654,8 @@ class Snoopy
$headerfile = uniqid(time());
+ # accept self-signed certs
+ $cmdline_params .= " -k";
exec($this->curl_path." -D \"/tmp/$headerfile\"".$cmdline_params." ".$URI,$results,$return);
if($return)
@@ -1010,8 +696,13 @@ class Snoopy
}
if(preg_match("|^HTTP/|",$result_headers[$currentHeader]))
+ {
$this->response_code = $result_headers[$currentHeader];
-
+ if(preg_match("|^HTTP/[^\s]*\s(.*?)\s|",$this->response_code, $match))
+ {
+ $this->status= $match[1];
+ }
+ }
$this->headers[] = $result_headers[$currentHeader];
}
diff --git a/htdocs/includes/magpierss/rss_cache.inc b/htdocs/includes/magpierss/rss_cache.inc
index 3dc39cbf36b..fdfa5dd2591 100644
--- a/htdocs/includes/magpierss/rss_cache.inc
+++ b/htdocs/includes/magpierss/rss_cache.inc
@@ -2,10 +2,10 @@
/*
* Project: MagpieRSS: a simple RSS integration tool
* File: rss_cache.inc, a simple, rolling(no GC), cache
- * for RSS objects, keyed on URL.
+ * for RSS objects, keyed on URL.
* Author: Kellan Elliott-McCrea
- * Version: 0.51
- * License: GPL
+ * Version: 0.51
+ * License: GPL
*
* The lastest version of MagpieRSS can be obtained from:
* http://magpierss.sourceforge.net
@@ -17,167 +17,167 @@
*/
class RSSCache {
- var $BASE_CACHE = './cache'; // where the cache files are stored
- var $MAX_AGE = 3600; // when are files stale, default one hour
- var $ERROR = ""; // accumulate error messages
-
- function RSSCache ($base='', $age='') {
- if ( $base ) {
- $this->BASE_CACHE = $base;
- }
- if ( $age ) {
- $this->MAX_AGE = $age;
- }
-
- // attempt to make the cache directory
- if ( ! file_exists( $this->BASE_CACHE ) ) {
- $status = @mkdir( $this->BASE_CACHE, 0755 );
-
- // if make failed
- if ( ! $status ) {
- $this->error(
- "Cache couldn't make dir '" . $this->BASE_CACHE . "'."
- );
- }
- }
- }
-
+ var $BASE_CACHE = './cache'; // where the cache files are stored
+ var $MAX_AGE = 3600; // when are files stale, default one hour
+ var $ERROR = ""; // accumulate error messages
+
+ function RSSCache ($base='', $age='') {
+ if ( $base ) {
+ $this->BASE_CACHE = $base;
+ }
+ if ( $age ) {
+ $this->MAX_AGE = $age;
+ }
+
+ // attempt to make the cache directory
+ if ( ! file_exists( $this->BASE_CACHE ) ) {
+ $status = @mkdir( $this->BASE_CACHE, 0755 );
+
+ // if make failed
+ if ( ! $status ) {
+ $this->error(
+ "Cache couldn't make dir '" . $this->BASE_CACHE . "'."
+ );
+ }
+ }
+ }
+
/*=======================================================================*\
- Function: set
- Purpose: add an item to the cache, keyed on url
- Input: url from wich the rss file was fetched
- Output: true on sucess
+ Function: set
+ Purpose: add an item to the cache, keyed on url
+ Input: url from wich the rss file was fetched
+ Output: true on sucess
\*=======================================================================*/
- function set ($url, $rss) {
- $this->ERROR = "";
- $cache_file = $this->file_name( $url );
- $fp = @fopen( $cache_file, 'w' );
-
- if ( ! $fp ) {
- $this->error(
- "Cache unable to open file for writing: $cache_file"
- );
- return 0;
- }
-
-
- $data = $this->serialize( $rss );
- fwrite( $fp, $data );
- fclose( $fp );
-
- return $cache_file;
- }
-
+ function set ($url, $rss) {
+ $this->ERROR = "";
+ $cache_file = $this->file_name( $url );
+ $fp = @fopen( $cache_file, 'w' );
+
+ if ( ! $fp ) {
+ $this->error(
+ "Cache unable to open file for writing: $cache_file"
+ );
+ return 0;
+ }
+
+
+ $data = $this->serialize( $rss );
+ fwrite( $fp, $data );
+ fclose( $fp );
+
+ return $cache_file;
+ }
+
/*=======================================================================*\
- Function: get
- Purpose: fetch an item from the cache
- Input: url from wich the rss file was fetched
- Output: cached object on HIT, false on MISS
-\*=======================================================================*/
- function get ($url) {
- $this->ERROR = "";
- $cache_file = $this->file_name( $url );
-
- if ( ! file_exists( $cache_file ) ) {
- $this->debug(
- "Cache doesn't contain: $url (cache file: $cache_file)"
- );
- return 0;
- }
-
- $fp = @fopen($cache_file, 'r');
- if ( ! $fp ) {
- $this->error(
- "Failed to open cache file for reading: $cache_file"
- );
- return 0;
- }
-
- $data = fread( $fp, filesize($cache_file) );
- $rss = $this->unserialize( $data );
-
- return $rss;
- }
+ Function: get
+ Purpose: fetch an item from the cache
+ Input: url from wich the rss file was fetched
+ Output: cached object on HIT, false on MISS
+\*=======================================================================*/
+ function get ($url) {
+ $this->ERROR = "";
+ $cache_file = $this->file_name( $url );
+
+ if ( ! file_exists( $cache_file ) ) {
+ $this->debug(
+ "Cache doesn't contain: $url (cache file: $cache_file)"
+ );
+ return 0;
+ }
+
+ $fp = @fopen($cache_file, 'r');
+ if ( ! $fp ) {
+ $this->error(
+ "Failed to open cache file for reading: $cache_file"
+ );
+ return 0;
+ }
+
+ $data = fread( $fp, filesize($cache_file) );
+ $rss = $this->unserialize( $data );
+
+ return $rss;
+ }
/*=======================================================================*\
- Function: check_cache
- Purpose: check a url for membership in the cache
- and whether the object is older then MAX_AGE (ie. STALE)
- Input: url from wich the rss file was fetched
- Output: cached object on HIT, false on MISS
-\*=======================================================================*/
- function check_cache ( $url ) {
- $this->ERROR = "";
- $filename = $this->file_name( $url );
-
- if ( file_exists( $filename ) ) {
- // find how long ago the file was added to the cache
- // and whether that is longer then MAX_AGE
- $mtime = filemtime( $filename );
- $age = time() - $mtime;
- if ( $this->MAX_AGE > $age ) {
- // object exists and is current
- return 'HIT';
- }
- else {
- // object exists but is old
- return 'STALE';
- }
- }
- else {
- // object does not exist
- return 'MISS';
- }
- }
+ Function: check_cache
+ Purpose: check a url for membership in the cache
+ and whether the object is older then MAX_AGE (ie. STALE)
+ Input: url from wich the rss file was fetched
+ Output: cached object on HIT, false on MISS
+\*=======================================================================*/
+ function check_cache ( $url ) {
+ $this->ERROR = "";
+ $filename = $this->file_name( $url );
+
+ if ( file_exists( $filename ) ) {
+ // find how long ago the file was added to the cache
+ // and whether that is longer then MAX_AGE
+ $mtime = filemtime( $filename );
+ $age = time() - $mtime;
+ if ( $this->MAX_AGE > $age ) {
+ // object exists and is current
+ return 'HIT';
+ }
+ else {
+ // object exists but is old
+ return 'STALE';
+ }
+ }
+ else {
+ // object does not exist
+ return 'MISS';
+ }
+ }
/*=======================================================================*\
- Function: serialize
-\*=======================================================================*/
- function serialize ( $rss ) {
- return serialize( $rss );
- }
+ Function: serialize
+\*=======================================================================*/
+ function serialize ( $rss ) {
+ return serialize( $rss );
+ }
/*=======================================================================*\
- Function: unserialize
-\*=======================================================================*/
- function unserialize ( $data ) {
- return unserialize( $data );
- }
-
+ Function: unserialize
+\*=======================================================================*/
+ function unserialize ( $data ) {
+ return unserialize( $data );
+ }
+
/*=======================================================================*\
- Function: file_name
- Purpose: map url to location in cache
- Input: url from wich the rss file was fetched
- Output: a file name
-\*=======================================================================*/
- function file_name ($url) {
- $filename = md5( $url );
- return join( DIRECTORY_SEPARATOR, array( $this->BASE_CACHE, $filename ) );
- }
+ Function: file_name
+ Purpose: map url to location in cache
+ Input: url from wich the rss file was fetched
+ Output: a file name
+\*=======================================================================*/
+ function file_name ($url) {
+ $filename = md5( $url );
+ return join( DIRECTORY_SEPARATOR, array( $this->BASE_CACHE, $filename ) );
+ }
/*=======================================================================*\
- Function: error
- Purpose: register error
-\*=======================================================================*/
- function error ($errormsg, $lvl=E_USER_WARNING) {
- // append PHP's error message if track_errors enabled
- if ( isset($php_errormsg) ) {
- $errormsg .= " ($php_errormsg)";
- }
- $this->ERROR = $errormsg;
- if ( MAGPIE_DEBUG ) {
- trigger_error( $errormsg, $lvl);
- }
- else {
- error_log( $errormsg, 0);
- }
- }
-
- function debug ($debugmsg, $lvl=E_USER_NOTICE) {
- if ( MAGPIE_DEBUG ) {
- $this->error("MagpieRSS [debug] $debugmsg", $lvl);
- }
- }
+ Function: error
+ Purpose: register error
+\*=======================================================================*/
+ function error ($errormsg, $lvl=E_USER_WARNING) {
+ // append PHP's error message if track_errors enabled
+ if ( isset($php_errormsg) ) {
+ $errormsg .= " ($php_errormsg)";
+ }
+ $this->ERROR = $errormsg;
+ if ( MAGPIE_DEBUG ) {
+ trigger_error( $errormsg, $lvl);
+ }
+ else {
+ error_log( $errormsg, 0);
+ }
+ }
+
+ function debug ($debugmsg, $lvl=E_USER_NOTICE) {
+ if ( MAGPIE_DEBUG ) {
+ $this->error("MagpieRSS [debug] $debugmsg", $lvl);
+ }
+ }
}
diff --git a/htdocs/includes/magpierss/rss_fetch.inc b/htdocs/includes/magpierss/rss_fetch.inc
index 29d4b0bb890..8a919811e65 100644
--- a/htdocs/includes/magpierss/rss_fetch.inc
+++ b/htdocs/includes/magpierss/rss_fetch.inc
@@ -5,7 +5,7 @@
to fetching and parsing RSS files, via the
function fetch_rss()
* Author: Kellan Elliott-McCrea
- * Version: 0.51
+ * Modified by Laurent Destailleur for Dolibarr
* License: GPL
*
* The lastest version of MagpieRSS can be obtained from:
@@ -82,7 +82,7 @@ require_once( MAGPIE_EXTLIB . 'Snoopy.class.inc');
version will be return, if it exists (and if MAGPIE_CACHE_FRESH_ONLY is off)
\*=======================================================================*/
-define('MAGPIE_VERSION', '0.51');
+define('MAGPIE_VERSION', '0.7');
$MAGPIE_ERROR = "";
@@ -117,10 +117,8 @@ function fetch_rss ($url) {
$cache = new RSSCache( MAGPIE_CACHE_DIR, MAGPIE_CACHE_AGE );
- if ($cache->ERROR) {
- // Erreur
- print $cache->ERROR;
- if (MAGPIE_DEBUG) { debug($cache->ERROR, E_USER_WARNING); }
+ if (MAGPIE_DEBUG and $cache->ERROR) {
+ debug($cache->ERROR, E_USER_WARNING);
}
@@ -129,15 +127,20 @@ function fetch_rss ($url) {
$rss = 0; // parsed RSS object
$errormsg = 0; // errors, if any
+ // store parsed XML by desired output encoding
+ // as character munging happens at parse time
+ $cache_key = $url . MAGPIE_OUTPUT_ENCODING;
+
if (!$cache->ERROR) {
// return cache HIT, MISS, or STALE
- $cache_status = $cache->check_cache( $url );
+ $cache_status = $cache->check_cache( $cache_key);
}
// if object cached, and cache is fresh, return cached obj
if ( $cache_status == 'HIT' ) {
- $rss = $cache->get( $url );
+ $rss = $cache->get( $cache_key );
if ( isset($rss) and $rss ) {
+ // should be cache age
$rss->from_cache = 1;
if ( MAGPIE_DEBUG > 1) {
debug("MagpieRSS: Cache HIT", E_USER_NOTICE);
@@ -150,8 +153,8 @@ function fetch_rss ($url) {
// setup headers
if ( $cache_status == 'STALE' ) {
- $rss = $cache->get( $url );
- if ( $rss->etag and $rss->last_modified ) {
+ $rss = $cache->get( $cache_key );
+ if ( $rss and $rss->etag and $rss->last_modified ) {
$request_headers['If-None-Match'] = $rss->etag;
$request_headers['If-Last-Modified'] = $rss->last_modified;
}
@@ -166,7 +169,7 @@ function fetch_rss ($url) {
debug("Got 304 for $url");
}
// reset cache on 304 (at minutillo insistent prodding)
- $cache->set($url, $rss);
+ $cache->set($cache_key, $rss);
return $rss;
}
elseif ( is_success( $resp->status ) ) {
@@ -176,18 +179,22 @@ function fetch_rss ($url) {
debug("Fetch successful");
}
// add object to cache
- $cache->set( $url, $rss );
+ $cache->set( $cache_key, $rss );
return $rss;
}
}
else {
- $errormsg = "Failed to fetch $url. ";
- if ( $resp->error ) {
+ $errormsg = "Failed to fetch $url ";
+ if ( $resp->status == '-100' ) {
+ $errormsg .= "(Request timed out after " . MAGPIE_FETCH_TIME_OUT . " seconds)";
+ }
+ elseif ( $resp->error ) {
# compensate for Snoopy's annoying habbit to tacking
# on '\n'
+ $http_error = substr($resp->error, 0, -2);
- // LDR FIX BUG
- $http_error = eregi_replace("\n","",$resp->error);
+ // LDR FIX BUG (plus necessaire car corrigé par ligne du dessus)
+ //$http_error = eregi_replace("\n","",$resp->error);
$errormsg .= "(HTTP Error: $http_error)";
}
@@ -198,7 +205,7 @@ function fetch_rss ($url) {
// LDR FIX BUG Si echec recup http mais cache bien lu, on stock erreur dans object rss
if ($rss) {
$rss->ERROR=$errormsg;
- if ($cache && $url) $rss->date=filemtime($cache->file_name($url));
+ if ($cache && $cache_key) $rss->date=filemtime($cache->file_name($url));
}
}
}
@@ -290,7 +297,7 @@ function _fetch_remote_file ($url, $headers = "" ) {
Output: parsed RSS object (see rss_parse)
\*=======================================================================*/
function _response_to_rss ($resp) {
- $rss = new MagpieRSS( $resp->results );
+ $rss = new MagpieRSS( $resp->results, MAGPIE_OUTPUT_ENCODING, MAGPIE_INPUT_ENCODING, MAGPIE_DETECT_ENCODING );
// if RSS parsed successfully
if ( $rss and !$rss->ERROR) {
@@ -339,11 +346,11 @@ function init () {
return;
}
else {
- define('MAGPIE_INITALIZED', 1);
+ define('MAGPIE_INITALIZED', true);
}
if ( !defined('MAGPIE_CACHE_ON') ) {
- define('MAGPIE_CACHE_ON', 1);
+ define('MAGPIE_CACHE_ON', true);
}
if ( !defined('MAGPIE_CACHE_DIR') ) {
@@ -372,9 +379,21 @@ function init () {
}
if ( !defined('MAGPIE_CACHE_FRESH_ONLY') ) {
- define('MAGPIE_CACHE_FRESH_ONLY', 0);
+ define('MAGPIE_CACHE_FRESH_ONLY', false);
}
+ if ( !defined('MAGPIE_OUTPUT_ENCODING') ) {
+ define('MAGPIE_OUTPUT_ENCODING', 'ISO-8859-1');
+ }
+
+ if ( !defined('MAGPIE_INPUT_ENCODING') ) {
+ define('MAGPIE_INPUT_ENCODING', null);
+ }
+
+ if ( !defined('MAGPIE_DETECT_ENCODING') ) {
+ define('MAGPIE_DETECT_ENCODING', true);
+ }
+
if ( !defined('MAGPIE_DEBUG') ) {
define('MAGPIE_DEBUG', 0);
}
diff --git a/htdocs/includes/magpierss/rss_parse.inc b/htdocs/includes/magpierss/rss_parse.inc
index 5566ecc53c3..af4020ebfb4 100644
--- a/htdocs/includes/magpierss/rss_parse.inc
+++ b/htdocs/includes/magpierss/rss_parse.inc
@@ -1,338 +1,589 @@
- * Version: 0.51
- * License: GPL
- *
- * The lastest version of MagpieRSS can be obtained from:
- * http://magpierss.sourceforge.net
- *
- * For questions, help, comments, discussion, etc., please join the
- * Magpie mailing list:
- * magpierss-general@lists.sourceforge.net
- *
- */
-
-/*
- * NOTES ON RSS PARSING PHILOSOPHY (moderately important):
- * MagpieRSS parse all versions of RSS with a few limitation (mod_content, and
- * mod_taxonomy support is shaky) into a simple object, with 2 fields,
- * the hash 'channel', and the array 'items'.
- *
- * MagpieRSS is a forgiving and inclusive parser. It currently makes no
- * attempt to enforce the validity on an RSS feed. It will include any
- * properly formatted tags it finds, allowing to you to mix RSS 0.93, with RSS
- * 1.0, with tags or your own imagining. This sort of witches brew is a bad
- * bad idea! But Magpie is less pendantic then I am.
- *
- * RSS validators are readily available on the web at:
- * http://feeds.archive.org/validator/
- * http://www.ldodds.com/rss_validator/1.0/validator.html
- *
- */
+/**
+* Project: MagpieRSS: a simple RSS integration tool
+* File: rss_parse.inc - parse an RSS or Atom feed
+* return as a simple object.
+*
+* Handles RSS 0.9x, RSS 2.0, RSS 1.0, and Atom 0.3
+*
+* The lastest version of MagpieRSS can be obtained from:
+* http://magpierss.sourceforge.net
+*
+* For questions, help, comments, discussion, etc., please join the
+* Magpie mailing list:
+* magpierss-general@lists.sourceforge.net
+*
+* @author Kellan Elliott-McCrea
+* @version 0.7a
+* @license GPL
+*
+*/
-/*
- * EXAMPLE PARSE RESULTS:
- *
- * Magpie tries to parse RSS into ease to use PHP datastructures.
- *
- * For example, Magpie on encountering RSS 1.0 item entry:
- *
- * -
- * Weekly Peace Vigil
- * http://protest.net/NorthEast/calendrome.cgi?span=event&ID=210257
- * Wear a white ribbon
- * Peace
- * 2002-06-01T11:00:00
- * Northampton, MA
- * 2002-06-01T12:00:00
- * Protest
- *
- *
- * Would transform it into the following associative array, and push it
- * onto the array $rss-items
- *
- * array(
- * title => 'Weekly Peace Vigil',
- * link =>
- * 'http://protest.net/NorthEast/calendrome.cgi?span=event&ID=210257',
- * description => 'Wear a white ribbon',
- * dc => array (
- * subject => 'Peace'
- * ),
- * ev => array (
- * startdate => '2002-06-01T11:00:00',
- * enddate => '2002-06-01T12:00:00',
- * type => 'Protest',
- * location => 'Northampton, MA'
- * )
- * )
- *
- */
+define('RSS', 'RSS');
+define('ATOM', 'Atom');
+require_once (MAGPIE_DIR . 'rss_utils.inc');
+
+/**
+* Hybrid parser, and object, takes RSS as a string and returns a simple object.
+*
+* see: rss_fetch.inc for a simpler interface with integrated caching support
+*
+*/
class MagpieRSS {
- /*
- * Hybrid parser, and object. (probably a bad idea! :)
- *
- * Useage Example:
- *
- * $some_rss = "channel['title'];
- *
- * // print the title of each item
- * foreach ($rss->items as $item ) {
- * echo $item[title];
- * }
- *
- * see rss_fetch.inc for a simpler interface
- */
-
- var $parser;
-
- var $current_item = array(); // item currently being parsed
- var $items = array(); // collection of parsed items
- var $channel = array(); // hash of channel fields
- var $textinput = array();
- var $image = array();
-
- var $parent_field = array('RDF');
- var $current_field = '';
- var $current_namespace = false;
-
- var $ERROR = "";
-
-/*======================================================================*\
- Function: MagpieRSS
- Purpose: Constructor, sets up XML parser,parses source,
- and populates object..
- Input: String containing the RSS to be parsed
-\*======================================================================*/
- function MagpieRSS ($source) {
-
- # if PHP xml isn't compiled in, die
- #
- if (!function_exists('xml_parser_create')) {
- $this->error( "Failed to load PHP's XML Extension. " .
- "http://www.php.net/manual/en/ref.xml.php",
- E_USER_ERROR );
- }
-
- $parser = @xml_parser_create();
-
- if (!is_resource($parser))
- {
- $this->error( "Failed to create an instance of PHP's XML parser. " .
- "http://www.php.net/manual/en/ref.xml.php",
- E_USER_ERROR );
- }
+ var $parser;
+
+ var $current_item = array(); // item currently being parsed
+ var $items = array(); // collection of parsed items
+ var $channel = array(); // hash of channel fields
+ var $textinput = array();
+ var $image = array();
+ var $feed_type;
+ var $feed_version;
+ var $encoding = ''; // output encoding of parsed rss
+
+ var $_source_encoding = ''; // only set if we have to parse xml prolog
+
+ var $ERROR = "";
+ var $WARNING = "";
+
+ // define some constants
+
+ var $_CONTENT_CONSTRUCTS = array('content', 'summary', 'info', 'title', 'tagline', 'copyright');
+ var $_KNOWN_ENCODINGS = array('UTF-8', 'US-ASCII', 'ISO-8859-1');
-
- $this->parser = $parser;
-
- # pass in parser, and a reference to this object
- # setup handlers
- #
- xml_set_object( $this->parser, $this );
- xml_set_element_handler($this->parser, 'start_element', 'end_element');
- xml_set_character_data_handler( $this->parser, 'cdata' );
-
-
- $status = xml_parse( $this->parser, $source );
-
- if (! $status ) {
- $errorcode = xml_get_error_code( $this->parser );
- if ( $errorcode != XML_ERROR_NONE ) {
- $xml_error = xml_error_string( $errorcode );
- $error_line = xml_get_current_line_number($this->parser);
- $error_col = xml_get_current_column_number($this->parser);
- $errormsg = "$xml_error at line $error_line, column $error_col";
+ // parser variables, useless if you're not a parser, treat as private
+ var $stack = array(); // parser stack
+ var $inchannel = false;
+ var $initem = false;
+ var $incontent = false; // if in Atom field
+ var $intextinput = false;
+ var $inimage = false;
+ var $current_field = '';
+ var $current_namespace = false;
+
- $this->error( $errormsg );
- }
- }
-
- xml_parser_free( $this->parser );
- }
-
- function start_element ($p, $element, &$attrs) {
- $element = strtolower( $element );
-
- # check for a namespace, and split if found
- #
- $namespace = false;
- if ( strpos( $element, ':' ) ) {
- list($namespace, $element) = split( ':', $element, 2);
- }
- $this->current_field = $element;
- if ( $namespace and $namespace != 'rdf' ) {
- $this->current_namespace = $namespace;
- }
-
- if ( $element == 'channel' ) {
- array_unshift( $this->parent_field, 'channel' );
- }
- elseif ( $element == 'items' ) {
- array_unshift( $this->parent_field, 'items' );
- }
- elseif ( $element == 'item' ) {
- array_unshift( $this->parent_field, 'item' );
- }
- elseif ( $element == 'textinput' ) {
- array_unshift( $this->parent_field, 'textinput' );
- }
- elseif ( $element == 'image' ) {
- array_unshift( $this->parent_field, 'image' );
- }
-
- }
-
- function end_element ($p, $element) {
- $element = strtolower($element);
-
- if ( $element == 'item' ) {
- $this->items[] = $this->current_item;
- $this->current_item = array();
- array_shift( $this->parent_field );
- }
- elseif ( $element == 'channel' or $element == 'items' or
- $element == 'textinput' or $element == 'image' ) {
- array_shift( $this->parent_field );
- }
-
- $this->current_field = '';
- $this->current_namespace = false;
- }
-
- function cdata ($p, $text) {
- # skip item, channel, items first time we see them
- #
- if ( $this->parent_field[0] == $this->current_field or
- ! $this->current_field ) {
- return;
- }
- elseif ( $this->parent_field[0] == 'channel') {
- if ( $this->current_namespace ) {
- $this->append(
- $this->channel[ $this->current_namespace ][ $this->current_field ],
- $text);
- }
- else {
- $this->append($this->channel[ $this->current_field ], $text);
- }
-
- }
- elseif ( $this->parent_field[0] == 'item' ) {
- if ( $this->current_namespace ) {
- $this->append(
- $this->current_item[ $this->current_namespace ][$this->current_field ],
- $text);
- }
- else {
- $this->append(
- $this->current_item[ $this->current_field ],
- $text );
- }
- }
- elseif ( $this->parent_field[0] == 'textinput' ) {
- if ( $this->current_namespace ) {
- $this->append(
- $this->textinput[ $this->current_namespace ][ $this->current_field ],
- $text );
- }
- else {
- $this->append(
- $this->textinput[ $this->current_field ],
- $text );
- }
- }
- elseif ( $this->parent_field[0] == 'image' ) {
- if ( $this->current_namespace ) {
- $this->append(
- $this->image[ $this->current_namespace ][ $this->current_field ],
- $text );
- }
- else {
- $this->append(
- $this->image[ $this->current_field ],
- $text );
- }
- }
- }
-
- function append (&$str1, $str2="") {
- if (!isset($str1) ) {
- $str1="";
- }
- $str1 .= $str2;
- }
-
- function error ($errormsg, $lvl=E_USER_WARNING) {
- // append PHP's error message if track_errors enabled
- if ( $php_errormsg ) {
- $errormsg .= " ($php_errormsg)";
- }
- $this->ERROR = $errormsg;
- if ( MAGPIE_DEBUG ) {
- trigger_error( $errormsg, $lvl);
- }
- else {
- error_log( $errormsg, 0);
- }
- }
-
+ /**
+ * Set up XML parser, parse source, and return populated RSS object..
+ *
+ * @param string $source string containing the RSS to be parsed
+ *
+ * NOTE: Probably a good idea to leave the encoding options alone unless
+ * you know what you're doing as PHP's character set support is
+ * a little weird.
+ *
+ * NOTE: A lot of this is unnecessary but harmless with PHP5
+ *
+ *
+ * @param string $output_encoding output the parsed RSS in this character
+ * set defaults to ISO-8859-1 as this is PHP's
+ * default.
+ *
+ * NOTE: might be changed to UTF-8 in future
+ * versions.
+ *
+ * @param string $input_encoding the character set of the incoming RSS source.
+ * Leave blank and Magpie will try to figure it
+ * out.
+ *
+ *
+ * @param bool $detect_encoding if false Magpie won't attempt to detect
+ * source encoding. (caveat emptor)
+ *
+ */
+ function MagpieRSS ($source, $output_encoding='ISO-8859-1',
+ $input_encoding=null, $detect_encoding=true)
+ {
+ # if PHP xml isn't compiled in, die
+ #
+ if (!function_exists('xml_parser_create')) {
+ $this->error( "Failed to load PHP's XML Extension. " .
+ "http://www.php.net/manual/en/ref.xml.php",
+ E_USER_ERROR );
+ }
+
+ list($parser, $source) = $this->create_parser($source,
+ $output_encoding, $input_encoding, $detect_encoding);
+
+
+ if (!is_resource($parser)) {
+ $this->error( "Failed to create an instance of PHP's XML parser. " .
+ "http://www.php.net/manual/en/ref.xml.php",
+ E_USER_ERROR );
+ }
-/*======================================================================*\
- EVERYTHING BELOW HERE IS FOR DEBUGGING PURPOSES
-\*======================================================================*/
- function show_list () {
- echo "\n";
- foreach ($this->items as $item) {
- echo "- ", $this->show_item( $item );
- }
- echo "
";
- }
-
- function show_channel () {
- echo "channel:
";
- echo "";
- while ( list($key, $value) = each( $this->channel ) ) {
- echo "- $key: $value";
- }
- echo "
";
- }
-
- function show_item ($item) {
- echo "item: $item[title]";
- echo "";
- while ( list($key, $value) = each($item) ) {
- if ( is_array($value) ) {
- echo "
$key";
- echo "";
- while ( list( $ns_key, $ns_value) = each( $value ) ) {
- echo "- $ns_key: $ns_value";
- }
- echo "
";
- }
- else {
- echo "- $key: $value";
- }
- }
- echo "
";
- }
+
+ $this->parser = $parser;
+
+ # pass in parser, and a reference to this object
+ # setup handlers
+ #
+ xml_set_object( $this->parser, $this );
+ xml_set_element_handler($this->parser,
+ 'feed_start_element', 'feed_end_element' );
+
+ xml_set_character_data_handler( $this->parser, 'feed_cdata' );
+
+ $status = xml_parse( $this->parser, $source );
+
+ if (! $status ) {
+ $errorcode = xml_get_error_code( $this->parser );
+ if ( $errorcode != XML_ERROR_NONE ) {
+ $xml_error = xml_error_string( $errorcode );
+ $error_line = xml_get_current_line_number($this->parser);
+ $error_col = xml_get_current_column_number($this->parser);
+ $errormsg = "$xml_error at line $error_line, column $error_col";
-/*======================================================================*\
- END DEBUGGING FUNCTIONS
-\*======================================================================*/
-
+ $this->error( $errormsg );
+ }
+ }
+
+ xml_parser_free( $this->parser );
+
+ $this->normalize();
+ }
+
+ function feed_start_element($p, $element, &$attrs) {
+ $el = $element = strtolower($element);
+ $attrs = array_change_key_case($attrs, CASE_LOWER);
+
+ // check for a namespace, and split if found
+ $ns = false;
+ if ( strpos( $element, ':' ) ) {
+ list($ns, $el) = split( ':', $element, 2);
+ }
+ if ( $ns and $ns != 'rdf' ) {
+ $this->current_namespace = $ns;
+ }
+
+ # if feed type isn't set, then this is first element of feed
+ # identify feed from root element
+ #
+ if (!isset($this->feed_type) ) {
+ if ( $el == 'rdf' ) {
+ $this->feed_type = RSS;
+ $this->feed_version = '1.0';
+ }
+ elseif ( $el == 'rss' ) {
+ $this->feed_type = RSS;
+ $this->feed_version = $attrs['version'];
+ }
+ elseif ( $el == 'feed' ) {
+ $this->feed_type = ATOM;
+ $this->feed_version = $attrs['version'];
+ $this->inchannel = true;
+ }
+ return;
+ }
+
+ if ( $el == 'channel' )
+ {
+ $this->inchannel = true;
+ }
+ elseif ($el == 'item' or $el == 'entry' )
+ {
+ $this->initem = true;
+ if ( isset($attrs['rdf:about']) ) {
+ $this->current_item['about'] = $attrs['rdf:about'];
+ }
+ }
+
+ // if we're in the default namespace of an RSS feed,
+ // record textinput or image fields
+ elseif (
+ $this->feed_type == RSS and
+ $this->current_namespace == '' and
+ $el == 'textinput' )
+ {
+ $this->intextinput = true;
+ }
+
+ elseif (
+ $this->feed_type == RSS and
+ $this->current_namespace == '' and
+ $el == 'image' )
+ {
+ $this->inimage = true;
+ }
+
+ # handle atom content constructs
+ elseif ( $this->feed_type == ATOM and in_array($el, $this->_CONTENT_CONSTRUCTS) )
+ {
+ // avoid clashing w/ RSS mod_content
+ if ($el == 'content' ) {
+ $el = 'atom_content';
+ }
+
+ $this->incontent = $el;
+
+
+ }
+
+ // if inside an Atom content construct (e.g. content or summary) field treat tags as text
+ elseif ($this->feed_type == ATOM and $this->incontent )
+ {
+ // if tags are inlined, then flatten
+ $attrs_str = join(' ',
+ array_map('map_attrs',
+ array_keys($attrs),
+ array_values($attrs) ) );
+
+ $this->append_content( "<$element $attrs_str>" );
+
+ array_unshift( $this->stack, $el );
+ }
+
+ // Atom support many links per containging element.
+ // Magpie treats link elements of type rel='alternate'
+ // as being equivalent to RSS's simple link element.
+ //
+ elseif ($this->feed_type == ATOM and $el == 'link' )
+ {
+ if ( isset($attrs['rel']) and $attrs['rel'] == 'alternate' )
+ {
+ $link_el = 'link';
+ }
+ else {
+ $link_el = 'link_' . $attrs['rel'];
+ }
+
+ $this->append($link_el, $attrs['href']);
+ }
+ // set stack[0] to current element
+ else {
+ array_unshift($this->stack, $el);
+ }
+ }
+
+
+
+ function feed_cdata ($p, $text) {
+
+ if ($this->feed_type == ATOM and $this->incontent)
+ {
+ $this->append_content( $text );
+ }
+ else {
+ $current_el = join('_', array_reverse($this->stack));
+ $this->append($current_el, $text);
+ }
+ }
+
+ function feed_end_element ($p, $el) {
+ $el = strtolower($el);
+
+ if ( $el == 'item' or $el == 'entry' )
+ {
+ $this->items[] = $this->current_item;
+ $this->current_item = array();
+ $this->initem = false;
+ }
+ elseif ($this->feed_type == RSS and $this->current_namespace == '' and $el == 'textinput' )
+ {
+ $this->intextinput = false;
+ }
+ elseif ($this->feed_type == RSS and $this->current_namespace == '' and $el == 'image' )
+ {
+ $this->inimage = false;
+ }
+ elseif ($this->feed_type == ATOM and in_array($el, $this->_CONTENT_CONSTRUCTS) )
+ {
+ $this->incontent = false;
+ }
+ elseif ($el == 'channel' or $el == 'feed' )
+ {
+ $this->inchannel = false;
+ }
+ elseif ($this->feed_type == ATOM and $this->incontent ) {
+ // balance tags properly
+ // note: i don't think this is actually neccessary
+ if ( $this->stack[0] == $el )
+ {
+ $this->append_content("$el>");
+ }
+ else {
+ $this->append_content("<$el />");
+ }
+
+ array_shift( $this->stack );
+ }
+ else {
+ array_shift( $this->stack );
+ }
+
+ $this->current_namespace = false;
+ }
+
+ function concat (&$str1, $str2="") {
+ if (!isset($str1) ) {
+ $str1="";
+ }
+ $str1 .= $str2;
+ }
+
+
+
+ function append_content($text) {
+ if ( $this->initem ) {
+ $this->concat( $this->current_item[ $this->incontent ], $text );
+ }
+ elseif ( $this->inchannel ) {
+ $this->concat( $this->channel[ $this->incontent ], $text );
+ }
+ }
+
+ // smart append - field and namespace aware
+ function append($el, $text) {
+ if (!$el) {
+ return;
+ }
+ if ( $this->current_namespace )
+ {
+ if ( $this->initem ) {
+ $this->concat(
+ $this->current_item[ $this->current_namespace ][ $el ], $text);
+ }
+ elseif ($this->inchannel) {
+ $this->concat(
+ $this->channel[ $this->current_namespace][ $el ], $text );
+ }
+ elseif ($this->intextinput) {
+ $this->concat(
+ $this->textinput[ $this->current_namespace][ $el ], $text );
+ }
+ elseif ($this->inimage) {
+ $this->concat(
+ $this->image[ $this->current_namespace ][ $el ], $text );
+ }
+ }
+ else {
+ if ( $this->initem ) {
+ $this->concat(
+ $this->current_item[ $el ], $text);
+ }
+ elseif ($this->intextinput) {
+ $this->concat(
+ $this->textinput[ $el ], $text );
+ }
+ elseif ($this->inimage) {
+ $this->concat(
+ $this->image[ $el ], $text );
+ }
+ elseif ($this->inchannel) {
+ $this->concat(
+ $this->channel[ $el ], $text );
+ }
+
+ }
+ }
+
+ function normalize () {
+ // if atom populate rss fields
+ if ( $this->is_atom() ) {
+ $this->channel['description'] = $this->channel['tagline'];
+ for ( $i = 0; $i < count($this->items); $i++) {
+ $item = $this->items[$i];
+ if ( isset($item['summary']) )
+ $item['description'] = $item['summary'];
+ if ( isset($item['atom_content']))
+ $item['content']['encoded'] = $item['atom_content'];
+
+ $atom_date = (isset($item['issued']) ) ? $item['issued'] : $item['modified'];
+ if ( $atom_date ) {
+ $epoch = @parse_w3cdtf($item['modified']);
+ if ($epoch and $epoch > 0) {
+ $item['date_timestamp'] = $epoch;
+ }
+ }
+
+ $this->items[$i] = $item;
+ }
+ }
+ elseif ( $this->is_rss() ) {
+ $this->channel['tagline'] = $this->channel['description'];
+ for ( $i = 0; $i < count($this->items); $i++) {
+ $item = $this->items[$i];
+ if ( isset($item['description']))
+ $item['summary'] = $item['description'];
+ if ( isset($item['content']['encoded'] ) )
+ $item['atom_content'] = $item['content']['encoded'];
+
+ if ( $this->is_rss() == '1.0' and isset($item['dc']['date']) ) {
+ $epoch = @parse_w3cdtf($item['dc']['date']);
+ if ($epoch and $epoch > 0) {
+ $item['date_timestamp'] = $epoch;
+ }
+ }
+ elseif ( isset($item['pubdate']) ) {
+ $epoch = @strtotime($item['pubdate']);
+ if ($epoch > 0) {
+ $item['date_timestamp'] = $epoch;
+ }
+ }
+
+ $this->items[$i] = $item;
+ }
+ }
+ }
+
+
+ function is_rss () {
+ if ( $this->feed_type == RSS ) {
+ return $this->feed_version;
+ }
+ else {
+ return false;
+ }
+ }
+
+ function is_atom() {
+ if ( $this->feed_type == ATOM ) {
+ return $this->feed_version;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * return XML parser, and possibly re-encoded source
+ *
+ */
+ function create_parser($source, $out_enc, $in_enc, $detect) {
+ if ( substr(phpversion(),0,1) == 5) {
+ $parser = $this->php5_create_parser($in_enc, $detect);
+ }
+ else {
+ list($parser, $source) = $this->php4_create_parser($source, $in_enc, $detect);
+ }
+ if ($out_enc) {
+ $this->encoding = $out_enc;
+ xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $out_enc);
+ }
+
+ return array($parser, $source);
+ }
+
+ /**
+ * Instantiate an XML parser under PHP5
+ *
+ * PHP5 will do a fine job of detecting input encoding
+ * if passed an empty string as the encoding.
+ *
+ * All hail libxml2!
+ *
+ */
+ function php5_create_parser($in_enc, $detect) {
+ // by default php5 does a fine job of detecting input encodings
+ if(!$detect && $in_enc) {
+ return xml_parser_create($in_enc);
+ }
+ else {
+ return xml_parser_create('');
+ }
+ }
+
+ /**
+ * Instaniate an XML parser under PHP4
+ *
+ * Unfortunately PHP4's support for character encodings
+ * and especially XML and character encodings sucks. As
+ * long as the documents you parse only contain characters
+ * from the ISO-8859-1 character set (a superset of ASCII,
+ * and a subset of UTF-8) you're fine. However once you
+ * step out of that comfy little world things get mad, bad,
+ * and dangerous to know.
+ *
+ * The following code is based on SJM's work with FoF
+ * @see http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss
+ *
+ */
+ function php4_create_parser($source, $in_enc, $detect) {
+ if ( !$detect ) {
+ return array(xml_parser_create($in_enc), $source);
+ }
+
+ if (!$in_enc) {
+ if (preg_match('//m', $source, $m)) {
+ $in_enc = strtoupper($m[1]);
+ $this->source_encoding = $in_enc;
+ }
+ else {
+ $in_enc = 'UTF-8';
+ }
+ }
+
+ if ($this->known_encoding($in_enc)) {
+ return array(xml_parser_create($in_enc), $source);
+ }
+
+ // the dectected encoding is not one of the simple encodings PHP knows
+
+ // attempt to use the iconv extension to
+ // cast the XML to a known encoding
+ // @see http://php.net/iconv
+
+ if (function_exists('iconv')) {
+ $encoded_source = iconv($in_enc,'UTF-8', $source);
+ if ($encoded_source) {
+ return array(xml_parser_create('UTF-8'), $encoded_source);
+ }
+ }
+
+ // iconv didn't work, try mb_convert_encoding
+ // @see http://php.net/mbstring
+ if(function_exists('mb_convert_encoding')) {
+ $encoded_source = mb_convert_encoding($source, 'UTF-8', $in_enc );
+ if ($encoded_source) {
+ return array(xml_parser_create('UTF-8'), $encoded_source);
+ }
+ }
+
+ // else
+ $this->error("Feed is in an unsupported character encoding. ($in_enc) " .
+ "You may see strange artifacts, and mangled characters.",
+ E_USER_NOTICE);
+
+ return array(xml_parser_create(), $source);
+ }
+
+ function known_encoding($enc) {
+ $enc = strtoupper($enc);
+ if ( in_array($enc, $this->_KNOWN_ENCODINGS) ) {
+ return $enc;
+ }
+ else {
+ return false;
+ }
+ }
+
+ function error ($errormsg, $lvl=E_USER_WARNING) {
+ // append PHP's error message if track_errors enabled
+ if ( $php_errormsg ) {
+ $errormsg .= " ($php_errormsg)";
+ }
+ if ( MAGPIE_DEBUG ) {
+ trigger_error( $errormsg, $lvl);
+ }
+ else {
+ error_log( $errormsg, 0);
+ }
+
+ $notices = E_USER_NOTICE|E_NOTICE;
+ if ( $lvl&$notices ) {
+ $this->WARNING = $errormsg;
+ } else {
+ $this->ERROR = $errormsg;
+ }
+ }
+
+
+} // end class RSS
+
+function map_attrs($k, $v) {
+ return "$k=\"$v\"";
+}
-} # end class RSS
?>
diff --git a/htdocs/includes/magpierss/rss_utils.inc b/htdocs/includes/magpierss/rss_utils.inc
index 655db8a1921..2a29e72a969 100644
--- a/htdocs/includes/magpierss/rss_utils.inc
+++ b/htdocs/includes/magpierss/rss_utils.inc
@@ -3,8 +3,8 @@
* Project: MagpieRSS: a simple RSS integration tool
* File: rss_utils.inc, utility methods for working with RSS
* Author: Kellan Elliott-McCrea
- * Version: 0.51
- * License: GPL
+ * Version: 0.51
+ * License: GPL
*
* The lastest version of MagpieRSS can be obtained from:
* http://magpierss.sourceforge.net
@@ -19,49 +19,49 @@
Function: parse_w3cdtf
Purpose: parse a W3CDTF date into unix epoch
- NOTE: http://www.w3.org/TR/NOTE-datetime
+ NOTE: http://www.w3.org/TR/NOTE-datetime
\*======================================================================*/
function parse_w3cdtf ( $date_str ) {
-
- # regex to match wc3dtf
- $pat = "/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(:(\d{2}))?(?:([-+])(\d{2}):?(\d{2})|(Z))?/";
-
- if ( preg_match( $pat, $date_str, $match ) ) {
- list( $year, $month, $day, $hours, $minutes, $seconds) =
- array( $match[1], $match[2], $match[3], $match[4], $match[5], $match[6]);
-
- # calc epoch for current date assuming GMT
- $epoch = gmmktime( $hours, $minutes, $seconds, $month, $day, $year);
-
- $offset = 0;
- if ( $match[10] == 'Z' ) {
- # zulu time, aka GMT
- }
- else {
- list( $tz_mod, $tz_hour, $tz_min ) =
- array( $match[8], $match[9], $match[10]);
-
- # zero out the variables
- if ( ! $tz_hour ) { $tz_hour = 0; }
- if ( ! $tz_min ) { $tz_min = 0; }
-
- $offset_secs = (($tz_hour*60)+$tz_min)*60;
-
- # is timezone ahead of GMT? then subtract offset
- #
- if ( $tz_mod == '+' ) {
- $offset_secs = $offset_secs * -1;
- }
-
- $offset = $offset_secs;
- }
- $epoch = $epoch + $offset;
- return $epoch;
- }
- else {
- return -1;
- }
+
+ # regex to match wc3dtf
+ $pat = "/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(:(\d{2}))?(?:([-+])(\d{2}):?(\d{2})|(Z))?/";
+
+ if ( preg_match( $pat, $date_str, $match ) ) {
+ list( $year, $month, $day, $hours, $minutes, $seconds) =
+ array( $match[1], $match[2], $match[3], $match[4], $match[5], $match[6]);
+
+ # calc epoch for current date assuming GMT
+ $epoch = gmmktime( $hours, $minutes, $seconds, $month, $day, $year);
+
+ $offset = 0;
+ if ( $match[10] == 'Z' ) {
+ # zulu time, aka GMT
+ }
+ else {
+ list( $tz_mod, $tz_hour, $tz_min ) =
+ array( $match[8], $match[9], $match[10]);
+
+ # zero out the variables
+ if ( ! $tz_hour ) { $tz_hour = 0; }
+ if ( ! $tz_min ) { $tz_min = 0; }
+
+ $offset_secs = (($tz_hour*60)+$tz_min)*60;
+
+ # is timezone ahead of GMT? then subtract offset
+ #
+ if ( $tz_mod == '+' ) {
+ $offset_secs = $offset_secs * -1;
+ }
+
+ $offset = $offset_secs;
+ }
+ $epoch = $epoch + $offset;
+ return $epoch;
+ }
+ else {
+ return -1;
+ }
}
?>