<?php
/*
M. Arndt <chmarndt at medemsand.de> (February 2006)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
function maxima_process($text) {
global $maxima_process_message, $maxima_ex_time, $maxima_session_result;
// Some Settings
$maxima_path = "/usr/local/bin/maxima";
$temp_path = "/tmp/maxima/";
$max_execution_time = 5; // in seconds
// As a simplistic security measure, all lines containing one of these expressions
// are not passed to maxima.
$maxima_blacklist = array("system", "save", "load", "plot", "lisp", "includ", "compil", "file", "batch", "stringout", "translat", "stout", "stin", "block");
$maxima_question = false;
$max_execution_time_exceeded = false;
$unique_md5 = md5 (uniqid (rand()));
$maxima_input = $text;
$maxima_process_message = "";
if ( ! is_dir( $temp_path ) ) { mkdir( $temp_path, 0777 ); }
$maxima_input = str_replace("\n", "", $maxima_input);
$lines = explode(";", $maxima_input);
foreach($lines as $line) {
$delete = False;
foreach($maxima_blacklist as $d) {
if (eregi($d, $line, $a)) {
$delete = True;
$maxima_process_message .= "The expression \"".trim($line).";\" has not been passed to maxima.<br>";
break;
}
}
if (!$delete) $newline[] = $line;
}
$maxima_input = implode(";", $newline);
$maxima_input = $maxima_input . " maxima_session_".$unique_md5.";";
$out_file = $temp_path."maxima_$unique_md5.out";
$in_file = $temp_path."maxima_$unique_md5.in";
$pid_file = $temp_path."maxima_$unique_md5.pid";
$fp = fopen($in_file, "w");
fwrite($fp, $maxima_input);
fclose($fp);
$cmd = "env MAXIMA_USERDIR=$temp_path $maxima_path --batch=\"$in_file\" > $out_file &\njobs -l > $pid_file";
// For checking the environment:
// $cmd = "/usr/local/bin/maxima -d";
// return $cmd;
$start_time = time() + microtime();
passthru($cmd, $ret);
// Process Control *****************************************************************
$pf = file_get_contents($pid_file);
preg_match("/^.*? ([0-9]+) .*/", $pf, $p);
$pid = trim($p[1]);
if ($pid > 0 and is_numeric($pid)) {
while( true ) {
$delta_time = time() + microtime() - $start_time;
if ($delta_time > $max_execution_time) $max_execution_time_exceeded = true;
shell_exec("kill -s stop $pid");
$l = shell_exec("wc -l $out_file");
$m = shell_exec("head -n $l $out_file");
shell_exec("kill -s cont $pid");
if (preg_match("/.*\?$/s", trim($m), $a)) $maxima_question = true;
$s = shell_exec("ps -o pid,args -p $pid | grep maxima");
//return $s;
if (!strstr($s, $pid)) break;
if ($max_execution_time_exceeded or $maxima_question) break;
}
$s = shell_exec("ps -o pid,args -p $pid | grep maxima");
if (strstr($s, $pid)) shell_exec("kill $pid");
// Process Control *****************************************************************
$end_time = time() + microtime();
$maxima_ex_time = ($end_time - $start_time);
if (file_exists($out_file) ) $maxima_response = file_get_contents($out_file); else {
$maxima_process_message .= "Maxima did not run properly (1).<br>";
}
// remove repeated questions
if ($maxima_question) {
preg_match("/.*(\n[^\n]*?\?)$/s", trim($m), $a);
$maxima_response = str_replace($a[1], "", $maxima_response);
$maxima_response = trim($maxima_response)."\n\n".trim($a[1]);
}
if (strstr($maxima_response, "maxima_session_".$unique_md5)) $maxima_session_result = true;
// remove headings, tail
if (strstr($maxima_response, $unique_md5)) {
$maxima_response = preg_replace("|.*$unique_md5.in\s*\n(.*?)|s", "\\1", $maxima_response);
$maxima_response = preg_replace("|(.*?)\n[^\n]*?maxima_session_$unique_md5.*|s", "\\1", $maxima_response);
}
if ($max_execution_time_exceeded) $maxima_process_message .= "The maximal allowed execution time has been exceeded.<br>";
} else {
$maxima_process_message .= "Maxima did not run properly (2).<br>";
}
$s = shell_exec("rm ".$temp_path."maxima_".$unique_md5."*");
return $maxima_response;
}
?>