*/ if(!defined('DOKU_INC')) die(); if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); require_once(DOKU_PLUGIN.'admin.php'); require_once(dirname(__FILE__).'/latexinc.php'); /** * All DokuWiki plugins to extend the admin function * need to inherit from this class */ class admin_plugin_latex extends DokuWiki_Admin_Plugin { var $output; /** * return some info */ function getInfo(){ $a = ''; if(method_exists(DokuWiki_Admin_Plugin,"getInfo")) { $a = parent::getInfo(); /// this will grab the data from the plugin.info.txt $a['name'] = 'LaTeX plugin administration'; return $a; } else // Otherwise return some hardcoded data for old dokuwikis return array( 'author' => 'Alexander Kraus, Michael Boyle, and Mark Lundeberg)', 'email' => '.', 'date' => '???', 'name' => 'LaTeX plugin', 'desc' => 'LaTeX rendering plugin; requires LaTeX, dvips, ImageMagick.', 'url' => 'http://www.dokuwiki.org/plugin:latex' ); } /** * return sort order for position in admin menu */ function getMenuSort() { return 999; } // Purgers. function vio_atime($fname) { if(time() - fileatime($fname) - $this->_timelimit > 0) { unlink($fname); return $this->_timelimit; } return false; } function vio_mtime($fname) { if(time() - filemtime($fname) - $this->_timelimit > 0) { unlink($fname); return true; } return false; } function vio_all($fname) { unlink($fname); return true; } // purge all files older than $timelimit (in seconds) // $mode = // atime: age based on fileatime(). // mtime: age based on filemtime(). // all: delete all cached files. function latexpurge($mode, $timelimit) { global $conf, $config_cascade; $meddir = $conf['mediadir'] . '/' . strtr($this->getConf('latex_namespace'),':','/'); $images = glob($meddir.'/img*'); $this->_timelimit = $timelimit; switch($mode) { case 'atime': $vio = array_map(array($this,'vio_atime'),$images); break; case 'mtime': $vio = array_map(array($this,'vio_mtime'),$images); break; case 'all': $vio = array_map(array($this,'vio_all'),$images); break; default: return false; } return array_combine($images,$vio); } /** * handle user request */ function handle() { global $conf, $config_cascade; $this->output = ""; if(isset($_POST['latexpurge'])) { $mode = $_POST['purgemode']; $days = $_POST['purgedays']; if(is_numeric($days) && $days == 0) $mode = 'all'; if($mode == 'all') { // If the admin wants to delete all of the images, probably it's good to print this reminder // since they are likely doing it after changing the colour or something. // (I don't know how many hours I spent trying to fix LaTeX heisenbugs that were just cached... grr.) $this->output .= '
'.$this->getLang('refresh_note').'
'; } $numdeleted = 0; $numkept = 0; $this->output .= "
Purge result ([x] = deleted):\n";
			if($mode == 'all' || (is_numeric($days) && $days >= 0)) {
				$res = $this->latexpurge($mode, $days*86400);				
				foreach($res as $img => $vio){
					if($vio) {
						$this->output .= '[x] '.$img . "\n";
						$numdeleted += 1;
					} else {
						// $this->output .= '[ ] '.$img . "\n";
						$numkept += 1;
					}
				}
			} else {
				$this->output = "
Purger: Bad form inputs. No action taken.
".$this->output; } $this->output .= "Totals: $numdeleted deleted, $numkept kept (kept files not shown).\n"; if ($numdeleted > 0) { touch($config_cascade['main']['local']); } $this->output .= "
"; } } /** * output appropriate html */ function html() { global $ID,$INFO; ptln('

'.$this->output.'

'); ptln('

LaTeX plugin administrator tasks

'); ptln('

'.$this->getLang('legend_purge').'

'); ptln('
'); ////////////// PURGE FORM ptln('
'); ptln(''); ptln(''); ptln('
'); $labtimes = $this->getLang('label_times'); ptln('('); ptln(' | )'); echo $this->getLang('label_olderthan'); echo ''; echo $this->getLang('label_days'); ptln('
'); echo ''; ptln('
'); ptln('
'); ptln('
'); /////////////// DIAGNOSER ptln('

LaTeX troubleshooter

'); ptln('
'); ptln('
'); ptln(' '); ptln(' '); ptln('Push this button to diagnose your LaTeX/ImageMagick installation:
'); ptln('Check this button to keep the temporary files used during compilation.
'); ptln('The following latex code will be inserted into the template and compiled:'); ptln('
'); if(isset($_REQUEST['testformula'])) $testformula = $_REQUEST['testformula']; else $testformula = '$$\underbrace{{\it f}({\rm DokuWiki}) = \overbrace{[a+b=c]}^\textrm{\LaTeX}}_{Success!}$$'; ptln(' '); ptln('
'); ptln('
'); if($_REQUEST['dotest']) { ptln('

Versions

'); ptln('
'); ptln('This is a test of the acessibility of your programs and their versions.'); ptln(''); ptln(''); foreach(array($this->getConf("latex_path"),$this->getConf("dvips_path"), $this->getConf("convert_path"),$this->getConf("identify_path")) as $path) { ptln(''); } ptln('
commandoutput
');
				$cmd = $path." --version 2>&1";
				echo htmlspecialchars($cmd);
				ptln('
'); unset($execout); exec($cmd,$execout,$statuscode); if($statuscode == 0) echo '
';
				else
					echo '
'; //pink for error status
				echo htmlspecialchars(implode(PHP_EOL,$execout));
				ptln('
'); ptln('
'); ptln('

Test run

'); $plug = new syntax_plugin_latex_common(); /// Directory sanity checks if(is_writable($plug->_latex->getPicturePath()) && is_dir($plug->_latex->getPicturePath())) ptln('
Media directory is writable: '.$plug->_latex->getPicturePath().'
'); else ptln('
Media directory not writable or nonexistant! '.$plug->_latex->getPicturePath().'
Recommendation: This media namespace must be writable on the file system.
'); if(is_writable($plug->_latex->_tmp_dir) && is_dir($plug->_latex->_tmp_dir)) ptln('
Temporary directory is writable: '.$plug->_latex->_tmp_dir.'
'); else ptln('
Temporary directory not writable or nonexistant! '.$plug->_latex->_tmp_dir.'
Recommendation: This media namespace must be writable on the file system.
'); // simulate a call to the syntax plugin; force render, keep temp files. $md5 = md5($testformula); $outname = $plug->_latex->getPicturePath()."/img".$md5.'.'.$plug->_latex->_image_format; if(file_exists($outname)) { if(unlink($outname)) ptln('
Removed cache file for test: '.$outname.'
WARNING: You may need to refresh your browser\'s cache to see changes in the resulting image.
'); else ptln('
Could not remove cached file for test! '.$outname.'
the following tests will not work (renderer will just reuse the cached file)
'); } ptln('
Attempting to render to target '.$outname.'
'); $plug->_latex->_keep_tmp = true; $plug->_latex->_cmdoutput = ''; // activate command log. $data = array($testformula,DOKU_LEXER_UNMATCHED,'class'=>"latex_inline", 'title'=>"Math", NULL); $this->doc = ''; $plug->render('xhtml', $this, $data); $tmpw = $this->getConf('latex_namespace').':tmp:'.$plug->_latex->_tmp_filename; $tmpf = $plug->_latex->_tmp_dir."/".$plug->_latex->_tmp_filename; $tmpext = array('tex','log','aux','dvi','ps',$plug->_latex->_image_format); foreach($tmpext as $ext) { $fname = $tmpf.'.'.$ext; if(is_file($fname)) { if(isset($_REQUEST['keep_tmp'])) { $rendstr = $this->render('{{'.$tmpw.'.'.$ext.'?linkonly&nocache|'.$fname.'}}'); $rendstr = preg_replace('/<\\/?p>/','',$rendstr); } else $rendstr = $fname; ptln('
File created: '.$rendstr.'
'); } else ptln('
File missing! '.$fname.'
'); } if(! isset($_REQUEST['keep_tmp'])) ptln('
These files '.$tmpf.'.* will be deleted at the end of this script.
'); if(is_file($outname)) ptln('
Successfully moved to media: '.$outname.'
'); else ptln('
File missing from media! '.$outname.'
'); ptln('
'); ptln(''); ptln(''); ptln('
Input LaTeX fileFinal result
');
			if(is_readable($tmpf.'.tex') && is_file($tmpf.'.tex'))
				echo htmlspecialchars(file_get_contents($tmpf.'.tex'));
			else
				echo 'MISSING';
			ptln('
'); // ptln(htmlspecialchars($plug->_url)); // ptln('

'); ptln('
'); ptln($this->doc); ptln('
'); ptln('Command log:'); echo '
';
			echo $plug->_latex->_cmdoutput;
			echo '
'; ptln('Contents of '.$tmpf.'.log:'); echo '
';
			echo htmlspecialchars(file_get_contents($tmpf.'.log'));
			echo '
'; if(! isset($_REQUEST['keep_tmp'])) $plug->_latex->cleanTemporaryDirectory(); ptln('
'); } } }