[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/simplepie/library/SimplePie/ -> Locator.php (source)

   1  <?php
   2  /**
   3   * SimplePie
   4   *
   5   * A PHP-Based RSS and Atom Feed Framework.
   6   * Takes the hard work out of managing a complete RSS/Atom solution.
   7   *
   8   * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
   9   * All rights reserved.
  10   *
  11   * Redistribution and use in source and binary forms, with or without modification, are
  12   * permitted provided that the following conditions are met:
  13   *
  14   *     * Redistributions of source code must retain the above copyright notice, this list of
  15   *       conditions and the following disclaimer.
  16   *
  17   *     * Redistributions in binary form must reproduce the above copyright notice, this list
  18   *       of conditions and the following disclaimer in the documentation and/or other materials
  19   *       provided with the distribution.
  20   *
  21   *     * Neither the name of the SimplePie Team nor the names of its contributors may be used
  22   *       to endorse or promote products derived from this software without specific prior
  23   *       written permission.
  24   *
  25   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
  26   * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  27   * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
  28   * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  29   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  30   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  31   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  32   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33   * POSSIBILITY OF SUCH DAMAGE.
  34   *
  35   * @package SimplePie
  36   * @version 1.3.1
  37   * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue
  38   * @author Ryan Parman
  39   * @author Geoffrey Sneddon
  40   * @author Ryan McCue
  41   * @link http://simplepie.org/ SimplePie
  42   * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  43   */
  44  
  45  /**
  46   * Used for feed auto-discovery
  47   *
  48   *
  49   * This class can be overloaded with {@see SimplePie::set_locator_class()}
  50   *
  51   * @package SimplePie
  52   */
  53  class SimplePie_Locator
  54  {
  55      var $useragent;
  56      var $timeout;
  57      var $file;
  58      var $local = array();
  59      var $elsewhere = array();
  60      var $cached_entities = array();
  61      var $http_base;
  62      var $base;
  63      var $base_location = 0;
  64      var $checked_feeds = 0;
  65      var $max_checked_feeds = 10;
  66      protected $registry;
  67  
  68  	public function __construct(SimplePie_File $file, $timeout = 10, $useragent = null, $max_checked_feeds = 10)
  69      {
  70          $this->file = $file;
  71          $this->useragent = $useragent;
  72          $this->timeout = $timeout;
  73          $this->max_checked_feeds = $max_checked_feeds;
  74  
  75          if (class_exists('DOMDocument'))
  76          {
  77              $this->dom = new DOMDocument();
  78  
  79              set_error_handler(array('SimplePie_Misc', 'silence_errors'));
  80              $this->dom->loadHTML($this->file->body);
  81              restore_error_handler();
  82          }
  83          else
  84          {
  85              $this->dom = null;
  86          }
  87      }
  88  
  89  	public function set_registry(SimplePie_Registry $registry)
  90      {
  91          $this->registry = $registry;
  92      }
  93  
  94  	public function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
  95      {
  96          if ($this->is_feed($this->file))
  97          {
  98              return $this->file;
  99          }
 100  
 101          if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
 102          {
 103              $sniffer = $this->registry->create('Content_Type_Sniffer', array($this->file));
 104              if ($sniffer->get_type() !== 'text/html')
 105              {
 106                  return null;
 107              }
 108          }
 109  
 110          if ($type & ~SIMPLEPIE_LOCATOR_NONE)
 111          {
 112              $this->get_base();
 113          }
 114  
 115          if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
 116          {
 117              return $working[0];
 118          }
 119  
 120          if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
 121          {
 122              if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
 123              {
 124                  return $working;
 125              }
 126  
 127              if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
 128              {
 129                  return $working;
 130              }
 131  
 132              if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
 133              {
 134                  return $working;
 135              }
 136  
 137              if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
 138              {
 139                  return $working;
 140              }
 141          }
 142          return null;
 143      }
 144  
 145  	public function is_feed($file)
 146      {
 147          if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
 148          {
 149              $sniffer = $this->registry->create('Content_Type_Sniffer', array($file));
 150              $sniffed = $sniffer->get_type();
 151              if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
 152              {
 153                  return true;
 154              }
 155              else
 156              {
 157                  return false;
 158              }
 159          }
 160          elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
 161          {
 162              return true;
 163          }
 164          else
 165          {
 166              return false;
 167          }
 168      }
 169  
 170  	public function get_base()
 171      {
 172          if ($this->dom === null)
 173          {
 174              throw new SimplePie_Exception('DOMDocument not found, unable to use locator');
 175          }
 176          $this->http_base = $this->file->url;
 177          $this->base = $this->http_base;
 178          $elements = $this->dom->getElementsByTagName('base');
 179          foreach ($elements as $element)
 180          {
 181              if ($element->hasAttribute('href'))
 182              {
 183                  $base = $this->registry->call('Misc', 'absolutize_url', array(trim($element->getAttribute('href')), $this->http_base));
 184                  if ($base === false)
 185                  {
 186                      continue;
 187                  }
 188                  $this->base = $base;
 189                  $this->base_location = method_exists($element, 'getLineNo') ? $element->getLineNo() : 0;
 190                  break;
 191              }
 192          }
 193      }
 194  
 195  	public function autodiscovery()
 196      {
 197          $done = array();
 198          $feeds = array();
 199          $feeds = array_merge($feeds, $this->search_elements_by_tag('link', $done, $feeds));
 200          $feeds = array_merge($feeds, $this->search_elements_by_tag('a', $done, $feeds));
 201          $feeds = array_merge($feeds, $this->search_elements_by_tag('area', $done, $feeds));
 202  
 203          if (!empty($feeds))
 204          {
 205              return array_values($feeds);
 206          }
 207          else
 208          {
 209              return null;
 210          }
 211      }
 212  
 213  	protected function search_elements_by_tag($name, &$done, $feeds)
 214      {
 215          if ($this->dom === null)
 216          {
 217              throw new SimplePie_Exception('DOMDocument not found, unable to use locator');
 218          }
 219  
 220          $links = $this->dom->getElementsByTagName($name);
 221          foreach ($links as $link)
 222          {
 223              if ($this->checked_feeds === $this->max_checked_feeds)
 224              {
 225                  break;
 226              }
 227              if ($link->hasAttribute('href') && $link->hasAttribute('rel'))
 228              {
 229                  $rel = array_unique($this->registry->call('Misc', 'space_seperated_tokens', array(strtolower($link->getAttribute('rel')))));
 230                  $line = method_exists($link, 'getLineNo') ? $link->getLineNo() : 1;
 231  
 232                  if ($this->base_location < $line)
 233                  {
 234                      $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base));
 235                  }
 236                  else
 237                  {
 238                      $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base));
 239                  }
 240                  if ($href === false)
 241                  {
 242                      continue;
 243                  }
 244  
 245                  if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !in_array('stylesheet', $rel) && $link->hasAttribute('type') && in_array(strtolower($this->registry->call('Misc', 'parse_mime', array($link->getAttribute('type')))), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href]))
 246                  {
 247                      $this->checked_feeds++;
 248                      $headers = array(
 249                          'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
 250                      );
 251                      $feed = $this->registry->create('File', array($href, $this->timeout, 5, $headers, $this->useragent));
 252                      if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
 253                      {
 254                          $feeds[$href] = $feed;
 255                      }
 256                  }
 257                  $done[] = $href;
 258              }
 259          }
 260  
 261          return $feeds;
 262      }
 263  
 264      public function get_links()
 265      {
 266          if ($this->dom === null)
 267          {
 268              throw new SimplePie_Exception('DOMDocument not found, unable to use locator');
 269          }
 270  
 271          $links = $this->dom->getElementsByTagName('a');
 272          foreach ($links as $link)
 273          {
 274              if ($link->hasAttribute('href'))
 275              {
 276                  $href = trim($link->getAttribute('href'));
 277                  $parsed = $this->registry->call('Misc', 'parse_url', array($href));
 278                  if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
 279                  {
 280                      if ($this->base_location < $link->getLineNo())
 281                      {
 282                          $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base));
 283                      }
 284                      else
 285                      {
 286                          $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base));
 287                      }
 288                      if ($href === false)
 289                      {
 290                          continue;
 291                      }
 292  
 293                      $current = $this->registry->call('Misc', 'parse_url', array($this->file->url));
 294  
 295                      if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
 296                      {
 297                          $this->local[] = $href;
 298                      }
 299                      else
 300                      {
 301                          $this->elsewhere[] = $href;
 302                      }
 303                  }
 304              }
 305          }
 306          $this->local = array_unique($this->local);
 307          $this->elsewhere = array_unique($this->elsewhere);
 308          if (!empty($this->local) || !empty($this->elsewhere))
 309          {
 310              return true;
 311          }
 312          return null;
 313      }
 314  
 315      public function extension(&$array)
 316      {
 317          foreach ($array as $key => $value)
 318          {
 319              if ($this->checked_feeds === $this->max_checked_feeds)
 320              {
 321                  break;
 322              }
 323              if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
 324              {
 325                  $this->checked_feeds++;
 326  
 327                  $headers = array(
 328                      'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
 329                  );
 330                  $feed = $this->registry->create('File', array($value, $this->timeout, 5, $headers, $this->useragent));
 331                  if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
 332                  {
 333                      return $feed;
 334                  }
 335                  else
 336                  {
 337                      unset($array[$key]);
 338                  }
 339              }
 340          }
 341          return null;
 342      }
 343  
 344  	public function body(&$array)
 345      {
 346          foreach ($array as $key => $value)
 347          {
 348              if ($this->checked_feeds === $this->max_checked_feeds)
 349              {
 350                  break;
 351              }
 352              if (preg_match('/(rss|rdf|atom|xml)/i', $value))
 353              {
 354                  $this->checked_feeds++;
 355                  $headers = array(
 356                      'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
 357                  );
 358                  $feed = $this->registry->create('File', array($value, $this->timeout, 5, null, $this->useragent));
 359                  if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
 360                  {
 361                      return $feed;
 362                  }
 363                  else
 364                  {
 365                      unset($array[$key]);
 366                  }
 367              }
 368          }
 369          return null;
 370      }
 371  }
 372  


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1