. /** * Book module local lib functions * * @package mod * @subpackage book * @copyright 2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; define('BOOK_NUM_NONE', '0'); define('BOOK_NUM_NUMBERS', '1'); define('BOOK_NUM_BULLETS', '2'); define('BOOK_NUM_INDENTED', '3'); require_once($CFG->dirroot.'/mod/book/lib.php'); function book_get_numbering_types() { return array (BOOK_NUM_NONE => get_string('numbering0', 'mod_book'), BOOK_NUM_NUMBERS => get_string('numbering1', 'mod_book'), BOOK_NUM_BULLETS => get_string('numbering2', 'mod_book'), BOOK_NUM_INDENTED => get_string('numbering3', 'mod_book') ); } ////////////////////////////////////////////////////////////////////////////////////// /// Any other book functions go here. Each of them must have a name that /// starts with book_ //check chapter ordering and //make sure subchapter is not first in book //hidden chapter must have all subchapters hidden too function book_check_structure($bookid) { if ($chapters = get_records('book_chapters', 'bookid', $bookid, 'pagenum', 'id, pagenum, subchapter, hidden')) { $first = true; $hidesub = true; $i = 1; foreach($chapters as $ch) { if ($first and $ch->subchapter) { $ch->subchapter = 0; } $first = false; if (!$ch->subchapter) { $hidesub = $ch->hidden; } else { $ch->hidden = $hidesub ? true : $ch->hidden; } $ch->pagenum = $i; update_record('book_chapters', $ch); $i++; } } } /// prepare button to turn chapter editing on - connected with course editing function book_edit_button($id, $courseid, $chapterid) { global $CFG, $USER; if (isteacheredit($courseid)) { if (!empty($USER->editing)) { $string = get_string("turneditingoff"); $edit = '0'; } else { $string = get_string("turneditingon"); $edit = '1'; } return '
'. ''. ''. ''. '
'; } else { return ''; } } /// general function for logging to table function book_log($str1, $str2, $level = 0) { switch ($level) { case 1: echo ''.$str1.''.$str2.''; break; case 2: echo ''.$str1.''.$str2.''; break; default: echo ''.$str1.''.$str2.''; break; } } //================================================= // import functions //================================================= /// normalize relative links (= remove ..) function book_prepare_link($ref) { if ($ref == '') { return ''; } $ref = str_replace('\\','/',$ref); //anti MS hack $cnt = substr_count($ref, '..'); for($i=0; $i<$cnt; $i++) { $ref = ereg_replace('[^/]+/\.\./', '', $ref); } //still any '..' left?? == error! error! if (substr_count($ref, '..') > 0) { return ''; } if (ereg('[\|\`]', $ref)) { // check for other bad characters return ''; } return $ref; } /// read chapter content from file function book_read_chapter($base, $ref) { $file = $base.'/'.$ref; if (filesize($file) <= 0 or !is_readable($file)) { book_log($ref, get_string('error'), 2); return; } //first read data $handle = fopen($file, "rb"); $contents = fread($handle, filesize($file)); fclose($handle); //extract title $chapter = new object(); if (preg_match('/([^<]+)<\/title>/i', $contents, $matches)) { $chapter->title = $matches[1]; } else { $chapter->title = $ref; } //extract page body if (preg_match('/<body[^>]*>(.+)<\/body>/is', $contents, $matches)) { $chapter->content = $matches[1]; } else { book_log($ref, get_string('error'), 2); return; } book_log($ref, get_string('ok')); $chapter->importsrc = $ref; //extract page head if (preg_match('/<head[^>]*>(.+)<\/head>/is', $contents, $matches)) { $head = $matches[1]; if (preg_match('/charset=([^"]+)/is', $head, $matches)) { $enc = $matches[1]; $textlib = textlib_get_instance(); $chapter->content = $textlib->convert($chapter->content, $enc, current_charset()); $chapter->title = $textlib->convert($chapter->title, $enc, current_charset()); } if (preg_match_all('/<link[^>]+rel="stylesheet"[^>]*>/i', $head, $matches)) { //dlnsk extract links to css for($i=0; $i<count($matches[0]); $i++){ $chapter->content = $matches[0][$i]."\n".$chapter->content; } } } return $chapter; } ///relink images and relative links function book_relink($id, $bookid, $courseid) { global $CFG; if ($CFG->slasharguments) { $coursebase = $CFG->wwwroot.'/file.php/'.$courseid; } else { $coursebase = $CFG->wwwroot.'/file.php?file=/'.$courseid; } $chapters = get_records('book_chapters', 'bookid', $bookid, 'pagenum', 'id, pagenum, title, content, importsrc'); $originals = array(); foreach($chapters as $ch) { $originals[$ch->importsrc] = $ch; } foreach($chapters as $ch) { $rel = substr($ch->importsrc, 0, strrpos($ch->importsrc, '/')+1); $base = $coursebase.strtr(urlencode($rel), array("%2F" => "/")); //for better internationalization (dlnsk) $modified = false; //image relinking if ($ch->importsrc && preg_match_all('/(<img[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $images)) { for($i = 0; $i<count($images[0]); $i++) { if (!preg_match('/[a-z]+:/i', $images[2][$i])) { // not absolute link $link = book_prepare_link($base.$images[2][$i]); if ($link == '') { continue; } $origtag = $images[0][$i]; $newtag = $images[1][$i].$link.$images[3][$i]; $ch->content = str_replace($origtag, $newtag, $ch->content); $modified = true; book_log($ch->title, $images[2][$i].' --> '.$link); } } } //css relinking (dlnsk) if ($ch->importsrc && preg_match_all('/(<link[^>]+href=")([^"]+)("[^>]*>)/i', $ch->content, $csslinks)) { for($i = 0; $i<count($csslinks[0]); $i++) { if (!preg_match('/[a-z]+:/i', $csslinks[2][$i])) { // not absolute link $link = book_prepare_link($base.$csslinks[2][$i]); if ($link == '') { continue; } $origtag = $csslinks[0][$i]; $newtag = $csslinks[1][$i].$link.$csslinks[3][$i]; $ch->content = str_replace($origtag, $newtag, $ch->content); $modified = true; book_log($ch->title, $csslinks[2][$i].' --> '.$link); } } } //general embed relinking - flash and others?? if ($ch->importsrc && preg_match_all('/(<embed[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $embeds)) { for($i = 0; $i<count($embeds[0]); $i++) { if (!preg_match('/[a-z]+:/i', $embeds[2][$i])) { // not absolute link $link = book_prepare_link($base.$embeds[2][$i]); if ($link == '') { continue; } $origtag = $embeds[0][$i]; $newtag = $embeds[1][$i].$link.$embeds[3][$i]; $ch->content = str_replace($origtag, $newtag, $ch->content); $modified = true; book_log($ch->title, $embeds[2][$i].' --> '.$link); } } } //flash in IE <param name=movie value="something" - I do hate IE! if ($ch->importsrc && preg_match_all('/<param[^>]+name\s*=\s*"?movie"?[^>]*>/i', $ch->content, $params)) { for($i = 0; $i<count($params[0]); $i++) { if (preg_match('/(value=\s*")([^"]+)(")/i', $params[0][$i], $values)) { if (!preg_match('/[a-z]+:/i', $values[2])) { // not absolute link $link = book_prepare_link($base.$values[2]); if ($link == '') { continue; } $newvalue = $values[1].$link.$values[3]; $newparam = str_replace($values[0], $newvalue, $params[0][$i]); $ch->content = str_replace($params[0][$i], $newparam, $ch->content); $modified = true; book_log($ch->title, $values[2].' --> '.$link); } } } } //java applet - add code bases if not present!!!! if ($ch->importsrc && preg_match_all('/<applet[^>]*>/i', $ch->content, $applets)) { for($i = 0; $i<count($applets[0]); $i++) { if (!stripos($applets[0][$i], 'codebase')) { $newapplet = str_ireplace('<applet', '<applet codebase="."', $applets[0][$i]); $ch->content = str_replace($applets[0][$i], $newapplet, $ch->content); $modified = true; } } } //relink java applet code bases if ($ch->importsrc && preg_match_all('/(<applet[^>]+codebase=")([^"]+)("[^>]*>)/i', $ch->content, $codebases)) { for($i = 0; $i<count($codebases[0]); $i++) { if (!preg_match('/[a-z]+:/i', $codebases[2][$i])) { // not absolute link $link = book_prepare_link($base.$codebases[2][$i]); if ($link == '') { continue; } $origtag = $codebases[0][$i]; $newtag = $codebases[1][$i].$link.$codebases[3][$i]; $ch->content = str_replace($origtag, $newtag, $ch->content); $modified = true; book_log($ch->title, $codebases[2][$i].' --> '.$link); } } } //relative link conversion if ($ch->importsrc && preg_match_all('/(<a\s[^>]*href=")([^"^#]*)(#[^"]*)?("[^>]*>)/i', $ch->content, $links)) { for($i = 0; $i<count($links[0]); $i++) { if ($links[2][$i] != '' //check for inner anchor links && !preg_match('/[a-z]+:/i', $links[2][$i])) { //not absolute link $origtag = $links[0][$i]; $target = book_prepare_link($rel.$links[2][$i]); //target chapter if ($target != '' && array_key_exists($target, $originals)) { $o = $originals[$target]; $newtag = $links[1][$i].$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i].$links[4][$i]; $newtag = preg_replace('/target=[^\s>]/i','', $newtag); $ch->content = str_replace($origtag, $newtag, $ch->content); $modified = true; book_log($ch->title, $links[2][$i].$links[3][$i].' --> '.$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i]); } else if ($target!='' && (!preg_match('/\.html$|\.htm$/i', $links[2][$i]))) { // other relative non html links converted to download links $target = book_prepare_link($base.$links[2][$i]); $origtag = $links[0][$i]; $newtag = $links[1][$i].$target.$links[4][$i]; $ch->content = str_replace($origtag, $newtag, $ch->content); $modified = true; book_log($ch->title, $links[2][$i].' --> '.$target); } } } } if ($modified) { $ch->title = addslashes($ch->title); $ch->content = addslashes($ch->content); $ch->importsrc = addslashes($ch->importsrc); if (!update_record('book_chapters', $ch)) { error('Could not update your book'); } } } }