<?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;
}


?>