[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/filter/mediaplugin/ -> filter.php (source)

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   *  Media plugin filtering
  19   *
  20   *  This filter will replace any links to a media file with
  21   *  a media plugin that plays that media inline
  22   *
  23   * @package    filter
  24   * @subpackage mediaplugin
  25   * @copyright  2004 onwards Martin Dougiamas  {@link http://moodle.com}
  26   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  27   */
  28  
  29  defined('MOODLE_INTERNAL') || die();
  30  
  31  /**
  32   * Automatic media embedding filter class.
  33   *
  34   * It is highly recommended to configure servers to be compatible with our slasharguments,
  35   * otherwise the "?d=600x400" may not work.
  36   *
  37   * @package    filter
  38   * @subpackage mediaplugin
  39   * @copyright  2004 onwards Martin Dougiamas  {@link http://moodle.com}
  40   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  41   */
  42  class filter_mediaplugin extends moodle_text_filter {
  43      /** @var bool True if currently filtering trusted text */
  44      private $trusted;
  45      /** @var core_media_renderer Media renderer */
  46      private $mediarenderer;
  47      /** @var string Partial regex pattern indicating possible embeddable content */
  48      private $embedmarkers;
  49  
  50      public function filter($text, array $options = array()) {
  51          global $CFG, $PAGE;
  52  
  53          if (!is_string($text) or empty($text)) {
  54              // non string data can not be filtered anyway
  55              return $text;
  56          }
  57  
  58          if (stripos($text, '</a>') === false) {
  59              // Performance shortcut - if not </a> tag, nothing can match.
  60              return $text;
  61          }
  62  
  63          if (!$this->mediarenderer) {
  64              $this->mediarenderer = $PAGE->get_renderer('core', 'media');
  65              $this->embedmarkers = $this->mediarenderer->get_embeddable_markers();
  66          }
  67  
  68          // Check SWF permissions.
  69          $this->trusted = !empty($options['noclean']) or !empty($CFG->allowobjectembed);
  70  
  71          // Looking for tags.
  72          $matches = preg_split('/(<[^>]*>)/i', $text, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
  73  
  74          if (!$matches) {
  75              return $text;
  76          }
  77  
  78          // Regex to find media extensions in an <a> tag.
  79          $re = '~<a\s[^>]*href="([^"]*(?:' .  $this->embedmarkers . ')[^"]*)"[^>]*>([^>]*)</a>~is';
  80  
  81          $newtext = '';
  82          $validtag = '';
  83          $sizeofmatches = count($matches);
  84  
  85          // We iterate through the given string to find valid <a> tags
  86          // and build them so that the callback function can check it for
  87          // embedded content. Then we rebuild the string.
  88          foreach ($matches as $idx => $tag) {
  89              if (preg_match('|</a>|', $tag) && !empty($validtag)) {
  90                  $validtag .= $tag;
  91  
  92                  // Given we now have a valid <a> tag to process it's time for
  93                  // ReDoS protection. Stop processing if a word is too large.
  94                  if (strlen($validtag) < 4096) {
  95                      $processed = preg_replace_callback($re, array($this, 'callback'), $validtag);
  96                  }
  97                  // Rebuilding the string with our new processed text.
  98                  $newtext .= !empty($processed) ? $processed : $validtag;
  99                  // Wipe it so we can catch any more instances to filter.
 100                  $validtag = '';
 101                  $processed = '';
 102              } else if (preg_match('/<a\s[^>]*/', $tag) && $sizeofmatches > 1) {
 103                  // Looking for a starting <a> tag.
 104                  $validtag = $tag;
 105              } else {
 106                  // If we have a validtag add to that to process later,
 107                  // else add straight onto our newtext string.
 108                  if (!empty($validtag)) {
 109                      $validtag .= $tag;
 110                  } else {
 111                      $newtext .= $tag;
 112                  }
 113              }
 114          }
 115  
 116          // Return the same string except processed by the above.
 117          return $newtext;
 118      }
 119  
 120      /**
 121       * Replace link with embedded content, if supported.
 122       *
 123       * @param array $matches
 124       * @return string
 125       */
 126      private function callback(array $matches) {
 127          global $CFG, $PAGE;
 128          // Check if we ignore it.
 129          if (preg_match('/class="[^"]*nomediaplugin/i', $matches[0])) {
 130              return $matches[0];
 131          }
 132  
 133          // Get name.
 134          $name = trim($matches[2]);
 135          if (empty($name) or strpos($name, 'http') === 0) {
 136              $name = ''; // Use default name.
 137          }
 138  
 139          // Split provided URL into alternatives.
 140          $urls = core_media::split_alternatives($matches[1], $width, $height);
 141  
 142          $options = array();
 143  
 144          // Allow SWF (or not).
 145          if ($this->trusted) {
 146              $options[core_media::OPTION_TRUSTED] = true;
 147          }
 148  
 149          // We could test whether embed is possible using can_embed, but to save
 150          // time, let's just embed it with the 'fallback to blank' option which
 151          // does most of the same stuff anyhow.
 152          $options[core_media::OPTION_FALLBACK_TO_BLANK] = true;
 153  
 154          // NOTE: Options are not passed through from filter because the 'embed'
 155          // code does not recognise filter options (it's a different kind of
 156          // option-space) as it can be used in non-filter situations.
 157          $result = $this->mediarenderer->embed_alternatives($urls, $name, $width, $height, $options);
 158  
 159          // If something was embedded, return it, otherwise return original.
 160          if ($result !== '') {
 161              return $result;
 162          } else {
 163              return $matches[0];
 164          }
 165      }
 166  }


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