[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |