1<?php 2 if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../../../').'/'); 3 if(!defined('EPUB_DIR')) define('EPUB_DIR',realpath(dirname(__FILE__).'/../').'/'); 4 require_once(EPUB_DIR.'/helper.php'); 5 /** 6 utilities 7 */ 8 /* 9 Creates headers for both the .opf and .ncx files 10 */ 11 function epub_opf_header($user_title) { 12 global $conf; 13 $lang = $conf['lang']; 14 $user= rawurldecode($_POST['user']); 15 $url=rawurldecode($_POST['location']); 16 $url=dirname($url); 17 $title=rawurldecode($_POST['title']); 18 19 $unique_identifier = rtrim($url,'/'); 20 $ident_title = str_replace(' ', '_',strtolower(trim($title))); 21 $unique_identifier .= "/$ident_title"; 22 23 $uniq_id = str_replace('/','', DOKU_BASE) . "_id"; 24 $dc_date = date("r"); 25 $epub_version = "fckglite"; 26 $info_data = file(EPUB_DIR . 'plugin.info.txt',FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); 27 for($i=0; $i<count($info_data); $i++) { 28 if(strpos($info_data[$i],'date') !== false) { 29 $epub_version = trim(str_replace('date',"",$info_data[$i])); 30 break; 31 } 32 } 33 34 if(!$user_title) { 35 $cover_png='<item id="cover-image" href="Images/cover.png" media-type="image/png"/>'. "\n"; 36 } 37 $outp = <<<OUTP 38<?xml version='1.0' encoding='utf-8'?> 39<package xmlns="http://www.idpf.org/2007/opf" xmlns:dc="http://purl.org/dc/elements/1.1/" 40 unique-identifier="$uniq_id" version="2.0"> 41<metadata> 42<dc:title>$title</dc:title> 43<dc:creator>$user</dc:creator> 44<dc:identifier id="$uniq_id">$unique_identifier</dc:identifier> 45<dc:language>$lang</dc:language> 46<dc:date>$dc_date</dc:date> 47<meta name="cover" content="cover-image" /> 48<meta name="plugin version" content="$epub_version"/> 49</metadata> 50<manifest> 51<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/> 52 <item id="cover" href="Text/title.html" media-type="application/xhtml+xml"/> 53 $cover_png 54OUTP; 55 56 $dir = epub_get_metadirectory() . 'OEBPS/'; 57 io_saveFile($dir . 'content.opf',$outp); 58 59 flush(); 60 61 $ncx=<<<NCX 62<?xml version="1.0"?> 63<!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN" 64 "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd"> 65 <ncx version="2005-1" xml:lang="en" xmlns="http://www.daisy.org/z3986/2005/ncx/"> 66 <head> 67 <meta content="$url" name="dtb:uid"/> 68 <meta content="1" name="dtb:depth"/> 69 <meta content="0" name="dtb:totalPageCount"/> 70 <meta content="0" name="dtb:maxPageNumber"/> 71 </head> 72 <docTitle> 73 <text>$title</text> 74 </docTitle> 75 <navMap> 76 77NCX; 78 io_saveFile($dir . 'toc.ncx',$ncx); 79 80 } 81 82 function epbub_entity_replace($matches) { 83 global $entities; 84 85 if(array_key_exists($matches[0], $entities)) { 86 return $entities[$matches[0]]; 87 } 88 return $matches[0]; 89 } 90 91 function epub_css($plugin) { 92 $use_less = false; 93 if($plugin !== false) { 94 $r = $plugin->get_renderer(); 95 $use_less = $r->getConf('less'); 96 } 97 98 $css = (class_exists('lessc') && $use_less) ? 'css3.php' : 'css2.php'; 99 if($css == 'css3.php') { 100 echo "Using LESS: $css\n"; 101 } 102 else { 103 echo "Not using LESS, either not found or excluded by configuration: using $css\n"; 104 } 105 require_once($css); 106 epub_css_out(epub_get_oebps()); 107 } 108 109 function epub_write_spine() { 110 $items = epub_push_spine(); 111 epub_opf_write('<spine toc="ncx">'); 112 epub_opf_write('<itemref idref="cover" linear="no"/>'); 113 foreach($items as $page) { 114 epub_opf_write('<itemref idref="' . $page[1] . '" linear="yes"/>'); 115 } 116 epub_opf_write('</spine>'); 117 } 118 119 function epub_write_footer() { 120 $footer=<<<FOOTER 121 <guide> 122 <reference href="Text/title.html" type="cover" title="Cover"/> 123 </guide> 124</package> 125FOOTER; 126 epub_opf_write($footer); 127 $handle = epub_opf_write(null); 128 fclose($handle); 129 } 130 131 /** 132 returns true if a page id is included among pages being processed for this ebook, 133 otherwise false 134 If a page id is included in the ebook then the Renderer will create a link to it for accesss 135 from within the ebook, otherwise it will create a text version of the url 136 */ 137 function is_epub_pageid($id) { 138 static $ep_ids; 139 if(!$ep_ids) { 140 if(isset($_POST['epub_ids'])) { 141 $ep_ids =explode(';;',rawurldecode($_POST['epub_ids'])); 142 $ns_pages = epub_save_ns_pages(); 143 if($ns_pages) { 144 $ep_ids = array_merge($ns_pages,$ep_ids); 145 } 146 //echo print_r($ep_ids,true); 147 } 148 else { 149 return false; 150 } 151 } 152 153 if(in_array($id,$ep_ids)) return true; 154 155 return in_array(":$id",$ep_ids); 156 } 157 158 function epub_get_metadirectory($temp_user=null) { 159 static $dir; 160 161 $seed = md5(rawurldecode($_POST['user']).time()); 162 if(!$dir) { 163 if(isset($_POST['client'])) { 164 $user= rawurldecode($_POST['client']) . ":$seed"; 165 } 166 else { 167 $user=$temp_user?"$temp_user:$seed":$seed; 168 } 169 $dir = dirname(metaFN("epub:$user:tmp",'.meta')) . '/'; 170 } 171 172 return $dir; 173 } 174 175 176 function epub_get_data_media() { 177 static $dir; 178 global $conf; 179 if(!$dir) { 180 $dir = init_path($conf['savedir']) . '/media/'; 181 } 182 183 return $dir; 184 185 } 186 187 /* 188 returns full path to the OEPBS directory 189 */ 190 function epub_get_oebps() { 191 static $dir; 192 if(!$dir) { 193 $dir=epub_get_metadirectory() . 'OEBPS/'; 194 } 195 return $dir; 196 197 } 198 199 /** 200 maintains the item id 201 */ 202 function epub_itemid() { 203 static $num = 0; 204 return 'item' . ++$num; 205 } 206 207 function epub_fn() { 208 static $num = 0; 209 return ++$num; 210 } 211 function epub_close_footnotes() { 212 $handle = epub_footnote_handle(true); 213 if(!$handle) return; 214 $item_num=epub_write_item('Text/footnotes.html', "application/xhtml+xml"); 215 epub_push_spine(array('Text/footnotes.html',$item_num)); 216 fwrite($handle,"\n</div></body></html>"); 217 } 218 219 function epub_write_footnote($fn_id,$page,$url) { 220 static $handle; 221 static $current_page=""; 222 if(!$handle) { 223 $handle = epub_footnote_handle(); 224 epub_write_fn_header($handle); 225 } 226 if($current_page != $page) { 227 fwrite($handle,"<br/><h1><a name='$page' id='$page'>$page</a></h1>\n"); 228 } 229 230 $url = preg_replace("/\s*\(.*?\)\s*$/","",$url); 231 232 233 if(!preg_match("#https?#",$url)) { 234 $url = preg_replace('#' . DOKU_BASE . '#', DOKU_URL, $url); 235 } 236 237 $footnote = "<a href='$page#backto_$fn_id' class='wikilink1' title='$page'>[$fn_id]</a> <a href='$url'>$url</a><br />\n"; 238 fwrite($handle,$footnote); 239 $current_page=$page; 240 } 241 242 function epub_write_fn_header($handle) { 243$header=<<<HEADER 244<?xml version="1.0" encoding="utf-8"?> 245<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 246"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> 247<html xmlns="http://www.w3.org/1999/xhtml"> 248<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 249<link rel="stylesheet" type="text/css" href="../Styles/style.css"/> 250 251<title>Footnotes</title></head><body> 252<div class='dokuwiki'> 253HEADER; 254 fwrite($handle,$header); 255 } 256 257 function epub_footnote_handle($return_only=false) { 258 static $handle; 259 if($return_only) return $handle; 260 if(!$handle) { 261 $oebps = epub_get_oebps(); 262 $handle=fopen($oebps. 'Text/footnotes.html', 'a'); 263 } 264 return $handle; 265 } 266 267 function epub_save_image($img,$fullpath){ 268 $command = "wget --quiet $img -O $fullpath"; 269 $s = exec ($command, $output,$retv); 270 271 if(!$retv && file_exists($fullpath)) { 272 return true; 273 } 274 else echo "Cannot fetch $img\n"; 275 276 return false; 277 } 278 279 function epub_write_item($url,$mime_type) { 280 $item_num = epub_itemid() ; 281 if(strpos($url, 'cover.png') !== false) { 282 $item='<item href="' . $url .'" id="cover-image" media-type="' . $mime_type . '" />'; 283 } 284 else { 285 $item='<item href="' . $url .'" id="' . $item_num . '" media-type="' . $mime_type . '" />'; 286 } 287 epub_opf_write($item); 288 epub_write_zip($url); 289 return $item_num; 290 } 291 292 function epub_zip_handle($path=null) { 293 static $zip; 294 if(!class_exists ('ZipArchive')) return false; 295 if($path && !$zip) { 296 $zip = new ZipArchive; 297 $zip->open($path); 298 } 299 300 return $zip; 301 } 302 303 function epub_write_zip($url) { 304 static $zip; 305 static $oebps; 306 307 if(!$zip) { 308 $zip = epub_zip_handle(); 309 if($zip) $oebps = epub_get_oebps(); 310 } 311 if($zip) { 312 $file = $oebps . $url; 313 $zip->addFile($file, "OEBPS/$url"); 314 } 315 316 } 317 318 /** 319 Adds content.opf and toc.ncx to zip file and closes it 320 */ 321 function epub_finalize_zip() { 322 $zip = epub_zip_handle() ; 323 if(!$zip) return false; 324 epub_write_zip('content.opf'); 325 epub_write_zip('toc.ncx'); 326 $zip->close(); 327 return true; 328 } 329 330 /** 331 loads spine array and adds nav points to the ncx file 332 then outputs closing tags to ncx file. The header to 333 ncx file is created in epub_opf_header() 334 */ 335 function epub_write_ncx() { 336 $toc = epub_get_oebps() . 'toc.ncx'; 337 338 $opf_handle= fopen($toc, 'a'); 339 if(!$opf_handle) { 340 echo "unable to open file: $toc\n"; 341 exit; 342 } 343 $items = epub_push_spine(); 344 345 array_unshift($items,array('Text/title.html')); 346 $num = 0; 347 foreach($items as $page) { 348 $num++; 349 $page = $page[0]; 350 $title=epub_titlesStack(); 351 if(!$page) continue; 352 if($title) echo "found $title for $page\n"; 353 $navpoint=<<<NAVPOINT 354 <navPoint id="np-$num" playOrder="$num"> 355 <navLabel> 356 <text>$title</text> 357 </navLabel> 358 <content src="$page"/> 359</navPoint> 360NAVPOINT; 361 fwrite($opf_handle,"$navpoint\n"); 362 } 363 fwrite($opf_handle,"</navMap>\n</ncx>\n"); 364 fflush($opf_handle); 365 fclose($opf_handle); 366 367 } 368 369 /* write data to opf file */ 370 function epub_opf_write($data=null) { 371 static $opf_handle; 372 static $opf_content; 373 if(!$opf_handle) { 374 $opf_content = epub_get_oebps() . 'content.opf'; 375 $opf_handle= fopen($opf_content, 'a'); 376 if(!$opf_handle) { 377 echo "unable to open file: $opf_content\n"; 378 exit; 379 } 380 } 381 382 if($data) { 383 if( fwrite($opf_handle,"$data\n") == false) { 384 echo "cannot write to $opf_content\n"; 385 exit; 386 } 387 } 388 389 return $opf_handle; 390 } 391 392 function epub_titlesStack($titles=null) { 393 static $e_titles; 394 if(is_array($titles)) { 395 $e_titles=$titles; 396 } 397 elseif(count($e_titles)) { 398 return array_shift($e_titles); 399 } 400 return ""; 401 } 402 403 function epub_setup_book_skel($user_title=false) { 404 $dir=epub_get_metadirectory(); 405 $meta = $dir . 'META-INF'; 406 $oebps = epub_get_oebps(); 407 $media_dir = epub_get_data_media() . 'epub'; 408 io_mkdir_p($meta); 409 io_mkdir_p($oebps); 410 io_mkdir_p($oebps . 'Images/'); 411 io_mkdir_p($oebps . 'Audio/'); 412 io_mkdir_p($oebps . 'Video/'); 413 io_mkdir_p($oebps . 'Text/'); 414 io_mkdir_p($media_dir); 415 io_mkdir_p($oebps . 'Styles/'); 416 if(isset($_POST['client'])) { 417 $user= cleanID(rawurldecode($_POST['client'])). '/'; 418 io_mkdir_p($media_dir. '/'. $user); 419 } 420 $book_id = cleanID(rawurldecode($_POST['book_page'])); 421 422 copy(EPUB_DIR . 'scripts/package/my-book.epub', $dir . 'my-book.epub'); 423 copy(EPUB_DIR . 'scripts/package/container.xml', $dir . 'META-INF/container.xml'); 424 if(!$user_title) { 425 copy(EPUB_DIR . 'scripts/package/title.html', $oebps . 'Text/title.html'); 426 copy(EPUB_DIR . 'scripts/package/cover.png', $oebps . 'Images/cover.png'); 427 } 428 $zip = epub_zip_handle($dir . 'my-book.epub'); 429 if($zip) { 430 $zip->addFile(EPUB_DIR . 'scripts/package/container.xml', 'META-INF/container.xml'); 431 if(!$user_title) { 432 $zip->addFile(EPUB_DIR . 'scripts/package/title.html', 'OEBPS/Text/title.html'); 433 $zip->addFile(EPUB_DIR . 'scripts/package/cover.png', 'OEBPS/Images/cover.png'); 434 } 435 } 436 } 437 438 /* Creates array of files required for spine */ 439 function epub_push_spine($page=null) { 440 static $spine = array(); 441 if(!$page) return $spine; 442 $spine[] = $page; 443 444 } 445 function epub_pack_book() { 446 echo "packing epub\n"; 447 448 $user = ""; 449 if(isset($_POST['client'])) { 450 $user= rawurldecode($_POST['client']) . '/'; 451 } 452 $meta = epub_get_metadirectory() ; 453 echo "$meta\n"; 454 if(!epub_zip_handle() && epub_isWindows()) { 455 epub_pack_ZipLib($meta); 456 } 457 elseif(!epub_zip_handle()) { 458 chdir($meta); 459 echo rawurlencode("*nix zip command used \n"); 460 $cmd = 'zip -Xr9Dq my-book.epub *'; 461 exec($cmd,$ar, $ret); 462 if($ret > 0) { 463 echo "zip error: exit status=$ret\n"; 464 echo "<b>Error codes:</b>\n 4: memory allocation error\n 11-18: unable write to or create file\n 127: zip command not found\n"; 465 echo "Trying ZipLib\n"; 466 epub_pack_ZipLib($meta); 467 } 468 } 469 else echo "ziparchive used\n"; 470 $plugin =& plugin_load('syntax','epub'); 471 $oldname = $meta . 'my-book.epub'; 472 $rmdir= $plugin->getConf('rmdir'); 473 $epub_file = strtolower(date("Y_F_j_h-i-s") ) . '.epub'; 474 $newname = mediaFN("epub:$user:$epub_file"); 475 if(rename ($oldname , $newname )) { 476 $epub_id = cleanID("epub:$user:$epub_file"); 477 $helper = new helper_plugin_epub(); 478 $id = cleanID(rawurldecode($_POST['book_page'])); 479 echo "ebook id=$id\n"; 480 $title=rawurldecode($_POST['title']); 481 $helper->addBook($id,$epub_id,$title); 482 echo "New Ebook: $epub_id\n" ; 483 $helper->delete_dw_cachefiles($id); 484 } 485 486 if($rmdir == 'y') { 487 if(epub_isWindows()) { 488 $meta = str_replace('/','\\',$meta); 489 $cmd = "RMDIR /s /q $meta"; 490 } 491 else { 492 $cmd ="rm -f -r $meta"; 493 } 494 495 system($cmd,$retval); 496 if($retval) { 497 echo "unable to remove dir:<br /> $meta<br /> error code: $retval\n"; 498 } 499 else { 500 echo "$cmd\n"; 501 } 502 } 503 504 } 505 506 function epub_pack_ZipLib($meta) { 507 chdir($meta); 508 echo rawurlencode("Using Dokuwiki's ZipLib Class\n"); 509 $epub_file = $meta . 'my-book.epub'; 510 unlink($epub_file); 511 $z = new ZipLib; 512 $z->add_File('application/epub+zip', 'mimetype', 0); 513 $z->Compress('OEBPS','./'); 514 $z->Compress('META-INF','./'); 515 $result = $z->get_file(); 516 file_put_contents($epub_file,$result); 517 } 518 519 function epub_is_installed_plugin($which) { 520 static $installed_plugins; 521 if(!$installed_plugins) { 522 $installed_plugins=plugin_list('syntax'); 523 } 524 if(in_array($which, $installed_plugins)) return true; 525 return false; 526 } 527 528 function epub_check_for_ditaa(&$xhtml,$renderer) { 529 530 if(strpos($xhtml,"ditaa/img.php") === false) return; 531 $regex = '#<img src=\"(.*?ditaa.*?)\".*\/>#m'; 532 533 if(!preg_match_all($regex,$xhtml,$matches,PREG_SET_ORDER)) return; 534 $plugin = plugin_load('syntax','ditaa'); 535 536 for($i=0; $i<count($matches); $i++ ) { 537 list($url,$params) = explode('?',$matches[$i][1]); 538 // parse the query string 539 $params = explode('&',$params); 540 541 $data = array(); 542 foreach($params as $param) { 543 list($key,$val) = explode('=',$param); 544 $data[$key]=$val; 545 } 546 $cache = $plugin->_imgfile($data); // get the image address in data/cache 547 if($cache) { 548 $name=$renderer->copy_media($cache,true); //copy the image to epub's OEBPS directory and enter it into opf file 549 if($name) { 550 $regex = '#<img src=\"(.*?' . $data['md5'] . '.*?)\".*\/>#m'; // use the ditaa plugin's md5 identifier to replace correct image 551 $replace = '<img src="../' . $name . '" />'; 552 $xhtml = preg_replace($regex,$replace,$xhtml); 553 } 554 } 555 556 } 557 } 558 559 function epub_check_for_graphviz(&$xhtml,$renderer,$data,$graphviz) { 560 $cache = $graphviz->_imgfile($data); 561 if($cache) { 562 $name=$renderer->copy_media($cache,true); //copy the image to epub's OEBPS directory and enter it into opf file 563 $regex = $regex = 'src=.*?'.$data['md5'] . '"' ; 564 $xhtml = preg_replace('#' . $regex .'#',"src=\"../$name\"",$xhtml); 565 } 566 } 567 568 function epub_check_for_math(&$xhtml,$renderer) { 569 $regex='#mathpublish\/img.php\?img=([a-f0-9]+)\"#'; 570 571 572 if(preg_match($regex,$xhtml,$matches)) { 573 574 $cache = getcachename($matches[1], '.mathpublish.png'); 575 $name=$renderer->copy_media($cache,true); 576 577 $name = 'src="../' . $name . '" ' ; 578 $regex = '#src\s*=.*?mathpublish\/img.php\?img=([a-f0-9]+)\"#'; 579 $xhtml = preg_replace($regex, $name ,$xhtml ); 580 581 } 582 } 583 584 function epub_check_for_mathjax(&$result) { 585 586 if(epub_is_installed_plugin('mathjax_protecttex') ) { 587 $plugin =& plugin_load('syntax','mathjax_protecttex'); 588 $url = $plugin->getConf('url'); 589 if(preg_match("#^//#",$url)) { 590 $url = "http:" . $url; 591 } 592 $config = $plugin->getConf('config'); 593 594$result .= <<<MATHJAX 595 596<script type="text/x-mathjax-config" charset="utf-8">/*<![CDATA[*/ 597$config 598} 599); 600/*!]]>*/</script> 601<script type="text/javascript" charset="utf-8" src="$url"></script> 602 603MATHJAX; 604 } 605 } 606 607 608 function epub_save_namespace($ns="") { 609 static $namespace; 610 if($ns !== false) { 611 $namespace = $ns; 612 } 613 return $namespace; 614 } 615 616 function epub_checkfor_ns($name, &$pages, &$titles) { 617 $name = rtrim($name); 618 619 $n = strrpos($name,'*',-1); 620 if(!$n) return; 621 array_shift($pages); // remove namespace id: namespace:* 622 623 $ns = wikiFN($name.':tmp'); 624 625 $path_parts= pathinfo($ns); 626 $dir = $path_parts['dirname']; 627 echo "Directory: $dir\n"; 628 $paths = glob("$dir/*.txt",GLOB_NOSORT); 629 $helper = new helper_plugin_epub(); 630 if($helper->get_conf('sort')){ 631 rsort($paths); 632 } 633 else { echo "not sorting files in namespace: $ns\n";} 634 $_pages = array(); 635 $_titles = array(); 636 637 $ns = rtrim($name,'*'); 638 foreach ($paths as $path) { 639 $_pages[] = $ns . basename($path, '.txt'); 640 } 641 $title_page = array_shift($titles); 642 array_shift($titles); // remove namespace asterisk from titles list 643 644 for ($i=0; $i<count($_pages); $i++) { 645 array_unshift ($pages , $_pages[$i]); 646 $_titles[$i] = basename($_pages[$i], '.txt'); 647 $elems = explode(':',$_titles[$i] ); 648 $_titles[$i] = $elems[count($elems)-1]; 649 $_titles[$i] = ucwords(str_replace('_',' ',$_titles[$i])); 650 array_unshift ($titles , $_titles[$i]); 651 } 652 array_unshift($titles,$title_page); 653 654 echo "Found following pages in $name namespace: \n"; 655 print_r($_pages); 656 echo "Saving namespace pages\n"; 657 epub_save_ns_pages($_pages); 658 echo "Created following titles: \n"; 659 print_r($_titles); 660 661 } 662 663 function epub_save_ns_pages($_pages="") { 664 static $pages; 665 if($_pages) { 666 $pages = $_pages; 667 } 668 return $pages; 669 } 670 671 function epub_isWindows() { 672 return (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'); 673 } 674 675 function epub_update_progress($msg=null) { 676 static $user; 677 static $dir; 678 static $progress_file; 679 if(!$msg && $progress_file) { 680 unlink($progress_file); 681 } 682 if(!$user) { 683 $user= rawurldecode($_POST['user']); 684 if($user) $user=cleanID($user); 685 } 686 if(!$dir) { 687 if($user) { 688 $dir = epub_get_metadirectory($user); 689 } 690 else $dir = epub_get_metadirectory(); 691 $dir = rtrim($dir,'/'); 692 $dir = dirname($dir . ".meta") . '/'; 693 $progress_file = $dir . "progress.meta"; 694 } 695 696 if($progress_file && $msg) { 697 io_saveFile($progress_file,"$msg\n"); 698 } 699 700 } 701 702 function epub_check_perm($id) { 703 $id= cleanID(rawurldecode($id)); 704 $acl = auth_quickaclcheck($id); 705 return $acl; 706 } 707 708 function epub_clean_name($name) { 709 return ltrim($name,'_'); 710 } 711