From eaf3fd7a450889cbd3617b8e0421d3038bfc4cb9 Mon Sep 17 00:00:00 2001 From: tjhunt <tjhunt> Date: Wed, 30 Sep 2009 17:19:32 +0000 Subject: [PATCH] question import/export: MDL-20299 fatal error cause by hotpot format changes Replaced copy and paste code from mod/hotpot/lib.php with a require_once. --- question/format/hotpot/format.php | 282 +----------------------------- 1 file changed, 1 insertion(+), 281 deletions(-) diff --git a/question/format/hotpot/format.php b/question/format/hotpot/format.php index 87ee56444c..0ac6e6b216 100644 --- a/question/format/hotpot/format.php +++ b/question/format/hotpot/format.php @@ -12,6 +12,7 @@ * @package questionbank * @subpackage importexport */ +require_once($CFG->dirroot . '/mod/hotpot/lib.php'); class qformat_hotpot extends qformat_default { @@ -507,284 +508,3 @@ class qformat_hotpot extends qformat_default { return $str; } } // end class - -// get the standard XML parser supplied with Moodle -require_once("$CFG->libdir/xmlize.php"); - -class hotpot_xml_tree { - function hotpot_xml_tree($str, $xml_root='') { - if (empty($str)) { - $this->xml = array(); - } else { - // encode htmlentities in JCloze - $this->encode_cdata($str, 'gap-fill'); - // xmlize (=convert xml to tree) - $this->xml = xmlize($str, 0); - } - $this->xml_root = $xml_root; - } - function xml_value($tags, $more_tags="[0]['#']") { - - $value = null; - if (isset($this->xml) && is_array($this->xml)) { - - $all_tags = $this->xml_root; - if ($tags) { - $all_tags .= "['".str_replace(",", "'][0]['#']['", $tags)."']"; - } - $all_tags .= $more_tags; - - $pos = strrpos($all_tags, '['); - if ($pos===false) { - $most_tags = ''; // shouldn't happen !! - } else { - $most_tags = substr($all_tags, 0, $pos); - } - - eval('if (isset($this->xml'.$most_tags.') && is_array($this->xml'.$most_tags.') && isset($this->xml'.$all_tags.')) {' - .'$value = &$this->xml'.$all_tags.';' - .'} else {' - .'$value = null;' - .'}' - ); - } - - if (is_string($value)) { - - // decode angle brackets and ampersands - $value = strtr($value, array('<'=>'<', '>'=>'>', '&'=>'&')); - - // remove white space between <table>, <ul|OL|DL> and <OBJECT|EMBED> parts - // (so it doesn't get converted to <br />) - $htmltags = '(' - . 'TABLE|/?CAPTION|/?COL|/?COLGROUP|/?TBODY|/?TFOOT|/?THEAD|/?TD|/?TH|/?TR' - . '|OL|UL|/?LI' - . '|DL|/?DT|/?DD' - . '|EMBED|OBJECT|APPLET|/?PARAM' - //. '|SELECT|/?OPTION' - //. '|FIELDSET|/?LEGEND' - //. '|FRAMESET|/?FRAME' - . ')' - ; - $search = '#(<'.$htmltags.'[^>]*'.'>)\s+'.'(?='.'<'.')#is'; - $value = preg_replace($search, '\\1', $value); - - // replace remaining newlines with <br /> - $value = str_replace("\n", '<br />', $value); - - // encode unicode characters as HTML entities - // (in particular, accented charaters that have not been encoded by HP) - - // multibyte unicode characters can be detected by checking the hex value of the first character - // 00 - 7F : ascii char (roman alphabet + punctuation) - // 80 - BF : byte 2, 3 or 4 of a unicode char - // C0 - DF : 1st byte of 2-byte char - // E0 - EF : 1st byte of 3-byte char - // F0 - FF : 1st byte of 4-byte char - // if the string doesn't match the above, it might be - // 80 - FF : single-byte, non-ascii char - $search = '#('.'[\xc0-\xdf][\x80-\xbf]'.'|'.'[\xe0-\xef][\x80-\xbf]{2}'.'|'.'[\xf0-\xff][\x80-\xbf]{3}'.'|'.'[\x80-\xff]'.')#se'; - $value = preg_replace($search, "hotpot_utf8_to_html_entity('\\1')", $value); - } - return $value; - } - function encode_cdata(&$str, $tag) { - - // conversion tables - static $HTML_ENTITIES = array( - ''' => "'", - '"' => '"', - '<' => '<', - '>' => '>', - '&' => '&', - ); - static $ILLEGAL_STRINGS = array( - "\r" => '', - "\n" => '<br />', - ']]>' => ']]>', - ); - - // extract the $tag from the $str(ing), if possible - $pattern = '|(^.*<'.$tag.'[^>]*)(>.*<)(/'.$tag.'>.*$)|is'; - if (preg_match($pattern, $str, $matches)) { - - // encode problematic CDATA chars and strings - $matches[2] = strtr($matches[2], $ILLEGAL_STRINGS); - - - // if there are any ampersands in "open text" - // surround them by CDATA start and end markers - // (and convert HTML entities to plain text) - $search = '/>([^<]*&[^<]*)</e'; - $replace = '"><![CDATA[".strtr("$1", $HTML_ENTITIES)."]]><"'; - $matches[2] = preg_replace($search, $replace, $matches[2]); - - $str = $matches[1].$matches[2].$matches[3]; - } - } -} - -function hotpot_charcode_to_utf8($charcode) { - if ($charcode <= 0x7F) { - // ascii char (roman alphabet + punctuation) - return chr($charcode); - } - if ($charcode <= 0x7FF) { - // 2-byte char - return chr(($charcode >> 0x06) + 0xC0).chr(($charcode & 0x3F) + 128); - } - if ($charcode <= 0xFFFF) { - // 3-byte char - return chr(($charcode >> 0x0C) + 0xE0).chr((($charcode >> 0x06) & 0x3F) + 0x80).chr(($charcode & 0x3F) + 0x80); - } - if ($charcode <= 0x1FFFFF) { - // 4-byte char - return chr(($charcode >> 0x12) + 0xF0).chr((($charcode >> 0x0C) & 0x3F) + 0x80).chr((($charcode >> 0x06) & 0x3F) + 0x80).chr(($charcode & 0x3F) + 0x80); - } - // unidentified char code !! - return ' '; -} - -function hotpot_utf8_to_html_entity($char) { - // http://www.zend.com/codex.php?id=835&single=1 - - // array used to figure what number to decrement from character order value - // according to number of characters used to map unicode to ascii by utf-8 - static $HOTPOT_UTF8_DECREMENT = array( - 1=>0, 2=>192, 3=>224, 4=>240 - ); - - // the number of bits to shift each character by - static $HOTPOT_UTF8_SHIFT = array( - 1=>array(0=>0), - 2=>array(0=>6, 1=>0), - 3=>array(0=>12, 1=>6, 2=>0), - 4=>array(0=>18, 1=>12, 2=>6, 3=>0) - ); - - $dec = 0; - $len = strlen($char); - for ($pos=0; $pos<$len; $pos++) { - $ord = ord ($char{$pos}); - $ord -= ($pos ? 128 : $HOTPOT_UTF8_DECREMENT[$len]); - $dec += ($ord << $HOTPOT_UTF8_SHIFT[$len][$pos]); - } - return '&#x'.sprintf('%04X', $dec).';'; -} - -function hotpot_convert_relative_urls($str, $baseurl, $filename) { - $tagopen = '(?:(<)|(<)|(&#x003C;))'; // left angle bracket - $tagclose = '(?(2)>|(?(3)>|(?(4)&#x003E;)))'; // right angle bracket (to match left angle bracket) - - $space = '\s+'; // at least one space - $anychar = '(?:[^>]*?)'; // any character - - $quoteopen = '("|"|&quot;)'; // open quote - $quoteclose = '\\5'; // close quote (to match open quote) - - $replace = "hotpot_convert_relative_url('".$baseurl."', '".$filename."', '\\1', '\\6', '\\7')"; - - $tags = array('script'=>'src', 'link'=>'href', 'a'=>'href','img'=>'src','param'=>'value', 'object'=>'data', 'embed'=>'src'); - foreach ($tags as $tag=>$attribute) { - if ($tag=='param') { - $url = '\S+?\.\S+?'; // must include a filename and have no spaces - } else { - $url = '.*?'; - } - $search = "%($tagopen$tag$space$anychar$attribute=$quoteopen)($url)($quoteclose$anychar$tagclose)%ise"; - $str = preg_replace($search, $replace, $str); - } - - return $str; -} - -function hotpot_convert_relative_url($baseurl, $filename, $opentag, $url, $closetag, $depricated=true) { - // catch <PARAM name="FlashVars" value="TheSound=soundfile.mp3"> - // ampersands can appear as "&", "&" or "&#x0026;amp;" - if (preg_match('|^'.'\w+=[^&]+'.'('.'&((amp;#x0026;)?amp;)?'.'\w+=[^&]+)*'.'$|', $url)) { - $query = $url; - $url = ''; - $fragment = ''; - - // parse the $url into $matches - // [1] path - // [2] query string, if any - // [3] anchor fragment, if any - } else if (preg_match('|^'.'([^?]*)'.'((?:\\?[^#]*)?)'.'((?:#.*)?)'.'$|', $url, $matches)) { - $url = $matches[1]; - $query = $matches[2]; - $fragment = $matches[3]; - - // there appears to be no query or fragment in this url - } else { - $query = ''; - $fragment = ''; - } - - if ($url) { - $url = hotpot_convert_url($baseurl, $filename, $url, false); - } - - if ($query) { - $search = '#'.'(file|src|thesound)='."([^&]+)".'#ise'; - $replace = "'\\1='.hotpot_convert_url('".$baseurl."','".$filename."','\\2')"; - $query = preg_replace($search, $replace, $query); - } - - $url = $opentag.$url.$query.$fragment.$closetag; - - return $url; -} - -function hotpot_convert_url($baseurl, $filename, $url, $depricated=true) { - // maintain a cache of converted urls - static $HOTPOT_RELATIVE_URLS = array(); - - // is this an absolute url? (or javascript pseudo url) - if (preg_match('%^(http://|/|javascript:)%i', $url)) { - // do nothing - - // has this relative url already been converted? - } else if (isset($HOTPOT_RELATIVE_URLS[$url])) { - $url = $HOTPOT_RELATIVE_URLS[$url]; - - } else { - $relativeurl = $url; - - // get the subdirectory, $dir, of the quiz $filename - $dir = dirname($filename); - - // allow for leading "./" and "../" - while (preg_match('|^(\.{1,2})/(.*)$|', $url, $matches)) { - if ($matches[1]=='..') { - $dir = dirname($dir); - } - $url = $matches[2]; - } - - // add subdirectory, $dir, to $baseurl, if necessary - if ($dir && $dir<>'.') { - $baseurl .= "$dir/"; - } - - // prefix $url with $baseurl - $url = "$baseurl$url"; - - // add url to cache - $HOTPOT_RELATIVE_URLS[$relativeurl] = $url; - } - return $url; -} - -// allow importing in Moodle v1.4 (and less) -// same core functions but different class name -if (!class_exists("quiz_file_format")) { - class quiz_file_format extends qformat_default { - function readquestions ($lines) { - $format = new qformat_hotpot(); - return $format->readquestions($lines); - } - } -} - -?> -- 2.39.5