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 />&nbsp;&nbsp;$meta<br />&nbsp;&nbsp;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('&amp;',$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