Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 401 and 402] [Versions 401 and 403]

   1  <?php
   2  
   3  /**
   4   * Moodle - Modular Object-Oriented Dynamic Learning Environment
   5   *          http://moodle.org
   6   * Copyright (C) 1999 onwards Martin Dougiamas  http://dougiamas.com
   7   *
   8   * This program is free software: you can redistribute it and/or modify
   9   * it under the terms of the GNU General Public License as published by
  10   * the Free Software Foundation, either version 2 of the License, or
  11   * (at your option) any later version.
  12   *
  13   * This program is distributed in the hope that it will be useful,
  14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16   * GNU General Public License for more details.
  17   *
  18   * You should have received a copy of the GNU General Public License
  19   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20   *
  21   * @package    moodle
  22   * @subpackage lib
  23   * @author     Dan Poltawski <talktodan@gmail.com>
  24   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   *
  26   * Customised version of SimplePie for Moodle
  27   */
  28  
  29  require_once($CFG->libdir.'/filelib.php');
  30  
  31  // PLEASE NOTE: we use the simplepie class _unmodified_
  32  // through the joys of OO. Distros are free to use their stock
  33  // version of this file.
  34  require_once($CFG->libdir.'/simplepie/autoloader.php');
  35  
  36  /**
  37   * Moodle Customised version of the SimplePie class
  38   *
  39   * This class extends the stock SimplePie class
  40   * in order to make sensible configuration choices,
  41   * such as using the Moodle cache directory and
  42   * curl functions/proxy config for making http
  43   * requests in line with moodle configuration.
  44   *
  45   * @copyright 2009 Dan Poltawski <talktodan@gmail.com>
  46   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  47   * @since     Moodle 2.0
  48   */
  49  class moodle_simplepie extends SimplePie {
  50      /**
  51       * Constructor - creates an instance of the SimplePie class
  52       * with Moodle defaults.
  53       *
  54       * @param string $feedurl optional URL of the feed
  55       * @param int $timeout how many seconds requests should wait for server response
  56       */
  57      public function __construct($feedurl = null, $timeout = 2) {
  58          $cachedir = moodle_simplepie::get_cache_directory();
  59          check_dir_exists($cachedir);
  60  
  61          parent::__construct();
  62  
  63          // Use the Moodle class for http requests
  64          $this->set_file_class('moodle_simplepie_file');
  65  
  66          // Use html purifier for text cleaning.
  67          $this->set_sanitize_class('moodle_simplepie_sanitize');
  68          $this->sanitize = new moodle_simplepie_sanitize();
  69  
  70          // Match moodle encoding
  71          $this->set_output_encoding('UTF-8');
  72  
  73          // default to a short timeout as most operations will be interactive
  74          $this->set_timeout($timeout);
  75  
  76          // 1 hour default cache
  77          $this->set_cache_location($cachedir);
  78          $this->set_cache_duration(3600);
  79  
  80          // init the feed url if passed in constructor
  81          if ($feedurl !== null) {
  82              $this->set_feed_url($feedurl);
  83              $this->init();
  84          }
  85      }
  86  
  87      /**
  88       * Get path for feed cache directory
  89       *
  90       * @return string absolute path to cache directory
  91       */
  92      private static function get_cache_directory() {
  93          global $CFG;
  94  
  95          return $CFG->cachedir.'/simplepie/';
  96      }
  97  
  98      /**
  99       * Reset RSS cache
 100       *
 101       * @return boolean success if cache clear or didn't exist
 102       */
 103      public static function reset_cache() {
 104  
 105          $cachedir = moodle_simplepie::get_cache_directory();
 106  
 107          return remove_dir($cachedir);
 108      }
 109  }
 110  
 111  /**
 112   * Moodle Customised version of the SimplePie_File class
 113   *
 114   * This class extends the stock SimplePie class
 115   * in order to utilise Moodles own curl class for making
 116   * http requests. By using the moodle curl class
 117   * we ensure that the correct proxy configuration is used.
 118   */
 119  class moodle_simplepie_file extends SimplePie_File {
 120  
 121      /**
 122       * The constructor is a copy of the stock simplepie File class which has
 123       * been modified to add in use the Moodle curl class rather than php curl
 124       * functions.
 125       */
 126      public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false) {
 127          $this->url = $url;
 128          $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
 129  
 130          $curl = new curl();
 131          $curl->setopt( array(
 132                  'CURLOPT_HEADER' => true,
 133                  'CURLOPT_TIMEOUT' => $timeout,
 134                  'CURLOPT_CONNECTTIMEOUT' => $timeout ));
 135  
 136  
 137          if ($headers !== null) {
 138              // translate simplepie headers to those class curl expects
 139              foreach($headers as $headername => $headervalue){
 140                  $headerstr = "{$headername}: {$headervalue}";
 141                  $curl->setHeader($headerstr);
 142              }
 143          }
 144  
 145          $this->headers = curl::strip_double_headers($curl->get($url));
 146  
 147          if ($curl->error) {
 148              $this->error = 'cURL Error: '.$curl->error;
 149              $this->success = false;
 150              return false;
 151          }
 152  
 153          $parser = new SimplePie_HTTP_Parser($this->headers);
 154  
 155          if ($parser->parse()) {
 156              $this->headers = $parser->headers;
 157              $this->body = trim($parser->body);
 158              $this->status_code = $parser->status_code;
 159  
 160  
 161              if (($this->status_code == 300 || $this->status_code == 301 || $this->status_code == 302 || $this->status_code == 303
 162                      || $this->status_code == 307 || $this->status_code > 307 && $this->status_code < 400)
 163                      && isset($this->headers['location']) && $this->redirects < $redirects) {
 164                  $this->redirects++;
 165                  $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
 166                  return $this->__construct($location, $timeout, $redirects, $headers);
 167              }
 168          }
 169      }
 170  }
 171  
 172  
 173  /**
 174   * Customised feed sanitization using HTMLPurifier.
 175   */
 176  class moodle_simplepie_sanitize extends SimplePie_Sanitize {
 177      public function sanitize($data, $type, $base = '') {
 178          $data = trim($data);
 179  
 180          if ($data === '') {
 181              return '';
 182          }
 183  
 184          if ($type & SIMPLEPIE_CONSTRUCT_BASE64){
 185              $data = base64_decode($data);
 186          }
 187  
 188          if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML) {
 189              if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data)) {
 190                  $type |= SIMPLEPIE_CONSTRUCT_HTML;
 191              } else {
 192                  $type |= SIMPLEPIE_CONSTRUCT_TEXT;
 193              }
 194          }
 195  
 196          if ($type & SIMPLEPIE_CONSTRUCT_IRI) {
 197              $absolute = $this->registry->call('Misc', 'absolutize_url', array($data, $base));
 198              if ($absolute !== false) {
 199                  $data = $absolute;
 200              }
 201              $data = clean_param($data, PARAM_URL);
 202          }
 203  
 204          if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI)) {
 205              $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
 206          }
 207  
 208          $data = purify_html($data);
 209  
 210          if ($this->remove_div) {
 211              $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
 212              $data = preg_replace('/<\/div>$/', '', $data);
 213          } else {
 214              $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
 215          }
 216  
 217          if ($this->output_encoding !== 'UTF-8') {
 218              core_text::convert($data, 'UTF-8', $this->output_encoding);
 219          }
 220  
 221          return $data;
 222      }
 223  }