[ Index ]
 

Code source de Serendipity 1.2

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/bundled-libs/Onyx/ -> RSS.php (source)

   1  <?php
   2  
   3  /* Copyright 2002-2003 Edward Swindelles (ed@readinged.com)
   4   *
   5   * This program is free software; you can redistribute it and/or modify
   6   * it under the terms of the GNU General Public License as published by
   7   * the Free Software Foundation; either version 2 of the License, or
   8   * (at your option) any later version.
   9   *
  10   * This program is distributed in the hope that it will be useful,
  11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13   * GNU General Public License for more details.
  14   *
  15   * You should have received a copy of the GNU General Public License
  16   * along with this program; if not, write to the Free Software
  17   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18  */
  19  
  20  if (!defined('ONYX_RSS_VERS'))
  21  {
  22     define('ONYX_RSS_VERS', '1.0');
  23     define('ONYX_ERR_NO_PARSER', '<a href="http://www.php.net/manual/en/ref.xml.php">PHP\'s XML Extension</a> is not loaded or available.');
  24     define('ONYX_ERR_NOT_WRITEABLE', 'The specified cache directory is not writeable.');
  25     define('ONYX_ERR_INVALID_URI', 'The specified file could not be opened.');
  26     define('ONYX_ERR_INVALID_ITEM', 'Invalid item index specified.');
  27     define('ONYX_ERR_NO_STREAM', 'Could not open the specified file.  Check the path, and make sure that you have write permissions to this file.');
  28     define('ONYX_META', 'meta');
  29     define('ONYX_ITEMS', 'items');
  30     define('ONYX_IMAGE', 'image');
  31     define('ONYX_TEXTINPUT', 'textinput');
  32     define('ONYX_NAMESPACES', 'namespaces');
  33     define('ONYX_CACHE_AGE', 'cache_age');
  34     define('ONYX_FETCH_ASSOC', 1);
  35     define('ONYX_FETCH_OBJECT', 2);
  36  }
  37  
  38  class ONYX_RSS
  39  {
  40     var $parser;
  41     var $conf;
  42     var $rss;
  43     var $data;
  44     var $type;
  45     /* For when PHP v.5 is released
  46      * http://www.phpvolcano.com/eide/php5.php?page=variables
  47      * private $parser;
  48      * private $conf;
  49      * private $rss;
  50      * private $data;
  51      * private $type;
  52     */
  53  
  54     function ONYX_RSS($charset = 'UTF-8')
  55     {
  56        $this->__construct($charset);
  57     }
  58  
  59     // Forward compatibility with PHP v.5
  60     // http://www.phpvolcano.com/eide/php5.php?page=start
  61     function __construct($charset = 'UTF-8')
  62     {
  63        $this->conf = array();
  64        $this->conf['error'] = '<br /><strong>Error on line %s of '.__FILE__.'</strong>: %s<br />';
  65        $this->conf['cache_path'] = dirname(__FILE__);
  66        $this->conf['cache_time'] = 180;
  67        $this->conf['debug_mode'] = true;
  68        $this->conf['fetch_mode'] = ONYX_FETCH_ASSOC;
  69  
  70        if (!function_exists('xml_parser_create'))
  71        {
  72           $this->raiseError((__LINE__-2), ONYX_ERR_NO_PARSER);
  73           return false;
  74        }
  75  
  76        if ($charset == 'native') {
  77           $charset = LANG_CHARSET;
  78        }
  79        $this->parser = @xml_parser_create($charset);
  80        if (!is_resource($this->parser))
  81        {
  82           $this->raiseError((__LINE__-3), ONYX_ERR_NO_PARSER);
  83           return false;
  84        }
  85        xml_set_object($this->parser, $this);
  86        xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
  87        @xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, LANG_CHARSET);
  88        xml_set_element_handler($this->parser, 'tag_open', 'tag_close');
  89        xml_set_character_data_handler($this->parser, 'cdata');
  90     }
  91  
  92     function parse($uri, $file=false, $time=false, $local=false)
  93     {
  94        $this->rss = array();
  95        $this->rss['cache_age'] = 0;
  96        $this->rss['current_tag'] = '';
  97        $this->rss['index'] = 0;
  98        $this->rss['output_index'] = -1;
  99        $this->data = array();
 100  
 101        if ($file)
 102        {
 103           if (!is_writeable($this->conf['cache_path']))
 104           {
 105              $this->raiseError((__LINE__-2), ONYX_ERR_NOT_WRITEABLE);
 106              return false;
 107           }
 108           $file = str_replace('//', '/', $this->conf['cache_path'].'/'.$file);
 109           if (!$time)
 110              $time = $this->conf['cache_time'];
 111           $this->rss['cache_age'] = file_exists($file) ? ceil((time() - filemtime($file)) / 60) : 0;
 112  
 113           clearstatcache();
 114           if (!$local && file_exists($file))
 115              if (($mod = $this->mod_time($uri)) === false)
 116              {
 117                 $this->raiseError((__LINE__-2), ONYX_ERR_INVALID_URI);
 118                 return false;
 119              }
 120              else
 121                 $mod = ($mod !== 0) ? strtotime($mod) : (time()+3600);
 122           elseif ($local)
 123              $mod = (file_exists($file) && ($m = filemtime($uri))) ? $m : time()+3600;
 124        }
 125        if ( !$file ||
 126             ($file && !file_exists($file)) ||
 127             ($file && file_exists($file) && $time <= $this->rss['cache_age'] && $mod >= (time() - ($this->rss['cache_age'] * 60))))
 128        {
 129           clearstatcache();
 130           
 131           require_once S9Y_PEAR_PATH . 'HTTP/Request.php';
 132           serendipity_request_start();
 133           $req = &new HTTP_Request($uri, array('allowRedirects' => true, 'maxRedirects' => 5));
 134           $res = $req->sendRequest();
 135          
 136           if (PEAR::isError($res) || $req->getResponseCode() != '200')
 137           {
 138              serendipity_request_end();
 139              $this->raiseError((__LINE__-2), ONYX_ERR_INVALID_URI . ' (#' . $req->getResponseCode() . ')');
 140              return false;
 141           }
 142  
 143           $fContent = $req->getResponseBody();
 144           serendipity_request_end();
 145           if (@preg_match('@<?xml[^>]*encoding="([^"]+)"@i', $fContent, $xml_encoding)) {
 146              $this->rss['encoding'] = strtolower($xml_encoding[1]);
 147           }
 148  
 149           $parsedOkay = xml_parse($this->parser, $fContent, true);
 150           if (!$parsedOkay && xml_get_error_code($this->parser) != XML_ERROR_NONE)
 151           {
 152              $this->raiseError((__LINE__-3), 'File has an XML error (<em>'.xml_error_string(xml_get_error_code($this->parser)).'</em> at line <em>'.xml_get_current_line_number($this->parser).'</em>).');
 153              return false;
 154           }
 155  
 156           clearstatcache();
 157           if ($file)
 158           {
 159              if (!($cache = @fopen($file, 'w')))
 160              {
 161                 $this->raiseError((__LINE__-2), 'Could not write to cache file (<em>'.$file.'</em>).  The path may be invalid or you may not have write permissions.');
 162                 return false;
 163              }
 164              fwrite($cache, serialize($this->data));
 165              fclose($cache);
 166              $this->rss['cache_age'] = 0;
 167           }
 168        }
 169        else
 170        {
 171           clearstatcache();
 172           if (!($fp = @fopen($file, 'r')))
 173           {
 174              $this->raiseError((__LINE__-2), 'Could not read contents of cache file (<em>'.$cache_file.'</em>).');
 175              return false;
 176           }
 177           $this->data = unserialize(fread($fp, filesize($file)));
 178           fclose($fp);
 179        }
 180        return true;
 181     }
 182  
 183     function parseLocal($uri, $file=false, $time=false)
 184     {
 185        return $this->parse($uri, $file, $time, true);
 186     }
 187  
 188     //private function tag_open($parser, $tag, $attrs)
 189     function tag_open($parser, $tag, $attrs)
 190     {
 191        $this->rss['current_tag'] = $tag = strtolower($tag);
 192        switch ($tag)
 193        {
 194           case 'channel':
 195           case 'image':
 196           case 'textinput':
 197              $this->type = $tag;
 198              break;
 199           case 'item':
 200              $this->type = $tag;
 201              $this->rss['index']++;
 202              break;
 203           default:
 204              break;
 205        }
 206        if (sizeof($attrs))
 207           foreach ($attrs as $k => $v)
 208              if (strpos($k, 'xmlns') !== false)
 209                 $this->data['namespaces'][$k] = $v;
 210     }
 211  
 212     //private function tag_close($parser, $tag){}
 213     function tag_close($parser, $tag){}
 214  
 215     //private function cdata($parser, $cdata)
 216     function cdata($parser, $cdata)
 217     {
 218        if (strlen(trim($cdata)) && $cdata != "\n")
 219           switch ($this->type)
 220           {
 221              case 'channel':
 222              case 'image':
 223              case 'textinput':
 224                 (!isset($this->data[$this->type][$this->rss['current_tag']]) ||
 225                  !strlen($this->data[$this->type][$this->rss['current_tag']])) ?
 226                    $this->data[$this->type][$this->rss['current_tag']] = $cdata :
 227                    $this->data[$this->type][$this->rss['current_tag']].= $cdata;
 228                 break;
 229              case 'item':
 230                 (!isset($this->data['items'][$this->rss['index']-1][$this->rss['current_tag']]) ||
 231                  !strlen($this->data['items'][$this->rss['index']-1][$this->rss['current_tag']])) ?
 232                    $this->data['items'][$this->rss['index']-1][$this->rss['current_tag']] = $cdata :
 233                    $this->data['items'][$this->rss['index']-1][$this->rss['current_tag']].= $cdata;
 234                 break;
 235           }
 236     }
 237  
 238     function getData($type)
 239     {
 240        if ($type == ONYX_META)
 241           return $this->conf['fetch_mode'] == 1 ? $this->data['channel'] : (object)$this->data['channel'];
 242        if ($type == ONYX_IMAGE)
 243           return $this->conf['fetch_mode'] == 1 ? $this->data['image'] : (object)$this->data['image'];
 244        if ($type == ONYX_TEXTINPUT)
 245           return $this->conf['fetch_mode'] == 1 ? $this->data['textinput'] : (object)$this->data['textinput'];
 246        if ($type == ONYX_ITEMS)
 247        {
 248           if ($this->conf['fetch_mode'] == 1)
 249              return $this->data['items'];
 250  
 251           $temp = array();
 252           for ($i=0; $i < sizeof($this->data['items']); $i++)
 253              $temp[] = (object)$this->data['items'][$i];
 254  
 255           return $temp;
 256        }
 257        if ($type == ONYX_NAMESPACES)
 258           return $this->conf['fetch_mode'] == 1 ? $this->data['namespaces'] : (object)$this->data['namespaces'];
 259        if ($type == ONYX_CACHE_AGE)
 260           return $this->rss['cache_age'];
 261  
 262        return false;
 263     }
 264  
 265     function numItems()
 266     {
 267        return sizeof($this->data['items']);
 268     }
 269  
 270     function getNextItem($max=false)
 271     {
 272        $type = $this->conf['fetch_mode'];
 273        $this->rss['output_index']++;
 274        if (($max && $this->rss['output_index'] > $max) || !isset($this->data['items'][$this->rss['output_index']]))
 275           return false;
 276  
 277        return ($type == ONYX_FETCH_ASSOC) ? $this->data['items'][$this->rss['output_index']] :
 278               (($type == ONYX_FETCH_OBJECT) ? (object)$this->data['items'][$this->rss['output_index']] : false);
 279     }
 280  
 281     function itemAt($num)
 282     {
 283        if (!isset($this->data['items'][$num]))
 284        {
 285           $this->raiseError((__LINE__-3), ONYX_ERR_INVALID_ITEM);
 286           return false;
 287        }
 288  
 289        $type = $this->conf['fetch_mode'];
 290        return ($type == ONYX_FETCH_ASSOC) ? $this->data['items'][$num] :
 291               (($type == ONYX_FETCH_OBJECT) ? (object)$this->data['items'][$num] : false);
 292     }
 293  
 294     function startBuffer($file=false)
 295     {
 296        $this->conf['output_file'] = $file;
 297        ob_start();
 298     }
 299  
 300     function endBuffer()
 301     {
 302        if (!$this->conf['output_file'])
 303           ob_end_flush();
 304        else
 305        {
 306           if (!($fp = @fopen($this->conf['output_file'], 'w')))
 307           {
 308              $this->raiseError((__LINE__-2), ONYX_ERR_NO_STREAM);
 309              ob_end_flush();
 310              return;
 311           }
 312           fwrite($fp, ob_get_contents());
 313           fclose($fp);
 314           ob_end_clean();
 315        }
 316     }
 317  
 318     //private function raiseError($line, $err)
 319     function raiseError($line, $err)
 320     {
 321        if ($this->conf['debug_mode'])
 322           printf($this->conf['error'], $line, $err);
 323     }
 324  
 325     function setCachePath($path)
 326     {
 327        $this->conf['cache_path'] = $path;
 328     }
 329  
 330     function setExpiryTime($time)
 331     {
 332        $this->conf['cache_time'] = $time;
 333     }
 334  
 335     function setDebugMode($state)
 336     {
 337        $this->conf['debug_mode'] = (bool)$state;
 338     }
 339  
 340     function setFetchMode($mode)
 341     {
 342        $this->conf['fetch_mode'] = $mode;
 343     }
 344  
 345     //private function mod_time($uri)
 346     function mod_time($uri)
 347     {
 348        if (function_exists('version_compare') && version_compare(phpversion(), '4.3.0') >= 0)
 349        {
 350           require_once S9Y_PEAR_PATH . 'HTTP/Request.php';
 351           serendipity_request_start();
 352           $req = &new HTTP_Request($uri);
 353  
 354           if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') {
 355              serendipity_request_end();
 356              return false;
 357           }
 358  
 359           $fHeader = $req->getResponseHeader();
 360           if (isset($fHeader['last-modified'])) {
 361              $modtime = $fHeader['last-modified'];
 362          }
 363          serendipity_request_end();
 364        }
 365        else
 366        {
 367           $parts = parse_url($uri);
 368           $host  = $parts['host'];
 369           $path  = $parts['path'];
 370  
 371           if (!($fp = @fsockopen($host, 80)))
 372              return false;
 373  
 374           $req = "HEAD $path HTTP/1.1\r\nUser-Agent: PHP/".phpversion();
 375           $req.= "\r\nHost: $host\r\nAccept: */*\r\n\r\n";
 376           fputs($fp, $req);
 377  
 378           while (!feof($fp))
 379           {
 380              $str = fgets($fp, 4096);
 381              if (strpos(strtolower($str), 'last-modified') !== false)
 382              {
 383                 $modtime = substr($str, 15);
 384                 break;
 385              }
 386           }
 387           fclose($fp);
 388        }
 389        return (isset($modtime)) ? $modtime : 0;
 390     }
 391  }
 392  
 393  
 394  ?>


Généré le : Sat Nov 24 09:00:37 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics