Source for file rss_fetch.inc
Documentation is available at rss_fetch.inc
* Project: MagpieRSS: a simple RSS integration tool
* File: rss_fetch.inc, a simple functional interface
to fetching and parsing RSS files, via the
* Author: Kellan Elliott-McCrea <kellan@protest.net>
* The lastest version of MagpieRSS can be obtained from:
* http://magpierss.sourceforge.net
* For questions, help, comments, discussion, etc., please join the
* magpierss-general@lists.sourceforge.net
// Setup MAGPIE_DIR for use on hosts that don't include
// the current path in include_path.
// with thanks to rajiv and smarty
define('DIR_SEP', DIRECTORY_SEPARATOR);
define('MAGPIE_DIR', dirname(__FILE__
) .
DIR_SEP);
require_once( MAGPIE_DIR .
'rss_parse.inc' );
require_once( MAGPIE_DIR .
'rss_cache.inc' );
// for including 3rd party libraries
define('MAGPIE_EXTLIB', MAGPIE_DIR .
'extlib' .
DIR_SEP);
require_once( MAGPIE_EXTLIB .
'Snoopy.class.inc');
* CONSTANTS - redefine these in your script to change the
* behaviour of fetch_rss() currently, most options effect the cache
* MAGPIE_CACHE_ON - Should Magpie cache parsed RSS objects?
* For me a built in cache was essential to creating a "PHP-like"
* feel to Magpie, see rss_cache.inc for rationale
* MAGPIE_CACHE_DIR - Where should Magpie cache parsed RSS objects?
* This should be a location that the webserver can write to. If this
* directory does not already exist Mapie will try to be smart and create
* it. This will often fail for permissions reasons.
* MAGPIE_CACHE_AGE - How long to store cached RSS objects? In seconds.
* MAGPIE_CACHE_FRESH_ONLY - If remote fetch fails, throw error
* instead of returning stale object?
* MAGPIE_DEBUG - Display debugging notices?
/*=======================================================================*\
Purpose: return RSS object for the give url
Output: parsed RSS object (see rss_parse.inc)
If caching is on (MAGPIE_CACHE_ON) fetch_rss will first check the cache.
NOTES ON RETRIEVING REMOTE FILES:
If conditional gets are on (MAGPIE_CONDITIONAL_GET_ON) fetch_rss will
return a cached object, and touch the cache object upon recieving a
NOTES ON FAILED REQUESTS:
If there is an HTTP error while fetching an RSS object, the cached
version will be return, if it exists (and if MAGPIE_CACHE_FRESH_ONLY is off)
\*=======================================================================*/
define('MAGPIE_VERSION', '0.72');
error("fetch_rss called without a url");
if ( !MAGPIE_CACHE_ON ) {
// fetch file, and parse it
error("Failed to fetch $url and cache is off");
// 2. if there is a hit, make sure its fresh
// 3. if cached obj fails freshness check, fetch remote
// 4. if remote fails, return stale object, or error
debug($cache->ERROR, E_USER_WARNING);
$cache_status =
0; // response of check_cache
$request_headers =
array(); // HTTP headers to send with fetch
$rss =
0; // parsed RSS object
$errormsg =
0; // errors, if any
// store parsed XML by desired output encoding
// as character munging happens at parse time
// return cache HIT, MISS, or STALE
$cache_status =
$cache->check_cache( $cache_key);
// if object cached, and cache is fresh, return cached obj
if ( $cache_status ==
'HIT' ) {
$rss =
$cache->get( $cache_key );
if ( isset
($rss) and $rss ) {
debug("MagpieRSS: Cache HIT", E_USER_NOTICE);
// else attempt a conditional get
if ( $cache_status ==
'STALE' ) {
$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;
if (isset
($resp) and $resp) {
if ($resp->status ==
'304' ) {
// we have the most current copy
debug("Got 304 for $url");
// reset cache on 304 (at minutillo insistent prodding)
$cache->set($cache_key, $rss);
debug("Fetch successful");
$cache->set( $cache_key, $rss );
$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
$errormsg .=
"(HTTP Error: $http_error)";
$errormsg .=
"(HTTP Response: " .
$resp->response_code .
')';
$errormsg =
"Unable to retrieve RSS file for unknown reasons.";
// attempt to return cached object
debug("Returning STALE object for $url");
// else we totally failed
} // end if ( !MAGPIE_CACHE_ON ) {
/*=======================================================================*\
Purpose: set MAGPIE_ERROR, and trigger error
\*=======================================================================*/
function error ($errormsg, $lvl=
E_USER_WARNING) {
// append PHP's error message if track_errors enabled
if ( isset
($php_errormsg) ) {
$errormsg .=
" ($php_errormsg)";
$errormsg =
"MagpieRSS: $errormsg";
$MAGPIE_ERROR =
$errormsg;
function debug ($debugmsg, $lvl=
E_USER_NOTICE) {
/*=======================================================================*\
Purpose: accessor for the magpie error variable
\*=======================================================================*/
if ( isset
($errormsg) and $errormsg ) {
$MAGPIE_ERROR =
$errormsg;
/*=======================================================================*\
Function: _fetch_remote_file
Purpose: retrieve an arbitrary remote file
Input: url of the remote file
headers to send along with the request (optional)
Output: an HTTP response object (see Snoopy.class.inc)
\*=======================================================================*/
// Snoopy is an HTTP client in PHP
$client->agent =
MAGPIE_USER_AGENT;
$client->read_timeout =
MAGPIE_FETCH_TIME_OUT;
$client->use_gzip =
MAGPIE_USE_GZIP;
$client->rawheaders =
$headers;
/*=======================================================================*\
Function: _response_to_rss
Purpose: parse an HTTP response object into an RSS object
Input: an HTTP response object (see Snoopy)
Output: parsed RSS object (see rss_parse)
\*=======================================================================*/
// if RSS parsed successfully
if ( $rss and !$rss->ERROR) {
// find Etag, and Last-Modified
foreach($resp->headers as $h) {
// 2003-03-02 - Nicola Asuni (www.tecnick.com) - fixed bug "Undefined offset: 1"
list
($field, $val) =
explode(": ", $h, 2);
if ( $field ==
'ETag' ) {
if ( $field ==
'Last-Modified' ) {
$rss->last_modified =
$val;
} // else construct error message
$errormsg =
"Failed to parse RSS file.";
$errormsg .=
" (" .
$rss->ERROR .
")";
} // end if ($rss and !$rss->error)
/*=======================================================================*\
Purpose: setup constants with default values
\*=======================================================================*/
if ( defined('MAGPIE_INITALIZED') ) {
define('MAGPIE_INITALIZED', true);
if ( !defined('MAGPIE_CACHE_ON') ) {
define('MAGPIE_CACHE_ON', true);
if ( !defined('MAGPIE_CACHE_DIR') ) {
define('MAGPIE_CACHE_DIR', './cache');
if ( !defined('MAGPIE_CACHE_AGE') ) {
define('MAGPIE_CACHE_AGE', 60*
60); // one hour
if ( !defined('MAGPIE_CACHE_FRESH_ONLY') ) {
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_USER_AGENT') ) {
$ua =
$ua .
'; No cache)';
define('MAGPIE_USER_AGENT', $ua);
if ( !defined('MAGPIE_FETCH_TIME_OUT') ) {
define('MAGPIE_FETCH_TIME_OUT', 5); // 5 second timeout
// use gzip encoding to fetch rss files if supported?
if ( !defined('MAGPIE_USE_GZIP') ) {
define('MAGPIE_USE_GZIP', true);
// NOTE: the following code should really be in Snoopy, or at least
// somewhere other then rss_fetch!
/*=======================================================================*\
HTTP STATUS CODE PREDICATES
These functions attempt to classify an HTTP status code
based on RFC 2616 and RFC 2518.
All of them take an HTTP status code as input, and return true or false
All this code is adapted from LWP's HTTP::Status.
\*=======================================================================*/
/*=======================================================================*\
Purpose: return true if Informational status code
\*=======================================================================*/
return $sc >=
100 &&
$sc <
200;
/*=======================================================================*\
Purpose: return true if Successful status code
\*=======================================================================*/
return $sc >=
200 &&
$sc <
300;
/*=======================================================================*\
Purpose: return true if Redirection status code
\*=======================================================================*/
return $sc >=
300 &&
$sc <
400;
/*=======================================================================*\
Purpose: return true if Error status code
\*=======================================================================*/
return $sc >=
400 &&
$sc <
600;
/*=======================================================================*\
Function: is_client_error
Purpose: return true if Error status code, and its a client error
\*=======================================================================*/
return $sc >=
400 &&
$sc <
500;
/*=======================================================================*\
Function: is_client_error
Purpose: return true if Error status code, and its a server error
\*=======================================================================*/
return $sc >=
500 &&
$sc <
600;
Documentation generated on Tue, 01 May 2007 16:47:09 +0200 by phpDocumentor 1.3.2