1<?php
2/**
3 * Prolog plug-in : Rule-based System for Groupware.
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Paweł Kupka <pawel.kupka@gmail.com>
7 */
8
9// must be run within Dokuwiki
10$webroot = reset(split('lib',dirname(__FILE__)));
11if(!defined('DOKU_INC')) define('DOKU_INC', $webroot);
12if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins');
13if(!defined('DOKU_PAGES')) define('DOKU_PAGES',DOKU_INC.'data/pages');
14if(!defined('DOKU_TMP')) define('DOKU_TMP',DOKU_INC.'data/tmp');
15require_once (DOKU_INC.'inc/pageutils.php');
16require_once (DOKU_INC.'inc/utf8.php');
17
18class PrologTag {
19
20	var $entryTagPattern = '/<prolog.*>/';
21	var $exitTagPattern = '/<\/prolog>/';
22
23	var $attributeEntryPattern = '\(';
24	var $attributeExitPattern = '\)';
25	var $attributeValuePattern = '[^\)]*';
26	var $attributeName;
27	var $attributePattern;
28
29	/**
30	 * Constructor
31	 */
32	function PrologTag()
33	{
34	}
35
36	/**
37	 * Gets all prolog entry tags from the text file
38	 * @param string $file file path
39	 * @return array $matchedTags found prolog entry tags
40	 */
41	function getEntryTags($file = null)
42	{
43		$fileContent = file_get_contents($file);
44		$foundTags = preg_match_all($this->entryTagPattern, $fileContent, $matchedTags);
45		return $matchedTags[0];
46	}
47
48	/**
49	 * Sets attribute pattern
50	 * @param string $attributeName attribute name
51	 */
52	function setAttributePattern($attributeName)
53	{
54		$this->attributeName = $attributeName;
55		$this->attributePattern = '/';
56		$this->attributePattern .= '([a-zA-Z0-9]+)';
57		$this->attributePattern .= $this->attributeEntryPattern;
58		$this->attributePattern .= '('.$this->attributeValuePattern.')';
59		$this->attributePattern .= $this->attributeExitPattern;
60		$this->attributePattern .= '/';
61	}
62
63	/**
64	 * Gets the attribute value from the prolog entry tag
65	 * @param string $prologTag prolog entry tag
66	 * @return string $matched matched attribute value
67	 */
68	function getAttributeValue($prologTag = null)
69	{
70		$found = preg_match_all($this->attributePattern, $prologTag, $matched);
71		$attrValue = '';
72		foreach($matched[1] as $i => $attrName) {
73			if($attrName == $this->attributeName) {
74				$attrValue = $matched[2][$i];
75				break;
76
77			}
78		}
79		return $attrValue;
80	}
81
82	/**
83	 * Executes prolog code in the Prolog interpreter
84	 * @param string $prologCode the prolog source code
85	 * @param string $maxExecutionTime the limit for maximum interpretation time (in seconds)
86	 * @return array $executed array with output and errors from the interpreter
87	 */
88	function execute($prologCode = null, $maxExecutionTime = 5)
89	{
90		$executed = array('','');
91
92		if(!isset($prologCode))
93			return $executed;
94
95		$maxExecutionTime = intval($maxExecutionTime);
96		if($maxExecutionTime < 1 || $maxExecutionTime > 5) //1sec - 30sec
97			$maxExecutionTime = 5;
98
99		$tmpname = tempnam(DOKU_TMP, 'pl_');
100		$stdin = $tmpname.'.pl';
101		unlink($tmpname);
102
103		$handleStdin = fopen($stdin, 'w');
104		fwrite($handleStdin, $prologCode);
105		fclose($handleStdin);
106
107
108		$descriptorspec = array(
109			0 => array('pipe', 'r'),  // stdin
110			1 => array('pipe', 'w'),  // stdout
111			2 => array('pipe', 'w')   // stderr
112		);
113
114		$process = proc_open('pl', $descriptorspec, $pipes);
115
116		if(is_resource($process)) {
117			fwrite($pipes[0], '[\''.substr($stdin, 0, -3).'\'].');
118			fclose($pipes[0]);
119
120			$step = 10000; //0.01 second
121			$maxExecutionTime = $maxExecutionTime * 1000000;
122			$status = proc_get_status($process);
123			while($status['running'] && $maxExecutionTime != 0) {
124
125  				$maxExecutionTime -= $step;
126				usleep($step);
127				$status = proc_get_status($process);
128			}
129
130														if($status['running'] == true) {
131    				fclose($pipes[1]); //stdout
132    				fclose($pipes[2]); //stderr
133				proc_terminate($process);
134				$executed[1] .= 'Process reached the maximum execution time and has been terminated! ';
135				proc_close($process);
136
137			}
138			else {
139				$executed[0] = stream_get_contents($pipes[1]);
140				$executed[1] = stream_get_contents($pipes[2]);
141				fclose($pipes[1]); //stdout
142    				fclose($pipes[2]); //stderr
143				proc_close($process);
144    			}
145			fclose($pipes[1]); //stdout
146    			fclose($pipes[2]); //stderr
147			proc_close($process);
148
149		}
150		unlink($stdin);
151
152		return $executed;
153	}
154}
155?>