[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/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-2016, Ryan Parman, Sam 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   * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue
  37   * @author Ryan Parman
  38   * @author Sam Sneddon
  39   * @author Ryan McCue
  40   * @link http://simplepie.org/ SimplePie
  41   * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  42   */
  43  
  44  /**
  45   * Used for feed auto-discovery
  46   *
  47   *
  48   * This class can be overloaded with {@see SimplePie::set_locator_class()}
  49   *
  50   * @package SimplePie
  51   */
  52  class SimplePie_Locator
  53  {
  54      var $useragent;
  55      var $timeout;
  56      var $file;
  57      var $local = array();
  58      var $elsewhere = array();
  59      var $cached_entities = array();
  60      var $http_base;
  61      var $base;
  62      var $base_location = 0;
  63      var $checked_feeds = 0;
  64      var $max_checked_feeds = 10;
  65      var $force_fsockopen = false;
  66      var $curl_options = array();
  67      var $dom;
  68      protected $registry;
  69  
  70  	public function __construct(SimplePie_File $file, $timeout = 10, $useragent = null, $max_checked_feeds = 10, $force_fsockopen = false, $curl_options = array())
  71      {
  72          $this->file = $file;
  73          $this->useragent = $useragent;
  74          $this->timeout = $timeout;
  75          $this->max_checked_feeds = $max_checked_feeds;
  76          $this->force_fsockopen = $force_fsockopen;
  77          $this->curl_options = $curl_options;
  78  
  79          if (class_exists('DOMDocument') && $this->file->body != '')
  80          {
  81              $this->dom = new DOMDocument();
  82  
  83              set_error_handler(array('SimplePie_Misc', 'silence_errors'));
  84              try
  85              {
  86                  $this->dom->loadHTML($this->file->body);
  87              }
  88              catch (Throwable $ex)
  89              {
  90                  $this->dom = null;
  91              }
  92              restore_error_handler();
  93          }
  94          else
  95          {
  96              $this->dom = null;
  97          }
  98      }
  99  
 100  	public function set_registry(SimplePie_Registry $registry)
 101      {
 102          $this->registry = $registry;
 103      }
 104  
 105  	public function find($type = SIMPLEPIE_LOCATOR_ALL, &$working = null)
 106      {
 107          if ($this->is_feed($this->file))
 108          {
 109              return $this->file;
 110          }
 111  
 112          if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
 113          {
 114              $sniffer = $this->registry->create('Content_Type_Sniffer', array($this->file));
 115              if ($sniffer->get_type() !== 'text/html')
 116              {
 117                  return null;
 118              }
 119          }
 120  
 121          if ($type & ~SIMPLEPIE_LOCATOR_NONE)
 122          {
 123              $this->get_base();
 124          }
 125  
 126          if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
 127          {
 128              return $working[0];
 129          }
 130  
 131          if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
 132          {
 133              if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
 134              {
 135                  return $working[0];
 136              }
 137  
 138              if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
 139              {
 140                  return $working[0];
 141              }
 142  
 143              if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
 144              {
 145                  return $working[0];
 146              }
 147  
 148              if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
 149              {
 150                  return $working[0];
 151              }
 152          }
 153          return null;
 154      }
 155  
 156  	public function is_feed($file, $check_html = false)
 157      {
 158          if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
 159          {
 160              $sniffer = $this->registry->create('Content_Type_Sniffer', array($file));
 161              $sniffed = $sniffer->get_type();
 162              $mime_types = array('application/rss+xml', 'application/rdf+xml',
 163                                  'text/rdf', 'application/atom+xml', 'text/xml',
 164                                  'application/xml', 'application/x-rss+xml');
 165              if ($check_html)
 166              {
 167                  $mime_types[] = 'text/html';
 168              }
 169  
 170              return in_array($sniffed, $mime_types);
 171          }
 172          elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
 173          {
 174              return true;
 175          }
 176          else
 177          {
 178              return false;
 179          }
 180      }
 181  
 182  	public function get_base()
 183      {
 184          if ($this->dom === null)
 185          {
 186              throw new SimplePie_Exception('DOMDocument not found, unable to use locator');
 187          }
 188          $this->http_base = $this->file->url;
 189          $this->base = $this->http_base;
 190          $elements = $this->dom->getElementsByTagName('base');
 191          foreach ($elements as $element)
 192          {
 193              if ($element->hasAttribute('href'))
 194              {
 195                  $base = $this->registry->call('Misc', 'absolutize_url', array(trim($element->getAttribute('href')), $this->http_base));
 196                  if ($base === false)
 197                  {
 198                      continue;
 199                  }
 200                  $this->base = $base;
 201                  $this->base_location = method_exists($element, 'getLineNo') ? $element->getLineNo() : 0;
 202                  break;
 203              }
 204          }
 205      }
 206  
 207  	public function autodiscovery()
 208      {
 209          $done = array();
 210          $feeds = array();
 211          $feeds = array_merge($feeds, $this->search_elements_by_tag('link', $done, $feeds));
 212          $feeds = array_merge($feeds, $this->search_elements_by_tag('a', $done, $feeds));
 213          $feeds = array_merge($feeds, $this->search_elements_by_tag('area', $done, $feeds));
 214  
 215          if (!empty($feeds))
 216          {
 217              return array_values($feeds);
 218          }
 219  
 220          return null;
 221      }
 222  
 223  	protected function search_elements_by_tag($name, &$done, $feeds)
 224      {
 225          if ($this->dom === null)
 226          {
 227              throw new SimplePie_Exception('DOMDocument not found, unable to use locator');
 228          }
 229  
 230          $links = $this->dom->getElementsByTagName($name);
 231          foreach ($links as $link)
 232          {
 233              if ($this->checked_feeds === $this->max_checked_feeds)
 234              {
 235                  break;
 236              }
 237              if ($link->hasAttribute('href') && $link->hasAttribute('rel'))
 238              {
 239                  $rel = array_unique($this->registry->call('Misc', 'space_separated_tokens', array(strtolower($link->getAttribute('rel')))));
 240                  $line = method_exists($link, 'getLineNo') ? $link->getLineNo() : 1;
 241  
 242                  if ($this->base_location < $line)
 243                  {
 244                      $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base));
 245                  }
 246                  else
 247                  {
 248                      $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base));
 249                  }
 250                  if ($href === false)
 251                  {
 252                      continue;
 253                  }
 254  
 255                  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('text/html', 'application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href]))
 256                  {
 257                      $this->checked_feeds++;
 258                      $headers = array(
 259                          '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',
 260                      );
 261                      $feed = $this->registry->create('File', array($href, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options));
 262                      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, true))
 263                      {
 264                          $feeds[$href] = $feed;
 265                      }
 266                  }
 267                  $done[] = $href;
 268              }
 269          }
 270  
 271          return $feeds;
 272      }
 273  
 274      public function get_links()
 275      {
 276          if ($this->dom === null)
 277          {
 278              throw new SimplePie_Exception('DOMDocument not found, unable to use locator');
 279          }
 280  
 281          $links = $this->dom->getElementsByTagName('a');
 282          foreach ($links as $link)
 283          {
 284              if ($link->hasAttribute('href'))
 285              {
 286                  $href = trim($link->getAttribute('href'));
 287                  $parsed = $this->registry->call('Misc', 'parse_url', array($href));
 288                  if ($parsed['scheme'] === '' || preg_match('/^(https?|feed)?$/i', $parsed['scheme']))
 289                  {
 290                      if (method_exists($link, 'getLineNo') && $this->base_location < $link->getLineNo())
 291                      {
 292                          $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base));
 293                      }
 294                      else
 295                      {
 296                          $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base));
 297                      }
 298                      if ($href === false)
 299                      {
 300                          continue;
 301                      }
 302  
 303                      $current = $this->registry->call('Misc', 'parse_url', array($this->file->url));
 304  
 305                      if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
 306                      {
 307                          $this->local[] = $href;
 308                      }
 309                      else
 310                      {
 311                          $this->elsewhere[] = $href;
 312                      }
 313                  }
 314              }
 315          }
 316          $this->local = array_unique($this->local);
 317          $this->elsewhere = array_unique($this->elsewhere);
 318          if (!empty($this->local) || !empty($this->elsewhere))
 319          {
 320              return true;
 321          }
 322          return null;
 323      }
 324  
 325      public function get_rel_link($rel)
 326      {
 327          if ($this->dom === null)
 328          {
 329              throw new SimplePie_Exception('DOMDocument not found, unable to use '.
 330                                            'locator');
 331          }
 332          if (!class_exists('DOMXpath'))
 333          {
 334              throw new SimplePie_Exception('DOMXpath not found, unable to use '.
 335                                            'get_rel_link');
 336          }
 337  
 338          $xpath = new DOMXpath($this->dom);
 339          $query = '//a[@rel and @href] | //link[@rel and @href]';
 340          foreach ($xpath->query($query) as $link)
 341          {
 342              $href = trim($link->getAttribute('href'));
 343              $parsed = $this->registry->call('Misc', 'parse_url', array($href));
 344              if ($parsed['scheme'] === '' ||
 345                  preg_match('/^https?$/i', $parsed['scheme']))
 346              {
 347                  if (method_exists($link, 'getLineNo') &&
 348                      $this->base_location < $link->getLineNo())
 349                  {
 350                      $href =
 351                          $this->registry->call('Misc', 'absolutize_url',
 352                                                array(trim($link->getAttribute('href')),
 353                                                      $this->base));
 354                  }
 355                  else
 356                  {
 357                      $href =
 358                          $this->registry->call('Misc', 'absolutize_url',
 359                                                array(trim($link->getAttribute('href')),
 360                                                      $this->http_base));
 361                  }
 362                  if ($href === false)
 363                  {
 364                      return null;
 365                  }
 366                  $rel_values = explode(' ', strtolower($link->getAttribute('rel')));
 367                  if (in_array($rel, $rel_values))
 368                  {
 369                      return $href;
 370                  }
 371              }
 372          }
 373          return null;
 374      }
 375  
 376      public function extension(&$array)
 377      {
 378          foreach ($array as $key => $value)
 379          {
 380              if ($this->checked_feeds === $this->max_checked_feeds)
 381              {
 382                  break;
 383              }
 384              if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
 385              {
 386                  $this->checked_feeds++;
 387  
 388                  $headers = array(
 389                      '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',
 390                  );
 391                  $feed = $this->registry->create('File', array($value, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options));
 392                  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))
 393                  {
 394                      return array($feed);
 395                  }
 396                  else
 397                  {
 398                      unset($array[$key]);
 399                  }
 400              }
 401          }
 402          return null;
 403      }
 404  
 405  	public function body(&$array)
 406      {
 407          foreach ($array as $key => $value)
 408          {
 409              if ($this->checked_feeds === $this->max_checked_feeds)
 410              {
 411                  break;
 412              }
 413              if (preg_match('/(feed|rss|rdf|atom|xml)/i', $value))
 414              {
 415                  $this->checked_feeds++;
 416                  $headers = array(
 417                      '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',
 418                  );
 419                  $feed = $this->registry->create('File', array($value, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen, $this->curl_options));
 420                  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))
 421                  {
 422                      return array($feed);
 423                  }
 424                  else
 425                  {
 426                      unset($array[$key]);
 427                  }
 428              }
 429          }
 430          return null;
 431      }
 432  }


Generated: Sat May 21 01:00:03 2022 Cross-referenced by PHPXref 0.7.1